Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pkp/pkp-lib#2433 editor recommendation #2749

Merged
merged 9 commits into from
Sep 14, 2017
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,54 @@ function importPeerReviews($args, $request) {
return new JSONMessage(true, empty($body)?__('editor.review.noReviews'):$body);
}

/**
* Show the editor recommendation form
* @param $args array
* @param $request PKPRequest
* @return JSONMessage
*/
function sendRecommendation($args, $request) {
// Retrieve the authorized submission, stage id and review round.
$submission = $this->getAuthorizedContextObject(ASSOC_TYPE_SUBMISSION);
$stageId = $this->getAuthorizedContextObject(ASSOC_TYPE_WORKFLOW_STAGE);
assert(in_array($stageId, $this->_getReviewStages()));
$reviewRound = $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ROUND);
assert(is_a($reviewRound, 'ReviewRound'));

// Form handling
import('lib.pkp.controllers.modals.editorDecision.form.RecommendationForm');
$editorRecommendationForm = new RecommendationForm($submission, $stageId, $reviewRound);
$editorRecommendationForm->initData($request);
return new JSONMessage(true, $editorRecommendationForm->fetch($request));
}

/**
* Show the editor recommendation form
* @param $args array
* @param $request PKPRequest
* @return JSONMessage
*/
function saveRecommendation($args, $request) {
// Retrieve the authorized submission, stage id and review round.
$submission = $this->getAuthorizedContextObject(ASSOC_TYPE_SUBMISSION);
$stageId = $this->getAuthorizedContextObject(ASSOC_TYPE_WORKFLOW_STAGE);
assert(in_array($stageId, $this->_getReviewStages()));
$reviewRound = $this->getAuthorizedContextObject(ASSOC_TYPE_REVIEW_ROUND);
assert(is_a($reviewRound, 'ReviewRound'));

// Form handling
import('lib.pkp.controllers.modals.editorDecision.form.RecommendationForm');
$editorRecommendationForm = new RecommendationForm($submission, $stageId, $reviewRound);
$editorRecommendationForm->readInputData();
if ($editorRecommendationForm->validate()) {
$editorRecommendationForm->execute($request);
$json = new JSONMessage(true);
$json->setGlobalEvent('decisionActionUpdated');
return $json;
}
return new JSONMessage(false);
}


//
// Protected helper methods
Expand All @@ -282,7 +330,7 @@ function importPeerReviews($args, $request) {
* @return array
*/
protected function _getReviewRoundOps() {
return array('promoteInReview', 'savePromoteInReview', 'newReviewRound', 'saveNewReviewRound', 'sendReviewsInReview', 'saveSendReviewsInReview', 'importPeerReviews');
return array('promoteInReview', 'savePromoteInReview', 'newReviewRound', 'saveNewReviewRound', 'sendReviewsInReview', 'saveSendReviewsInReview', 'importPeerReviews', 'sendRecommendation', 'saveRecommendation');
}

/**
Expand Down
1 change: 1 addition & 0 deletions classes/log/PKPSubmissionEmailLogEntry.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
define('SUBMISSION_EMAIL_EDITOR_NOTIFY_AUTHOR', 0x30000001);
define('SUBMISSION_EMAIL_EDITOR_ASSIGN', 0x30000002);
define('SUBMISSION_EMAIL_EDITOR_NOTIFY_AUTHOR_UNSUITABLE', 0x30000003);
define('SUBMISSION_EMAIL_EDITOR_RECOMMEND_NOTIFY', 0x30000004);

// Reviewer events 0x40000000
define('SUBMISSION_EMAIL_REVIEW_NOTIFY_REVIEWER', 0x40000001);
Expand Down
2 changes: 1 addition & 1 deletion classes/log/PKPSubmissionEventLogEntry.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
define('SUBMISSION_LOG_METADATA_UNPUBLISH', 0x10000007);

// Editor events

define('SUBMISSION_LOG_EDITOR_DECISION', 0x30000003);
define('SUBMISSION_LOG_EDITOR_RECOMMENDATION', 0x30000004);

// Reviewer events 0x40000000
define('SUBMISSION_LOG_REVIEW_ASSIGN', 0x40000001);
Expand Down
18 changes: 18 additions & 0 deletions classes/security/UserGroup.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,24 @@ function setPermitSelfRegistration($permitSelfRegistration) {
$this->setData('permitSelfRegistration', $permitSelfRegistration);
}

/**
* Get the recommendOnly option (whether or not the manager or the sub-editor role
* can only recommend or also make decisions in the submission review)
* @return boolean
*/
function getRecommendOnly() {
return $this->getData('recommendOnly');
}

/**
* Set the recommendOnly option (whether or not the manager or the sub-editor role
* can only recommend or also make decisions in the submission review)
* @param $recommendOnly boolean
*/
function setRecommendOnly($recommendOnly) {
$this->setData('recommendOnly', $recommendOnly);
}

/**
* Get the localized role name
* @return string
Expand Down
39 changes: 39 additions & 0 deletions classes/security/UserGroupDAO.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,15 @@ function getLocaleFieldNames() {
return array('name', 'abbrev');
}

/**
* @copydoc DAO::getAdditionalFieldNames()
*/
function getAdditionalFieldNames() {
return array_merge(parent::getAdditionalFieldNames(), array(
'recommendOnly',
));
}

/**
* Update the localized data for this object
* @param $author object
Expand Down Expand Up @@ -946,6 +955,36 @@ function userAssignmentExists($contextId, $userId, $stageId) {
$result->Close();
return $returner;
}

/**
* Get all user group IDs with recommendOnly option enabled.
* @param $contextId integer
* @param $roleId integer (optional)
* @return array
*/
function getRecommendOnlyGroupIds($contextId, $roleId = null) {
$params = array((int) $contextId);
if ($roleId) $params[] = (int) $roleId;

$result = $this->retrieve(
'SELECT ug.user_group_id
FROM user_groups ug
JOIN user_group_settings ugs ON (ugs.user_group_id = ug.user_group_id AND ugs.setting_name = \'recommendOnly\' AND ugs.setting_value = \'1\')
WHERE ug.context_id = ?
' . ($roleId?' AND ug.role_id = ?':''),
$params
);

$userGroupIds = array();
while (!$result->EOF) {
$userGroupIds[] = (int) $result->fields[0];
$result->MoveNext();
}

$result->Close();
return $userGroupIds;
}

}

?>
15 changes: 15 additions & 0 deletions classes/services/PKPSubmissionService.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public function getSubmissionList($contextId, $args = array()) {
'orderDirection' => 'DESC',
'assignedTo' => null,
'status' => null,
'stageIds' => null,
'searchPhrase' => null,
'count' => 20,
'offset' => 0,
Expand Down Expand Up @@ -525,6 +526,20 @@ public function toArrayStageDetails($submission, $stageIds = null) {
$stage['files'] = array(
'count' => count($submissionFiles),
);

// See if the curent user can only recommend:
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO');
$user = $request->getUser();
$editorsStageAssignments = $stageAssignmentDao->getEditorsAssignedToStage($submission->getId(), $stageId);
// if the user is assigned several times in the editorial role, and
// one of the assignments have recommendOnly option set, consider it here
$stage['currentUserCanRecommendOnly'] = false;
foreach ($editorsStageAssignments as $editorsStageAssignment) {
if ($editorsStageAssignment->getUserId() == $user->getId() && $editorsStageAssignment->getRecommendOnly()) {
$stage['currentUserCanRecommendOnly'] = true;
break;
}
}
}
break;

Expand Down
17 changes: 17 additions & 0 deletions classes/stageAssignment/StageAssignment.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,23 @@ function setDateAssigned($dateAssigned) {
function getDateAssigned() {
return $this->getData('dateAssigned');
}

/**
* Get recommendOnly option.
* @return boolean
*/
function getRecommendOnly() {
return $this->getData('recommendOnly');
}

/**
* Set recommendOnly option.
* @param $recommendOnly boolean
*/
function setRecommendOnly($recommendOnly) {
$this->setData('recommendOnly', $recommendOnly);
}

}

?>
19 changes: 13 additions & 6 deletions classes/stageAssignment/StageAssignmentDAO.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function getByUserId($userId) {
* Get editor stage assignments.
* @param $submissionId int
* @param $stageId int
* @return array
* @return array StageAssignment
*/
function getEditorsAssignedToStage($submissionId, $stageId) {
$managerAssignmentFactory = $this->getBySubmissionAndRoleId($submissionId, ROLE_ID_MANAGER, $stageId);
Expand Down Expand Up @@ -109,9 +109,10 @@ function editorAssignedToStage($submissionId, $stageId = null) {
* @param $submissionId int
* @param $userGroupId int
* @param $userId int
* @param $recommendOnly boolean
* @return StageAssignment
*/
function build($submissionId, $userGroupId, $userId) {
function build($submissionId, $userGroupId, $userId, $recommendOnly = false) {

// If one exists, fetch and return.
$stageAssignment = $this->getBySubmissionAndStageId($submissionId, null, $userGroupId, $userId);
Expand All @@ -122,6 +123,7 @@ function build($submissionId, $userGroupId, $userId) {
$stageAssignment->setSubmissionId($submissionId);
$stageAssignment->setUserGroupId($userGroupId);
$stageAssignment->setUserId($userId);
$stageAssignment->setRecommendOnly($recommendOnly);
$this->insertObject($stageAssignment);
$stageAssignment->setId($this->getInsertId());
return $stageAssignment;
Expand Down Expand Up @@ -149,6 +151,7 @@ function _fromRow($row) {
$stageAssignment->setUserGroupId($row['user_group_id']);
$stageAssignment->setDateAssigned($row['date_assigned']);
$stageAssignment->setStageId($row['stage_id']);
$stageAssignment->setRecommendOnly($row['recommend_only']);

return $stageAssignment;
}
Expand All @@ -161,15 +164,16 @@ function insertObject($stageAssignment) {
$this->update(
sprintf(
'INSERT INTO stage_assignments
(submission_id, user_group_id, user_id, date_assigned)
(submission_id, user_group_id, user_id, date_assigned, recommend_only)
VALUES
(?, ?, ?, %s)',
(?, ?, ?, %s, ?)',
$this->datetimeToDB(Core::getCurrentDate())
),
array(
$stageAssignment->getSubmissionId(),
$this->nullOrInt($stageAssignment->getUserGroupId()),
$this->nullOrInt($stageAssignment->getUserId())
$this->nullOrInt($stageAssignment->getUserId()),
$stageAssignment->getRecommendOnly()?$stageAssignment->getRecommendOnly():0
)
);
}
Expand All @@ -185,7 +189,8 @@ function updateObject($stageAssignment) {
submission_id = ?,
user_group_id = ?,
user_id = ?,
date_assigned = %s
date_assigned = %s,
recommend_only = ?
WHERE stage_assignment_id = ?',
$this->datetimeToDB(Core::getCurrentDate())
),
Expand All @@ -194,6 +199,7 @@ function updateObject($stageAssignment) {
$this->nullOrInt($stageAssignment->getUserGroupId()),
$this->nullOrInt($stageAssignment->getUserId()),
(int) $stageAssignment->getId(),
$stageAssignment->getRecommendOnly()?$stageAssignment->getRecommendOnly():0
)
);
}
Expand Down Expand Up @@ -243,6 +249,7 @@ function getInsertId() {
* @param $stageId int optional
* @param $userGroupId int optional
* @param $userId int optional
* @param $roleId int optional ROLE_ID_...
* @param $single bool specify if only one stage assignment (default is a ResultFactory)
* @return StageAssignment|ResultFactory Mixed, depending on $single
*/
Expand Down
9 changes: 6 additions & 3 deletions classes/submission/EditDecisionDAO.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ function deleteDecisionsBySubmissionId($submissionId) {
* @param $submissionId int Submission ID
* @param $stageId int Optional STAGE_ID_...
* @param $round int Optional review round number
* @param $editorId int Optional editor ID
* @return array List of information on the editor decisions:
* editDecisionId, reviewRoundId, stageId, round, editorId, decision, dateDecided
*/
function getEditorDecisions($submissionId, $stageId = null, $round = null) {
function getEditorDecisions($submissionId, $stageId = null, $round = null, $editorId = null) {
$params = array((int) $submissionId);
if ($stageId) $params[] = (int) $stageId;
if ($round) $params[] = (int) $round;
if ($editorId) $params[] = (int) $editorId;

$result = $this->retrieve(
'SELECT edit_decision_id, editor_id, decision,
Expand All @@ -78,7 +80,8 @@ function getEditorDecisions($submissionId, $stageId = null, $round = null) {
WHERE submission_id = ?
' . ($stageId?' AND stage_id = ?':'') . '
' . ($round?' AND round = ?':'') . '
ORDER BY date_decided ASC',
' . ($editorId?' AND editor_id = ?':'') . '
ORDER BY date_decided ASC',
$params
);

Expand Down Expand Up @@ -110,7 +113,7 @@ function transferEditorDecisions($oldUserId, $newUserId) {
array((int) $newUserId, (int) $oldUserId)
);
}

/**
* Find any still valid pending revisions decision for the passed
* submission id. A valid decision is one that is not overriden by any
Expand Down
15 changes: 9 additions & 6 deletions classes/submission/action/EditorAction.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ function __construct() {
* @param $request PKPRequest
* @param $submission Submission
* @param $decision integer
* @param $decisionLabels array(DECISION_CONSTANT => decision.locale.key, ...)
* @param $reviewRound ReviewRound Current review round that user is taking the decision, if any.
* @param $stageId int
* @param $decisionLabels array(SUBMISSION_EDITOR_DECISION_... or SUBMISSION_EDITOR_RECOMMEND_... => editor.submission.decision....)
* @param $reviewRound ReviewRound optional Current review round that user is taking the decision, if any.
* @param $stageId integer optional
* @param $recommendation boolean optional
*/
function recordDecision($request, $submission, $decision, $decisionLabels, $reviewRound = null, $stageId = null) {
function recordDecision($request, $submission, $decision, $decisionLabels, $reviewRound = null, $stageId = null, $recommendation = false) {
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO');

// Define the stage and round data.
Expand Down Expand Up @@ -66,7 +67,7 @@ function recordDecision($request, $submission, $decision, $decisionLabels, $revi
);

$result = $editorDecision;
if (!HookRegistry::call('EditorAction::recordDecision', array(&$submission, &$editorDecision, &$result))) {
if (!HookRegistry::call('EditorAction::recordDecision', array(&$submission, &$editorDecision, &$result, &$recommendation))) {
// Record the new decision
$editDecisionDao = DAORegistry::getDAO('EditDecisionDAO');
$editDecisionDao->updateEditorDecision($submission->getId(), $editorDecision, $stageId, $reviewRound);
Expand All @@ -87,7 +88,9 @@ function recordDecision($request, $submission, $decision, $decisionLabels, $revi
import('lib.pkp.classes.log.SubmissionLog');
import('lib.pkp.classes.log.PKPSubmissionEventLogEntry');
AppLocale::requireComponents(LOCALE_COMPONENT_APP_COMMON, LOCALE_COMPONENT_APP_EDITOR);
SubmissionLog::logEvent($request, $submission, SUBMISSION_LOG_EDITOR_DECISION, 'log.editor.decision', array('editorName' => $user->getFullName(), 'submissionId' => $submission->getId(), 'decision' => __($decisionLabels[$decision])));
$eventType = $recommendation ? SUBMISSION_LOG_EDITOR_RECOMMENDATION : SUBMISSION_LOG_EDITOR_DECISION;
$logKey = $recommendation ? 'log.editor.recommendation' : 'log.editor.decision';
SubmissionLog::logEvent($request, $submission, $eventType, $logKey, array('editorName' => $user->getFullName(), 'submissionId' => $submission->getId(), 'decision' => __($decisionLabels[$decision])));
}
return $result;
}
Expand Down
4 changes: 2 additions & 2 deletions classes/submission/form/PKPSubmissionSubmitStep4Form.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ function execute($args, $request) {
$users = $userGroupDao->getUsersById($userGroup->getId(), $this->submission->getContextId());
if($users->getCount() == 1) {
$user = $users->next();
$stageAssignmentDao->build($this->submission->getId(), $userGroup->getId(), $user->getId());
$stageAssignmentDao->build($this->submission->getId(), $userGroup->getId(), $user->getId(), $userGroup->getRecommendOnly());
if ($userGroup->getRoleId() == ROLE_ID_MANAGER) $managerFound = true;
}
}
Expand Down Expand Up @@ -92,7 +92,7 @@ function execute($args, $request) {
$userGroups = $userGroupDao->getByUserId($subEditor->getId(), $this->submission->getContextId());
while ($userGroup = $userGroups->next()) {
if ($userGroup->getRoleId() != ROLE_ID_SUB_EDITOR) continue;
$stageAssignmentDao->build($this->submission->getId(), $userGroup->getId(), $subEditor->getId());
$stageAssignmentDao->build($this->submission->getId(), $userGroup->getId(), $subEditor->getId(), $userGroup->getRecommendOnly());
// If we assign a stage assignment in the Submission stage to a sub editor, make note.
if ($userGroupDao->userGroupAssignedToStage($userGroup->getId(), WORKFLOW_STAGE_ID_SUBMISSION)) {
$submissionSubEditorFound = true;
Expand Down
Loading