1244 lines
44 KiB
PHP
1244 lines
44 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @file classes/controllers/grid/users/reviewer/PKPReviewerGridHandler.php
|
|
*
|
|
* Copyright (c) 2014-2021 Simon Fraser University
|
|
* Copyright (c) 2000-2021 John Willinsky
|
|
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
|
*
|
|
* @class PKPReviewerGridHandler
|
|
*
|
|
* @ingroup classes_controllers_grid_users_reviewer
|
|
*
|
|
* @brief Handle reviewer grid requests.
|
|
*/
|
|
|
|
namespace PKP\controllers\grid\users\reviewer;
|
|
|
|
use APP\core\Application;
|
|
use APP\core\PageRouter;
|
|
use APP\core\Request;
|
|
use APP\facades\Repo;
|
|
use APP\log\event\SubmissionEventLogEntry;
|
|
use APP\notification\NotificationManager;
|
|
use APP\submission\Submission;
|
|
use APP\template\TemplateManager;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use PKP\controllers\grid\GridColumn;
|
|
use PKP\controllers\grid\GridHandler;
|
|
use PKP\controllers\grid\users\reviewer\form\EditReviewForm;
|
|
use PKP\controllers\grid\users\reviewer\form\EmailReviewerForm;
|
|
use PKP\controllers\grid\users\reviewer\form\ReinstateReviewerForm;
|
|
use PKP\controllers\grid\users\reviewer\form\ResendRequestReviewerForm;
|
|
use PKP\controllers\grid\users\reviewer\form\ReviewerGossipForm;
|
|
use PKP\controllers\grid\users\reviewer\form\ReviewReminderForm;
|
|
use PKP\controllers\grid\users\reviewer\form\ThankReviewerForm;
|
|
use PKP\controllers\grid\users\reviewer\form\UnassignReviewerForm;
|
|
use PKP\core\Core;
|
|
use PKP\core\JSONMessage;
|
|
use PKP\core\PKPApplication;
|
|
use PKP\core\PKPRequest;
|
|
use PKP\core\PKPServices;
|
|
use PKP\db\DAO;
|
|
use PKP\db\DAORegistry;
|
|
use PKP\emailTemplate\EmailTemplate;
|
|
use PKP\facades\Locale;
|
|
use PKP\linkAction\LinkAction;
|
|
use PKP\linkAction\request\AjaxModal;
|
|
use PKP\log\event\PKPSubmissionEventLogEntry;
|
|
use PKP\log\SubmissionLog;
|
|
use PKP\mail\Mailable;
|
|
use PKP\mail\mailables\ReviewerReinstate;
|
|
use PKP\mail\mailables\ReviewerResendRequest;
|
|
use PKP\mail\mailables\ReviewerUnassign;
|
|
use PKP\mail\traits\Sender;
|
|
use PKP\notification\NotificationDAO;
|
|
use PKP\notification\PKPNotification;
|
|
use PKP\notification\PKPNotificationManager;
|
|
use PKP\reviewForm\ReviewFormDAO;
|
|
use PKP\reviewForm\ReviewFormElementDAO;
|
|
use PKP\reviewForm\ReviewFormResponseDAO;
|
|
use PKP\security\authorization\internal\ReviewAssignmentRequiredPolicy;
|
|
use PKP\security\authorization\internal\ReviewRoundRequiredPolicy;
|
|
use PKP\security\authorization\WorkflowStageAccessPolicy;
|
|
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;
|
|
use PKP\user\User;
|
|
use Symfony\Component\Mailer\Exception\TransportException;
|
|
|
|
class PKPReviewerGridHandler extends GridHandler
|
|
{
|
|
// Reviewer selection types
|
|
public const REVIEWER_SELECT_ADVANCED_SEARCH = 1;
|
|
public const REVIEWER_SELECT_CREATE = 2;
|
|
public const REVIEWER_SELECT_ENROLL_EXISTING = 3;
|
|
|
|
/** @var Submission */
|
|
public $_submission;
|
|
|
|
/** @var int */
|
|
public $_stageId;
|
|
|
|
/** @var bool Is the current user assigned as an author to this submission */
|
|
public $_isCurrentUserAssignedAuthor;
|
|
|
|
public bool $isAuthorGrid = false;
|
|
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
|
|
$allOperations = array_merge($this->_getReviewAssignmentOps(), $this->_getReviewRoundOps());
|
|
|
|
$this->addRoleAssignment(
|
|
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_SUB_EDITOR],
|
|
$allOperations
|
|
);
|
|
|
|
// Remove operations related to creation and enrollment of users.
|
|
$assistantOperations = array_flip($allOperations);
|
|
unset($assistantOperations['createReviewer']);
|
|
unset($assistantOperations['enrollReviewer']);
|
|
unset($assistantOperations['gossip']);
|
|
$assistantOperations = array_flip($assistantOperations);
|
|
|
|
$this->addRoleAssignment(
|
|
[Role::ROLE_ID_ASSISTANT],
|
|
$assistantOperations
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @copydoc PKPHandler::authorize()
|
|
*/
|
|
public function authorize($request, &$args, $roleAssignments)
|
|
{
|
|
if (!$this->isAuthorGrid) {
|
|
$stageId = $request->getUserVar('stageId'); // This is being validated in WorkflowStageAccessPolicy
|
|
|
|
// Not all actions need a stageId. Some work off the reviewAssignment which has the type and round.
|
|
$this->_stageId = (int)$stageId;
|
|
|
|
// Get the stage access policy
|
|
$workflowStageAccessPolicy = new WorkflowStageAccessPolicy($request, $args, $roleAssignments, 'submissionId', $stageId, PKPApplication::WORKFLOW_TYPE_EDITORIAL);
|
|
|
|
// Add policy to ensure there is a review round id.
|
|
$workflowStageAccessPolicy->addPolicy(new ReviewRoundRequiredPolicy($request, $args, 'reviewRoundId', $this->_getReviewRoundOps()));
|
|
|
|
// Add policy to ensure there is a review assignment for certain operations.
|
|
$workflowStageAccessPolicy->addPolicy(new ReviewAssignmentRequiredPolicy($request, $args, 'reviewAssignmentId', $this->_getReviewAssignmentOps()));
|
|
$this->addPolicy($workflowStageAccessPolicy);
|
|
|
|
$success = parent::authorize($request, $args, $roleAssignments);
|
|
|
|
// Prevent authors from accessing review details, even if they are also
|
|
// assigned as an editor, sub-editor or assistant.
|
|
$userAssignedRoles = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES);
|
|
$this->_isCurrentUserAssignedAuthor = false;
|
|
foreach ($userAssignedRoles as $stageId => $roles) {
|
|
if (in_array(Role::ROLE_ID_AUTHOR, $roles)) {
|
|
$this->_isCurrentUserAssignedAuthor = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($this->_isCurrentUserAssignedAuthor) {
|
|
/** @var PageRouter */
|
|
$router = $request->getRouter();
|
|
$operation = $router->getRequestedOp($request);
|
|
|
|
if (in_array($operation, $this->_getAuthorDeniedOps())) {
|
|
return false;
|
|
}
|
|
|
|
if (in_array($operation, $this->_getAuthorDeniedAnonymousOps())) {
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
if ($reviewAssignment && in_array($reviewAssignment->getReviewMethod(), [ReviewAssignment::SUBMISSION_REVIEW_METHOD_ANONYMOUS, ReviewAssignment::SUBMISSION_REVIEW_METHOD_DOUBLEANONYMOUS])) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $success;
|
|
} else {
|
|
return parent::authorize($request, $args, $roleAssignments);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Getters and Setters
|
|
//
|
|
/**
|
|
* Get the authorized submission.
|
|
*
|
|
* @return Submission
|
|
*/
|
|
public function getSubmission()
|
|
{
|
|
return $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
|
}
|
|
|
|
/**
|
|
* Get the review stage id.
|
|
*
|
|
* @return int
|
|
*/
|
|
public function getStageId()
|
|
{
|
|
return $this->_stageId;
|
|
}
|
|
|
|
/**
|
|
* Get review round object.
|
|
*
|
|
* @return ReviewRound
|
|
*/
|
|
public function getReviewRound()
|
|
{
|
|
$reviewRound = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ROUND);
|
|
if ($reviewRound instanceof ReviewRound) {
|
|
return $reviewRound;
|
|
} else {
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT); /** @var ReviewAssignment $reviewAssignment */
|
|
$reviewRoundId = $reviewAssignment->getReviewRoundId();
|
|
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /** @var ReviewRoundDAO $reviewRoundDao */
|
|
$reviewRound = $reviewRoundDao->getById($reviewRoundId);
|
|
return $reviewRound;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Overridden methods from PKPHandler
|
|
//
|
|
/**
|
|
* @copydoc GridHandler::initialize()
|
|
*
|
|
* @param null|mixed $args
|
|
*/
|
|
public function initialize($request, $args = null)
|
|
{
|
|
parent::initialize($request, $args);
|
|
$this->setTitle('user.role.reviewers');
|
|
|
|
// Grid actions
|
|
if (!$this->_isCurrentUserAssignedAuthor) {
|
|
$router = $request->getRouter();
|
|
$actionArgs = array_merge($this->getRequestArgs(), ['selectionType' => self::REVIEWER_SELECT_ADVANCED_SEARCH]);
|
|
$this->addAction(
|
|
new LinkAction(
|
|
'addReviewer',
|
|
new AjaxModal(
|
|
$router->url($request, null, null, 'showReviewerForm', null, $actionArgs),
|
|
__('editor.submission.addReviewer'),
|
|
'modal_add_user'
|
|
),
|
|
__('editor.submission.addReviewer'),
|
|
'add_user'
|
|
)
|
|
);
|
|
}
|
|
|
|
// Columns
|
|
$cellProvider = new ReviewerGridCellProvider($this->_isCurrentUserAssignedAuthor);
|
|
$this->addColumn(
|
|
new GridColumn(
|
|
'name',
|
|
'user.name',
|
|
null,
|
|
null,
|
|
$cellProvider
|
|
)
|
|
);
|
|
|
|
// Add a column for the status of the review.
|
|
$this->addColumn(
|
|
new GridColumn(
|
|
'considered',
|
|
'common.status',
|
|
null,
|
|
null,
|
|
$cellProvider,
|
|
['anyhtml' => true]
|
|
)
|
|
);
|
|
|
|
// Add a column for the review method
|
|
$this->addColumn(
|
|
new GridColumn(
|
|
'method',
|
|
'common.type',
|
|
null,
|
|
null,
|
|
$cellProvider
|
|
)
|
|
);
|
|
|
|
// Add a column for the status of the review.
|
|
$this->addColumn(
|
|
new GridColumn(
|
|
'actions',
|
|
'grid.columns.actions',
|
|
null,
|
|
null,
|
|
$cellProvider
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
//
|
|
// Overridden methods from GridHandler
|
|
//
|
|
/**
|
|
* @see GridHandler::getRowInstance()
|
|
*
|
|
* @return ReviewerGridRow
|
|
*/
|
|
protected function getRowInstance()
|
|
{
|
|
return new ReviewerGridRow($this->_isCurrentUserAssignedAuthor);
|
|
}
|
|
|
|
/**
|
|
* @see GridHandler::getRequestArgs()
|
|
*/
|
|
public function getRequestArgs()
|
|
{
|
|
$submission = $this->getSubmission();
|
|
$reviewRound = $this->getReviewRound();
|
|
return [
|
|
'submissionId' => $submission->getId(),
|
|
'stageId' => $this->getStageId(),
|
|
'reviewRoundId' => $reviewRound->getId()
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @see GridHandler::loadData()
|
|
*/
|
|
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());
|
|
}
|
|
|
|
|
|
//
|
|
// Public actions
|
|
//
|
|
/**
|
|
* Add a reviewer.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function showReviewerForm($args, $request)
|
|
{
|
|
return new JSONMessage(true, $this->_fetchReviewerForm($args, $request));
|
|
}
|
|
|
|
/**
|
|
* Load the contents of the reviewer form
|
|
*
|
|
* @param array $args
|
|
* @param Request $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function reloadReviewerForm($args, $request)
|
|
{
|
|
$json = new JSONMessage(true);
|
|
$json->setEvent('refreshForm', $this->_fetchReviewerForm($args, $request));
|
|
return $json;
|
|
}
|
|
|
|
/**
|
|
* Create a new user as reviewer.
|
|
*
|
|
* @param array $args
|
|
* @param Request $request
|
|
*
|
|
* @return JSONMessage Serialized JSON object
|
|
*/
|
|
public function createReviewer($args, $request)
|
|
{
|
|
return $this->updateReviewer($args, $request);
|
|
}
|
|
|
|
/**
|
|
* Enroll an existing user as reviewer.
|
|
*
|
|
* @param array $args
|
|
* @param Request $request
|
|
*
|
|
* @return JSONMessage Serialized JSON object
|
|
*/
|
|
public function enrollReviewer($args, $request)
|
|
{
|
|
return $this->updateReviewer($args, $request);
|
|
}
|
|
|
|
/**
|
|
* Edit a reviewer
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function updateReviewer($args, $request)
|
|
{
|
|
$selectionType = $request->getUserVar('selectionType');
|
|
$formClassName = $this->_getReviewerFormClassName($selectionType);
|
|
|
|
// Form handling
|
|
$reviewerForm = new $formClassName($this->getSubmission(), $this->getReviewRound());
|
|
$reviewerForm->readInputData();
|
|
if ($reviewerForm->validate()) {
|
|
$reviewAssignment = $reviewerForm->execute();
|
|
$json = DAO::getDataChangedEvent($reviewAssignment->getId());
|
|
$json->setGlobalEvent('update:decisions');
|
|
return $json;
|
|
} else {
|
|
// There was an error, redisplay the form
|
|
return new JSONMessage(true, $reviewerForm->fetch($request));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Manage reviewer access to files
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function editReview($args, $request)
|
|
{
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
$editReviewForm = new EditReviewForm($reviewAssignment, $this->getSubmission());
|
|
$editReviewForm->initData();
|
|
return new JSONMessage(true, $editReviewForm->fetch($request));
|
|
}
|
|
|
|
/**
|
|
* Save a change to reviewer access to files
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function updateReview($args, $request)
|
|
{
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
$editReviewForm = new EditReviewForm($reviewAssignment, $this->getSubmission());
|
|
$editReviewForm->readInputData();
|
|
if ($editReviewForm->validate()) {
|
|
$editReviewForm->execute();
|
|
$json = DAO::getDataChangedEvent($reviewAssignment->getId());
|
|
$json->setGlobalEvent('update:decisions');
|
|
return $json;
|
|
} else {
|
|
return new JSONMessage(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a list of all non-reviewer users in the system to populate the reviewer role assignment autocomplete.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function getUsersNotAssignedAsReviewers($args, $request)
|
|
{
|
|
$context = $request->getContext();
|
|
$term = $request->getUserVar('term');
|
|
|
|
$users = Repo::user()->getCollector()
|
|
->filterExcludeRoles([Role::ROLE_ID_REVIEWER])
|
|
->filterByContextIds([$context->getId()])
|
|
->searchPhrase($term)
|
|
->getMany();
|
|
|
|
$userList = [];
|
|
foreach ($users as $user) {
|
|
$label = $user->getFullName() . ' (' . $user->getEmail() . ')';
|
|
$userList[] = ['label' => $label, 'value' => $user->getId()];
|
|
}
|
|
|
|
if (count($userList) == 0) {
|
|
return $this->noAutocompleteResults();
|
|
}
|
|
|
|
return new JSONMessage(true, $userList);
|
|
}
|
|
|
|
/**
|
|
* Unassign a reviewer
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function unassignReviewer($args, $request)
|
|
{
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
$reviewRound = $this->getReviewRound();
|
|
$submission = $this->getSubmission();
|
|
|
|
$unassignReviewerForm = new UnassignReviewerForm($reviewAssignment, $reviewRound, $submission);
|
|
$unassignReviewerForm->initData();
|
|
|
|
return new JSONMessage(true, $unassignReviewerForm->fetch($request));
|
|
}
|
|
|
|
/**
|
|
* Reinstate a reviewer
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function reinstateReviewer($args, $request)
|
|
{
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
$reviewRound = $this->getReviewRound();
|
|
$submission = $this->getSubmission();
|
|
|
|
$reinstateReviewerForm = new ReinstateReviewerForm($reviewAssignment, $reviewRound, $submission);
|
|
$reinstateReviewerForm->initData();
|
|
|
|
return new JSONMessage(true, $reinstateReviewerForm->fetch($request));
|
|
}
|
|
|
|
/**
|
|
* Save the reviewer reinstatement
|
|
*
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function updateReinstateReviewer($args, $request)
|
|
{
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
$reviewRound = $this->getReviewRound();
|
|
$submission = $this->getSubmission();
|
|
|
|
$reinstateReviewerForm = new ReinstateReviewerForm($reviewAssignment, $reviewRound, $submission);
|
|
$reinstateReviewerForm->readInputData();
|
|
|
|
// Reinstate the reviewer and return status message
|
|
if (!$reinstateReviewerForm->validate()) {
|
|
return new JSONMessage(false, __('editor.review.errorReinstatingReviewer'));
|
|
}
|
|
|
|
// Create mailable and send email
|
|
if ($reinstateReviewerForm->execute() && !$request->getUserVar('skipEmail')) {
|
|
$reviewer = Repo::user()->get($reviewAssignment->getReviewerId());
|
|
$user = $request->getUser();
|
|
$context = PKPServices::get('context')->get($submission->getData('contextId'));
|
|
$template = Repo::emailTemplate()->getByKey($context->getId(), ReviewerReinstate::getEmailTemplateKey());
|
|
$mailable = new ReviewerReinstate($context, $submission, $reviewAssignment);
|
|
$this->createMail($mailable, $request->getUserVar('personalMessage'), $template, $user, $reviewer);
|
|
}
|
|
|
|
$json = DAO::getDataChangedEvent($reviewAssignment->getId());
|
|
$json->setGlobalEvent('update:decisions');
|
|
return $json;
|
|
}
|
|
|
|
/**
|
|
* Resend request to reviewer to reconsider previously declined review invitation
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function resendRequestReviewer($args, $request)
|
|
{
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
$reviewRound = $this->getReviewRound(); /** @var ReviewRound $reviewRound */
|
|
$submission = $this->getSubmission(); /** @var Submission $submission */
|
|
|
|
$resendRequestReviewerForm = new ResendRequestReviewerForm($reviewAssignment, $reviewRound, $submission);
|
|
$resendRequestReviewerForm->initData();
|
|
|
|
return new JSONMessage(true, $resendRequestReviewerForm->fetch($request));
|
|
}
|
|
|
|
/**
|
|
* Save the reviewer resend request
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function updateResendRequestReviewer($args, $request)
|
|
{
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
$reviewRound = $this->getReviewRound(); /** @var ReviewRound $reviewRound */
|
|
$submission = $this->getSubmission(); /** @var Submission $submission */
|
|
|
|
$resendRequestReviewerForm = new ResendRequestReviewerForm($reviewAssignment, $reviewRound, $submission);
|
|
$resendRequestReviewerForm->readInputData();
|
|
|
|
if (!$resendRequestReviewerForm->validate()) {
|
|
return new JSONMessage(false, __('editor.review.errorResendingReviewerRequest'));
|
|
}
|
|
|
|
// Create mailable and send email
|
|
if ($resendRequestReviewerForm->execute() && !$request->getUserVar('skipEmail')) {
|
|
$reviewer = Repo::user()->get($reviewAssignment->getReviewerId());
|
|
$user = $request->getUser();
|
|
$context = $request->getContext();
|
|
$template = Repo::emailTemplate()->getByKey($context->getId(), ReviewerResendRequest::getEmailTemplateKey());
|
|
$mailable = new ReviewerResendRequest($context, $submission, $reviewAssignment);
|
|
$this->createMail($mailable, $request->getUserVar('personalMessage'), $template, $user, $reviewer);
|
|
}
|
|
|
|
$json = DAO::getDataChangedEvent($reviewAssignment->getId());
|
|
$json->setGlobalEvent('update:decisions');
|
|
return $json;
|
|
}
|
|
|
|
/**
|
|
* Save the reviewer unassignment
|
|
*
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function updateUnassignReviewer($args, $request)
|
|
{
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
$reviewRound = $this->getReviewRound();
|
|
$submission = $this->getSubmission();
|
|
|
|
$unassignReviewerForm = new UnassignReviewerForm($reviewAssignment, $reviewRound, $submission);
|
|
$unassignReviewerForm->readInputData();
|
|
|
|
// Unassign the reviewer and return status message
|
|
if (!$unassignReviewerForm->validate()) {
|
|
return new JSONMessage(false, __('editor.review.errorDeletingReviewer'));
|
|
}
|
|
|
|
// Create mailable and send email
|
|
if ($unassignReviewerForm->execute() && !$request->getUserVar('skipEmail')) {
|
|
$reviewer = Repo::user()->get($reviewAssignment->getReviewerId());
|
|
$user = $request->getUser();
|
|
$context = PKPServices::get('context')->get($submission->getData('contextId'));
|
|
$template = Repo::emailTemplate()->getByKey($context->getId(), ReviewerUnassign::getEmailTemplateKey());
|
|
$mailable = new ReviewerUnassign($context, $submission, $reviewAssignment);
|
|
$this->createMail($mailable, $request->getUserVar('personalMessage'), $template, $user, $reviewer);
|
|
}
|
|
|
|
$json = DAO::getDataChangedEvent($reviewAssignment->getId());
|
|
$json->setGlobalEvent('update:decisions');
|
|
return $json;
|
|
}
|
|
|
|
/**
|
|
* An action triggered by a confirmation modal to allow an editor to unconsider a review.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function unconsiderReview($args, $request)
|
|
{
|
|
if (!$request->checkCSRF()) {
|
|
return new JSONMessage(false);
|
|
}
|
|
|
|
// This resets the state of the review to 'unread', but does not delete note history.
|
|
$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);
|
|
|
|
// log the unconsider.
|
|
$eventLog = Repo::eventLog()->newDataObject([
|
|
'assocType' => PKPApplication::ASSOC_TYPE_SUBMISSION,
|
|
'assocId' => $submission->getId(),
|
|
'eventType' => PKPSubmissionEventLogEntry::SUBMISSION_LOG_REVIEW_UNCONSIDERED,
|
|
'userId' => Validation::loggedInAs() ?? $user->getId(),
|
|
'message' => 'log.review.reviewUnconsidered',
|
|
'isTranslated' => false,
|
|
'dateLogged' => Core::getCurrentDate(),
|
|
'editorName' => $user->getFullName(),
|
|
'submissionId' => $submission->getId(),
|
|
'round' => $reviewAssignment->getRound(),
|
|
]);
|
|
Repo::eventLog()->add($eventLog);
|
|
|
|
return DAO::getDataChangedEvent($reviewAssignment->getId());
|
|
}
|
|
|
|
/**
|
|
* Mark the review as read and trigger a rewrite of the row.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function reviewRead($args, $request)
|
|
{
|
|
if (!$request->checkCSRF()) {
|
|
return new JSONMessage(false);
|
|
}
|
|
|
|
// Retrieve review assignment.
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT); /** @var \PKP\submission\reviewAssignment\ReviewAssignment $reviewAssignment */
|
|
|
|
// Rate the reviewer's performance on this assignment
|
|
$quality = $request->getUserVar('quality');
|
|
if ($quality) {
|
|
$reviewAssignment->setQuality((int) $quality);
|
|
$reviewAssignment->setDateRated(Core::getCurrentDate());
|
|
} else {
|
|
$reviewAssignment->setQuality(null);
|
|
$reviewAssignment->setDateRated(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
|
|
);
|
|
|
|
if (!$reviewAssignment->getDateCompleted()) {
|
|
// Editor completes the review.
|
|
$reviewAssignment->setDateConfirmed(Core::getCurrentDate());
|
|
$reviewAssignment->setDateCompleted(Core::getCurrentDate());
|
|
}
|
|
|
|
// Trigger an update of the review round status
|
|
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
|
|
$reviewAssignmentDao->updateObject($reviewAssignment);
|
|
|
|
//if the review was read by an editor, log event
|
|
if ($reviewAssignment->isRead()) {
|
|
$submissionId = $reviewAssignment->getSubmissionId();
|
|
$submission = Repo::submission()->get($submissionId);
|
|
|
|
$eventLog = Repo::eventLog()->newDataObject([
|
|
'assocType' => PKPApplication::ASSOC_TYPE_SUBMISSION,
|
|
'assocId' => $submission->getId(),
|
|
'eventType' => PKPSubmissionEventLogEntry::SUBMISSION_LOG_REVIEW_CONFIRMED,
|
|
'userId' => Validation::loggedInAs() ?? $user->getId(),
|
|
'message' => 'log.review.reviewConfirmed',
|
|
'isTranslated' => false,
|
|
'dateLogged' => Core::getCurrentDate(),
|
|
'editorName' => $user->getFullName(),
|
|
'submissionId' => $reviewAssignment->getSubmissionId(),
|
|
'round' => $reviewAssignment->getRound()
|
|
]);
|
|
Repo::eventLog()->add($eventLog);
|
|
}
|
|
// Remove the reviewer task.
|
|
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
|
|
$notificationDao->deleteByAssoc(
|
|
Application::ASSOC_TYPE_REVIEW_ASSIGNMENT,
|
|
$reviewAssignment->getId(),
|
|
$reviewAssignment->getReviewerId(),
|
|
PKPNotification::NOTIFICATION_TYPE_REVIEW_ASSIGNMENT
|
|
);
|
|
|
|
$json = DAO::getDataChangedEvent($reviewAssignment->getId());
|
|
$json->setGlobalEvent('update:decisions');
|
|
return $json;
|
|
}
|
|
|
|
/**
|
|
* Displays a modal to allow the editor to enter a message to send to the reviewer as a thank you.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function editThankReviewer($args, $request)
|
|
{
|
|
// Identify the review assignment being updated.
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
|
|
// Initialize form.
|
|
$thankReviewerForm = new ThankReviewerForm($reviewAssignment);
|
|
$thankReviewerForm->initData();
|
|
|
|
// Render form.
|
|
return new JSONMessage(true, $thankReviewerForm->fetch($request));
|
|
}
|
|
|
|
/**
|
|
* Open a modal to read the reviewer's review and
|
|
* download any files they may have uploaded
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function readReview($args, $request)
|
|
{
|
|
$templateMgr = TemplateManager::getManager($request);
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
$starHtml = '<span class="fa fa-star"></span>';
|
|
$templateMgr->assign([
|
|
'submission' => $this->getSubmission(),
|
|
'reviewAssignment' => $reviewAssignment,
|
|
'reviewerRatingOptions' => [
|
|
0 => __('editor.review.reviewerRating.none'),
|
|
ReviewAssignment::SUBMISSION_REVIEWER_RATING_VERY_GOOD => str_repeat($starHtml, ReviewAssignment::SUBMISSION_REVIEWER_RATING_VERY_GOOD),
|
|
ReviewAssignment::SUBMISSION_REVIEWER_RATING_GOOD => str_repeat($starHtml, ReviewAssignment::SUBMISSION_REVIEWER_RATING_GOOD),
|
|
ReviewAssignment::SUBMISSION_REVIEWER_RATING_AVERAGE => str_repeat($starHtml, ReviewAssignment::SUBMISSION_REVIEWER_RATING_AVERAGE),
|
|
ReviewAssignment::SUBMISSION_REVIEWER_RATING_POOR => str_repeat($starHtml, ReviewAssignment::SUBMISSION_REVIEWER_RATING_POOR),
|
|
ReviewAssignment::SUBMISSION_REVIEWER_RATING_VERY_POOR => str_repeat($starHtml, ReviewAssignment::SUBMISSION_REVIEWER_RATING_VERY_POOR),
|
|
],
|
|
'reviewerRecommendationOptions' => ReviewAssignment::getReviewerRecommendationOptions(),
|
|
]);
|
|
|
|
if ($reviewAssignment->getReviewFormId()) {
|
|
// Retrieve review form
|
|
$context = $request->getContext();
|
|
$reviewFormElementDao = DAORegistry::getDAO('ReviewFormElementDAO'); /** @var ReviewFormElementDAO $reviewFormElementDao */
|
|
$reviewFormElements = $reviewFormElementDao->getByReviewFormId($reviewAssignment->getReviewFormId());
|
|
$reviewFormResponseDao = DAORegistry::getDAO('ReviewFormResponseDAO'); /** @var ReviewFormResponseDAO $reviewFormResponseDao */
|
|
$reviewFormResponses = $reviewFormResponseDao->getReviewReviewFormResponseValues($reviewAssignment->getId());
|
|
$reviewFormDao = DAORegistry::getDAO('ReviewFormDAO'); /** @var ReviewFormDAO $reviewFormDao */
|
|
$reviewForm = $reviewFormDao->getById($reviewAssignment->getReviewFormId(), Application::getContextAssocType(), $context->getId());
|
|
$templateMgr->assign([
|
|
'reviewForm' => $reviewForm,
|
|
'reviewFormElements' => $reviewFormElements,
|
|
'reviewFormResponses' => $reviewFormResponses,
|
|
'disabled' => true,
|
|
]);
|
|
} else {
|
|
// Retrieve reviewer comments.
|
|
$submissionCommentDao = DAORegistry::getDAO('SubmissionCommentDAO'); /** @var SubmissionCommentDAO $submissionCommentDao */
|
|
$templateMgr->assign([
|
|
'comments' => $submissionCommentDao->getReviewerCommentsByReviewerId($reviewAssignment->getSubmissionId(), null, $reviewAssignment->getId(), true),
|
|
'commentsPrivate' => $submissionCommentDao->getReviewerCommentsByReviewerId($reviewAssignment->getSubmissionId(), null, $reviewAssignment->getId(), false),
|
|
]);
|
|
}
|
|
|
|
|
|
// Render the response.
|
|
return $templateMgr->fetchJson('controllers/grid/users/reviewer/readReview.tpl');
|
|
}
|
|
|
|
/**
|
|
* Send the acknowledgement email, if desired, and trigger a row refresh action.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function thankReviewer($args, $request)
|
|
{
|
|
// Identify the review assignment being updated.
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
|
|
// Form handling
|
|
$thankReviewerForm = new ThankReviewerForm($reviewAssignment);
|
|
$thankReviewerForm->readInputData();
|
|
if ($thankReviewerForm->validate()) {
|
|
$thankReviewerForm->execute();
|
|
$json = DAO::getDataChangedEvent($reviewAssignment->getId());
|
|
// Insert a trivial notification to indicate the reviewer was reminded successfully.
|
|
$currentUser = $request->getUser();
|
|
$notificationMgr = new NotificationManager();
|
|
$messageKey = $thankReviewerForm->getData('skipEmail') ? __('notification.reviewAcknowledged') : __('notification.reviewerThankedEmail');
|
|
$notificationMgr->createTrivialNotification($currentUser->getId(), PKPNotification::NOTIFICATION_TYPE_SUCCESS, ['contents' => $messageKey]);
|
|
} else {
|
|
$json = new JSONMessage(false, __('editor.review.thankReviewerError'));
|
|
}
|
|
|
|
return $json;
|
|
}
|
|
|
|
/**
|
|
* Displays a modal to allow the editor to enter a message to send to the reviewer as a reminder
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage Serialized JSON object
|
|
*/
|
|
public function editReminder($args, $request)
|
|
{
|
|
// Identify the review assignment being updated.
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
|
|
// Initialize form.
|
|
$reviewReminderForm = new ReviewReminderForm($reviewAssignment);
|
|
$reviewReminderForm->initData();
|
|
|
|
// Render form.
|
|
return new JSONMessage(true, $reviewReminderForm->fetch($request));
|
|
}
|
|
|
|
/**
|
|
* Send the reviewer reminder and close the modal
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function sendReminder($args, $request)
|
|
{
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
|
|
// Form handling
|
|
$reviewReminderForm = new ReviewReminderForm($reviewAssignment);
|
|
$reviewReminderForm->readInputData();
|
|
if ($reviewReminderForm->validate()) {
|
|
$reviewReminderForm->execute();
|
|
// Insert a trivial notification to indicate the reviewer was reminded successfully.
|
|
$currentUser = $request->getUser();
|
|
$notificationMgr = new NotificationManager();
|
|
$notificationMgr->createTrivialNotification($currentUser->getId(), PKPNotification::NOTIFICATION_TYPE_SUCCESS, ['contents' => __('notification.sentNotification')]);
|
|
return new JSONMessage(true);
|
|
} else {
|
|
return new JSONMessage(false, __('editor.review.reminderError'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Displays a modal to send an email message to the user.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function sendEmail($args, $request)
|
|
{
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
|
|
|
// Form handling.
|
|
$emailReviewerForm = new EmailReviewerForm($reviewAssignment, $submission);
|
|
if (!$request->isPost()) {
|
|
$emailReviewerForm->initData();
|
|
return new JSONMessage(
|
|
true,
|
|
$emailReviewerForm->fetch(
|
|
$request,
|
|
null,
|
|
false,
|
|
$this->getRequestArgs()
|
|
)
|
|
);
|
|
}
|
|
$emailReviewerForm->readInputData();
|
|
$emailReviewerForm->execute();
|
|
return new JSONMessage(true);
|
|
}
|
|
|
|
|
|
/**
|
|
* Displays a modal containing history for the review assignment.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function reviewHistory($args, $request)
|
|
{
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
|
|
$templateMgr = TemplateManager::getManager($request);
|
|
$dates = [
|
|
'common.assigned' => $reviewAssignment->getDateAssigned(),
|
|
'common.notified' => $reviewAssignment->getDateNotified(),
|
|
'common.reminder' => $reviewAssignment->getDateReminded(),
|
|
'common.confirm' => $reviewAssignment->getDateConfirmed(),
|
|
'common.completed' => $reviewAssignment->getDateCompleted(),
|
|
'common.acknowledged' => $reviewAssignment->getDateAcknowledged(),
|
|
];
|
|
asort($dates);
|
|
$templateMgr->assign('dates', $dates);
|
|
|
|
return $templateMgr->fetchJson('workflow/reviewHistory.tpl');
|
|
}
|
|
|
|
|
|
/**
|
|
* Displays a modal containing the gossip values for a reviewer
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function gossip($args, $request)
|
|
{
|
|
$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
|
|
$user = Repo::user()->get($reviewAssignment->getReviewerId(), true);
|
|
|
|
// Check that the current user is specifically allowed to access gossip for
|
|
// this user
|
|
$canCurrentUserGossip = Repo::user()->canCurrentUserGossip($user->getId());
|
|
if (!$canCurrentUserGossip) {
|
|
return new JSONMessage(false, __('user.authorization.roleBasedAccessDenied'));
|
|
}
|
|
|
|
$requestArgs = array_merge($this->getRequestArgs(), ['reviewAssignmentId' => $reviewAssignment->getId()]);
|
|
$reviewerGossipForm = new ReviewerGossipForm($user, $requestArgs);
|
|
|
|
// View form
|
|
if (!$request->isPost()) {
|
|
return new JSONMessage(true, $reviewerGossipForm->fetch($request));
|
|
}
|
|
|
|
// Execute form
|
|
$reviewerGossipForm->readInputData();
|
|
if ($reviewerGossipForm->validate()) {
|
|
$reviewerGossipForm->execute();
|
|
return new JSONMessage(true);
|
|
}
|
|
|
|
return new JSONMessage(false, __('user.authorization.roleBasedAccessDenied'));
|
|
}
|
|
|
|
|
|
/**
|
|
* Fetches an email template's message body and returns it via AJAX.
|
|
*/
|
|
public function fetchTemplateBody(array $args, PKPRequest $request): ?JSONMessage
|
|
{
|
|
$context = $request->getContext();
|
|
$mailable = new class ([$context, $this->getSubmission()]) extends Mailable {
|
|
use Sender;
|
|
};
|
|
$template = Repo::emailTemplate()->getByKey($context->getId(), $request->getUserVar('template'));
|
|
|
|
if (!$template) {
|
|
return null;
|
|
}
|
|
|
|
$user = $request->getUser();
|
|
$mailable->sender($user);
|
|
$mailable->addData([
|
|
'messageToReviewer' => __('reviewer.step1.requestBoilerplate'),
|
|
'abstractTermIfEnabled' => ($this->getSubmission()->getLocalizedAbstract() == '' ? '' : __('common.abstract')), // Deprecated; for OJS 2.x templates
|
|
]);
|
|
|
|
$body = Mail::compileParams($template->getLocalizedData('body'), $mailable->getData(Locale::getLocale()));
|
|
|
|
return new JSONMessage(true, $body);
|
|
}
|
|
|
|
|
|
//
|
|
// Private helper methods
|
|
//
|
|
/**
|
|
* Return a fetched reviewer form data in string.
|
|
*
|
|
* @param array $args
|
|
* @param Request $request
|
|
*
|
|
* @return string
|
|
*/
|
|
public function _fetchReviewerForm($args, $request)
|
|
{
|
|
$selectionType = $request->getUserVar('selectionType');
|
|
assert(!empty($selectionType));
|
|
$formClassName = $this->_getReviewerFormClassName($selectionType);
|
|
$userRoles = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES);
|
|
|
|
// Form handling.
|
|
$reviewerForm = new $formClassName($this->getSubmission(), $this->getReviewRound());
|
|
$reviewerForm->initData();
|
|
$reviewerForm->setUserRoles($userRoles);
|
|
|
|
return $reviewerForm->fetch($request);
|
|
}
|
|
|
|
/**
|
|
* Get the name of ReviewerForm class for the current selection type.
|
|
*
|
|
* @param string $selectionType (const)
|
|
*
|
|
* @return string Form class name
|
|
*/
|
|
public function _getReviewerFormClassName($selectionType)
|
|
{
|
|
switch ($selectionType) {
|
|
case self::REVIEWER_SELECT_ADVANCED_SEARCH:
|
|
return '\PKP\controllers\grid\users\reviewer\form\AdvancedSearchReviewerForm';
|
|
case self::REVIEWER_SELECT_CREATE:
|
|
return '\PKP\controllers\grid\users\reviewer\form\CreateReviewerForm';
|
|
case self::REVIEWER_SELECT_ENROLL_EXISTING:
|
|
return '\PKP\controllers\grid\users\reviewer\form\EnrollExistingReviewerForm';
|
|
}
|
|
assert(false);
|
|
}
|
|
|
|
/**
|
|
* Get operations that need a review assignment policy.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function _getReviewAssignmentOps()
|
|
{
|
|
// Define operations that need a review assignment policy.
|
|
return [
|
|
'readReview',
|
|
'reviewHistory',
|
|
'reviewRead',
|
|
'editThankReviewer',
|
|
'thankReviewer',
|
|
'editReminder',
|
|
'sendReminder',
|
|
'unassignReviewer',
|
|
'updateUnassignReviewer',
|
|
'reinstateReviewer',
|
|
'updateReinstateReviewer',
|
|
'resendRequestReviewer',
|
|
'updateResendRequestReviewer',
|
|
'sendEmail',
|
|
'unconsiderReview',
|
|
'editReview',
|
|
'updateReview',
|
|
'gossip'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get operations that need a review round policy.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function _getReviewRoundOps()
|
|
{
|
|
// Define operations that need a review round policy.
|
|
return [
|
|
'fetchGrid', 'fetchRow', 'showReviewerForm', 'reloadReviewerForm',
|
|
'createReviewer', 'enrollReviewer', 'updateReviewer',
|
|
'getUsersNotAssignedAsReviewers',
|
|
'fetchTemplateBody'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get operations that an author is not allowed to access regardless of review
|
|
* type.
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function _getAuthorDeniedOps()
|
|
{
|
|
return [
|
|
'showReviewerForm',
|
|
'reloadReviewerForm',
|
|
'createReviewer',
|
|
'enrollReviewer',
|
|
'updateReviewer',
|
|
'getUsersNotAssignedAsReviewers',
|
|
'fetchTemplateBody',
|
|
'editThankReviewer',
|
|
'thankReviewer',
|
|
'editReminder',
|
|
'sendReminder',
|
|
'unassignReviewer', 'updateUnassignReviewer',
|
|
'reinstateReviewer', 'updateReinstateReviewer',
|
|
'resendRequestReviewer', 'updateResendRequestReviewer',
|
|
'unconsiderReview',
|
|
'editReview', 'updateReview',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get additional operations that an author is not allowed to access when the
|
|
* review type is anonymous or double-anonymous.
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function _getAuthorDeniedAnonymousOps()
|
|
{
|
|
return [
|
|
'readReview',
|
|
'reviewHistory',
|
|
'reviewRead',
|
|
'sendEmail',
|
|
'gossip',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Creates and sends email to the reviewer
|
|
*/
|
|
protected function createMail(Mailable $mailable, string $emailBody, EmailTemplate $template, User $sender, User $reviewer): void
|
|
{
|
|
if ($subject = $template->getLocalizedData('subject')) {
|
|
$mailable->subject($subject);
|
|
}
|
|
|
|
$mailable
|
|
->body($emailBody)
|
|
->sender($sender)
|
|
->recipients([$reviewer]);
|
|
|
|
try {
|
|
Mail::send($mailable);
|
|
} catch (TransportException $e) {
|
|
$notificationMgr = new PKPNotificationManager();
|
|
$notificationMgr->createTrivialNotification(
|
|
$sender->getId(),
|
|
PKPNotification::NOTIFICATION_TYPE_ERROR,
|
|
['contents' => __('email.compose.error')]
|
|
);
|
|
trigger_error($e->getMessage(), E_USER_WARNING);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!PKP_STRICT_MODE) {
|
|
class_alias('\PKP\controllers\grid\users\reviewer\PKPReviewerGridHandler', '\PKPReviewerGridHandler');
|
|
foreach ([
|
|
'REVIEWER_SELECT_ADVANCED_SEARCH',
|
|
'REVIEWER_SELECT_CREATE',
|
|
'REVIEWER_SELECT_ENROLL_EXISTING',
|
|
] as $constantName) {
|
|
define($constantName, constant('\PKPReviewerGridHandler::' . $constantName));
|
|
}
|
|
}
|