first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-06-08 17:09:23 -04:00
commit df3a033196
17887 changed files with 8637778 additions and 0 deletions
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/events/BatchMetadataChanged.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 BatchMetadataChanged
*
* @ingroup core
*
* @brief Event fired when metadata changes batch as called
*/
namespace PKP\observers\events;
use Illuminate\Foundation\Events\Dispatchable;
class BatchMetadataChanged
{
use Dispatchable;
/** @var array $submissionIds Submission ids associated */
public $submissionIds;
public function __construct(array $submissionIds = [])
{
$this->submissionIds = $submissionIds;
}
}
@@ -0,0 +1,66 @@
<?php
/**
* @file classes/observers/events/DecisionAdded.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 DecisionAdded
*
* @ingroup observers_events
*
* @brief An event fired when an editorial decision is recorded.
*/
namespace PKP\observers\events;
use APP\decision\Decision;
use APP\submission\Submission;
use Illuminate\Foundation\Events\Dispatchable;
use PKP\context\Context;
use PKP\decision\DecisionType;
use PKP\user\User;
class DecisionAdded
{
use Dispatchable;
/** The decision that was recorded */
public Decision $decision;
/** The type of decision that was recorded */
public DecisionType $decisionType;
/** The journal, press or preprint server this decision was recorded in */
public Context $context;
/** The submission for which this decision was recorded */
public Submission $submission;
/** The editor who recorded the decision */
public User $editor;
/**
* Any additional actions that were requested when this
* decision was recorded.
*
* Actions include emails sent, files promoted, and other form
* data submitted when the decision was recorded. Each decision
* supports different actions. See the REST API documentation
* for more information about what actions to expect with each
* decision.
*/
public array $actions;
public function __construct(Decision $decision, DecisionType $decisionType, Submission $submission, User $editor, Context $context, array $actions)
{
$this->actions = $actions;
$this->context = $context;
$this->decision = $decision;
$this->decisionType = $decisionType;
$this->editor = $editor;
$this->submission = $submission;
}
}
@@ -0,0 +1,32 @@
<?php
/**
* @file classes/observers/events/MessageSendingFromContext.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 MessageSendingFromContext
*
* @ingroup observers_events
*
* @brief overrides Illuminate event which is fired just before sending email message from the journal/press
*/
namespace PKP\observers\events;
use Illuminate\Mail\Events\MessageSending as IlluminateMessageSending;
use PKP\context\Context;
use Symfony\Component\Mime\Email as SymfonyEmail;
class MessageSendingFromContext extends IlluminateMessageSending
{
public Context $context;
public function __construct(Context $context, SymfonyEmail $message, array $data = [])
{
parent::__construct($message, $data);
$this->context = $context;
}
}
@@ -0,0 +1,32 @@
<?php
/**
* @file classes/observers/events/MessageSendingFromSite.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 MessageSendingFromSite
*
* @ingroup observers_events
*
* @brief overrides Illuminate event which is fired just before sending email message from the site
*/
namespace PKP\observers\events;
use Illuminate\Mail\Events\MessageSending as IlluminateMessageSending;
use PKP\site\Site;
use Symfony\Component\Mime\Email as SymfonyEmail;
class MessageSendingFromSite extends IlluminateMessageSending
{
public Site $site;
public function __construct(Site $site, SymfonyEmail $message, array $data = [])
{
parent::__construct($message, $data);
$this->site = $site;
}
}
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/events/MetadataChanged.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 MetadataChanged
*
* @ingroup core
*
* @brief Event fired when metadata changed
*/
namespace PKP\observers\events;
use Illuminate\Foundation\Events\Dispatchable;
use PKP\submission\PKPSubmission;
class MetadataChanged
{
use Dispatchable;
/** @var PKPSubmission $submission Submission associated */
public $submission;
public function __construct(PKPSubmission $submission)
{
$this->submission = $submission;
}
}
@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/events/PluginSettingChanged.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 PluginSettingChanged
*
* @ingroup observers_events
*
* @brief Event fired when a plugin's setting is changed, including whether
* it is enabled or disabled.
*/
namespace PKP\observers\events;
use Illuminate\Foundation\Events\Dispatchable;
use PKP\plugins\Plugin;
class PluginSettingChanged
{
use Dispatchable;
public Plugin $plugin;
public string $settingName;
public mixed $newValue;
public ?int $contextId;
public function __construct(
Plugin $plugin,
string $settingName,
$newValue,
?int $contextId = null
) {
$this->plugin = $plugin;
$this->settingName = $settingName;
$this->newValue = $newValue;
$this->contextId = $contextId;
}
}
@@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/events/PublicationPublished.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 PublicationPublished
*
* @ingroup observers_events
*
* @brief Event fired when publication is published
*/
namespace PKP\observers\events;
use APP\publication\Publication;
use APP\submission\Submission;
use Illuminate\Foundation\Events\Dispatchable;
use PKP\context\Context;
class PublicationPublished
{
use Dispatchable;
/** @var Publication $publication The publication that was published */
public Publication $publication;
/** @var Publication $publication The publication before it was published */
public Publication $oldPublication;
public Submission $submission;
public Context $context;
/**
* Class construct
*
* @param Publication $publication The publication that was published
* @param Publication $oldPublication The publication before it was published
*/
public function __construct(
Publication $publication,
Publication $oldPublication,
Submission $submission,
Context $context
) {
$this->publication = $publication;
$this->oldPublication = $oldPublication;
$this->submission = $submission;
$this->context = $context;
}
}
@@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/events/PublicationUnpublished.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 PublicationUnpublished
*
* @ingroup core
*
* @brief Event fired when publication is being unpublished
*/
namespace PKP\observers\events;
use APP\publication\Publication;
use APP\submission\Submission;
use Illuminate\Foundation\Events\Dispatchable;
use PKP\context\Context;
class PublicationUnpublished
{
use Dispatchable;
/** @var Publication $publication The publication that was unpublished */
public Publication $publication;
/** @var Publication $publication The publication before it was unpublished */
public Publication $oldPublication;
public Submission $submission;
public Context $context;
/**
* Class construct
*
* @param Publication $publication The publication that was unpublished
* @param Publication $oldPublication The publication before it was unpublished
*/
public function __construct(
Publication $publication,
Publication $oldPublication,
Submission $submission,
Context $context
) {
$this->publication = $publication;
$this->oldPublication = $oldPublication;
$this->submission = $submission;
$this->context = $context;
}
}
@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/events/SubmissionDeleted.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 SubmissionDeleted
*
* @ingroup core
*
* @brief Event fired when submission's deleted
*/
namespace PKP\observers\events;
use Illuminate\Foundation\Events\Dispatchable;
class SubmissionDeleted
{
use Dispatchable;
/**
* The submission id of the targeted submission to delete
*/
public int $submissionId;
public function __construct(int $submissionId)
{
$this->submissionId = $submissionId;
}
}
@@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/events/SubmissionFileDeleted.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 SubmissionFileDeleted
*
* @ingroup core
*
* @brief Event fired when submission's deleted
*/
namespace PKP\observers\events;
use Illuminate\Foundation\Events\Dispatchable;
class SubmissionFileDeleted
{
use Dispatchable;
/**
* The submission id of the targeted submission
*/
public int $submissionId;
/**
* The submission file id of the targeted submission file to delete
*/
public int $submissionFileId;
public function __construct(int $submissionId, int $submissionFileId)
{
$this->submissionId = $submissionId;
$this->submissionFileId = $submissionFileId;
}
}
@@ -0,0 +1,31 @@
<?php
/**
* @file classes/observers/events/SubmissionSubmitted.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 SubmissionSubmitted
*
* @ingroup observers_events
*
* @brief Event fired when a submission is submitted.
*/
namespace PKP\observers\events;
use APP\submission\Submission;
use PKP\context\Context;
class SubmissionSubmitted
{
public Context $context;
public Submission $submission;
public function __construct(Submission $submission, Context $context)
{
$this->context = $context;
$this->submission = $submission;
}
}
@@ -0,0 +1,180 @@
<?php
/**
* @file classes/observers/events/UsageEvent.php
*
* Copyright (c) 2022 Simon Fraser University
* Copyright (c) 2022 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class UsageEvent
*
* @ingroup observers_events
*
* @brief Base class for the usage event used to record usage logs.
*/
namespace PKP\observers\events;
use APP\core\Application;
use APP\core\PageRouter;
use APP\core\Request;
use APP\submission\Submission;
use Exception;
use Illuminate\Foundation\Events\Dispatchable;
use PKP\config\Config;
use PKP\context\Context;
use PKP\core\Core;
use PKP\core\Registry;
use PKP\submission\Representation;
use PKP\submissionFile\SubmissionFile;
abstract class UsageEvent
{
use Dispatchable;
/** Current time */
public string $time;
/** Viewed/downloaded object, one of the Application::ASSOC_TYPE_... constants */
public int $assocType;
/** Canonical URL for the pub object */
public string $canonicalUrl;
public Request $request;
public Context $context;
public ?Submission $submission;
/** Representation (galley or publication format) */
public ?Representation $representation;
public ?SubmissionFile $submissionFile;
/** Application's complete version string */
public string $version;
/**
* Create a new usage event instance.
*/
public function __construct(
int $assocType,
Context $context,
Submission $submission = null,
Representation $representation = null,
SubmissionFile $submissionFile = null
) {
$this->time = Core::getCurrentDate();
$this->assocType = $assocType;
$this->context = $context;
$this->submission = $submission;
$this->representation = $representation;
$this->submissionFile = $submissionFile;
$this->version = Registry::get('appVersion');
$this->request = Application::get()->getRequest();
$this->canonicalUrl = $this->getCanonicalUrl();
}
/**
* Get the canonical URL for the usage object
*
* @throws Exception
*/
protected function getCanonicalUrl(): string
{
$canonicalUrlPage = $canonicalUrlOp = null;
$canonicalUrlParams = [];
switch ($this->assocType) {
case Application::ASSOC_TYPE_SUBMISSION_FILE_COUNTER_OTHER:
case Application::ASSOC_TYPE_SUBMISSION_FILE:
$canonicalUrlOp = 'download';
$canonicalUrlParams = [$this->submission->getId()];
$router = $this->request->getRouter(); /** @var PageRouter $router */
$op = $router->getRequestedOp($this->request);
$args = $router->getRequestedArgs($this->request);
if ($op == 'download' && count($args) > 1) {
if ($args[1] == 'version' && count($args) == 5) {
$publicationId = (int) $args[2];
$canonicalUrlParams[] = 'version';
$canonicalUrlParams[] = $publicationId;
}
}
$canonicalUrlParams[] = $this->representation->getId();
$canonicalUrlParams[] = $this->submissionFile->getId();
break;
case Application::ASSOC_TYPE_SUBMISSION:
$canonicalUrlOp = 'view';
if (Application::get()->getName() == 'omp') {
$canonicalUrlOp = 'book';
}
$canonicalUrlParams = [$this->submission->getId()];
$router = $this->request->getRouter(); /** @var PageRouter $router */
$op = $router->getRequestedOp($this->request);
$args = $router->getRequestedArgs($this->request);
if ($op == $canonicalUrlOp && count($args) > 1) {
if ($args[1] == 'version' && count($args) == 3) {
$publicationId = (int) $args[2];
$canonicalUrlParams[] = 'version';
$canonicalUrlParams[] = $publicationId;
}
}
break;
case Application::getContextAssocType():
$canonicalUrlOp = '';
$canonicalUrlPage = 'index';
break;
default:
throw new Exception('Not recognized assoc type that we can create the canonical URL for.');
}
$canonicalUrl = $this->getRouterCanonicalUrl($this->request, $canonicalUrlPage, $canonicalUrlOp, $canonicalUrlParams);
return $canonicalUrl;
}
/**
* Construct the URL from page, op, and params
*/
protected function getRouterCanonicalUrl(Request $request, string $canonicalUrlPage = null, string $canonicalUrlOp = null, array $canonicalUrlParams = null): string
{
$router = $request->getRouter(); /** @var PageRouter $router */
$context = $router->getContext($request);
if (!isset($canonicalUrlPage)) {
$canonicalUrlPage = $router->getRequestedPage($request);
}
if (!isset($canonicalUrlOp)) {
$canonicalUrlOp = $router->getRequestedOp($request);
}
if (!isset($canonicalUrlParams)) {
$canonicalUrlParams = $router->getRequestedArgs($request);
}
$canonicalUrl = $router->url(
$request,
null,
$canonicalUrlPage,
$canonicalUrlOp,
$canonicalUrlParams
);
// Make sure we log the server name and not aliases.
$configBaseUrl = Config::getVar('general', 'base_url');
$requestBaseUrl = $request->getBaseUrl();
if ($requestBaseUrl !== $configBaseUrl) {
// Make sure it's not an url override (no alias on that case).
if (!in_array($requestBaseUrl, Config::getContextBaseUrls()) &&
$requestBaseUrl !== Config::getVar('general', 'base_url[index]')) {
// Alias found, replace it by base_url from config file.
// Make sure we use the correct base url override value for the context, if any.
$baseUrlReplacement = Config::getVar('general', 'base_url[' . $context->getPath() . ']');
if (!$baseUrlReplacement) {
$baseUrlReplacement = $configBaseUrl;
}
$canonicalUrl = str_replace($requestBaseUrl, $baseUrlReplacement, $canonicalUrl);
}
}
return $canonicalUrl;
}
}
@@ -0,0 +1,36 @@
<?php
/**
* @file classes/observers/events/UserRegisteredContext.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 UserRegisteredContext
*
* @ingroup observers_events
*
* @brief An event fired when a user registers with a context
*/
namespace PKP\observers\events;
use Illuminate\Foundation\Events\Dispatchable;
use PKP\context\Context;
use PKP\user\User;
class UserRegisteredContext
{
use Dispatchable;
public User $recipient;
public Context $context;
public function __construct(User $recipient, Context $context)
{
$this->recipient = $recipient;
$this->context = $context;
}
}
@@ -0,0 +1,36 @@
<?php
/**
* @file classes/observers/events/UserRegisteredSite.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 UserRegisteredSite
*
* @ingroup observers_events
*
* @brief An event fired when a user registers from the site-wide registration form
*/
namespace PKP\observers\events;
use Illuminate\Foundation\Events\Dispatchable;
use PKP\site\Site;
use PKP\user\User;
class UserRegisteredSite
{
use Dispatchable;
public User $recipient;
public Site $site;
public function __construct(User $recipient, Site $site)
{
$this->recipient = $recipient;
$this->site = $site;
}
}
@@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/listeners/AssignDOIs.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 AssignDOIs
*
* @ingroup core
*
* @brief Assign DOIs when a submission is moved to the appropriate stage
*/
namespace PKP\observers\listeners;
use APP\facades\Repo;
use Illuminate\Events\Dispatcher;
use PKP\context\Context;
use PKP\observers\events\DecisionAdded;
class AssignDOIs
{
/**
* Maps methods with corresponding events to listen to
*/
public function subscribe(Dispatcher $events): void
{
$events->listen(
DecisionAdded::class,
self::class . '@handle'
);
}
/**
* Allows DOI creation upon reaching copy-editing or production workflow stage
*/
public function handle(DecisionAdded $event)
{
$context = $event->context;
$doiCreationTime = $context->getData(Context::SETTING_DOI_CREATION_TIME);
$workflowStageId = $event->decisionType->getNewStageId($event->submission, $event->decision->getData('reviewRoundId'));
if (
$doiCreationTime === Repo::doi()::CREATION_TIME_COPYEDIT
&& in_array($workflowStageId, [WORKFLOW_STAGE_ID_EDITING, WORKFLOW_STAGE_ID_PRODUCTION])
) {
Repo::submission()->createDois($event->submission);
}
}
}
@@ -0,0 +1,128 @@
<?php
/**
* @file classes/observers/listeners/AssignEditors.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 AssignEditors
*
* @ingroup observers_listeners
*
* @brief Assign editors to a submission based on the configuration settings
*
* If no editors are assigned, creates a notification that an editor needs
* to be assigned.
*/
namespace PKP\observers\listeners;
use APP\core\Application;
use APP\facades\Repo;
use APP\notification\Notification;
use APP\notification\NotificationManager;
use Illuminate\Events\Dispatcher;
use Illuminate\Support\Facades\Mail;
use PKP\context\SubEditorsDAO;
use PKP\db\DAORegistry;
use PKP\log\SubmissionEmailLogDAO;
use PKP\log\SubmissionEmailLogEntry;
use PKP\mail\mailables\SubmissionNeedsEditor;
use PKP\notification\NotificationSubscriptionSettingsDAO;
use PKP\observers\events\SubmissionSubmitted;
use PKP\security\Role;
class AssignEditors
{
public function subscribe(Dispatcher $events): void
{
$events->listen(
SubmissionSubmitted::class,
AssignEditors::class
);
}
public function handle(SubmissionSubmitted $event)
{
/** @var SubEditorsDAO $subEditorsDao */
$subEditorsDao = DAORegistry::getDAO('SubEditorsDAO');
$assignedUserIds = $subEditorsDao->assignEditors($event->submission, $event->context);
if ($assignedUserIds->count()) {
return;
}
$managers = Repo::user()
->getCollector()
->filterByRoleIds([Role::ROLE_ID_MANAGER])
->filterByContextIds([$event->context->getId()])
->getMany();
if (!$managers->count()) {
return;
}
$notificationManager = new NotificationManager();
/** @var NotificationSubscriptionSettingsDAO $notificationSubscriptionSettingsDao */
$notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO');
/** @var SubmissionEmailLogDAO $logDao */
$logDao = DAORegistry::getDAO('SubmissionEmailLogDAO');
foreach ($managers as $manager) {
// Send notification
$notification = $notificationManager->createNotification(
Application::get()->getRequest(),
$manager->getId(),
Notification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_REQUIRED,
$event->context->getId(),
Application::ASSOC_TYPE_SUBMISSION,
$event->submission->getId(),
Notification::NOTIFICATION_LEVEL_TASK
);
// Check if subscribed to this type of emails
$unsubscribed = in_array(
Notification::NOTIFICATION_TYPE_SUBMISSION_SUBMITTED,
$notificationSubscriptionSettingsDao->getNotificationSubscriptionSettings(
NotificationSubscriptionSettingsDAO::BLOCKED_EMAIL_NOTIFICATION_KEY,
$manager->getId(),
$event->context->getId()
)
);
if ($unsubscribed) {
continue;
}
// Send email
$emailTemplate = Repo::emailTemplate()->getByKey($event->context->getId(), SubmissionNeedsEditor::getEmailTemplateKey());
$mailable = new SubmissionNeedsEditor($event->context, $event->submission);
// The template may not exist, see pkp/pkp-lib#9217;
if (!$emailTemplate) {
$emailTemplate = Repo::emailTemplate()->getByKey($event->context->getId(), 'NOTIFICATION');
$request = Application::get()->getRequest();
$mailable->addData([
'notificationContents' => $notificationManager->getNotificationContents($request, $notification),
'notificationUrl' => $notificationManager->getNotificationUrl($request, $notification),
]);
}
$mailable
->from($event->context->getData('contactEmail'), $event->context->getData('contactName'))
->subject($emailTemplate->getLocalizedData('subject'))
->body($emailTemplate->getLocalizedData('body'))
->recipients([$manager]);
Mail::send($mailable);
// Log email
$logDao->logMailable(
SubmissionEmailLogEntry::SUBMISSION_EMAIL_NEEDS_EDITOR,
$mailable,
$event->submission
);
}
}
}
@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/listeners/BatchMetadataChangedListener.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 BatchMetadataChangedListener
*
* @ingroup core
*
* @brief Listener fired when submission metadata's changed on batch
*/
namespace PKP\observers\listeners;
use Illuminate\Events\Dispatcher;
use PKP\jobs\metadata\BatchMetadataChangedJob;
use PKP\observers\events\BatchMetadataChanged;
class BatchMetadataChangedListener
{
/**
* Maps methods with correspondent events to listen
*/
public function subscribe(Dispatcher $events): void
{
$events->listen(
BatchMetadataChanged::class,
self::class . '@handle'
);
}
/**
* Handle the listener call
*/
public function handle(BatchMetadataChanged $event)
{
dispatch(new BatchMetadataChangedJob($event->submissionIds));
}
}
@@ -0,0 +1,50 @@
<?php
/**
* @file classes/observers/listeners/LogSubmissionSubmitted.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 LogSubmissionSubmitted
*
* @ingroup observers_listeners
*
* @brief Create an entry in the submission log when a submission is submitted
*/
namespace PKP\observers\listeners;
use APP\core\Application;
use APP\facades\Repo;
use Illuminate\Events\Dispatcher;
use PKP\core\Core;
use PKP\core\PKPApplication;
use PKP\log\event\PKPSubmissionEventLogEntry;
use PKP\observers\events\SubmissionSubmitted;
use PKP\security\Validation;
class LogSubmissionSubmitted
{
public function subscribe(Dispatcher $events): void
{
$events->listen(
SubmissionSubmitted::class,
LogSubmissionSubmitted::class
);
}
public function handle(SubmissionSubmitted $event)
{
$eventLog = Repo::eventLog()->newDataObject([
'assocType' => PKPApplication::ASSOC_TYPE_SUBMISSION,
'assocId' => $event->submission->getId(),
'eventType' => PKPSubmissionEventLogEntry::SUBMISSION_LOG_SUBMISSION_SUBMIT,
'userId' => Validation::loggedInAs() ?? Application::get()->getRequest()->getUser()?->getId(),
'message' => 'submission.event.submissionSubmitted',
'isTranslated' => false,
'dateLogged' => Core::getCurrentDate(),
]);
Repo::eventLog()->add($eventLog);
}
}
@@ -0,0 +1,229 @@
<?php
/**
* @file classes/observers/listeners/LogUsageEvent.php
*
* Copyright (c) 2022 Simon Fraser University
* Copyright (c) 2022 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class LogUsageEvent
*
* @ingroup observers_traits
*
* @brief Listener listening for and logging the usage events.
*/
namespace PKP\observers\listeners;
use APP\core\Application;
use APP\observers\events\UsageEvent;
use APP\statistics\StatisticsHelper;
use APP\submission\Submission;
use Illuminate\Events\Dispatcher;
use PKP\cache\FileCache;
use PKP\file\PrivateFileManager;
use PKP\plugins\Hook;
class LogUsageEvent
{
public FileCache $geoDataCache;
public FileCache $institutionDataCache;
/**
* Maps methods with correspondent events to listen
*/
public function subscribe(Dispatcher $events): void
{
$events->listen(
UsageEvent::class,
self::class . '@handle'
);
}
/**
* Handle the event.
*/
public function handle(UsageEvent $usageEvent): void
{
if (!$this->canHandle($usageEvent)) {
return;
}
$usageEventLogEntry = $this->prepareUsageEvent($usageEvent);
$this->logUsageEvent($usageEventLogEntry);
}
/**
* Shall this event be processed here
*/
protected function canHandle(UsageEvent $usageEvent): bool
{
if ($usageEvent->request->getDoNotTrack()) {
return false;
}
if (in_array($usageEvent->assocType, [
Application::ASSOC_TYPE_SUBMISSION,
Application::ASSOC_TYPE_SUBMISSION_FILE,
Application::ASSOC_TYPE_SUBMISSION_FILE_COUNTER_OTHER,
]) && $usageEvent->submission->getData('status') != Submission::STATUS_PUBLISHED) {
return false;
}
if (Application::get()->getName() == 'ojs2') {
if (in_array($usageEvent->assocType, [Application::ASSOC_TYPE_ISSUE, Application::ASSOC_TYPE_ISSUE_GALLEY]) &&
!$usageEvent->issue->getPublished()) {
return false;
}
} elseif (Application::get()->getName() == 'omp') {
if (in_array($usageEvent->assocType, [Application::ASSOC_TYPE_CHAPTER]) &&
$usageEvent->submission->getData('status') != Submission::STATUS_PUBLISHED) {
return false;
}
}
return true;
}
/**
* Log the usage event
*/
protected function logUsageEvent(array $usageEventLogEntry): void
{
Hook::call('Stats::logUsageEvent', [$usageEventLogEntry]);
$usageEventLogEntry = json_encode($usageEventLogEntry) . PHP_EOL;
// Log file name (from the current day)
$logFileName = $this->getUsageEventLogFileName();
// Write the event to the log file
// Keep the locking in order not to care about the filesystems's block sizes and if the file is on a local filesystem
$fp = fopen($logFileName, 'a+b');
if (flock($fp, LOCK_EX)) {
fwrite($fp, $usageEventLogEntry);
flock($fp, LOCK_UN);
} else {
error_log("UsageEventLog: Couldn't lock the usage event log file.");
}
fclose($fp);
}
/**
* Prepare the usage event:
* create new daily salt file, if necessary
* get Geo data, if needed
* get institution IDs, if needed
* hash the IP
*/
protected function prepareUsageEvent(UsageEvent $usageEvent): array
{
$request = $usageEvent->request;
// The current usage event log file name (from the current day)
$logFileName = $this->getUsageEventLogFileName();
// Salt management.
[$salt, $flushCache] = $this->getSalt($logFileName);
// Hash the IP
$ip = $request->getRemoteAddr();
$hashedIp = StatisticsHelper::hashIp($ip, $salt);
$site = $request->getSite();
$context = $usageEvent->context;
// Geo data
$statisticsHelper = new StatisticsHelper();
[$country, $region, $city] = $statisticsHelper->getGeoData($site, $context, $ip, $hashedIp, $flushCache);
// institutions IDs
$institutionIds = [];
if ($context->isInstitutionStatsEnabled($site)) {
$institutionIds = $statisticsHelper->getInstitutionIds($context->getId(), $ip, $hashedIp, $flushCache);
}
// format the usage event log entry
$usageEventLogEntry = [
'time' => $usageEvent->time,
'ip' => $hashedIp,
'userAgent' => $request->getUserAgent(),
'canonicalUrl' => $usageEvent->canonicalUrl,
'assocType' => $usageEvent->assocType,
'contextId' => $context->getId(),
'submissionId' => $usageEvent->submission?->getId(),
'representationId' => $usageEvent->representation?->getId(),
'submissionFileId' => $usageEvent->submissionFile?->getId(),
'fileType' => $usageEvent->submissionFile ? StatisticsHelper::getDocumentType($usageEvent->submissionFile->getData('mimetype')) : null,
'country' => $country,
'region' => $region,
'city' => $city,
'institutionIds' => $institutionIds,
'version' => $usageEvent->version
];
// get application specific IDs
if (Application::get()->getName() == 'ojs2') {
$usageEventLogEntry['issueId'] = $usageEvent->issue?->getId();
$usageEventLogEntry['issueGalleyId'] = $usageEvent->issueGalley?->getId();
} elseif (Application::get()->getName() == 'omp') {
$usageEventLogEntry['chapterId'] = $usageEvent->chapter?->getId();
$usageEventLogEntry['seriesId'] = $usageEvent->series?->getId();
}
return $usageEventLogEntry;
}
/**
* Get current day usage event log file name.
*/
protected function getUsageEventLogFileName(): string
{
$usageEventLogsDir = StatisticsHelper::getUsageStatsDirPath() . '/usageEventLogs';
if (!file_exists($usageEventLogsDir) || !is_dir($usageEventLogsDir)) {
$fileMgr = new PrivateFileManager();
$success = $fileMgr->mkdirtree($usageEventLogsDir);
if (!$success) {
// Files directory wrong configuration?
error_log("UsageEventLog: Couldn't create {$usageEventLogsDir}.");
}
}
return $usageEventLogsDir . '/usage_events_' . date('Ymd') . '.log';
}
/**
* Get salt (used for IP hashing) from the file.
* For privacy reasons, the salt will change every day.
* When salt changes, the IP hash will change too, so the cach containing the hashed IPs (for Geo and institutions data) will be removed.
* If the salt file does not exist, it will be created.
* If the salt file exists and it was not modified at the current day the salt will be changed.
*/
protected function getSalt(string $logFileName): array
{
$salt = null;
$flushCache = false;
$saltFileName = StatisticsHelper::getSaltFileName();
// Create salt file and salt for the first time
if (!file_exists($saltFileName)) {
$salt = StatisticsHelper::createNewSalt($saltFileName);
// Salt changed, flush the cache
$flushCache = true;
}
$currentDate = date('Ymd');
$saltFileLastModified = date('Ymd', filemtime($saltFileName));
// Create new salt if the usage log file with current date does not exist.
// The current usage log file will be created next (s. function handle() and logUsageEvent() above).
// If another process accesses this before the current usage event log file is created,
// consider the last modified date stamp of the salt file too.
if (!file_exists($logFileName) && ($currentDate != $saltFileLastModified)) {
$salt = StatisticsHelper::createNewSalt($saltFileName);
// Salt changed, flush the cache
$flushCache = true;
}
if (!isset($salt)) {
$salt = trim(file_get_contents($saltFileName));
}
return [$salt, $flushCache];
}
}
@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/listeners/MetadataChangedListener.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 MetadataChangedListener
*
* @ingroup core
*
* @brief Listener fired when submission metadata's changed
*/
namespace PKP\observers\listeners;
use Illuminate\Events\Dispatcher;
use PKP\jobs\metadata\MetadataChangedJob;
use PKP\observers\events\MetadataChanged;
class MetadataChangedListener
{
/**
* Maps methods with correspondent events to listen
*/
public function subscribe(Dispatcher $events): void
{
$events->listen(
MetadataChanged::class,
self::class . '@handle'
);
}
/**
* Handle the listener call
*/
public function handle(MetadataChanged $event)
{
dispatch(new MetadataChangedJob($event->submission->getId()));
}
}
@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/listeners/RemoveSubmissionFileFromSearchIndex.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 RemoveSubmissionFileFromSearchIndex
*
* @ingroup core
*
* @brief Remove a submission file from the search index when it is deleted.
*/
namespace PKP\observers\listeners;
use Illuminate\Events\Dispatcher;
use PKP\jobs\submissions\RemoveSubmissionFileFromSearchIndexJob;
use PKP\observers\events\SubmissionFileDeleted;
class RemoveSubmissionFileFromSearchIndex
{
/**
* Maps methods with correspondent events to listen
*/
public function subscribe(Dispatcher $events): void
{
$events->listen(
SubmissionFileDeleted::class,
self::class . '@handle'
);
}
/**
* Handle the listener call
*/
public function handle(SubmissionFileDeleted $event)
{
dispatch(
new RemoveSubmissionFileFromSearchIndexJob(
$event->submissionId,
$event->submissionFileId
)
);
}
}
@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/listeners/RemoveSubmissionFromSearchIndex.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 RemoveSubmissionFromSearchIndex
*
* @ingroup core
*
* @brief Remove a submission from the search index when it is deleted
*/
namespace PKP\observers\listeners;
use Illuminate\Events\Dispatcher;
use PKP\jobs\submissions\RemoveSubmissionFromSearchIndexJob;
use PKP\observers\events\SubmissionDeleted;
class RemoveSubmissionFromSearchIndex
{
/**
* Maps methods with correspondent events to listen
*/
public function subscribe(Dispatcher $events): void
{
$events->listen(
SubmissionDeleted::class,
self::class . '@handle'
);
}
/**
* Handle the listener call
*/
public function handle(SubmissionDeleted $event)
{
dispatch(new RemoveSubmissionFromSearchIndexJob($event->submissionId));
}
}
@@ -0,0 +1,55 @@
<?php
/**
* @file classes/observers/listeners/RestrictAuthorAssignment.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 RestrictAuthorAssignment
*
* @ingroup observers_listeners
*
* @brief Change the authors' stage assignments to restrict their
* permission to edit after the submission is complete.
*/
namespace PKP\observers\listeners;
use APP\facades\Repo;
use Illuminate\Events\Dispatcher;
use PKP\db\DAORegistry;
use PKP\db\DAOResultFactory;
use PKP\observers\events\SubmissionSubmitted;
use PKP\security\Role;
use PKP\stageAssignment\StageAssignment;
use PKP\stageAssignment\StageAssignmentDAO;
class RestrictAuthorAssignment
{
public function subscribe(Dispatcher $events): void
{
$events->listen(
SubmissionSubmitted::class,
RestrictAuthorAssignment::class
);
}
public function handle(SubmissionSubmitted $event)
{
/** @var StageAssignmentDAO $stageAssignmentDao */
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO');
$assignments = $stageAssignmentDao->getBySubmissionAndRoleIds($event->submission->getId(), [Role::ROLE_ID_AUTHOR]);
while ($assignment = $assignments->next()) {
/** @var StageAssignment $assignment */
$userGroup = Repo::userGroup()->get($assignment->getUserGroupId(), $event->context->getId());
if (!$userGroup) {
continue;
}
$assignment->setCanChangeMetadata($userGroup->getPermitMetadataEdit());
$stageAssignmentDao->updateObject($assignment);
}
}
}
@@ -0,0 +1,127 @@
<?php
/**
* @file classes/observers/listeners/SendSubmissionAcknowledgement.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 SendSubmissionAcknowledgement
*
* @ingroup observers_listeners
*
* @brief Send an email acknowledgement to the submitting author when a new submission is submitted
*
* Sends an email to all users with author stage assignments and
* sends a separate email to all other contributors named on the
* submission.
*/
namespace PKP\observers\listeners;
use APP\author\Author;
use APP\facades\Repo;
use Illuminate\Events\Dispatcher;
use Illuminate\Support\Enumerable;
use Illuminate\Support\Facades\Mail;
use PKP\db\DAORegistry;
use PKP\log\SubmissionEmailLogDAO;
use PKP\log\SubmissionEmailLogEntry;
use PKP\mail\Mailable;
use PKP\mail\mailables\SubmissionAcknowledgement;
use PKP\mail\mailables\SubmissionAcknowledgementOtherAuthors;
use PKP\observers\events\SubmissionSubmitted;
use PKP\security\Role;
use PKP\stageAssignment\StageAssignment;
use PKP\stageAssignment\StageAssignmentDAO;
use PKP\user\User;
abstract class SendSubmissionAcknowledgement
{
abstract public function subscribe(Dispatcher $events): void;
public function handle(SubmissionSubmitted $event)
{
/** @var StageAssignmentDAO $stageAssignmentDao */
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO');
$result = $stageAssignmentDao->getBySubmissionAndRoleIds($event->submission->getId(), [Role::ROLE_ID_AUTHOR]);
$assignedUserIds = [];
while ($stageAssignment = $result->next()) {
/** @var StageAssignment $stageAssignment */
$assignedUserIds[] = $stageAssignment->getUserId();
}
$submitterUsers = Repo::user()
->getCollector()
->filterByUserIds($assignedUserIds)
->getMany();
if ($submitterUsers->count()) {
$mailable = $this->getSubmitterMailable($event, $submitterUsers);
if ($event->context->getData('copySubmissionAckPrimaryContact')) {
$mailable->bcc($event->context->getData('contactEmail'), $event->context->getData('contactName'));
}
if (!empty($event->context->getData('copySubmissionAckAddress'))) {
$emails = explode(',', trim($event->context->getData('copySubmissionAckAddress')));
$mailable->bcc($emails);
}
Mail::send($mailable);
/** @var SubmissionEmailLogDAO $logDao */
$logDao = DAORegistry::getDAO('SubmissionEmailLogDAO');
$logDao->logMailable(
SubmissionEmailLogEntry::SUBMISSION_EMAIL_AUTHOR_SUBMISSION_ACK,
$mailable,
$event->submission
);
}
$submitterEmails = $submitterUsers->map(fn (User $user) => $user->getEmail());
$otherAuthors = $event->submission
->getCurrentPublication()
->getData('authors')
->filter(fn (Author $author) => !$submitterEmails->contains($author->getEmail()));
if ($otherAuthors->count()) {
$emailTemplate = Repo::emailTemplate()->getByKey(
$event->context->getId(),
SubmissionAcknowledgementOtherAuthors::getEmailTemplateKey()
);
$mailable = new SubmissionAcknowledgementOtherAuthors($event->context, $event->submission, $submitterUsers);
$mailable
->from($event->context->getData('contactEmail'), $event->context->getData('contactName'))
->recipients($otherAuthors->toArray())
->subject($emailTemplate->getLocalizedData('subject'))
->body($emailTemplate->getLocalizedData('body'));
Mail::send($mailable);
/** @var SubmissionEmailLogDAO $logDao */
$logDao = DAORegistry::getDAO('SubmissionEmailLogDAO');
$logDao->logMailable(
SubmissionEmailLogEntry::SUBMISSION_EMAIL_AUTHOR_SUBMISSION_ACK,
$mailable,
$event->submission
);
}
}
protected function getSubmitterMailable(SubmissionSubmitted $event, Enumerable $submitterUsers): Mailable
{
$emailTemplate = Repo::emailTemplate()->getByKey(
$event->context->getId(),
SubmissionAcknowledgement::getEmailTemplateKey()
);
return (new SubmissionAcknowledgement($event->context, $event->submission))
->from($event->context->getData('contactEmail'), $event->context->getData('contactName'))
->recipients($submitterUsers->toArray())
->subject($emailTemplate->getLocalizedData('subject'))
->body($emailTemplate->getLocalizedData('body'));
}
}
@@ -0,0 +1,64 @@
<?php
/**
* @file classes/observers/listeners/UpdateAuthorStageAssignments.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 UpdateAuthorStageAssignments
*
* @ingroup observers_listeners
*
* @brief Update author stage assignments when a submission is submitted
* to restrict their ability to edit the metadata, depending on how their
* user group is configured.
*/
namespace PKP\observers\listeners;
use APP\facades\Repo;
use Illuminate\Events\Dispatcher;
use PKP\db\DAORegistry;
use PKP\observers\events\SubmissionSubmitted;
use PKP\security\Role;
use PKP\stageAssignment\StageAssignment;
use PKP\stageAssignment\StageAssignmentDAO;
class UpdateAuthorStageAssignments
{
public function subscribe(Dispatcher $events): void
{
$events->listen(
SubmissionSubmitted::class,
UpdateAuthorStageAssignments::class
);
}
public function handle(SubmissionSubmitted $event)
{
/** @var StageAssignmentDAO $stageAssignmentDao */
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO');
$stageAssigments = $stageAssignmentDao->getBySubmissionAndRoleIds(
$event->submission->getId(),
[Role::ROLE_ID_AUTHOR],
$event->submission->getData('stageId')
);
$userGroups = Repo::userGroup()
->getCollector()
->filterByContextIds([$event->context->getId()])
->filterByRoleIds([Role::ROLE_ID_AUTHOR])
->getMany();
/** @var StageAssignment $stageAssignment */
while ($stageAssignment = $stageAssigments->next()) {
$userGroup = $userGroups->get($stageAssignment->getUserGroupId());
if (!$userGroup || $stageAssignment->getCanChangeMetadata() === $userGroup->getPermitMetadataEdit()) {
continue;
}
$stageAssignment->setCanChangeMetadata($userGroup->getPermitMetadataEdit());
$stageAssignmentDao->updateObject($stageAssignment);
}
}
}
@@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/listeners/UpdateSubmissionInSearchIndex.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 UpdateSubmissionInSearchIndex
*
* @ingroup core
*
* @brief Reindex a submission in the search index when a publication is published or unpublished
*/
namespace PKP\observers\listeners;
use Illuminate\Events\Dispatcher;
use PKP\jobs\submissions\UpdateSubmissionSearchJob;
use PKP\observers\events\PublicationPublished;
use PKP\observers\events\PublicationUnpublished;
class UpdateSubmissionInSearchIndex
{
/**
* Maps methods with correspondent events to listen
*/
public function subscribe(Dispatcher $events): void
{
$events->listen(
PublicationPublished::class,
self::class . '@handlePublicationPublished'
);
$events->listen(
PublicationUnpublished::class,
self::class . '@handleUnpublished'
);
}
public function handleUnpublished(PublicationUnpublished $event)
{
dispatch(new UpdateSubmissionSearchJob($event->submission->getId()));
}
public function handlePublicationPublished(PublicationPublished $event)
{
dispatch(new UpdateSubmissionSearchJob($event->submission->getId()));
}
}
@@ -0,0 +1,112 @@
<?php
/**
* @file classes/observers/listeners/ValidateRegisteredEmail.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 ValidateRegisteredEmail
*
* @ingroup observers_listeners
*
* @brief Send an email to a newly registered user asking them to validate their email address
*/
namespace PKP\observers\listeners;
use APP\facades\Repo;
use Illuminate\Events\Dispatcher;
use Illuminate\Support\Facades\Mail;
use PKP\config\Config;
use PKP\core\PKPApplication;
use PKP\mail\mailables\ValidateEmailContext as ContextMailable;
use PKP\mail\mailables\ValidateEmailSite as SiteMailable;
use PKP\observers\events\UserRegisteredContext;
use PKP\observers\events\UserRegisteredSite;
use PKP\security\AccessKeyManager;
class ValidateRegisteredEmail
{
/**
* Maps methods with correspondent events to listen
*/
public function subscribe(Dispatcher $events): void
{
$events->listen(
UserRegisteredContext::class,
self::class . '@handleContextRegistration'
);
$events->listen(
UserRegisteredSite::class,
self::class . '@handleSiteRegistration'
);
}
/**
* @param \PKP\observers\events\UserRegisteredContext
*/
public function handleContextRegistration(UserRegisteredContext $event): void
{
$this->manageEmail($event);
}
/**
*/
public function handleSiteRegistration(UserRegisteredSite $event): void
{
$this->manageEmail($event);
}
/**
* Sends mail depending on a source - context or site registration
*
* @param UserRegisteredContext|UserRegisteredSite $event
*/
protected function manageEmail($event): void
{
if (!$this->emailValidationRequired()) {
return;
}
$accessKeyManager = new AccessKeyManager();
$accessKey = $accessKeyManager->createKey(
'RegisterContext',
$event->recipient->getId(),
null,
Config::getVar('email', 'validation_timeout')
);
// Create and compile email template
if (get_class($event) === UserRegisteredContext::class) {
$mailable = new ContextMailable($event->context);
$mailable->from($event->context->getData('supportEmail'), $event->context->getData('supportName'));
$mailable->addData([
'activateUrl' => PKPApplication::get()->getRequest()->url($event->context->getData('urlPath'), 'user', 'activateUser', [$event->recipient->getUsername(), $accessKey]),
]);
$registerTemplate = Repo::emailTemplate()->getByKey($event->context->getId(), $mailable::getEmailTemplateKey());
} else {
$mailable = new SiteMailable($event->site);
$mailable->from($event->site->getLocalizedContactEmail(), $event->site->getLocalizedContactName());
$mailable->addData([
'activateUrl' => PKPApplication::get()->getRequest()->url(null, 'user', 'activateUser', [$event->recipient->getUsername(), $accessKey]),
]);
$registerTemplate = Repo::emailTemplate()->getByKey(PKPApplication::CONTEXT_SITE, $mailable::getEmailTemplateKey());
}
// Send mail
$mailable
->body($registerTemplate->getLocalizedData('body'))
->subject($registerTemplate->getLocalizedData('subject'))
->recipients([$event->recipient]);
Mail::send($mailable);
}
protected function emailValidationRequired(): bool
{
return (bool) Config::getVar('email', 'require_validation');
}
}
@@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
/**
* @file classes/observers/listeners/VersionDois.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 VersionDois
*
* @ingroup observers_listeners
*
* @brief Listener fired when publication's published
*/
namespace PKP\observers\listeners;
use APP\facades\Repo;
use APP\publication\Publication;
use Illuminate\Events\Dispatcher;
use PKP\context\Context;
use PKP\observers\events\PublicationPublished;
class VersionDois
{
public function subscribe(Dispatcher $events): void
{
$events->listen(
PublicationPublished::class,
self::class . '@handlePublishedEvent'
);
}
/**
* Handle DOI assignment at the publication stage and versioning
*/
public function handlePublishedEvent(PublicationPublished $event): void
{
$submission = $event->submission;
$context = $event->context;
$doisEnabled = $context->getData(Context::SETTING_ENABLE_DOIS);
if (!$doisEnabled) {
return;
}
$_failureResults = Repo::submission()->createDois($submission);
}
}