263 lines
9.8 KiB
PHP
263 lines
9.8 KiB
PHP
<?php
|
|
/**
|
|
* @file classes/mailable/Repository.php
|
|
*
|
|
* Copyright (c) 2014-2022 Simon Fraser University
|
|
* Copyright (c) 2000-2022 John Willinsky
|
|
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
|
*
|
|
* @class Repository
|
|
*
|
|
* @brief A repository to find and edit Mailables.
|
|
*/
|
|
|
|
namespace PKP\mail;
|
|
|
|
use APP\core\Application;
|
|
use APP\facades\Repo;
|
|
use Illuminate\Support\Collection;
|
|
use PKP\context\Context;
|
|
use PKP\core\PKPString;
|
|
use PKP\mail\mailables\DecisionNotifyOtherAuthors;
|
|
use PKP\mail\mailables\EditReviewNotify;
|
|
use PKP\mail\mailables\ReviewCompleteNotifyEditors;
|
|
use PKP\mail\mailables\StatisticsReportNotify;
|
|
use PKP\mail\mailables\SubmissionAcknowledgement;
|
|
use PKP\mail\mailables\SubmissionAcknowledgementNotAuthor;
|
|
use PKP\mail\mailables\SubmissionNeedsEditor;
|
|
use PKP\mail\mailables\SubmissionSavedForLater;
|
|
use PKP\mail\traits\Configurable;
|
|
use PKP\plugins\Hook;
|
|
|
|
class Repository
|
|
{
|
|
/**
|
|
* Get a list of mailables
|
|
*
|
|
* @param string $searchPhrase Only include mailables with a name or description matching this search phrase
|
|
* @param ?bool $includeDisabled Whether or not to include mailables not used in this context, based on the context settings
|
|
*
|
|
* @return Collection<int,string> The fully-qualified class name of each mailable
|
|
*/
|
|
public function getMany(
|
|
Context $context,
|
|
?string $searchPhrase = null,
|
|
?bool $includeDisabled = false,
|
|
?bool $includeConfigurableOnly = false
|
|
): Collection
|
|
{
|
|
$mailables = $this->map();
|
|
Hook::call('Mailer::Mailables', [$mailables, $context]);
|
|
|
|
return $mailables
|
|
->filter(fn (string $class) => !$searchPhrase || $this->containsSearchPhrase($class, $searchPhrase))
|
|
->filter(function (string $class) use ($context, $includeDisabled) {
|
|
return $includeDisabled || $this->isMailableEnabled($class, $context);
|
|
})
|
|
->filter(function (string $class) use ($context, $includeConfigurableOnly) {
|
|
return !$includeConfigurableOnly || $this->isMailableConfigurable($class, $context);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Simple check if mailable's name and description contains a search phrase
|
|
* doesn't look up in associated email templates
|
|
*
|
|
* @param string $className The fully-qualified class name of the Mailable
|
|
*/
|
|
protected function containsSearchPhrase(string $className, string $searchPhrase): bool
|
|
{
|
|
$searchPhrase = PKPString::strtolower($searchPhrase);
|
|
|
|
/** @var Mailable $className */
|
|
return str_contains(PKPString::strtolower($className::getName()), $searchPhrase) ||
|
|
str_contains(PKPString::strtolower($className::getDescription()), $searchPhrase);
|
|
}
|
|
|
|
/**
|
|
* Get a mailable by its email template key
|
|
*
|
|
* @return ?string The fully-qualified class name of the mailable
|
|
*/
|
|
public function get(string $emailTemplateKey, Context $context): ?string
|
|
{
|
|
/** @var ?string $mailable */
|
|
$mailable = $this->getMany($context)
|
|
->first(fn (string $mailable) => $mailable::getEmailTemplateKey() === $emailTemplateKey);
|
|
|
|
if (!$mailable) {
|
|
return null;
|
|
}
|
|
|
|
return $mailable;
|
|
}
|
|
|
|
/**
|
|
* Get a summary of a mailable's properties
|
|
*/
|
|
public function summarizeMailable(string $class): array
|
|
{
|
|
$dataDescriptions = $class::getDataDescriptions();
|
|
ksort($dataDescriptions);
|
|
|
|
return [
|
|
'_href' => Application::get()->getRequest()->getDispatcher()->url(
|
|
Application::get()->getRequest(),
|
|
Application::ROUTE_API,
|
|
Application::get()->getRequest()->getContext()->getPath(),
|
|
'mailables/' . $class::getEmailTemplateKey(),
|
|
),
|
|
'dataDescriptions' => $dataDescriptions,
|
|
'description' => $class::getDescription(),
|
|
'emailTemplateKey' => $class::getEmailTemplateKey(),
|
|
'fromRoleIds' => $class::getFromRoleIds(),
|
|
'groupIds' => $class::getGroupIds(),
|
|
'name' => $class::getName(),
|
|
'supportsTemplates' => $class::getSupportsTemplates(),
|
|
'toRoleIds' => $class::getToRoleIds(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get a full description of a mailable's properties, including any
|
|
* assigned email templates
|
|
*/
|
|
public function describeMailable(string $class, int $contextId): array
|
|
{
|
|
$data = $this->summarizeMailable($class);
|
|
|
|
if (!$class::getSupportsTemplates()) {
|
|
$data['emailTemplates'] = [];
|
|
} else {
|
|
$templates = Repo::emailTemplate()
|
|
->getCollector($contextId)
|
|
->alternateTo([$class::getEmailTemplateKey()])
|
|
->getMany();
|
|
|
|
$defaultTemplate = Repo::emailTemplate()->getByKey($contextId, $class::getEmailTemplateKey());
|
|
|
|
$data['emailTemplates'] = Repo::emailTemplate()
|
|
->getSchemaMap()
|
|
->summarizeMany(
|
|
collect(
|
|
array_merge(
|
|
[$defaultTemplate],
|
|
$templates->values()->toArray()
|
|
)
|
|
)
|
|
)
|
|
->values();
|
|
}
|
|
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Check if a mailable is enabled on this context
|
|
*/
|
|
protected function isMailableEnabled(string $class, Context $context): bool
|
|
{
|
|
if ($class === StatisticsReportNotify::class) {
|
|
return (bool) $context->getData('editorialStatsEmail');
|
|
} elseif (in_array($class, [SubmissionAcknowledgement::class, SubmissionAcknowledgementNotAuthor::class])) {
|
|
$setting = $context->getData('submissionAcknowledgement');
|
|
if ($setting === Context::SUBMISSION_ACKNOWLEDGEMENT_ALL_AUTHORS) {
|
|
return true;
|
|
} elseif ($setting === Context::SUBMISSION_ACKNOWLEDGEMENT_OFF) {
|
|
return false;
|
|
} elseif ($class === SubmissionAcknowledgementNotAuthor::class) {
|
|
return false;
|
|
}
|
|
return true;
|
|
} elseif ($class === DecisionNotifyOtherAuthors::class) {
|
|
return $context->getData('notifyAllAuthors');
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Check if mailable can be configured
|
|
*/
|
|
protected function isMailableConfigurable(string $class, Context $context): bool
|
|
{
|
|
if (!in_array(Configurable::class, class_uses_recursive($class))) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Mailables may not have associated email templates due to pkp/pkp-lib#9109 and pkp/pkp-lib#9217,
|
|
* don't allow to configure them
|
|
*/
|
|
if (in_array($class, [
|
|
EditReviewNotify::class,
|
|
ReviewCompleteNotifyEditors::class,
|
|
SubmissionSavedForLater::class,
|
|
SubmissionNeedsEditor::class,
|
|
])) {
|
|
$template = Repo::emailTemplate()->getByKey($context->getId(), $class::getEmailTemplateKey());
|
|
if (!$template) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Get the mailables used in this app
|
|
*/
|
|
public function map(): Collection
|
|
{
|
|
return collect([
|
|
mailables\AnnouncementNotify::class,
|
|
mailables\DecisionAcceptNotifyAuthor::class,
|
|
mailables\DecisionBackFromCopyeditingNotifyAuthor::class,
|
|
mailables\DecisionBackFromProductionNotifyAuthor::class,
|
|
mailables\DecisionCancelReviewRoundNotifyAuthor::class,
|
|
mailables\DecisionDeclineNotifyAuthor::class,
|
|
mailables\DecisionInitialDeclineNotifyAuthor::class,
|
|
mailables\DecisionNewReviewRoundNotifyAuthor::class,
|
|
mailables\DecisionNotifyOtherAuthors::class,
|
|
mailables\DecisionNotifyReviewer::class,
|
|
mailables\DecisionRequestRevisionsNotifyAuthor::class,
|
|
mailables\DecisionResubmitNotifyAuthor::class,
|
|
mailables\DecisionRevertDeclineNotifyAuthor::class,
|
|
mailables\DecisionRevertInitialDeclineNotifyAuthor::class,
|
|
mailables\DecisionSendExternalReviewNotifyAuthor::class,
|
|
mailables\DecisionSendToProductionNotifyAuthor::class,
|
|
mailables\DecisionSkipExternalReviewNotifyAuthor::class,
|
|
mailables\DiscussionCopyediting::class,
|
|
mailables\DiscussionProduction::class,
|
|
mailables\DiscussionReview::class,
|
|
mailables\DiscussionSubmission::class,
|
|
mailables\EditorAssigned::class,
|
|
mailables\EditReviewNotify::class,
|
|
mailables\EditorialReminder::class,
|
|
mailables\PasswordResetRequested::class,
|
|
mailables\PublicationVersionNotify::class,
|
|
mailables\RecommendationNotifyEditors::class,
|
|
mailables\ReviewAcknowledgement::class,
|
|
mailables\ReviewCompleteNotifyEditors::class,
|
|
mailables\ReviewConfirm::class,
|
|
mailables\ReviewDecline::class,
|
|
mailables\ReviewRemind::class,
|
|
mailables\ReviewRemindAuto::class,
|
|
mailables\ReviewRequest::class,
|
|
mailables\ReviewRequestSubsequent::class,
|
|
mailables\ReviewResponseRemindAuto::class,
|
|
mailables\ReviewerRegister::class,
|
|
mailables\ReviewerReinstate::class,
|
|
mailables\ReviewerResendRequest::class,
|
|
mailables\ReviewerUnassign::class,
|
|
mailables\RevisedVersionNotify::class,
|
|
mailables\StatisticsReportNotify::class,
|
|
mailables\SubmissionAcknowledgement::class,
|
|
mailables\SubmissionAcknowledgementNotAuthor::class,
|
|
mailables\UserCreated::class,
|
|
mailables\ValidateEmailContext::class,
|
|
mailables\ValidateEmailSite::class,
|
|
]);
|
|
}
|
|
}
|