Skip to content

Commit

Permalink
pkp#9455 Add support for multiple occurrences on review reminders
Browse files Browse the repository at this point in the history
  • Loading branch information
nibou230 committed Nov 30, 2023
1 parent c6a9c9b commit 03167ee
Show file tree
Hide file tree
Showing 61 changed files with 362 additions and 129 deletions.
12 changes: 12 additions & 0 deletions classes/components/forms/context/PKPReviewSetupForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,23 @@ public function __construct($action, $locales, $context)
'value' => $context->getData('numDaysBeforeInviteReminder'),
'size' => 'small',
]))
->addField(new FieldText('numOccurrencesForInviteReminder', [
'label' => __('manager.setup.reviewOptions.occurrencesForInvite'),
'description' => __('manager.setup.reviewOptions.occurrencesForInvite.description'),
'value' => $context->getData('numOccurrencesForInviteReminder'),
'size' => 'small',
]))
->addField(new FieldText('numDaysBeforeSubmitReminder', [
'label' => __('manager.setup.reviewOptions.reminders.submit'),
'description' => __('manager.setup.reviewOptions.reminders.submit.description'),
'value' => $context->getData('numDaysBeforeSubmitReminder'),
'size' => 'small',
]))
->addField(new FieldText('numOccurrencesForSubmitReminder', [
'label' => __('manager.setup.reviewOptions.occurrencesForSubmit'),
'description' => __('manager.setup.reviewOptions.occurrencesForSubmit.description'),
'value' => $context->getData('numOccurrencesForSubmitReminder'),
'size' => 'small',
]));
} else {
$this->addField(new FieldHTML('reviewRemindersDisabled', [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
use PKP\mail\mailables\ReviewerReinstate;
use PKP\mail\mailables\ReviewerResendRequest;
use PKP\mail\mailables\ReviewerUnassign;
use PKP\mail\mailables\ReviewRemindAuto;
use PKP\mail\traits\Sender;
use PKP\notification\NotificationDAO;
use PKP\notification\PKPNotification;
Expand Down Expand Up @@ -979,7 +980,8 @@ public function reviewHistory($args, $request)
$dates = [
'common.assigned' => $reviewAssignment->getDateAssigned(),
'common.notified' => $reviewAssignment->getDateNotified(),
'common.reminder' => $reviewAssignment->getDateReminded(),
'common.invite.reminder' => $reviewAssignment->getDateInviteReminded(),
'common.submit.reminder' => $reviewAssignment->getDateSubmitReminded(),
'common.confirm' => $reviewAssignment->getDateConfirmed(),
'common.completed' => $reviewAssignment->getDateCompleted(),
'common.acknowledged' => $reviewAssignment->getDateAcknowledged(),
Expand Down Expand Up @@ -1045,11 +1047,20 @@ public function fetchTemplateBody(array $args, PKPRequest $request): ?JSONMessag
return null;
}

$reviewAssignment = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT);
if ($mailable instanceof ReviewRemindAuto) {
$occurrence = $reviewAssignment->getCountSubmitReminder();
}
else {
$occurrence = $reviewAssignment->getCountInviteReminder();
}

$user = $request->getUser();
$mailable->sender($user);
$mailable->addData([
'messageToReviewer' => __('reviewer.step1.requestBoilerplate'),
'abstractTermIfEnabled' => ($this->getSubmission()->getLocalizedAbstract() == '' ? '' : __('common.abstract')), // Deprecated; for OJS 2.x templates
'occurrence' => $occurrence,
]);

$body = Mail::compileParams($template->getLocalizedData('body'), $mailable->getData(Locale::getLocale()));
Expand Down
5 changes: 4 additions & 1 deletion classes/migration/install/ReviewsMigration.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ public function up(): void
$table->smallInteger('declined')->default(0);
$table->smallInteger('cancelled')->default(0);
$table->datetime('date_rated')->nullable();
$table->datetime('date_reminded')->nullable();
$table->datetime('date_invite_reminded')->nullable();
$table->smallInteger('count_invite_reminder')->default(0);
$table->datetime('date_submit_reminded')->nullable();
$table->smallInteger('count_submit_reminder')->default(0);
$table->smallInteger('quality')->nullable();

$table->bigInteger('review_round_id');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/**
* @file classes/migration/upgrade/v3_5_0/I9455_ReviewRemindersOccurrences.php
*
* Copyright (c) 2014-2023 Simon Fraser University
* Copyright (c) 2000-2023 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class I9455_ReviewRemindersOccurrences
*/

namespace PKP\migration\upgrade\v3_5_0;

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use PKP\migration\Migration;

class I9455_ReviewRemindersOccurrences extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('review_assignments', function (Blueprint $table) {
$table->after('date_rated', function (Blueprint $table) {
$table->dateTime('date_invite_reminded')->nullable();
$table->smallInteger('count_invite_reminder')->default(0);
});

// Rename date_reminded to date_submit_reminded to avoid confusion with another column with a similar name
$table->renameColumn('date_reminded', 'date_submit_reminded');

$table->after('date_reminded', function (Blueprint $table) {
$table->smallInteger('count_submit_reminder')->default(0);
});
});
}

/**
* Reverse the migration.
*/
public function down(): void
{
Schema::table('review_assignments', function (Blueprint $table) {
$table->dropColumn('date_invite_reminded');
$table->dropColumn('count_invite_reminder');
$table->renameColumn('date_submit_reminded', 'date_reminded');
$table->dropColumn('count_submit_reminder');
});
}
}
5 changes: 4 additions & 1 deletion classes/submission/reviewAssignment/DAO.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ class DAO extends EntityDAO
'declined' => 'declined',
'cancelled' => 'cancelled',
'dateRated' => 'date_rated',
'dateReminded' => 'date_reminded',
'dateInviteReminded' => 'date_invite_reminded',
'countInviteReminder' => 'count_invite_reminder',
'dateSubmitReminded' => 'date_submit_reminded',
'countSubmitReminder' => 'count_submit_reminder',
'quality' => 'quality',
'reviewRoundId' => 'review_round_id',
'stageId' => 'stage_id',
Expand Down
74 changes: 67 additions & 7 deletions classes/submission/reviewAssignment/ReviewAssignment.php
Original file line number Diff line number Diff line change
Expand Up @@ -418,23 +418,83 @@ public function setDateAcknowledged($dateAcknowledged)
}

/**
* Get the reviewer's last reminder date.
* Get the reviewer's last invite reminder date.
*
* @return string
*/
public function getDateReminded()
public function getDateInviteReminded()
{
return $this->getData('dateReminded');
return $this->getData('dateInviteReminded');
}

/**
* Set the reviewer's last reminder date.
* Set the reviewer's last invite reminder date.
*
* @param string $dateReminded
* @param string $dateInviteReminded
*/
public function setDateReminded($dateReminded)
public function setDateInviteReminded($dateInviteReminded)
{
$this->setData('dateReminded', $dateReminded);
$this->setData('dateInviteReminded', $dateInviteReminded);
}

/**
* Get the reviewer's invite reminder count.
*
* @return int
*/
function getCountInviteReminder()
{
return $this->getData('countInviteReminder');
}

/**
* Set the reviewer's invite reminder count.
*
* @param $countInviteReminder int
*/
function setCountInviteReminder($countInviteReminder)
{
$this->setData('countInviteReminder', $countInviteReminder);
}

/**
* Get the reviewer's last submit reminder date.
*
* @return string
*/
function getDateSubmitReminded()
{
return $this->getData('dateSubmitReminded');
}

/**
* Set the reviewer's last submit reminder date.
*
* @param $dateSubmitReminded string
*/
function setDateSubmitReminded($dateSubmitReminded)
{
$this->setData('dateSubmitReminded', $dateSubmitReminded);
}

/**
* Get the reviewer's submit reminder count.
*
* @return int
*/
function getCountSubmitReminder()
{
return $this->getData('countSubmitReminder');
}

/**
* Set the reviewer's submit reminder count.
*
* @param $countSubmitReminder int
*/
function setCountSubmitReminder($countSubmitReminder)
{
$this->setData('countSubmitReminder', $countSubmitReminder);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion classes/submission/reviewer/ReviewerAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public function confirmReview(
}

Repo::reviewAssignment()->edit($reviewAssignment, [
'dateReminded' => null,
'dateSubmitReminded' => null,
'reminderWasAutomatic' => 0,
'declined' => $decline,
'dateConfirmed' => Core::getCurrentDate(),
Expand Down
58 changes: 44 additions & 14 deletions classes/task/ReviewReminder.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,33 @@ public function sendReminder(
$reviewInvitation->dispatch();
}

if ($mailable instanceof ReviewRemindAuto) {
$occurrence = $reviewAssignment->getCountSubmitReminder() + 1;
}
else {
$occurrence = $reviewAssignment->getCountInviteReminder() + 1;
}

// deprecated template variables OJS 2.x
$mailable->addData([
'messageToReviewer' => __('reviewer.step1.requestBoilerplate'),
'abstractTermIfEnabled' => ($submission->getLocalizedAbstract() == '' ? '' : __('common.abstract')),
'occurrence' => $occurrence,
]);

Mail::send($mailable);

if ($mailable instanceof ReviewRemindAuto) {
$dateFieldToUpdate = 'dateSubmitReminded';
$countFieldToUpdate = 'countSubmitReminder';
}
else {
$dateFieldToUpdate = 'dateInviteReminded';
$countFieldToUpdate = 'countInviteReminder';
}
Repo::reviewAssignment()->edit($reviewAssignment, [
'dateReminded' => Core::getCurrentDate(),
$dateFieldToUpdate => Core::getCurrentDate(),
$countFieldToUpdate => $occurrence,
'reminderWasAutomatic' => 1
]);

Expand Down Expand Up @@ -114,12 +131,8 @@ public function executeActions()

$incompleteAssignments = Repo::reviewAssignment()->getCollector()->filterByIsIncomplete(true)->getMany();
$inviteReminderDays = $submitReminderDays = null;
$occurrencesInviteReminder = $occurrencesSubmitReminder = null;
foreach ($incompleteAssignments as $reviewAssignment) {
// Avoid review assignments that a reminder exists for.
if ($reviewAssignment->getDateReminded() !== null) {
continue;
}

// Fetch the submission
if ($submission == null || $submission->getId() != $reviewAssignment->getSubmissionId()) {
unset($submission);
Expand All @@ -141,19 +154,36 @@ public function executeActions()

$inviteReminderDays = $context->getData('numDaysBeforeInviteReminder');
$submitReminderDays = $context->getData('numDaysBeforeSubmitReminder');
$occurrencesInviteReminder = $context->getData('numOccurrencesForInviteReminder');
$occurrencesSubmitReminder = $context->getData('numOccurrencesForSubmitReminder');
}

$mailable = null;
if ($submitReminderDays >= 1 && $reviewAssignment->getDateDue() != null) {
$checkDate = strtotime($reviewAssignment->getDateDue());
if (time() - $checkDate > 60 * 60 * 24 * $submitReminderDays) {
$mailable = new ReviewRemindAuto($context, $submission, $reviewAssignment);

$countSubmitReminder = $reviewAssignment->getCountSubmitReminder();
if ($countSubmitReminder == 0 || !$occurrencesSubmitReminder || $countSubmitReminder < $occurrencesSubmitReminder) {
$dateDue = $reviewAssignment->getDateDue();
if ($submitReminderDays >= 1 && $dateDue) {
$dateSubmitReminded = $reviewAssignment->getDateSubmitReminded();
$time = $dateSubmitReminded ? strtotime($dateSubmitReminded) : strtotime($dateDue);
$checkDate = $time + (60 * 60 * 24 * $submitReminderDays);
if (time() > $checkDate) {
$mailable = new ReviewRemindAuto($context, $submission, $reviewAssignment);
}
}
}
if ($inviteReminderDays >= 1 && $reviewAssignment->getDateConfirmed() == null) {
$checkDate = strtotime($reviewAssignment->getDateResponseDue());
if (time() - $checkDate > 60 * 60 * 24 * $inviteReminderDays) {
$mailable = new ReviewResponseRemindAuto($context, $submission, $reviewAssignment);

$countInviteReminder = $reviewAssignment->getCountInviteReminder();
if ($countInviteReminder == 0 || !$occurrencesInviteReminder || $countInviteReminder < $occurrencesInviteReminder) {
$dateConfirmed = $reviewAssignment->getDateConfirmed();
if ($inviteReminderDays >= 1 && !$dateConfirmed) {
$dateResponseDue = $reviewAssignment->getDateResponseDue();
$dateInviteReminded = $reviewAssignment->getDateInviteReminded();
$time = $dateInviteReminded ? strtotime($dateInviteReminded) : strtotime($dateResponseDue);
$checkDate = $time + (60 * 60 * 24 * $inviteReminderDays);
if (time() > $checkDate) {
$mailable = new ReviewResponseRemindAuto($context, $submission, $reviewAssignment);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public function execute(...$functionArgs)
Repo::eventLog()->add($eventLog);

Repo::reviewAssignment()->edit($reviewAssignment, [
'dateReminded' => Core::getCurrentDate(),
'dateSubmitReminded' => Core::getCurrentDate(),
]);
} catch (TransportException $e) {
$notificationMgr = new NotificationManager();
Expand Down
1 change: 1 addition & 0 deletions controllers/grid/users/reviewer/form/ReviewerForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ protected function getMailable(): ReviewRequest
$mailable->addData([
'messageToReviewer' => __('reviewer.step1.requestBoilerplate'),
'abstractTermIfEnabled' => ($submission->getLocalizedAbstract() == '' ? '' : __('common.abstract')), // Deprecated; for OJS 2.x templates
'occurrence' => 0,
]);

// Remove template variables that haven't been set yet during form initialization
Expand Down
4 changes: 2 additions & 2 deletions locale/ar/common.po
Original file line number Diff line number Diff line change
Expand Up @@ -744,10 +744,10 @@ msgstr "تحديث"
msgid "common.related"
msgstr "ذو صلة"

msgid "common.reminder"
msgid "common.submit.reminder"
msgstr "تذكير"

msgid "common.reminded.date"
msgid "common.submit.reminded.date"
msgstr "مذكَّر بتاريخ: {$dateReminded}"

msgid "common.remote"
Expand Down
4 changes: 2 additions & 2 deletions locale/az/common.po
Original file line number Diff line number Diff line change
Expand Up @@ -1047,10 +1047,10 @@ msgstr "Yenilə"
msgid "common.related"
msgstr "Əlaqəli"

msgid "common.reminder"
msgid "common.submit.reminder"
msgstr "Xatırlatma"

msgid "common.reminded.date"
msgid "common.submit.reminded.date"
msgstr "Xatırladıldı: {$dateReminded}"

msgid "common.remote"
Expand Down
4 changes: 2 additions & 2 deletions locale/bg/common.po
Original file line number Diff line number Diff line change
Expand Up @@ -742,10 +742,10 @@ msgstr "Обновяване"
msgid "common.related"
msgstr "Свързани"

msgid "common.reminder"
msgid "common.submit.reminder"
msgstr "Напомняне"

msgid "common.reminded.date"
msgid "common.submit.reminded.date"
msgstr "Напомняне на дата: {$dateReminded}"

msgid "common.remote"
Expand Down
Loading

0 comments on commit 03167ee

Please sign in to comment.