first commit
This commit is contained in:
@@ -0,0 +1,884 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/submission/reviewAssignment/ReviewAssignment.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ReviewAssignment
|
||||
*
|
||||
* @ingroup submission
|
||||
*
|
||||
* @see ReviewAssignmentDAO
|
||||
*
|
||||
* @brief Describes review assignment properties.
|
||||
*/
|
||||
|
||||
namespace PKP\submission\reviewAssignment;
|
||||
|
||||
use PKP\core\Core;
|
||||
|
||||
class ReviewAssignment extends \PKP\core\DataObject
|
||||
{
|
||||
public const SUBMISSION_REVIEWER_RECOMMENDATION_ACCEPT = 1;
|
||||
public const SUBMISSION_REVIEWER_RECOMMENDATION_PENDING_REVISIONS = 2;
|
||||
public const SUBMISSION_REVIEWER_RECOMMENDATION_RESUBMIT_HERE = 3;
|
||||
public const SUBMISSION_REVIEWER_RECOMMENDATION_RESUBMIT_ELSEWHERE = 4;
|
||||
public const SUBMISSION_REVIEWER_RECOMMENDATION_DECLINE = 5;
|
||||
public const SUBMISSION_REVIEWER_RECOMMENDATION_SEE_COMMENTS = 6;
|
||||
|
||||
public const SUBMISSION_REVIEWER_RATING_VERY_GOOD = 5;
|
||||
public const SUBMISSION_REVIEWER_RATING_GOOD = 4;
|
||||
public const SUBMISSION_REVIEWER_RATING_AVERAGE = 3;
|
||||
public const SUBMISSION_REVIEWER_RATING_POOR = 2;
|
||||
public const SUBMISSION_REVIEWER_RATING_VERY_POOR = 1;
|
||||
|
||||
public const SUBMISSION_REVIEW_METHOD_ANONYMOUS = 1;
|
||||
public const SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS = 2;
|
||||
public const SUBMISSION_REVIEW_METHOD_OPEN = 3;
|
||||
|
||||
public const REVIEW_ASSIGNMENT_NEW = 0; // Has never been considered by an editor, review assignment just created
|
||||
public const REVIEW_ASSIGNMENT_CONSIDERED = 3; // Has been marked considered by an editor
|
||||
public const REVIEW_ASSIGNMENT_UNCONSIDERED = 1; // Considered status has been revoked by an editor and is awaiting re-confirmation by an editor
|
||||
public const REVIEW_ASSIGNMENT_RECONSIDERED = 2; // Considered status has been granted again by an editor
|
||||
|
||||
public const REVIEW_ASSIGNMENT_STATUS_AWAITING_RESPONSE = 0; // request has been sent but reviewer has not responded
|
||||
public const REVIEW_ASSIGNMENT_STATUS_DECLINED = 1; // reviewer declined review request
|
||||
public const REVIEW_ASSIGNMENT_STATUS_RESPONSE_OVERDUE = 4; // review not responded within due date
|
||||
public const REVIEW_ASSIGNMENT_STATUS_ACCEPTED = 5; // reviewer has agreed to the review
|
||||
public const REVIEW_ASSIGNMENT_STATUS_REVIEW_OVERDUE = 6; // review not submitted within due date
|
||||
public const REVIEW_ASSIGNMENT_STATUS_RECEIVED = 7; // review has been submitted
|
||||
public const REVIEW_ASSIGNMENT_STATUS_COMPLETE = 8; // review has been confirmed by an editor
|
||||
public const REVIEW_ASSIGNMENT_STATUS_THANKED = 9; // reviewer has been thanked
|
||||
public const REVIEW_ASSIGNMENT_STATUS_CANCELLED = 10; // reviewer cancelled review request
|
||||
public const REVIEW_ASSIGNMENT_STATUS_REQUEST_RESEND = 11; // request resent to reviewer after they declined
|
||||
|
||||
/**
|
||||
* All review assignment statuses that indicate a
|
||||
* review was completed
|
||||
*
|
||||
* @var array<int>
|
||||
*/
|
||||
public const REVIEW_COMPLETE_STATUSES = [
|
||||
self::REVIEW_ASSIGNMENT_STATUS_RECEIVED,
|
||||
self::REVIEW_ASSIGNMENT_STATUS_COMPLETE,
|
||||
self::REVIEW_ASSIGNMENT_STATUS_THANKED,
|
||||
];
|
||||
|
||||
//
|
||||
// Get/set methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Get ID of review assignment's submission.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSubmissionId()
|
||||
{
|
||||
return $this->getData('submissionId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ID of review assignment's submission
|
||||
*
|
||||
* @param int $submissionId
|
||||
*/
|
||||
public function setSubmissionId($submissionId)
|
||||
{
|
||||
$this->setData('submissionId', $submissionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ID of reviewer.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getReviewerId()
|
||||
{
|
||||
return $this->getData('reviewerId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ID of reviewer.
|
||||
*
|
||||
* @param int $reviewerId
|
||||
*/
|
||||
public function setReviewerId($reviewerId)
|
||||
{
|
||||
$this->setData('reviewerId', $reviewerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full name of reviewer.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getReviewerFullName()
|
||||
{
|
||||
return $this->getData('reviewerFullName');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set full name of reviewer.
|
||||
*
|
||||
* @param string $reviewerFullName
|
||||
*/
|
||||
public function setReviewerFullName($reviewerFullName)
|
||||
{
|
||||
$this->setData('reviewerFullName', $reviewerFullName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get reviewer comments.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getComments()
|
||||
{
|
||||
return $this->getData('comments');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set reviewer comments.
|
||||
*
|
||||
* @param string $comments
|
||||
*/
|
||||
public function setComments($comments)
|
||||
{
|
||||
$this->setData('comments', $comments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get competing interests.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCompetingInterests()
|
||||
{
|
||||
return $this->getData('competingInterests');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set competing interests.
|
||||
*
|
||||
* @param string $competingInterests
|
||||
*/
|
||||
public function setCompetingInterests($competingInterests)
|
||||
{
|
||||
$this->setData('competingInterests', $competingInterests);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the workflow stage id.
|
||||
*
|
||||
* @return int WORKFLOW_STAGE_ID_...
|
||||
*/
|
||||
public function getStageId()
|
||||
{
|
||||
return $this->getData('stageId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the workflow stage id.
|
||||
*
|
||||
* @param int $stageId WORKFLOW_STAGE_ID_...
|
||||
*/
|
||||
public function setStageId($stageId)
|
||||
{
|
||||
$this->setData('stageId', $stageId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the method of the review (open, anonymous, or double-anonymous).
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getReviewMethod()
|
||||
{
|
||||
return $this->getData('reviewMethod');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of review.
|
||||
*
|
||||
* @param int $method
|
||||
*/
|
||||
public function setReviewMethod($method)
|
||||
{
|
||||
$this->setData('reviewMethod', $method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get review round id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getReviewRoundId()
|
||||
{
|
||||
return $this->getData('reviewRoundId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set review round id.
|
||||
*
|
||||
* @param int $reviewRoundId
|
||||
*/
|
||||
public function setReviewRoundId($reviewRoundId)
|
||||
{
|
||||
$this->setData('reviewRoundId', $reviewRoundId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get reviewer recommendation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRecommendation()
|
||||
{
|
||||
return $this->getData('recommendation');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set reviewer recommendation.
|
||||
*
|
||||
* @param string $recommendation
|
||||
*/
|
||||
public function setRecommendation($recommendation)
|
||||
{
|
||||
$this->setData('recommendation', $recommendation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get considered state.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getConsidered()
|
||||
{
|
||||
return $this->getData('considered');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set considered state.
|
||||
*
|
||||
* @param int $considered
|
||||
*/
|
||||
public function setConsidered($considered)
|
||||
{
|
||||
$this->setData('considered', $considered);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the date the reviewer was rated.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateRated()
|
||||
{
|
||||
return $this->getData('dateRated');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the date the reviewer was rated.
|
||||
*
|
||||
* @param string $dateRated
|
||||
*/
|
||||
public function setDateRated($dateRated)
|
||||
{
|
||||
$this->setData('dateRated', $dateRated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the date of the last modification.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLastModified()
|
||||
{
|
||||
return $this->getData('lastModified');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the date of the last modification.
|
||||
*
|
||||
* @param string $dateModified
|
||||
*/
|
||||
public function setLastModified($dateModified)
|
||||
{
|
||||
$this->setData('lastModified', $dateModified);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stamp the date of the last modification to the current time.
|
||||
*/
|
||||
public function stampModified()
|
||||
{
|
||||
return $this->setLastModified(Core::getCurrentDate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reviewer's assigned date.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateAssigned()
|
||||
{
|
||||
return $this->getData('dateAssigned');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reviewer's assigned date.
|
||||
*
|
||||
* @param string $dateAssigned
|
||||
*/
|
||||
public function setDateAssigned($dateAssigned)
|
||||
{
|
||||
$this->setData('dateAssigned', $dateAssigned);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reviewer's notified date.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateNotified()
|
||||
{
|
||||
return $this->getData('dateNotified');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reviewer's notified date.
|
||||
*
|
||||
* @param string $dateNotified
|
||||
*/
|
||||
public function setDateNotified($dateNotified)
|
||||
{
|
||||
$this->setData('dateNotified', $dateNotified);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reviewer's confirmed date.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDateConfirmed()
|
||||
{
|
||||
return $this->getData('dateConfirmed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reviewer's confirmed date.
|
||||
*
|
||||
* @param string|null $dateConfirmed
|
||||
*/
|
||||
public function setDateConfirmed($dateConfirmed)
|
||||
{
|
||||
$this->setData('dateConfirmed', $dateConfirmed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reviewer's completed date.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateCompleted()
|
||||
{
|
||||
return $this->getData('dateCompleted');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reviewer's completed date.
|
||||
*
|
||||
* @param string $dateCompleted
|
||||
*/
|
||||
public function setDateCompleted($dateCompleted)
|
||||
{
|
||||
$this->setData('dateCompleted', $dateCompleted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reviewer's acknowledged date.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateAcknowledged()
|
||||
{
|
||||
return $this->getData('dateAcknowledged');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reviewer's acknowledged date.
|
||||
*
|
||||
* @param string $dateAcknowledged
|
||||
*/
|
||||
public function setDateAcknowledged($dateAcknowledged)
|
||||
{
|
||||
$this->setData('dateAcknowledged', $dateAcknowledged);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reviewer's last reminder date.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateReminded()
|
||||
{
|
||||
return $this->getData('dateReminded');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reviewer's last reminder date.
|
||||
*
|
||||
* @param string $dateReminded
|
||||
*/
|
||||
public function setDateReminded($dateReminded)
|
||||
{
|
||||
$this->setData('dateReminded', $dateReminded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reviewer's due date.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateDue()
|
||||
{
|
||||
return $this->getData('dateDue');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reviewer's due date.
|
||||
*
|
||||
* @param string $dateDue
|
||||
*/
|
||||
public function setDateDue($dateDue)
|
||||
{
|
||||
$this->setData('dateDue', $dateDue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reviewer's response due date.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateResponseDue()
|
||||
{
|
||||
return $this->getData('dateResponseDue');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reviewer's response due date.
|
||||
*
|
||||
* @param string $dateResponseDue
|
||||
*/
|
||||
public function setDateResponseDue($dateResponseDue)
|
||||
{
|
||||
$this->setData('dateResponseDue', $dateResponseDue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the declined value.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getDeclined()
|
||||
{
|
||||
return $this->getData('declined');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reviewer's declined value.
|
||||
*
|
||||
* @param bool $declined
|
||||
*/
|
||||
public function setDeclined($declined)
|
||||
{
|
||||
$this->setData('declined', $declined);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cancelled value.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getCancelled()
|
||||
{
|
||||
return $this->getData('cancelled');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reviewer's cancelled value.
|
||||
*
|
||||
* @param bool $cancelled
|
||||
*/
|
||||
public function setCancelled($cancelled)
|
||||
{
|
||||
$this->setData('cancelled', $cancelled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reviewer's request resent value.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getRequestResent()
|
||||
{
|
||||
return $this->getData('request_resent');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reviewer's request resent value.
|
||||
*
|
||||
* @param bool $resent
|
||||
*/
|
||||
public function setRequestResent($resent)
|
||||
{
|
||||
$this->setData('request_resent', $resent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a boolean indicating whether or not the last reminder was automatic.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getReminderWasAutomatic()
|
||||
{
|
||||
return $this->getData('reminderWasAutomatic') == 1 ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the boolean indicating whether or not the last reminder was automatic.
|
||||
*
|
||||
* @param bool $wasAutomatic
|
||||
*/
|
||||
public function setReminderWasAutomatic($wasAutomatic)
|
||||
{
|
||||
$this->setData('reminderWasAutomatic', $wasAutomatic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get quality.
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getQuality()
|
||||
{
|
||||
return $this->getData('quality');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set quality.
|
||||
*
|
||||
* @param int|null $quality
|
||||
*/
|
||||
public function setQuality($quality)
|
||||
{
|
||||
$this->setData('quality', $quality);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get round.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRound()
|
||||
{
|
||||
return $this->getData('round');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set round.
|
||||
*
|
||||
* @param int $round
|
||||
*/
|
||||
public function setRound($round)
|
||||
{
|
||||
$this->setData('round', $round);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get step.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStep()
|
||||
{
|
||||
return $this->getData('step');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set step.
|
||||
*
|
||||
* @param int $step
|
||||
*/
|
||||
public function setStep($step)
|
||||
{
|
||||
$this->setData('step', $step);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get review form id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getReviewFormId()
|
||||
{
|
||||
return $this->getData('reviewFormId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set review form id.
|
||||
*
|
||||
* @param int $reviewFormId
|
||||
*/
|
||||
public function setReviewFormId($reviewFormId)
|
||||
{
|
||||
$this->setData('reviewFormId', $reviewFormId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current status of this review assignment
|
||||
*
|
||||
* @return int ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_...
|
||||
*/
|
||||
public function getStatus()
|
||||
{
|
||||
if ($this->getDeclined()) {
|
||||
return self::REVIEW_ASSIGNMENT_STATUS_DECLINED;
|
||||
}
|
||||
if ($this->getCancelled()) {
|
||||
return self::REVIEW_ASSIGNMENT_STATUS_CANCELLED;
|
||||
}
|
||||
|
||||
if (!$this->getDeclined() && !$this->getDateConfirmed() && $this->getRequestResent()) {
|
||||
return self::REVIEW_ASSIGNMENT_STATUS_REQUEST_RESEND;
|
||||
}
|
||||
|
||||
if (!$this->getDateCompleted()) {
|
||||
$dueTimes = array_map(function ($dateTime) {
|
||||
// If no due time, set it to the end of the day
|
||||
if (substr($dateTime, 11) === '00:00:00') {
|
||||
$dateTime = substr($dateTime, 0, 11) . '23:59:59';
|
||||
}
|
||||
return strtotime($dateTime);
|
||||
}, [$this->getDateResponseDue(), $this->getDateDue()]);
|
||||
$responseDueTime = $dueTimes[0];
|
||||
$reviewDueTime = $dueTimes[1];
|
||||
if (!$this->getDateConfirmed()) { // no response
|
||||
if ($responseDueTime < time()) { // response overdue
|
||||
return self::REVIEW_ASSIGNMENT_STATUS_RESPONSE_OVERDUE;
|
||||
} elseif ($reviewDueTime < strtotime('tomorrow')) { // review overdue but not response
|
||||
return self::REVIEW_ASSIGNMENT_STATUS_REVIEW_OVERDUE;
|
||||
} else { // response not due yet
|
||||
return self::REVIEW_ASSIGNMENT_STATUS_AWAITING_RESPONSE;
|
||||
}
|
||||
} else { // response given
|
||||
if ($reviewDueTime < strtotime('tomorrow')) { // review due
|
||||
return self::REVIEW_ASSIGNMENT_STATUS_REVIEW_OVERDUE;
|
||||
} else {
|
||||
return self::REVIEW_ASSIGNMENT_STATUS_ACCEPTED;
|
||||
}
|
||||
}
|
||||
} elseif ($this->getDateAcknowledged()) { // reviewer thanked...
|
||||
if ($this->getConsidered() == self::REVIEW_ASSIGNMENT_UNCONSIDERED) { // ...but review later unconsidered
|
||||
return self::REVIEW_ASSIGNMENT_STATUS_RECEIVED;
|
||||
}
|
||||
return self::REVIEW_ASSIGNMENT_STATUS_THANKED;
|
||||
} elseif ($this->getDateCompleted()) { // review submitted...
|
||||
if ($this->getConsidered() != self::REVIEW_ASSIGNMENT_UNCONSIDERED && $this->isRead()) { // ...and confirmed by an editor
|
||||
return self::REVIEW_ASSIGNMENT_STATUS_COMPLETE;
|
||||
}
|
||||
return self::REVIEW_ASSIGNMENT_STATUS_RECEIVED;
|
||||
}
|
||||
|
||||
return self::REVIEW_ASSIGNMENT_STATUS_AWAITING_RESPONSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether an editorial user has read this review
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRead()
|
||||
{
|
||||
if ($this->getConsidered() === self::REVIEW_ASSIGNMENT_CONSIDERED || $this->getConsidered() === self::REVIEW_ASSIGNMENT_RECONSIDERED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the translation key for the current status
|
||||
*
|
||||
* @param int $status Optionally pass a status to retrieve a specific key.
|
||||
* Default will return the key for the current status.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getStatusKey($status = null)
|
||||
{
|
||||
if (is_null($status)) {
|
||||
$status = $this->getStatus();
|
||||
}
|
||||
|
||||
switch ($status) {
|
||||
case self::REVIEW_ASSIGNMENT_STATUS_AWAITING_RESPONSE:
|
||||
return 'submission.review.status.awaitingResponse';
|
||||
case self::REVIEW_ASSIGNMENT_STATUS_CANCELLED:
|
||||
return 'common.cancelled';
|
||||
case self::REVIEW_ASSIGNMENT_STATUS_DECLINED:
|
||||
return 'submission.review.status.declined';
|
||||
case self::REVIEW_ASSIGNMENT_STATUS_RESPONSE_OVERDUE:
|
||||
return 'submission.review.status.responseOverdue';
|
||||
case self::REVIEW_ASSIGNMENT_STATUS_REVIEW_OVERDUE:
|
||||
return 'submission.review.status.reviewOverdue';
|
||||
case self::REVIEW_ASSIGNMENT_STATUS_ACCEPTED:
|
||||
return 'submission.review.status.accepted';
|
||||
case self::REVIEW_ASSIGNMENT_STATUS_RECEIVED:
|
||||
return 'submission.review.status.received';
|
||||
case self::REVIEW_ASSIGNMENT_STATUS_COMPLETE:
|
||||
return 'submission.review.status.complete';
|
||||
case self::REVIEW_ASSIGNMENT_STATUS_THANKED:
|
||||
return 'submission.review.status.thanked';
|
||||
case self::REVIEW_ASSIGNMENT_STATUS_REQUEST_RESEND:
|
||||
return 'submission.review.status.awaitingResponse';
|
||||
}
|
||||
|
||||
assert(false, 'No status key could be found for ' . get_class($this) . ' on ' . __LINE__);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the translation key for the review method
|
||||
*
|
||||
* @param int|null $method Optionally pass a method to retrieve a specific key.
|
||||
* Default will return the key for the current review method
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getReviewMethodKey($method = null)
|
||||
{
|
||||
if (is_null($method)) {
|
||||
$method = $this->getReviewMethod();
|
||||
}
|
||||
|
||||
switch ($method) {
|
||||
case self::SUBMISSION_REVIEW_METHOD_OPEN:
|
||||
return 'editor.submissionReview.open';
|
||||
case self::SUBMISSION_REVIEW_METHOD_ANONYMOUS:
|
||||
return 'editor.submissionReview.anonymous';
|
||||
case self::SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS:
|
||||
return 'editor.submissionReview.doubleAnonymous';
|
||||
}
|
||||
|
||||
assert(false, 'No review method key could be found for ' . get_class($this) . ' on ' . __LINE__);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
//
|
||||
// Files
|
||||
//
|
||||
|
||||
/**
|
||||
* Get number of weeks until review is due (or number of weeks overdue).
|
||||
*
|
||||
* @return ?int
|
||||
*/
|
||||
public function getWeeksDue()
|
||||
{
|
||||
$dateDue = $this->getDateDue();
|
||||
if ($dateDue === null) {
|
||||
return null;
|
||||
}
|
||||
return round((strtotime($dateDue) - time()) / (86400 * 7.0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an associative array matching reviewer recommendation codes with locale strings.
|
||||
* (Includes default '' => "Choose One" string.)
|
||||
*
|
||||
* @return array recommendation => localeString
|
||||
*/
|
||||
public static function getReviewerRecommendationOptions()
|
||||
{
|
||||
static $reviewerRecommendationOptions = [
|
||||
'' => 'common.chooseOne',
|
||||
self::SUBMISSION_REVIEWER_RECOMMENDATION_ACCEPT => 'reviewer.article.decision.accept',
|
||||
self::SUBMISSION_REVIEWER_RECOMMENDATION_PENDING_REVISIONS => 'reviewer.article.decision.pendingRevisions',
|
||||
self::SUBMISSION_REVIEWER_RECOMMENDATION_RESUBMIT_HERE => 'reviewer.article.decision.resubmitHere',
|
||||
self::SUBMISSION_REVIEWER_RECOMMENDATION_RESUBMIT_ELSEWHERE => 'reviewer.article.decision.resubmitElsewhere',
|
||||
self::SUBMISSION_REVIEWER_RECOMMENDATION_DECLINE => 'reviewer.article.decision.decline',
|
||||
self::SUBMISSION_REVIEWER_RECOMMENDATION_SEE_COMMENTS => 'reviewer.article.decision.seeComments'
|
||||
];
|
||||
return $reviewerRecommendationOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a localized string representing the reviewer recommendation.
|
||||
*/
|
||||
public function getLocalizedRecommendation()
|
||||
{
|
||||
$options = self::getReviewerRecommendationOptions();
|
||||
if (array_key_exists($this->getRecommendation(), $options)) {
|
||||
return __($options[$this->getRecommendation()]);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if can resend request to reconsider review for this review assignment
|
||||
*/
|
||||
public function canResendReviewRequest(): bool
|
||||
{
|
||||
if ($this->getCancelled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->getDeclined()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\submission\reviewAssignment\ReviewAssignment', '\ReviewAssignment');
|
||||
foreach ([
|
||||
'SUBMISSION_REVIEWER_RECOMMENDATION_ACCEPT',
|
||||
'SUBMISSION_REVIEWER_RECOMMENDATION_PENDING_REVISIONS',
|
||||
'SUBMISSION_REVIEWER_RECOMMENDATION_RESUBMIT_HERE',
|
||||
'SUBMISSION_REVIEWER_RECOMMENDATION_RESUBMIT_ELSEWHERE',
|
||||
'SUBMISSION_REVIEWER_RECOMMENDATION_DECLINE',
|
||||
'SUBMISSION_REVIEWER_RECOMMENDATION_SEE_COMMENTS',
|
||||
'SUBMISSION_REVIEWER_RATING_VERY_GOOD',
|
||||
'SUBMISSION_REVIEWER_RATING_GOOD',
|
||||
'SUBMISSION_REVIEWER_RATING_AVERAGE',
|
||||
'SUBMISSION_REVIEWER_RATING_POOR',
|
||||
'SUBMISSION_REVIEWER_RATING_VERY_POOR',
|
||||
'SUBMISSION_REVIEW_METHOD_ANONYMOUS',
|
||||
'SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS',
|
||||
'SUBMISSION_REVIEW_METHOD_OPEN',
|
||||
'REVIEW_ASSIGNMENT_STATUS_AWAITING_RESPONSE',
|
||||
'REVIEW_ASSIGNMENT_STATUS_DECLINED',
|
||||
'REVIEW_ASSIGNMENT_STATUS_RESPONSE_OVERDUE',
|
||||
'REVIEW_ASSIGNMENT_STATUS_ACCEPTED',
|
||||
'REVIEW_ASSIGNMENT_STATUS_REVIEW_OVERDUE',
|
||||
'REVIEW_ASSIGNMENT_STATUS_RECEIVED',
|
||||
'REVIEW_ASSIGNMENT_STATUS_COMPLETE',
|
||||
'REVIEW_ASSIGNMENT_STATUS_THANKED',
|
||||
'REVIEW_ASSIGNMENT_STATUS_CANCELLED',
|
||||
'REVIEW_ASSIGNMENT_STATUS_REQUEST_RESEND',
|
||||
] as $constantName) {
|
||||
if (!defined($constantName)) {
|
||||
define($constantName, constant('\PKP\submission\reviewAssignment\ReviewAssignment::' . $constantName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,676 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/submission/reviewAssignment/ReviewAssignmentDAO.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ReviewAssignmentDAO
|
||||
*
|
||||
* @ingroup submission
|
||||
*
|
||||
* @see ReviewAssignment
|
||||
*
|
||||
* @brief Class for DAO relating reviewers to submissions.
|
||||
*/
|
||||
|
||||
namespace PKP\submission\reviewAssignment;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\notification\NotificationDAO;
|
||||
use PKP\reviewForm\ReviewFormResponseDAO;
|
||||
use PKP\submission\ReviewFilesDAO;
|
||||
use PKP\submission\reviewRound\ReviewRoundDAO;
|
||||
|
||||
class ReviewAssignmentDAO extends \PKP\db\DAO
|
||||
{
|
||||
/**
|
||||
* Retrieve review assignments for the passed review round id.
|
||||
*
|
||||
* @param int $reviewRoundId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getByReviewRoundId($reviewRoundId)
|
||||
{
|
||||
$params = [(int)$reviewRoundId];
|
||||
$query = $this->_getSelectQuery() .
|
||||
' WHERE r.review_round_id = ? ORDER BY review_id';
|
||||
return $this->_getReviewAssignmentsArray($query, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve open review assignments for the passed review round id.
|
||||
*
|
||||
* @param int $reviewRoundId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getOpenReviewsByReviewRoundId($reviewRoundId)
|
||||
{
|
||||
$params = [(int)$reviewRoundId, ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN];
|
||||
$query = $this->_getSelectQuery() .
|
||||
' WHERE r.review_round_id = ? AND r.review_method = ? AND r.date_confirmed IS NOT NULL AND r.declined <> 1 ORDER BY review_id';
|
||||
return $this->_getReviewAssignmentsArray($query, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve review assignments from table using the passed
|
||||
* sql query and parameters.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $queryParams
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function _getReviewAssignmentsArray($query, $queryParams)
|
||||
{
|
||||
$result = $this->retrieve($query, $queryParams);
|
||||
|
||||
$reviewAssignments = [];
|
||||
foreach ($result as $row) {
|
||||
$reviewAssignments[$row->review_id] = $this->_fromRow((array) $row);
|
||||
}
|
||||
return $reviewAssignments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the review_rounds join string. Must be implemented
|
||||
* by subclasses.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getReviewRoundJoin()
|
||||
{
|
||||
return 'r.review_round_id = r2.review_round_id';
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Public methods.
|
||||
//
|
||||
/**
|
||||
* Retrieve a review assignment by review round and reviewer.
|
||||
*
|
||||
* @param int $reviewRoundId
|
||||
* @param int $reviewerId
|
||||
*
|
||||
* @return ReviewAssignment
|
||||
*/
|
||||
public function getReviewAssignment($reviewRoundId, $reviewerId)
|
||||
{
|
||||
$result = $this->retrieve(
|
||||
$this->_getSelectQuery() .
|
||||
' WHERE r.review_round_id = ? AND
|
||||
r.reviewer_id = ?',
|
||||
[
|
||||
(int) $reviewRoundId,
|
||||
(int) $reviewerId
|
||||
]
|
||||
);
|
||||
$row = $result->current();
|
||||
return $row ? $this->_fromRow((array) $row) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a review assignment by review assignment id.
|
||||
*
|
||||
* @param int $reviewId
|
||||
*
|
||||
* @return ReviewAssignment
|
||||
*/
|
||||
public function getById($reviewId)
|
||||
{
|
||||
$result = $this->retrieve(
|
||||
'SELECT r.*, r2.review_revision
|
||||
FROM review_assignments r
|
||||
LEFT JOIN review_rounds r2 ON (' . $this->getReviewRoundJoin() . ')
|
||||
WHERE r.review_id = ?',
|
||||
[(int) $reviewId]
|
||||
);
|
||||
$row = $result->current();
|
||||
return $row ? $this->_fromRow((array) $row) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all incomplete review assignments for all journals/conferences/presses
|
||||
*
|
||||
* @return array ReviewAssignments
|
||||
*/
|
||||
public function getIncompleteReviewAssignments()
|
||||
{
|
||||
$result = $this->retrieve(
|
||||
'SELECT r.*, r2.review_revision
|
||||
FROM review_assignments r
|
||||
LEFT JOIN review_rounds r2 ON (' . $this->getReviewRoundJoin() . ')
|
||||
WHERE' . $this->getIncompleteReviewAssignmentsWhereString() .
|
||||
' ORDER BY r.submission_id'
|
||||
);
|
||||
|
||||
$reviewAssignments = [];
|
||||
foreach ($result as $row) {
|
||||
$reviewAssignments[] = $this->_fromRow((array) $row);
|
||||
}
|
||||
return $reviewAssignments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WHERE sql string to filter incomplete review
|
||||
* assignments.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIncompleteReviewAssignmentsWhereString()
|
||||
{
|
||||
return ' r.date_notified IS NOT NULL AND
|
||||
r.date_completed IS NULL AND
|
||||
r.declined <> 1 AND
|
||||
r.cancelled <> 1';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all review assignments for a submission.
|
||||
*
|
||||
* @param int $submissionId Submission ID
|
||||
* @param int $reviewRoundId Review round ID
|
||||
* @param int $stageId Optional stage ID
|
||||
*
|
||||
* @return array ReviewAssignments
|
||||
*/
|
||||
public function getBySubmissionId($submissionId, $reviewRoundId = null, $stageId = null)
|
||||
{
|
||||
$query = $this->_getSelectQuery() .
|
||||
' WHERE r.submission_id = ?';
|
||||
|
||||
$orderBy = ' ORDER BY review_id';
|
||||
|
||||
$queryParams[] = (int) $submissionId;
|
||||
|
||||
if ($reviewRoundId != null) {
|
||||
$query .= ' AND r2.review_round_id = ?';
|
||||
$queryParams[] = (int) $reviewRoundId;
|
||||
} else {
|
||||
$orderBy .= ', r2.review_round_id';
|
||||
}
|
||||
|
||||
if ($stageId != null) {
|
||||
$query .= ' AND r2.stage_id = ?';
|
||||
$queryParams[] = (int) $stageId;
|
||||
} else {
|
||||
$orderBy .= ', r2.stage_id';
|
||||
}
|
||||
|
||||
$query .= $orderBy;
|
||||
|
||||
return $this->_getReviewAssignmentsArray($query, $queryParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all review assignments by submission and reviewer.
|
||||
*
|
||||
* @param int $submissionId
|
||||
* @param int $reviewerId
|
||||
* @param int $stageId optional
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBySubmissionReviewer($submissionId, $reviewerId, $stageId = null)
|
||||
{
|
||||
$query = $this->_getSelectQuery() .
|
||||
' WHERE r.submission_id = ? AND r.reviewer_id = ?';
|
||||
$queryParams = [(int) $submissionId, (int) $reviewerId];
|
||||
if ($stageId != null) {
|
||||
$query .= ' AND r.stage_id = ?';
|
||||
$queryParams[] = (int) $stageId;
|
||||
}
|
||||
return $this->_getReviewAssignmentsArray($query, $queryParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all review assignments for a reviewer.
|
||||
*
|
||||
* @param int $userId
|
||||
*
|
||||
* @return array ReviewAssignments
|
||||
*/
|
||||
public function getByUserId($userId)
|
||||
{
|
||||
$reviewRoundJoinString = $this->getReviewRoundJoin();
|
||||
|
||||
if (!$reviewRoundJoinString) {
|
||||
throw new Exception('Review round join string not specified');
|
||||
}
|
||||
$result = $this->retrieve(
|
||||
'SELECT r.*, r2.review_revision
|
||||
FROM review_assignments r
|
||||
LEFT JOIN review_rounds r2 ON (' . $reviewRoundJoinString . ')
|
||||
WHERE r.reviewer_id = ?
|
||||
ORDER BY round, review_id',
|
||||
[(int) $userId]
|
||||
);
|
||||
|
||||
$reviewAssignments = [];
|
||||
foreach ($result as $row) {
|
||||
$reviewAssignments[] = $this->_fromRow((array) $row);
|
||||
}
|
||||
|
||||
return $reviewAssignments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a reviewer is assigned to a specified submission.
|
||||
*
|
||||
* @param int $reviewRoundId
|
||||
* @param int $reviewerId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function reviewerExists($reviewRoundId, $reviewerId)
|
||||
{
|
||||
$result = $this->retrieve(
|
||||
'SELECT COUNT(*) AS row_count
|
||||
FROM review_assignments
|
||||
WHERE review_round_id = ? AND
|
||||
reviewer_id = ?',
|
||||
[(int) $reviewRoundId, (int) $reviewerId]
|
||||
);
|
||||
$row = (array) $result->current();
|
||||
return $row && $row['row_count'] == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all review assignments for a review form.
|
||||
*
|
||||
* @param int $reviewFormId
|
||||
*
|
||||
* @return array ReviewAssignments
|
||||
*/
|
||||
public function getByReviewFormId($reviewFormId)
|
||||
{
|
||||
$reviewRoundJoinString = $this->getReviewRoundJoin();
|
||||
|
||||
if (!$reviewRoundJoinString) {
|
||||
throw new Exception('Review round join string not specified');
|
||||
}
|
||||
$result = $this->retrieve(
|
||||
'SELECT r.*, r2.review_revision
|
||||
FROM review_assignments r
|
||||
LEFT JOIN review_rounds r2 ON (' . $reviewRoundJoinString . ')
|
||||
WHERE r.review_form_id = ?
|
||||
ORDER BY round, review_id',
|
||||
[(int) $reviewFormId]
|
||||
);
|
||||
|
||||
$reviewAssignments = [];
|
||||
foreach ($result as $row) {
|
||||
$reviewAssignments[] = $this->_fromRow((array) $row);
|
||||
}
|
||||
return $reviewAssignments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the order of active reviews for the given round of the given submission
|
||||
*
|
||||
* @param int $submissionId Submission ID
|
||||
* @param int $reviewRoundId Review round ID
|
||||
*
|
||||
* @return array Associating review ID with number, i.e. if review ID 26 is first returned['26']=0.
|
||||
*/
|
||||
public function getReviewIndexesForRound($submissionId, $reviewRoundId)
|
||||
{
|
||||
$result = $this->retrieve(
|
||||
'SELECT review_id
|
||||
FROM review_assignments
|
||||
WHERE submission_id = ? AND
|
||||
review_round_id = ?
|
||||
ORDER BY review_id',
|
||||
[(int) $submissionId, (int) $reviewRoundId]
|
||||
);
|
||||
|
||||
$index = 0;
|
||||
$returner = [];
|
||||
foreach ($result as $row) {
|
||||
$returner[$row->review_id] = $index++;
|
||||
}
|
||||
return $returner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new Review Assignment.
|
||||
*
|
||||
* @param ReviewAssignment $reviewAssignment
|
||||
*/
|
||||
public function insertObject($reviewAssignment)
|
||||
{
|
||||
$result = $this->update(
|
||||
sprintf(
|
||||
'INSERT INTO review_assignments (
|
||||
submission_id,
|
||||
reviewer_id,
|
||||
stage_id,
|
||||
review_method,
|
||||
round,
|
||||
step,
|
||||
competing_interests,
|
||||
recommendation,
|
||||
declined,
|
||||
cancelled,
|
||||
date_assigned, date_notified, date_confirmed,
|
||||
date_completed, date_acknowledged, date_due, date_response_due,
|
||||
quality, date_rated,
|
||||
last_modified,
|
||||
date_reminded, reminder_was_automatic,
|
||||
review_form_id,
|
||||
review_round_id,
|
||||
considered,
|
||||
request_resent
|
||||
) VALUES (
|
||||
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, %s, %s, %s, %s, %s, %s, %s, ?, %s, %s, %s, ?, ?, ?, ?, ?
|
||||
)',
|
||||
$this->datetimeToDB($reviewAssignment->getDateAssigned()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateNotified()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateConfirmed()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateCompleted()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateAcknowledged()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateDue()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateResponseDue()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateRated()),
|
||||
$this->datetimeToDB($reviewAssignment->getLastModified()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateReminded())
|
||||
),
|
||||
[
|
||||
(int) $reviewAssignment->getSubmissionId(),
|
||||
(int) $reviewAssignment->getReviewerId(),
|
||||
(int) $reviewAssignment->getStageId(),
|
||||
(int) $reviewAssignment->getReviewMethod(),
|
||||
max((int) $reviewAssignment->getRound(), 1),
|
||||
max((int) $reviewAssignment->getStep(), 1),
|
||||
$reviewAssignment->getCompetingInterests(),
|
||||
$reviewAssignment->getRecommendation(),
|
||||
(int) $reviewAssignment->getDeclined(),
|
||||
(int) $reviewAssignment->getCancelled(),
|
||||
$reviewAssignment->getQuality(),
|
||||
(int) $reviewAssignment->getReminderWasAutomatic(),
|
||||
$reviewAssignment->getReviewFormId(),
|
||||
(int) $reviewAssignment->getReviewRoundId(),
|
||||
(int) $reviewAssignment->getConsidered(),
|
||||
(int) $reviewAssignment->getRequestResent(),
|
||||
]
|
||||
);
|
||||
|
||||
$reviewAssignment->setId($this->getInsertId());
|
||||
|
||||
// Update review stage status whenever a review assignment is changed
|
||||
$this->updateReviewRoundStatus($reviewAssignment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing review assignment.
|
||||
*
|
||||
* @param ReviewAssignment $reviewAssignment
|
||||
*/
|
||||
public function updateObject($reviewAssignment)
|
||||
{
|
||||
$result = $this->update(
|
||||
sprintf(
|
||||
'UPDATE review_assignments
|
||||
SET submission_id = ?,
|
||||
reviewer_id = ?,
|
||||
stage_id = ?,
|
||||
review_method = ?,
|
||||
round = ?,
|
||||
step = ?,
|
||||
competing_interests = ?,
|
||||
recommendation = ?,
|
||||
declined = ?,
|
||||
cancelled = ?,
|
||||
date_assigned = %s,
|
||||
date_notified = %s,
|
||||
date_confirmed = %s,
|
||||
date_completed = %s,
|
||||
date_acknowledged = %s,
|
||||
date_due = %s,
|
||||
date_response_due = %s,
|
||||
quality = ?,
|
||||
date_rated = %s,
|
||||
last_modified = %s,
|
||||
date_reminded = %s,
|
||||
reminder_was_automatic = ?,
|
||||
review_form_id = ?,
|
||||
review_round_id = ?,
|
||||
considered = ?,
|
||||
request_resent = ?
|
||||
WHERE review_id = ?',
|
||||
$this->datetimeToDB($reviewAssignment->getDateAssigned()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateNotified()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateConfirmed()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateCompleted()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateAcknowledged()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateDue()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateResponseDue()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateRated()),
|
||||
$this->datetimeToDB($reviewAssignment->getLastModified()),
|
||||
$this->datetimeToDB($reviewAssignment->getDateReminded())
|
||||
),
|
||||
[
|
||||
(int) $reviewAssignment->getSubmissionId(),
|
||||
(int) $reviewAssignment->getReviewerId(),
|
||||
(int) $reviewAssignment->getStageId(),
|
||||
(int) $reviewAssignment->getReviewMethod(),
|
||||
(int) $reviewAssignment->getRound(),
|
||||
(int) $reviewAssignment->getStep(),
|
||||
$reviewAssignment->getCompetingInterests(),
|
||||
$reviewAssignment->getRecommendation(),
|
||||
(int) $reviewAssignment->getDeclined(),
|
||||
(int) $reviewAssignment->getCancelled(),
|
||||
$reviewAssignment->getQuality(),
|
||||
$reviewAssignment->getReminderWasAutomatic() ? 1 : 0,
|
||||
$reviewAssignment->getReviewFormId(),
|
||||
(int) $reviewAssignment->getReviewRoundId(),
|
||||
(int) $reviewAssignment->getConsidered(),
|
||||
(int) $reviewAssignment->getRequestResent(),
|
||||
(int) $reviewAssignment->getId(),
|
||||
]
|
||||
);
|
||||
|
||||
// Update review stage status whenever a review assignment is changed
|
||||
$this->updateReviewRoundStatus($reviewAssignment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the status of the review round an assignment is attached to. This
|
||||
* should be fired whenever a reviewer assignment is modified.
|
||||
*
|
||||
* @param ReviewAssignment $reviewAssignment
|
||||
*/
|
||||
public function updateReviewRoundStatus($reviewAssignment)
|
||||
{
|
||||
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /** @var ReviewRoundDAO $reviewRoundDao */
|
||||
$reviewRound = $reviewRoundDao->getReviewRound(
|
||||
$reviewAssignment->getSubmissionId(),
|
||||
$reviewAssignment->getStageId(),
|
||||
$reviewAssignment->getRound()
|
||||
);
|
||||
|
||||
// Review round may not exist if submission is being deleted
|
||||
if ($reviewRound) {
|
||||
return $reviewRoundDao->updateStatus($reviewRound);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function to return a review assignment object from a row.
|
||||
*
|
||||
* @param array $row
|
||||
*
|
||||
* @return ReviewAssignment
|
||||
*/
|
||||
public function _fromRow($row)
|
||||
{
|
||||
$reviewAssignment = $this->newDataObject(); /** @var ReviewAssignment $reviewAssignment */
|
||||
$user = Repo::user()->get($row['reviewer_id'], true);
|
||||
|
||||
$reviewAssignment->setId((int) $row['review_id']);
|
||||
$reviewAssignment->setSubmissionId((int) $row['submission_id']);
|
||||
$reviewAssignment->setReviewerId((int) $row['reviewer_id']);
|
||||
$reviewAssignment->setReviewerFullName($user->getFullName());
|
||||
$reviewAssignment->setCompetingInterests($row['competing_interests']);
|
||||
$reviewAssignment->setRecommendation($row['recommendation']);
|
||||
$reviewAssignment->setDateAssigned($this->datetimeFromDB($row['date_assigned']));
|
||||
$reviewAssignment->setDateNotified($this->datetimeFromDB($row['date_notified']));
|
||||
$reviewAssignment->setDateConfirmed($this->datetimeFromDB($row['date_confirmed']));
|
||||
$reviewAssignment->setDateCompleted($this->datetimeFromDB($row['date_completed']));
|
||||
$reviewAssignment->setDateAcknowledged($this->datetimeFromDB($row['date_acknowledged']));
|
||||
$reviewAssignment->setDateDue($this->datetimeFromDB($row['date_due']));
|
||||
$reviewAssignment->setDateResponseDue($this->datetimeFromDB($row['date_response_due']));
|
||||
$reviewAssignment->setLastModified($this->datetimeFromDB($row['last_modified']));
|
||||
$reviewAssignment->setDeclined((int) $row['declined']);
|
||||
$reviewAssignment->setCancelled((int) $row['cancelled']);
|
||||
$reviewAssignment->setQuality($row['quality']);
|
||||
$reviewAssignment->setDateRated($this->datetimeFromDB($row['date_rated']));
|
||||
$reviewAssignment->setDateReminded($this->datetimeFromDB($row['date_reminded']));
|
||||
$reviewAssignment->setReminderWasAutomatic((int) $row['reminder_was_automatic']);
|
||||
$reviewAssignment->setRound((int) $row['round']);
|
||||
$reviewAssignment->setStep((int) $row['step']);
|
||||
$reviewAssignment->setReviewFormId($row['review_form_id']);
|
||||
$reviewAssignment->setReviewRoundId((int) $row['review_round_id']);
|
||||
$reviewAssignment->setReviewMethod((int) $row['review_method']);
|
||||
$reviewAssignment->setStageId((int) $row['stage_id']);
|
||||
$reviewAssignment->setConsidered((int) $row['considered']);
|
||||
$reviewAssignment->setRequestResent((int) $row['request_resent'] ?? null);
|
||||
|
||||
return $reviewAssignment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new review assignment data object.
|
||||
*
|
||||
* @return ReviewAssignment
|
||||
*/
|
||||
public function newDataObject()
|
||||
{
|
||||
return new ReviewAssignment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete review assignment.
|
||||
*
|
||||
* @param int $reviewId
|
||||
*/
|
||||
public function deleteById($reviewId)
|
||||
{
|
||||
$reviewFormResponseDao = DAORegistry::getDAO('ReviewFormResponseDAO'); /** @var ReviewFormResponseDAO $reviewFormResponseDao */
|
||||
$reviewFormResponseDao->deleteByReviewId($reviewId);
|
||||
|
||||
$reviewFilesDao = DAORegistry::getDAO('ReviewFilesDAO'); /** @var ReviewFilesDAO $reviewFilesDao */
|
||||
$reviewFilesDao->revokeByReviewId($reviewId);
|
||||
|
||||
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
|
||||
$notificationDao->deleteByAssoc(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT, $reviewId);
|
||||
|
||||
// Retrieve the review assignment before it's deleted, so it can be
|
||||
// be used to fire an update on the review round status.
|
||||
$reviewAssignment = $this->getById($reviewId);
|
||||
|
||||
$result = $this->update('DELETE FROM review_assignments WHERE review_id = ?', [(int) $reviewId]);
|
||||
|
||||
$this->updateReviewRoundStatus($reviewAssignment);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete review assignments by submission ID.
|
||||
*
|
||||
* @param int $submissionId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteBySubmissionId($submissionId)
|
||||
{
|
||||
$result = $this->retrieve(
|
||||
'SELECT review_id FROM review_assignments WHERE submission_id = ?',
|
||||
[(int) $submissionId]
|
||||
);
|
||||
|
||||
$returner = false;
|
||||
foreach ($result as $row) {
|
||||
$this->deleteById($row->review_id);
|
||||
$returner = true;
|
||||
}
|
||||
return $returner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last review round review assignment for a given user.
|
||||
*
|
||||
* @param int $submissionId
|
||||
* @param int $reviewerId
|
||||
*
|
||||
* @return ?ReviewAssignment
|
||||
*/
|
||||
public function getLastReviewRoundReviewAssignmentByReviewer($submissionId, $reviewerId)
|
||||
{
|
||||
$result = $this->retrieve(
|
||||
$this->_getSelectQuery() . ' WHERE r.submission_id = ? AND r.reviewer_id = ? ORDER BY r2.stage_id DESC, r2.round DESC',
|
||||
[(int) $submissionId, (int) $reviewerId]
|
||||
);
|
||||
$row = (array) $result->current();
|
||||
return $row ? $this->_fromRow($row) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the review methods translation keys.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getReviewMethodsTranslationKeys()
|
||||
{
|
||||
return [
|
||||
ReviewAssignment::SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS => 'editor.submissionReview.doubleAnonymous',
|
||||
ReviewAssignment::SUBMISSION_REVIEW_METHOD_ANONYMOUS => 'editor.submissionReview.anonymous',
|
||||
ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN => 'editor.submissionReview.open',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sql query to select review assignments.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function _getSelectQuery()
|
||||
{
|
||||
return 'SELECT r.*, r2.review_revision FROM review_assignments r
|
||||
LEFT JOIN review_rounds r2 ON (r.review_round_id = r2.review_round_id)';
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete review assignments by review round ID.
|
||||
*
|
||||
* @param int $reviewRoundId
|
||||
*
|
||||
* @return int Number of deleted review assignments.
|
||||
*/
|
||||
public function deleteByReviewRoundId($reviewRoundId): int
|
||||
{
|
||||
return DB::table('review_assignments')
|
||||
->select(['review_id', 'review_round_id'])
|
||||
->where('review_round_id', $reviewRoundId)
|
||||
->get()
|
||||
->pluck('review_id')
|
||||
->map(fn ($reviewId) => $this->deleteById($reviewId))
|
||||
->count();
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\submission\reviewAssignment\ReviewAssignmentDAO', '\ReviewAssignmentDAO');
|
||||
}
|
||||
Reference in New Issue
Block a user