first commit
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/submission/reviewer/ReviewerAction.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ReviewerAction
|
||||
*
|
||||
* @ingroup submission
|
||||
*
|
||||
* @brief ReviewerAction class.
|
||||
*/
|
||||
|
||||
namespace PKP\submission\reviewer;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use APP\log\event\SubmissionEventLogEntry;
|
||||
use APP\notification\NotificationManager;
|
||||
use APP\submission\Submission;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use PKP\context\Context;
|
||||
use PKP\core\Core;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\log\SubmissionEmailLogDAO;
|
||||
use PKP\log\SubmissionEmailLogEntry;
|
||||
use PKP\mail\mailables\ReviewConfirm;
|
||||
use PKP\mail\mailables\ReviewDecline;
|
||||
use PKP\notification\PKPNotification;
|
||||
use PKP\plugins\Hook;
|
||||
use PKP\security\Role;
|
||||
use PKP\security\Validation;
|
||||
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
|
||||
{
|
||||
//
|
||||
// Actions.
|
||||
//
|
||||
/**
|
||||
* Records whether the reviewer accepts the review assignment.
|
||||
*/
|
||||
public function confirmReview(
|
||||
PKPRequest $request,
|
||||
ReviewAssignment $reviewAssignment,
|
||||
Submission $submission,
|
||||
bool $decline,
|
||||
?string $emailText = null
|
||||
): void {
|
||||
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
|
||||
$reviewer = Repo::user()->get($reviewAssignment->getReviewerId());
|
||||
if (!isset($reviewer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only confirm the review for the reviewer if
|
||||
// he has not previously done so.
|
||||
if ($reviewAssignment->getDateConfirmed() == null) {
|
||||
$mailable = $this->getResponseEmail($submission, $reviewAssignment, $decline, $emailText);
|
||||
Hook::call('ReviewerAction::confirmReview', [$request, $submission, $mailable, $decline]);
|
||||
|
||||
if (!empty($mailable->to)) {
|
||||
try {
|
||||
Mail::send($mailable);
|
||||
$submissionEmailLogDao = DAORegistry::getDAO('SubmissionEmailLogDAO'); /** @var SubmissionEmailLogDAO $submissionEmailLogDao */
|
||||
$submissionEmailLogDao->logMailable(
|
||||
$decline ? SubmissionEmailLogEntry::SUBMISSION_EMAIL_REVIEW_DECLINE : SubmissionEmailLogEntry::SUBMISSION_EMAIL_REVIEW_CONFIRM,
|
||||
$mailable,
|
||||
$submission,
|
||||
$mailable->getSenderUser()
|
||||
);
|
||||
} catch (TransportException $e) {
|
||||
$notificationMgr = new NotificationManager();
|
||||
$notificationMgr->createTrivialNotification(
|
||||
$request->getUser()->getId(),
|
||||
PKPNotification::NOTIFICATION_TYPE_ERROR,
|
||||
['contents' => __('email.compose.error')]
|
||||
);
|
||||
trigger_error($e->getMessage(), E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
$reviewAssignment->setDateReminded(null);
|
||||
$reviewAssignment->setReminderWasAutomatic(0);
|
||||
$reviewAssignment->setDeclined($decline);
|
||||
$reviewAssignment->setDateConfirmed(Core::getCurrentDate());
|
||||
$reviewAssignment->stampModified();
|
||||
$reviewAssignmentDao->updateObject($reviewAssignment);
|
||||
|
||||
// Add log
|
||||
$eventLog = Repo::eventLog()->newDataObject([
|
||||
'assocType' => PKPApplication::ASSOC_TYPE_SUBMISSION,
|
||||
'assocId' => $submission->getId(),
|
||||
'eventType' => $decline ? SubmissionEventLogEntry::SUBMISSION_LOG_REVIEW_DECLINE : SubmissionEventLogEntry::SUBMISSION_LOG_REVIEW_ACCEPT,
|
||||
'userId' => Validation::loggedInAs() ?? $request->getUser()->getId(),
|
||||
'message' => $decline ? 'log.review.reviewDeclined' : 'log.review.reviewAccepted',
|
||||
'isTranslate' => 0,
|
||||
'dateLogged' => Core::getCurrentDate(),
|
||||
'reviewAssignmentId' => $reviewAssignment->getId(),
|
||||
'reviewerName' => $reviewer->getFullName(),
|
||||
'submissionId' => $reviewAssignment->getSubmissionId(),
|
||||
'round' => $reviewAssignment->getRound()
|
||||
]);
|
||||
Repo::eventLog()->add($eventLog);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reviewer response email template.
|
||||
*/
|
||||
public function getResponseEmail(
|
||||
PKPSubmission $submission,
|
||||
ReviewAssignment $reviewAssignment,
|
||||
bool $decline,
|
||||
?string $emailText
|
||||
): ReviewConfirm|ReviewDecline {
|
||||
$context = Application::getContextDAO()->getById($submission->getData('contextId')); /** @var Context $context */
|
||||
|
||||
$mailable = $decline ?
|
||||
new ReviewDecline($submission, $reviewAssignment, $context) :
|
||||
new ReviewConfirm($submission, $reviewAssignment, $context);
|
||||
|
||||
// Get reviewer
|
||||
$reviewer = Repo::user()->get($reviewAssignment->getReviewerId());
|
||||
$mailable->sender($reviewer);
|
||||
$mailable->replyTo($reviewer->getEmail(), $reviewer->getFullName());
|
||||
|
||||
// Get editorial contact name
|
||||
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */
|
||||
$stageAssignments = $stageAssignmentDao->getBySubmissionAndStageId($submission->getId(), $reviewAssignment->getStageId());
|
||||
$recipients = [];
|
||||
while ($stageAssignment = $stageAssignments->next()) {
|
||||
$userGroup = Repo::userGroup()->get($stageAssignment->getUserGroupId());
|
||||
if (!in_array($userGroup->getRoleId(), [Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$recipients[] = Repo::user()->get($stageAssignment->getUserId());
|
||||
}
|
||||
|
||||
// Create dummy user if no one assigned
|
||||
if (empty($recipients)) {
|
||||
$contextUser = Repo::user()->getUserFromContextContact($context);
|
||||
if ($contextUser->getData('email')) {
|
||||
$recipients[] = $contextUser;
|
||||
}
|
||||
}
|
||||
|
||||
$mailable->recipients($recipients);
|
||||
|
||||
// Set email body and subject
|
||||
$template = Repo::emailTemplate()->getByKey($context->getId(), $mailable->getEmailTemplateKey());
|
||||
$emailText ? $mailable->body($emailText) : $mailable->body($template->getLocalizedData('body'));
|
||||
$mailable->subject($template->getLocalizedData('subject'));
|
||||
|
||||
return $mailable;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\submission\reviewer\ReviewerAction', '\ReviewerAction');
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/submission/reviewer/form/PKPReviewerReviewStep1Form.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class PKPReviewerReviewStep1Form
|
||||
*
|
||||
* @ingroup submission_reviewer_form
|
||||
*
|
||||
* @brief Form for Step 1 of a review.
|
||||
*/
|
||||
|
||||
namespace PKP\submission\reviewer\form;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\controllers\confirmationModal\linkAction\ViewCompetingInterestGuidelinesLinkAction;
|
||||
use PKP\controllers\modals\review\ReviewerViewMetadataLinkAction;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\linkAction\LinkAction;
|
||||
use PKP\linkAction\request\AjaxModal;
|
||||
use PKP\linkAction\request\ConfirmationModal;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
use PKP\submission\reviewer\ReviewerAction;
|
||||
|
||||
class PKPReviewerReviewStep1Form extends ReviewerReviewForm
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct(PKPRequest $request, Submission $reviewSubmission, ReviewAssignment $reviewAssignment)
|
||||
{
|
||||
parent::__construct($request, $reviewSubmission, $reviewAssignment, 1);
|
||||
$context = $request->getContext();
|
||||
if (!$reviewAssignment->getDateConfirmed() && $context->getData('privacyStatement')) {
|
||||
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'privacyConsent', 'required', 'user.profile.form.privacyConsentRequired'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Implement protected template methods from Form
|
||||
//
|
||||
/**
|
||||
* @copydoc ReviewerReviewForm::fetch()
|
||||
*
|
||||
* @param null|mixed $template
|
||||
*/
|
||||
public function fetch($request, $template = null, $display = false)
|
||||
{
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$context = $request->getContext();
|
||||
|
||||
// Add submission parameters.
|
||||
$reviewAssignment = $this->getReviewAssignment();
|
||||
|
||||
$templateMgr->assign('reviewerCompetingInterests', $reviewAssignment->getCompetingInterests());
|
||||
|
||||
// Add review assignment.
|
||||
$templateMgr->assign([
|
||||
'reviewAssignment' => $reviewAssignment,
|
||||
'reviewRoundId' => $reviewAssignment->getReviewRoundId(),
|
||||
'restrictReviewerFileAccess' => $context->getData('restrictReviewerFileAccess'),
|
||||
'reviewMethod' => __($reviewAssignment->getReviewMethodKey()),
|
||||
]);
|
||||
|
||||
// Add reviewer request text.
|
||||
$templateMgr->assign('reviewerRequest', __('reviewer.step1.requestBoilerplate'));
|
||||
|
||||
//
|
||||
// Assign the link actions
|
||||
//
|
||||
|
||||
// "View metadata" action.
|
||||
$viewMetadataLinkAction = new ReviewerViewMetadataLinkAction($request, $reviewAssignment->getSubmissionId(), $reviewAssignment->getId());
|
||||
$templateMgr->assign('viewMetadataAction', $viewMetadataLinkAction);
|
||||
|
||||
// include the confirmation modal for competing interests if the context has them.
|
||||
if ($context->getLocalizedData('competingInterests') != '') {
|
||||
$competingInterestsAction = new ViewCompetingInterestGuidelinesLinkAction($request);
|
||||
$templateMgr->assign('competingInterestsAction', $competingInterestsAction);
|
||||
}
|
||||
// Instantiate the view review guidelines confirmation modal.
|
||||
$aboutDueDateAction = new LinkAction(
|
||||
'viewReviewGuidelines',
|
||||
new ConfirmationModal(
|
||||
__('reviewer.aboutDueDates.text'),
|
||||
__('reviewer.aboutDueDates'),
|
||||
'modal_information',
|
||||
null,
|
||||
'',
|
||||
false
|
||||
),
|
||||
__('reviewer.aboutDueDates')
|
||||
);
|
||||
|
||||
$templateMgr->assign('aboutDueDatesAction', $aboutDueDateAction);
|
||||
|
||||
$declineReviewLinkAction = new LinkAction(
|
||||
'declineReview',
|
||||
new AjaxModal(
|
||||
$request->url(null, null, 'showDeclineReview', $reviewAssignment->getSubmissionId()),
|
||||
__('reviewer.submission.declineReview')
|
||||
)
|
||||
);
|
||||
$templateMgr->assign('declineReviewAction', $declineReviewLinkAction);
|
||||
|
||||
return parent::fetch($request, $template, $display);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Form::readInputData()
|
||||
*/
|
||||
public function readInputData()
|
||||
{
|
||||
$this->readUserVars(['competingInterestOption', 'reviewerCompetingInterests', 'privacyConsent']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Form::execute()
|
||||
*/
|
||||
public function execute(...$functionParams)
|
||||
{
|
||||
$reviewAssignment = $this->getReviewAssignment();
|
||||
$reviewSubmission = $this->getReviewSubmission();
|
||||
|
||||
// Set competing interests.
|
||||
if ($this->getData('competingInterestOption') == 'hasCompetingInterests') {
|
||||
$reviewAssignment->setCompetingInterests($this->request->getUserVar('reviewerCompetingInterests'));
|
||||
} else {
|
||||
$reviewAssignment->setCompetingInterests(null);
|
||||
}
|
||||
|
||||
// Set review to next step.
|
||||
$this->updateReviewStepAndSaveSubmission($reviewAssignment);
|
||||
|
||||
// if the reviewer has not previously confirmed the review, then
|
||||
// Set that the reviewer has accepted the review.
|
||||
if (!$reviewAssignment->getDateConfirmed()) {
|
||||
$reviewerAction = new ReviewerAction();
|
||||
$reviewerAction->confirmReview($this->request, $reviewAssignment, $reviewSubmission, false);
|
||||
}
|
||||
|
||||
parent::execute(...$functionParams);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\submission\reviewer\form\PKPReviewerReviewStep1Form', '\PKPReviewerReviewStep1Form');
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/submission/reviewer/form/PKPReviewerReviewStep2Form.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class PKPReviewerReviewStep2Form
|
||||
*
|
||||
* @ingroup submission_reviewer_form
|
||||
*
|
||||
* @brief Form for Step 2 of a review.
|
||||
*/
|
||||
|
||||
namespace PKP\submission\reviewer\form;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class PKPReviewerReviewStep2Form extends ReviewerReviewForm
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct(PKPRequest $request, Submission $reviewSubmission, ReviewAssignment $reviewAssignment)
|
||||
{
|
||||
parent::__construct($request, $reviewSubmission, $reviewAssignment, 2);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Implement protected template methods from Form
|
||||
//
|
||||
/**
|
||||
* @copydoc ReviewerReviewForm::fetch()
|
||||
*
|
||||
* @param null|mixed $template
|
||||
*/
|
||||
public function fetch($request, $template = null, $display = false)
|
||||
{
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$context = $this->request->getContext();
|
||||
|
||||
$reviewAssignment = $this->getReviewAssignment();
|
||||
$reviewerGuidelines = $context->getLocalizedData($reviewAssignment->getStageId() == WORKFLOW_STAGE_ID_INTERNAL_REVIEW ? 'internalReviewGuidelines' : 'reviewGuidelines');
|
||||
if (empty($reviewerGuidelines)) {
|
||||
$reviewerGuidelines = __('reviewer.submission.noGuidelines');
|
||||
}
|
||||
$templateMgr->assign('reviewerGuidelines', $reviewerGuidelines);
|
||||
|
||||
return parent::fetch($request, $template, $display);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see Form::execute()
|
||||
*/
|
||||
public function execute(...$functionParams)
|
||||
{
|
||||
// Set review to next step.
|
||||
$this->updateReviewStepAndSaveSubmission($this->getReviewAssignment());
|
||||
|
||||
parent::execute(...$functionParams);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\submission\reviewer\form\PKPReviewerReviewStep2Form', '\PKPReviewerReviewStep2Form');
|
||||
}
|
||||
@@ -0,0 +1,406 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/submission/reviewer/form/PKPReviewerReviewStep3Form.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class PKPReviewerReviewStep3Form
|
||||
*
|
||||
* @ingroup submission_reviewer_form
|
||||
*
|
||||
* @brief Form for Step 3 of a review.
|
||||
*/
|
||||
|
||||
namespace PKP\submission\reviewer\form;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use APP\notification\NotificationManager;
|
||||
use APP\submission\Submission;
|
||||
use APP\template\TemplateManager;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use PKP\controllers\confirmationModal\linkAction\ViewReviewGuidelinesLinkAction;
|
||||
use PKP\core\Core;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\log\event\PKPSubmissionEventLogEntry;
|
||||
use PKP\mail\mailables\ReviewCompleteNotifyEditors;
|
||||
use PKP\notification\NotificationDAO;
|
||||
use PKP\notification\NotificationSubscriptionSettingsDAO;
|
||||
use PKP\notification\PKPNotification;
|
||||
use PKP\reviewForm\ReviewFormDAO;
|
||||
use PKP\reviewForm\ReviewFormElement;
|
||||
use PKP\reviewForm\ReviewFormElementDAO;
|
||||
use PKP\reviewForm\ReviewFormResponse;
|
||||
use PKP\reviewForm\ReviewFormResponseDAO;
|
||||
use PKP\security\Role;
|
||||
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;
|
||||
|
||||
class PKPReviewerReviewStep3Form extends ReviewerReviewForm
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct(PKPRequest $request, Submission $reviewSubmission, ReviewAssignment $reviewAssignment)
|
||||
{
|
||||
parent::__construct($request, $reviewSubmission, $reviewAssignment, 3);
|
||||
|
||||
// Validation checks for this form
|
||||
$reviewFormElementDao = DAORegistry::getDAO('ReviewFormElementDAO'); /** @var ReviewFormElementDAO $reviewFormElementDao */
|
||||
$requiredReviewFormElementIds = $reviewFormElementDao->getRequiredReviewFormElementIds($reviewAssignment->getReviewFormId());
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'reviewFormResponses', 'required', 'reviewer.submission.reviewFormResponse.form.responseRequired', function ($reviewFormResponses) use ($requiredReviewFormElementIds) {
|
||||
foreach ($requiredReviewFormElementIds as $requiredReviewFormElementId) {
|
||||
if (!isset($reviewFormResponses[$requiredReviewFormElementId]) || $reviewFormResponses[$requiredReviewFormElementId] == '') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc ReviewerReviewForm::initData
|
||||
*/
|
||||
public function initData()
|
||||
{
|
||||
$reviewAssignment = $this->getReviewAssignment();
|
||||
|
||||
// Retrieve most recent reviewer comments, one private, one public.
|
||||
$submissionCommentDao = DAORegistry::getDAO('SubmissionCommentDAO'); /** @var SubmissionCommentDAO $submissionCommentDao */
|
||||
|
||||
$submissionComments = $submissionCommentDao->getReviewerCommentsByReviewerId($reviewAssignment->getSubmissionId(), $reviewAssignment->getReviewerId(), $reviewAssignment->getId(), true);
|
||||
$submissionComment = $submissionComments->next();
|
||||
$this->setData('comments', $submissionComment ? $submissionComment->getComments() : '');
|
||||
|
||||
$submissionCommentsPrivate = $submissionCommentDao->getReviewerCommentsByReviewerId($reviewAssignment->getSubmissionId(), $reviewAssignment->getReviewerId(), $reviewAssignment->getId(), false);
|
||||
$submissionCommentPrivate = $submissionCommentsPrivate->next();
|
||||
$this->setData('commentsPrivate', $submissionCommentPrivate ? $submissionCommentPrivate->getComments() : '');
|
||||
|
||||
parent::initData();
|
||||
}
|
||||
|
||||
//
|
||||
// Implement protected template methods from Form
|
||||
//
|
||||
/**
|
||||
* @see Form::readInputData()
|
||||
*/
|
||||
public function readInputData()
|
||||
{
|
||||
$this->readUserVars(
|
||||
['reviewFormResponses', 'comments', 'recommendation', 'commentsPrivate']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc ReviewerReviewForm::fetch()
|
||||
*
|
||||
* @param null|mixed $template
|
||||
*/
|
||||
public function fetch($request, $template = null, $display = false)
|
||||
{
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$reviewAssignment = $this->getReviewAssignment();
|
||||
|
||||
// Assign the objects and data to the template.
|
||||
$context = $this->request->getContext();
|
||||
$templateMgr->assign([
|
||||
'reviewAssignment' => $reviewAssignment,
|
||||
'reviewRoundId' => $reviewAssignment->getReviewRoundId(),
|
||||
'reviewerRecommendationOptions' => ReviewAssignment::getReviewerRecommendationOptions(),
|
||||
]);
|
||||
|
||||
if ($reviewAssignment->getReviewFormId()) {
|
||||
// Get the review form components
|
||||
$reviewFormElementDao = DAORegistry::getDAO('ReviewFormElementDAO'); /** @var ReviewFormElementDAO $reviewFormElementDao */
|
||||
$reviewFormResponseDao = DAORegistry::getDAO('ReviewFormResponseDAO'); /** @var ReviewFormResponseDAO $reviewFormResponseDao */
|
||||
$reviewFormDao = DAORegistry::getDAO('ReviewFormDAO'); /** @var ReviewFormDAO $reviewFormDao */
|
||||
$templateMgr->assign([
|
||||
'reviewForm' => $reviewFormDao->getById($reviewAssignment->getReviewFormId(), Application::getContextAssocType(), $context->getId()),
|
||||
'reviewFormElements' => $reviewFormElementDao->getByReviewFormId($reviewAssignment->getReviewFormId()),
|
||||
'reviewFormResponses' => $reviewFormResponseDao->getReviewReviewFormResponseValues($reviewAssignment->getId()),
|
||||
'disabled' => isset($reviewAssignment) && $reviewAssignment->getDateCompleted() != null,
|
||||
]);
|
||||
}
|
||||
|
||||
//
|
||||
// Assign the link actions
|
||||
//
|
||||
$viewReviewGuidelinesAction = new ViewReviewGuidelinesLinkAction($request, $reviewAssignment->getStageId());
|
||||
if ($viewReviewGuidelinesAction->getGuidelines()) {
|
||||
$templateMgr->assign('viewGuidelinesAction', $viewReviewGuidelinesAction);
|
||||
}
|
||||
|
||||
return parent::fetch($request, $template, $display);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Form::execute()
|
||||
*/
|
||||
public function execute(...$functionParams)
|
||||
{
|
||||
$reviewAssignment = $this->getReviewAssignment();
|
||||
$notificationMgr = new NotificationManager();
|
||||
|
||||
// Save the answers to the review form
|
||||
$this->saveReviewForm($reviewAssignment);
|
||||
|
||||
// Send notification
|
||||
$submission = Repo::submission()->get($reviewAssignment->getSubmissionId());
|
||||
$context = Application::getContextDAO()->getById($submission->getData('contextId'));
|
||||
|
||||
// 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);
|
||||
|
||||
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */
|
||||
$stageAssignments = $stageAssignmentDao->getBySubmissionAndStageId($submission->getId(), $submission->getStageId());
|
||||
|
||||
$receivedList = []; // Avoid sending twice to the same user.
|
||||
|
||||
/** @var NotificationSubscriptionSettingsDAO $notificationSubscriptionSettingsDao */
|
||||
$notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO');
|
||||
while ($stageAssignment = $stageAssignments->next()) {
|
||||
$userId = $stageAssignment->getUserId();
|
||||
$userGroup = Repo::userGroup()->get($stageAssignment->getUserGroupId());
|
||||
|
||||
// Never send reviewer comment notification to users other than managers and editors.
|
||||
if (!in_array($userGroup->getRoleId(), [Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR]) || in_array($userId, $receivedList)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Notify editors
|
||||
$notification = $notificationMgr->createNotification(
|
||||
Application::get()->getRequest(),
|
||||
$userId,
|
||||
PKPNotification::NOTIFICATION_TYPE_REVIEWER_COMMENT,
|
||||
$submission->getContextId(),
|
||||
PKPApplication::ASSOC_TYPE_REVIEW_ASSIGNMENT,
|
||||
$reviewAssignment->getId()
|
||||
);
|
||||
|
||||
// Check if user is subscribed to this type of notification emails
|
||||
if (!$notification || in_array(
|
||||
PKPNotification::NOTIFICATION_TYPE_REVIEWER_COMMENT,
|
||||
$notificationSubscriptionSettingsDao->getNotificationSubscriptionSettings(
|
||||
NotificationSubscriptionSettingsDAO::BLOCKED_EMAIL_NOTIFICATION_KEY,
|
||||
$userId,
|
||||
(int) $context->getId()
|
||||
)
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$mailable = new ReviewCompleteNotifyEditors($context, $submission, $reviewAssignment);
|
||||
$template = Repo::emailTemplate()->getByKey($context->getId(), ReviewCompleteNotifyEditors::getEmailTemplateKey());
|
||||
|
||||
// The template may not exist, see pkp/pkp-lib#9109
|
||||
if (!$template) {
|
||||
$template = Repo::emailTemplate()->getByKey($context->getId(), 'NOTIFICATION');
|
||||
$request = Application::get()->getRequest();
|
||||
$mailable->addData([
|
||||
'notificationContents' => $notificationMgr->getNotificationContents($request, $notification),
|
||||
'notificationUrl' => $notificationMgr->getNotificationUrl($request, $notification),
|
||||
]);
|
||||
}
|
||||
|
||||
$user = Repo::user()->get($userId);
|
||||
$mailable
|
||||
->from($context->getData('contactEmail'), $context->getData('contactName'))
|
||||
->recipients([$user])
|
||||
->subject($template->getLocalizedData('subject'))
|
||||
->body($template->getLocalizedData('body'))
|
||||
->allowUnsubscribe($notification);
|
||||
|
||||
Mail::send($mailable);
|
||||
|
||||
$receivedList[] = $userId;
|
||||
}
|
||||
|
||||
// Remove the task
|
||||
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
|
||||
$notificationDao->deleteByAssoc(
|
||||
PKPApplication::ASSOC_TYPE_REVIEW_ASSIGNMENT,
|
||||
$reviewAssignment->getId(),
|
||||
$reviewAssignment->getReviewerId(),
|
||||
PKPNotification::NOTIFICATION_TYPE_REVIEW_ASSIGNMENT
|
||||
);
|
||||
|
||||
// Add log
|
||||
$reviewer = Repo::user()->get($reviewAssignment->getReviewerId(), true);
|
||||
$eventLog = Repo::eventLog()->newDataObject([
|
||||
'assocType' => PKPApplication::ASSOC_TYPE_SUBMISSION,
|
||||
'assocId' => $submission->getId(),
|
||||
'eventType' => PKPSubmissionEventLogEntry::SUBMISSION_LOG_REVIEW_READY,
|
||||
'userId' => Validation::loggedInAs() ?? Application::get()->getRequest()->getUser()->getId(),
|
||||
'message' => 'log.review.reviewReady',
|
||||
'isTranslated' => false,
|
||||
'dateLogged' => Core::getCurrentDate(),
|
||||
'reviewAssignmentId' => $reviewAssignment->getId(),
|
||||
'reviewerName' => $reviewer->getFullName(),
|
||||
'submissionId' => $reviewAssignment->getSubmissionId(),
|
||||
'round' => $reviewAssignment->getRound()
|
||||
]);
|
||||
Repo::eventLog()->add($eventLog);
|
||||
|
||||
parent::execute(...$functionParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the given answers for later
|
||||
*/
|
||||
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);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the given answers to the review form
|
||||
*
|
||||
* @param ReviewAssignment $reviewAssignment
|
||||
*/
|
||||
public function saveReviewForm($reviewAssignment)
|
||||
{
|
||||
if ($reviewAssignment->getReviewFormId()) {
|
||||
$reviewFormResponseDao = DAORegistry::getDAO('ReviewFormResponseDAO'); /** @var ReviewFormResponseDAO $reviewFormResponseDao */
|
||||
$reviewFormResponses = $this->getData('reviewFormResponses');
|
||||
if (is_array($reviewFormResponses)) {
|
||||
foreach ($reviewFormResponses as $reviewFormElementId => $reviewFormResponseValue) {
|
||||
$reviewFormResponse = $reviewFormResponseDao->getReviewFormResponse($reviewAssignment->getId(), $reviewFormElementId);
|
||||
if (!isset($reviewFormResponse)) {
|
||||
$reviewFormResponse = new ReviewFormResponse();
|
||||
}
|
||||
$reviewFormElementDao = DAORegistry::getDAO('ReviewFormElementDAO'); /** @var ReviewFormElementDAO $reviewFormElementDao */
|
||||
$reviewFormElement = $reviewFormElementDao->getById($reviewFormElementId);
|
||||
$elementType = $reviewFormElement->getElementType();
|
||||
switch ($elementType) {
|
||||
case ReviewFormElement::REVIEW_FORM_ELEMENT_TYPE_SMALL_TEXT_FIELD:
|
||||
case ReviewFormElement::REVIEW_FORM_ELEMENT_TYPE_TEXT_FIELD:
|
||||
case ReviewFormElement::REVIEW_FORM_ELEMENT_TYPE_TEXTAREA:
|
||||
$reviewFormResponse->setResponseType('string');
|
||||
$reviewFormResponse->setValue($reviewFormResponseValue);
|
||||
break;
|
||||
case ReviewFormElement::REVIEW_FORM_ELEMENT_TYPE_RADIO_BUTTONS:
|
||||
case ReviewFormElement::REVIEW_FORM_ELEMENT_TYPE_DROP_DOWN_BOX:
|
||||
$reviewFormResponse->setResponseType('int');
|
||||
$reviewFormResponse->setValue($reviewFormResponseValue);
|
||||
break;
|
||||
case ReviewFormElement::REVIEW_FORM_ELEMENT_TYPE_CHECKBOXES:
|
||||
$reviewFormResponse->setResponseType('object');
|
||||
$reviewFormResponse->setValue($reviewFormResponseValue);
|
||||
break;
|
||||
}
|
||||
if ($reviewFormResponse->getReviewFormElementId() != null && $reviewFormResponse->getReviewId() != null) {
|
||||
$reviewFormResponseDao->updateObject($reviewFormResponse);
|
||||
} else {
|
||||
$reviewFormResponse->setReviewFormElementId($reviewFormElementId);
|
||||
$reviewFormResponse->setReviewId($reviewAssignment->getId());
|
||||
$reviewFormResponseDao->insertObject($reviewFormResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No review form configured. Use the default form.
|
||||
if (strlen($comments = $this->getData('comments')) > 0) {
|
||||
// Create a comment with the review.
|
||||
$submissionCommentDao = DAORegistry::getDAO('SubmissionCommentDAO'); /** @var SubmissionCommentDAO $submissionCommentDao */
|
||||
$submissionComments = $submissionCommentDao->getReviewerCommentsByReviewerId($reviewAssignment->getSubmissionId(), $reviewAssignment->getReviewerId(), $reviewAssignment->getId(), true);
|
||||
$comment = $submissionComments->next();
|
||||
|
||||
if (!isset($comment)) {
|
||||
$comment = $submissionCommentDao->newDataObject();
|
||||
}
|
||||
|
||||
$comment->setCommentType(SubmissionComment::COMMENT_TYPE_PEER_REVIEW);
|
||||
$comment->setRoleId(Role::ROLE_ID_REVIEWER);
|
||||
$comment->setAssocId($reviewAssignment->getId());
|
||||
$comment->setSubmissionId($reviewAssignment->getSubmissionId());
|
||||
$comment->setAuthorId($reviewAssignment->getReviewerId());
|
||||
$comment->setComments($comments);
|
||||
$comment->setCommentTitle('');
|
||||
$comment->setViewable(true);
|
||||
$comment->setDatePosted(Core::getCurrentDate());
|
||||
|
||||
// Save or update
|
||||
if ($comment->getId() != null) {
|
||||
$submissionCommentDao->updateObject($comment);
|
||||
} else {
|
||||
$submissionCommentDao->insertObject($comment);
|
||||
}
|
||||
}
|
||||
unset($comment);
|
||||
|
||||
if (strlen($commentsPrivate = $this->getData('commentsPrivate')) > 0) {
|
||||
// Create a comment with the review.
|
||||
$submissionCommentDao = DAORegistry::getDAO('SubmissionCommentDAO'); /** @var SubmissionCommentDAO $submissionCommentDao */
|
||||
$submissionCommentsPrivate = $submissionCommentDao->getReviewerCommentsByReviewerId($reviewAssignment->getSubmissionId(), $reviewAssignment->getReviewerId(), $reviewAssignment->getId(), false);
|
||||
$comment = $submissionCommentsPrivate->next();
|
||||
|
||||
if (!isset($comment)) {
|
||||
$comment = $submissionCommentDao->newDataObject();
|
||||
}
|
||||
|
||||
$comment->setCommentType(SubmissionComment::COMMENT_TYPE_PEER_REVIEW);
|
||||
$comment->setRoleId(Role::ROLE_ID_REVIEWER);
|
||||
$comment->setAssocId($reviewAssignment->getId());
|
||||
$comment->setSubmissionId($reviewAssignment->getSubmissionId());
|
||||
$comment->setAuthorId($reviewAssignment->getReviewerId());
|
||||
$comment->setComments($commentsPrivate);
|
||||
$comment->setCommentTitle('');
|
||||
$comment->setViewable(false);
|
||||
$comment->setDatePosted(Core::getCurrentDate());
|
||||
|
||||
// Save or update
|
||||
if ($comment->getId() != null) {
|
||||
$submissionCommentDao->updateObject($comment);
|
||||
} else {
|
||||
$submissionCommentDao->insertObject($comment);
|
||||
}
|
||||
}
|
||||
unset($comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\submission\reviewer\form\PKPReviewerReviewStep3Form', '\PKPReviewerReviewStep3Form');
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/submission/reviewer/form/ReviewerReviewForm.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ReviewerReviewForm
|
||||
*
|
||||
* @ingroup submission_reviewer_form
|
||||
*
|
||||
* @brief Base class for reviewer forms.
|
||||
*/
|
||||
|
||||
namespace PKP\submission\reviewer\form;
|
||||
|
||||
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
|
||||
{
|
||||
/** @var Submission The current submission */
|
||||
public Submission $_reviewSubmission;
|
||||
|
||||
/** @var \PKP\submission\reviewAssignment\ReviewAssignment */
|
||||
public $_reviewAssignment;
|
||||
|
||||
/** @var int the current step */
|
||||
public $_step;
|
||||
|
||||
/** @var PKPRequest the request object */
|
||||
public $request;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct(PKPRequest $request, Submission $reviewSubmission, ReviewAssignment $reviewAssignment, int $step)
|
||||
{
|
||||
parent::__construct(sprintf('reviewer/review/step%d.tpl', $step));
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
|
||||
$this->request = $request;
|
||||
$this->_step = (int) $step;
|
||||
$this->_reviewSubmission = $reviewSubmission;
|
||||
$this->_reviewAssignment = $reviewAssignment;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Setters and Getters
|
||||
//
|
||||
/**
|
||||
* Get the reviewer submission.
|
||||
*/
|
||||
public function getReviewSubmission(): Submission
|
||||
{
|
||||
return $this->_reviewSubmission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the review assignment.
|
||||
*/
|
||||
public function getReviewAssignment(): ReviewAssignment
|
||||
{
|
||||
return $this->_reviewAssignment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the review step.
|
||||
*/
|
||||
public function getStep(): int
|
||||
{
|
||||
return $this->_step;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Implement protected template methods from Form
|
||||
//
|
||||
/**
|
||||
* @copydoc Form::fetch()
|
||||
*
|
||||
* @param null|mixed $template
|
||||
*/
|
||||
public function fetch($request, $template = null, $display = false)
|
||||
{
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->assign([
|
||||
'submission' => $this->getReviewSubmission(),
|
||||
'reviewAssignment' => $this->getReviewAssignment(),
|
||||
'reviewIsClosed' => $this->getReviewAssignment()->getDateCompleted() || $this->getReviewAssignment()->getCancelled(),
|
||||
'step' => $this->getStep(),
|
||||
]);
|
||||
return parent::fetch($request, $template, $display);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Protected helper methods
|
||||
//
|
||||
/**
|
||||
* Set the review step of the submission to the given
|
||||
* value if it is not already set to a higher value. Then
|
||||
* update the given reviewer submission.
|
||||
*/
|
||||
public function updateReviewStepAndSaveSubmission(ReviewAssignment $reviewAssignment)
|
||||
{
|
||||
// Update the review step.
|
||||
$nextStep = $this->getStep() + 1;
|
||||
if ($reviewAssignment->getStep() < $nextStep) {
|
||||
$reviewAssignment->setStep($nextStep);
|
||||
}
|
||||
|
||||
// Save the reviewer submission.
|
||||
/** @var ReviewAssignmentDAO */
|
||||
$reviewAssignmentDAO = DAORegistry::getDAO('ReviewAssignmentDAO');
|
||||
$reviewAssignmentDAO->updateObject($reviewAssignment);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\submission\reviewer\form\ReviewerReviewForm', '\ReviewerReviewForm');
|
||||
}
|
||||
Reference in New Issue
Block a user