From 72db9ed3265baf93b6c308227a9f45ad60d7d356 Mon Sep 17 00:00:00 2001 From: Vitalii Bezsheiko Date: Thu, 16 Jan 2025 21:19:05 +0200 Subject: [PATCH] pkp/pkp-lib#10480 Record only latest recommendation & fix canCurrentUserChangeMetadata --- classes/submission/maps/Schema.php | 102 ++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 24 deletions(-) diff --git a/classes/submission/maps/Schema.php b/classes/submission/maps/Schema.php index f17545958af..3f14a1aa556 100644 --- a/classes/submission/maps/Schema.php +++ b/classes/submission/maps/Schema.php @@ -422,10 +422,7 @@ protected function mapByProperties(array $props, Submission $submission, bool|Co break; case 'canCurrentUserChangeMetadata': // Identify if current user can change metadata. Consider roles in the active stage. - $output[$prop] = !empty(array_intersect( - PKPApplication::getWorkflowTypeRoles()[PKPApplication::WORKFLOW_TYPE_EDITORIAL], - $stages[$submission->getData('stageId')]['currentUserAssignedRoles'] - )); + $output[$prop] = $this->canChangeMetadata($this->stageAssignments, $submission); break; case 'editorAssigned': $output[$prop] = $this->getPropertyStageAssignments($this->stageAssignments); @@ -487,6 +484,43 @@ protected function mapByProperties(array $props, Submission $submission, bool|Co return $output; } + /** + * Determine whether current user is able to change metadata + */ + protected function canChangeMetadata(Enumerable $stageAssignments, Submission $submission): bool + { + $currentUser = Application::get()->getRequest()->getUser(); + $isAssigned = false; + $canChangeMetadata = false; + + // Check if stage assignment is associated with the current user and edit metadata flag + foreach ($stageAssignments as $stageAssignment) { + if ($stageAssignment->userId === $currentUser->getId()) { + $isAssigned = true; + if ($stageAssignment->canChangeMetadata) { + $canChangeMetadata = true; + break; + } + } + } + + if ($canChangeMetadata) { + return true; + } + + // If user is assigned, check editorial global roles, journal admin and managers should have access for editing metadata + if (!$isAssigned) { + if (!empty(array_intersect( + PKPApplication::getWorkflowTypeRoles()[PKPApplication::WORKFLOW_TYPE_EDITORIAL], + $stages[$submission->getData('stageId')]['currentUserAssignedRoles'] + ))) { + return true; + } + } + + return false; + } + /** * Get details about the review assignments for a submission */ @@ -602,7 +636,6 @@ protected function getPropertyStages(Enumerable $stageAssignments, Submission $s // values false by default, to be determined later 'editorAssigned' => false, - 'isCurrentUserDecidingEditor' => false, 'currentUserAssignedRoles' => [], ]; } @@ -663,7 +696,7 @@ protected function getPropertyStages(Enumerable $stageAssignments, Submission $s } if (!$stageAssignment->recommendOnly) { - $isCurrentUserDecidingEditor = $stages[$groupStage->stageId]['isCurrentUserDecidingEditor'] = true; + $isCurrentUserDecidingEditor = true; } // if the user is assigned several times in the editorial role, and @@ -683,19 +716,22 @@ protected function getPropertyStages(Enumerable $stageAssignments, Submission $s if (!empty($globalRoles)) { foreach ($stageIds as $stageId) { $stages[$stageId]['currentUserAssignedRoles'] = $globalRoles; - $isCurrentUserDecidingEditor = $stages[$stageId]['isCurrentUserDecidingEditor'] = true; + if ($hasRecommendingEditors) { + $isCurrentUserDecidingEditor = $stages[$stageId]['isCurrentUserDecidingEditor'] = true; + } } } } - // Set recommendation related props + // Retrieve recommendations for the review stage + $reviewRecommendations = collect(); if ( isset($currentReviewRound) && isset($decisions) && $decisions->isNotEmpty() ) { foreach ($decisions as $decision) { - // Get only recommendations + // Get only recommendation decisions $decisionType = Repo::decision()->getDecisionType($decision->getData('decision')); if (!Repo::decision()->isRecommendation($decisionType->getDecision())) { continue; @@ -706,27 +742,45 @@ protected function getPropertyStages(Enumerable $stageAssignments, Submission $s continue; } - $recommendation = [ - 'decision' => $decision->getData('decision'), - 'label' => $decisionType->getRecommendationLabel(), - ]; + $reviewRecommendations->push($decision); + } + } - // Set recommendations for the deciding editor - if ($isCurrentUserDecidingEditor) { - $stages[$decision->getData('stageId')]['recommendations'][] = $recommendation; - } + $latestRecommendation = $reviewRecommendations->sortByDesc( + fn (Decision $recommendation) => + strtotime($recommendation->getData('dateDecided')) + )->first(); - // Set own recommendations of the current user - if ($currentUser->getId() == $decision->getData('editorId')) { - $stages[$decision->getData('stageId')]['currentUserRecommendation'] = $recommendation; - } + if ($latestRecommendation) { + + $recommendationData = [ + 'decision' => $latestRecommendation->getData('decision'), + 'label' => Repo::decision()->getDecisionType($latestRecommendation->getData('decision'))->getRecommendationLabel(), + ]; + + // Set recommendations for the deciding editor + if ($isCurrentUserDecidingEditor) { + $stages[$decision->getData('stageId')]['recommendations'] = $recommendationData; + } + + // Set own recommendations of the current user + if ($currentUser->getId() == $decision->getData('editorId')) { + $stages[$decision->getData('stageId')]['currentUserRecommendation'] = $recommendationData; } } foreach ($stages as $stageId => $stage) { - // Determine if deciding editor is assigned - if ($hasDecidingEditor && $hasRecommendingEditors) { - $stages[$stageId]['isDecidingEditorAssigned'] = true; + if ($hasRecommendingEditors) { + + // Determine if deciding editor is assigned + if ($hasDecidingEditor) { + $stages[$stageId]['isDecidingEditorAssigned'] = true; + } + + // We need to expose isCurrentUserDecidingEditor prop only when recommending editor is assigned + if ($isCurrentUserDecidingEditor) { + $stages[$stageId]['isCurrentUserDecidingEditor'] = true; + } } }