first commit
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file mail/EmailData.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 EmailData
|
||||
*
|
||||
* @ingroup mail
|
||||
*
|
||||
* @brief A class to hold data received from common request parameters. Used
|
||||
* with the Composer UI component.
|
||||
*/
|
||||
|
||||
namespace PKP\mail;
|
||||
|
||||
class EmailData
|
||||
{
|
||||
/**
|
||||
* User IDs for the recipients of the email
|
||||
*
|
||||
* @var int[] $recipients
|
||||
*/
|
||||
public array $recipients = [];
|
||||
|
||||
/**
|
||||
* The body of the email
|
||||
*/
|
||||
public string $body;
|
||||
|
||||
/**
|
||||
* The subject of the email
|
||||
*/
|
||||
public string $subject;
|
||||
|
||||
/**
|
||||
* The bcc recipients of this email
|
||||
*/
|
||||
public array $bcc = [];
|
||||
|
||||
/**
|
||||
* The cc recipients of this email
|
||||
*/
|
||||
public array $cc = [];
|
||||
|
||||
/**
|
||||
* Attachments for the email
|
||||
*
|
||||
* Each attachment is an array with id and name properties.
|
||||
* The id key must be one of the Mailable::ATTACHMENT_TEMPORARY_FILE
|
||||
* constants.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* [
|
||||
* ['temporaryFileId' => 1, 'name' => 'example.docx']
|
||||
* ['submissionFileId' => 2, 'name' => 'other.pdf']
|
||||
* ]
|
||||
*
|
||||
* @param array[]
|
||||
*/
|
||||
public array $attachments = [];
|
||||
|
||||
/**
|
||||
* The locale of the email
|
||||
*/
|
||||
public ?string $locale = null;
|
||||
|
||||
/**
|
||||
* Instantiate an object from an assoc array of request data
|
||||
*
|
||||
* @param array $args [
|
||||
*/
|
||||
public function __construct(array $args = [])
|
||||
{
|
||||
foreach ($args as $key => $value) {
|
||||
if (property_exists(EmailData::class, $key)) {
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,628 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/Mailable.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 Mailable
|
||||
*
|
||||
* @ingroup mail
|
||||
*
|
||||
* @brief A base class that represents an email sent in the system.
|
||||
*
|
||||
* This class extends Laravel's mailable class, which provides methods to
|
||||
* configure and send email. This class overrides Laravel's support for message
|
||||
* templates that use blade or markdown templates. Instead, it supports PKP's
|
||||
* email templates system.
|
||||
*
|
||||
* Each email sent by the system which uses an email template should extend
|
||||
* this class. The arguments in the constructor method are used to define the
|
||||
* variables that can be used in the corresponding email templates. This mailable
|
||||
* class provides helper methods to compile the variables and render the email
|
||||
* subject and body.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\mail;
|
||||
|
||||
use APP\core\Services;
|
||||
use APP\decision\Decision;
|
||||
use APP\facades\Repo;
|
||||
use APP\mail\variables\ContextEmailVariable;
|
||||
use APP\mail\variables\SubmissionEmailVariable;
|
||||
use BadMethodCallException;
|
||||
use Exception;
|
||||
use Illuminate\Mail\Mailable as IlluminateMailable;
|
||||
use Illuminate\Support\Collection;
|
||||
use InvalidArgumentException;
|
||||
use PKP\config\Config;
|
||||
use PKP\context\Context;
|
||||
use PKP\context\LibraryFile;
|
||||
use PKP\context\LibraryFileDAO;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\facades\Locale;
|
||||
use PKP\file\TemporaryFileManager;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\mail\variables\DecisionEmailVariable;
|
||||
use PKP\mail\variables\QueuedPaymentEmailVariable;
|
||||
use PKP\mail\variables\RecipientEmailVariable;
|
||||
use PKP\mail\variables\ReviewAssignmentEmailVariable;
|
||||
use PKP\mail\variables\SenderEmailVariable;
|
||||
use PKP\mail\variables\SiteEmailVariable;
|
||||
use PKP\mail\variables\Variable;
|
||||
use PKP\payment\QueuedPayment;
|
||||
use PKP\site\Site;
|
||||
use PKP\submission\PKPSubmission;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
use ReflectionClass;
|
||||
use ReflectionIntersectionType;
|
||||
use ReflectionMethod;
|
||||
use ReflectionNamedType;
|
||||
use ReflectionParameter;
|
||||
use ReflectionType;
|
||||
use ReflectionUnionType;
|
||||
|
||||
class Mailable extends IlluminateMailable
|
||||
{
|
||||
/** Used internally by Illuminate Mailer. Do not touch. */
|
||||
public const DATA_KEY_MESSAGE = 'message';
|
||||
|
||||
/** Data key for the context associated with the Mailable */
|
||||
public const DATA_KEY_CONTEXT = 'context';
|
||||
|
||||
public const GROUP_OTHER = 'other';
|
||||
public const GROUP_SUBMISSION = 'submission';
|
||||
public const GROUP_REVIEW = 'review';
|
||||
public const GROUP_COPYEDITING = 'copyediting';
|
||||
public const GROUP_PRODUCTION = 'production';
|
||||
|
||||
/**
|
||||
* A dummy "role" for the Sent From filters in the mailable UI.
|
||||
*
|
||||
* Mailables sent from this "role" are sent by the system itself.
|
||||
*/
|
||||
public const FROM_SYSTEM = -1;
|
||||
|
||||
public const ATTACHMENT_TEMPORARY_FILE = 'temporaryFileId';
|
||||
public const ATTACHMENT_SUBMISSION_FILE = 'submissionFileId';
|
||||
public const ATTACHMENT_LIBRARY_FILE = 'libraryFileId';
|
||||
|
||||
/** @var string|null Locale key for the name of this Mailable */
|
||||
protected static ?string $name = null;
|
||||
|
||||
/** @var string|null Locale key for the description of this Mailable */
|
||||
protected static ?string $description = null;
|
||||
|
||||
/** @var string|null Key of the default email template key to use with this Mailable */
|
||||
protected static ?string $emailTemplateKey = null;
|
||||
|
||||
/** @var bool Whether users can assign extra email templates to this Mailable */
|
||||
protected static bool $supportsTemplates = false;
|
||||
|
||||
/** @var int[] Mailables are organized into one or more self::GROUP_ */
|
||||
protected static array $groupIds = [self::GROUP_OTHER];
|
||||
|
||||
/** @var bool Whether user can disable this Mailable */
|
||||
protected static bool $canDisable = false;
|
||||
|
||||
/** @var int[] Role ID of the sender, see Role::ROLE_ID_ constants */
|
||||
protected static array $fromRoleIds = [];
|
||||
|
||||
/** @var int[] Role ID of the recipient(s) see Role::ROLE_ID_ constants */
|
||||
protected static array $toRoleIds = [];
|
||||
|
||||
/** @var Variable[] The email variables supported by this mailable */
|
||||
protected array $variables = [];
|
||||
|
||||
/** @var string embedded footer of the email */
|
||||
protected string $footer;
|
||||
|
||||
public function __construct(array $variables = [])
|
||||
{
|
||||
if (!empty($variables)) {
|
||||
$this->setupVariables($variables);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of this Mailable
|
||||
*/
|
||||
public static function getName(): string
|
||||
{
|
||||
return static::$name ? __(static::$name) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the description of this Mailable
|
||||
*/
|
||||
public static function getDescription(): string
|
||||
{
|
||||
return static::$description ? __(static::$description) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the description of this Mailable
|
||||
*/
|
||||
public static function getEmailTemplateKey(): string
|
||||
{
|
||||
return static::$emailTemplateKey ? static::$emailTemplateKey : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether or not this Mailable supports extra email templates
|
||||
*/
|
||||
public static function getSupportsTemplates(): bool
|
||||
{
|
||||
return static::$supportsTemplates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the groups this Mailable is in
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getGroupIds(): array
|
||||
{
|
||||
return static::$groupIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get role IDs of users that are able to send the Mailable
|
||||
*/
|
||||
public static function getFromRoleIds(): array
|
||||
{
|
||||
return static::$fromRoleIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get role IDs of recipients
|
||||
*/
|
||||
public static function getToRoleIds(): array
|
||||
{
|
||||
return static::$toRoleIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add data for this email
|
||||
*/
|
||||
public function addData(array $data): self
|
||||
{
|
||||
$this->viewData = array_merge($this->viewData, $data);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of self::addData()
|
||||
*
|
||||
* @see \Illuminate\Mail\Mailable::with()
|
||||
*
|
||||
* @param null|mixed $value
|
||||
*/
|
||||
public function with($key, $value = null)
|
||||
{
|
||||
if (is_array($key)) {
|
||||
return $this->addData($key);
|
||||
}
|
||||
|
||||
return $this->addData([$key => $value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data for this email
|
||||
*/
|
||||
public function getData(?string $locale = null): array
|
||||
{
|
||||
$this->setData($locale);
|
||||
return $this->viewData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the data for this email
|
||||
*/
|
||||
public function setData(?string $locale = null): void
|
||||
{
|
||||
if (is_null($locale)) {
|
||||
$locale = Locale::getLocale();
|
||||
}
|
||||
foreach ($this->variables as $variable) {
|
||||
$this->viewData = array_merge(
|
||||
$this->viewData,
|
||||
$variable->values($locale)
|
||||
);
|
||||
}
|
||||
|
||||
$this->addFooter($locale); // set the locale for the email footer
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $localeKey
|
||||
*
|
||||
* @throws BadMethodCallException
|
||||
*/
|
||||
public function locale($localeKey)
|
||||
{
|
||||
throw new BadMethodCallException('This method isn\'t supported, data passed to ' . static::class .
|
||||
' should already by localized.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Use instead of the \Illuminate\Mail\Mailable::view() to compile template message's body
|
||||
*
|
||||
* @param string $view HTML string with template variables
|
||||
*/
|
||||
public function body(?string $view): self
|
||||
{
|
||||
return parent::view($view ?? '', []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple From addresses per mailbox-list syntax according to RFC 5322 isn't supported by PHPMailer transport
|
||||
*
|
||||
* @copydoc Illuminate\Mail\Mailable::from()
|
||||
*
|
||||
* @param null|mixed $name
|
||||
*/
|
||||
public function from($address, $name = null)
|
||||
{
|
||||
if (
|
||||
(is_array($address) && count($address) > 1)
|
||||
||
|
||||
($address instanceof Collection && $address->count() > 1)
|
||||
) {
|
||||
trigger_error(
|
||||
'Mailbox-list syntax in the From field isn\'t supported by PHPMailer transport',
|
||||
E_USER_WARNING
|
||||
);
|
||||
}
|
||||
|
||||
return parent::from($address, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Doesn't support Illuminate markdown
|
||||
*
|
||||
* @throws BadMethodCallException
|
||||
*/
|
||||
public function markdown($view, array $data = []): self
|
||||
{
|
||||
throw new BadMethodCallException('Markdown isn\'t supported');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method's implementation is required for Mailable to be sent according to Laravel docs
|
||||
*
|
||||
* @see \Illuminate\Mail\Mailable::send(), https://laravel.com/docs/7.x/mail#writing-mailables
|
||||
*/
|
||||
public function build(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether Mailable can be disabled
|
||||
*/
|
||||
public static function canDisable(): bool
|
||||
{
|
||||
return static::$canDisable;
|
||||
}
|
||||
|
||||
/**
|
||||
* These data keys are reserved and shouldn't be used as email template variable names
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getReservedDataKeys(): array
|
||||
{
|
||||
return [
|
||||
self::DATA_KEY_MESSAGE,
|
||||
self::DATA_KEY_CONTEXT,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Variable class instances associated with the Mailable
|
||||
*
|
||||
* @return Variable[]
|
||||
*/
|
||||
public function getVariables(): array
|
||||
{
|
||||
return $this->variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a footer to the email
|
||||
*
|
||||
* A mailable may override this method to add a footer to the end of the email body before it is sent.
|
||||
* Use this to add an unsubscribe link or append other automated messages.
|
||||
*/
|
||||
protected function addFooter(string $locale): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow data to be passed to the subject
|
||||
*
|
||||
* @param \Illuminate\Mail\Message $message
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function buildSubject($message): self
|
||||
{
|
||||
$this->subject ??= ''; // Allow email with empty subject if not set
|
||||
$withoutTagViewData = collect($this->viewData)
|
||||
->map(fn(mixed $viewableData) => is_string($viewableData) ? strip_tags($viewableData) : $viewableData)
|
||||
->toArray();
|
||||
|
||||
$subject = app('mailer')->compileParams($this->subject, $withoutTagViewData);
|
||||
if (empty($subject)) {
|
||||
trigger_error(
|
||||
'You are sending ' . static::getName() ?? static::class . ' email with empty subject',
|
||||
E_USER_WARNING
|
||||
);
|
||||
}
|
||||
$message->subject($subject);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns variables map associated with a specific object,
|
||||
* variables names should be unique
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected static function templateVariablesMap(): array
|
||||
{
|
||||
return
|
||||
[
|
||||
Context::class => ContextEmailVariable::class,
|
||||
Decision::class => DecisionEmailVariable::class,
|
||||
PKPSubmission::class => SubmissionEmailVariable::class,
|
||||
ReviewAssignment::class => ReviewAssignmentEmailVariable::class,
|
||||
QueuedPayment::class => QueuedPaymentEmailVariable::class,
|
||||
Site::class => SiteEmailVariable::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans arguments to retrieve variables which can be assigned to the template of the email
|
||||
*/
|
||||
protected function setupVariables(array $variables): void
|
||||
{
|
||||
$map = static::templateVariablesMap();
|
||||
foreach ($variables as $variable) {
|
||||
// Pass context as additional data if exists, see pkp/pkp-lib#8204
|
||||
if (is_a($variable, Context::class)) {
|
||||
static::buildViewDataUsing(function () use ($variable) {
|
||||
return [self::DATA_KEY_CONTEXT => $variable];
|
||||
});
|
||||
}
|
||||
|
||||
// Setup variables
|
||||
foreach ($map as $className => $assoc) {
|
||||
if (is_a($variable, $className)) {
|
||||
$this->variables[] = new $assoc($variable, $this);
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
$type = is_object($variable) ? get_class($variable) : gettype($variable);
|
||||
throw new InvalidArgumentException($type . ' argument passed to the ' . static::class . ' constructor isn\'t associated with template variables');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of data variables supported by this mailable
|
||||
* with a description of each variable.
|
||||
*
|
||||
* @return array ['variableName' => description]
|
||||
*/
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$args = static::getParamsClass(static::getConstructor());
|
||||
$map = static::templateVariablesMap();
|
||||
$descriptions = [];
|
||||
|
||||
// check presence of traits in the current class and parents
|
||||
$traits = class_uses(static::class) ?: [];
|
||||
if ($parents = class_parents(static::class)) {
|
||||
foreach ($parents as $parent) {
|
||||
$parentTraits = class_uses($parent);
|
||||
if (!$parentTraits) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$traits = array_merge(
|
||||
$traits,
|
||||
$parentTraits
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($traits)) {
|
||||
if (array_key_exists(Recipient::class, $traits)) {
|
||||
$descriptions = array_merge(
|
||||
$descriptions,
|
||||
RecipientEmailVariable::descriptions(),
|
||||
);
|
||||
}
|
||||
if (array_key_exists(Sender::class, $traits)) {
|
||||
$descriptions = array_merge(
|
||||
$descriptions,
|
||||
SenderEmailVariable::descriptions(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($args as $arg) {
|
||||
$argTypes = static::getTypeNames($arg->getType());
|
||||
foreach ($map as $dataClass => $variableClass) {
|
||||
foreach ($argTypes as $argType) {
|
||||
if (is_a($argType, $dataClass, true)) {
|
||||
$descriptions = array_merge(
|
||||
$descriptions,
|
||||
$variableClass::descriptions()
|
||||
);
|
||||
// An intersection type could be passed in (e.g. Submission & PublishedSubmission), so allow the code check other maps for correctness
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $descriptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the list of type names that might compose a given type
|
||||
* @return string[]
|
||||
*/
|
||||
protected static function getTypeNames(ReflectionType $type): array
|
||||
{
|
||||
if ($type instanceof ReflectionNamedType) {
|
||||
return [$type->getName()];
|
||||
}
|
||||
$isUnion = $type instanceof ReflectionUnionType;
|
||||
if ($isUnion || $type instanceof ReflectionIntersectionType) {
|
||||
$flattenTypes = collect($type->getTypes())
|
||||
->map(fn ($type) => static::getTypeNames($type))
|
||||
->flatten();
|
||||
|
||||
if ($isUnion) {
|
||||
$classTypes = $flattenTypes->filter(fn ($type) => class_exists($type));
|
||||
if ($classTypes->count() > 1) {
|
||||
error_log(new Exception('The Mailable uses constructor arguments to retrieve variables, but union types with more than one "active" class is not well supported, only the first found one will be used. Create a specific mailable for each variant'));
|
||||
// Retrieves the rest of types and only the first class one
|
||||
$flattenTypes = $flattenTypes->diff($classTypes)->add($classTypes->first());
|
||||
}
|
||||
}
|
||||
return $flattenTypes->toArray();
|
||||
|
||||
}
|
||||
throw new Exception('Unexpected subtype ' . $type::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see self::getTemplateVarsDescription
|
||||
*/
|
||||
protected static function getConstructor(): ReflectionMethod
|
||||
{
|
||||
$constructor = (new ReflectionClass(static::class))->getConstructor();
|
||||
if (!$constructor) {
|
||||
throw new BadMethodCallException(static::class . ' requires constructor to be explicitly declared');
|
||||
}
|
||||
|
||||
return $constructor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves arguments of the specified methods
|
||||
*
|
||||
* @see self::getTemplateVarsDescription
|
||||
* @return ReflectionParameter[]
|
||||
*/
|
||||
protected static function getParamsClass(ReflectionMethod $method): array
|
||||
{
|
||||
$params = $method->getParameters();
|
||||
if (empty($params)) {
|
||||
throw new BadMethodCallException(static::class . ' constructor declaration requires at least one argument');
|
||||
}
|
||||
|
||||
foreach ($params as $param) {
|
||||
$type = $param->getType();
|
||||
if (!$type) {
|
||||
throw new BadMethodCallException(static::class . ' constructor argument $' . $param->getName() . ' should be type hinted');
|
||||
}
|
||||
}
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Illuminate\Mail\Mailable::buildView()
|
||||
*/
|
||||
protected function buildView()
|
||||
{
|
||||
$view = parent::buildView();
|
||||
if (!isset($this->footer)) {
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* If it's an array with numerical keys, append footer to the first element;
|
||||
* if a string, just append to the view;
|
||||
* see: Illuminate\Mail\Mailer::parseView()
|
||||
*/
|
||||
if (is_array($view) && isset($view[0])) {
|
||||
return [$view[0] . $this->footer, $view[1]];
|
||||
}
|
||||
|
||||
if (is_string($view)) {
|
||||
return $view . $this->footer;
|
||||
}
|
||||
|
||||
return $view; // $this->html, $this->textView or $this->markdown; see parent::buildView() for details
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a temporary file
|
||||
*/
|
||||
public function attachTemporaryFile(string $id, string $name, int $uploaderId): self
|
||||
{
|
||||
$temporaryFileManager = new TemporaryFileManager();
|
||||
$file = $temporaryFileManager->getFile($id, $uploaderId);
|
||||
if (!$file) {
|
||||
throw new Exception('Tried to attach temporary file ' . $id . ' that does not exist.');
|
||||
}
|
||||
$this->attach($file->getFilePath(), ['as' => $name]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a submission file
|
||||
*/
|
||||
public function attachSubmissionFile(int $id, string $name): self
|
||||
{
|
||||
$submissionFile = Repo::submissionFile()->get($id);
|
||||
if (!$submissionFile) {
|
||||
throw new Exception('Tried to attach submission file ' . $id . ' that does not exist.');
|
||||
}
|
||||
$file = Services::get('file')->get($submissionFile->getData('fileId'));
|
||||
$this->attach(
|
||||
Config::getVar('files', 'files_dir') . '/' . $file->path,
|
||||
[
|
||||
'as' => $name,
|
||||
'mime' => $file->mimetype,
|
||||
]
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a library file
|
||||
*/
|
||||
public function attachLibraryFile(int $id, string $name): self
|
||||
{
|
||||
/** @var LibraryFileDAO $libraryFileDao */
|
||||
$libraryFileDao = DAORegistry::getDAO('LibraryFileDAO');
|
||||
/** @var LibraryFile $file */
|
||||
$file = $libraryFileDao->getById($id);
|
||||
if (!$file) {
|
||||
throw new Exception('Tried to attach library file ' . $id . ' that does not exist.');
|
||||
}
|
||||
$this->attach($file->getFilePath(), ['as' => $name]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a footer, e.g., this may be required to remove personal information like unsubscribe link for logging purposes
|
||||
*/
|
||||
public function removeFooter(): void
|
||||
{
|
||||
$this->footer = '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/Mailer.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 Mailer
|
||||
*
|
||||
* @ingroup mail
|
||||
*
|
||||
* @brief Represents interface to manage emails sending and view
|
||||
*/
|
||||
|
||||
namespace PKP\mail;
|
||||
|
||||
use APP\core\Application;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Contracts\Support\Htmlable;
|
||||
use Illuminate\Mail\Mailer as IlluminateMailer;
|
||||
use Illuminate\Mail\Message;
|
||||
use InvalidArgumentException;
|
||||
use PKP\config\Config;
|
||||
use PKP\observers\events\MessageSendingFromContext;
|
||||
use PKP\observers\events\MessageSendingFromSite;
|
||||
use PKP\site\Site;
|
||||
use Symfony\Component\Mailer\Envelope;
|
||||
use Symfony\Component\Mailer\Exception\TransportException;
|
||||
use Symfony\Component\Mailer\Transport\TransportInterface;
|
||||
use Symfony\Component\Mime\Email;
|
||||
|
||||
class Mailer extends IlluminateMailer
|
||||
{
|
||||
/**
|
||||
* Don't bind Laravel View Service, as it's not implemented
|
||||
*
|
||||
* @var null
|
||||
*/
|
||||
protected $views = null;
|
||||
|
||||
/**
|
||||
* Maximum number of notification emails that can be sent per job
|
||||
*/
|
||||
public const BULK_EMAIL_SIZE_LIMIT = 50;
|
||||
|
||||
/**
|
||||
* Creates new Mailer instance without binding with View
|
||||
*
|
||||
* @copydoc \Illuminate\Mail\Mailer::__construct()
|
||||
*/
|
||||
public function __construct(string $name, TransportInterface $transport, Dispatcher $events = null)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->transport = $transport;
|
||||
$this->events = $events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders email content into HTML string
|
||||
*
|
||||
* @param string|object $view
|
||||
* @param array $data variable => value, 'message' is reserved for the Laravel's Swift Message (Illuminate\Mail\Message)
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @see \Illuminate\Mail\Mailer::renderView()
|
||||
*/
|
||||
protected function renderView($view, $data): string
|
||||
{
|
||||
if ($view instanceof Htmlable) {
|
||||
// return HTML without data compiling
|
||||
return $view->toHtml();
|
||||
}
|
||||
|
||||
if (!is_string($view)) {
|
||||
throw new InvalidArgumentException('View must be instance of ' . Htmlable::class . ' or a string, ' . get_class($view) . ' is given');
|
||||
}
|
||||
|
||||
return $this->compileParams($view, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles email templates by substituting variables with their real values
|
||||
*
|
||||
* @param string $view text or HTML string
|
||||
* @param array $data variables with their values passes ['variable' => value]
|
||||
*
|
||||
* @return string compiled string with substitute variables
|
||||
*/
|
||||
public function compileParams(string $view, array $data): string
|
||||
{
|
||||
$variables = [];
|
||||
$replacements = [];
|
||||
foreach ($data as $key => $value) {
|
||||
// Don't compile pre-set message data variables not belonging to the template
|
||||
if (in_array($key, Mailable::getReservedDataKeys())) {
|
||||
continue;
|
||||
}
|
||||
$variables[] = '/\{\$' . $key . '\}/';
|
||||
$replacements[] = $value;
|
||||
}
|
||||
|
||||
return preg_replace($variables, $replacements, $view);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc IlluminateMailer::send()
|
||||
*
|
||||
* @param null|mixed $callback
|
||||
*/
|
||||
public function send($view, array $data = [], $callback = null)
|
||||
{
|
||||
if (is_a($view, Mailable::class)) {
|
||||
/** @var Mailable $view */
|
||||
$view->setData();
|
||||
}
|
||||
|
||||
// Application is set to sandbox mode and will sent any emails to log
|
||||
if (Config::getVar('general', 'sandbox', false)) {
|
||||
error_log('Application is set to sandbox mode and will sent any emails to log');
|
||||
}
|
||||
|
||||
parent::send($view, $data, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Illuminate Mailer method to provide additional parameters to the event
|
||||
*
|
||||
* @param \Symfony\Component\Mime\Email $message
|
||||
* @param array $data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldSendMessage($message, $data = [])
|
||||
{
|
||||
if (!$this->events) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (array_key_exists(Mailable::DATA_KEY_CONTEXT, $data)) {
|
||||
$context = $data[Mailable::DATA_KEY_CONTEXT];
|
||||
return $this->events->until(new MessageSendingFromContext($context, $message, $data)) !== false;
|
||||
}
|
||||
|
||||
$site = Application::get()->getRequest()->getSite();
|
||||
return $this->events->until(new MessageSendingFromSite($site, $message, $data)) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override method to catch an exception while sending email instance
|
||||
*
|
||||
* @return \Symfony\Component\Mailer\SentMessage|null
|
||||
*/
|
||||
protected function sendSymfonyMessage(Email $message)
|
||||
{
|
||||
$sentMessage = null;
|
||||
try {
|
||||
$sentMessage = $this->transport->send($message, Envelope::create($message));
|
||||
} catch (TransportException $e) {
|
||||
error_log($e->getMessage());
|
||||
}
|
||||
|
||||
return $sentMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Illuminate Mailer method to modify email header
|
||||
*
|
||||
* @copydoc Illuminate\Mail\Mailer::addContent()
|
||||
*/
|
||||
protected function addContent($message, $view, $plain, $raw, $data): void
|
||||
{
|
||||
parent::addContent($message, $view, $plain, $raw, $data);
|
||||
|
||||
$this->setEnvelopeSenderDefault($message, $data);
|
||||
$this->setDmarcCompliantFrom($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets envelope sender, either the default one or from the context settings
|
||||
*/
|
||||
protected function setEnvelopeSenderDefault(Message $message, array $data): void
|
||||
{
|
||||
// Force default site-wide envelope sender if set
|
||||
$configDefaultEnvelopeSender = Config::getVar('email', 'default_envelope_sender');
|
||||
if (Config::getVar('email', 'force_default_envelope_sender') && $configDefaultEnvelopeSender) {
|
||||
$message->sender($configDefaultEnvelopeSender);
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't provide further checks if envelope sender isn't allowed in the config
|
||||
if (!Config::getVar('email', 'allow_envelope_sender')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the sender provided in the context settings
|
||||
$context = $data[Mailable::DATA_KEY_CONTEXT] ?? null;
|
||||
if ($context && $sender = $context->getData('envelopeSender')) {
|
||||
$message->sender($sender);
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally, provide default sender from the config if not specified
|
||||
if (!$message->getSender() && $configDefaultEnvelopeSender) {
|
||||
$message->sender($configDefaultEnvelopeSender);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set DMARC compliant From header field body
|
||||
*/
|
||||
protected function setDmarcCompliantFrom(Message $message): void
|
||||
{
|
||||
if (empty($message->getFrom())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(
|
||||
Config::getVar('email', 'force_default_envelope_sender')
|
||||
&& Config::getVar('email', 'default_envelope_sender')
|
||||
&& Config::getVar('email', 'force_dmarc_compliant_from')
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->promoteFromToReplyTo($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a DMARC compliant RFC5322.From was requested we need to promote the original RFC5322. From into a Reply-to header
|
||||
* and then munge the RFC5322.From
|
||||
*/
|
||||
protected function promoteFromToReplyTo(Message $message): void
|
||||
{
|
||||
$replyToEmails = array_map(fn ($x) => $x->getAddress(), $message->getReplyTo());
|
||||
$fromEmails = array_map(fn ($x) => $x->getAddress(), $message->getFrom());
|
||||
$alreadyExists = array_intersect($replyToEmails, $fromEmails);
|
||||
|
||||
foreach ($message->getFrom() as $address) {
|
||||
if (!in_array($address->getAddress(), $alreadyExists)) {
|
||||
$message->addReplyTo($address);
|
||||
}
|
||||
}
|
||||
|
||||
$site = Application::get()->getRequest()->getSite(); /** @var Site $site **/
|
||||
$dmarcFromName = '';
|
||||
if (Config::getVar('email', 'dmarc_compliant_from_displayname')) {
|
||||
$patterns = ['#%n#', '#%s#'];
|
||||
$replacements = [
|
||||
implode(',', array_map(fn ($x) => $x->getName(), $message->getFrom())),
|
||||
$site->getLocalizedData('title'),
|
||||
];
|
||||
$dmarcFromName = preg_replace($patterns, $replacements, Config::getVar('email', 'dmarc_compliant_from_displayname'));
|
||||
}
|
||||
|
||||
$message->from(Config::getVar('email', 'default_envelope_sender'), $dmarcFromName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
<?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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/AnnouncementNotify.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 AnnouncementNotify
|
||||
*
|
||||
* @brief Email sent to notify users about new announcement
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\announcement\Announcement;
|
||||
use PKP\context\Context;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\facades\Locale;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\mail\traits\Unsubscribe;
|
||||
use PKP\security\Role;
|
||||
|
||||
class AnnouncementNotify extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
use Unsubscribe;
|
||||
|
||||
protected static ?string $name = 'mailable.announcementNotify.name';
|
||||
protected static ?string $description = 'mailable.announcementNotify.description';
|
||||
protected static ?string $emailTemplateKey = 'ANNOUNCEMENT';
|
||||
protected static array $groupIds = [self::GROUP_OTHER];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_READER];
|
||||
|
||||
protected static string $announcementTitle = 'announcementTitle';
|
||||
protected static string $announcementSummary = 'announcementSummary';
|
||||
protected static string $announcementUrl = 'announcementUrl';
|
||||
|
||||
protected Announcement $announcement;
|
||||
protected Context $context;
|
||||
|
||||
public function __construct(Context $context, Announcement $announcement)
|
||||
{
|
||||
parent::__construct(array_slice(func_get_args(), 0, -1));
|
||||
$this->announcement = $announcement;
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add description to a new email template variables
|
||||
*/
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
$variables[static::$announcementTitle] = __('emailTemplate.variable.announcementTitle');
|
||||
$variables[static::$announcementSummary] = __('emailTemplate.variable.announcementSummary');
|
||||
$variables[static::$announcementUrl] = __('emailTemplate.variable.announcementUrl');
|
||||
return $variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set localized email template variables
|
||||
*/
|
||||
public function setData(?string $locale = null): void
|
||||
{
|
||||
parent::setData($locale);
|
||||
if (is_null($locale)) {
|
||||
$locale = Locale::getLocale();
|
||||
}
|
||||
|
||||
$request = Application::get()->getRequest();
|
||||
$dispatcher = $request->getDispatcher();
|
||||
$this->viewData = array_merge(
|
||||
$this->viewData,
|
||||
[
|
||||
static::$announcementTitle => $this->announcement->getData('title', $locale),
|
||||
static::$announcementSummary => $this->announcement->getData('descriptionShort', $locale),
|
||||
static::$announcementUrl => $dispatcher->url(
|
||||
$request,
|
||||
PKPApplication::ROUTE_PAGE,
|
||||
$this->context->getData('urlPath'),
|
||||
'announcement',
|
||||
'view',
|
||||
$this->announcement->getId()
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a footer with unsubscribe link
|
||||
*/
|
||||
protected function addFooter(string $locale): Mailable
|
||||
{
|
||||
$this->setupUnsubscribeFooter($locale, $this->context);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionAcceptNotifyAuthor.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 DecisionAcceptNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when the following decisions is made:
|
||||
* Decision::ACCEPT
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\ReviewerComments;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class DecisionAcceptNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use ReviewerComments;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.decision.accept.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.accept.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_ACCEPT';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
/**
|
||||
* @param array<ReviewAssignment> $reviewAssignments
|
||||
*/
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision, array $reviewAssignments)
|
||||
{
|
||||
parent::__construct(array_slice(func_get_args(), 0, -1));
|
||||
$this->setupReviewerCommentsVariable($reviewAssignments, $submission);
|
||||
}
|
||||
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
return self::addReviewerCommentsDescription($variables);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionBackFromCopyeditingNotifyAuthor.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 DecisionBackFromCopyeditingNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when following decisions are made :
|
||||
* Decision::BACK_FROM_COPYEDITING
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DecisionBackFromCopyeditingNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.decision.backFromCopyediting.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.backFromCopyediting.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_BACK_FROM_COPYEDITING';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_COPYEDITING];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionBackFromProductionNotifyAuthor.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 DecisionBackFromProductionNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when the following decision is made:
|
||||
* Decision::BACK_FROM_PRODUCTION
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DecisionBackFromProductionNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.decision.backToCopyediting.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.backToCopyediting.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_BACK_FROM_PRODUCTION';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_PRODUCTION];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionCancelReviewRoundNotifyAuthor.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 DecisionCancelReviewRoundNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when the following decision is made:
|
||||
* Decision::CANCEL_REVIEW_ROUND
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DecisionCancelReviewRoundNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.decision.cancelReviewRound.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.cancelReviewRound.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_CANCEL_REVIEW_ROUND';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionDeclineNotifyAuthor.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 DecisionDeclineNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when the following decisions are made:
|
||||
* Decision::DECLINE
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\ReviewerComments;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class DecisionDeclineNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use ReviewerComments;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.decision.decline.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.decline.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_DECLINE';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
/**
|
||||
* @param array<ReviewAssignment> $reviewAssignments
|
||||
*/
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision, array $reviewAssignments)
|
||||
{
|
||||
parent::__construct(array_slice(func_get_args(), 0, -1));
|
||||
$this->setupReviewerCommentsVariable($reviewAssignments, $submission);
|
||||
}
|
||||
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
return self::addReviewerCommentsDescription($variables);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionInitialDeclineNotifyAuthor.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 DecisionInitialDeclineNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when the following decision is made
|
||||
* Decision::INITIAL_DECLINE
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DecisionInitialDeclineNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.decision.initialDecline.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.initialDecline.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_INITIAL_DECLINE';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_SUBMISSION];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionNewReviewRoundNotifyAuthor.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 DecisionNewReviewRoundNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when the following decisions are made:
|
||||
* Decision::NEW_EXTERNAL_ROUND
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DecisionNewReviewRoundNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.decision.newReviewRound.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.newReviewRound.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_NEW_ROUND';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionNotifyOtherAuthors.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 DecisionNotifyOtherAuthors
|
||||
*
|
||||
* @brief Email sent to other authors of a submission when an editorial decision
|
||||
* is made. These are authors with metadata records on the publication who are
|
||||
* not assigned as participants to the submission workflow.
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\facades\Locale;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\user\User;
|
||||
|
||||
class DecisionNotifyOtherAuthors extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Sender;
|
||||
|
||||
/** @var string An email variable that contains the message that was sent to the submitting author */
|
||||
public const MESSAGE_TO_SUBMITTING_AUTHOR = 'messageToSubmittingAuthor';
|
||||
public const SUBMITTING_AUTHOR_NAME = 'submittingAuthorName';
|
||||
|
||||
protected static ?string $name = 'mailable.decision.notifyOtherAuthors.name';
|
||||
protected static ?string $description = 'mailable.decision.notifyOtherAuthors.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_NOTIFY_OTHER_AUTHORS';
|
||||
protected static array $groupIds = [
|
||||
self::GROUP_SUBMISSION,
|
||||
self::GROUP_REVIEW,
|
||||
self::GROUP_COPYEDITING,
|
||||
self::GROUP_PRODUCTION,
|
||||
];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
/** @var User[] */
|
||||
protected array $assignedAuthors;
|
||||
|
||||
public function __construct(Context $context, Submission $submission, array $assignedAuthors)
|
||||
{
|
||||
parent::__construct([$context, $submission]);
|
||||
|
||||
$this->assignedAuthors = $assignedAuthors;
|
||||
}
|
||||
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
$variables[self::MESSAGE_TO_SUBMITTING_AUTHOR] = __('mailable.decision.notifyOtherAuthors.variable.message.description');
|
||||
$variables[self::SUBMITTING_AUTHOR_NAME] = __('emailTemplate.variable.submission.submittingAuthorName');
|
||||
return $variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set submitting author name email template variable
|
||||
*/
|
||||
public function setData(?string $locale = null): void
|
||||
{
|
||||
parent::setData($locale);
|
||||
|
||||
if (is_null($locale)) {
|
||||
$locale = Locale::getLocale();
|
||||
}
|
||||
|
||||
$this->viewData[self::SUBMITTING_AUTHOR_NAME] = $this->getSubmittingAuthorName($locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* The name(s) of authors assigned as participants to the
|
||||
* submission workflow.
|
||||
*
|
||||
* Usually this is the submitting author.
|
||||
*/
|
||||
protected function getSubmittingAuthorName(string $locale): string
|
||||
{
|
||||
$authorNames = [];
|
||||
foreach ($this->assignedAuthors as $user) {
|
||||
$authorNames[] = $user->getFullName(true, false, $locale);
|
||||
}
|
||||
return join(__('common.commaListSeparator'), $authorNames);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionNotifyReviewer.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 DecisionNotifyReviewer
|
||||
*
|
||||
* @brief Email sent to the reviewers who have completed a review in the review round
|
||||
* when the following decisions is made:
|
||||
* Decision::ACCEPT
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DecisionNotifyReviewer extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
|
||||
/** @var string An email variable that contains a description of the editorial decision */
|
||||
public const DECISION_DESCRIPTION = 'decisionDescription';
|
||||
|
||||
protected static ?string $name = 'mailable.decision.notifyReviewer.name';
|
||||
protected static ?string $description = 'mailable.decision.notifyReviewer.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_NOTIFY_REVIEWERS';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
protected Decision $decision;
|
||||
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision)
|
||||
{
|
||||
$this->decision = $decision;
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
|
||||
public function getDecision(): Decision
|
||||
{
|
||||
return $this->decision;
|
||||
}
|
||||
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
$variables[self::DECISION_DESCRIPTION] = __('mailable.decision.notifyReviewer.variable.decisionDescription');
|
||||
return $variables;
|
||||
}
|
||||
|
||||
public function setData(?string $locale = null): void
|
||||
{
|
||||
parent::setData($locale);
|
||||
$this->viewData[self::DECISION_DESCRIPTION] = $this->getDecisionDescription($locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a description of the decision to use as an email variable
|
||||
*/
|
||||
protected function getDecisionDescription(?string $locale = null): string
|
||||
{
|
||||
switch ($this->decision->getData('decision')) {
|
||||
case Decision::ACCEPT: return __('mailable.decision.notifyReviewer.variable.decisionDescription.accept', [], $locale);
|
||||
case Decision::DECLINE: return __('mailable.decision.notifyReviewer.variable.decisionDescription.decline', [], $locale);
|
||||
case Decision::PENDING_REVISIONS: return __('mailable.decision.notifyReviewer.variable.decisionDescription.pendingRevisions', [], $locale);
|
||||
case Decision::RESUBMIT: return __('mailable.decision.notifyReviewer.variable.decisionDescription.resubmit', [], $locale);
|
||||
default: return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionRequestRevisionsNotifyAuthor.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 DecisionRequestRevisionsNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when the following decisions are made:
|
||||
* Decision::PENDING_REVISIONS
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\ReviewerComments;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class DecisionRequestRevisionsNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use ReviewerComments;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.decision.requestRevisions.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.requestRevisions.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_REVISIONS';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
/**
|
||||
* @param array<ReviewAssignment> $reviewAssignments
|
||||
*/
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision, array $reviewAssignments)
|
||||
{
|
||||
parent::__construct(array_slice(func_get_args(), 0, -1));
|
||||
$this->setupReviewerCommentsVariable($reviewAssignments, $submission);
|
||||
}
|
||||
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
return self::addReviewerCommentsDescription($variables);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionResubmitNotifyAuthor.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 DecisionResubmitNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when the following decisions are made:
|
||||
* Decision::RESUBMIT
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\ReviewerComments;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class DecisionResubmitNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use ReviewerComments;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.decision.resubmit.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.resubmit.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_RESUBMIT';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
/**
|
||||
* @param array<ReviewAssignment> $reviewAssignments
|
||||
*/
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision, array $reviewAssignments)
|
||||
{
|
||||
parent::__construct(array_slice(func_get_args(), 0, -1));
|
||||
$this->setupReviewerCommentsVariable($reviewAssignments, $submission);
|
||||
}
|
||||
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
return self::addReviewerCommentsDescription($variables);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionRevertDeclineNotifyAuthor.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 DecisionRevertDeclineNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when the following decisions are made:
|
||||
* Decision::DECLINE
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DecisionRevertDeclineNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.decision.revertDecline.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.revertDecline.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_REVERT_DECLINE';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionRevertInitialDeclineNotifyAuthor.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 DecisionRevertInitialDeclineNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when the following decisions are made:
|
||||
* Decision::REVERT_INITIAL_DECLINE
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DecisionRevertInitialDeclineNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.decision.revertInitialDecline.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.revertInitialDecline.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_REVERT_INITIAL_DECLINE';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_SUBMISSION];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionSendExternalReviewNotifyAuthor.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 DecisionSendExternalReviewNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when a the following decisions is made:
|
||||
* Decision::EXTERNAL_REVIEW
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class DecisionSendExternalReviewNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
|
||||
public const REVIEW_TYPE_DESCRIPTION_VARIABLE = 'reviewTypeDescription';
|
||||
|
||||
protected static ?string $name = 'mailable.decision.sendExternalReview.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.sendExternalReview.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_SEND_TO_EXTERNAL';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_SUBMISSION];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
$this->setupReviewTypeVariable($context);
|
||||
}
|
||||
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::getDataDescriptions(),
|
||||
[
|
||||
static::REVIEW_TYPE_DESCRIPTION_VARIABLE => __('emailTemplate.variable.reviewType'),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
protected function setupReviewTypeVariable(Context $context)
|
||||
{
|
||||
switch ($context->getData('defaultReviewMode')) {
|
||||
case ReviewAssignment::SUBMISSION_REVIEW_METHOD_ANONYMOUS:
|
||||
$description = __('emailTemplate.variable.reviewType.anonymous');
|
||||
break;
|
||||
case ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN:
|
||||
$description = __('emailTemplate.variable.reviewType.open');
|
||||
break;
|
||||
default:
|
||||
$description = __('emailTemplate.variable.reviewType.doubleAnonymous');
|
||||
}
|
||||
|
||||
$this->addData([
|
||||
static::REVIEW_TYPE_DESCRIPTION_VARIABLE => $description,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionSendToProductionNotifyAuthor.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 DecisionSendToProductionNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when the following decisions are made:
|
||||
* Decision::SEND_TO_PRODUCTION
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DecisionSendToProductionNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.decision.sendToProduction.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.sendToProduction.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_SEND_TO_PRODUCTION';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_COPYEDITING];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DecisionSkipExternalReviewNotifyAuthor.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 DecisionSkipExternalReviewNotifyAuthor
|
||||
*
|
||||
* @brief Email sent to the author(s) when the following decisions are made:
|
||||
* Decision::SKIP_EXTERNAL_REVIEW
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DecisionSkipExternalReviewNotifyAuthor extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.decision.skipReview.notifyAuthor.name';
|
||||
protected static ?string $description = 'mailable.decision.skipReview.notifyAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_DECISION_SKIP_REVIEW';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_SUBMISSION];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DiscussionCopyediting.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 DiscussionCopyediting
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email sent when a new query is created or a note is added to a query on the copyediting workflow stage
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Discussion;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DiscussionCopyediting extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Sender;
|
||||
use Configurable;
|
||||
use Discussion;
|
||||
|
||||
protected static ?string $name = 'mailable.discussionCopyediting.name';
|
||||
protected static ?string $description = 'mailable.discussionCopyediting.description';
|
||||
protected static ?string $emailTemplateKey = 'DISCUSSION_NOTIFICATION_COPYEDITING';
|
||||
protected static bool $canDisable = true;
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_COPYEDITING];
|
||||
protected static array $fromRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
Role::ROLE_ID_ASSISTANT,
|
||||
Role::ROLE_ID_AUTHOR,
|
||||
];
|
||||
protected static array $toRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
Role::ROLE_ID_ASSISTANT,
|
||||
Role::ROLE_ID_AUTHOR,
|
||||
];
|
||||
|
||||
protected Context $context;
|
||||
|
||||
public function __construct(Context $context, Submission $submission)
|
||||
{
|
||||
parent::__construct([$context, $submission]);
|
||||
$this->context = $context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DiscussionProduction.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 DiscussionProduction
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email sent when a new query is created or a note is added to a query on the production workflow stage
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Discussion;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DiscussionProduction extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Sender;
|
||||
use Configurable;
|
||||
use Discussion;
|
||||
|
||||
protected static ?string $name = 'mailable.discussionProduction.name';
|
||||
protected static ?string $description = 'mailable.discussionProduction.description';
|
||||
protected static ?string $emailTemplateKey = 'DISCUSSION_NOTIFICATION_PRODUCTION';
|
||||
protected static bool $canDisable = true;
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_PRODUCTION];
|
||||
protected static array $fromRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
Role::ROLE_ID_ASSISTANT,
|
||||
Role::ROLE_ID_AUTHOR,
|
||||
];
|
||||
protected static array $toRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
Role::ROLE_ID_ASSISTANT,
|
||||
Role::ROLE_ID_AUTHOR,
|
||||
];
|
||||
|
||||
protected Context $context;
|
||||
|
||||
public function __construct(Context $context, Submission $submission)
|
||||
{
|
||||
parent::__construct([$context, $submission]);
|
||||
$this->context = $context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DiscussionReview.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 DiscussionReview
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email sent when a new query is created or a note is added to a query on the (external) review workflow stage
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Discussion;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DiscussionReview extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Sender;
|
||||
use Configurable;
|
||||
use Discussion;
|
||||
|
||||
protected static ?string $name = 'mailable.discussionReview.name';
|
||||
protected static ?string $description = 'mailable.discussionReview.description';
|
||||
protected static ?string $emailTemplateKey = 'DISCUSSION_NOTIFICATION_REVIEW';
|
||||
protected static bool $canDisable = true;
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
Role::ROLE_ID_ASSISTANT,
|
||||
Role::ROLE_ID_AUTHOR,
|
||||
];
|
||||
protected static array $toRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
Role::ROLE_ID_ASSISTANT,
|
||||
Role::ROLE_ID_AUTHOR,
|
||||
];
|
||||
|
||||
protected Context $context;
|
||||
|
||||
public function __construct(Context $context, Submission $submission)
|
||||
{
|
||||
parent::__construct([$context, $submission]);
|
||||
$this->context = $context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/DiscussionSubmission.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 DiscussionSubmission
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email sent when a new query is created or a note is added to a query on the submission workflow stage
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Discussion;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
|
||||
class DiscussionSubmission extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Sender;
|
||||
use Configurable;
|
||||
use Discussion;
|
||||
|
||||
protected static ?string $name = 'mailable.discussionSubmission.name';
|
||||
protected static ?string $description = 'mailable.discussionSubmission.description';
|
||||
protected static ?string $emailTemplateKey = 'DISCUSSION_NOTIFICATION_SUBMISSION';
|
||||
protected static bool $canDisable = true;
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_SUBMISSION];
|
||||
protected static array $fromRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
Role::ROLE_ID_ASSISTANT,
|
||||
Role::ROLE_ID_AUTHOR,
|
||||
];
|
||||
protected static array $toRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
Role::ROLE_ID_ASSISTANT,
|
||||
Role::ROLE_ID_AUTHOR,
|
||||
];
|
||||
|
||||
protected Context $context;
|
||||
|
||||
public function __construct(Context $context, Submission $submission)
|
||||
{
|
||||
parent::__construct([$context, $submission]);
|
||||
$this->context = $context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/EditReviewNotify.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 EditReviewNotify
|
||||
*
|
||||
* @brief An automatic email sent to the reviewer when the details of their review assignment have been changed
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\mail\traits\Unsubscribe;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class EditReviewNotify extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
use Unsubscribe;
|
||||
|
||||
protected static ?string $name = 'mailable.editReviewNotify.name';
|
||||
protected static ?string $description = 'mailable.editReviewNotify.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEW_EDIT';
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
|
||||
protected Context $context;
|
||||
|
||||
public function __construct(
|
||||
Context $context,
|
||||
Submission $submission,
|
||||
ReviewAssignment $reviewAssignment
|
||||
) {
|
||||
parent::__construct(func_get_args());
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
protected function addFooter(string $locale): self
|
||||
{
|
||||
$this->setupUnsubscribeFooter($locale, $this->context, 'emails.footer.unsubscribe.automated');
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/EditorAssigned.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 EditorAssigned
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email sent to editors assigned to a submission.
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\security\Role;
|
||||
|
||||
class EditorAssigned extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Configurable;
|
||||
|
||||
protected static ?string $name = 'mailable.editorAssigned.name';
|
||||
protected static ?string $description = 'mailable.editorAssigned.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_ASSIGN';
|
||||
protected static array $groupIds = [self::GROUP_SUBMISSION];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR];
|
||||
|
||||
public function __construct(Context $context, Submission $submission)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/EditorialReminder.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 EditorialReminder
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email is sent automatically to an editor to remind them of outstanding tasks
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\publication\Publication;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Unsubscribe;
|
||||
use PKP\security\Role;
|
||||
|
||||
class EditorialReminder extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Unsubscribe;
|
||||
|
||||
public const OUTSTANDING_TASKS = 'outstandingTasks';
|
||||
public const NUMBER_OF_SUBMISSIONS = 'numberOfSubmissions';
|
||||
|
||||
protected static ?string $name = 'mailable.editorialReminder.name';
|
||||
protected static ?string $description = 'mailable.editorialReminder.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITORIAL_REMINDER';
|
||||
protected static array $groupIds = [self::GROUP_OTHER];
|
||||
protected static array $fromRoleIds = [self::FROM_SYSTEM];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
|
||||
protected Context $context;
|
||||
protected array $outstanding = [];
|
||||
|
||||
/** @var Submission[] $submissions */
|
||||
protected array $submissions = [];
|
||||
|
||||
/** @TODO: docblock for $outstanding */
|
||||
public function __construct(Context $context)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {$outstandingTasks} variable
|
||||
*
|
||||
* @TODO docblock params
|
||||
*/
|
||||
public function setOutstandingTasks(array $outstanding, array $submissions, int $numberOfSubmissions): self
|
||||
{
|
||||
$outstandingTasks = [];
|
||||
foreach ($outstanding as $submissionId => $task) {
|
||||
/** @var Submission $submission */
|
||||
$submission = $submissions[$submissionId];
|
||||
/** @var Publication $publication */
|
||||
$publication = $submission->getCurrentPublication();
|
||||
$url = Application::get()->getRequest()->getDispatcher()->url(
|
||||
Application::get()->getRequest(),
|
||||
Application::ROUTE_PAGE,
|
||||
$this->context->getPath(),
|
||||
'workflow',
|
||||
'access',
|
||||
$submission->getId()
|
||||
);
|
||||
|
||||
$outstandingTasks[] = '
|
||||
<tr>
|
||||
<td style="color: red; vertical-align: top; width: 25px;">⬤</td>
|
||||
<td style="vertical-align: top">
|
||||
' . $task . '<br />
|
||||
<a href="' . $url . '">'
|
||||
. $submission->getId()
|
||||
. ' — '
|
||||
. htmlspecialchars($publication->getShortAuthorString())
|
||||
. ' — '
|
||||
. htmlspecialchars($publication->getLocalizedFullTitle(null, 'html'))
|
||||
. '</a><br />
|
||||
<br />
|
||||
</td>
|
||||
</tr>';
|
||||
}
|
||||
|
||||
$this->addData([
|
||||
self::OUTSTANDING_TASKS => '<table>' . join('', $outstandingTasks) . '</table>',
|
||||
self::NUMBER_OF_SUBMISSIONS => $numberOfSubmissions,
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Mailable::getDataDescriptions()
|
||||
*/
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
$variables[static::OUTSTANDING_TASKS] = __('emailTemplate.variable.editorialReminder.outstandingTasks');
|
||||
$variables[static::NUMBER_OF_SUBMISSIONS] = __('emailTemplate.variable.editorialReminder.numberOfSubmissions');
|
||||
return $variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a footer with unsubscribe link
|
||||
*/
|
||||
protected function addFooter(string $locale): Mailable
|
||||
{
|
||||
$this->setupUnsubscribeFooter($locale, $this->context, 'emails.footer.unsubscribe.automated');
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/PasswordResetRequested.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 PasswordResetRequested
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email sent automatically when user requests to reset a password
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\PasswordResetUrl;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\security\Role;
|
||||
use PKP\site\Site;
|
||||
use PKP\user\User;
|
||||
|
||||
class PasswordResetRequested extends Mailable
|
||||
{
|
||||
use Recipient {
|
||||
recipients as recipientsTrait;
|
||||
}
|
||||
use Configurable;
|
||||
use PasswordResetUrl;
|
||||
|
||||
protected static ?string $name = 'mailable.passwordResetRequested.name';
|
||||
protected static ?string $description = 'mailable.passwordResetRequested.description';
|
||||
protected static ?string $emailTemplateKey = 'PASSWORD_RESET_CONFIRM';
|
||||
protected static array $groupIds = [self::GROUP_OTHER];
|
||||
protected static array $fromRoleIds = [self::FROM_SYSTEM];
|
||||
protected static array $toRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
Role::ROLE_ID_ASSISTANT,
|
||||
Role::ROLE_ID_AUTHOR,
|
||||
Role::ROLE_ID_READER,
|
||||
Role::ROLE_ID_REVIEWER,
|
||||
Role::ROLE_ID_SUBSCRIPTION_MANAGER,
|
||||
];
|
||||
|
||||
public function __construct(Site $site)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
return static::addPasswordResetUrlDescription(parent::getDataDescriptions());
|
||||
}
|
||||
|
||||
public function recipients(User $recipient, ?string $locale = null): Mailable
|
||||
{
|
||||
$this->recipientsTrait([$recipient], $locale);
|
||||
$this->setPasswordResetUrl($recipient);
|
||||
|
||||
// See pkp/pkp-lib#9111
|
||||
$this->addData(['lostPasswordUrl' => $this->viewData[self::$passwordResetUrl]]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/PublicationVersionNotify.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 PublicationVersionNotify
|
||||
*
|
||||
* @brief Email is automatically sent to editors assigned to submission when new publication version is created
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Unsubscribe;
|
||||
use PKP\security\Role;
|
||||
|
||||
class PublicationVersionNotify extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Unsubscribe;
|
||||
|
||||
protected static ?string $name = 'mailable.publicationVersionNotify.name';
|
||||
protected static ?string $description = 'mailable.publicationVersionNotify.description';
|
||||
protected static ?string $emailTemplateKey = 'VERSION_CREATED';
|
||||
protected static array $groupIds = [self::GROUP_PRODUCTION];
|
||||
protected static array $fromRoleIds = [self::FROM_SYSTEM];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
|
||||
protected Context $context;
|
||||
|
||||
public function __construct(Context $context, Submission $submission)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
protected function addFooter(string $locale): self
|
||||
{
|
||||
$this->setupUnsubscribeFooter($locale, $this->context);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/RecommendationNotifyEditors.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 RecommendationNotifyEditors
|
||||
*
|
||||
* @brief Message sent to deciding editors when any SUBMISSION_EDITOR_RECOMMEND_*
|
||||
* decision is made.
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\facades\Repo;
|
||||
use APP\submission\Submission;
|
||||
use Exception;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\ReviewerComments;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\mail\variables\RecipientEmailVariable;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class RecommendationNotifyEditors extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient {
|
||||
recipients as traitRecipients;
|
||||
}
|
||||
use ReviewerComments;
|
||||
use Sender;
|
||||
|
||||
public const RECOMMENDATION_VARIABLE = 'recommendation';
|
||||
|
||||
protected static ?string $name = 'mailable.decision.recommendation.notifyEditors.name';
|
||||
protected static ?string $description = 'mailable.decision.recommendation.notifyEditors.description';
|
||||
protected static ?string $emailTemplateKey = 'EDITOR_RECOMMENDATION';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
|
||||
/**
|
||||
* @param array<ReviewAssignment> $reviewAssignments
|
||||
*/
|
||||
public function __construct(Context $context, Submission $submission, Decision $decision, array $reviewAssignments)
|
||||
{
|
||||
parent::__construct(array_slice(func_get_args(), 0, -1));
|
||||
$this->setupRecommendationVariable($decision);
|
||||
$this->setupReviewerCommentsVariable($reviewAssignments, $submission);
|
||||
}
|
||||
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
$variables[static::RECOMMENDATION_VARIABLE] = __('emailTemplate.variable.recommendation');
|
||||
return self::addReviewerCommentsDescription($variables);
|
||||
}
|
||||
|
||||
protected function setupRecommendationVariable(Decision $decision)
|
||||
{
|
||||
$decisionType = Repo::decision()->getDecisionType($decision->getData('decision'));
|
||||
if (!$decisionType || !method_exists($decisionType, 'getRecommendationLabel')) {
|
||||
throw new Exception('Tried to get the recommendation from a decision that does not exist');
|
||||
}
|
||||
$this->addData([
|
||||
static::RECOMMENDATION_VARIABLE => $decisionType->getRecommendationLabel(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function recipients(array $recipients): Mailable
|
||||
{
|
||||
$this->traitRecipients($recipients);
|
||||
|
||||
// See pkp/pkp-lib#9111
|
||||
foreach ($this->variables as $key => $variable) {
|
||||
if (get_class($variable) === RecipientEmailVariable::class) {
|
||||
|
||||
// override including new variable
|
||||
$this->variables[$key] = new class($recipients, $this) extends RecipientEmailVariable
|
||||
{
|
||||
public function values(string $locale): array
|
||||
{
|
||||
$values = parent::values($locale);
|
||||
$values['editors'] = $values[RecipientEmailVariable::RECIPIENT_FULL_NAME];
|
||||
return $values;
|
||||
}
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ReviewAcknowledgement.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 ReviewAcknowledgement
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email sent by a section editor to confirm receipt of a completed review and thank the reviewer
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\PKPSubmission;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class ReviewAcknowledgement extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.reviewAcknowledgement.name';
|
||||
protected static ?string $description = 'mailable.reviewAcknowledgement.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEW_ACK';
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
|
||||
public function __construct(Context $context, PKPSubmission $submission, ReviewAssignment $reviewAssignment)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ReviewCompleteNotifyEditors.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 ReviewCompleteNotifyEditors
|
||||
*
|
||||
* @brief Email is automatically sent to the assigned editors when the reviewer completes the review
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Unsubscribe;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class ReviewCompleteNotifyEditors extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
use Unsubscribe;
|
||||
|
||||
public const REVIEWER_FILES = 'reviewerFiles';
|
||||
|
||||
protected static ?string $name = 'mailable.reviewCompleteNotifyEditors.name';
|
||||
protected static ?string $description = 'mailable.reviewCompleteNotifyEditors.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEW_COMPLETE';
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
|
||||
protected Context $context;
|
||||
|
||||
public function __construct(
|
||||
Context $context,
|
||||
Submission $submission,
|
||||
ReviewAssignment $reviewAssignment
|
||||
) {
|
||||
parent::__construct(func_get_args());
|
||||
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
protected function addFooter(string $locale): self
|
||||
{
|
||||
$this->setupUnsubscribeFooter($locale, $this->context, 'emails.footer.unsubscribe.automated');
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ReviewConfirm.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 ReviewConfirm
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email is sent automatically by a reviewer after accepting review request
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\PKPSubmission;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class ReviewConfirm extends Mailable
|
||||
{
|
||||
use Sender;
|
||||
use Recipient;
|
||||
use Configurable;
|
||||
|
||||
protected static ?string $name = 'mailable.reviewConfirm.name';
|
||||
protected static ?string $description = 'mailable.reviewConfirm.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEW_CONFIRM';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static bool $canDisable = true;
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
|
||||
public function __construct(PKPSubmission $submission, ReviewAssignment $reviewAssignment, Context $context)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ReviewDecline.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 ReviewDecline
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email is sent by a reviewer after declining a review request
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\PKPSubmission;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class ReviewDecline extends Mailable
|
||||
{
|
||||
use Sender;
|
||||
use Recipient;
|
||||
use Configurable;
|
||||
|
||||
protected static ?string $name = 'mailable.reviewDecline.name';
|
||||
protected static ?string $description = 'mailable.reviewDecline.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEW_DECLINE';
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static bool $canDisable = true;
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
|
||||
public function __construct(PKPSubmission $submission, ReviewAssignment $reviewAssignment, Context $context)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ReviewRemind.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 ReviewRemind
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email is sent by an editor to a reviewer to remind about the review request
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\OneClickReviewerAccess;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\mail\variables\ContextEmailVariable;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class ReviewRemind extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use OneClickReviewerAccess;
|
||||
use Sender;
|
||||
use Recipient;
|
||||
|
||||
protected static ?string $name = 'mailable.reviewRemind.name';
|
||||
protected static ?string $description = 'mailable.reviewRemind.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEW_REMIND';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
|
||||
protected Context $context;
|
||||
protected ReviewAssignment $reviewAssignment;
|
||||
|
||||
public function __construct(Context $context, Submission $submission, ReviewAssignment $reviewAssignment)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
|
||||
$this->context = $context;
|
||||
$this->reviewAssignment = $reviewAssignment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the setData method to add the one-click access
|
||||
* URL for the reviewer
|
||||
*/
|
||||
public function setData(?string $locale = null): void
|
||||
{
|
||||
parent::setData($locale);
|
||||
|
||||
$this->setOneClickAccessUrl($this->context, $this->reviewAssignment);
|
||||
|
||||
// See pkp/pkp-lib#9111
|
||||
$this->addData(['lostPasswordUrl' => $this->viewData[ContextEmailVariable::PASSWORD_LOST_URL]]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ReviewRemindAuto.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 ReviewRemindAuto
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email is sent automatically to a reviewer after a due date as a reminder to complete a review
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\OneClickReviewerAccess;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\variables\ContextEmailVariable;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class ReviewRemindAuto extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use OneClickReviewerAccess;
|
||||
use Recipient;
|
||||
|
||||
protected static ?string $name = 'mailable.reviewRemindAuto.name';
|
||||
protected static ?string $description = 'mailable.reviewRemindAuto.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEW_REMIND_AUTO';
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [self::FROM_SYSTEM];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
|
||||
protected Context $context;
|
||||
protected ReviewAssignment $reviewAssignment;
|
||||
|
||||
public function __construct(Context $context, Submission $submission, ReviewAssignment $reviewAssignment)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
|
||||
$this->context = $context;
|
||||
$this->reviewAssignment = $reviewAssignment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the setData method to add the one-click access
|
||||
* URL for the reviewer
|
||||
*/
|
||||
public function setData(?string $locale = null): void
|
||||
{
|
||||
parent::setData($locale);
|
||||
|
||||
$this->setOneClickAccessUrl($this->context, $this->reviewAssignment);
|
||||
|
||||
// See pkp/pkp-lib#9111
|
||||
$this->addData(['lostPasswordUrl' => $this->viewData[ContextEmailVariable::PASSWORD_LOST_URL]]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ReviewerRequest.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 ReviewRequest
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief An email send to a reviewer with a request to accept or decline a task to review a submission
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\PKPSubmission;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class ReviewRequest extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Sender;
|
||||
use Configurable;
|
||||
|
||||
protected static ?string $name = 'mailable.reviewRequest.name';
|
||||
protected static ?string $description = 'mailable.reviewRequest.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEW_REQUEST';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static bool $canDisable = true;
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
|
||||
public function __construct(Context $context, PKPSubmission $submission, ReviewAssignment $reviewAssignment)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ReviewRequestSubsequent.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 ReviewRequestSubsequent
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief An email send to a reviewer with a request to accept or decline a task to review a submission on subsequent review rounds
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\PKPSubmission;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class ReviewRequestSubsequent extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Sender;
|
||||
use Configurable;
|
||||
|
||||
protected static ?string $name = 'mailable.reviewRequestSubsequent.name';
|
||||
protected static ?string $description = 'mailable.reviewRequestSubsequent.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEW_REQUEST_SUBSEQUENT';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static bool $canDisable = true;
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
|
||||
public function __construct(Context $context, PKPSubmission $submission, ReviewAssignment $reviewAssignment)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ReviewResponseRemindAuto.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 ReviewResponseRemindAuto
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email is sent automatically to a reviewer as a reminder after a deadline for response
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\OneClickReviewerAccess;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\variables\ContextEmailVariable;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class ReviewResponseRemindAuto extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use OneClickReviewerAccess;
|
||||
use Recipient;
|
||||
|
||||
protected static ?string $name = 'mailable.reviewResponseOverdueAuto.name';
|
||||
protected static ?string $description = 'mailable.reviewResponseOverdueAuto.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEW_RESPONSE_OVERDUE_AUTO';
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [self::FROM_SYSTEM];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
|
||||
protected Context $context;
|
||||
protected ReviewAssignment $reviewAssignment;
|
||||
|
||||
public function __construct(Context $context, Submission $submission, ReviewAssignment $reviewAssignment)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
|
||||
$this->context = $context;
|
||||
$this->reviewAssignment = $reviewAssignment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the setData method to add the one-click access
|
||||
* URL for the reviewer
|
||||
*/
|
||||
public function setData(?string $locale = null): void
|
||||
{
|
||||
parent::setData($locale);
|
||||
|
||||
$this->setOneClickAccessUrl($this->context, $this->reviewAssignment);
|
||||
|
||||
// See pkp/pkp-lib#9111
|
||||
$this->addData([
|
||||
'lostPasswordUrl' => $this->viewData[ContextEmailVariable::PASSWORD_LOST_URL],
|
||||
'passwordResetUrl' => $this->viewData[ContextEmailVariable::PASSWORD_LOST_URL],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ReviewerRegister.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 ReviewerRegister
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email is sent automatically to a newly registered reviewer (see Create Reviewer Form)
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\user\User;
|
||||
|
||||
class ReviewerRegister extends Mailable
|
||||
{
|
||||
use Recipient {
|
||||
recipients as traitRecipients;
|
||||
}
|
||||
use Sender;
|
||||
use Configurable;
|
||||
|
||||
protected static ?string $name = 'mailable.reviewerRegister.name';
|
||||
protected static ?string $description = 'mailable.reviewerRegister.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEWER_REGISTER';
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
Role::ROLE_ID_ASSISTANT,
|
||||
];
|
||||
protected static array $toRoleIds = [
|
||||
Role::ROLE_ID_REVIEWER,
|
||||
];
|
||||
protected static ?string $variablePassword = 'password';
|
||||
|
||||
protected string $password;
|
||||
|
||||
public function __construct(Context $context, string $password)
|
||||
{
|
||||
parent::__construct([$context]);
|
||||
$this->password = $password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Mailable::getDataDescriptions()
|
||||
*/
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
return static::addPasswordVariable($variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a description to a new password variable
|
||||
*/
|
||||
protected static function addPasswordVariable(array $variables): array
|
||||
{
|
||||
$variables[static::$variablePassword] = __('emailTemplate.variable.password');
|
||||
return $variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override trait's method to include user password variable
|
||||
*/
|
||||
public function recipients(User $recipient, ?string $locale = null): Mailable
|
||||
{
|
||||
$this->traitRecipients([$recipient], $locale);
|
||||
$this->addData([
|
||||
static::$variablePassword => htmlspecialchars($this->password)
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ReviewerReinstate.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 ReviewerReinstate
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email sent to a reviewer when their assignment is reinstated
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\PKPSubmission;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class ReviewerReinstate extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Sender;
|
||||
use Configurable;
|
||||
|
||||
protected static ?string $name = 'mailable.reviewerReinstate.name';
|
||||
protected static ?string $description = 'mailable.reviewerReinstate.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEW_REINSTATE';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static bool $canDisable = true;
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
|
||||
public function __construct(Context $context, PKPSubmission $submission, ReviewAssignment $reviewAssignment)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ReviewerResendRequest.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 ReviewerResendRequest
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email sent to a review who has declined their review assignment to ask them
|
||||
* to reconsider accepting the review assignment
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\PKPSubmission;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class ReviewerResendRequest extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Sender;
|
||||
use Configurable;
|
||||
|
||||
protected static ?string $name = 'mailable.reviewerResendRequest.name';
|
||||
protected static ?string $description = 'mailable.reviewerResendRequest.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEW_RESEND_REQUEST';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static bool $canDisable = true;
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
|
||||
public function __construct(Context $context, PKPSubmission $submission, ReviewAssignment $reviewAssignment)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ReviewerUnassign.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 ReviewerUnassign
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email sent when a reviewer is unassigned
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\PKPSubmission;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class ReviewerUnassign extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Sender;
|
||||
use Configurable;
|
||||
|
||||
/** @var string An email variable that contains a description of the editorial decision */
|
||||
public const DECISION_DESCRIPTION = 'decisionDescription';
|
||||
|
||||
protected static ?string $name = 'mailable.reviewerUnassign.name';
|
||||
protected static ?string $description = 'mailable.reviewerUnassign.description';
|
||||
protected static ?string $emailTemplateKey = 'REVIEW_CANCEL';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static bool $canDisable = true;
|
||||
protected static array $fromRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_REVIEWER];
|
||||
|
||||
protected ?Decision $decision;
|
||||
|
||||
public function __construct(
|
||||
Context $context,
|
||||
PKPSubmission $submission,
|
||||
?ReviewAssignment $reviewAssignment = null,
|
||||
?Decision $decision = null
|
||||
) {
|
||||
parent::__construct(array_filter(func_get_args(), fn ($param) => !is_null($param)));
|
||||
$this->decision = $decision;
|
||||
}
|
||||
|
||||
public function getDecision(): ?Decision
|
||||
{
|
||||
return $this->decision;
|
||||
}
|
||||
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
|
||||
$variables[self::DECISION_DESCRIPTION] = __('mailable.decision.notifyReviewer.variable.decisionDescription');
|
||||
return $variables;
|
||||
}
|
||||
|
||||
public function setData(?string $locale = null): void
|
||||
{
|
||||
parent::setData($locale);
|
||||
|
||||
if ($this->decision) {
|
||||
$this->viewData[self::DECISION_DESCRIPTION] = $this->getDecisionDescription($locale);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a description of the decision to use as an email variable
|
||||
*/
|
||||
protected function getDecisionDescription(?string $locale = null): string
|
||||
{
|
||||
$class = Decision::class;
|
||||
$reviewerUnassignedTypes = collect([
|
||||
'CANCEL_REVIEW_ROUND',
|
||||
'CANCEL_INTERNAL_REVIEW_ROUND',
|
||||
])
|
||||
->map(fn ($type) => defined("{$class}::{$type}") ? constant("{$class}::{$type}") : null)
|
||||
->filter(fn ($type) => !is_null($type))
|
||||
->toArray();
|
||||
|
||||
if (in_array($this->decision->getData('decision'), $reviewerUnassignedTypes)) {
|
||||
return __('mailable.decision.notifyReviewer.variable.decisionDescription.unassigned', [], $locale);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/RevisedVersionNotify.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 RevisedVersionNotify
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief The email is sent automatically to the assigned editor when author uploads a revised version of an article
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewRound\ReviewRound;
|
||||
use PKP\user\User;
|
||||
|
||||
class RevisedVersionNotify extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Sender;
|
||||
use Configurable;
|
||||
|
||||
protected static ?string $name = 'mailable.revisedVersionNotify.name';
|
||||
protected static ?string $description = 'mailable.revisedVersionNotify.description';
|
||||
protected static ?string $emailTemplateKey = 'REVISED_VERSION_NOTIFY';
|
||||
protected static bool $supportsTemplates = false;
|
||||
protected static array $groupIds = [self::GROUP_REVIEW];
|
||||
protected static array $fromRoleIds = [self::FROM_SYSTEM];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
|
||||
protected Submission $submission;
|
||||
protected static string $submitterName = 'submitterName';
|
||||
|
||||
public function __construct(Context $context, Submission $submission, User $uploader, ReviewRound $reviewRound)
|
||||
{
|
||||
parent::__construct(array_slice(func_get_args(), 0, -2));
|
||||
$this->setupSubmitterNameVariable($uploader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add description to a submissionUrl email template variable
|
||||
*/
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
$variables[static::$submitterName] = __('emailTemplate.variable.submitterName');
|
||||
return $variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add submitterName variable; submitter may not be a sender
|
||||
*/
|
||||
protected function setupSubmitterNameVariable(User $uploader): void
|
||||
{
|
||||
$this->addData([static::$submitterName => $uploader->getFullName()]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/AnnouncementNotify.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 StatisticsReportNotify
|
||||
*
|
||||
* @brief Email sent to notify users about new announcement
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\context\Context;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Unsubscribe;
|
||||
use PKP\security\Role;
|
||||
|
||||
class StatisticsReportNotify extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Configurable;
|
||||
use Unsubscribe;
|
||||
|
||||
protected static ?string $name = 'mailable.statisticsReportNotify.name';
|
||||
protected static ?string $description = 'mailable.statisticsReportNotify.description';
|
||||
protected static ?string $emailTemplateKey = 'STATISTICS_REPORT_NOTIFICATION';
|
||||
protected static bool $canDisable = true;
|
||||
protected static array $groupIds = [self::GROUP_OTHER];
|
||||
protected static array $fromRoleIds = [self::FROM_SYSTEM];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_SUB_EDITOR];
|
||||
|
||||
protected Context $context;
|
||||
|
||||
public function __construct(
|
||||
Context $context,
|
||||
array $editorialTrends,
|
||||
int $totalSubmissions,
|
||||
string $month,
|
||||
int $year
|
||||
) {
|
||||
parent::__construct([$context]);
|
||||
$this->context = $context;
|
||||
$this->setupStatisticsVariables($context, $editorialTrends, $totalSubmissions, $month, $year);
|
||||
}
|
||||
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = [
|
||||
'newSubmissions' => __('emailTemplate.variable.statisticsReportNotify.newSubmissions'),
|
||||
'declinedSubmissions' => __('emailTemplate.variable.statisticsReportNotify.declinedSubmissions'),
|
||||
'acceptedSubmissions' => __('emailTemplate.variable.statisticsReportNotify.acceptedSubmissions'),
|
||||
'skippedSubmissions' => __('emailTemplate.variable.statisticsReportNotify.otherSubmissions'),
|
||||
'totalSubmissions' => __('emailTemplate.variable.statisticsReportNotify.totalSubmissions'),
|
||||
'month' => __('emailTemplate.variable.statisticsReportNotify.month'),
|
||||
'year' => __('emailTemplate.variable.statisticsReportNotify.year'),
|
||||
'editorialStatsLink' => __('emailTemplate.variable.statisticsReportNotify.editorialStatsLink'),
|
||||
'publicationStatsLink' => __('emailTemplate.variable.statisticsReportNotify.publicationStatsLink'),
|
||||
];
|
||||
|
||||
return array_merge(parent::getDataDescriptions(), $variables);
|
||||
}
|
||||
|
||||
protected function setupStatisticsVariables(
|
||||
Context $context,
|
||||
array $editorialTrends,
|
||||
int $totalSubmissions,
|
||||
string $month,
|
||||
int $year
|
||||
): void {
|
||||
$dispatcher = Application::get()->getDispatcher();
|
||||
$request = Application::get()->getRequest();
|
||||
|
||||
$trends = [];
|
||||
foreach ($editorialTrends as $stat) {
|
||||
$trends[$stat['key']] = $stat['value'];
|
||||
}
|
||||
|
||||
// The submissionsAccepted might not exist
|
||||
$trends['submissionsAccepted'] ??= null;
|
||||
[
|
||||
'submissionsReceived' => $newSubmissions,
|
||||
'submissionsDeclined' => $declinedSubmissions,
|
||||
'submissionsAccepted' => $acceptedSubmissions,
|
||||
'submissionsSkipped' => $skippedSubmissions
|
||||
] = $trends;
|
||||
|
||||
$this->addData([
|
||||
'newSubmissions' => $newSubmissions,
|
||||
'declinedSubmissions' => $declinedSubmissions,
|
||||
'acceptedSubmissions' => $acceptedSubmissions,
|
||||
'skippedSubmissions' => $skippedSubmissions,
|
||||
'totalSubmissions' => $totalSubmissions,
|
||||
'month' => $month,
|
||||
'year' => $year,
|
||||
'editorialStatsLink' => $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'stats', 'editorial'),
|
||||
'publicationStatsLink' => $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'stats', 'publications')
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a footer with unsubscribe link
|
||||
*/
|
||||
protected function addFooter(string $locale): Mailable
|
||||
{
|
||||
$this->setupUnsubscribeFooter($locale, $this->context);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/SubmissionAcknowledgement.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 SubmissionAcknowledgement
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email sent to a submitting author when they submit their submission
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\mail\variables\ContextEmailVariable;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\security\Role;
|
||||
|
||||
class SubmissionAcknowledgement extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Configurable;
|
||||
|
||||
protected static ?string $name = 'mailable.submissionAck.name';
|
||||
protected static ?string $description = 'mailable.submissionAck.description';
|
||||
protected static ?string $emailTemplateKey = 'SUBMISSION_ACK';
|
||||
protected static bool $canDisable = true;
|
||||
protected static array $groupIds = [self::GROUP_SUBMISSION];
|
||||
protected static array $fromRoleIds = [self::FROM_SYSTEM];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
public function __construct(Context $context, Submission $submission)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Mailable::setData()
|
||||
*/
|
||||
public function setData(?string $locale = null): void
|
||||
{
|
||||
parent::setData($locale);
|
||||
$this->addData([
|
||||
'editorialContactSignature' => $this->viewData[ContextEmailVariable::CONTEXT_SIGNATURE],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/SubmissionAcknowledgementNotAuthor.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 SubmissionAcknowledgementNotAuthor
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief This email is sent automatically to the contributors identified in a submission to the journal
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\security\Role;
|
||||
use PKP\user\User;
|
||||
|
||||
class SubmissionAcknowledgementNotAuthor extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Configurable;
|
||||
|
||||
protected static ?string $name = 'mailable.submissionAckNotAuthor.name';
|
||||
protected static ?string $description = 'mailable.submissionAckNotAuthor.description';
|
||||
protected static ?string $emailTemplateKey = 'SUBMISSION_ACK_NOT_USER';
|
||||
protected static bool $canDisable = true;
|
||||
protected static array $groupIds = [self::GROUP_SUBMISSION];
|
||||
protected static array $fromRoleIds = [self::FROM_SYSTEM];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
protected static string $submitterName = 'submitterName';
|
||||
|
||||
public function __construct(Context $context, Submission $submission, User $submitter)
|
||||
{
|
||||
parent::__construct(array_slice(func_get_args(), 0, -1));
|
||||
|
||||
$this->addData([
|
||||
self::$submitterName => $submitter->getFullName()
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
return static::addSubmitterNameDescription($variables);
|
||||
}
|
||||
|
||||
protected static function addSubmitterNameDescription(array $variables): array
|
||||
{
|
||||
$variables[self::$submitterName] = __('emailTemplate.variable.submitterName');
|
||||
return $variables;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/SubmissionAcknowledgementOtherAuthors.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 SubmissionAcknowledgementOtherAuthors
|
||||
*
|
||||
* @brief Email sent to authors named as contributors to a new submission who
|
||||
* are not the submitting author.
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\author\Author;
|
||||
use APP\submission\Submission;
|
||||
use Illuminate\Support\Enumerable;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\security\Role;
|
||||
use PKP\user\User;
|
||||
|
||||
class SubmissionAcknowledgementOtherAuthors extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
|
||||
protected const AUTHORS_WITH_AFFILIATION = 'authorsWithAffiliation';
|
||||
protected const SUBMITTER_NAME = 'submitterName';
|
||||
|
||||
protected static ?string $name = 'mailable.submissionAckOtherAuthors.name';
|
||||
protected static ?string $description = 'emails.submissionAckNotUser.description';
|
||||
protected static ?string $emailTemplateKey = 'SUBMISSION_ACK_NOT_USER';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_SUBMISSION];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
protected Submission $submission;
|
||||
protected Enumerable $submitterUsers;
|
||||
|
||||
|
||||
public function __construct(Context $context, Submission $submission, Enumerable $submitterUsers)
|
||||
{
|
||||
parent::__construct([$context, $submission]);
|
||||
$this->submission = $submission;
|
||||
$this->submitterUsers = $submitterUsers;
|
||||
$this->addData([
|
||||
self::AUTHORS_WITH_AFFILIATION => $this->getAuthorsWithAffiliation(),
|
||||
self::SUBMITTER_NAME => $this->getSubmitterName(),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
return array_merge([
|
||||
parent::getDataDescriptions(),
|
||||
[
|
||||
self::AUTHORS_WITH_AFFILIATION => __('emailTemplate.variable.authorsWithAffiliation'),
|
||||
self::SUBMITTER_NAME => __('emailTemplate.variable.submitterName'),
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getSubmitterName(): string
|
||||
{
|
||||
return $this->submitterUsers
|
||||
->map(fn (User $user) => $user->getFullName())
|
||||
->join(__('common.commaListSeparator'));
|
||||
}
|
||||
|
||||
protected function getAuthorsWithAffiliation(): string
|
||||
{
|
||||
$authors = $this->submission->getCurrentPublication()->getData('authors');
|
||||
|
||||
if ($authors->empty()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $authors
|
||||
->map(fn (Author $author) => join(__('common.commaListSeparator'), [$author->getFullName(), $author->getLocalizedAffiliation()]))
|
||||
->join('<br>');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/SubmissionNeedsEditor.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 SubmissionNeedsEditor
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email sent to managers when a new submission is made and no editor is assigned
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\security\Role;
|
||||
|
||||
class SubmissionNeedsEditor extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
use Configurable;
|
||||
|
||||
protected static ?string $name = 'mailable.submissionNeedsEditor.name';
|
||||
protected static ?string $description = 'mailable.submissionNeedsEditor.description';
|
||||
protected static ?string $emailTemplateKey = 'SUBMISSION_NEEDS_EDITOR';
|
||||
protected static bool $canDisable = true;
|
||||
protected static array $groupIds = [self::GROUP_SUBMISSION];
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
|
||||
public function __construct(Context $context, Submission $submission)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/SubmissionSavedForLater.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 SubmissionSavedForLater
|
||||
*
|
||||
* @brief Email sent to a submitting author when they save their submission
|
||||
* to be completed later
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\submission\Submission;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\security\Role;
|
||||
|
||||
class SubmissionSavedForLater extends Mailable
|
||||
{
|
||||
use Recipient;
|
||||
|
||||
/** @var string An email variable that contains a description of the editorial decision */
|
||||
public const DECISION_DESCRIPTION = 'decisionDescription';
|
||||
|
||||
protected static ?string $name = 'mailable.submissionSavedForLater.name';
|
||||
protected static ?string $description = 'mailable.submissionSavedForLater.description';
|
||||
protected static ?string $emailTemplateKey = 'SUBMISSION_SAVED_FOR_LATER';
|
||||
protected static bool $supportsTemplates = true;
|
||||
protected static array $groupIds = [self::GROUP_SUBMISSION];
|
||||
protected static bool $canDisable = true;
|
||||
protected static array $toRoleIds = [Role::ROLE_ID_AUTHOR];
|
||||
protected Decision $decision;
|
||||
|
||||
public function __construct(Context $context, Submission $submission)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/UserCreated.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 UserCreated
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Email sent when a new user is added from the user management screen.
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\mail\traits\Sender;
|
||||
use PKP\security\Role;
|
||||
use PKP\user\User;
|
||||
|
||||
class UserCreated extends Mailable
|
||||
{
|
||||
use Recipient {
|
||||
recipients as traitRecipients;
|
||||
}
|
||||
use Configurable;
|
||||
use Sender;
|
||||
|
||||
protected static ?string $name = 'mailable.userRegister.name';
|
||||
protected static ?string $description = 'mailable.userRegister.description';
|
||||
protected static ?string $emailTemplateKey = 'USER_REGISTER';
|
||||
protected static array $groupIds = [self::GROUP_OTHER];
|
||||
protected static array $fromRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
];
|
||||
protected static array $toRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
Role::ROLE_ID_ASSISTANT,
|
||||
Role::ROLE_ID_AUTHOR,
|
||||
Role::ROLE_ID_READER,
|
||||
Role::ROLE_ID_REVIEWER,
|
||||
Role::ROLE_ID_SUBSCRIPTION_MANAGER,
|
||||
];
|
||||
protected static ?string $variablePassword = 'password';
|
||||
|
||||
protected string $password;
|
||||
|
||||
public function __construct(Context $context, string $password)
|
||||
{
|
||||
parent::__construct([$context]);
|
||||
$this->password = $password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Mailable::getDataDescriptions()
|
||||
*/
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
$variables = parent::getDataDescriptions();
|
||||
return static::addPasswordVariable($variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a description to a new password variable
|
||||
*/
|
||||
protected static function addPasswordVariable(array $variables): array
|
||||
{
|
||||
$variables[static::$variablePassword] = __('emailTemplate.variable.password');
|
||||
return $variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override trait's method to include user password variable
|
||||
*/
|
||||
public function recipients(User $recipient, ?string $locale = null): Mailable
|
||||
{
|
||||
$this->traitRecipients([$recipient], $locale);
|
||||
$this->addData([
|
||||
static::$variablePassword => htmlspecialchars($this->password)
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ValidateEmailContext.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 ValidateEmailContext
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Represents registration validation email
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\security\Role;
|
||||
|
||||
class ValidateEmailContext extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
|
||||
protected static ?string $name = 'mailable.validateEmailContext.name';
|
||||
protected static ?string $description = 'mailable.validateEmailContext.description';
|
||||
protected static ?string $emailTemplateKey = 'USER_VALIDATE_CONTEXT';
|
||||
protected static array $groupIds = [self::GROUP_OTHER];
|
||||
protected static array $fromRoleIds = [self::FROM_SYSTEM];
|
||||
protected static array $toRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
Role::ROLE_ID_ASSISTANT,
|
||||
Role::ROLE_ID_AUTHOR,
|
||||
Role::ROLE_ID_READER,
|
||||
Role::ROLE_ID_REVIEWER,
|
||||
Role::ROLE_ID_SUBSCRIPTION_MANAGER,
|
||||
];
|
||||
|
||||
public function __construct(Context $context)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add description for the validation link variable
|
||||
*/
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
return array_merge(parent::getDataDescriptions(), [
|
||||
'activateUrl' => __('emailTemplate.variable.activateUrl'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/mailables/ValidateEmailSite.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 ValidateEmailSite
|
||||
*
|
||||
* @ingroup mail_mailables
|
||||
*
|
||||
* @brief Represents registration validation email
|
||||
*/
|
||||
|
||||
namespace PKP\mail\mailables;
|
||||
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\traits\Configurable;
|
||||
use PKP\mail\traits\Recipient;
|
||||
use PKP\security\Role;
|
||||
use PKP\site\Site;
|
||||
|
||||
class ValidateEmailSite extends Mailable
|
||||
{
|
||||
use Configurable;
|
||||
use Recipient;
|
||||
|
||||
protected static ?string $name = 'mailable.validateEmailSite.name';
|
||||
protected static ?string $description = 'mailable.validateEmailSite.description';
|
||||
protected static ?string $emailTemplateKey = 'USER_VALIDATE_SITE';
|
||||
protected static array $groupIds = [self::GROUP_OTHER];
|
||||
protected static array $fromRoleIds = [self::FROM_SYSTEM];
|
||||
protected static array $toRoleIds = [
|
||||
Role::ROLE_ID_SUB_EDITOR,
|
||||
Role::ROLE_ID_ASSISTANT,
|
||||
Role::ROLE_ID_AUTHOR,
|
||||
Role::ROLE_ID_READER,
|
||||
Role::ROLE_ID_REVIEWER,
|
||||
Role::ROLE_ID_SUBSCRIPTION_MANAGER,
|
||||
];
|
||||
|
||||
public function __construct(Site $site)
|
||||
{
|
||||
parent::__construct(func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add description for the validation link variable
|
||||
*/
|
||||
public static function getDataDescriptions(): array
|
||||
{
|
||||
return array_merge(parent::getDataDescriptions(), [
|
||||
'activateUrl' => __('emailTemplate.variable.activateUrl'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/traits/Configurable.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 Configurable
|
||||
*
|
||||
* @ingroup mail_traits
|
||||
*
|
||||
* @brief trait to support Mailable's name and description displayed in the UI
|
||||
*/
|
||||
|
||||
namespace PKP\mail\traits;
|
||||
|
||||
use Exception;
|
||||
|
||||
trait Configurable
|
||||
{
|
||||
/**
|
||||
* Retrieve localized Mailable's name
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getName(): string
|
||||
{
|
||||
if (is_null(static::$name)) {
|
||||
throw new Exception('Configurable mailable created without a name.');
|
||||
}
|
||||
|
||||
return __(static::$name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve localized Mailable's description
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getDescription(): string
|
||||
{
|
||||
if (is_null(static::$description)) {
|
||||
throw new Exception('Configurable mailable created without a description.');
|
||||
}
|
||||
|
||||
return __(static::$description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a unique Mailable's ID
|
||||
*/
|
||||
public static function getId(): string
|
||||
{
|
||||
return str_replace('\\', '-', static::class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/traits/Discussion.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 Discussion
|
||||
*
|
||||
* @ingroup mail_traits
|
||||
*
|
||||
* @brief trait to support Discussion email template variables
|
||||
*/
|
||||
|
||||
namespace PKP\mail\traits;
|
||||
|
||||
use PKP\mail\variables\SubmissionEmailVariable;
|
||||
|
||||
trait Discussion
|
||||
{
|
||||
use Unsubscribe {
|
||||
getRequiredVariables as getTraitRequiredVariables;
|
||||
}
|
||||
|
||||
protected function addFooter(string $locale): self
|
||||
{
|
||||
$this->setupUnsubscribeFooter($locale, $this->context);
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function setFooterText(string $locale, string $localeKey = null): string
|
||||
{
|
||||
if (is_null($localeKey)) {
|
||||
$localeKey = 'emails.footer.unsubscribe.discussion';
|
||||
}
|
||||
|
||||
return __($localeKey, [], $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds email template variable class required to generate submission-related variables
|
||||
*/
|
||||
protected static function getRequiredVariables(): array
|
||||
{
|
||||
return array_merge(
|
||||
static::getTraitRequiredVariables(),
|
||||
[SubmissionEmailVariable::class]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/traits/OneClickReviewerAccess.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 OneClickReviewerAccess
|
||||
*
|
||||
* @ingroup mail_traits
|
||||
*
|
||||
* @brief Mailable trait to override the review assignment URL with the
|
||||
* secure, one-click access URL for reviewers
|
||||
*/
|
||||
|
||||
namespace PKP\mail\traits;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\variables\ReviewAssignmentEmailVariable;
|
||||
use PKP\security\AccessKeyManager;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
trait OneClickReviewerAccess
|
||||
{
|
||||
protected function setOneClickAccessUrl(Context $context, ReviewAssignment $reviewAssignment): void
|
||||
{
|
||||
if (!$context->getData('reviewerAccessKeysEnabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$application = Application::get();
|
||||
$request = $application->getRequest();
|
||||
$dispatcher = $application->getDispatcher();
|
||||
|
||||
$accessKeyManager = new AccessKeyManager();
|
||||
$expiryDays = ($this->context->getData('numWeeksPerReview') + 4) * 7;
|
||||
$accessKey = $accessKeyManager->createKey(
|
||||
$context->getId(),
|
||||
$reviewAssignment->getReviewerId(),
|
||||
$reviewAssignment->getId(),
|
||||
$expiryDays
|
||||
);
|
||||
|
||||
$this->viewData[ReviewAssignmentEmailVariable::REVIEW_ASSIGNMENT_URL] = $dispatcher->url(
|
||||
$request,
|
||||
Application::ROUTE_PAGE,
|
||||
$context->getData('urlPath'),
|
||||
'reviewer',
|
||||
'submission',
|
||||
null,
|
||||
[
|
||||
'submissionId' => $reviewAssignment->getSubmissionId(),
|
||||
'reviewId' => $reviewAssignment->getId(),
|
||||
'key' => $accessKey,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/traits/PasswordResetUrl.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 PasswordResetUrl
|
||||
*
|
||||
* @ingroup mail_traits
|
||||
*
|
||||
* @brief Mailable trait to ensure compatibility of `passwordResetUrl` variable for templates:
|
||||
* REVIEW_REMIND, REVIEW_REMIND_AUTO, REVIEW_REMIND_OVERDUE_AUTO, PASSWORD_RESET_CONFIRM
|
||||
*/
|
||||
|
||||
namespace PKP\mail\traits;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\security\Validation;
|
||||
use PKP\user\User;
|
||||
|
||||
trait PasswordResetUrl
|
||||
{
|
||||
protected static string $passwordResetUrl = 'passwordResetUrl';
|
||||
|
||||
/**
|
||||
* Adds passwordResetUrl variable's value to the Mailable
|
||||
*/
|
||||
protected function setPasswordResetUrl(User $user, ?string $contextUrlPath = null): void
|
||||
{
|
||||
$request = Application::get()->getRequest();
|
||||
$dispatcher = $request->getDispatcher();
|
||||
|
||||
$this->addData([self::$passwordResetUrl =>
|
||||
$dispatcher->url(
|
||||
$request,
|
||||
Application::ROUTE_PAGE,
|
||||
$contextUrlPath,
|
||||
'login',
|
||||
'resetPassword',
|
||||
$user->getUsername(),
|
||||
['confirm' => Validation::generatePasswordResetHash($user->getId())]
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds passwordResetUrl variable's description to the Mailable
|
||||
*/
|
||||
public static function addPasswordResetUrlDescription(array $variables): array
|
||||
{
|
||||
$variables[self::$passwordResetUrl] = __('emailTemplate.variable.passwordResetUrl');
|
||||
return $variables;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/traits/Recipient.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 Recipient
|
||||
*
|
||||
* @ingroup mail_traits
|
||||
*
|
||||
* @brief Mailable trait to set the recipients to an array of Users
|
||||
*/
|
||||
|
||||
namespace PKP\mail\traits;
|
||||
|
||||
use BadMethodCallException;
|
||||
use InvalidArgumentException;
|
||||
use PKP\identity\Identity;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\variables\RecipientEmailVariable;
|
||||
|
||||
trait Recipient
|
||||
{
|
||||
/**
|
||||
* @copydoc Illuminate\Mail\Mailable::setAddress()
|
||||
*
|
||||
* @param null|mixed $name
|
||||
*/
|
||||
abstract protected function setAddress($address, $name = null, $property = 'to');
|
||||
|
||||
/**
|
||||
* @copydoc Illuminate\Mail\Mailable::to()
|
||||
*
|
||||
* @param null|mixed $name
|
||||
*/
|
||||
public function to($address, $name = null)
|
||||
{
|
||||
throw new BadMethodCallException(static::class . ' doesn\'t support ' . __FUNCTION__ . '(), use recipients() instead');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set recipients of the email and set values for related template variables
|
||||
*
|
||||
* @param Identity[] $recipients
|
||||
* @param ?string $locale Optional. A locale key to use when setting the recipient names. Default: current locale
|
||||
*/
|
||||
public function recipients(array $recipients, ?string $locale = null): Mailable
|
||||
{
|
||||
$to = [];
|
||||
foreach ($recipients as $recipient) {
|
||||
if (!is_a($recipient, Identity::class)) {
|
||||
throw new InvalidArgumentException('Expecting an array consisting of instances of ' . Identity::class . ' to be passed to ' . static::class . '::' . __FUNCTION__);
|
||||
}
|
||||
$to[] = [
|
||||
'email' => $recipient->getEmail(),
|
||||
'name' => $recipient->getFullName(true, false, $locale),
|
||||
];
|
||||
}
|
||||
|
||||
// Override the existing recipient data
|
||||
$this->to = [];
|
||||
$this->variables = array_filter($this->variables, function ($variable) {
|
||||
return !is_a($variable, RecipientEmailVariable::class);
|
||||
});
|
||||
|
||||
$this->setAddress($to);
|
||||
$this->variables[] = new RecipientEmailVariable($recipients, $this);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/traits/ReviewerComments.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 ReviewerComments
|
||||
*
|
||||
* @ingroup mail_traits
|
||||
*
|
||||
* @brief Mailable trait to add reviewer comments to a mailable's variables
|
||||
*/
|
||||
|
||||
namespace PKP\mail\traits;
|
||||
|
||||
use APP\submission\Submission;
|
||||
use PKP\core\PKPString;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\reviewForm\ReviewFormElementDAO;
|
||||
use PKP\reviewForm\ReviewFormResponse;
|
||||
use PKP\reviewForm\ReviewFormResponseDAO;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
use PKP\submission\SubmissionComment;
|
||||
use PKP\submission\SubmissionCommentDAO;
|
||||
|
||||
trait ReviewerComments
|
||||
{
|
||||
protected static string $allReviewerComments = 'allReviewerComments';
|
||||
|
||||
/**
|
||||
* Add the reviewer comments to the list of registered variables
|
||||
*/
|
||||
protected static function addReviewerCommentsDescription(array $variables): array
|
||||
{
|
||||
$variables[static::$allReviewerComments] = __('emailTemplate.variable.allReviewersComments');
|
||||
return $variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a variable with comments from all completed review assignments
|
||||
*
|
||||
* @param array<ReviewAssignment> $reviewAssignments
|
||||
*/
|
||||
protected function setupReviewerCommentsVariable(array $reviewAssignments, Submission $submission)
|
||||
{
|
||||
/** @var SubmissionCommentDAO $submissionCommentDao */
|
||||
$submissionCommentDao = DAORegistry::getDAO('SubmissionCommentDAO');
|
||||
|
||||
$reviewerNumber = 0;
|
||||
$comments = [];
|
||||
foreach ($reviewAssignments as $reviewAssignment) {
|
||||
$reviewerNumber++;
|
||||
|
||||
$submissionComments = $submissionCommentDao->getReviewerCommentsByReviewerId(
|
||||
$submission->getId(),
|
||||
$reviewAssignment->getReviewerId(),
|
||||
$reviewAssignment->getId(),
|
||||
true
|
||||
);
|
||||
|
||||
$reviewerIdentity = $reviewAssignment->getReviewMethod() == ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN
|
||||
? $reviewAssignment->getReviewerFullName()
|
||||
: __('submission.comments.importPeerReviews.reviewerLetter', ['reviewerLetter' => $reviewerNumber]);
|
||||
$recommendation = $reviewAssignment->getLocalizedRecommendation();
|
||||
|
||||
$commentsBody = '';
|
||||
/** @var SubmissionComment $comment */
|
||||
while ($comment = $submissionComments->next()) {
|
||||
// If the comment is viewable by the author, then add the comment.
|
||||
if ($comment->getViewable()) {
|
||||
$commentsBody .= PKPString::stripUnsafeHtml($comment->getComments());
|
||||
}
|
||||
}
|
||||
|
||||
$comments[] =
|
||||
'<p>'
|
||||
. '<strong>' . $reviewerIdentity . '</strong>'
|
||||
. '<br>'
|
||||
. __('submission.recommendation', ['recommendation' => $recommendation])
|
||||
. '</p>'
|
||||
. $commentsBody
|
||||
. $this->getReviewFormComments($reviewAssignment);
|
||||
}
|
||||
|
||||
$this->addData([
|
||||
static::$allReviewerComments => join('', $comments),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getReviewFormComments(ReviewAssignment $reviewAssignment): string
|
||||
{
|
||||
if (!$reviewAssignment->getReviewFormId()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
/** @var ReviewFormElementDAO $reviewFormElementDao */
|
||||
$reviewFormElementDao = DAORegistry::getDAO('ReviewFormElementDAO');
|
||||
$reviewFormElements = $reviewFormElementDao->getByReviewFormId($reviewAssignment->getReviewFormId());
|
||||
|
||||
if ($reviewFormElements->wasEmpty()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
/** @var ReviewFormResponseDAO $reviewFormResponseDao */
|
||||
$reviewFormResponseDao = DAORegistry::getDAO('ReviewFormResponseDAO');
|
||||
|
||||
$comments = '';
|
||||
while ($reviewFormElement = $reviewFormElements->next()) {
|
||||
if (!$reviewFormElement->getIncluded()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var ReviewFormResponse|null $reviewFormResponse */
|
||||
$reviewFormResponse = $reviewFormResponseDao->getReviewFormResponse($reviewAssignment->getId(), $reviewFormElement->getId());
|
||||
if (!$reviewFormResponse) {
|
||||
continue;
|
||||
}
|
||||
$comments .= PKPString::stripUnsafeHtml($reviewFormElement->getLocalizedQuestion());
|
||||
$possibleResponses = $reviewFormElement->getLocalizedPossibleResponses();
|
||||
// See issue #2437.
|
||||
if (in_array($reviewFormElement->getElementType(), [$reviewFormElement::REVIEW_FORM_ELEMENT_TYPE_CHECKBOXES, $reviewFormElement::REVIEW_FORM_ELEMENT_TYPE_RADIO_BUTTONS])) {
|
||||
ksort($possibleResponses);
|
||||
$possibleResponses = array_values($possibleResponses);
|
||||
}
|
||||
if (in_array($reviewFormElement->getElementType(), $reviewFormElement->getMultipleResponsesElementTypes())) {
|
||||
if ($reviewFormElement->getElementType() == $reviewFormElement::REVIEW_FORM_ELEMENT_TYPE_CHECKBOXES) {
|
||||
$comments .= '<ul>';
|
||||
foreach ($reviewFormResponse->getValue() as $value) {
|
||||
$comments .= '<li>' . PKPString::stripUnsafeHtml($possibleResponses[$value]) . '</li>';
|
||||
}
|
||||
$comments .= '</ul>';
|
||||
} else {
|
||||
$comments .= '<p>' . PKPString::stripUnsafeHtml($possibleResponses[$reviewFormResponse->getValue()]) . '</p>';
|
||||
}
|
||||
} else {
|
||||
$comments .= '<p>' . nl2br(htmlspecialchars($reviewFormResponse->getValue())) . '</p>';
|
||||
}
|
||||
}
|
||||
|
||||
return $comments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/traits/Sender.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 Sender
|
||||
*
|
||||
* @ingroup mail_traits
|
||||
*
|
||||
* @brief Mailable trait to set the sender to a User
|
||||
*/
|
||||
|
||||
namespace PKP\mail\traits;
|
||||
|
||||
use BadMethodCallException;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\variables\SenderEmailVariable;
|
||||
use PKP\user\User;
|
||||
|
||||
trait Sender
|
||||
{
|
||||
/**
|
||||
* User that sends mailable
|
||||
*/
|
||||
protected User $sender;
|
||||
|
||||
/**
|
||||
* @copydoc Illuminate\Mail\Mailable::setAddress()
|
||||
*
|
||||
* @param null|mixed $name
|
||||
*/
|
||||
abstract protected function setAddress($address, $name = null, $property = 'to');
|
||||
|
||||
/**
|
||||
* @copydoc Illuminate\Mail\Mailable::from()
|
||||
*
|
||||
* @param null|mixed $name
|
||||
*/
|
||||
public function from($address, $name = null)
|
||||
{
|
||||
throw new BadMethodCallException(static::class . ' doesn\'t support ' . __FUNCTION__ . '(), use sender() instead');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set recipients of the email and set values for related template variables
|
||||
*/
|
||||
public function sender(User $sender, ?string $defaultLocale = null): Mailable
|
||||
{
|
||||
$this->setAddress($sender->getEmail(), $sender->getFullName(true, false, $defaultLocale), 'from');
|
||||
$this->variables[] = new SenderEmailVariable($sender, $this);
|
||||
$this->sender = $sender;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSenderUser(): User
|
||||
{
|
||||
return $this->sender;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/traits/Unsubscribe.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 Unsubscribe
|
||||
*
|
||||
* @ingroup mail_traits
|
||||
*
|
||||
* @brief trait to embed footer with unsubscribe link to notification emails
|
||||
*/
|
||||
|
||||
namespace PKP\mail\traits;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\mail\variables\ContextEmailVariable;
|
||||
use APP\notification\Notification;
|
||||
use APP\notification\NotificationManager;
|
||||
use Exception;
|
||||
use Illuminate\Mail\Mailables\Headers;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\mail\variables\ContextEmailVariable as PKPContextEmailVariable;
|
||||
|
||||
trait Unsubscribe
|
||||
{
|
||||
protected static string $unsubscribeUrl = 'unsubscribeUrl';
|
||||
|
||||
// Notification to generate unsubscribe link
|
||||
protected Notification $notification;
|
||||
|
||||
// Locale key used by default in the footer if none is specified by Mailable::setupUnsubscribeFooter()
|
||||
protected string $defaultUnsubscribeLocaleKey = 'emails.footer.unsubscribe';
|
||||
|
||||
/**
|
||||
* @var string[] template variables required for the unsubscribe footer
|
||||
*/
|
||||
protected static array $requiredVariables = [PKPContextEmailVariable::class];
|
||||
|
||||
abstract public function addData(array $data): Mailable;
|
||||
abstract public function getVariables(): array;
|
||||
|
||||
/**
|
||||
* Use this public method to set footer for this email
|
||||
*/
|
||||
public function allowUnsubscribe(Notification $notification): self
|
||||
{
|
||||
$this->notification = $notification;
|
||||
|
||||
if (!$this->hasRequiredVariables()) {
|
||||
throw new Exception(
|
||||
'Mailable should include the following template variables: ' .
|
||||
implode(',', static::getRequiredVariables())
|
||||
);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup footer with unsubscribe link if notification is deliberately set with self::allowUnsubscribe()
|
||||
*
|
||||
* @param null|mixed $localeKey
|
||||
*/
|
||||
protected function setupUnsubscribeFooter(string $locale, $context, $localeKey = null): void
|
||||
{
|
||||
if (!isset($this->notification)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->footer = $this->renameContextVariables($this->setFooterText($locale, $localeKey));
|
||||
|
||||
$notificationManager = new NotificationManager(); /** @var NotificationManager $notificationManager */
|
||||
$request = Application::get()->getRequest();
|
||||
$this->addData([
|
||||
self::$unsubscribeUrl => $notificationManager->getUnsubscribeNotificationUrl(
|
||||
$request,
|
||||
$this->notification,
|
||||
$context
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds unsubscribe headers, see pkp/pkp-lib#6627
|
||||
*/
|
||||
public function headers(): Headers
|
||||
{
|
||||
$unsubscribeUrl = $this->viewData[self::$unsubscribeUrl] ?? null;
|
||||
return new Headers(
|
||||
null,
|
||||
[],
|
||||
$unsubscribeUrl ? [
|
||||
'List-Unsubscribe-Post' => 'List-Unsubscribe=One-Click',
|
||||
'List-Unsubscribe' => '<' . $unsubscribeUrl . '>',
|
||||
] : []
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool whether mailable contains variables requires for the footer
|
||||
*/
|
||||
protected function hasRequiredVariables(): bool
|
||||
{
|
||||
$included = [];
|
||||
$requiredVariables = static::getRequiredVariables();
|
||||
foreach ($requiredVariables as $requiredVariable) {
|
||||
foreach ($this->getVariables() as $variable) {
|
||||
if (is_a($variable, $requiredVariable, true)) {
|
||||
$included[] = $requiredVariable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count($included) === count($requiredVariables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace email template variables in the locale string, so they correspond to the application,
|
||||
* e.g., contextName => journalName/pressName/serverName
|
||||
*/
|
||||
protected function renameContextVariables(string $footer): string
|
||||
{
|
||||
$map = [
|
||||
'{$' . PKPContextEmailVariable::CONTEXT_NAME . '}' => '{$' . ContextEmailVariable::CONTEXT_NAME . '}',
|
||||
'{$' . PKPContextEmailVariable::CONTEXT_URL . '}' => '{$' . ContextEmailVariable::CONTEXT_URL . '}',
|
||||
'{$' . PKPContextEmailVariable::CONTEXT_SIGNATURE . '}' => '{$' . ContextEmailVariable::CONTEXT_SIGNATURE . '}',
|
||||
];
|
||||
|
||||
return str_replace(array_keys($map), array_values($map), $footer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the message to be displayed in the footer
|
||||
*/
|
||||
protected function setFooterText(string $locale, string $localeKey = null): string
|
||||
{
|
||||
if (is_null($localeKey)) {
|
||||
$localeKey = $this->defaultUnsubscribeLocaleKey;
|
||||
}
|
||||
|
||||
return __($localeKey, [], $locale);
|
||||
}
|
||||
|
||||
protected static function getRequiredVariables(): array
|
||||
{
|
||||
return static::$requiredVariables;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/transport/PHPMailerTransport.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 PHPMailerTransport.php
|
||||
*
|
||||
* @brief Transport/adapter to send with PHPMailer
|
||||
*/
|
||||
|
||||
namespace PKP\mail\transport;
|
||||
|
||||
use APP\core\Application;
|
||||
use Exception;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PKP\core\PKPString;
|
||||
use ReflectionObject;
|
||||
use Symfony\Component\Mailer\Envelope;
|
||||
use Symfony\Component\Mailer\SentMessage;
|
||||
use Symfony\Component\Mailer\Transport\TransportInterface;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Symfony\Component\Mime\RawMessage;
|
||||
|
||||
class PHPMailerTransport implements TransportInterface
|
||||
{
|
||||
public const MAIL_WRAP = 76;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function send(RawMessage $symfonyMessage, Envelope $envelope = null): ?SentMessage
|
||||
{
|
||||
if (!($symfonyMessage instanceof Email)) {
|
||||
throw new Exception('Can\'t send raw message with phpmailer');
|
||||
}
|
||||
|
||||
$phpmailerMessage = $this->getPHPMailerMessage($symfonyMessage);
|
||||
try {
|
||||
$success = $phpmailerMessage->Send();
|
||||
if (!$success) {
|
||||
error_log($phpmailerMessage->ErrorInfo);
|
||||
return null;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log($phpmailerMessage->ErrorInfo);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new SentMessage($symfonyMessage, $envelope ?? Envelope::create($symfonyMessage));
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return 'phpmailer';
|
||||
}
|
||||
|
||||
/**
|
||||
* We won't send symfony message; transfer data to PHPMailer to send with mail()
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function getPHPMailerMessage(Email $symfonyMessage): PHPMailer
|
||||
{
|
||||
$mailer = new PHPMailer();
|
||||
$mailer->isMail();
|
||||
$mailer->IsHTML();
|
||||
$mailer->Encoding = PHPMailer::ENCODING_BASE64;
|
||||
$mailer->CharSet = $symfonyMessage->getHtmlCharset() ?? 'utf-8';
|
||||
$mailer->XMailer = 'Public Knowledge Project Suite v3';
|
||||
$mailer->WordWrap = static::MAIL_WRAP;
|
||||
|
||||
$request = Application::get()->getRequest();
|
||||
$fromAddresses = $symfonyMessage->getFrom();
|
||||
if (!empty($fromAddresses)) {
|
||||
$f = array_shift($fromAddresses);
|
||||
if (!empty($fromAddresses)) {
|
||||
throw new Exception('Can\'t set multiple From email field value with PHPMailer');
|
||||
}
|
||||
$mailer->setFrom($f->getAddress(), $f->getName());
|
||||
}
|
||||
// Set the envelope sender (RFC5321.MailFrom)
|
||||
if (($s = $symfonyMessage->getSender()) != null) {
|
||||
$mailer->Sender = $s->toString();
|
||||
}
|
||||
foreach ($symfonyMessage->getReplyTo() as $r) {
|
||||
$mailer->addReplyTo($r->getAddress(), $r->getName());
|
||||
}
|
||||
foreach ($symfonyMessage->getTo() as $recipientInfo) {
|
||||
$mailer->addAddress($recipientInfo->getAddress(), $recipientInfo->getName());
|
||||
}
|
||||
foreach ($symfonyMessage->getCc() as $ccInfo) {
|
||||
$mailer->addCC($ccInfo->getAddress(), $ccInfo->getName());
|
||||
}
|
||||
foreach ($symfonyMessage->getBcc() as $bccInfo) {
|
||||
$mailer->addBCC($bccInfo->getAddress(), $bccInfo->getName());
|
||||
}
|
||||
$mailer->Subject = $symfonyMessage->getSubject();
|
||||
$mailer->Body = $symfonyMessage->getHtmlBody();
|
||||
$mailer->AltBody = PKPString::html2text($symfonyMessage->getHtmlBody());
|
||||
|
||||
$remoteAddr = $mailer->secureHeader($request->getRemoteAddr());
|
||||
if ($remoteAddr != '') {
|
||||
$mailer->addCustomHeader("X-Originating-IP: {$remoteAddr}");
|
||||
}
|
||||
|
||||
foreach ($this->getAttachments($symfonyMessage) as $attachmentInfo) {
|
||||
$mailer->addStringAttachment(
|
||||
$attachmentInfo['body'],
|
||||
$attachmentInfo['filename'],
|
||||
PHPMailer::ENCODING_BASE64,
|
||||
$attachmentInfo['mediaType'] . '/' . $attachmentInfo['subtype']
|
||||
);
|
||||
}
|
||||
|
||||
return $mailer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Symfony Message's assignments
|
||||
*/
|
||||
protected function getAttachments(Email $message): array
|
||||
{
|
||||
$attachments = [];
|
||||
foreach ($message->getAttachments() as $dataPart) {
|
||||
$reflection = new ReflectionObject($dataPart);
|
||||
$attachment = [];
|
||||
foreach ($reflection->getProperties() as $property) {
|
||||
switch ($property->getName()) {
|
||||
case 'filename':
|
||||
case 'mediaType':
|
||||
$property->setAccessible(true);
|
||||
$attachment[$property->getName()] = $property->getValue($dataPart);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$attachment['subtype'] = $dataPart->getMediaSubtype();
|
||||
$attachment['body'] = $dataPart->getBody();
|
||||
$attachments[] = $attachment;
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/variables/ContextEmailVariable.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 ContextEmailVariable
|
||||
*
|
||||
* @ingroup mail_variables
|
||||
*
|
||||
* @brief Represents variables that are associated with a given context (journal or press)
|
||||
*/
|
||||
|
||||
namespace PKP\mail\variables;
|
||||
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use PKP\context\Context;
|
||||
use PKP\core\Dispatcher;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\core\PKPString;
|
||||
use PKP\mail\Mailable;
|
||||
|
||||
class ContextEmailVariable extends Variable
|
||||
{
|
||||
public const CONTACT_NAME = 'contactName';
|
||||
public const CONTACT_EMAIL = 'contactEmail';
|
||||
public const CONTEXT_NAME = 'contextName';
|
||||
public const CONTEXT_SIGNATURE = 'contextSignature';
|
||||
public const CONTEXT_URL = 'contextUrl';
|
||||
public const MAILING_ADDRESS = 'mailingAddress';
|
||||
public const PASSWORD_LOST_URL = 'passwordLostUrl';
|
||||
public const SUBMISSIONS_URL = 'submissionsUrl';
|
||||
public const USER_PROFILE_URL = 'userProfileUrl';
|
||||
|
||||
protected Context $context;
|
||||
protected PKPRequest $request;
|
||||
protected Dispatcher $dispatcher;
|
||||
|
||||
public function __construct(Context $context, Mailable $mailable)
|
||||
{
|
||||
parent::__construct($mailable);
|
||||
|
||||
$this->context = $context;
|
||||
$application = PKPApplication::get();
|
||||
$this->request = $application->getRequest();
|
||||
$this->dispatcher = $application->getDispatcher();
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::descriptions()
|
||||
*/
|
||||
public static function descriptions(): array
|
||||
{
|
||||
return
|
||||
[
|
||||
static::CONTEXT_NAME => __('emailTemplate.variable.context.contextName'),
|
||||
static::CONTEXT_SIGNATURE => __('emailTemplate.variable.context.contextSignature'),
|
||||
static::CONTEXT_URL => __('emailTemplate.variable.context.contextUrl'),
|
||||
static::CONTACT_NAME => __('emailTemplate.variable.context.contactName'),
|
||||
static::CONTACT_EMAIL => __('emailTemplate.variable.context.contactEmail'),
|
||||
static::MAILING_ADDRESS => __('emailTemplate.variable.context.mailingAddress'),
|
||||
static::PASSWORD_LOST_URL => __('emailTemplate.variable.context.passwordLostUrl'),
|
||||
static::SUBMISSIONS_URL => __('emailTemplate.variable.context.submissionsUrl'),
|
||||
static::USER_PROFILE_URL => __('emailTemplate.variable.context.userProfileUrl'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::values()
|
||||
*/
|
||||
public function values(string $locale): array
|
||||
{
|
||||
return
|
||||
[
|
||||
static::CONTEXT_NAME => htmlspecialchars($this->context->getLocalizedData('name', $locale)),
|
||||
static::CONTEXT_URL => $this->getContextUrl(),
|
||||
static::CONTACT_NAME => htmlspecialchars((string) $this->context->getData('contactName')),
|
||||
static::CONTACT_EMAIL => htmlspecialchars((string) $this->context->getData('contactEmail')),
|
||||
static::MAILING_ADDRESS => PKPString::stripUnsafeHtml((string) $this->context->getData('mailingAddress')),
|
||||
static::PASSWORD_LOST_URL => $this->getPasswordLostUrl(),
|
||||
static::SUBMISSIONS_URL => $this->getSubmissionsUrl(),
|
||||
static::USER_PROFILE_URL => $this->getUserProfileUrl(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve context; required to generate other email template variables
|
||||
*/
|
||||
public function getContextFromVariable(): Context
|
||||
{
|
||||
return $this->context;
|
||||
}
|
||||
|
||||
protected function getContextUrl(): string
|
||||
{
|
||||
return $this->dispatcher->url($this->request, PKPApplication::ROUTE_PAGE, $this->context->getData('urlPath'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CONTEXT_SIGNATURE and render the variable values
|
||||
* in the signature
|
||||
*
|
||||
* @param array $values The values of this email variable
|
||||
*/
|
||||
protected function getContextSignature(array $values): string
|
||||
{
|
||||
$signature = Mail::compileParams(
|
||||
PKPString::stripUnsafeHtml((string) $this->context->getData('emailSignature')),
|
||||
$values
|
||||
);
|
||||
return $signature
|
||||
? PKPString::stripUnsafeHtml($signature)
|
||||
: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the lost password page
|
||||
*/
|
||||
protected function getPasswordLostUrl(): string
|
||||
{
|
||||
return $this->dispatcher->url($this->request, PKPApplication::ROUTE_PAGE, $this->context->getData('urlPath'), 'login', 'lostPassword');
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the submissions lists
|
||||
*/
|
||||
protected function getSubmissionsUrl(): string
|
||||
{
|
||||
return $this->dispatcher->url(
|
||||
$this->request,
|
||||
PKPApplication::ROUTE_PAGE,
|
||||
$this->context->getPath(),
|
||||
'submissions',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the user profile page
|
||||
*/
|
||||
protected function getUserProfileUrl(): string
|
||||
{
|
||||
return $this->dispatcher->url(
|
||||
$this->request,
|
||||
PKPApplication::ROUTE_PAGE,
|
||||
$this->context->getPath(),
|
||||
'user',
|
||||
'profile'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/variables/DecisionEmailVariable.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 DecisionEmailVariable
|
||||
*
|
||||
* @ingroup mail_variables
|
||||
*
|
||||
* @brief Represents variables associated with an editorial decision
|
||||
*/
|
||||
|
||||
namespace PKP\mail\variables;
|
||||
|
||||
use APP\decision\Decision;
|
||||
use APP\facades\Repo;
|
||||
use PKP\decision\DecisionType;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\workflow\WorkflowStageDAO;
|
||||
|
||||
class DecisionEmailVariable extends Variable
|
||||
{
|
||||
public const DECISION = 'decision';
|
||||
public const DESCRIPTION = 'decisionDescription';
|
||||
public const STAGE = 'decisionStage';
|
||||
public const ROUND = 'decisionReviewRound';
|
||||
|
||||
protected Decision $decision;
|
||||
protected DecisionType $decisionType;
|
||||
|
||||
public function __construct(Decision $decision, Mailable $mailable)
|
||||
{
|
||||
parent::__construct($mailable);
|
||||
|
||||
$this->decision = $decision;
|
||||
$this->decisionType = Repo::decision()->getDecisionType($decision->getData('decision'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::descriptions()
|
||||
*/
|
||||
public static function descriptions(): array
|
||||
{
|
||||
return
|
||||
[
|
||||
self::DECISION => __('emailTemplate.variable.decision.name'),
|
||||
self::DESCRIPTION => __('emailTemplate.variable.decision.description'),
|
||||
self::STAGE => __('emailTemplate.variable.decision.stage'),
|
||||
self::ROUND => __('emailTemplate.variable.decision.round'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::values()
|
||||
*/
|
||||
public function values(string $locale): array
|
||||
{
|
||||
return
|
||||
[
|
||||
self::DECISION => $this->decisionType->getLabel($locale),
|
||||
self::DESCRIPTION => $this->decisionType->getDescription($locale),
|
||||
self::STAGE => $this->getStageName($locale),
|
||||
self::ROUND => (string) $this->decision->getData('round'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function getStageName(string $locale): string
|
||||
{
|
||||
return __(
|
||||
(string) WorkflowStageDAO::getTranslationKeyFromId($this->decision->getData('stageId')),
|
||||
[],
|
||||
$locale
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/variables/QueuedPaymentEmailVariable.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 QueuedPaymentEmailVariable
|
||||
*
|
||||
* @ingroup mail_variables
|
||||
*
|
||||
* @brief Represents email template variables that are associated with payments
|
||||
*/
|
||||
|
||||
namespace PKP\mail\variables;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\payment\QueuedPayment;
|
||||
|
||||
class QueuedPaymentEmailVariable extends Variable
|
||||
{
|
||||
public const PAYMENT_NAME = 'paymentName';
|
||||
public const PAYMENT_AMOUNT = 'paymentAmount';
|
||||
public const PAYMENT_CURRENCY_CODE = 'paymentCurrencyCode';
|
||||
|
||||
protected QueuedPayment $queuedPayment;
|
||||
|
||||
public function __construct(QueuedPayment $queuedPayment, Mailable $mailable)
|
||||
{
|
||||
parent::__construct($mailable);
|
||||
|
||||
$this->queuedPayment = $queuedPayment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Validation::descriptions()
|
||||
*/
|
||||
public static function descriptions(): array
|
||||
{
|
||||
return
|
||||
[
|
||||
self::PAYMENT_NAME => __('emailTemplate.variable.queuedPayment.itemName'),
|
||||
self::PAYMENT_AMOUNT => __('emailTemplate.variable.queuedPayment.itemCost'),
|
||||
self::PAYMENT_CURRENCY_CODE => __('emailTemplate.variable.queuedPayment.itemCurrencyCode'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Validation::values()
|
||||
*/
|
||||
public function values(string $locale): array
|
||||
{
|
||||
return
|
||||
[
|
||||
self::PAYMENT_NAME => htmlspecialchars($this->getItemName()),
|
||||
self::PAYMENT_AMOUNT => (string) $this->getItemCost(),
|
||||
self::PAYMENT_CURRENCY_CODE => (string) $this->getItemCurrencyCode(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function getItemName(): string
|
||||
{
|
||||
$context = $this->getContext();
|
||||
$paymentManager = Application::getPaymentManager($context);
|
||||
return $paymentManager->getPaymentName($this->queuedPayment);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float|int|string|null
|
||||
*/
|
||||
protected function getItemCost()
|
||||
{
|
||||
return $this->queuedPayment->getAmount();
|
||||
}
|
||||
|
||||
protected function getItemCurrencyCode(): ?string
|
||||
{
|
||||
return $this->queuedPayment->getCurrencyCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/variables/RecipientEmailVariable.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 RecipientEmailVariable
|
||||
*
|
||||
* @ingroup mail_variables
|
||||
*
|
||||
* @brief Represents variables that are associated with an email recipient
|
||||
*/
|
||||
|
||||
namespace PKP\mail\variables;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use PKP\identity\Identity;
|
||||
use PKP\mail\Mailable;
|
||||
|
||||
class RecipientEmailVariable extends Variable
|
||||
{
|
||||
public const RECIPIENT_FULL_NAME = 'recipientName';
|
||||
public const RECIPIENT_USERNAME = 'recipientUsername';
|
||||
|
||||
/** @var iterable<Identity> */
|
||||
protected iterable $recipients;
|
||||
|
||||
public function __construct(iterable $recipients, Mailable $mailable)
|
||||
{
|
||||
parent::__construct($mailable);
|
||||
|
||||
foreach ($recipients as $recipient) {
|
||||
if (!is_a($recipient, Identity::class)) {
|
||||
throw new InvalidArgumentException('recipient array values should be an instances or ancestors of ' . Identity::class . ', ' . get_class($recipient) . ' is given');
|
||||
}
|
||||
}
|
||||
|
||||
$this->recipients = $recipients;
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::descriptions()
|
||||
*/
|
||||
public static function descriptions(): array
|
||||
{
|
||||
return
|
||||
[
|
||||
self::RECIPIENT_FULL_NAME => __('emailTemplate.variable.recipient.userFullName'),
|
||||
self::RECIPIENT_USERNAME => __('emailTemplate.variable.recipient.username'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::values()
|
||||
*/
|
||||
public function values(string $locale): array
|
||||
{
|
||||
return
|
||||
[
|
||||
self::RECIPIENT_FULL_NAME => htmlspecialchars($this->getRecipientsFullName($locale)),
|
||||
self::RECIPIENT_USERNAME => htmlspecialchars($this->getRecipientsUserName()),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Full names of recipients in all supported locales separated by a comma
|
||||
*/
|
||||
protected function getRecipientsFullName(string $locale): string
|
||||
{
|
||||
$names = [];
|
||||
foreach ($this->recipients as $recipient) {
|
||||
$names[] = $recipient->getFullName(true, false, $locale);
|
||||
}
|
||||
|
||||
return join(__('common.commaListSeparator'), $names);
|
||||
}
|
||||
|
||||
/**
|
||||
* Usernames of recipients separated by a comma
|
||||
*/
|
||||
protected function getRecipientsUserName(): string
|
||||
{
|
||||
$userNames = [];
|
||||
foreach ($this->recipients as $recipient) {
|
||||
$userNames[] = $recipient->getData('userName');
|
||||
}
|
||||
return join(__('common.commaListSeparator'), $userNames);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/variables/ReviewAssignmentEmailVariable.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 ReviewAssignmentEmailVariable
|
||||
*
|
||||
* @ingroup mail_variables
|
||||
*
|
||||
* @brief Represents email template variables that are associated with a review assignment
|
||||
*/
|
||||
|
||||
namespace PKP\mail\variables;
|
||||
|
||||
use PKP\context\Context;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\core\PKPString;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
|
||||
class ReviewAssignmentEmailVariable extends Variable
|
||||
{
|
||||
public const RESPONSE_DUE_DATE = 'responseDueDate';
|
||||
public const REVIEW_ASSIGNED_DATE = 'reviewAssignedDate';
|
||||
public const REVIEW_ASSIGNMENT_URL = 'reviewAssignmentUrl';
|
||||
public const REVIEW_DUE_DATE = 'reviewDueDate';
|
||||
public const REVIEW_METHOD = 'reviewMethod';
|
||||
public const REVIEW_RECOMMENDATION = 'reviewRecommendation';
|
||||
public const REVIEW_ROUND = 'reviewRound';
|
||||
public const REVIEWER_NAME = 'reviewerName';
|
||||
|
||||
protected ReviewAssignment $reviewAssignment;
|
||||
|
||||
public function __construct(ReviewAssignment $reviewAssignment, Mailable $mailable)
|
||||
{
|
||||
parent::__construct($mailable);
|
||||
|
||||
$this->reviewAssignment = $reviewAssignment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::descriptions()
|
||||
*/
|
||||
public static function descriptions(): array
|
||||
{
|
||||
return
|
||||
[
|
||||
self::RESPONSE_DUE_DATE => __('emailTemplate.variable.recipient.responseDueDate'),
|
||||
self::REVIEW_ASSIGNED_DATE => __('emailTemplate.variable.review.assignedDate'),
|
||||
self::REVIEW_ASSIGNMENT_URL => __('emailTemplate.variable.recipient.reviewAssignmentUrl'),
|
||||
self::REVIEW_DUE_DATE => __('emailTemplate.variable.recipient.reviewDueDate'),
|
||||
self::REVIEW_METHOD => __('emailTemplate.variable.review.method'),
|
||||
self::REVIEW_RECOMMENDATION => __('emailTemplate.variable.review.recommendation'),
|
||||
self::REVIEW_ROUND => __('emailTemplate.variable.review.round'),
|
||||
self::REVIEWER_NAME => __('emailTemplate.variable.review.name'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::values()
|
||||
*/
|
||||
public function values(string $locale): array
|
||||
{
|
||||
$context = $this->getContext();
|
||||
|
||||
return
|
||||
[
|
||||
self::RESPONSE_DUE_DATE => $this->formatDate((string) $this->reviewAssignment->getDateResponseDue(), $locale, $context) ?? '{$' . self::RESPONSE_DUE_DATE . '}',
|
||||
self::REVIEW_ASSIGNED_DATE => $this->formatDate((string) $this->reviewAssignment->getDateAssigned(), $locale, $context) ?? '{$' . self::REVIEW_ASSIGNED_DATE . '}',
|
||||
self::REVIEW_ASSIGNMENT_URL => $this->getReviewUrl($context),
|
||||
self::REVIEW_DUE_DATE => $this->formatDate((string) $this->reviewAssignment->getDateDue(), $locale, $context) ?? '{$' . self::REVIEW_DUE_DATE . '}',
|
||||
self::REVIEW_METHOD => $this->getReviewMethod($locale),
|
||||
self::REVIEW_RECOMMENDATION => $this->getRecommendation($locale),
|
||||
self::REVIEW_ROUND => __('common.reviewRoundNumber', ['round' => $this->reviewAssignment->getRound()], $locale),
|
||||
self::REVIEWER_NAME => $this->reviewAssignment->getReviewerFullName(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function formatDate(string $date, string $locale, Context $context): ?string
|
||||
{
|
||||
$time = strtotime($date);
|
||||
|
||||
if ($time === -1 || $time === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$format = PKPString::convertStrftimeFormat($context->getLocalizedDateFormatShort($locale));
|
||||
|
||||
return date($format, $time);
|
||||
}
|
||||
|
||||
protected function getRecommendation(string $locale): string
|
||||
{
|
||||
$recommendationOptions = ReviewAssignment::getReviewerRecommendationOptions();
|
||||
|
||||
return isset($recommendationOptions[$this->reviewAssignment->getRecommendation()])
|
||||
? __($recommendationOptions[$this->reviewAssignment->getRecommendation()], [], $locale)
|
||||
: __('common.none', [], $locale);
|
||||
}
|
||||
|
||||
protected function getReviewMethod(string $locale): string
|
||||
{
|
||||
if (!$this->reviewAssignment->getReviewMethod()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return __(
|
||||
$this->reviewAssignment->getReviewMethodKey(),
|
||||
[],
|
||||
$locale
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL of the submission for the assigned reviewer
|
||||
*/
|
||||
protected function getReviewUrl(Context $context): string
|
||||
{
|
||||
$application = PKPApplication::get();
|
||||
$request = $application->getRequest();
|
||||
$dispatcher = $application->getDispatcher();
|
||||
return $dispatcher->url(
|
||||
$request,
|
||||
PKPApplication::ROUTE_PAGE,
|
||||
$context->getData('urlPath'),
|
||||
'reviewer',
|
||||
'submission',
|
||||
null,
|
||||
['submissionId' => $this->reviewAssignment->getSubmissionId()]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/variables/SenderEmailVariable.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 SenderEmailVariable
|
||||
*
|
||||
* @ingroup mail_variables
|
||||
*
|
||||
* @brief Represents variables that are associated with an email sender
|
||||
*/
|
||||
|
||||
namespace PKP\mail\variables;
|
||||
|
||||
use PKP\core\PKPString;
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\user\User;
|
||||
|
||||
class SenderEmailVariable extends Variable
|
||||
{
|
||||
public const SENDER_NAME = 'senderName';
|
||||
public const SENDER_EMAIL = 'senderEmail';
|
||||
public const SENDER_CONTACT_SIGNATURE = 'signature';
|
||||
|
||||
protected User $sender;
|
||||
|
||||
public function __construct(User $sender, Mailable $mailable)
|
||||
{
|
||||
parent::__construct($mailable);
|
||||
|
||||
$this->sender = $sender;
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::descriptions()
|
||||
*/
|
||||
public static function descriptions(): array
|
||||
{
|
||||
return
|
||||
[
|
||||
self::SENDER_NAME => __('emailTemplate.variable.sender.senderName'),
|
||||
self::SENDER_EMAIL => __('emailTemplate.variable.sender.senderEmail'),
|
||||
self::SENDER_CONTACT_SIGNATURE => __('emailTemplate.variable.sender.signature'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::values()
|
||||
*/
|
||||
public function values(string $locale): array
|
||||
{
|
||||
return
|
||||
[
|
||||
self::SENDER_NAME => htmlspecialchars($this->sender->getFullName(true, false, $locale)),
|
||||
self::SENDER_EMAIL => htmlspecialchars($this->sender->getData('email')),
|
||||
self::SENDER_CONTACT_SIGNATURE => $this->getSignature($locale),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sender's contact signature
|
||||
*/
|
||||
protected function getSignature(string $locale): string
|
||||
{
|
||||
$signature = $this->sender->getSignature($locale);
|
||||
return $signature
|
||||
? PKPString::stripUnsafeHtml($signature)
|
||||
: '<p>' . htmlspecialchars($this->sender->getFullName(true, false, $locale)) . '</p>';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/variables/SiteEmailVariable.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 SiteEmailVariable
|
||||
*
|
||||
* @ingroup mail_variables
|
||||
*
|
||||
* @brief Represents variables that are associated with a website
|
||||
*/
|
||||
|
||||
namespace PKP\mail\variables;
|
||||
|
||||
use PKP\mail\Mailable;
|
||||
use PKP\site\Site;
|
||||
|
||||
class SiteEmailVariable extends Variable
|
||||
{
|
||||
public const SITE_TITLE = 'siteTitle';
|
||||
public const SITE_CONTACT = 'siteContactName';
|
||||
public const SITE_EMAIL = 'siteContactEmail';
|
||||
public const SITE_SIGNATURE = 'siteSignature';
|
||||
|
||||
protected Site $site;
|
||||
|
||||
public function __construct(Site $site, Mailable $mailable)
|
||||
{
|
||||
parent::__construct($mailable);
|
||||
|
||||
$this->site = $site;
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::descriptions()
|
||||
*/
|
||||
public static function descriptions(): array
|
||||
{
|
||||
return
|
||||
[
|
||||
self::SITE_TITLE => __('emailTemplate.variable.site.siteTitle'),
|
||||
self::SITE_CONTACT => __('emailTemplate.variable.site.siteContactName'),
|
||||
self::SITE_EMAIL => __('emailTemplate.variable.site.siteContactEmail'),
|
||||
self::SITE_SIGNATURE => __('emailTemplate.variable.site.siteSignature'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::values()
|
||||
*/
|
||||
public function values(string $locale): array
|
||||
{
|
||||
return
|
||||
[
|
||||
self::SITE_TITLE => htmlspecialchars($this->site->getLocalizedData('title', $locale)),
|
||||
self::SITE_CONTACT => htmlspecialchars($this->site->getLocalizedData('contactName', $locale)),
|
||||
self::SITE_EMAIL => htmlspecialchars($this->site->getLocalizedData('contactEmail', $locale)),
|
||||
self::SITE_SIGNATURE => '<p>' .
|
||||
htmlspecialchars($this->site->getLocalizedData('contactName', $locale)) . '<br/>' .
|
||||
htmlspecialchars($this->site->getLocalizedData('title', $locale)) .
|
||||
'</p>',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/variables/SubmissionEmailVariable.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 SubmissionEmailVariable
|
||||
*
|
||||
* @ingroup mail_variables
|
||||
*
|
||||
* @brief Represents variables associated with a submission that can be assigned to a template
|
||||
*/
|
||||
|
||||
namespace PKP\mail\variables;
|
||||
|
||||
use APP\publication\Publication;
|
||||
use APP\submission\Submission;
|
||||
use PKP\author\Author;
|
||||
use PKP\context\Context;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\core\PKPString;
|
||||
use PKP\mail\Mailable;
|
||||
|
||||
abstract class SubmissionEmailVariable extends Variable
|
||||
{
|
||||
public const AUTHOR_SUBMISSION_URL = 'authorSubmissionUrl';
|
||||
public const AUTHORS = 'authors';
|
||||
public const AUTHORS_SHORT = 'authorsShort';
|
||||
public const SUBMISSION_ABSTRACT = 'submissionAbstract';
|
||||
public const SUBMISSION_ID = 'submissionId';
|
||||
public const SUBMISSION_PUBLISHED_URL = 'submissionPublishedUrl';
|
||||
public const SUBMISSION_TITLE = 'submissionTitle';
|
||||
public const SUBMISSION_URL = 'submissionUrl';
|
||||
public const SUBMISSION_WIZARD_URL = 'submissionWizardUrl';
|
||||
|
||||
protected Submission $submission;
|
||||
protected Publication $currentPublication;
|
||||
|
||||
public function __construct(Submission $submission, Mailable $mailable)
|
||||
{
|
||||
parent::__construct($mailable);
|
||||
|
||||
$this->submission = $submission;
|
||||
$this->currentPublication = $this->submission->getCurrentPublication();
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::descriptions()
|
||||
*/
|
||||
public static function descriptions(): array
|
||||
{
|
||||
return
|
||||
[
|
||||
self::AUTHOR_SUBMISSION_URL => __('emailTemplate.variable.submission.authorSubmissionUrl'),
|
||||
self::AUTHORS => __('emailTemplate.variable.submission.authors'),
|
||||
self::AUTHORS_SHORT => __('emailTemplate.variable.submission.authorsShort'),
|
||||
self::SUBMISSION_ABSTRACT => __('emailTemplate.variable.submission.submissionAbstract'),
|
||||
self::SUBMISSION_ID => __('emailTemplate.variable.submission.submissionId'),
|
||||
self::SUBMISSION_PUBLISHED_URL => __('emailTemplate.variable.submission.submissionPublishedUrl'),
|
||||
self::SUBMISSION_TITLE => __('emailTemplate.variable.submission.submissionTitle'),
|
||||
self::SUBMISSION_URL => __('emailTemplate.variable.submission.submissionUrl'),
|
||||
self::SUBMISSION_WIZARD_URL => __('emailTemplate.variable.submission.submissionWizardUrl'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Variable::values()
|
||||
*/
|
||||
public function values(string $locale): array
|
||||
{
|
||||
$context = $this->getContext();
|
||||
return
|
||||
[
|
||||
self::AUTHOR_SUBMISSION_URL => $this->getAuthorSubmissionUrl($context),
|
||||
self::AUTHORS => htmlspecialchars($this->getAuthorsFull($locale)),
|
||||
self::AUTHORS_SHORT => htmlspecialchars($this->currentPublication->getShortAuthorString($locale)),
|
||||
self::SUBMISSION_ABSTRACT => PKPString::stripUnsafeHtml($this->currentPublication->getLocalizedData('abstract', $locale)),
|
||||
self::SUBMISSION_ID => (string) $this->submission->getId(),
|
||||
self::SUBMISSION_PUBLISHED_URL => $this->getSubmissionPublishedUrl($this->getContext()),
|
||||
self::SUBMISSION_TITLE => $this->currentPublication->getLocalizedFullTitle($locale, 'html'),
|
||||
self::SUBMISSION_URL => $this->getSubmissionUrl($context),
|
||||
self::SUBMISSION_WIZARD_URL => $this->getSubmissionWizardUrl($context),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* List of authors as a string separated by a comma
|
||||
*/
|
||||
protected function getAuthorsFull(string $locale): string
|
||||
{
|
||||
$authors = $this->currentPublication->getData('authors');
|
||||
$fullNames = array_map(function (Author $author) use ($locale) {
|
||||
return $author->getFullName(true, false, $locale);
|
||||
}, iterator_to_array($authors));
|
||||
|
||||
return join(__('common.commaListSeparator'), $fullNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the author's submission workflow
|
||||
*/
|
||||
protected function getAuthorSubmissionUrl(Context $context): string
|
||||
{
|
||||
$request = PKPApplication::get()->getRequest();
|
||||
return $request->getDispatcher()->url(
|
||||
$request,
|
||||
PKPApplication::ROUTE_PAGE,
|
||||
$context->getData('urlPath'),
|
||||
'authorDashboard',
|
||||
'submission',
|
||||
[
|
||||
$this->submission->getId(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to a current workflow stage of the submission
|
||||
*/
|
||||
protected function getSubmissionUrl(Context $context): string
|
||||
{
|
||||
$application = PKPApplication::get();
|
||||
$request = $application->getRequest();
|
||||
$dispatcher = $application->getDispatcher();
|
||||
return $dispatcher->url(
|
||||
$request,
|
||||
PKPApplication::ROUTE_PAGE,
|
||||
$context->getData('urlPath'),
|
||||
'workflow',
|
||||
'access',
|
||||
$this->submission->getId()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the submission in the submission wizard
|
||||
*/
|
||||
protected function getSubmissionWizardUrl(Context $context): string
|
||||
{
|
||||
$application = PKPApplication::get();
|
||||
$request = $application->getRequest();
|
||||
$dispatcher = $application->getDispatcher();
|
||||
return $dispatcher->url(
|
||||
$request,
|
||||
PKPApplication::ROUTE_PAGE,
|
||||
$context->getPath(),
|
||||
'submission',
|
||||
null,
|
||||
null,
|
||||
[
|
||||
'id' => $this->submission->getId(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the published submission
|
||||
*/
|
||||
abstract protected function getSubmissionPublishedUrl(Context $context): string;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/mail/variables/Variable.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 Variable
|
||||
*
|
||||
* @ingroup mail_variables
|
||||
*
|
||||
* @brief A base class for email template variables
|
||||
*/
|
||||
|
||||
namespace PKP\mail\variables;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Arr;
|
||||
use PKP\context\Context;
|
||||
use PKP\mail\Mailable;
|
||||
|
||||
abstract class Variable
|
||||
{
|
||||
protected Mailable $mailable;
|
||||
|
||||
public function __construct(Mailable $mailable)
|
||||
{
|
||||
$this->mailable = $mailable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve mailable context from associated variables, see pkp/pkp-lib#8204
|
||||
*/
|
||||
protected function getContext(): Context
|
||||
{
|
||||
$contextEmailVariable = Arr::first($this->mailable->getVariables(), function (Variable $variable) {
|
||||
return $variable instanceof ContextEmailVariable;
|
||||
});
|
||||
|
||||
if (!$contextEmailVariable) {
|
||||
throw new Exception(static::class . ' is unable to generate email variables without providing the context to the Mailable');
|
||||
}
|
||||
|
||||
return $contextEmailVariable->getContextFromVariable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get descriptions of the variables provided by this class
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
abstract public static function descriptions(): array;
|
||||
|
||||
/**
|
||||
* Get the value of variables supported by this class
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
abstract public function values(string $locale): array;
|
||||
}
|
||||
Reference in New Issue
Block a user