Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

pkp/pkp-lib#9455 Add support for multiple occurrences on review reminders #9548

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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