diff --git a/api/v1/_submissions/PKPBackendSubmissionsController.php b/api/v1/_submissions/PKPBackendSubmissionsController.php index 0d1dded80e1..8ffd6053a7e 100644 --- a/api/v1/_submissions/PKPBackendSubmissionsController.php +++ b/api/v1/_submissions/PKPBackendSubmissionsController.php @@ -112,6 +112,7 @@ public function getGroupRoutes(): void Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT, + Role::ROLE_ID_AUTHOR, ]), ]); @@ -122,11 +123,12 @@ public function getGroupRoutes(): void Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT, + Role::ROLE_ID_AUTHOR, ]) ]); Route::get('viewsCount', $this->assigned(...)) - ->name('_submission.viewsCount') + ->name('_submission.getViewsCount') ->middleware([ self::roleAuthorizer([ Role::ROLE_ID_MANAGER, @@ -134,6 +136,12 @@ public function getGroupRoutes(): void Role::ROLE_ID_ASSISTANT, ]) ]); + + Route::get('reviewAssignments', $this->assigned(...)) + ->name('_submission.getReviewAssignments') + ->middleware([ + Role::ROLE_ID_REVIEWER, + ]); } } @@ -185,10 +193,6 @@ public function getMany(Request $illuminateRequest): JsonResponse } $collector->assignedTo($val); break; - - case 'isIncomplete': - $collector->filterByIncomplete(true); - break; } } @@ -304,6 +308,12 @@ public function reviews(SlimRequest $slimRequest, APIResponse $response, array $ case 'reviewsOverdue': $collector->filterByOverdue(true); break; + case 'revisionsRequested': + $collector->filterByRevisionsRequested(true); + break; + case 'revisionsSubmitted': + $collector->filterByRevisionsSubmitted(true); + break; } } @@ -326,7 +336,7 @@ public function reviews(SlimRequest $slimRequest, APIResponse $response, array $ /** * Get a number of the submissions for each view */ - public function viewsCount(SlimRequest $slimRequest, APIResponse $response, array $args): APIResponse + public function getViewsCount(SlimRequest $slimRequest, APIResponse $response, array $args): APIResponse { $request = Application::get()->getRequest(); $context = $request->getContext(); @@ -340,6 +350,19 @@ public function viewsCount(SlimRequest $slimRequest, APIResponse $response, arra return $response->withJson($dashboardViews->map(fn(DashboardView $view) => $view->getCount()), 200); } + /** + * Get all reviewer's assignments + */ + public function getReviewAssignments(SlimRequest $slimRequest, APIResponse $response, array $args) + { + $request = Application::get()->getRequest(); + $context = $request->getContext(); + if (!$context) { + return $response->withStatus(404)->withJsonError('api.404.resourceNotFound'); + } + $currentUser = $request->getUser(); + } + /** * Delete a submission */ @@ -436,6 +459,10 @@ protected function getSubmissionCollector(array $queryParams): Collector case 'isOverdue': $collector->filterByOverdue(true); break; + + case 'isIncomplete': + $collector->filterByIncomplete(true); + break; } } diff --git a/api/v1/submissions/PKPSubmissionController.php b/api/v1/submissions/PKPSubmissionController.php index ea6be4640c1..09ef8c0b9de 100644 --- a/api/v1/submissions/PKPSubmissionController.php +++ b/api/v1/submissions/PKPSubmissionController.php @@ -886,11 +886,13 @@ public function getPublications(Request $illuminateRequest): JsonResponse ->filterByContextIds([$submission->getData('contextId')]) ->getMany(); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var \PKP\submission\reviewAssignment\ReviewAssignmentDAO $reviewAssignmentDao */ - $currentUserReviewAssignment = $reviewAssignmentDao->getLastReviewRoundReviewAssignmentByReviewer( - $submission->getId(), - $request->getUser()->getId() - ); + $currentUserReviewAssignment = Repo::reviewAssignment()->getCollector() + ->filterBySubmissionIds([$submission->getId()]) + ->filterByReviewerIds([$request->getUser()->getId()]) + ->filterByLastReviewRound(true) + ->getMany() + ->first(); + $anonymize = $currentUserReviewAssignment && $currentUserReviewAssignment->getReviewMethod() === ReviewAssignment::SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS; /** @var GenreDAO $genreDao */ diff --git a/classes/controllers/grid/users/reviewer/PKPReviewerGridHandler.php b/classes/controllers/grid/users/reviewer/PKPReviewerGridHandler.php index 6fb2f63925a..31cb644e837 100644 --- a/classes/controllers/grid/users/reviewer/PKPReviewerGridHandler.php +++ b/classes/controllers/grid/users/reviewer/PKPReviewerGridHandler.php @@ -63,7 +63,6 @@ use PKP\security\Role; use PKP\security\Validation; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\reviewRound\ReviewRound; use PKP\submission\reviewRound\ReviewRoundDAO; use PKP\submission\SubmissionCommentDAO; @@ -330,8 +329,12 @@ protected function loadData($request, $filter) { // Get the existing review assignments for this submission $reviewRound = $this->getReviewRound(); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - return $reviewAssignmentDao->getByReviewRoundId($reviewRound->getId()); + return Repo::reviewAssignment()->getCollector() + ->filterByReviewRoundIds([$reviewRound->getId()]) + ->getMany() + ->keyBy(fn(ReviewAssignment $reviewAssignment, int $key) => $reviewAssignment->getId()) + ->sortKeys() + ->toArray(); } @@ -676,10 +679,8 @@ public function unconsiderReview($args, $request) $submission = $this->getSubmission(); $user = $request->getUser(); $reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment->setConsidered(ReviewAssignment::REVIEW_ASSIGNMENT_UNCONSIDERED); - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, ['considered' => ReviewAssignment::REVIEW_ASSIGNMENT_UNCONSIDERED]); // log the unconsider. $eventLog = Repo::eventLog()->newDataObject([ @@ -718,39 +719,32 @@ public function reviewRead($args, $request) // Rate the reviewer's performance on this assignment $quality = $request->getUserVar('quality'); + $newReviewData = []; if ($quality) { - $reviewAssignment->setQuality((int) $quality); - $reviewAssignment->setDateRated(Core::getCurrentDate()); + $newReviewData['quality'] = (int) $quality; + $newReviewData['dateRated'] = Core::getCurrentDate(); } else { - $reviewAssignment->setQuality(null); - $reviewAssignment->setDateRated(null); + $newReviewData['quality'] = $newReviewData['dateRated'] = null; } - // Mark the latest read date of the review by the editor. - $user = $request->getUser(); - // if the review assignment had been unconsidered, update the flag. - $reviewAssignment->setConsidered( - $reviewAssignment->getConsidered() === ReviewAssignment::REVIEW_ASSIGNMENT_NEW - ? ReviewAssignment::REVIEW_ASSIGNMENT_CONSIDERED - : ReviewAssignment::REVIEW_ASSIGNMENT_RECONSIDERED - ); + $newReviewData['considered'] = $reviewAssignment->getConsidered() === ReviewAssignment::REVIEW_ASSIGNMENT_NEW + ? ReviewAssignment::REVIEW_ASSIGNMENT_CONSIDERED + : ReviewAssignment::REVIEW_ASSIGNMENT_RECONSIDERED; if (!$reviewAssignment->getDateCompleted()) { // Editor completes the review. - $reviewAssignment->setDateConfirmed(Core::getCurrentDate()); - $reviewAssignment->setDateCompleted(Core::getCurrentDate()); + $newReviewData['dateConfirmed'] = $newReviewData['dateCompleted'] = Core::getCurrentDate(); } // Trigger an update of the review round status - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, $newReviewData); //if the review was read by an editor, log event if ($reviewAssignment->isRead()) { $submissionId = $reviewAssignment->getSubmissionId(); $submission = Repo::submission()->get($submissionId); - + $user = $request->getUser(); $eventLog = Repo::eventLog()->newDataObject([ 'assocType' => PKPApplication::ASSOC_TYPE_SUBMISSION, 'assocId' => $submission->getId(), diff --git a/classes/core/PKPApplication.php b/classes/core/PKPApplication.php index 4ce4f447184..f2824003287 100644 --- a/classes/core/PKPApplication.php +++ b/classes/core/PKPApplication.php @@ -492,7 +492,6 @@ public function getDAOMap() 'PluginSettingsDAO' => 'PKP\plugins\PluginSettingsDAO', 'PublicationDAO' => 'APP\publication\PublicationDAO', 'QueuedPaymentDAO' => 'PKP\payment\QueuedPaymentDAO', - 'ReviewAssignmentDAO' => 'PKP\submission\reviewAssignment\ReviewAssignmentDAO', 'ReviewFilesDAO' => 'PKP\submission\ReviewFilesDAO', 'ReviewFormDAO' => 'PKP\reviewForm\ReviewFormDAO', 'ReviewFormElementDAO' => 'PKP\reviewForm\ReviewFormElementDAO', diff --git a/classes/decision/types/CancelReviewRound.php b/classes/decision/types/CancelReviewRound.php index ae81b406928..630e2eb2f1a 100644 --- a/classes/decision/types/CancelReviewRound.php +++ b/classes/decision/types/CancelReviewRound.php @@ -16,6 +16,7 @@ namespace PKP\decision\types; use APP\decision\Decision; +use APP\facades\Repo; use APP\submission\Submission; use Illuminate\Validation\Validator; use PKP\context\Context; @@ -193,10 +194,11 @@ public function runAdditionalActions(Decision $decision, Submission $submission, } $reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /** @var ReviewRoundDAO $reviewRoundDao */ - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var \PKP\submission\reviewAssignment\ReviewAssignmentDAO $reviewAssignmentDao */ $reviewRoundId = $decision->getData('reviewRoundId'); - $reviewAssignmentDao->deleteByReviewRoundId($reviewRoundId); + Repo::reviewAssignment()->deleteMany( + Repo::reviewAssignment()->getCollector()->filterByReviewRoundIds([$reviewRoundId]) + ); $reviewRoundDao->deleteById($reviewRoundId); } diff --git a/classes/decision/types/traits/InExternalReviewRound.php b/classes/decision/types/traits/InExternalReviewRound.php index aeb94dbb9a0..0e2cd6e8078 100644 --- a/classes/decision/types/traits/InExternalReviewRound.php +++ b/classes/decision/types/traits/InExternalReviewRound.php @@ -21,8 +21,7 @@ use PKP\components\fileAttachers\ReviewFiles; use PKP\components\fileAttachers\Upload; use PKP\context\Context; -use PKP\db\DAORegistry; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; +use PKP\submission\reviewAssignment\ReviewAssignment; use PKP\submission\reviewRound\ReviewRound; use PKP\submissionFile\SubmissionFile; @@ -78,9 +77,13 @@ protected function getFileAttachers(Submission $submission, Context $context, ?R ]; if ($reviewRound) { - /** @var ReviewAssignmentDAO $reviewAssignmentDAO */ - $reviewAssignmentDAO = DAORegistry::getDAO('ReviewAssignmentDAO'); - $reviewAssignments = $reviewAssignmentDAO->getByReviewRoundId($reviewRound->getId()); + $reviewAssignments = Repo::reviewAssignment()->getCollector() + ->filterByReviewRoundIds([$reviewRound->getId()]) + ->getMany() + ->keyBy(fn(ReviewAssignment $reviewAssignment, int $key) => $reviewAssignment->getId()) + ->sortKeys() + ->toArray(); + $reviewerFiles = []; if (!empty($reviewAssignments)) { $reviewerFiles = Repo::submissionFile() diff --git a/classes/decision/types/traits/NotifyReviewers.php b/classes/decision/types/traits/NotifyReviewers.php index 8cc99aee765..89cc37a1942 100644 --- a/classes/decision/types/traits/NotifyReviewers.php +++ b/classes/decision/types/traits/NotifyReviewers.php @@ -20,14 +20,11 @@ use Illuminate\Validation\Validator; use PKP\core\Core; use PKP\core\PKPApplication; -use PKP\db\DAORegistry; use PKP\log\event\PKPSubmissionEventLogEntry; use PKP\mail\EmailData; use PKP\mail\mailables\DecisionNotifyReviewer; use PKP\mail\mailables\ReviewerUnassign; use PKP\security\Validation; -use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\user\User; trait NotifyReviewers @@ -52,13 +49,15 @@ protected function sendReviewersEmail(DecisionNotifyReviewer|ReviewerUnassign $m // Update the ReviewAssignment to indicate the reviewer has been acknowledged if (is_a($mailable, DecisionNotifyReviewer::class)) { - /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); - $reviewAssignment = $reviewAssignmentDao->getReviewAssignment($mailable->getDecision()->getData('reviewRoundId'), $recipient->getId()); + $reviewAssignment = Repo::reviewAssignment()->getCollector() + ->filterByReviewRoundIds([$mailable->getDecision()->getData('reviewRoundId')]) + ->filterByReviewerIds([$recipient->getId()]) + ->getMany() + ->first(); if ($reviewAssignment) { - $reviewAssignment->setDateAcknowledged(Core::getCurrentDate()); - $reviewAssignment->stampModified(); - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, [ + 'dateAcknowledged' => Core::getCurrentDate(), + ]); } } } diff --git a/classes/decision/types/traits/WithReviewAssignments.php b/classes/decision/types/traits/WithReviewAssignments.php index dbbbf9c70bf..510474b2cd4 100644 --- a/classes/decision/types/traits/WithReviewAssignments.php +++ b/classes/decision/types/traits/WithReviewAssignments.php @@ -14,11 +14,10 @@ namespace PKP\decision\types\traits; +use APP\facades\Repo; use Exception; -use PKP\db\DAORegistry; use PKP\decision\DecisionType; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; trait WithReviewAssignments { @@ -36,10 +35,12 @@ trait WithReviewAssignments */ protected function getReviewAssignments(int $submissionId, int $reviewRoundId, int $reviewAssignmentStatus): array { - /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); + $reviewAssignments = Repo::reviewAssignment()->getCollector() + ->filterByReviewRoundIds([$reviewRoundId]) + ->filterBySubmissionIds([$submissionId]) + ->filterByStageId($this->getStageId()) + ->getMany(); - $reviewAssignments = $reviewAssignmentDao->getBySubmissionId($submissionId, $reviewRoundId, $this->getStageId()); $assignments = []; foreach ($reviewAssignments as $reviewAssignment) { diff --git a/classes/invitation/invitations/ReviewerAccessInvite.php b/classes/invitation/invitations/ReviewerAccessInvite.php index f3e46387b52..f65bfc831ce 100644 --- a/classes/invitation/invitations/ReviewerAccessInvite.php +++ b/classes/invitation/invitations/ReviewerAccessInvite.php @@ -20,7 +20,6 @@ use APP\facades\Repo; use Illuminate\Mail\Mailable; use PKP\core\PKPApplication; -use PKP\db\DAORegistry; use PKP\invitation\invitations\enums\InvitationStatus; use PKP\mail\variables\ReviewAssignmentEmailVariable; use PKP\security\Validation; @@ -46,8 +45,7 @@ public function __construct( parent::__construct($invitedUserId, null, $contextId, $reviewAssignmentId, $expiryDays); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $this->reviewAssignment = $reviewAssignmentDao->getById($reviewAssignmentId); + $this->reviewAssignment = Repo::reviewAssignment()->get($this->reviewAssignmentId); } public function getMailable(): ?Mailable @@ -127,8 +125,7 @@ private function _validateAccessKey(): bool return false; } - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getById($reviewId); + $reviewAssignment = Repo::reviewAssignment()->get($reviewId); if (!$reviewAssignment) { return false; } // e.g. deleted review assignment diff --git a/classes/log/event/EventLogEntry.php b/classes/log/event/EventLogEntry.php index 1e6d826c772..c8068167482 100644 --- a/classes/log/event/EventLogEntry.php +++ b/classes/log/event/EventLogEntry.php @@ -18,7 +18,6 @@ use APP\core\Application; use APP\facades\Repo; -use PKP\db\DAORegistry; use PKP\facades\Locale; use PKP\submission\reviewAssignment\ReviewAssignment; use PKP\submissionFile\SubmissionFile; @@ -196,12 +195,11 @@ public function getTranslatedMessage($locale = null, $hideReviewerName = false) $eventLog = clone $this; if ($hideReviewerName) { - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var \PKP\submission\reviewAssignment\ReviewAssignmentDAO $reviewAssignmentDao */ // Reviewer activity log entries (assigning, accepting, declining) if ($eventLog->getData('reviewerName')) { $anonymousAuthor = true; if ($reviewAssignmentId = $eventLog->getData('reviewAssignmentId')) { - $reviewAssignment = $reviewAssignmentDao->getById($reviewAssignmentId); + $reviewAssignment = Repo::reviewAssignment()->get($reviewAssignmentId); if ($reviewAssignment && !in_array($reviewAssignment->getReviewMethod(), [ReviewAssignment::SUBMISSION_REVIEW_METHOD_ANONYMOUS, ReviewAssignment::SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS])) { $anonymousAuthor = false; } @@ -218,7 +216,7 @@ public function getTranslatedMessage($locale = null, $hideReviewerName = false) $anonymousAuthor = true; $submissionFile = Repo::submissionFile()->get($submissionFileId); if ($submissionFile && $submissionFile->getData('assocType') === Application::ASSOC_TYPE_REVIEW_ASSIGNMENT) { - $reviewAssignment = $reviewAssignmentDao->getById($submissionFile->getData('assocId')); + $reviewAssignment = Repo::reviewAssignment()->get($submissionFile->getData('assocId')); if ($reviewAssignment && !in_array($reviewAssignment->getReviewMethod(), [ReviewAssignment::SUBMISSION_REVIEW_METHOD_ANONYMOUS, ReviewAssignment::SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS])) { $anonymousAuthor = false; } diff --git a/classes/notification/PKPNotificationManager.php b/classes/notification/PKPNotificationManager.php index 6d93703fa21..3136e2699e5 100644 --- a/classes/notification/PKPNotificationManager.php +++ b/classes/notification/PKPNotificationManager.php @@ -36,7 +36,6 @@ use PKP\payment\QueuedPaymentDAO; use PKP\security\Role; use PKP\stageAssignment\StageAssignmentDAO; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\reviewRound\ReviewRoundDAO; use PKP\workflow\WorkflowStageDAO; @@ -65,15 +64,13 @@ public function getNotificationUrl($request, $notification) return $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'workflow', 'access', $notification->getAssocId()); case PKPNotification::NOTIFICATION_TYPE_REVIEWER_COMMENT: assert($notification->getAssocType() == Application::ASSOC_TYPE_REVIEW_ASSIGNMENT && is_numeric($notification->getAssocId())); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getById($notification->getAssocId()); + $reviewAssignment = Repo::reviewAssignment()->get($notification->getAssocId()); $workflowStageDao = DAORegistry::getDAO('WorkflowStageDAO'); /** @var WorkflowStageDAO $workflowStageDao */ $operation = $reviewAssignment->getStageId() == WORKFLOW_STAGE_ID_INTERNAL_REVIEW ? $workflowStageDao::WORKFLOW_STAGE_PATH_INTERNAL_REVIEW : $workflowStageDao::WORKFLOW_STAGE_PATH_EXTERNAL_REVIEW; return $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'workflow', $operation, $reviewAssignment->getSubmissionId()); case PKPNotification::NOTIFICATION_TYPE_REVIEW_ASSIGNMENT: case PKPNotification::NOTIFICATION_TYPE_REVIEW_ASSIGNMENT_UPDATED: - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getById($notification->getAssocId()); + $reviewAssignment = Repo::reviewAssignment()->get($notification->getAssocId()); return $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'reviewer', 'submission', $reviewAssignment->getSubmissionId()); case PKPNotification::NOTIFICATION_TYPE_NEW_ANNOUNCEMENT: assert($notification->getAssocType() == Application::ASSOC_TYPE_ANNOUNCEMENT); @@ -141,8 +138,7 @@ public function getNotificationMessage($request, $notification) return $this->_getTranslatedKeyWithParameters('common.pluginDisabled', $notification->getId()); case PKPNotification::NOTIFICATION_TYPE_REVIEWER_COMMENT: assert($notification->getAssocType() == Application::ASSOC_TYPE_REVIEW_ASSIGNMENT && is_numeric($notification->getAssocId())); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getById($notification->getAssocId()); + $reviewAssignment = Repo::reviewAssignment()->get($notification->getAssocId()); $submission = Repo::submission()->get($reviewAssignment->getSubmissionId()); return __('notification.type.reviewerComment', ['title' => $submission->getCurrentPublication()->getLocalizedTitle(null, 'html')]); case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGN: diff --git a/classes/security/authorization/ReviewAssignmentFileWritePolicy.php b/classes/security/authorization/ReviewAssignmentFileWritePolicy.php index 1fc4ee1fc6e..7f78d54ff78 100644 --- a/classes/security/authorization/ReviewAssignmentFileWritePolicy.php +++ b/classes/security/authorization/ReviewAssignmentFileWritePolicy.php @@ -19,11 +19,10 @@ use APP\core\Application; use APP\core\Request; +use APP\facades\Repo; use PKP\core\PKPRequest; -use PKP\db\DAORegistry; use PKP\security\Role; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; class ReviewAssignmentFileWritePolicy extends AuthorizationPolicy { @@ -67,9 +66,7 @@ public function effect() return AuthorizationPolicy::AUTHORIZATION_DENY; } - /** @var ReviewAssignmentDAO */ - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); - $reviewAssignment = $reviewAssignmentDao->getById($this->_reviewAssignmentId); + $reviewAssignment = Repo::reviewAssignment()->get($this->_reviewAssignmentId); if (!($reviewAssignment instanceof ReviewAssignment)) { return AuthorizationPolicy::AUTHORIZATION_DENY; diff --git a/classes/security/authorization/internal/QueryUserAccessibleWorkflowStageRequiredPolicy.php b/classes/security/authorization/internal/QueryUserAccessibleWorkflowStageRequiredPolicy.php index f7ae9232c86..448c93e4282 100644 --- a/classes/security/authorization/internal/QueryUserAccessibleWorkflowStageRequiredPolicy.php +++ b/classes/security/authorization/internal/QueryUserAccessibleWorkflowStageRequiredPolicy.php @@ -17,10 +17,9 @@ namespace PKP\security\authorization\internal; use APP\core\Application; -use PKP\db\DAORegistry; +use APP\facades\Repo; use PKP\security\authorization\AuthorizationPolicy; use PKP\security\Role; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; class QueryUserAccessibleWorkflowStageRequiredPolicy extends UserAccessibleWorkflowStageRequiredPolicy { @@ -42,8 +41,7 @@ public function effect() } $submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignments = $reviewAssignmentDao->getBySubmissionId($submission->getId()); + $reviewAssignments = Repo::reviewAssignment()->getCollector()->filterBySubmissionIds([$submission->getId()])->getMany(); foreach ($reviewAssignments as $reviewAssignment) { if ($reviewAssignment->getReviewerId() == $this->_request->getUser()->getId()) { $accessibleWorkflowStages = (array) $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES); diff --git a/classes/security/authorization/internal/ReviewAssignmentAccessPolicy.php b/classes/security/authorization/internal/ReviewAssignmentAccessPolicy.php index c118d3b9f17..abc2024de3f 100644 --- a/classes/security/authorization/internal/ReviewAssignmentAccessPolicy.php +++ b/classes/security/authorization/internal/ReviewAssignmentAccessPolicy.php @@ -19,11 +19,10 @@ namespace PKP\security\authorization\internal; use APP\core\Application; +use APP\facades\Repo; use APP\submission\Submission; use PKP\core\PKPRequest; -use PKP\db\DAORegistry; use PKP\security\authorization\AuthorizationPolicy; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\user\User; class ReviewAssignmentAccessPolicy extends AuthorizationPolicy @@ -67,9 +66,11 @@ public function effect() return AuthorizationPolicy::AUTHORIZATION_DENY; } - // Check if a review assignment exists between the submission and the user - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getLastReviewRoundReviewAssignmentByReviewer($submission->getId(), $user->getId()); + $reviewAssignment = Repo::reviewAssignment()->getCollector() + ->filterBySubmissionIds([$submission->getId()]) + ->filterByReviewerIds([$user->getId()]) + ->getMany() + ->first(); // Ensure a valid review assignment was fetched from the database if (!($reviewAssignment instanceof \PKP\submission\reviewAssignment\ReviewAssignment)) { diff --git a/classes/security/authorization/internal/ReviewAssignmentRequiredPolicy.php b/classes/security/authorization/internal/ReviewAssignmentRequiredPolicy.php index be915d44958..14b6b0b96a2 100644 --- a/classes/security/authorization/internal/ReviewAssignmentRequiredPolicy.php +++ b/classes/security/authorization/internal/ReviewAssignmentRequiredPolicy.php @@ -16,12 +16,11 @@ namespace PKP\security\authorization\internal; use APP\core\Application; +use APP\facades\Repo; use APP\submission\Submission; use PKP\core\PKPRequest; -use PKP\db\DAORegistry; use PKP\security\authorization\AuthorizationPolicy; use PKP\security\authorization\DataObjectRequiredPolicy; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; class ReviewAssignmentRequiredPolicy extends DataObjectRequiredPolicy { @@ -58,8 +57,7 @@ public function dataObjectEffect() return AuthorizationPolicy::AUTHORIZATION_DENY; } - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getById($reviewId); + $reviewAssignment = Repo::reviewAssignment()->get($reviewId); if (!($reviewAssignment instanceof \PKP\submission\reviewAssignment\ReviewAssignment)) { return AuthorizationPolicy::AUTHORIZATION_DENY; } diff --git a/classes/security/authorization/internal/SubmissionFileAssignedReviewerAccessPolicy.php b/classes/security/authorization/internal/SubmissionFileAssignedReviewerAccessPolicy.php index 386f6dcd5e8..a0c3f4712b7 100644 --- a/classes/security/authorization/internal/SubmissionFileAssignedReviewerAccessPolicy.php +++ b/classes/security/authorization/internal/SubmissionFileAssignedReviewerAccessPolicy.php @@ -18,10 +18,10 @@ namespace PKP\security\authorization\internal; use APP\core\Application; +use APP\facades\Repo; use Exception; use PKP\db\DAORegistry; use PKP\security\authorization\AuthorizationPolicy; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\ReviewFilesDAO; use PKP\submissionFile\SubmissionFile; @@ -50,8 +50,7 @@ public function effect() } $context = $request->getContext(); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignments = $reviewAssignmentDao->getByUserId($user->getId()); + $reviewAssignments = Repo::reviewAssignment()->getCollector()->filterByReviewerIds([$user->getId()]); $reviewFilesDao = DAORegistry::getDAO('ReviewFilesDAO'); /** @var ReviewFilesDAO $reviewFilesDao */ foreach ($reviewAssignments as $reviewAssignment) { if ($context->getData('restrictReviewerFileAccess') && !$reviewAssignment->getDateConfirmed()) { diff --git a/classes/security/authorization/internal/SubmissionFileAuthorEditorPolicy.php b/classes/security/authorization/internal/SubmissionFileAuthorEditorPolicy.php index 5302392a115..f540c3c3e79 100644 --- a/classes/security/authorization/internal/SubmissionFileAuthorEditorPolicy.php +++ b/classes/security/authorization/internal/SubmissionFileAuthorEditorPolicy.php @@ -18,11 +18,10 @@ namespace PKP\security\authorization\internal; use APP\core\Application; -use PKP\db\DAORegistry; +use APP\facades\Repo; use PKP\security\authorization\AuthorizationPolicy; use PKP\security\Role; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submissionFile\SubmissionFile; class SubmissionFileAuthorEditorPolicy extends SubmissionFileBaseAccessPolicy @@ -50,8 +49,7 @@ public function effect() $userRoles = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES); foreach ($userRoles as $stageRoles) { if (in_array(Role::ROLE_ID_AUTHOR, $stageRoles)) { - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getById((int) $submissionFile->getData('assocId')); + $reviewAssignment = Repo::reviewAssignment()->get((int) $submissionFile->getData('assocId')); if ($reviewAssignment && $reviewAssignment->getReviewMethod() != ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN) { return AuthorizationPolicy::AUTHORIZATION_DENY; } diff --git a/classes/security/authorization/internal/SubmissionFileStageRequiredPolicy.php b/classes/security/authorization/internal/SubmissionFileStageRequiredPolicy.php index 7f7b080f514..4d1b60a34b9 100644 --- a/classes/security/authorization/internal/SubmissionFileStageRequiredPolicy.php +++ b/classes/security/authorization/internal/SubmissionFileStageRequiredPolicy.php @@ -17,11 +17,10 @@ namespace PKP\security\authorization\internal; use APP\core\Application; +use APP\facades\Repo; use PKP\core\PKPRequest; -use PKP\db\DAORegistry; use PKP\security\authorization\AuthorizationPolicy; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; class SubmissionFileStageRequiredPolicy extends SubmissionFileBaseAccessPolicy { @@ -73,8 +72,7 @@ public function effect() // Make sure the file is visible. Unless file is included in an open review. if (!$submissionFile->getViewable()) { if ($submissionFile->getData('assocType') === Application::ASSOC_TYPE_REVIEW_ASSIGNMENT) { - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getById((int) $submissionFile->getData('assocId')); + $reviewAssignment = Repo::reviewAssignment()->get((int) $submissionFile->getData('assocId')); if ($reviewAssignment->getReviewMethod() != ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN) { return AuthorizationPolicy::AUTHORIZATION_DENY; } diff --git a/classes/submission/Collector.php b/classes/submission/Collector.php index 2c8860350d7..f9075098d5a 100644 --- a/classes/submission/Collector.php +++ b/classes/submission/Collector.php @@ -78,6 +78,7 @@ abstract class Collector implements CollectorInterface public ?bool $awaitingReviews = null; public ?bool $reviewsSubmitted = null; public ?bool $revisionsRequested = null; + public ?bool $revisionsSubmitted = null; public function __construct(DAO $dao) { @@ -229,6 +230,24 @@ public function filterByAwaitingReviews(?bool $hasAwaitingReviews): AppCollector return $this; } + /** + * Filter results by submissions in the review stage where revisions are requested from the author + */ + public function filterByRevisionsRequested(?bool $revisionsRequested): AppCollector + { + $this->revisionsRequested = $revisionsRequested; + return $this; + } + + /** + * Limit results by submissions in the review stage where revisions are submitted by the author + * and editor response is required + */ + public function filterByRevisionsSubmitted(?bool $revisionsSubmitted): AppCollector + { + $this->revisionsSubmitted = $revisionsSubmitted; + return $this; + } /** * Limit results to submissions assigned to these users @@ -643,7 +662,7 @@ public static function getViewsCountBuilder(Collection $keyCollectorPair): Build */ protected function buildReviewStageQueries(Builder $q): Builder { - $reviewFilters = collect([$this->isReviewedBy, $this->reviewersNumber, $this->awaitingReviews, $this->reviewsSubmitted, $this->revisionsRequested])->filter(); + $reviewFilters = collect([$this->isReviewedBy, $this->reviewersNumber, $this->awaitingReviews, $this->reviewsSubmitted, $this->revisionsRequested, $this->revisionsSubmitted])->filter(); if ($reviewFilters->isEmpty()) { return $q; } @@ -667,9 +686,10 @@ protected function buildReviewStageQueries(Builder $q): Builder ->joinSub($currentReviewRound, 'agrr', fn(JoinClause $join) => $join->on('ra.submission_id', '=', 'agrr.submission_id') ) - ->whereIn('reviewer_id', (array) $this->isReviewedBy) - ->where('declined', 0) - ->where('cancelled', 0) + ->whereIn('ra.reviewer_id', (array) $this->isReviewedBy) + ->where('ra.declined', 0) + ->where('ra.cancelled', 0) + ->whereRaw('ra.round = agrr.current_round') ) ); @@ -741,7 +761,6 @@ protected function buildReviewStageQueries(Builder $q): Builder ) ->whereNotNull('ra.date_completed') ->whereRaw('ra.round = agrr.current_round') - // TODO include only those, which weren't confirmed by the editor? ) ); @@ -752,11 +771,23 @@ protected function buildReviewStageQueries(Builder $q): Builder ->joinSub($currentReviewRound, 'agrr', fn(JoinClause $join) => $join->on('rr.submission_id', '=', 'agrr.submission_id') ) - ->whereRaw('rr.round = agrr.curent_round') + ->whereRaw('rr.round = agrr.current_round') ->where('rr.status', ReviewRound::REVIEW_ROUND_STATUS_REVISIONS_REQUESTED) ) ); + $q->when($this->revisionsSubmitted !== null, fn(Builder $q) => $q + ->whereIn('s.submission_id', fn(Builder $q) => $q + ->select('rr.submission_id') + ->from('review_rounds AS rr') + ->joinSub($currentReviewRound, 'agrr', fn(JoinClause $join) => + $join->on('rr.submission_id', '=', 'agrr.submission_id') + ) + ->whereRaw('rr.round = agrr.current_round') + ->where('rr.status', ReviewRound::REVIEW_ROUND_STATUS_REVISIONS_SUBMITTED) + ) + ); + return $q; } diff --git a/classes/submission/DAO.php b/classes/submission/DAO.php index a2d887869a6..dcbbe3c5f51 100644 --- a/classes/submission/DAO.php +++ b/classes/submission/DAO.php @@ -31,7 +31,6 @@ use PKP\query\QueryDAO; use PKP\services\PKPSchemaService; use PKP\stageAssignment\StageAssignmentDAO; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\reviewRound\ReviewRoundDAO; /** @@ -272,8 +271,9 @@ public function deleteById(int $id) Repo::decision()->deleteBySubmissionId($id); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignmentDao->deleteBySubmissionId($id); + Repo::reviewAssignment()->deleteMany( + Repo::reviewAssignment()->getCollector()->filterBySubmissionIds([$id]) + ); $reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /** @var ReviewRoundDAO $reviewRoundDao */ $reviewRoundDao->deleteBySubmissionId($id); diff --git a/classes/submission/DashboardView.php b/classes/submission/DashboardView.php index 63dee9d2f5e..6e85aa5088d 100644 --- a/classes/submission/DashboardView.php +++ b/classes/submission/DashboardView.php @@ -35,6 +35,12 @@ class DashboardView const TYPE_SCHEDULED = 'scheduled'; const TYPE_PUBLISHED = 'published'; const TYPE_DECLINED = 'declined'; + const TYPE_REVISIONS_REQUESTED = 'revisions-requested'; + const TYPE_REVISIONS_SUBMITTED = 'revisions-submitted'; + const TYPE_INCOMPLETE_SUBMISSIONS = 'incomplete-submissions'; + const TYPE_REVIEWER_ASSIGNMENTS_ALL = 'reviewer-assignments-all'; + const TYPE_REVIEWER_ASSIGNMENTS_PENDING = 'reviewer-assignments-pending'; + const TYPE_REVIEWER_ASSIGNMENTS_FINISHED = 'reviewer-assignments-finished'; // The number of submissions in the view protected int $count; diff --git a/classes/submission/Repository.php b/classes/submission/Repository.php index a5fdca46a94..47d6db62d5a 100644 --- a/classes/submission/Repository.php +++ b/classes/submission/Repository.php @@ -39,7 +39,6 @@ use PKP\services\PKPSchemaService; use PKP\stageAssignment\StageAssignmentDAO; use PKP\submission\Collector as SubmissionCollector; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submissionFile\SubmissionFile; use PKP\user\User; use PKP\validation\ValidatorFactory; @@ -218,8 +217,13 @@ public function getWorkflowUrlByUserRoles(Submission $submission, ?int $userId = } // Send reviewers to review wizard - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getLastReviewRoundReviewAssignmentByReviewer($submission->getId(), $user->getId()); + $reviewAssignment = Repo::reviewAssignment()->getCollector() + ->filterBySubmissionIds([$submission->getId()]) + ->filterByReviewerIds([$user->getId()]) + ->filterByLastReviewRound(true) + ->getMany() + ->first(); + if ($reviewAssignment && !$reviewAssignment->getCancelled() && !$reviewAssignment->getDeclined()) { return $dispatcher->url( $request, @@ -934,7 +938,7 @@ public function getDashboardViews(Context $context, User $user): Collection return new DashboardView( $key, __('submission.dashboard.view.scheduled'), - [Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT], + [Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT, Role::ROLE_ID_AUTHOR], $canAccessUnassignedSubmission ? $collector : $collector->assignedTo([$user->getId()]), $canAccessUnassignedSubmission ? null : 'assigned', ['status' => [PKPSubmission::STATUS_SCHEDULED]] @@ -946,21 +950,60 @@ public function getDashboardViews(Context $context, User $user): Collection return new DashboardView( $key, __('submission.dashboard.view.published'), - [Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT], + [Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT, Role::ROLE_ID_AUTHOR], $canAccessUnassignedSubmission ? $collector : $collector->assignedTo([$user->getId()]), $canAccessUnassignedSubmission ? null : 'assigned', ['status' => [PKPSubmission::STATUS_PUBLISHED]] ); case DashboardView::TYPE_DECLINED: + $collector = Repo::submission()->getCollector() + ->filterByContextIds([$context->getId()]) + ->filterByStatus([PKPSubmission::STATUS_DECLINED]); return new DashboardView( $key, __('submission.dashboard.view.declined'), - [Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER], + [Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER, Role::ROLE_ID_AUTHOR], + $canAccessUnassignedSubmission ? $collector : $collector->assignedTo([$user->getId()]), + $canAccessUnassignedSubmission ? null : 'assigned', + ['status' => [PKPSubmission::STATUS_DECLINED]] + ); + case DashboardView::TYPE_REVISIONS_REQUESTED: + return new DashboardView( + $key, + __('submission.dashboard.view.revisionsRequested'), + [Role::ROLE_ID_AUTHOR], Repo::submission()->getCollector() + ->assignedTo([$user->getId()]) ->filterByContextIds([$context->getId()]) - ->filterByStatus([PKPSubmission::STATUS_DECLINED]), - null, - ['status' => [PKPSubmission::STATUS_DECLINED]] + ->filterByRevisionsRequested(true) + ->filterByStatus([PKPSubmission::STATUS_QUEUED]), + 'reviews', + ['revisionsRequested' => true] + ); + case DashboardView::TYPE_REVISIONS_SUBMITTED: + return new DashboardView( + $key, + __('submission.dashboard.view.revisionsSubmitted'), + [Role::ROLE_ID_AUTHOR], + Repo::submission()->getCollector() + ->assignedTo([$user->getId()]) + ->filterByContextIds([$context->getId()]) + ->filterByRevisionsSubmitted(true) + ->filterByStatus([PKPSubmission::STATUS_QUEUED]), + 'reviews', + ['revisionsSubmitted' => true] + ); + case DashboardView::TYPE_INCOMPLETE_SUBMISSIONS: + return new DashboardView( + $key, + __('submission.dashboard.view.incompleteSubmissions'), + [Role::ROLE_ID_AUTHOR], + Repo::submission()->getCollector() + ->assignedTo([$user->getId()]) + ->filterByContextIds([$context->getId()]) + ->filterByIncomplete(true), + 'assigned', + ['isIncomplete' => true] ); } }); diff --git a/classes/submission/action/EditorAction.php b/classes/submission/action/EditorAction.php index eb3651bb79c..3dd560e8107 100644 --- a/classes/submission/action/EditorAction.php +++ b/classes/submission/action/EditorAction.php @@ -38,7 +38,6 @@ use PKP\security\Validation; use PKP\submission\PKPSubmission; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\reviewRound\ReviewRound; use PKP\submission\reviewRound\ReviewRoundDAO; use PKP\user\User; @@ -72,32 +71,40 @@ public function __construct() */ public function addReviewer($request, $submission, $reviewerId, &$reviewRound, $reviewDueDate, $responseDueDate, $reviewMethod = null) { - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ $reviewer = Repo::user()->get($reviewerId); // Check to see if the requested reviewer is not already // assigned to review this submission. - $assigned = $reviewAssignmentDao->reviewerExists($reviewRound->getId(), $reviewerId); + $assigned = (bool) Repo::reviewAssignment()->getCollector() + ->filterByReviewRoundIds([$reviewRound->getId()]) + ->filterByReviewerIds([$reviewerId]) + ->getMany() + ->first(); // Only add the reviewer if he has not already // been assigned to review this submission. $stageId = $reviewRound->getStageId(); $round = $reviewRound->getRound(); + $newData = [ + 'submissionId' => $submission->getId(), + 'reviewerId' => $reviewerId, + 'dateAssigned' => Core::getCurrentDate(), + 'stageId' => $stageId, + 'round' => $round, + 'reviewRoundId' => $reviewRound->getId(), + ]; + if (isset($reviewMethod)) { + $newData['reviewMethod'] = $reviewMethod; + } + if (!$assigned && isset($reviewer) && !Hook::call('EditorAction::addReviewer', [&$submission, $reviewerId])) { - $reviewAssignment = $reviewAssignmentDao->newDataObject(); - $reviewAssignment->setSubmissionId($submission->getId()); - $reviewAssignment->setReviewerId($reviewerId); - $reviewAssignment->setDateAssigned(Core::getCurrentDate()); - $reviewAssignment->setStageId($stageId); - $reviewAssignment->setRound($round); - $reviewAssignment->setReviewRoundId($reviewRound->getId()); - if (isset($reviewMethod)) { - $reviewAssignment->setReviewMethod($reviewMethod); - } - $reviewAssignmentDao->insertObject($reviewAssignment); + $reviewAssignment = Repo::reviewAssignment()->newDataObject($newData); $this->setDueDates($request, $submission, $reviewAssignment, $reviewDueDate, $responseDueDate); + + Repo::reviewAssignment()->add($reviewAssignment); + // Add notification $notificationMgr = new NotificationManager(); $notificationMgr->createNotification( @@ -173,18 +180,10 @@ public function setDueDates($request, $submission, $reviewAssignment, $reviewDue } if ($reviewAssignment->getSubmissionId() == $submission->getId() && !Hook::call('EditorAction::setDueDates', [&$reviewAssignment, &$reviewer, &$reviewDueDate, &$responseDueDate])) { - // Set the review due date - $defaultNumWeeks = $context->getData('numWeeksPerReview'); - $reviewAssignment->setDateDue($reviewDueDate); - - // Set the response due date - $defaultNumWeeks = $context->getData('numWeeksPerResponse'); - $reviewAssignment->setDateResponseDue($responseDueDate); - - // update the assignment (with both the new dates) - $reviewAssignment->stampModified(); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, [ + 'dateDue' => $reviewDueDate, // Set the review due date + 'dateResponseDue' => $responseDueDate, // Set the response due date + ]); // N.B. Only logging Date Due if ($logEntry) { diff --git a/classes/submission/maps/Schema.php b/classes/submission/maps/Schema.php index a09b6e5d744..fd700b09fab 100644 --- a/classes/submission/maps/Schema.php +++ b/classes/submission/maps/Schema.php @@ -27,7 +27,6 @@ use PKP\stageAssignment\StageAssignmentDAO; use PKP\submission\Genre; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\reviewRound\ReviewRoundDAO; use PKP\submissionFile\SubmissionFile; use PKP\userGroup\UserGroup; @@ -221,11 +220,12 @@ protected function mapByProperties(array $props, Submission $submission): array $output = []; if (in_array('publications', $props)) { - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $currentUserReviewAssignment = $reviewAssignmentDao->getLastReviewRoundReviewAssignmentByReviewer( - $submission->getId(), - $this->request->getUser()->getId() - ); + $currentUserReviewAssignment = Repo::reviewAssignment()->getCollector() + ->filterBySubmissionIds([$submission->getId()]) + ->filterByReviewerIds([$this->request->getUser()->getId()]) + ->filterByLastReviewRound(true) + ->getMany() + ->first(); $anonymize = $currentUserReviewAssignment && $currentUserReviewAssignment->getReviewMethod() === ReviewAssignment::SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS; } @@ -279,8 +279,7 @@ protected function mapByProperties(array $props, Submission $submission): array */ protected function getPropertyReviewAssignments(Submission $submission): array { - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignments = $reviewAssignmentDao->getBySubmissionId($submission->getId()); + $reviewAssignments = Repo::reviewAssignment()->getCollector()->filterBySubmissionIds([$submission->getId()])->getMany(); $reviews = []; foreach ($reviewAssignments as $reviewAssignment) { diff --git a/classes/submission/reviewAssignment/Collector.php b/classes/submission/reviewAssignment/Collector.php new file mode 100644 index 00000000000..f345e967405 --- /dev/null +++ b/classes/submission/reviewAssignment/Collector.php @@ -0,0 +1,267 @@ +dao = $dao; + } + + /** @copydoc DAO::getCount() */ + public function getCount(): int + { + return $this->dao->getCount($this); + } + + /** + * @copydoc DAO::getIds() + * @return Collection + */ + public function getIds(): Collection + { + return $this->dao->getIds($this); + } + + /** + * @copydoc DAO::getMany() + * @return LazyCollection + */ + public function getMany(): LazyCollection + { + return $this->dao->getMany($this); + } + + /** + * Filter review assignments by one or more contexts + */ + public function filterByContextIds(?array $contextIds): self + { + $this->contextIds = $contextIds; + return $this; + } + + /** + * Filter review assignments by associated submissions + */ + public function filterBySubmissionIds(?array $submissionIds): self + { + $this->submissionIds = $submissionIds; + return $this; + } + + /** + * Filter by active assignments only: + * is not completed or declines or cancelled and associated submission is in the review stage + * + */ + public function filterByIsIncomplete(?bool $isIncomplete): self + { + $this->isIncomplete = $isIncomplete; + return $this; + } + + /** + * Filter by overdue assignments + */ + public function filterByIsOverdue(?bool $isOverdue): self + { + $this->isOverdue = $isOverdue; + return $this; + } + + /** + * Filter by review round ids + */ + public function filterByReviewRoundIds(?array $reviewRoundIds): self + { + $this->reviewRoundIds = $reviewRoundIds; + return $this; + } + + public function filterByReviewerIds(?array $reviewerIds): self + { + $this->reviewerIds = $reviewerIds; + return $this; + } + + public function filterByLastReviewRound(bool $isLastReviewRound): self + { + $this->isLastReviewRound = $isLastReviewRound; + return $this; + } + + /** + * Filter by review method, one or more of the ReviewAssignment::SUBMISSION_REVIEW_METHOD_ constants + */ + public function filterByReviewMethods(?array $reviewMethods): self + { + $this->reviewMethods = $reviewMethods; + return $this; + } + + /** + * Filter by WORKFLOW_STAGE_ID_EXTERNAL_REVIEW or WORKFLOW_STAGE_ID_INTERNAL_REVIEW + */ + public function filterByStageId(?int $stageId): self + { + $this->stageId = $stageId; + return $this; + } + + public function filterByReviewFormIds(?array $reviewFormIds): self + { + $this->reviewFormIds = $reviewFormIds; + return $this; + } + + /** + * Limit the number of objects retrieved + */ + public function limit(?int $count): self + { + $this->count = $count; + return $this; + } + + /** + * Offset the number of objects retrieved, for example to + * retrieve the second page of contents + */ + public function offset(?int $offset): self + { + $this->offset = $offset; + return $this; + } + + /** + * @copydoc CollectorInterface::getQueryBuilder() + */ + public function getQueryBuilder(): Builder + { + $q = DB::table($this->dao->table . ' as ra') + // Aggregate the latest review round number for the given assignment + ->leftJoinSub( + DB::table('review_rounds', 'rr') + ->select('rr.submission_id') + ->selectRaw('MAX(rr.round) as current_round') + ->selectRaw('MAX(rr.stage_id) as current_stage') + ->groupBy('rr.submission_id'), + 'agrr', + fn(JoinClause $join) => $join->on('ra.submission_id', '=', 'agrr.submission_id')) + ->select(['ra.*']); + + $q->when($this->contextIds !== null, fn(Builder $q) => + $q->whereIn('ra.submission_id', fn (Builder $q) => $q + ->select('s.submission_id') + ->from('submissions as s') + ->whereIn('s.context_id', $this->contextIds) + ) + ); + + $q->when($this->submissionIds !== null, fn(Builder $q) => + $q->whereIn('ra.submission_id', $this->submissionIds) + ); + + $q->when($this->isLastReviewRound || $this->isIncomplete, function(Builder $q) {$q + ->whereRaw('ra.round = agrr.current_round') // assignments from the last review round only + ->whereRaw('ra.stage_id = agrr.stage_id') // assignments for the current review stage only (for OMP) + ->when($this->isIncomplete, fn(Builder $q) => $q + ->where(fn(Builder $q) => $q + ->whereNotNull('ra.date_notified') + ->whereNull('ra.date_completed') + ->where('ra.declined', '<>', 1) + ->where('ra.cancelled', '<>', 1) + ->whereIn('ra.submission_id', fn(Builder $q) => $q + ->select('s.submission_id') + ->from('submissions AS s') + ->where('s.stage_id', 'ra.stage_id') + ) + ) + ); + }); + + $q->when($this->isOverdue, fn(Builder $q) => $q + ->where(fn(Builder $q) => $q + ->whereNull('ra.date_completed') + ->where('raod.declined', '<>', 1) + ->where('raod.cancelled', '<>', 1) + ->where(fn (Builder $q) => + $q->where('raod.date_due', '<', Core::getCurrentDate(strtotime('tomorrow'))) + ->whereNull('raod.date_completed') + ) + ->orWhere(fn (Builder $q) => + $q->where('raod.date_response_due', '<', Core::getCurrentDate(strtotime('tomorrow'))) + ->whereNull('raod.date_confirmed') + ) + ) + ); + + $q->when($this->reviewRoundIds !== null, fn(Builder $q) => + $q->whereIn('ra.review_round_id', $this->reviewRoundIds) + ); + + $q->when($this->reviewerIds !== null, fn(Builder $q) => + $q->whereIn('ra.reviewer_id', $this->reviewerIds) + ); + + $q->when($this->reviewMethods !== null, fn(Builder $q) => + $q->whereIn('ra.review_method', $this->reviewMethods) + ); + + $q->when($this->stageId !== null, fn(Builder $q) => + $q->where('ra.stage_id', $this->stageId) + ); + + $q->when($this->reviewFormIds !== null, fn(Builder $q) => + $q->whereIn('ra.review_form_id', $this->reviewFormIds) + ); + + $q->when($this->count !== null, fn() => + $q->limit($this->count) + ); + + $q->when($this->offset !== null, fn() => + $q->offset($this->offset) + ); + + return $q; + } +} diff --git a/classes/submission/reviewAssignment/DAO.php b/classes/submission/reviewAssignment/DAO.php new file mode 100644 index 00000000000..efe809b2770 --- /dev/null +++ b/classes/submission/reviewAssignment/DAO.php @@ -0,0 +1,160 @@ + + */ +class DAO extends EntityDAO +{ + /** @copydoc EntityDAO::$schema */ + public $schema = \PKP\services\PKPSchemaService::SCHEMA_REVIEW_ASSIGNMENT; + + /** @copydoc EntityDAO::$table */ + public $table = 'review_assignments'; + + /** @copydoc EntityDAO::$primaryKeyColumn */ + public $primaryKeyColumn = 'review_id'; + + /** @copydoc EntityDAO::$primaryTableColumns */ + public $primaryTableColumns = [ + 'id' => 'review_id', + 'submissionId' => 'submission_id', + 'reviewerId' => 'reviewer_id', + 'competingInterests' => 'competing_interests', + 'recommendation' => 'recommendation', + 'dateAssigned' => 'date_assigned', + 'dateNotified' => 'date_notified', + 'dateConfirmed' => 'date_confirmed', + 'dateCompleted' => 'date_completed', + 'dateAcknowledged' => 'date_acknowledged', + 'dateDue' => 'date_due', + 'dateResponseDue' => 'date_response_due', + 'lastModified' => 'last_modified', + 'reminderWasAutomatic' => 'reminder_was_automatic', + 'declined' => 'declined', + 'cancelled' => 'cancelled', + 'dateRated' => 'date_rated', + 'dateReminded' => 'date_reminded', + 'quality' => 'quality', + 'reviewRoundId' => 'review_round_id', + 'stageId' => 'stage_id', + 'reviewMethod' => 'review_method', + 'round' => 'round', + 'step' => 'step', + 'reviewFormId' => 'review_form_id', + 'considered' => 'considered', + 'requestResent' => 'request_resent', + ]; + + /** + * Instantiate a new DataObject + */ + public function newDataObject(): ReviewAssignment + { + return app(ReviewAssignment::class); + } + + /** + * Check if a review assignment exists + */ + public function exists(int $id): bool + { + return DB::table($this->table) + ->where($this->primaryKeyColumn, '=', $id) + ->exists(); + } + + /** + * Get a review assignment + */ + public function get(int $id): ?ReviewAssignment + { + $row = DB::table($this->table) + ->where($this->primaryKeyColumn, $id) + ->first(); + return $row ? $this->fromRow($row) : null; + } + + /** + * Get the number of review assignments matching the configured query + */ + public function getCount(Collector $query): int + { + return $query + ->getQueryBuilder() + ->get('ra.' . $this->primaryKeyColumn) + ->count(); + } + + /** + * Get a list of ids matching the configured query + * + * @return Collection + */ + public function getIds(Collector $query): Collection + { + return $query + ->getQueryBuilder() + ->pluck('ra.' . $this->primaryKeyColumn); + } + + /** + * Get a collection of review assignments matching the configured query + * + * @return LazyCollection + */ + public function getMany(Collector $query): LazyCollection + { + $rows = $query + ->getQueryBuilder() + ->get(); + + return LazyCollection::make(function() use ($rows) { + foreach ($rows as $row) { + yield $row->review_id => $this->fromRow($row); + } + }); + } + + /** + * @copydoc EntityDAO::insert() + */ + public function insert(ReviewAssignment $reviewAssignment): int + { + return parent::_insert($reviewAssignment); + } + + /** + * @copydoc EntityDAO::update() + */ + public function update(ReviewAssignment $reviewAssignment) + { + parent::_update($reviewAssignment); + } + + /** + * @copydoc EntityDAO::delete() + */ + public function delete(ReviewAssignment $reviewAssignment) + { + parent::_delete($reviewAssignment); + } +} diff --git a/classes/submission/reviewAssignment/Repository.php b/classes/submission/reviewAssignment/Repository.php new file mode 100644 index 00000000000..ed68eff2633 --- /dev/null +++ b/classes/submission/reviewAssignment/Repository.php @@ -0,0 +1,256 @@ + $schemaService */ + protected PKPSchemaService $schemaService; + + public function __construct(DAO $dao, Request $request, PKPSchemaService $schemaService) + { + $this->dao = $dao; + $this->request = $request; + $this->schemaService = $schemaService; + } + + /** @copydoc DAO::newDataObject() */ + public function newDataObject(array $params = []): ReviewAssignment + { + $object = $this->dao->newDataObject(); + if (!empty($params)) { + $object->setAllData($params); + } + return $object; + } + + /** @copydoc DAO::get() */ + public function get(int $id): ?ReviewAssignment + { + return $this->dao->get($id); + } + + /** @copydoc DAO::exists() */ + public function exists(int $id): bool + { + return $this->dao->exists($id); + } + + /** @copydoc DAO::getCollector() */ + public function getCollector(): Collector + { + return app(Collector::class); + } + + /** + * Get an instance of the map class for mapping + * announcements to their schema + */ + public function getSchemaMap(): maps\Schema + { + return app('maps')->withExtensions($this->schemaMap); + } + + /** + * Validate properties for a category + * + * Perform validation checks on data used to add or edit a review assignment. + * + * @param array $props A key/value array with the new data to validate + * @param array $allowedLocales The context's supported locales + * @param string $primaryLocale The context's primary locale + * + * @return array A key/value array with validation errors. Empty if no errors + */ + public function validate(?ReviewAssignment $object, array $props, Context $context): array + { + $primaryLocale = $context->getData('primaryLocale'); + $allowedLocales = $context->getData('supportedFormLocales'); + + $validator = ValidatorFactory::make( + $props, + $this->schemaService->getValidationRules($this->dao->schema, $allowedLocales), + [] + ); + + // Check required fields + ValidatorFactory::required( + $validator, + $object, + $this->schemaService->getRequiredProps($this->dao->schema), + $this->schemaService->getMultilingualProps($this->dao->schema), + $allowedLocales, + $primaryLocale + ); + + // Check if submission exists + if (isset($props['submissionId'])) { + $validator->after(function($validator) use ($props) { + if (!$validator->errors()->get('submissionId')) { + $submission = Repo::submission()->get($props['submissionId']); + if (!$submission) { + $validator->errors()->add('submissionId', __('api.reviews.assignments.invalidSubmission')); + } + } + }); + } + + // Check if reviewer exists + if (isset($props['reviewerId'])) { + $validator->after(function($validator) use ($props, $context) { + if (!$validator->errors()->get('reviewerId')) { + $reviewer = Repo::user()->get($props['reviewerId']); + if (!$reviewer) { + $validator->errors()->add('reviewerId', __('api.reviews.assignments.invalidReviewer')); + } + $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */ + $isReviewer = $roleDao->userHasRole($context->getId(), $reviewer->getId(), Role::ROLE_ID_REVIEWER); + if (!$isReviewer) { + $validator->errors()->add('reviewerId', __('api.reviews.assignments.invalidReviewer')); + } + } + }); + } + + // Check for input from disallowed locales + ValidatorFactory::allowedLocales($validator, $this->schemaService->getMultilingualProps($this->dao->schema), $allowedLocales); + + $errors = []; + + if ($validator->fails()) { + $errors = $this->schemaService->formatValidationErrors($validator->errors()); + } + + Hook::call('Category::validate', [&$errors, $object, $props, $allowedLocales, $primaryLocale]); + + return $errors; + } + + /** + * Add a new review assignment + */ + public function add(ReviewAssignment $reviewAssignment): int + { + $id = $this->dao->insert($reviewAssignment); + $reviewAssignment->stampModified(); + Hook::call('ReviewAssignment::add', [$reviewAssignment]); + $this->updateReviewRoundStatus($reviewAssignment); + + return $id; + } + + /** + * Edit a review assignment + */ + public function edit(ReviewAssignment $reviewAssignment, array $params) + { + $newReviewAssignment = clone $reviewAssignment; + $newReviewAssignment->setAllData(array_merge($newReviewAssignment->_data, $params)); + $newReviewAssignment->stampModified(); + + Hook::call('ReviewAssignment::edit', [$newReviewAssignment, $reviewAssignment, $params]); + + $this->dao->update($newReviewAssignment); + $this->updateReviewRoundStatus($newReviewAssignment); + } + + /** + * Delete a review assignment + */ + public function delete(ReviewAssignment $reviewAssignment) + { + Hook::call('ReviewAssignment::delete::before', [$reviewAssignment]); + + $reviewFormResponseDao = DAORegistry::getDAO('ReviewFormResponseDAO'); /** @var ReviewFormResponseDAO $reviewFormResponseDao */ + $reviewFormResponseDao->deleteByReviewId($reviewAssignment->getId()); + + $reviewFilesDao = DAORegistry::getDAO('ReviewFilesDAO'); /** @var ReviewFilesDAO $reviewFilesDao */ + $reviewFilesDao->revokeByReviewId($reviewAssignment->getId()); + + $notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */ + $notificationDao->deleteByAssoc(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT, $reviewAssignment->getId()); + + $this->dao->delete($reviewAssignment); + + $this->updateReviewRoundStatus($reviewAssignment); + + Hook::call('ReviewAssignment::delete', [$reviewAssignment]); + } + + /** + * Delete a collection of announcements + */ + public function deleteMany(Collector $collector) + { + foreach ($collector->getMany() as $reviewAssignment) { + $this->delete($reviewAssignment); + } + } + + /** + * Return the review methods translation keys. + */ + public function getReviewMethodsTranslationKeys(): array + { + 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', + ]; + } + + /** + * Update the status of the review round an assignment is attached to. This + * should be fired whenever a reviewer assignment is modified. + */ + protected function updateReviewRoundStatus(ReviewAssignment $reviewAssignment): bool + { + $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) { + $reviewRoundDao->updateStatus($reviewRound); + return true; + } + + return false; + } +} diff --git a/classes/submission/reviewAssignment/ReviewAssignment.php b/classes/submission/reviewAssignment/ReviewAssignment.php index 9d4f08ba242..86600ae9334 100644 --- a/classes/submission/reviewAssignment/ReviewAssignment.php +++ b/classes/submission/reviewAssignment/ReviewAssignment.php @@ -526,7 +526,7 @@ public function setCancelled($cancelled) */ public function getRequestResent() { - return $this->getData('request_resent'); + return $this->getData('requestResent'); } /** @@ -536,7 +536,7 @@ public function getRequestResent() */ public function setRequestResent($resent) { - $this->setData('request_resent', $resent); + $this->setData('requestResent', $resent); } /** diff --git a/classes/submission/reviewAssignment/maps/Schema.php b/classes/submission/reviewAssignment/maps/Schema.php new file mode 100644 index 00000000000..876ab3a6b13 --- /dev/null +++ b/classes/submission/reviewAssignment/maps/Schema.php @@ -0,0 +1,95 @@ +mapByProperties($this->getProps(), $item); + } + + /** + * Summarize an announcement + * + * Includes properties with the apiSummary flag in the review assignment schema. + */ + public function summarize(ReviewAssignment $item): array + { + return $this->mapByProperties($this->getSummaryProps(), $item); + } + + /** + * Map a collection of Review Assignments + * + * @see self::map + */ + public function mapMany(Enumerable $collection): Enumerable + { + $this->collection = $collection; + return $collection->map(function ($item) { + return $this->map($item); + }); + } + + /** + * Summarize a collection of Review Assignments + * + * @see self::summarize + */ + public function summarizeMany(Enumerable $collection): Enumerable + { + $this->collection = $collection; + return $collection->map(function ($item) { + return $this->summarize($item); + }); + } + + /** + * Map schema properties of an Announcement to an assoc array + */ + protected function mapByProperties(array $props, ReviewAssignment $item): array + { + $output = []; + foreach ($props as $prop) { + switch ($prop) { + case '_href': + $output[$prop] = $this->getApiUrl('_submissions/reviewAssignments/' . $item->getId()); + break; + default: + $output[$prop] = $item->getData($prop); + break; + } + } + + $output = $this->schemaService->addMissingMultilingualValues($this->schema, $output, $this->context->getSupportedFormLocales()); + + ksort($output); + + return $this->withExtensions($output, $item); + } +} diff --git a/classes/submission/reviewRound/ReviewRound.php b/classes/submission/reviewRound/ReviewRound.php index 4f81ca5b371..36939a7a4b5 100644 --- a/classes/submission/reviewRound/ReviewRound.php +++ b/classes/submission/reviewRound/ReviewRound.php @@ -26,7 +26,6 @@ use PKP\db\DAORegistry; use PKP\stageAssignment\StageAssignmentDAO; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; class ReviewRound extends \PKP\core\DataObject { @@ -232,8 +231,10 @@ public function determineStatus() $anyOverdueReview = false; $anyIncompletedReview = false; $anyUnreadReview = false; - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignments = $reviewAssignmentDao->getByReviewRoundId($this->getId()); + $reviewAssignments = Repo::reviewAssignment()->getCollector() + ->filterByReviewerIds([$this->getId()]) + ->getMany(); + foreach ($reviewAssignments as $reviewAssignment) { assert($reviewAssignment instanceof ReviewAssignment); @@ -263,7 +264,7 @@ public function determineStatus() // 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)) { + if ($reviewAssignments->isEmpty()) { return self::REVIEW_ROUND_STATUS_PENDING_REVIEWERS; } elseif ($anyOverdueReview) { return self::REVIEW_ROUND_STATUS_REVIEWS_OVERDUE; diff --git a/classes/submission/reviewer/ReviewerAction.php b/classes/submission/reviewer/ReviewerAction.php index d635f9c6dc8..e984cf8b94d 100644 --- a/classes/submission/reviewer/ReviewerAction.php +++ b/classes/submission/reviewer/ReviewerAction.php @@ -38,7 +38,6 @@ use PKP\stageAssignment\StageAssignmentDAO; use PKP\submission\PKPSubmission; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use Symfony\Component\Mailer\Exception\TransportException; class ReviewerAction @@ -58,7 +57,6 @@ public function confirmReview( bool $decline, ?string $emailText = null ): void { - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ $reviewer = Repo::user()->get($reviewAssignment->getReviewerId()); if (!isset($reviewer)) { return; @@ -91,12 +89,12 @@ public function confirmReview( } } - $reviewAssignment->setDateReminded(null); - $reviewAssignment->setReminderWasAutomatic(0); - $reviewAssignment->setDeclined($decline); - $reviewAssignment->setDateConfirmed(Core::getCurrentDate()); - $reviewAssignment->stampModified(); - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, [ + 'dateReminded' => null, + 'reminderWasAutomatic' => 0, + 'declined' => $decline, + 'dateConfirmed' => Core::getCurrentDate(), + ]); // Add log $eventLog = Repo::eventLog()->newDataObject([ diff --git a/classes/submission/reviewer/form/PKPReviewerReviewStep3Form.php b/classes/submission/reviewer/form/PKPReviewerReviewStep3Form.php index 3b28537c416..45ae3b3cdbf 100644 --- a/classes/submission/reviewer/form/PKPReviewerReviewStep3Form.php +++ b/classes/submission/reviewer/form/PKPReviewerReviewStep3Form.php @@ -41,7 +41,6 @@ use PKP\security\Validation; use PKP\stageAssignment\StageAssignmentDAO; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\SubmissionComment; use PKP\submission\SubmissionCommentDAO; @@ -164,16 +163,11 @@ public function execute(...$functionParams) // Set review to next step. $this->updateReviewStepAndSaveSubmission($this->getReviewAssignment()); - // Mark the review assignment as completed. - $reviewAssignment->setDateCompleted(Core::getCurrentDate()); - $reviewAssignment->stampModified(); - - // assign the recommendation to the review assignment, if there was one. - $reviewAssignment->setRecommendation((int) $this->getData('recommendation')); - // Persist the updated review assignment. - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, [ + 'dateCompleted' => Core::getCurrentDate(), // Mark the review assignment as completed. + 'recommendation' => (int) $this->getData('recommendation'), // assign the recommendation to the review assignment, if there was one. + ]); $stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */ $stageAssignments = $stageAssignmentDao->getBySubmissionAndStageId($submission->getId(), $submission->getStageId()); @@ -275,20 +269,14 @@ public function execute(...$functionParams) public function saveForLater() { $reviewAssignment = $this->getReviewAssignment(); - $notificationMgr = new NotificationManager(); // Save the answers to the review form $this->saveReviewForm($reviewAssignment); - // Mark the review assignment as modified. - $reviewAssignment->stampModified(); - - // save the recommendation to the review assignment - $reviewAssignment->setRecommendation((int) $this->getData('recommendation')); - // Persist the updated review assignment. - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, [ + 'recommendation' => (int) $this->getData('recommendation'), // save the recommendation to the review assignment + ]); return true; } diff --git a/classes/submission/reviewer/form/ReviewerReviewForm.php b/classes/submission/reviewer/form/ReviewerReviewForm.php index 1d2fbbac55c..61d308ddfc4 100644 --- a/classes/submission/reviewer/form/ReviewerReviewForm.php +++ b/classes/submission/reviewer/form/ReviewerReviewForm.php @@ -15,13 +15,12 @@ namespace PKP\submission\reviewer\form; +use APP\facades\Repo; use APP\submission\Submission; use APP\template\TemplateManager; use PKP\core\PKPRequest; -use PKP\db\DAORegistry; use PKP\form\Form; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; class ReviewerReviewForm extends Form { @@ -118,9 +117,7 @@ public function updateReviewStepAndSaveSubmission(ReviewAssignment $reviewAssign } // Save the reviewer submission. - /** @var ReviewAssignmentDAO */ - $reviewAssignmentDAO = DAORegistry::getDAO('ReviewAssignmentDAO'); - $reviewAssignmentDAO->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, $reviewAssignment->getAllData()); } } diff --git a/classes/submissionFile/DAO.php b/classes/submissionFile/DAO.php index 706f68fcc99..347de0cef28 100644 --- a/classes/submissionFile/DAO.php +++ b/classes/submissionFile/DAO.php @@ -19,6 +19,7 @@ namespace PKP\submissionFile; use APP\core\Application; +use APP\facades\Repo; use Exception; use Illuminate\Database\Query\Builder; use Illuminate\Support\Collection; @@ -28,7 +29,6 @@ use PKP\db\DAORegistry; use PKP\plugins\PKPPubIdPluginDAO; use PKP\services\PKPSchemaService; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\ReviewFilesDAO; use PKP\submission\reviewRound\ReviewRound; use PKP\submission\reviewRound\ReviewRoundDAO; @@ -450,8 +450,7 @@ protected function getReviewRound(SubmissionFile $submissionFile): ?ReviewRound } if ($submissionFile->getData('assocType') === Application::ASSOC_TYPE_REVIEW_ASSIGNMENT) { - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getById($submissionFile->getData('assocId')); + $reviewAssignment = Repo::reviewAssignment()->get($submissionFile->getData('assocId')); $reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /** @var ReviewRoundDAO $reviewRoundDao */ return $reviewRoundDao->getById($reviewAssignment->getReviewRoundId()); } diff --git a/classes/task/ReviewReminder.php b/classes/task/ReviewReminder.php index 165927807a1..e5523526b25 100644 --- a/classes/task/ReviewReminder.php +++ b/classes/task/ReviewReminder.php @@ -22,7 +22,6 @@ use PKP\context\Context; use PKP\core\Core; use PKP\core\PKPApplication; -use PKP\db\DAORegistry; use PKP\invitation\invitations\ReviewerAccessInvite; use PKP\log\event\PKPSubmissionEventLogEntry; use PKP\mail\mailables\ReviewRemindAuto; @@ -30,7 +29,6 @@ use PKP\scheduledTask\ScheduledTask; use PKP\submission\PKPSubmission; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; class ReviewReminder extends ScheduledTask { @@ -51,8 +49,6 @@ public function sendReminder( Context $context, ReviewRemindAuto|ReviewResponseRemindAuto $mailable ): void { - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewId = $reviewAssignment->getId(); $reviewer = Repo::user()->get($reviewAssignment->getReviewerId()); if (!isset($reviewer)) { @@ -68,9 +64,6 @@ public function sendReminder( $mailable->setData($primaryLocale); - $application = Application::get(); - $request = $application->getRequest(); - $dispatcher = $application->getDispatcher(); $reviewerAccessKeysEnabled = $context->getData('reviewerAccessKeysEnabled'); if ($reviewerAccessKeysEnabled) { // Give one-click access if enabled $reviewInvitation = new ReviewerAccessInvite( @@ -90,9 +83,10 @@ public function sendReminder( Mail::send($mailable); - $reviewAssignment->setDateReminded(Core::getCurrentDate()); - $reviewAssignment->setReminderWasAutomatic(1); - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, [ + 'dateReminded' => Core::getCurrentDate(), + 'reminderWasAutomatic' => 1 + ]); $eventLog = Repo::eventLog()->newDataObject([ 'assocType' => PKPApplication::ASSOC_TYPE_SUBMISSION, @@ -116,10 +110,9 @@ public function executeActions() $submission = null; $context = null; - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ $contextDao = Application::getContextDAO(); - $incompleteAssignments = $reviewAssignmentDao->getIncompleteReviewAssignments(); + $incompleteAssignments = Repo::reviewAssignment()->getCollector()->filterByIsIncomplete(true)->getMany(); $inviteReminderDays = $submitReminderDays = null; foreach ($incompleteAssignments as $reviewAssignment) { // Avoid review assignments that a reminder exists for. diff --git a/classes/user/Repository.php b/classes/user/Repository.php index 9e18b1d11b5..4ef7352c10b 100644 --- a/classes/user/Repository.php +++ b/classes/user/Repository.php @@ -29,7 +29,6 @@ use PKP\security\RoleDAO; use PKP\session\SessionDAO; use PKP\stageAssignment\StageAssignmentDAO; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\SubmissionCommentDAO; class Repository @@ -314,10 +313,9 @@ public function mergeUsers(int $oldUserId, int $newUserId) Repo::decision()->dao->reassignDecisions($oldUserId, $newUserId); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - foreach ($reviewAssignmentDao->getByUserId($oldUserId) as $reviewAssignment) { - $reviewAssignment->setReviewerId($newUserId); - $reviewAssignmentDao->updateObject($reviewAssignment); + $reviewAssignments = Repo::reviewAssignment()->getCollector()->filterByReviewerIds([$oldUserId])->getMany(); + foreach ($reviewAssignments as $reviewAssignment) { + Repo::reviewAssignment()->edit($reviewAssignment, ['reviewerId' => $newUserId]); } $submissionEmailLogDao = DAORegistry::getDAO('SubmissionEmailLogDAO'); /** @var SubmissionEmailLogDAO $submissionEmailLogDao */ diff --git a/controllers/grid/eventLog/EventLogGridCellProvider.php b/controllers/grid/eventLog/EventLogGridCellProvider.php index 90268edf5e9..6e41afe58fd 100644 --- a/controllers/grid/eventLog/EventLogGridCellProvider.php +++ b/controllers/grid/eventLog/EventLogGridCellProvider.php @@ -20,11 +20,9 @@ use APP\facades\Repo; use PKP\controllers\grid\DataObjectGridCellProvider; use PKP\controllers\grid\GridColumn; -use PKP\db\DAORegistry; use PKP\log\event\EventLogEntry; use PKP\log\event\PKPSubmissionEventLogEntry; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submissionFile\SubmissionFile; class EventLogGridCellProvider extends DataObjectGridCellProvider @@ -73,7 +71,6 @@ public function getTemplateVarsFromRowColumn($row, $column) // Anonymize reviewer details where necessary if ($this->_isCurrentUserAssignedAuthor) { - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ // Maybe anonymize reviewer log entries $reviewerLogTypes = [ @@ -84,7 +81,7 @@ public function getTemplateVarsFromRowColumn($row, $column) if (in_array($element->getEventType(), $reviewerLogTypes)) { $userName = __('editor.review.anonymousReviewer'); if ($reviewAssignmentId = $element->getData('reviewAssignmentId')) { - $reviewAssignment = $reviewAssignmentDao->getById($reviewAssignmentId); + $reviewAssignment = Repo::reviewAssignment()->get($reviewAssignmentId); if ($reviewAssignment && $reviewAssignment->getReviewMethod() === ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN) { $userName = $element->getUserFullName(); } @@ -98,7 +95,7 @@ public function getTemplateVarsFromRowColumn($row, $column) assert($element->getData('fileId') && $element->getData('submissionId') && $submissionFileId); $submissionFile = Repo::submissionFile()->get($submissionFileId); if ($submissionFile && $submissionFile->getData('assocType') === Application::ASSOC_TYPE_REVIEW_ASSIGNMENT) { - $reviewAssignment = $reviewAssignmentDao->getById($submissionFile->getData('assocId')); + $reviewAssignment = Repo::reviewAssignment()->get($submissionFile->getData('assocId')); if (!$reviewAssignment || in_array($reviewAssignment->getReviewMethod(), [ReviewAssignment::SUBMISSION_REVIEW_METHOD_ANONYMOUS, ReviewAssignment::SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS])) { $userName = __('editor.review.anonymousReviewer'); } diff --git a/controllers/grid/eventLog/EventLogGridRow.php b/controllers/grid/eventLog/EventLogGridRow.php index ddf84ec82c8..34661b4c35e 100644 --- a/controllers/grid/eventLog/EventLogGridRow.php +++ b/controllers/grid/eventLog/EventLogGridRow.php @@ -22,12 +22,10 @@ use PKP\controllers\api\file\linkAction\DownloadFileLinkAction; use PKP\controllers\grid\eventLog\linkAction\EmailLinkAction; use PKP\controllers\grid\GridRow; -use PKP\db\DAORegistry; use PKP\log\EmailLogEntry; use PKP\log\event\EventLogEntry; use PKP\log\event\SubmissionFileEventLogEntry; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submissionFile\SubmissionFile; class EventLogGridRow extends GridRow @@ -83,8 +81,7 @@ public function initialize($request, $template = null) $anonymousAuthor = false; $maybeAnonymousAuthor = $this->_isCurrentUserAssignedAuthor && $submissionFile->getData('fileStage') === SubmissionFile::SUBMISSION_FILE_REVIEW_ATTACHMENT; if ($maybeAnonymousAuthor && $submissionFile->getData('assocType') === Application::ASSOC_TYPE_REVIEW_ASSIGNMENT) { - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getById($submissionFile->getData('assocId')); + $reviewAssignment = Repo::reviewAssignment()->get($submissionFile->getData('assocId')); if ($reviewAssignment && in_array($reviewAssignment->getReviewMethod(), [ReviewAssignment::SUBMISSION_REVIEW_METHOD_ANONYMOUS, ReviewAssignment::SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS])) { $anonymousAuthor = true; } diff --git a/controllers/grid/files/attachment/ReviewerReviewAttachmentGridDataProvider.php b/controllers/grid/files/attachment/ReviewerReviewAttachmentGridDataProvider.php index eb26549d7a5..e33a7a28cb8 100644 --- a/controllers/grid/files/attachment/ReviewerReviewAttachmentGridDataProvider.php +++ b/controllers/grid/files/attachment/ReviewerReviewAttachmentGridDataProvider.php @@ -19,10 +19,8 @@ use APP\facades\Repo; use PKP\controllers\api\file\linkAction\AddFileLinkAction; use PKP\controllers\grid\files\SubmissionFilesGridDataProvider; -use PKP\db\DAORegistry; use PKP\security\authorization\internal\ReviewAssignmentRequiredPolicy; use PKP\security\authorization\ReviewStageAccessPolicy; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submissionFile\SubmissionFile; class ReviewerReviewAttachmentGridDataProvider extends SubmissionFilesGridDataProvider @@ -111,9 +109,7 @@ public function loadData($filter = []) public function getAddFileAction($request) { $submission = $this->getSubmission(); - - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getById($this->_getReviewId()); + $reviewAssignment = Repo::reviewAssignment()->get($this->_getReviewId()); return new AddFileLinkAction( $request, diff --git a/controllers/grid/notifications/NotificationsGridCellProvider.php b/controllers/grid/notifications/NotificationsGridCellProvider.php index b7a41ffae24..a46697e65b8 100644 --- a/controllers/grid/notifications/NotificationsGridCellProvider.php +++ b/controllers/grid/notifications/NotificationsGridCellProvider.php @@ -30,7 +30,6 @@ use PKP\linkAction\request\AjaxAction; use PKP\payment\QueuedPaymentDAO; use PKP\query\QueryDAO; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\reviewRound\ReviewRoundDAO; class NotificationsGridCellProvider extends GridCellProvider @@ -142,8 +141,7 @@ public function _getTitle($notification) $fileId = $notification->getAssocId(); break; case Application::ASSOC_TYPE_REVIEW_ASSIGNMENT: - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getById($notification->getAssocId()); + $reviewAssignment = Repo::reviewAssignment()->get($notification->getAssocId()); assert($reviewAssignment instanceof \PKP\submission\reviewAssignment\ReviewAssignment); $submissionId = $reviewAssignment->getSubmissionId(); break; diff --git a/controllers/grid/queries/form/QueryForm.php b/controllers/grid/queries/form/QueryForm.php index 68f5cf13a19..adf0517e6f2 100644 --- a/controllers/grid/queries/form/QueryForm.php +++ b/controllers/grid/queries/form/QueryForm.php @@ -34,7 +34,6 @@ use PKP\security\Role; use PKP\stageAssignment\StageAssignmentDAO; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; class QueryForm extends Form { @@ -310,8 +309,7 @@ public function fetch($request, $template = null, $display = false, $actionArgs if ($query->getStageId() == WORKFLOW_STAGE_ID_EXTERNAL_REVIEW || $query->getStageId() == WORKFLOW_STAGE_ID_INTERNAL_REVIEW) { // Get all review assignments for current submission - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignments = $reviewAssignmentDao->getBySubmissionId($submission->getId()); + $reviewAssignments = Repo::reviewAssignment()->getCollector()->filterBySubmissionIds([$submission->getId()])->getMany(); // if current user is editor/journal manager/site admin and not have author role , add all reviewers if (array_intersect($assignedRoles, [Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR]) || (empty($assignedRoles) && ($user->hasRole([Role::ROLE_ID_MANAGER], $context->getId()) || $user->hasRole([Role::ROLE_ID_SITE_ADMIN], PKPApplication::CONTEXT_SITE)))) { @@ -431,7 +429,6 @@ public function validate($callHooks = true) $submissionId = $query->getAssocId(); $stageId = $query->getStageId(); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ $stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */ // get the selected participants @@ -449,9 +446,14 @@ public function validate($callHooks = true) if ($stageId == WORKFLOW_STAGE_ID_EXTERNAL_REVIEW || $stageId == WORKFLOW_STAGE_ID_INTERNAL_REVIEW) { // validate the anonymity // get participant review assignments - $reviewAssignments = $reviewAssignmentDao->getBySubmissionReviewer($submissionId, $participantId, $stageId); + $reviewAssignments = Repo::reviewAssignment()->getCollector() + ->filterBySubmissionIds([$submissionId]) + ->filterByReviewerIds([$participantId]) + ->filterByStageId($stageId) + ->getMany(); + // if participant has no role in this stage and is not a reviewer - if (empty($assignedRoles) && empty($reviewAssignments)) { + if (empty($assignedRoles) && $reviewAssignments->isEmpty()) { // if participant is current user and the user has admin or manager role, ignore participant if (($participantId == $user->getId()) && ($user->hasRole([Role::ROLE_ID_SITE_ADMIN], PKPApplication::CONTEXT_SITE) || $user->hasRole([Role::ROLE_ID_MANAGER], $context->getId()))) { continue; diff --git a/controllers/grid/settings/reviewForms/ReviewFormGridHandler.php b/controllers/grid/settings/reviewForms/ReviewFormGridHandler.php index cef4a0d2857..0154fd93132 100644 --- a/controllers/grid/settings/reviewForms/ReviewFormGridHandler.php +++ b/controllers/grid/settings/reviewForms/ReviewFormGridHandler.php @@ -17,6 +17,7 @@ namespace PKP\controllers\grid\settings\reviewForms; use APP\core\Application; +use APP\facades\Repo; use APP\notification\NotificationManager; use APP\template\TemplateManager; use PKP\controllers\grid\feature\OrderGridItemsFeature; @@ -35,7 +36,6 @@ use PKP\security\authorization\PolicySet; use PKP\security\authorization\RoleBasedHandlerOperationPolicy; use PKP\security\Role; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; class ReviewFormGridHandler extends GridHandler { @@ -502,12 +502,10 @@ public function deleteReviewForm($args, $request) $reviewForm = $reviewFormDao->getById($reviewFormId, Application::getContextAssocType(), $context->getId()); if ($request->checkCSRF() && isset($reviewForm) && $reviewForm->getCompleteCount() == 0 && $reviewForm->getIncompleteCount() == 0) { - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignments = $reviewAssignmentDao->getByReviewFormId($reviewFormId); + $reviewAssignments = Repo::reviewAssignment()->getCollector()->filterByReviewFormIds([$reviewFormId])->getMany(); foreach ($reviewAssignments as $reviewAssignment) { - $reviewAssignment->setReviewFormId(null); - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, ['reviewFormId' => null]); } $reviewFormDao->deleteById($reviewFormId); diff --git a/controllers/grid/users/reviewer/AuthorReviewerGridHandler.php b/controllers/grid/users/reviewer/AuthorReviewerGridHandler.php index 56253e6c6aa..ace0de69594 100644 --- a/controllers/grid/users/reviewer/AuthorReviewerGridHandler.php +++ b/controllers/grid/users/reviewer/AuthorReviewerGridHandler.php @@ -17,6 +17,7 @@ namespace PKP\controllers\grid\users\reviewer; use APP\core\Application; +use APP\facades\Repo; use APP\template\TemplateManager; use PKP\controllers\grid\GridColumn; use PKP\controllers\grid\GridHandler; @@ -31,7 +32,6 @@ use PKP\security\authorization\WorkflowStageAccessPolicy; use PKP\security\Role; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\SubmissionCommentDAO; class AuthorReviewerGridHandler extends PKPReviewerGridHandler @@ -158,8 +158,13 @@ protected function loadData($request, $filter) // Get the existing review assignments for this submission // Only show open requests that have been accepted $reviewRound = $this->getReviewRound(); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - return $reviewAssignmentDao->getOpenReviewsByReviewRoundId($reviewRound->getId()); + return Repo::reviewAssignment()->getCollector() + ->filterByReviewRoundIds([$reviewRound->getId()]) + ->filterByReviewMethods([ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN]) + ->getMany() + ->keyBy(fn(ReviewAssignment $reviewAssignment, int $key) => $reviewAssignment->getId()) + ->sortKeys() + ->toArray(); } /** diff --git a/controllers/grid/users/reviewer/form/AdvancedSearchReviewerForm.php b/controllers/grid/users/reviewer/form/AdvancedSearchReviewerForm.php index c6a32d86d9f..d41d042d798 100644 --- a/controllers/grid/users/reviewer/form/AdvancedSearchReviewerForm.php +++ b/controllers/grid/users/reviewer/form/AdvancedSearchReviewerForm.php @@ -33,7 +33,6 @@ use PKP\mail\mailables\ReviewRequestSubsequent; use PKP\security\Role; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\reviewRound\ReviewRound; use PKP\submission\reviewRound\ReviewRoundDAO; @@ -112,12 +111,14 @@ public function fetch($request, $template = null, $display = false) $this->setReviewerFormAction($advancedSearchAction); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - // get reviewer IDs already assign to this submission and this round - $reviewAssignments = $reviewAssignmentDao->getBySubmissionId($this->getSubmissionId(), $this->getReviewRound()->getId()); + $reviewAssignments = Repo::reviewAssignment()->getCollector() + ->filterBySubmissionIds([$this->getSubmissionId()]) + ->filterByReviewRoundIds([$this->getReviewRound()->getId()]) + ->getMany(); + $currentlyAssigned = []; - if (!empty($reviewAssignments)) { + if ($reviewAssignments->isNotEmpty()) { foreach ($reviewAssignments as $reviewAssignment) { $currentlyAssigned[] = (int) $reviewAssignment->getReviewerId(); } @@ -185,7 +186,7 @@ public function fetch($request, $template = null, $display = false) $lastReviewRound = $reviewRoundDao->getReviewRound($this->getSubmissionId(), $this->getReviewRound()->getStageId(), $previousRound); if ($lastReviewRound) { - $lastReviewAssignments = $reviewAssignmentDao->getByReviewRoundId($lastReviewRound->getId()); + $lastReviewAssignments = Repo::reviewAssignment()->getCollector()->filterByReviewerIds([$lastReviewRound->getId()])->getMany(); foreach ($lastReviewAssignments as $reviewAssignment) { if (in_array($reviewAssignment->getStatus(), [ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_THANKED, ReviewAssignment::REVIEW_ASSIGNMENT_STATUS_COMPLETE])) { $lastRoundReviewerIds[] = (int) $reviewAssignment->getReviewerId(); diff --git a/controllers/grid/users/reviewer/form/EditReviewForm.php b/controllers/grid/users/reviewer/form/EditReviewForm.php index b1669299f43..fccf65df483 100644 --- a/controllers/grid/users/reviewer/form/EditReviewForm.php +++ b/controllers/grid/users/reviewer/form/EditReviewForm.php @@ -32,7 +32,6 @@ use PKP\notification\PKPNotification; use PKP\reviewForm\ReviewFormDAO; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\ReviewFilesDAO; use PKP\submission\reviewRound\ReviewRound; use PKP\submission\reviewRound\ReviewRoundDAO; @@ -90,7 +89,6 @@ public function initData() public function fetch($request, $template = null, $display = false) { $templateMgr = TemplateManager::getManager($request); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ $context = $request->getContext(); if (!$this->_reviewAssignment->getDateCompleted()) { @@ -112,7 +110,7 @@ public function fetch($request, $template = null, $display = false) 'submissionId' => $this->_reviewAssignment->getSubmissionId(), 'reviewAssignmentId' => $this->_reviewAssignment->getId(), 'reviewMethod' => $this->_reviewAssignment->getReviewMethod(), - 'reviewMethods' => $reviewAssignmentDao->getReviewMethodsTranslationKeys(), + 'reviewMethods' => Repo::reviewAssignment()->getReviewMethodsTranslationKeys(), ]); return parent::fetch($request, $template, $display); } @@ -163,8 +161,11 @@ public function execute(...$functionArgs) } } - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getReviewAssignment($this->_reviewRound->getId(), $this->_reviewAssignment->getReviewerId()); + $reviewAssignment = Repo::reviewAssignment()->getCollector() + ->filterByReviewRoundIds([$this->_reviewRound->getId()]) + ->filterByReviewerIds([$this->_reviewAssignment->getReviewerId()]) + ->getMany() + ->first(); // Send notification to reviewer if details have changed. if (strtotime($reviewAssignment->getDateDue()) != strtotime($this->getData('reviewDueDate')) || strtotime($reviewAssignment->getDateResponseDue()) != strtotime($this->getData('responseDueDate')) || $reviewAssignment->getReviewMethod() != $this->getData('reviewMethod')) { @@ -217,19 +218,21 @@ public function execute(...$functionArgs) } } - $reviewAssignment->setDateDue($this->getData('reviewDueDate')); - $reviewAssignment->setDateResponseDue($this->getData('responseDueDate')); - $reviewAssignment->setReviewMethod($this->getData('reviewMethod')); + $reviewNewParams = [ + 'dateDue' => $this->getData('reviewDueDate'), + 'dateResponseDue' => $this->getData('responseDueDate'), + 'reviewMethod' => $this->getData('reviewMethod'), + ]; if (!$reviewAssignment->getDateCompleted()) { // Ensure that the review form ID is valid, if specified $reviewFormId = (int) $this->getData('reviewFormId'); $reviewFormDao = DAORegistry::getDAO('ReviewFormDAO'); /** @var ReviewFormDAO $reviewFormDao */ $reviewForm = $reviewFormDao->getById($reviewFormId, Application::getContextAssocType(), $context->getId()); - $reviewAssignment->setReviewFormId($reviewForm ? $reviewFormId : null); + $reviewNewParams['reviewFormId'] = $reviewForm ? $reviewFormId : null; } - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, $reviewNewParams); parent::execute(...$functionArgs); } } diff --git a/controllers/grid/users/reviewer/form/ReinstateReviewerForm.php b/controllers/grid/users/reviewer/form/ReinstateReviewerForm.php index bce3e09f842..3e81fe5fcf6 100644 --- a/controllers/grid/users/reviewer/form/ReinstateReviewerForm.php +++ b/controllers/grid/users/reviewer/form/ReinstateReviewerForm.php @@ -22,7 +22,6 @@ use PKP\context\Context; use PKP\core\Core; use PKP\core\PKPApplication; -use PKP\db\DAORegistry; use PKP\log\event\PKPSubmissionEventLogEntry; use PKP\mail\Mailable; use PKP\mail\mailables\ReviewerReinstate; @@ -30,7 +29,6 @@ use PKP\plugins\Hook; use PKP\security\Validation; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\reviewRound\ReviewRound; class ReinstateReviewerForm extends ReviewerNotifyActionForm @@ -71,15 +69,15 @@ public function execute(...$functionArgs) $reviewAssignment = $this->getReviewAssignment(); // Reinstate the review assignment. - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ if (isset($reviewAssignment) && $reviewAssignment->getSubmissionId() == $submission->getId() && !Hook::call('EditorAction::reinstateReview', [&$submission, $reviewAssignment])) { $reviewer = Repo::user()->get($reviewAssignment->getReviewerId()); if (!isset($reviewer)) { return false; } - $reviewAssignment->setCancelled(false); - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, [ + 'cancelled' => false, + ]); // Stamp the modification date $submission->stampModified(); diff --git a/controllers/grid/users/reviewer/form/ResendRequestReviewerForm.php b/controllers/grid/users/reviewer/form/ResendRequestReviewerForm.php index df3fa703fcf..e837af8f593 100644 --- a/controllers/grid/users/reviewer/form/ResendRequestReviewerForm.php +++ b/controllers/grid/users/reviewer/form/ResendRequestReviewerForm.php @@ -23,14 +23,12 @@ use PKP\context\Context; use PKP\core\Core; use PKP\core\PKPApplication; -use PKP\db\DAORegistry; use PKP\log\event\PKPSubmissionEventLogEntry; use PKP\mail\Mailable; use PKP\mail\mailables\ReviewerResendRequest; use PKP\notification\PKPNotification; use PKP\security\Validation; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\reviewRound\ReviewRound; class ResendRequestReviewerForm extends ReviewerNotifyActionForm @@ -74,7 +72,6 @@ public function execute(...$functionArgs) $request = Application::get()->getRequest(); /** @var Request $request */ $submission = $this->getSubmission(); /** @var Submission $submission */ $reviewAssignment = $this->getReviewAssignment(); /** @var ReviewAssignment $reviewAssignment */ - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ if (isset($reviewAssignment) && $reviewAssignment->getSubmissionId() == $submission->getId()) { $reviewer = Repo::user()->get($reviewAssignment->getReviewerId()); @@ -83,10 +80,11 @@ public function execute(...$functionArgs) } // $reviewAssignment->setCancelled(false); - $reviewAssignment->setDeclined(false); - $reviewAssignment->setRequestResent(true); - $reviewAssignment->setDateConfirmed(null); - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, [ + 'declined' => false, + 'requestResent' => true, + 'dateConfirmed' => null, + ]); // Stamp the modification date $submission->stampLastActivity(); diff --git a/controllers/grid/users/reviewer/form/ReviewReminderForm.php b/controllers/grid/users/reviewer/form/ReviewReminderForm.php index 3f0361046fe..8ed411b6b55 100644 --- a/controllers/grid/users/reviewer/form/ReviewReminderForm.php +++ b/controllers/grid/users/reviewer/form/ReviewReminderForm.php @@ -23,7 +23,6 @@ use Illuminate\Support\Facades\Mail; use PKP\core\Core; use PKP\core\PKPApplication; -use PKP\db\DAORegistry; use PKP\facades\Locale; use PKP\form\Form; use PKP\log\event\PKPSubmissionEventLogEntry; @@ -32,7 +31,6 @@ use PKP\notification\PKPNotification; use PKP\security\Validation; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use Symfony\Component\Mailer\Exception\TransportException; class ReviewReminderForm extends Form @@ -169,10 +167,9 @@ public function execute(...$functionArgs) ]); Repo::eventLog()->add($eventLog); - $reviewAssignment->setDateReminded(Core::getCurrentDate()); - $reviewAssignment->stampModified(); - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, [ + 'dateReminded' => Core::getCurrentDate(), + ]); } catch (TransportException $e) { $notificationMgr = new NotificationManager(); $notificationMgr->createTrivialNotification( diff --git a/controllers/grid/users/reviewer/form/ReviewerForm.php b/controllers/grid/users/reviewer/form/ReviewerForm.php index c7dfdc567c2..28179853488 100644 --- a/controllers/grid/users/reviewer/form/ReviewerForm.php +++ b/controllers/grid/users/reviewer/form/ReviewerForm.php @@ -39,7 +39,6 @@ use PKP\security\RoleDAO; use PKP\submission\action\EditorAction; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\ReviewFilesDAO; use PKP\submission\reviewRound\ReviewRound; use PKP\submissionFile\SubmissionFile; @@ -238,8 +237,7 @@ public function fetch($request, $template = null, $display = false) $context = $request->getContext(); // Get the review method options. - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewMethods = $reviewAssignmentDao->getReviewMethodsTranslationKeys(); + $reviewMethods = Repo::reviewAssignment()->getReviewMethodsTranslationKeys(); $templateMgr = TemplateManager::getManager($request); $templateMgr->assign('reviewMethods', $reviewMethods); @@ -339,18 +337,21 @@ public function execute(...$functionParams) $editorAction->addReviewer($request, $submission, $reviewerId, $currentReviewRound, $reviewDueDate, $responseDueDate, $reviewMethod); // Get the reviewAssignment object now that it has been added. - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->getReviewAssignment($currentReviewRound->getId(), $reviewerId); - $reviewAssignment->setDateNotified(Core::getCurrentDate()); - $reviewAssignment->stampModified(); + $reviewAssignment = Repo::reviewAssignment()->getCollector() + ->filterByReviewRoundIds([$currentReviewRound->getId()]) + ->filterByReviewerIds([$reviewerId]) + ->getMany() + ->first(); // Ensure that the review form ID is valid, if specified $reviewFormId = (int) $this->getData('reviewFormId'); $reviewFormDao = DAORegistry::getDAO('ReviewFormDAO'); /** @var ReviewFormDAO $reviewFormDao */ $reviewForm = $reviewFormDao->getById($reviewFormId, Application::getContextAssocType(), $context->getId()); - $reviewAssignment->setReviewFormId($reviewForm ? $reviewFormId : null); - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, [ + 'dateNotified' => Core::getCurrentDate(), + 'reviewFormId' => $reviewForm ? $reviewFormId : null + ]); $fileStages = [$stageId == WORKFLOW_STAGE_ID_INTERNAL_REVIEW ? SubmissionFile::SUBMISSION_FILE_INTERNAL_REVIEW_FILE : SubmissionFile::SUBMISSION_FILE_REVIEW_FILE]; // Grant access for this review to all selected files. @@ -429,8 +430,11 @@ public function getAdvancedSearchAction($request) public function _isValidReviewer($context, $submission, $reviewRound, $reviewerId) { // Ensure the user isn't already assigned to the current submission - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignments = $reviewAssignmentDao->getBySubmissionId($submission->getId(), $reviewRound->getId()); + $reviewAssignments = Repo::reviewAssignment()->getCollector() + ->filterBySubmissionIds([$submission->getId()]) + ->filterByReviewRoundIds([$reviewRound->getId()]) + ->getMany(); + foreach ($reviewAssignments as $reviewAssignment) { if ($reviewerId == $reviewAssignment->getReviewerId()) { return false; @@ -447,12 +451,15 @@ public function _isValidReviewer($context, $submission, $reviewRound, $reviewerI */ protected function getMailable(): ReviewRequest { - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment = $reviewAssignmentDao->newDataObject(); /** @var ReviewAssignment $reviewAssignment */ - $reviewAssignment->setSubmissionId($this->getSubmissionId()); $submission = $this->getSubmission(); $request = Application::get()->getRequest(); - $mailable = new ReviewRequest($request->getContext(), $submission, $reviewAssignment); + $mailable = new ReviewRequest( + $request->getContext(), + $submission, + Repo::reviewAssignment()->newDataObject([ + 'submissionId' => $this->getSubmissionId(), + ]) + ); $mailable->sender($request->getUser()); $mailable->addData([ 'messageToReviewer' => __('reviewer.step1.requestBoilerplate'), diff --git a/controllers/grid/users/reviewer/form/ThankReviewerForm.php b/controllers/grid/users/reviewer/form/ThankReviewerForm.php index 4f4200555fc..0f6fc0bac20 100644 --- a/controllers/grid/users/reviewer/form/ThankReviewerForm.php +++ b/controllers/grid/users/reviewer/form/ThankReviewerForm.php @@ -30,7 +30,6 @@ use PKP\notification\PKPNotification; use PKP\plugins\Hook; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use Symfony\Component\Mailer\Exception\TransportException; class ThankReviewerForm extends Form @@ -149,17 +148,13 @@ public function execute(...$functionArgs) } // update the ReviewAssignment with the acknowledged date - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignment->setDateAcknowledged(Core::getCurrentDate()); - $reviewAssignment->stampModified(); + $newData = ['dateAcknowledged' => Core::getCurrentDate()]; if (!in_array($reviewAssignment->getConsidered(), [ReviewAssignment::REVIEW_ASSIGNMENT_CONSIDERED, ReviewAssignment::REVIEW_ASSIGNMENT_RECONSIDERED])) { - $reviewAssignment->setConsidered( - $reviewAssignment->getConsidered() === ReviewAssignment::REVIEW_ASSIGNMENT_NEW - ? ReviewAssignment::REVIEW_ASSIGNMENT_CONSIDERED - : ReviewAssignment::REVIEW_ASSIGNMENT_RECONSIDERED - ); + $newData['considered'] = $reviewAssignment->getConsidered() === ReviewAssignment::REVIEW_ASSIGNMENT_NEW + ? ReviewAssignment::REVIEW_ASSIGNMENT_CONSIDERED + : ReviewAssignment::REVIEW_ASSIGNMENT_RECONSIDERED; } - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, $newData); parent::execute(...$functionArgs); } diff --git a/controllers/grid/users/reviewer/form/UnassignReviewerForm.php b/controllers/grid/users/reviewer/form/UnassignReviewerForm.php index 661ed93ec61..34ec5a59dfe 100644 --- a/controllers/grid/users/reviewer/form/UnassignReviewerForm.php +++ b/controllers/grid/users/reviewer/form/UnassignReviewerForm.php @@ -31,7 +31,6 @@ use PKP\plugins\Hook; use PKP\security\Validation; use PKP\submission\reviewAssignment\ReviewAssignment; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; class UnassignReviewerForm extends ReviewerNotifyActionForm { @@ -71,8 +70,6 @@ public function execute(...$functionArgs) $reviewAssignment = $this->getReviewAssignment(); // Delete or cancel the review assignment. - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - if (isset($reviewAssignment) && $reviewAssignment->getSubmissionId() == $submission->getId() && !Hook::call('EditorAction::clearReview', [&$submission, $reviewAssignment])) { $reviewer = Repo::user()->get($reviewAssignment->getReviewerId(), true); if (!isset($reviewer)) { @@ -80,11 +77,10 @@ public function execute(...$functionArgs) } if ($reviewAssignment->getDateConfirmed()) { // The review has been confirmed but not completed. Flag it as cancelled. - $reviewAssignment->setCancelled(true); - $reviewAssignmentDao->updateObject($reviewAssignment); + Repo::reviewAssignment()->edit($reviewAssignment, ['cancelled' => true]); } else { // The review had not been confirmed yet. Delete the assignment. - $reviewAssignmentDao->deleteById($reviewAssignment->getId()); + Repo::reviewAssignment()->delete($reviewAssignment); } // Stamp the modification date diff --git a/controllers/grid/users/stageParticipant/form/AddParticipantForm.php b/controllers/grid/users/stageParticipant/form/AddParticipantForm.php index 0be66f1d630..f46db82a3c4 100644 --- a/controllers/grid/users/stageParticipant/form/AddParticipantForm.php +++ b/controllers/grid/users/stageParticipant/form/AddParticipantForm.php @@ -24,7 +24,7 @@ use PKP\security\Role; use PKP\stageAssignment\StageAssignment; use PKP\stageAssignment\StageAssignmentDAO; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; +use PKP\submission\reviewAssignment\ReviewAssignment; use PKP\userGroup\relationships\UserGroupStage; use PKP\userGroup\UserGroup; @@ -202,11 +202,14 @@ public function fetch($request, $template = null, $display = false) \PKP\submission\reviewAssignment\ReviewAssignment::SUBMISSION_REVIEW_METHOD_ANONYMOUS, \PKP\submission\reviewAssignment\ReviewAssignment::SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS ]; - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - $reviewAssignments = $reviewAssignmentDao->getBySubmissionId($this->getSubmission()->getId()); - $anonymousReviews = array_filter($reviewAssignments, function ($reviewAssignment) use ($anonymousReviewMethods) { - return in_array($reviewAssignment->getReviewMethod(), $anonymousReviewMethods) && !$reviewAssignment->getDeclined(); - }); + + $anonymousReviews = Repo::reviewAssignment()->getCollector() + ->filterBySubmissionIds([$this->getSubmission()->getId()]) + ->getMany() + ->filter(fn(ReviewAssignment $reviewAssignment) => + in_array($reviewAssignment->getReviewMethod(), $anonymousReviewMethods) && !$reviewAssignment->getDeclined()) + ->toArray(); + $anonymousReviewerIds = array_map(function ($reviewAssignment) { return $reviewAssignment->getReviewerId(); }, $anonymousReviews); diff --git a/controllers/tab/authorDashboard/AuthorDashboardReviewRoundTabHandler.php b/controllers/tab/authorDashboard/AuthorDashboardReviewRoundTabHandler.php index b855f019008..6aa1e4c79f3 100644 --- a/controllers/tab/authorDashboard/AuthorDashboardReviewRoundTabHandler.php +++ b/controllers/tab/authorDashboard/AuthorDashboardReviewRoundTabHandler.php @@ -18,6 +18,7 @@ use APP\core\Application; use APP\core\Request; +use APP\facades\Repo; use APP\notification\Notification; use APP\pages\authorDashboard\AuthorDashboardHandler; use APP\template\TemplateManager; @@ -29,7 +30,7 @@ use PKP\security\authorization\internal\ReviewRoundRequiredPolicy; use PKP\security\authorization\internal\WorkflowStageRequiredPolicy; use PKP\security\Role; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; +use PKP\submission\reviewAssignment\ReviewAssignment; class AuthorDashboardReviewRoundTabHandler extends AuthorDashboardHandler { @@ -101,8 +102,12 @@ public function fetchReviewRoundInfo($args, $request) ]); // If open reviews exist, show the reviewers grid - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */ - if ($reviewAssignmentDao->getOpenReviewsByReviewRoundId($reviewRound->getId())) { + $reviewAssignments = Repo::reviewAssignment()->getCollector() + ->filterByReviewRoundIds([$reviewRound->getId()]) + ->filterByReviewMethods([ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN]) + ->getMany(); + + if ($reviewAssignments->isNotEmpty()) { $templateMgr->assign('showReviewerGrid', true); } diff --git a/controllers/wizard/fileUpload/form/PKPSubmissionFilesUploadBaseForm.php b/controllers/wizard/fileUpload/form/PKPSubmissionFilesUploadBaseForm.php index 13835ee755a..4e6fbe3b7ca 100644 --- a/controllers/wizard/fileUpload/form/PKPSubmissionFilesUploadBaseForm.php +++ b/controllers/wizard/fileUpload/form/PKPSubmissionFilesUploadBaseForm.php @@ -27,7 +27,6 @@ use PKP\linkAction\request\ConfirmationModal; use PKP\security\Role; use PKP\stageAssignment\StageAssignmentDAO; -use PKP\submission\reviewAssignment\ReviewAssignmentDAO; use PKP\submission\reviewRound\ReviewRound; use PKP\submission\reviewRound\ReviewRoundDAO; use PKP\submissionFile\SubmissionFile; @@ -88,10 +87,7 @@ public function __construct( $this->_reviewRound = & $reviewRound; } elseif ($assocType == Application::ASSOC_TYPE_REVIEW_ASSIGNMENT && !$reviewRound) { // Get the review assignment object. - /** @var ReviewAssignmentDAO */ - $reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); - /** @var \PKP\submission\reviewAssignment\ReviewAssignment */ - $reviewAssignment = $reviewAssignmentDao->getById((int) $assocId); + $reviewAssignment = Repo::reviewAssignment()->get((int) $assocId); if ($reviewAssignment->getDateCompleted()) { fatalError('Review already completed!'); } diff --git a/locale/en/api.po b/locale/en/api.po index 502c1cb2e15..f9117e97bec 100644 --- a/locale/en/api.po +++ b/locale/en/api.po @@ -307,3 +307,9 @@ msgstr "Unable to delete failed job from failed list." msgid "api.jobs.200.failedJobDeleteSucceed" msgstr "Failed job deleted successfully from failed list." + +msgid "api.reviews.assignments.invalidSubmission" +msgstr "The submission for this review assignment could not be found." + +msgid "api.reviews.assignments.invalidReviewer" +msgstr "The reviewer for the assignment could not be found" diff --git a/schemas/reviewAssignment.json b/schemas/reviewAssignment.json new file mode 100644 index 00000000000..371f1b5aa00 --- /dev/null +++ b/schemas/reviewAssignment.json @@ -0,0 +1,191 @@ +{ + "title": "Review Assignment", + "description": "An assignment to the reviewer to review a submission.", + "required": [ + "submissionId", + "reviewerId", + "reviewRoundId", + "stageId" + ], + "properties": { + "_href": { + "type": "string", + "description": "A URL to this object in the REST API.", + "readOnly": true, + "apiSummary": true + }, + "cancelled": { + "type": "boolean", + "description": "Indicates whether review assignment was cancelled", + "apiSummary": true + }, + "comments": { + "type": "string", + "description": "Comments from a reviewer", + "apiSummary": true + }, + "competingInterests": { + "type": "string", + "description": "Reviewer's competing interests", + "apiSummary": true + }, + "considered": { + "type": "boolean", + "description": "Whether reviewer considers a review assignment request", + "apiSummary": true + }, + "dateAcknowledged": { + "type": "string", + "description": "Date editor was familiarized with the review", + "validation": [ + "date:Y-m-d H:i:s" + ], + "apiSummary": true + }, + "dateAssigned": { + "type": "string", + "description": "Date the reviewer was assigned to the submission", + "validation": [ + "date:Y-m-d H:i:s" + ], + "apiSummary": true + }, + "dateConfirmed": { + "type": "string", + "description": "Date the reviewer confirmed the assignment to the submission", + "validation": [ + "date:Y-m-d H:i:s" + ], + "apiSummary": true + }, + "dateCompleted": { + "type": "string", + "description": "Date the assignment was completed", + "validation": [ + "date:Y-m-d H:i:s" + ], + "apiSummary": true + }, + "dateDue": { + "type": "string", + "description": "Date the review assignment should be completed", + "validation": [ + "date:Y-m-d H:i:s" + ], + "apiSummary": true + }, + "dateNotified": { + "type": "string", + "description": "Date the reviewer was notified about the assignment", + "validation": [ + "date:Y-m-d H:i:s" + ], + "apiSummary": true + }, + "dateRated": { + "type": "string", + "description": "Date the submission was rated by the reviewer", + "validation": [ + "date:Y-m-d H:i:s" + ], + "apiSummary": true + }, + "dateReminded": { + "type": "string", + "description": "Date the reviewer was reminded about the assignment", + "validation": [ + "date:Y-m-d H:i:s" + ], + "apiSummary": true + }, + "dateResponseDue": { + "type": "string", + "description": "Date until which the response from reviewer is expected", + "validation": [ + "date:Y-m-d H:i:s" + ], + "apiSummary": true + }, + "declined": { + "type": "boolean", + "description": "Whether review assignment was declined by tge reviewer", + "apiSummary": true + }, + "lastModified": { + "type": "string", + "description": "Date of the most recent assignment update", + "validation": [ + "date:Y-m-d H:i:s" + ], + "apiSummary": true, + "writeDisabledInApi": true + }, + "quality": { + "type": "integer", + "description": "Assessment of the review quality", + "apiSummary": true + }, + "recommendation": { + "type": "integer", + "description": "Reviewer's recommendation", + "apiSummary": true + }, + "requestResent": { + "type": "boolean", + "description": "Whether the review request was resent to the reviewer", + "apiSummary": true + }, + "reminderWasAutomatic": { + "type": "boolean", + "description": "Whether the reminder for the reviewer about the assignment was send automatically", + "apiSummary": true + }, + "reviewerFullName": { + "type": "string", + "description": "The full name of the reviewer", + "readOnly": true, + "apiSummary": true + }, + "reviewerId": { + "type": "integer", + "description": "reviewer's unique ID", + "apiSummary": true + }, + "reviewFormId": { + "type": "integer", + "description": "The ID of the custom review form", + "apiSummary": true + }, + "reviewMethod": { + "type": "integer", + "description": "The method used in the review. One of the SUBMISSION_REVIEW_METHOD_ constants", + "apiSummary": true + }, + "reviewRoundId": { + "type": "integer", + "description": "The ID of the review round", + "apiSummary": true + }, + "round": { + "type": "integer", + "description": "The round of the review stage", + "apiSummary": true + }, + "stageId": { + "type": "integer", + "description": "The ID of the review stage: external or internal review", + "apiSummary": true + }, + "step": { + "type": "integer", + "description": "The current step of the reviewer form", + "apiSummary": true + }, + "submissionId": { + "type": "integer", + "description": "The ID of the submission associated with the assignment", + "readOnly": true, + "apiSummary": true + } + } +}