first commit
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file jobs/email/EditorialReminder.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 EditorialReminder
|
||||
*
|
||||
* @ingroup jobs
|
||||
*
|
||||
* @brief Class to handle a job to send an editorial reminder
|
||||
*/
|
||||
|
||||
namespace PKP\jobs\email;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\core\Services;
|
||||
use APP\facades\Repo;
|
||||
use APP\notification\Notification;
|
||||
use APP\notification\NotificationManager;
|
||||
use APP\submission\Submission;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use PKP\context\Context;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\facades\Locale;
|
||||
use PKP\jobs\BaseJob;
|
||||
use PKP\mail\mailables\EditorialReminder as MailablesEditorialReminder;
|
||||
use PKP\notification\NotificationSubscriptionSettingsDAO;
|
||||
use PKP\notification\PKPNotification;
|
||||
use PKP\submission\reviewRound\ReviewRound;
|
||||
use PKP\submission\reviewRound\ReviewRoundDAO;
|
||||
use PKP\user\User;
|
||||
use PKP\workflow\WorkflowStageDAO;
|
||||
|
||||
class EditorialReminder extends BaseJob
|
||||
{
|
||||
protected int $editorId;
|
||||
protected int $contextId;
|
||||
|
||||
public function __construct(int $editorId, int $contextId)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->editorId = $editorId;
|
||||
$this->contextId = $contextId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
if (!$this->isSubscribed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var Context $context */
|
||||
$context = Services::get('context')->get($this->contextId);
|
||||
$editor = Repo::user()->get($this->editorId);
|
||||
|
||||
// Don't use the request locale because this job is
|
||||
// run during a scheduled task
|
||||
$requestLocale = Locale::getLocale();
|
||||
Locale::setLocale($this->getLocale($editor, $context));
|
||||
|
||||
$submissionIds = Repo::submission()
|
||||
->getCollector()
|
||||
->assignedTo([$this->editorId])
|
||||
->filterByContextIds([$this->contextId])
|
||||
->filterByStatus([Submission::STATUS_QUEUED])
|
||||
->filterByIncomplete(false)
|
||||
->getIds();
|
||||
|
||||
$outstanding = [];
|
||||
$submissions = [];
|
||||
|
||||
/** @var int $submissionId */
|
||||
foreach ($submissionIds as $submissionId) {
|
||||
$submission = Repo::submission()->get($submissionId);
|
||||
$submissions[$submissionId] = $submission;
|
||||
|
||||
if ($submission->getData('stageId') == WORKFLOW_STAGE_ID_SUBMISSION) {
|
||||
$outstanding[$submissionId] = __('editor.submission.status.waitingInitialReview');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($submission->getData('stageId'), [WORKFLOW_STAGE_ID_INTERNAL_REVIEW, WORKFLOW_STAGE_ID_EXTERNAL_REVIEW])) {
|
||||
/** @var ReviewRoundDAO $reviewRoundDao */
|
||||
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO');
|
||||
$reviewRound = $reviewRoundDao->getLastReviewRoundBySubmissionId($submission->getId(), $submission->getData('stageId'));
|
||||
|
||||
if ($reviewRound->getStatus() === ReviewRound::REVIEW_ROUND_STATUS_PENDING_REVIEWERS) {
|
||||
$outstanding[$submissionId] = __('editor.submission.roundStatus.pendingReviewers');
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($reviewRound->getStatus() === ReviewRound::REVIEW_ROUND_STATUS_REVIEWS_COMPLETED) {
|
||||
$outstanding[$submissionId] = __('editor.submission.roundStatus.reviewsCompleted');
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($reviewRound->getStatus() === ReviewRound::REVIEW_ROUND_STATUS_REVIEWS_OVERDUE) {
|
||||
$outstanding[$submissionId] = __('editor.submission.roundStatus.reviewOverdue');
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($reviewRound->getStatus() === ReviewRound::REVIEW_ROUND_STATUS_REVISIONS_SUBMITTED) {
|
||||
$outstanding[$submissionId] = __('editor.submission.roundStatus.revisionsSubmitted');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array($submission->getData('stageId'), [WORKFLOW_STAGE_ID_EDITING, WORKFLOW_STAGE_ID_PRODUCTION])) {
|
||||
$lastActivityTimestamp = strtotime($submission->getData('dateLastActivity'));
|
||||
if ($lastActivityTimestamp < strtotime('+30 days')) {
|
||||
/** @var WorkflowStageDAO $workflowStageDao */
|
||||
$workflowStageDao = DAORegistry::getDAO('WorkflowStageDAO');
|
||||
$outstanding[$submissionId] = __(
|
||||
'editor.submission.status.inactiveDaysInStage',
|
||||
[
|
||||
'days' => 30,
|
||||
'stage' => __($workflowStageDao->getTranslationKeyFromId($submission->getData('stageId')))
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($outstanding) > 20) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($outstanding)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Context or user was removed since job was created, or the user was disabled
|
||||
if (!$context || !$editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
$notificationManager = new NotificationManager();
|
||||
$notification = $notificationManager->createNotification(
|
||||
Application::get()->getRequest(),
|
||||
$this->editorId,
|
||||
PKPNotification::NOTIFICATION_TYPE_EDITORIAL_REMINDER,
|
||||
$this->contextId
|
||||
);
|
||||
|
||||
$mailable = new MailablesEditorialReminder($context);
|
||||
$emailTemplate = Repo::emailTemplate()->getByKey($context->getId(), $mailable::getEmailTemplateKey());
|
||||
|
||||
$mailable
|
||||
->setOutstandingTasks($outstanding, $submissions, $submissionIds->count())
|
||||
->from($context->getContactEmail(), $context->getLocalizedName(Locale::getLocale()))
|
||||
->recipients([$editor])
|
||||
->subject($emailTemplate->getLocalizedData('subject'))
|
||||
->body($emailTemplate->getLocalizedData('body'))
|
||||
->allowUnsubscribe($notification);
|
||||
|
||||
Mail::send($mailable);
|
||||
|
||||
// Restore the current locale after the email is sent
|
||||
Locale::setLocale($requestLocale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this editor subscribed to this email?
|
||||
*/
|
||||
protected function isSubscribed(): bool
|
||||
{
|
||||
/** @var NotificationSubscriptionSettingsDAO $notificationSubscriptionSettingsDao */
|
||||
$notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO');
|
||||
$blockedEmails = $notificationSubscriptionSettingsDao->getNotificationSubscriptionSettings('blocked_emailed_notification', $this->editorId, $this->contextId);
|
||||
return !in_array(Notification::NOTIFICATION_TYPE_EDITORIAL_REMINDER, $blockedEmails);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the locale to use with this email
|
||||
*
|
||||
* Returns the context's primary locale, or the first locale
|
||||
* supported by the context and the user.
|
||||
*
|
||||
* @return string Locale key. Example: en
|
||||
*/
|
||||
protected function getLocale(User $editor, Context $context): string
|
||||
{
|
||||
$locale = $context->getPrimaryLocale();
|
||||
|
||||
// A user's locales may not be an array due to bug with data structure
|
||||
// See: https://github.com/pkp/pkp-lib/issues/8023
|
||||
if ($editor->getLocales() === false) {
|
||||
return $locale;
|
||||
}
|
||||
|
||||
$locales = array_intersect($editor->getLocales(), $context->getSupportedLocales());
|
||||
if (!empty($locales) && !in_array($context->getPrimaryLocale(), $locales)) {
|
||||
$locale = $locales[0];
|
||||
}
|
||||
|
||||
return $locale;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user