first commit
This commit is contained in:
@@ -0,0 +1,354 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup submission_reviewRound Review Round
|
||||
*/
|
||||
/**
|
||||
* @file classes/submission/reviewRound/ReviewRound.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 ReviewRound
|
||||
*
|
||||
* @ingroup submission_reviewRound
|
||||
*
|
||||
* @see ReviewRoundDAO
|
||||
*
|
||||
* @brief Basic class describing a review round.
|
||||
*/
|
||||
|
||||
namespace PKP\submission\reviewRound;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\facades\Repo;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\stageAssignment\StageAssignmentDAO;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignmentDAO;
|
||||
|
||||
class ReviewRound extends \PKP\core\DataObject
|
||||
{
|
||||
// The first four statuses are set explicitly by Decisions, which override
|
||||
// the current status.
|
||||
public const REVIEW_ROUND_STATUS_REVISIONS_REQUESTED = 1;
|
||||
public const REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW = 2;
|
||||
public const REVIEW_ROUND_STATUS_SENT_TO_EXTERNAL = 3;
|
||||
public const REVIEW_ROUND_STATUS_ACCEPTED = 4;
|
||||
public const REVIEW_ROUND_STATUS_DECLINED = 5;
|
||||
|
||||
// The following statuses are calculated based on the statuses of ReviewAssignments
|
||||
// in this round.
|
||||
public const REVIEW_ROUND_STATUS_PENDING_REVIEWERS = 6; // No reviewers have been assigned
|
||||
public const REVIEW_ROUND_STATUS_PENDING_REVIEWS = 7; // Waiting for reviews to be submitted by reviewers
|
||||
public const REVIEW_ROUND_STATUS_REVIEWS_READY = 8; // One or more reviews is ready for an editor to view
|
||||
public const REVIEW_ROUND_STATUS_REVIEWS_COMPLETED = 9; // All assigned reviews have been confirmed by an editor
|
||||
public const REVIEW_ROUND_STATUS_REVIEWS_OVERDUE = 10; // One or more reviews is overdue
|
||||
// The following status is calculated when the round is in ReviewRound::REVIEW_ROUND_STATUS_REVISIONS_REQUESTED and
|
||||
// at least one revision file has been uploaded.
|
||||
public const REVIEW_ROUND_STATUS_REVISIONS_SUBMITTED = 11;
|
||||
|
||||
// The following statuses are calculated based on the statuses of recommendOnly EditorAssignments
|
||||
// and their decisions in this round.
|
||||
public const REVIEW_ROUND_STATUS_PENDING_RECOMMENDATIONS = 12; // Waiting for recommendations to be submitted by recommendOnly editors
|
||||
public const REVIEW_ROUND_STATUS_RECOMMENDATIONS_READY = 13; // One or more recommendations are ready for an editor to view
|
||||
public const REVIEW_ROUND_STATUS_RECOMMENDATIONS_COMPLETED = 14; // All assigned recommendOnly editors have made a recommendation
|
||||
|
||||
// The following status is calculated when the round is in ReviewRound::REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW and
|
||||
// at least one revision file has been uploaded.
|
||||
public const REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW_SUBMITTED = 15;
|
||||
|
||||
// The following status is set when a submission return back from copyediting stage to last review round again
|
||||
public const REVIEW_ROUND_STATUS_RETURNED_TO_REVIEW = 16;
|
||||
|
||||
//
|
||||
// Get/set methods
|
||||
//
|
||||
|
||||
/**
|
||||
* get submission id
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSubmissionId()
|
||||
{
|
||||
return $this->getData('submissionId');
|
||||
}
|
||||
|
||||
/**
|
||||
* set submission id
|
||||
*
|
||||
* @param int $submissionId
|
||||
*/
|
||||
public function setSubmissionId($submissionId)
|
||||
{
|
||||
$this->setData('submissionId', $submissionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get review stage id (internal or external review).
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStageId()
|
||||
{
|
||||
return $this->getData('stageId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set review stage id
|
||||
*
|
||||
* @param int $stageId
|
||||
*/
|
||||
public function setStageId($stageId)
|
||||
{
|
||||
$this->setData('stageId', $stageId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get review round
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRound()
|
||||
{
|
||||
return $this->getData('round');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set review round
|
||||
*/
|
||||
public function setRound($round)
|
||||
{
|
||||
$this->setData('round', $round);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current round status
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStatus()
|
||||
{
|
||||
return $this->getData('status');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set current round status
|
||||
*
|
||||
* @param int $status
|
||||
*/
|
||||
public function setStatus($status)
|
||||
{
|
||||
$this->setData('status', $status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the status of this review round.
|
||||
*
|
||||
* If the round is in revisions, it will search for revision files and set
|
||||
* the status accordingly. If the round has not reached a revision status
|
||||
* yet, it will determine the status based on the statuses of the round's
|
||||
* ReviewAssignments.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function determineStatus()
|
||||
{
|
||||
// If revisions have been requested, check to see if any have been
|
||||
// submitted
|
||||
if ($this->getStatus() == self::REVIEW_ROUND_STATUS_REVISIONS_REQUESTED || $this->getStatus() == self::REVIEW_ROUND_STATUS_REVISIONS_SUBMITTED) {
|
||||
// get editor decisions
|
||||
$pendingRevisionDecision = Repo::decision()->getActivePendingRevisionsDecision($this->getSubmissionId(), $this->getStageId(), Decision::PENDING_REVISIONS);
|
||||
|
||||
if ($pendingRevisionDecision) {
|
||||
if (Repo::decision()->revisionsUploadedSinceDecision($pendingRevisionDecision, $this->getSubmissionId())) {
|
||||
return self::REVIEW_ROUND_STATUS_REVISIONS_SUBMITTED;
|
||||
}
|
||||
}
|
||||
return self::REVIEW_ROUND_STATUS_REVISIONS_REQUESTED;
|
||||
}
|
||||
|
||||
// If revisions have been requested for re-submission, check to see if any have been
|
||||
// submitted
|
||||
if ($this->getStatus() == self::REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW || $this->getStatus() == self::REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW_SUBMITTED) {
|
||||
// get editor decisions
|
||||
$pendingRevisionDecision = Repo::decision()->getActivePendingRevisionsDecision($this->getSubmissionId(), $this->getStageId(), Decision::RESUBMIT);
|
||||
|
||||
if ($pendingRevisionDecision) {
|
||||
if (Repo::decision()->revisionsUploadedSinceDecision($pendingRevisionDecision, $this->getSubmissionId())) {
|
||||
return self::REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW_SUBMITTED;
|
||||
}
|
||||
}
|
||||
return self::REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW;
|
||||
}
|
||||
|
||||
$statusFinished = in_array(
|
||||
$this->getStatus(),
|
||||
[
|
||||
self::REVIEW_ROUND_STATUS_SENT_TO_EXTERNAL,
|
||||
self::REVIEW_ROUND_STATUS_ACCEPTED,
|
||||
self::REVIEW_ROUND_STATUS_DECLINED
|
||||
]
|
||||
);
|
||||
if ($statusFinished) {
|
||||
return $this->getStatus();
|
||||
}
|
||||
|
||||
// Determine the round status by looking at the recommendOnly editor assignment statuses
|
||||
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */
|
||||
$pendingRecommendations = false;
|
||||
$recommendationsFinished = true;
|
||||
$recommendationsReady = false;
|
||||
$editorsStageAssignments = $stageAssignmentDao->getEditorsAssignedToStage($this->getSubmissionId(), $this->getStageId());
|
||||
foreach ($editorsStageAssignments as $editorsStageAssignment) {
|
||||
if ($editorsStageAssignment->getRecommendOnly()) {
|
||||
$pendingRecommendations = true;
|
||||
// Get recommendation from the assigned recommendOnly editor
|
||||
$decisions = Repo::decision()->getCollector()
|
||||
->filterBySubmissionIds([$this->getSubmissionId()])
|
||||
->filterByStageIds([$this->getStageId()])
|
||||
->filterByReviewRoundIds([$this->getId()])
|
||||
->filterByEditorIds([$editorsStageAssignment->getUserId()])
|
||||
->getCount();
|
||||
|
||||
if (!$decisions) {
|
||||
$recommendationsFinished = false;
|
||||
} else {
|
||||
$recommendationsReady = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($pendingRecommendations) {
|
||||
if ($recommendationsFinished) {
|
||||
return self::REVIEW_ROUND_STATUS_RECOMMENDATIONS_COMPLETED;
|
||||
} elseif ($recommendationsReady) {
|
||||
return self::REVIEW_ROUND_STATUS_RECOMMENDATIONS_READY;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the round status by looking at the assignment statuses
|
||||
$anyOverdueReview = false;
|
||||
$anyIncompletedReview = false;
|
||||
$anyUnreadReview = false;
|
||||
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
|
||||
$reviewAssignments = $reviewAssignmentDao->getByReviewRoundId($this->getId());
|
||||
foreach ($reviewAssignments as $reviewAssignment) {
|
||||
assert($reviewAssignment instanceof ReviewAssignment);
|
||||
|
||||
$assignmentStatus = $reviewAssignment->getStatus();
|
||||
|
||||
switch ($assignmentStatus) {
|
||||
case ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_DECLINED:
|
||||
case ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_CANCELLED:
|
||||
break;
|
||||
|
||||
case ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_RESPONSE_OVERDUE:
|
||||
case ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_REVIEW_OVERDUE:
|
||||
$anyOverdueReview = true;
|
||||
break;
|
||||
|
||||
case ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_AWAITING_RESPONSE:
|
||||
case ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_ACCEPTED:
|
||||
$anyIncompletedReview = true;
|
||||
break;
|
||||
|
||||
case ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_RECEIVED:
|
||||
$anyUnreadReview = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the correct review round status based on the state of
|
||||
// the current review assignments. The check order matters: the
|
||||
// first conditions override the others.
|
||||
if (empty($reviewAssignments)) {
|
||||
return self::REVIEW_ROUND_STATUS_PENDING_REVIEWERS;
|
||||
} elseif ($anyOverdueReview) {
|
||||
return self::REVIEW_ROUND_STATUS_REVIEWS_OVERDUE;
|
||||
} elseif ($anyUnreadReview) {
|
||||
return self::REVIEW_ROUND_STATUS_REVIEWS_READY;
|
||||
} elseif ($anyIncompletedReview) {
|
||||
return self::REVIEW_ROUND_STATUS_PENDING_REVIEWS;
|
||||
} elseif ($pendingRecommendations) {
|
||||
return self::REVIEW_ROUND_STATUS_PENDING_RECOMMENDATIONS;
|
||||
}
|
||||
|
||||
// The submission back form copy editing stage to last review round
|
||||
if ($this->getStatus() == self::REVIEW_ROUND_STATUS_RETURNED_TO_REVIEW) {
|
||||
return self::REVIEW_ROUND_STATUS_RETURNED_TO_REVIEW;
|
||||
}
|
||||
|
||||
return self::REVIEW_ROUND_STATUS_REVIEWS_COMPLETED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get locale key associated with current status
|
||||
*
|
||||
* @param bool $isAuthor True iff the status is to be shown to the author (slightly tweaked phrasing)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getStatusKey($isAuthor = false)
|
||||
{
|
||||
switch ($this->determineStatus()) {
|
||||
case self::REVIEW_ROUND_STATUS_REVISIONS_REQUESTED:
|
||||
return 'editor.submission.roundStatus.revisionsRequested';
|
||||
case self::REVIEW_ROUND_STATUS_REVISIONS_SUBMITTED:
|
||||
return 'editor.submission.roundStatus.revisionsSubmitted';
|
||||
case self::REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW:
|
||||
return 'editor.submission.roundStatus.resubmitForReview';
|
||||
case self::REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW_SUBMITTED:
|
||||
return 'editor.submission.roundStatus.submissionResubmitted';
|
||||
case self::REVIEW_ROUND_STATUS_SENT_TO_EXTERNAL:
|
||||
return 'editor.submission.roundStatus.sentToExternal';
|
||||
case self::REVIEW_ROUND_STATUS_ACCEPTED:
|
||||
return 'editor.submission.roundStatus.accepted';
|
||||
case self::REVIEW_ROUND_STATUS_DECLINED:
|
||||
return 'editor.submission.roundStatus.declined';
|
||||
case self::REVIEW_ROUND_STATUS_PENDING_REVIEWERS:
|
||||
return 'editor.submission.roundStatus.pendingReviewers';
|
||||
case self::REVIEW_ROUND_STATUS_PENDING_REVIEWS:
|
||||
return 'editor.submission.roundStatus.pendingReviews';
|
||||
case self::REVIEW_ROUND_STATUS_REVIEWS_READY:
|
||||
return $isAuthor ? 'author.submission.roundStatus.reviewsReady' : 'editor.submission.roundStatus.reviewsReady';
|
||||
case self::REVIEW_ROUND_STATUS_REVIEWS_COMPLETED:
|
||||
return 'editor.submission.roundStatus.reviewsCompleted';
|
||||
case self::REVIEW_ROUND_STATUS_REVIEWS_OVERDUE:
|
||||
return $isAuthor ? 'author.submission.roundStatus.reviewOverdue' : 'editor.submission.roundStatus.reviewOverdue';
|
||||
case self::REVIEW_ROUND_STATUS_PENDING_RECOMMENDATIONS:
|
||||
return 'editor.submission.roundStatus.pendingRecommendations';
|
||||
case self::REVIEW_ROUND_STATUS_RECOMMENDATIONS_READY:
|
||||
return 'editor.submission.roundStatus.recommendationsReady';
|
||||
case self::REVIEW_ROUND_STATUS_RECOMMENDATIONS_COMPLETED:
|
||||
return 'editor.submission.roundStatus.recommendationsCompleted';
|
||||
case self::REVIEW_ROUND_STATUS_RETURNED_TO_REVIEW:
|
||||
return 'editor.submission.roundStatus.returnedToReview';
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\submission\reviewRound\ReviewRound', '\ReviewRound');
|
||||
foreach ([
|
||||
'REVIEW_ROUND_STATUS_REVISIONS_REQUESTED',
|
||||
'REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW',
|
||||
'REVIEW_ROUND_STATUS_SENT_TO_EXTERNAL',
|
||||
'REVIEW_ROUND_STATUS_ACCEPTED',
|
||||
'REVIEW_ROUND_STATUS_DECLINED',
|
||||
'REVIEW_ROUND_STATUS_PENDING_REVIEWERS',
|
||||
'REVIEW_ROUND_STATUS_PENDING_REVIEWS',
|
||||
'REVIEW_ROUND_STATUS_REVIEWS_READY',
|
||||
'REVIEW_ROUND_STATUS_REVIEWS_COMPLETED',
|
||||
'REVIEW_ROUND_STATUS_REVIEWS_OVERDUE',
|
||||
'REVIEW_ROUND_STATUS_REVISIONS_SUBMITTED',
|
||||
'REVIEW_ROUND_STATUS_PENDING_RECOMMENDATIONS',
|
||||
'REVIEW_ROUND_STATUS_RECOMMENDATIONS_READY',
|
||||
'REVIEW_ROUND_STATUS_RECOMMENDATIONS_COMPLETED',
|
||||
'REVIEW_ROUND_STATUS_RESUBMIT_FOR_REVIEW_SUBMITTED',
|
||||
] as $constantName) {
|
||||
define($constantName, constant('\ReviewRound::' . $constantName));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user