first commit
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user