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,107 @@
<?php
/**
* @file classes/notification/INotificationInfoProvider.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 INotificationInfoProvider
*
* @ingroup notification
*
* @brief Interface to retrieve notification presentation information.
*/
namespace PKP\notification;
use APP\notification\Notification;
use PKP\core\PKPRequest;
define('NOTIFICATION_STYLE_CLASS_WARNING', 'notifyWarning');
define('NOTIFICATION_STYLE_CLASS_INFORMATION', 'notifyInfo');
define('NOTIFICATION_STYLE_CLASS_SUCCESS', 'notifySuccess');
define('NOTIFICATION_STYLE_CLASS_ERROR', 'notifyError');
define('NOTIFICATION_STYLE_CLASS_FORM_ERROR', 'notifyFormError');
define('NOTIFICATION_STYLE_CLASS_FORBIDDEN', 'notifyForbidden');
define('NOTIFICATION_STYLE_CLASS_HELP', 'notifyHelp');
interface INotificationInfoProvider
{
/**
* Get a URL for the notification.
*
* @param PKPRequest $request
* @param Notification $notification
*
* @return string
*/
public function getNotificationUrl($request, $notification);
/**
* Get the notification message. Only return translated locale
* key strings.
*
* @param PKPRequest $request
* @param Notification $notification
*
* @return string|array
*/
public function getNotificationMessage($request, $notification);
/**
* Get the notification contents. Content is anything that's
* more than text, like presenting link actions inside fetched
* template files.
*
* @param PKPRequest $request
* @param Notification $notification
*
* @return string|array
*/
public function getNotificationContents($request, $notification);
/**
* Get the notification title.
*
* @param Notification $notification
*
* @return string
*/
public function getNotificationTitle($notification);
/**
* Get the notification style class.
*
* @param Notification $notification
*
* @return string
*/
public function getStyleClass($notification);
/**
* Get the notification icon class.
*
* @param Notification $notification
*
* @return string
*/
public function getIconClass($notification);
/**
* Whether any notification with the passed notification type
* is visible to all users or not.
*
* @param int $notificationType
* @param int $assocType Application::ASSOC_TYPE_...
* @param int $assocId
*
* @return bool
*/
public function isVisibleToAllUsers($notificationType, $assocType, $assocId);
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\INotificationInfoProvider', '\INotificationInfoProvider');
}
@@ -0,0 +1,283 @@
<?php
/**
* @file classes/notification/NotificationDAO.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 NotificationDAO
*
* @ingroup notification
*
* @see Notification
*
* @brief Operations for retrieving and modifying Notification objects.
*/
namespace PKP\notification;
use APP\notification\Notification;
use Illuminate\Support\Facades\DB;
use PKP\core\Core;
use PKP\core\PKPApplication;
use PKP\db\DAOResultFactory;
use PKP\plugins\Hook;
class NotificationDAO extends \PKP\db\DAO
{
/**
* Retrieve Notification by notification id
*/
public function getById(int $notificationId, ?int $userId = null): ?Notification
{
$params = [(int) $notificationId];
if ($userId) {
$params[] = (int) $userId;
}
$result = $this->retrieve(
'SELECT *
FROM notifications
WHERE notification_id = ?
' . ($userId ? ' AND user_id = ?' : ''),
$params
);
$row = (array) $result->current();
return $row ? $this->_fromRow($row) : null;
}
/**
* Retrieve Notifications by user id
* Note that this method will not return fully-fledged notification objects. Use
* NotificationManager::getNotificationsForUser() to get notifications with URL, and contents
*
* @return DAOResultFactory<Notification> Object containing matching Notification objects
*/
public function getByUserId(?int $userId, int $level = Notification::NOTIFICATION_LEVEL_NORMAL, ?int $type = null, ?int $contextId = null): DAOResultFactory
{
$result = DB::table('notifications')
->where('user_id', '=', $userId)
->where('level', '=', $level)
->when($type !== null, fn ($query) => $query->where('type', '=', $type))
->when($contextId === PKPApplication::CONTEXT_SITE, fn ($query) => $query->whereNull('context_id'))
->when($contextId, fn ($query) => $query->where('context_id', '=', $contextId))
->orderBy('date_created', 'desc')
->get();
return new DAOResultFactory($result, $this, '_fromRow');
}
/**
* Retrieve Notifications by assoc.
* Note that this method will not return fully-fledged notification objects. Use
* NotificationManager::getNotificationsForUser() to get notifications with URL, and contents
*
* @param int $assocType Application::ASSOC_TYPE_...
*
* @return DAOResultFactory<Notification>
*/
public function getByAssoc(int $assocType, int $assocId, ?int $userId = null, ?int $type = null, ?int $contextId = null): DAOResultFactory
{
$params = [$assocType, $assocId];
if ($userId) {
$params[] = $userId;
}
if ($contextId) {
$params[] = $contextId;
}
if ($type) {
$params[] = $type;
}
$result = $this->retrieveRange(
'SELECT * FROM notifications WHERE assoc_type = ? AND assoc_id = ?' .
($userId ? ' AND user_id = ?' : '') .
($contextId ? ' AND context_id = ?' : '') .
($type ? ' AND type = ?' : '') .
' ORDER BY date_created DESC',
$params
);
return new DAOResultFactory($result, $this, '_fromRow');
}
/**
* Set the date read for a notification
*/
public function setDateRead(int $notificationId, string $dateRead): string
{
$this->update(
sprintf(
'UPDATE notifications
SET date_read = %s
WHERE notification_id = ?',
$this->datetimeToDB($dateRead)
),
[$notificationId]
);
return $dateRead;
}
/**
* Instantiate and return a new data object.
*/
public function newDataObject(): Notification
{
return new Notification();
}
/**
* Inserts a new notification into notifications table
*/
public function insertObject(Notification $notification): int
{
$this->update(
sprintf(
'INSERT INTO notifications
(user_id, level, date_created, context_id, type, assoc_type, assoc_id)
VALUES
(?, ?, %s, ?, ?, ?, ?)',
$this->datetimeToDB(Core::getCurrentDate())
),
[
$notification->getUserId() ? (int) $notification->getUserId() : null,
(int) $notification->getLevel(),
$notification->getContextId() ? (int) $notification->getContextId() : null,
(int) $notification->getType(),
(int) $notification->getAssocType(),
(int) $notification->getAssocId()
]
);
$notification->setId($this->getInsertId());
return $notification->getId();
}
/**
* Inserts or update a notification into notifications table.
*
* @param int $userId (optional)
* @param int $contextId (optional)
*
* @return mixed Notification or null
*/
public function build(int $contextId, int $level, int $type, int $assocType, int $assocId, ?int $userId = null): Notification
{
DB::table('notifications')
->when(
$contextId === PKPApplication::CONTEXT_SITE,
fn ($query) => $query->whereNull('context_id'),
fn ($query) => $query->where('context_id', '=', $contextId)
)
->where('level', '=', $level)
->where('assoc_type', '=', $assocType)
->where('assoc_id', '=', $assocId)
->when($userId !== null, fn ($query, $userId) => $query->where('user_id', '=', $userId))
->delete();
$notification = $this->newDataObject();
$notification->setContextId($contextId);
$notification->setLevel($level);
$notification->setType($type);
$notification->setAssocType($assocType);
$notification->setAssocId($assocId);
$notification->setUserId($userId);
$notificationId = $this->insertObject($notification);
$notification->setId($notificationId);
return $notification;
}
/**
* Delete Notification by notification id
*
* @param int $userId
*
*/
public function deleteById(int $notificationId, ?int $userId = null)
{
$query = DB::table('notifications')
->where('notification_id', '=', $notificationId)
->when($userId, fn ($query, $userId) => $query->where('user_id', '=', $userId))
->delete();
}
/**
* Delete Notification
*/
public function deleteObject(Notification $notification)
{
$this->deleteById($notification->getId());
}
/**
* Delete notification(s) by association
*/
public function deleteByAssoc(int $assocType, int $assocId, ?int $userId = null, ?int $type = null, ?int $contextId = null)
{
$notificationsFactory = $this->getByAssoc($assocType, $assocId, $userId, $type, $contextId);
while ($notification = $notificationsFactory->next()) {
$this->deleteObject($notification);
}
}
/**
* Get the number of unread messages for a user
*
* @param bool $read Whether to check for read (true) or unread (false) notifications
*/
public function getNotificationCount(bool $read = true, ?int $userId = null, ?int $contextId = null, ?int $level = Notification::NOTIFICATION_LEVEL_NORMAL): int
{
$params = [(int) $userId, (int) $level];
if ($contextId) {
$params[] = (int) $contextId;
}
$result = $this->retrieve(
'SELECT count(*) AS row_count FROM notifications WHERE user_id = ? AND date_read IS' . ($read ? ' NOT' : '') . ' NULL AND level = ?'
. (isset($contextId) ? ' AND context_id = ?' : ''),
$params
);
$row = (array) $result->current();
return $row ? $row['row_count'] : 0;
}
/**
* Transfer the notifications for a user.
*/
public function transferNotifications(int $oldUserId, int $newUserId)
{
$this->update(
'UPDATE notifications SET user_id = ? WHERE user_id = ?',
[$newUserId, $oldUserId]
);
}
/**
* Creates and returns an notification object from a row
*/
public function _fromRow(array $row): Notification
{
$notification = $this->newDataObject();
$notification->setId($row['notification_id']);
$notification->setUserId($row['user_id']);
$notification->setLevel($row['level']);
$notification->setDateCreated($this->datetimeFromDB($row['date_created']));
$notification->setDateRead($this->datetimeFromDB($row['date_read']));
$notification->setContextId($row['context_id']);
$notification->setType($row['type']);
$notification->setAssocType($row['assoc_type']);
$notification->setAssocId($row['assoc_id']);
Hook::call('NotificationDAO::_fromRow', [&$notification, &$row]);
return $notification;
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\NotificationDAO', '\NotificationDAO');
}
@@ -0,0 +1,101 @@
<?php
/**
* @file classes/notification/NotificationManagerDelegate.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class NotificationManagerDelegate
*
* @ingroup notification
*
* @brief Abstract class to support notification manager delegates
* that provide default implementation to the interface that defines
* notification presentation data. It also introduce a method to be
* extended by subclasses to update notification objects.
*/
namespace PKP\notification;
use APP\notification\Notification;
use PKP\core\PKPRequest;
abstract class NotificationManagerDelegate extends PKPNotificationOperationManager
{
/** @var int NOTIFICATION_TYPE_... */
private $_notificationType;
/**
* Constructor.
*
* @param int $notificationType NOTIFICATION_TYPE_...
*/
public function __construct($notificationType)
{
$this->_notificationType = $notificationType;
}
/**
* Get the current notification type this manager is handling.
*
* @return int NOTIFICATION_TYPE_...
*/
public function getNotificationType()
{
return $this->_notificationType;
}
/**
* Define operations to update notifications.
*
* @param PKPRequest $request Request object
* @param array $userIds List of user IDs to notify
* @param int $assocType Application::ASSOC_TYPE_...
* @param int $assocId ID corresponding to $assocType
*
* @return bool True iff success
*/
public function updateNotification($request, $userIds, $assocType, $assocId)
{
return false;
}
/**
* Check if this manager delegate can handle the
* creation of the passed notification type.
*
* @copydoc PKPNotificationOperationManager::createNotification()
*
* @param null|mixed $userId
* @param null|mixed $notificationType
* @param null|mixed $contextId
* @param null|mixed $assocType
* @param null|mixed $assocId
* @param null|mixed $params
*/
public function createNotification($request, $userId = null, $notificationType = null, $contextId = null, $assocType = null, $assocId = null, $level = Notification::NOTIFICATION_LEVEL_NORMAL, $params = null)
{
assert($notificationType == $this->getNotificationType() || $this->multipleTypesUpdate());
return parent::createNotification($request, $userId, $notificationType, $contextId, $assocType, $assocId, $level, $params);
}
/**
* Flag a notification manager that handles multiple notification
* types inside the update method within the same call. Only set
* this to true if you're sure the notification manager provides
* all information for all notification types you're handling (via
* the getNotification... methods).
*
* @return bool
*/
protected function multipleTypesUpdate()
{
return false;
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\NotificationManagerDelegate', '\NotificationManagerDelegate');
}
@@ -0,0 +1,99 @@
<?php
/**
* @file classes/notification/NotificationSettingsDAO.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 NotificationSettingsDAO
*
* @ingroup notification
*
* @see Notification
*
* @brief Operations for retrieving and modifying Notification metadata.
*/
namespace PKP\notification;
use APP\notification\Notification;
use Illuminate\Support\Facades\DB;
class NotificationSettingsDAO extends \PKP\db\DAO
{
/**
* Update a notification's metadata
*
* @param int $notificationId
*
* @return $params array
*/
public function getNotificationSettings($notificationId)
{
$result = $this->retrieve(
'SELECT * FROM notification_settings WHERE notification_id = ?',
[(int) $notificationId]
);
$params = [];
foreach ($result as $row) {
$name = $row->setting_name;
$value = $this->convertFromDB($row->setting_value, $row->setting_type);
$locale = $row->locale;
if ($locale == '') {
$params[$name] = $value;
} else {
$params[$name][$locale] = $value;
}
}
return $params;
}
/**
* Store a notification's metadata
*
* @param int $notificationId
* @param string $name
* @param string $value
* @param bool $isLocalized optional
* @param string $type optional
*/
public function updateNotificationSetting($notificationId, $name, $value, $isLocalized = false, $type = null)
{
if (!$isLocalized) {
$value = $this->convertToDB($value, $type);
DB::table('notification_settings')->updateOrInsert(
['notification_id' => (int) $notificationId, 'setting_name' => $name, 'locale' => ''],
['setting_value' => $value, 'setting_type' => $type]
);
} else {
if (is_array($value)) {
foreach ($value as $locale => $localeValue) {
$this->update('DELETE FROM notification_settings WHERE notification_id = ? AND setting_name = ? AND locale = ?', [$notificationId, $name, $locale]);
if (empty($localeValue)) {
continue;
}
$type = null;
$this->update(
'INSERT INTO notification_settings
(notification_id, setting_name, setting_value, setting_type, locale)
VALUES (?, ?, ?, ?, ?)',
[
(int) $notificationId,
$name, $this->convertToDB($localeValue, $type),
$type,
$locale
]
);
}
}
}
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\NotificationSettingsDAO', '\NotificationSettingsDAO');
}
@@ -0,0 +1,207 @@
<?php
/**
* @file classes/notification/NotificationSubscriptionSettingsDAO.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 NotificationSubscriptionSettingsDAO
*
* @ingroup notification
*
* @see Notification
*
* @brief Operations for retrieving and modifying user's notification settings.
* This class stores user settings that determine how notifications should be
* delivered to them.
*/
namespace PKP\notification;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
class NotificationSubscriptionSettingsDAO extends \PKP\db\DAO
{
/** @var string The setting which holds the notification status */
public const BLOCKED_NOTIFICATION_KEY = 'blocked_notification';
/** @var string The setting which holds the email notification status */
public const BLOCKED_EMAIL_NOTIFICATION_KEY = 'blocked_emailed_notification';
/**
* Delete a notification setting by setting name
*
* @param int $notificationId
* @param int $userId
* @param string $settingName optional
*/
public function deleteNotificationSubscriptionSettings($notificationId, $userId, $settingName = null)
{
$params = [(int) $notificationId, (int) $userId];
if ($settingName) {
$params[] = $settingName;
}
return $this->update(
'DELETE FROM notification_subscription_settings
WHERE notification_id= ? AND user_id = ?' . isset($settingName) ? ' AND setting_name = ?' : '',
$params
);
}
/**
* Retrieve Notification subscription settings by user id
*
* @param string $settingName
* @param int $userId
*
* @return array
*/
public function &getNotificationSubscriptionSettings($settingName, $userId, ?int $contextId)
{
$result = $this->retrieve(
'SELECT setting_value FROM notification_subscription_settings WHERE user_id = ? AND setting_name = ? AND context = ?',
[(int) $userId, $settingName, $contextId]
);
$settings = [];
foreach ($result as $row) {
$settings[] = (int) $row->setting_value;
}
return $settings;
}
/**
* Update a user's notification subscription settings
*
* @param string $settingName
* @param array $settings
* @param int $userId
*/
public function updateNotificationSubscriptionSettings($settingName, $settings, $userId, ?int $contextId)
{
// Delete old settings first, then insert new settings
$this->update(
'DELETE FROM notification_subscription_settings WHERE user_id = ? AND setting_name = ? AND context = ?',
[(int) $userId, $settingName, $contextId]
);
foreach ($settings as $setting) {
$this->update(
'INSERT INTO notification_subscription_settings
(setting_name, setting_value, user_id, context, setting_type)
VALUES
(?, ?, ?, ?, ?)',
[
$settingName,
(int) $setting,
(int) $userId,
$contextId,
'int'
]
);
}
}
/**
* Gets a user id by an RSS token value
*
* @param int $token
* @param int $contextId
*
* @return int|null
*/
public function getUserIdByRSSToken($token, $contextId)
{
$result = $this->retrieve(
'SELECT user_id FROM notification_subscription_settings WHERE setting_value = ? AND setting_name = ? AND context = ?',
[$token, 'token', (int) $contextId]
);
$row = $result->current();
return $row ? $row->user_id : null;
}
/**
* Gets an RSS token for a user id
*
* @param int $userId
* @param int $contextId
*
* @return int|null
*/
public function getRSSTokenByUserId($userId, $contextId)
{
$result = $this->retrieve(
'SELECT setting_value FROM notification_subscription_settings WHERE user_id = ? AND setting_name = ? AND context = ?',
[(int) $userId, 'token', (int) $contextId]
);
$row = $result->current();
return $row ? $row->setting_value : null;
}
/**
* Generates and inserts a new token for a user's RSS feed
*
* @param int $userId
* @param int $contextId
*
* @return string
*/
public function insertNewRSSToken($userId, $contextId)
{
$token = uniqid(random_int(0, PHP_INT_MAX));
// Recurse if this token already exists
if ($this->getUserIdByRSSToken($token, $contextId)) {
return $this->insertNewRSSToken($userId, $contextId);
}
$this->update(
'INSERT INTO notification_subscription_settings
(setting_name, setting_value, user_id, context, setting_type)
VALUES
(?, ?, ?, ?, ?)',
[
'token',
$token,
(int) $userId,
(int) $contextId,
'string'
]
);
return $token;
}
/**
* Retrieves IDs of all users subscribed to the notification of specific type
*
* @param string[] $blockedNotificationKey list of the NotificationSubscriptionSettingsDAO::BLOCKED_* constants
* @param int[] $blockedNotificationType list of the PKPNotification::NOTIFICATION_TYPE_* constants
*/
public function getSubscribedUserIds(array $blockedNotificationKey, array $blockedNotificationType, array $contextIds, ?array $roleIds = null): Collection
{
return DB::table('users as u')->select('u.user_id')
->whereNotIn(
'u.user_id',
fn (Builder $q) =>
$q->select('nss.user_id')->from('notification_subscription_settings as nss')
->whereIn('setting_name', $blockedNotificationKey)
->whereIn('setting_value', $blockedNotificationType)
)->whereExists(
fn (Builder $q) => $q->from('user_user_groups', 'uug')
->join('user_groups AS ug', 'uug.user_group_id', '=', 'ug.user_group_id')
->whereColumn('uug.user_id', '=', 'u.user_id')
->whereIn('ug.context_id', $contextIds)
->when(!is_null($roleIds), fn (Builder $q) => $q->whereIn('ug.role_id', $roleIds))
)->pluck('user_id');
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\NotificationSubscriptionSettingsDAO', '\NotificationSubscriptionSettingsDAO');
}
@@ -0,0 +1,315 @@
<?php
/**
* @file classes/notification/Notification.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 PKPNotification
*
* @ingroup notification
*
* @see NotificationDAO
*
* @brief Class for Notification.
*/
namespace PKP\notification;
class PKPNotification extends \PKP\core\DataObject
{
// Notification levels. Determines notification behavior
public const NOTIFICATION_LEVEL_TRIVIAL = 1;
public const NOTIFICATION_LEVEL_NORMAL = 2;
public const NOTIFICATION_LEVEL_TASK = 3;
// Notification types. Determines what text and URL to display for notification
public const NOTIFICATION_TYPE_SUCCESS = 0x0000001;
public const NOTIFICATION_TYPE_WARNING = 0x0000002;
public const NOTIFICATION_TYPE_ERROR = 0x0000003;
public const NOTIFICATION_TYPE_FORBIDDEN = 0x0000004;
public const NOTIFICATION_TYPE_INFORMATION = 0x0000005;
public const NOTIFICATION_TYPE_HELP = 0x0000006;
public const NOTIFICATION_TYPE_FORM_ERROR = 0x0000007;
public const NOTIFICATION_TYPE_NEW_ANNOUNCEMENT = 0x0000008;
// define('NOTIFICATION_TYPE_LOCALE_INSTALLED', 0x4000001); // DEPRECATED; DO NOT USE
public const NOTIFICATION_TYPE_PLUGIN_ENABLED = 0x5000001;
public const NOTIFICATION_TYPE_PLUGIN_DISABLED = 0x5000002;
public const NOTIFICATION_TYPE_PLUGIN_BASE = 0x6000001;
// Workflow-level notifications
public const NOTIFICATION_TYPE_SUBMISSION_SUBMITTED = 0x1000001;
// public const NOTIFICATION_TYPE_METADATA_MODIFIED = 0x1000002; // DEPRECATED; DO NOT USE
public const NOTIFICATION_TYPE_REVIEWER_COMMENT = 0x1000003;
public const NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_SUBMISSION = 0x1000004;
public const NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_INTERNAL_REVIEW = 0x1000005;
public const NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EXTERNAL_REVIEW = 0x1000006;
public const NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EDITING = 0x1000007;
public const NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_PRODUCTION = 0x1000008;
// define('NOTIFICATION_TYPE_AUDITOR_REQUEST', 0x1000009); // DEPRECATED; DO NOT USE
public const NOTIFICATION_TYPE_REVIEW_ASSIGNMENT = 0x100000B;
public const NOTIFICATION_TYPE_EDITOR_DECISION_INTERNAL_REVIEW = 0x100000D;
public const NOTIFICATION_TYPE_EDITOR_DECISION_ACCEPT = 0x100000E;
public const NOTIFICATION_TYPE_EDITOR_DECISION_EXTERNAL_REVIEW = 0x100000F;
public const NOTIFICATION_TYPE_EDITOR_DECISION_PENDING_REVISIONS = 0x1000010;
public const NOTIFICATION_TYPE_EDITOR_DECISION_RESUBMIT = 0x1000011;
public const NOTIFICATION_TYPE_EDITOR_DECISION_NEW_ROUND = 0x1000030;
public const NOTIFICATION_TYPE_EDITOR_DECISION_DECLINE = 0x1000012;
public const NOTIFICATION_TYPE_EDITOR_DECISION_SEND_TO_PRODUCTION = 0x1000013;
public const NOTIFICATION_TYPE_EDITOR_DECISION_REVERT_DECLINE = 0x1000020;
public const NOTIFICATION_TYPE_REVIEW_ROUND_STATUS = 0x1000014;
public const NOTIFICATION_TYPE_PENDING_INTERNAL_REVISIONS = 0x1000015;
public const NOTIFICATION_TYPE_PENDING_EXTERNAL_REVISIONS = 0x1000016;
public const NOTIFICATION_TYPE_COPYEDIT_ASSIGNMENT = 0x1000017;
public const NOTIFICATION_TYPE_LAYOUT_ASSIGNMENT = 0x1000019;
public const NOTIFICATION_TYPE_INDEX_ASSIGNMENT = 0x100001A;
public const NOTIFICATION_TYPE_APPROVE_SUBMISSION = 0x100001B;
public const NOTIFICATION_TYPE_CONFIGURE_PAYMENT_METHOD = 0x100001C;
public const NOTIFICATION_TYPE_FORMAT_NEEDS_APPROVED_SUBMISSION = 0x100001D;
public const NOTIFICATION_TYPE_VISIT_CATALOG = 0x100001E;
public const NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_REQUIRED = 0x100001F;
public const NOTIFICATION_TYPE_NEW_QUERY = 0x1000021;
public const NOTIFICATION_TYPE_QUERY_ACTIVITY = 0x1000022;
public const NOTIFICATION_TYPE_ASSIGN_COPYEDITOR = 0x1000023;
public const NOTIFICATION_TYPE_AWAITING_COPYEDITS = 0x1000024;
public const NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS = 0x1000025;
public const NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER = 0x1000026;
public const NOTIFICATION_TYPE_EDITOR_ASSIGN = 0x1000027;
public const NOTIFICATION_TYPE_PAYMENT_REQUIRED = 0x1000028;
public const NOTIFICATION_TYPE_REVIEW_ASSIGNMENT_UPDATED = 0x1000029;
public const NOTIFICATION_TYPE_EDITORIAL_REPORT = 0x100002A;
public const NOTIFICATION_TYPE_SUBMISSION_NEW_VERSION = 0x100002B;
public const NOTIFICATION_TYPE_EDITORIAL_REMINDER = 0x100002C;
// Maximum number of notifications that can be sent per job
public const NOTIFICATION_CHUNK_SIZE_LIMIT = 100;
/**
* get user id associated with this notification
*
* @return int
*/
public function getUserId()
{
return $this->getData('userId');
}
/**
* set user id associated with this notification
*
* @param int $userId
*/
public function setUserId($userId)
{
$this->setData('userId', $userId);
}
/**
* Get the level (NOTIFICATION_LEVEL_...) for this notification
*
* @return int
*/
public function getLevel()
{
return $this->getData('level');
}
/**
* Set the level (NOTIFICATION_LEVEL_...) for this notification
*
* @param int $level
*/
public function setLevel($level)
{
$this->setData('level', $level);
}
/**
* get date notification was created
*
* @return string (YYYY-MM-DD HH:MM:SS)
*/
public function getDateCreated()
{
return $this->getData('dateCreated');
}
/**
* set date notification was created
*
* @param string $dateCreated (YYYY-MM-DD HH:MM:SS)
*/
public function setDateCreated($dateCreated)
{
$this->setData('dateCreated', $dateCreated);
}
/**
* get date notification is read by user
*
* @return string (YYYY-MM-DD HH:MM:SS)
*/
public function getDateRead()
{
return $this->getData('dateRead');
}
/**
* set date notification is read by user
*
* @param string $dateRead (YYYY-MM-DD HH:MM:SS)
*/
public function setDateRead($dateRead)
{
$this->setData('dateRead', $dateRead);
}
/**
* get notification type
*
* @return int
*/
public function getType()
{
return $this->getData('type');
}
/**
* set notification type
*
* @param int $type
*/
public function setType($type)
{
$this->setData('type', $type);
}
/**
* get notification type
*
* @return int
*/
public function getAssocType()
{
return $this->getData('assocType');
}
/**
* set notification type
*
* @param int $assocType
*/
public function setAssocType($assocType)
{
$this->setData('assocType', $assocType);
}
/**
* get notification assoc id
*
* @return int
*/
public function getAssocId()
{
return $this->getData('assocId');
}
/**
* set notification assoc id
*
* @param int $assocId
*/
public function setAssocId($assocId)
{
$this->setData('assocId', $assocId);
}
/**
* get context id
*
* @return int
*/
public function getContextId()
{
return $this->getData('context_id');
}
/**
* set context id
*/
public function setContextId($contextId)
{
$this->setData('context_id', $contextId);
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\PKPNotification', '\PKPNotification');
foreach ([
'NOTIFICATION_LEVEL_TRIVIAL',
'NOTIFICATION_LEVEL_NORMAL',
'NOTIFICATION_LEVEL_TASK',
'NOTIFICATION_TYPE_SUCCESS',
'NOTIFICATION_TYPE_WARNING',
'NOTIFICATION_TYPE_ERROR',
'NOTIFICATION_TYPE_FORBIDDEN',
'NOTIFICATION_TYPE_INFORMATION',
'NOTIFICATION_TYPE_HELP',
'NOTIFICATION_TYPE_FORM_ERROR',
'NOTIFICATION_TYPE_NEW_ANNOUNCEMENT',
'NOTIFICATION_TYPE_PLUGIN_ENABLED',
'NOTIFICATION_TYPE_PLUGIN_DISABLED',
'NOTIFICATION_TYPE_PLUGIN_BASE',
'NOTIFICATION_TYPE_SUBMISSION_SUBMITTED',
'NOTIFICATION_TYPE_REVIEWER_COMMENT',
'NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_SUBMISSION',
'NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_INTERNAL_REVIEW',
'NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EXTERNAL_REVIEW',
'NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EDITING',
'NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_PRODUCTION',
'NOTIFICATION_TYPE_REVIEW_ASSIGNMENT',
'NOTIFICATION_TYPE_EDITOR_DECISION_INTERNAL_REVIEW',
'NOTIFICATION_TYPE_EDITOR_DECISION_ACCEPT',
'NOTIFICATION_TYPE_EDITOR_DECISION_EXTERNAL_REVIEW',
'NOTIFICATION_TYPE_EDITOR_DECISION_PENDING_REVISIONS',
'NOTIFICATION_TYPE_EDITOR_DECISION_RESUBMIT',
'NOTIFICATION_TYPE_EDITOR_DECISION_NEW_ROUND',
'NOTIFICATION_TYPE_EDITOR_DECISION_DECLINE',
'NOTIFICATION_TYPE_EDITOR_DECISION_SEND_TO_PRODUCTION',
'NOTIFICATION_TYPE_EDITOR_DECISION_REVERT_DECLINE',
'NOTIFICATION_TYPE_REVIEW_ROUND_STATUS',
'NOTIFICATION_TYPE_PENDING_INTERNAL_REVISIONS',
'NOTIFICATION_TYPE_PENDING_EXTERNAL_REVISIONS',
'NOTIFICATION_TYPE_COPYEDIT_ASSIGNMENT',
'NOTIFICATION_TYPE_LAYOUT_ASSIGNMENT',
'NOTIFICATION_TYPE_INDEX_ASSIGNMENT',
'NOTIFICATION_TYPE_APPROVE_SUBMISSION',
'NOTIFICATION_TYPE_CONFIGURE_PAYMENT_METHOD',
'NOTIFICATION_TYPE_FORMAT_NEEDS_APPROVED_SUBMISSION',
'NOTIFICATION_TYPE_VISIT_CATALOG',
'NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_REQUIRED',
'NOTIFICATION_TYPE_NEW_QUERY',
'NOTIFICATION_TYPE_QUERY_ACTIVITY',
'NOTIFICATION_TYPE_ASSIGN_COPYEDITOR',
'NOTIFICATION_TYPE_AWAITING_COPYEDITS',
'NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS',
'NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER',
'NOTIFICATION_TYPE_EDITOR_ASSIGN',
'NOTIFICATION_TYPE_PAYMENT_REQUIRED',
'NOTIFICATION_TYPE_REVIEW_ASSIGNMENT_UPDATED',
'NOTIFICATION_TYPE_EDITORIAL_REPORT',
'NOTIFICATION_TYPE_SUBMISSION_NEW_VERSION',
] as $constantName) {
define($constantName, constant('\PKPNotification::' . $constantName));
}
}
@@ -0,0 +1,586 @@
<?php
/**
* @file classes/notification/PKPNotificationManager.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 PKPNotificationManager
*
* @ingroup notification
*
* @see NotificationDAO
* @see Notification
*
* @brief Class for Notification Manager.
*/
namespace PKP\notification;
use APP\core\Application;
use APP\decision\Decision;
use APP\facades\Repo;
use APP\notification\Notification;
use APP\template\TemplateManager;
use PKP\core\PKPApplication;
use PKP\db\DAORegistry;
use PKP\notification\managerDelegate\EditorAssignmentNotificationManager;
use PKP\notification\managerDelegate\EditorDecisionNotificationManager;
use PKP\notification\managerDelegate\EditorialReportNotificationManager;
use PKP\notification\managerDelegate\PendingRevisionsNotificationManager;
use PKP\notification\managerDelegate\PKPEditingProductionStatusNotificationManager;
use PKP\notification\managerDelegate\QueryNotificationManager;
use PKP\notification\managerDelegate\SubmissionNotificationManager;
use PKP\payment\QueuedPaymentDAO;
use PKP\security\Role;
use PKP\stageAssignment\StageAssignmentDAO;
use PKP\submission\reviewAssignment\ReviewAssignmentDAO;
use PKP\submission\reviewRound\ReviewRoundDAO;
use PKP\workflow\WorkflowStageDAO;
class PKPNotificationManager extends PKPNotificationOperationManager
{
/**
* Construct a URL for the notification based on its type and associated object
*
* @copydoc PKPNotificationOperationManager::getNotificationContents()
*/
public function getNotificationUrl($request, $notification)
{
$url = parent::getNotificationUrl($request, $notification);
$dispatcher = Application::get()->getDispatcher();
$contextDao = Application::getContextDAO();
$context = $contextDao->getById($notification->getContextId());
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGN:
assert($notification->getAssocType() == Application::ASSOC_TYPE_SUBMISSION && is_numeric($notification->getAssocId()));
return $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'workflow', 'access', $notification->getAssocId());
case PKPNotification::NOTIFICATION_TYPE_COPYEDIT_ASSIGNMENT:
case PKPNotification::NOTIFICATION_TYPE_LAYOUT_ASSIGNMENT:
case PKPNotification::NOTIFICATION_TYPE_INDEX_ASSIGNMENT:
assert($notification->getAssocType() == Application::ASSOC_TYPE_SUBMISSION && is_numeric($notification->getAssocId()));
return $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'workflow', 'access', $notification->getAssocId());
case PKPNotification::NOTIFICATION_TYPE_REVIEWER_COMMENT:
assert($notification->getAssocType() == Application::ASSOC_TYPE_REVIEW_ASSIGNMENT && is_numeric($notification->getAssocId()));
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
$reviewAssignment = $reviewAssignmentDao->getById($notification->getAssocId());
$workflowStageDao = DAORegistry::getDAO('WorkflowStageDAO'); /** @var WorkflowStageDAO $workflowStageDao */
$operation = $reviewAssignment->getStageId() == WORKFLOW_STAGE_ID_INTERNAL_REVIEW ? $workflowStageDao::WORKFLOW_STAGE_PATH_INTERNAL_REVIEW : $workflowStageDao::WORKFLOW_STAGE_PATH_EXTERNAL_REVIEW;
return $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'workflow', $operation, $reviewAssignment->getSubmissionId());
case PKPNotification::NOTIFICATION_TYPE_REVIEW_ASSIGNMENT:
case PKPNotification::NOTIFICATION_TYPE_REVIEW_ASSIGNMENT_UPDATED:
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
$reviewAssignment = $reviewAssignmentDao->getById($notification->getAssocId());
return $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'reviewer', 'submission', $reviewAssignment->getSubmissionId());
case PKPNotification::NOTIFICATION_TYPE_NEW_ANNOUNCEMENT:
assert($notification->getAssocType() == Application::ASSOC_TYPE_ANNOUNCEMENT);
$announcement = Repo::announcement()->get($notification->getAssocId());
$context = $contextDao->getById($announcement->getAssocId());
return $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'announcement', 'view', [$notification->getAssocId()]);
case PKPNotification::NOTIFICATION_TYPE_CONFIGURE_PAYMENT_METHOD:
return __('notification.type.configurePaymentMethod');
case PKPNotification::NOTIFICATION_TYPE_PAYMENT_REQUIRED:
$context = $contextDao->getById($notification->getContextId());
Application::getPaymentManager($context);
assert($notification->getAssocType() == Application::ASSOC_TYPE_QUEUED_PAYMENT);
$queuedPaymentDao = DAORegistry::getDAO('QueuedPaymentDAO'); /** @var QueuedPaymentDAO $queuedPaymentDao */
$queuedPayment = $queuedPaymentDao->getById($notification->getAssocId());
$context = $contextDao->getById($queuedPayment->getContextId());
return $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'payment', 'pay', [$queuedPayment->getId()]);
default:
$delegateResult = $this->getByDelegate(
$notification->getType(),
$notification->getAssocType(),
$notification->getAssocId(),
__FUNCTION__,
[$request, $notification]
);
if ($delegateResult) {
$url = $delegateResult;
}
return $url;
}
}
/**
* Return a message string for the notification based on its type
* and associated object.
*
* @copydoc PKPNotificationOperationManager::getNotificationContents()
*/
public function getNotificationMessage($request, $notification)
{
$message = parent::getNotificationMessage($request, $notification);
$type = $notification->getType();
assert(isset($type));
switch ($type) {
case PKPNotification::NOTIFICATION_TYPE_SUCCESS:
case PKPNotification::NOTIFICATION_TYPE_ERROR:
case PKPNotification::NOTIFICATION_TYPE_WARNING:
if (!is_null($this->getNotificationSettings($notification->getId()))) {
$notificationSettings = $this->getNotificationSettings($notification->getId());
return $notificationSettings['contents'];
} else {
return __('common.changesSaved');
}
// no break
case PKPNotification::NOTIFICATION_TYPE_FORM_ERROR:
case PKPNotification::NOTIFICATION_TYPE_ERROR:
$notificationSettings = $this->getNotificationSettings($notification->getId());
assert(!is_null($notificationSettings['contents']));
return $notificationSettings['contents'];
case PKPNotification::NOTIFICATION_TYPE_PLUGIN_ENABLED:
return $this->_getTranslatedKeyWithParameters('common.pluginEnabled', $notification->getId());
case PKPNotification::NOTIFICATION_TYPE_PLUGIN_DISABLED:
return $this->_getTranslatedKeyWithParameters('common.pluginDisabled', $notification->getId());
case PKPNotification::NOTIFICATION_TYPE_REVIEWER_COMMENT:
assert($notification->getAssocType() == Application::ASSOC_TYPE_REVIEW_ASSIGNMENT && is_numeric($notification->getAssocId()));
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
$reviewAssignment = $reviewAssignmentDao->getById($notification->getAssocId());
$submission = Repo::submission()->get($reviewAssignment->getSubmissionId());
return __('notification.type.reviewerComment', ['title' => $submission->getCurrentPublication()->getLocalizedTitle(null, 'html')]);
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGN:
assert($notification->getAssocType() == Application::ASSOC_TYPE_SUBMISSION && is_numeric($notification->getAssocId()));
$submission = Repo::submission()->get($notification->getAssocId());
return __('notification.type.editorAssign', ['title' => $submission->getCurrentPublication()->getLocalizedTitle(null, 'html')]);
case PKPNotification::NOTIFICATION_TYPE_COPYEDIT_ASSIGNMENT:
assert($notification->getAssocType() == Application::ASSOC_TYPE_SUBMISSION && is_numeric($notification->getAssocId()));
$submission = Repo::submission()->get($notification->getAssocId());
return __('notification.type.copyeditorRequest', ['title' => $submission->getCurrentPublication()->getLocalizedTitle(null, 'html')]);
case PKPNotification::NOTIFICATION_TYPE_LAYOUT_ASSIGNMENT:
assert($notification->getAssocType() == Application::ASSOC_TYPE_SUBMISSION && is_numeric($notification->getAssocId()));
$submission = Repo::submission()->get($notification->getAssocId());
return __('notification.type.layouteditorRequest', ['title' => $submission->getCurrentPublication()->getLocalizedTitle(null, 'html')]);
case PKPNotification::NOTIFICATION_TYPE_INDEX_ASSIGNMENT:
assert($notification->getAssocType() == Application::ASSOC_TYPE_SUBMISSION && is_numeric($notification->getAssocId()));
$submission = Repo::submission()->get($notification->getAssocId());
return __('notification.type.indexRequest', ['title' => $submission->getCurrentPublication()->getLocalizedTitle(null, 'html')]);
case PKPNotification::NOTIFICATION_TYPE_REVIEW_ASSIGNMENT:
return __('notification.type.reviewAssignment');
case PKPNotification::NOTIFICATION_TYPE_REVIEW_ASSIGNMENT_UPDATED:
return __('notification.type.reviewAssignmentUpdated');
case PKPNotification::NOTIFICATION_TYPE_REVIEW_ROUND_STATUS:
assert($notification->getAssocType() == Application::ASSOC_TYPE_REVIEW_ROUND && is_numeric($notification->getAssocId()));
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /** @var ReviewRoundDAO $reviewRoundDao */
$reviewRound = $reviewRoundDao->getById($notification->getAssocId());
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */
$user = $request->getUser();
$stageAssignments = $stageAssignmentDao->getBySubmissionAndRoleIds($reviewRound->getSubmissionId(), [Role::ROLE_ID_AUTHOR], null, $user->getId());
$isAuthor = (bool) $stageAssignments->next();
return __($reviewRound->getStatusKey($isAuthor));
case PKPNotification::NOTIFICATION_TYPE_PAYMENT_REQUIRED:
return __('payment.type.publication.required');
case PKPNotification::NOTIFICATION_TYPE_EDITORIAL_REPORT:
case PKPNotification::NOTIFICATION_TYPE_EDITORIAL_REMINDER:
$notificationSettings = $this->getNotificationSettings($notification->getId());
return $notificationSettings['contents'];
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_REVERT_DECLINE:
return __('notification.type.revertDecline');
default:
$delegateResult = $this->getByDelegate(
$notification->getType(),
$notification->getAssocType(),
$notification->getAssocId(),
__FUNCTION__,
[$request, $notification]
);
if ($delegateResult) {
$message = $delegateResult;
}
return $message;
}
}
/**
* Using the notification message, construct, if needed, any additional
* content for the notification body. If a specific notification type
* is not defined, it will return the parent method return value.
* Define a notification type case on this method only if you need to
* present more than just text in notification. If you need to define
* just a locale key, use the getNotificationMessage method only.
*
* @copydoc PKPNotificationOperationManager::getNotificationContents()
*/
public function getNotificationContents($request, $notification)
{
$content = parent::getNotificationContents($request, $notification);
$type = $notification->getType();
assert(isset($type));
switch ($type) {
case PKPNotification::NOTIFICATION_TYPE_FORM_ERROR:
return join(' ', $content);
case PKPNotification::NOTIFICATION_TYPE_ERROR:
if (!is_array($content)) {
return $content;
}
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign('errors', $content);
return $templateMgr->fetch('controllers/notification/errorNotificationContent.tpl');
default:
$delegateResult = $this->getByDelegate(
$notification->getType(),
$notification->getAssocType(),
$notification->getAssocId(),
__FUNCTION__,
[$request, $notification]
);
if ($delegateResult) {
$content = $delegateResult;
}
return $content;
}
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationContents()
*/
public function getNotificationTitle($notification)
{
$title = parent::getNotificationTitle($notification);
$type = $notification->getType();
assert(isset($type));
switch ($type) {
case PKPNotification::NOTIFICATION_TYPE_REVIEW_ROUND_STATUS:
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /** @var ReviewRoundDAO $reviewRoundDao */
$reviewRound = $reviewRoundDao->getById($notification->getAssocId());
return __('notification.type.roundStatusTitle', ['round' => $reviewRound->getRound()]);
case PKPNotification::NOTIFICATION_TYPE_FORM_ERROR:
return __('form.errorsOccurred');
default:
$delegateResult = $this->getByDelegate(
$notification->getType(),
$notification->getAssocType(),
$notification->getAssocId(),
__FUNCTION__,
[$notification]
);
if ($delegateResult) {
$title = $delegateResult;
}
return $title;
}
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationContents()
*/
public function getStyleClass($notification)
{
$styleClass = parent::getStyleClass($notification);
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_SUCCESS: return NOTIFICATION_STYLE_CLASS_SUCCESS;
case PKPNotification::NOTIFICATION_TYPE_WARNING: return NOTIFICATION_STYLE_CLASS_WARNING;
case PKPNotification::NOTIFICATION_TYPE_ERROR: return NOTIFICATION_STYLE_CLASS_ERROR;
case PKPNotification::NOTIFICATION_TYPE_INFORMATION: return NOTIFICATION_STYLE_CLASS_INFORMATION;
case PKPNotification::NOTIFICATION_TYPE_FORBIDDEN: return NOTIFICATION_STYLE_CLASS_FORBIDDEN;
case PKPNotification::NOTIFICATION_TYPE_HELP: return NOTIFICATION_STYLE_CLASS_HELP;
case PKPNotification::NOTIFICATION_TYPE_FORM_ERROR: return NOTIFICATION_STYLE_CLASS_FORM_ERROR;
case PKPNotification::NOTIFICATION_TYPE_REVIEW_ROUND_STATUS: return NOTIFICATION_STYLE_CLASS_INFORMATION;
default:
$delegateResult = $this->getByDelegate(
$notification->getType(),
$notification->getAssocType(),
$notification->getAssocId(),
__FUNCTION__,
[$notification]
);
if ($delegateResult) {
$styleClass = $delegateResult;
}
return $styleClass;
}
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationContents()
*/
public function getIconClass($notification)
{
$iconClass = parent::getIconClass($notification);
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_SUCCESS: return 'notifyIconSuccess';
case PKPNotification::NOTIFICATION_TYPE_WARNING: return 'notifyIconWarning';
case PKPNotification::NOTIFICATION_TYPE_ERROR: return 'notifyIconError';
case PKPNotification::NOTIFICATION_TYPE_INFORMATION: return 'notifyIconInfo';
case PKPNotification::NOTIFICATION_TYPE_FORBIDDEN: return 'notifyIconForbidden';
case PKPNotification::NOTIFICATION_TYPE_HELP: return 'notifyIconHelp';
default:
$delegateResult = $this->getByDelegate(
$notification->getType(),
$notification->getAssocType(),
$notification->getAssocId(),
__FUNCTION__,
[$notification]
);
if ($delegateResult) {
$iconClass = $delegateResult;
}
return $iconClass;
}
}
/**
* @copydoc PKPNotificationOperationManager::isVisibleToAllUsers()
*/
public function isVisibleToAllUsers($notificationType, $assocType, $assocId)
{
$isVisible = parent::isVisibleToAllUsers($notificationType, $assocType, $assocId);
switch ($notificationType) {
case PKPNotification::NOTIFICATION_TYPE_REVIEW_ROUND_STATUS:
case PKPNotification::NOTIFICATION_TYPE_APPROVE_SUBMISSION:
case PKPNotification::NOTIFICATION_TYPE_VISIT_CATALOG:
case PKPNotification::NOTIFICATION_TYPE_CONFIGURE_PAYMENT_METHOD:
$isVisible = true;
break;
case PKPNotification::NOTIFICATION_TYPE_PAYMENT_REQUIRED:
$isVisible = false;
break;
default:
$delegateResult = $this->getByDelegate(
$notificationType,
$assocType,
$assocId,
__FUNCTION__,
[$notificationType, $assocType, $assocId]
);
if (!is_null($delegateResult)) {
$isVisible = $delegateResult;
}
break;
}
return $isVisible;
}
/**
* Update notifications by type using a delegate. If you want to be able to use
* this method to update notifications associated with a certain type, you need
* to first create a manager delegate and define it in getMgrDelegate() method.
*
* @param \PKP\core\PKPRequest $request
* @param array $notificationTypes The type(s) of the notification(s) to
* be updated.
* @param array|null $userIds The notification user(s) id(s), or null for all.
* @param int $assocType Application::ASSOC_TYPE_... The notification associated object type.
* @param int $assocId The notification associated object id.
*
* @return mixed Return false if no operation is executed or the last operation
* returned value.
*/
final public function updateNotification($request, $notificationTypes, $userIds, $assocType, $assocId)
{
$returner = false;
foreach ($notificationTypes as $type) {
$managerDelegate = $this->getMgrDelegate($type, $assocType, $assocId);
if (!is_null($managerDelegate) && $managerDelegate instanceof \PKP\notification\NotificationManagerDelegate) {
$returner = $managerDelegate->updateNotification($request, $userIds, $assocType, $assocId);
} else {
assert(false);
}
}
return $returner;
}
/**
* Get all subscribable notification types along with names and their setting type values
*
* @return array
*/
public function getNotificationSettingsMap()
{
return [
PKPNotification::NOTIFICATION_TYPE_SUBMISSION_SUBMITTED => ['settingName' => 'notificationSubmissionSubmitted',
'emailSettingName' => 'emailNotificationSubmissionSubmitted',
'settingKey' => 'notification.type.submissionSubmitted'],
PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_REQUIRED => ['settingName' => 'notificationEditorAssignmentRequired',
'emailSettingName' => 'emailNotificationEditorAssignmentRequired',
'settingKey' => 'notification.type.editorAssignmentTask'],
PKPNotification::NOTIFICATION_TYPE_REVIEWER_COMMENT => ['settingName' => 'notificationReviewerComment',
'emailSettingName' => 'emailNotificationReviewerComment',
'settingKey' => 'notification.type.reviewerComment'],
PKPNotification::NOTIFICATION_TYPE_NEW_QUERY => ['settingName' => 'notificationNewQuery',
'emailSettingName' => 'emailNotificationNewQuery',
'settingKey' => 'notification.type.queryAdded'],
PKPNotification::NOTIFICATION_TYPE_QUERY_ACTIVITY => ['settingName' => 'notificationQueryActivity',
'emailSettingName' => 'emailNotificationQueryActivity',
'settingKey' => 'notification.type.queryActivity'],
PKPNotification::NOTIFICATION_TYPE_NEW_ANNOUNCEMENT => ['settingName' => 'notificationNewAnnouncement',
'emailSettingName' => 'emailNotificationNewAnnouncement',
'settingKey' => 'notification.type.newAnnouncement'],
PKPNotification::NOTIFICATION_TYPE_EDITORIAL_REMINDER => ['settingName' => 'notificationEditorialReminder',
'emailSettingName' => 'emailNotificationEditorialReminder',
'settingKey' => 'notification.type.editorialReminder'],
PKPNotification::NOTIFICATION_TYPE_EDITORIAL_REPORT => ['settingName' => 'notificationEditorialReport',
'emailSettingName' => 'emailNotificationEditorialReport',
'settingKey' => 'notification.type.editorialReport']
];
}
/**
* Get the stage-level notification type constants for editorial decisions
*
* @return int[]
*/
public function getDecisionStageNotifications(): array
{
return [
PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_SUBMISSION,
PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EXTERNAL_REVIEW,
PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EDITING,
PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_PRODUCTION
];
}
/**
* Get the notification type for each editor decision
*
* @return int One of the Notification::NOTIFICATION_TYPE_ constants
*/
public function getNotificationTypeByEditorDecision(Decision $decision): ?int
{
switch ($decision->getData('decision')) {
case Decision::ACCEPT:
return Notification::NOTIFICATION_TYPE_EDITOR_DECISION_ACCEPT;
case Decision::EXTERNAL_REVIEW:
return Notification::NOTIFICATION_TYPE_EDITOR_DECISION_EXTERNAL_REVIEW;
case Decision::PENDING_REVISIONS:
return Notification::NOTIFICATION_TYPE_EDITOR_DECISION_PENDING_REVISIONS;
case Decision::RESUBMIT:
return Notification::NOTIFICATION_TYPE_EDITOR_DECISION_RESUBMIT;
case Decision::NEW_EXTERNAL_ROUND:
return Notification::NOTIFICATION_TYPE_EDITOR_DECISION_NEW_ROUND;
case Decision::DECLINE:
case Decision::INITIAL_DECLINE:
return Notification::NOTIFICATION_TYPE_EDITOR_DECISION_DECLINE;
case Decision::REVERT_DECLINE:
return Notification::NOTIFICATION_TYPE_EDITOR_DECISION_REVERT_DECLINE;
case Decision::SEND_TO_PRODUCTION:
return Notification::NOTIFICATION_TYPE_EDITOR_DECISION_SEND_TO_PRODUCTION;
}
return null;
}
//
// Protected methods
//
/**
* Get the notification manager delegate based on the passed notification type.
*
* @param int $notificationType
* @param int $assocType
* @param int $assocId
*
* @return mixed Null or NotificationManagerDelegate
*/
protected function getMgrDelegate($notificationType, $assocType, $assocId)
{
switch ($notificationType) {
case PKPNotification::NOTIFICATION_TYPE_SUBMISSION_SUBMITTED:
case PKPNotification::NOTIFICATION_TYPE_SUBMISSION_NEW_VERSION:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_REQUIRED:
assert($assocType == Application::ASSOC_TYPE_SUBMISSION && is_numeric($assocId));
return new SubmissionNotificationManager($notificationType);
case PKPNotification::NOTIFICATION_TYPE_NEW_QUERY:
case PKPNotification::NOTIFICATION_TYPE_QUERY_ACTIVITY:
return new QueryNotificationManager($notificationType);
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_SUBMISSION:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EXTERNAL_REVIEW:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EDITING:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_PRODUCTION:
assert($assocType == Application::ASSOC_TYPE_SUBMISSION && is_numeric($assocId));
return new EditorAssignmentNotificationManager($notificationType);
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_ACCEPT:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_EXTERNAL_REVIEW:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_PENDING_REVISIONS:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_RESUBMIT:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_NEW_ROUND:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_DECLINE:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_REVERT_DECLINE:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_SEND_TO_PRODUCTION:
assert($assocType == Application::ASSOC_TYPE_SUBMISSION && is_numeric($assocId));
return new EditorDecisionNotificationManager($notificationType);
case PKPNotification::NOTIFICATION_TYPE_PENDING_INTERNAL_REVISIONS:
case PKPNotification::NOTIFICATION_TYPE_PENDING_EXTERNAL_REVISIONS:
assert($assocType == Application::ASSOC_TYPE_SUBMISSION && is_numeric($assocId));
return new PendingRevisionsNotificationManager($notificationType);
case PKPNotification::NOTIFICATION_TYPE_ASSIGN_COPYEDITOR:
case PKPNotification::NOTIFICATION_TYPE_AWAITING_COPYEDITS:
case PKPNotification::NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER:
case PKPNotification::NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS:
assert($assocType == Application::ASSOC_TYPE_SUBMISSION && is_numeric($assocId));
return new PKPEditingProductionStatusNotificationManager($notificationType);
case PKPNotification::NOTIFICATION_TYPE_EDITORIAL_REPORT:
return new EditorialReportNotificationManager($notificationType);
}
return null; // No delegate required, let calling context handle null.
}
/**
* Try to use a delegate to retrieve a notification data that's defined
* by the implementation of the
*
* @param string $operationName
*/
protected function getByDelegate($notificationType, $assocType, $assocId, $operationName, $parameters)
{
$delegate = $this->getMgrDelegate($notificationType, $assocType, $assocId);
if ($delegate instanceof \PKP\notification\NotificationManagerDelegate) {
return call_user_func_array([$delegate, $operationName], $parameters);
} else {
return null;
}
}
//
// Private helper methods.
//
/**
* Return notification settings.
*
* @param int $notificationId
*
* @return ?array
*/
private function getNotificationSettings($notificationId)
{
$notificationSettingsDao = DAORegistry::getDAO('NotificationSettingsDAO'); /** @var NotificationSettingsDAO $notificationSettingsDao */
$notificationSettings = $notificationSettingsDao->getNotificationSettings($notificationId);
if (empty($notificationSettings)) {
return null;
} else {
return $notificationSettings;
}
}
/**
* Helper function to get a translated string from a notification with parameters
*
* @param string $key
* @param int $notificationId
*
* @return string
*/
private function _getTranslatedKeyWithParameters($key, $notificationId)
{
$params = $this->getNotificationSettings($notificationId);
return __($key, $this->getParamsForCurrentLocale($params));
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\PKPNotificationManager', '\PKPNotificationManager');
}
@@ -0,0 +1,452 @@
<?php
/**
* @file classes/notification/PKPNotificationOperationManager.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 PKPNotificationOperationManager
*
* @ingroup notification
*
* @see NotificationDAO
* @see Notification
*
* @brief Base class for notification manager that implements
* basic notification operations and default notifications info.
* Subclasses can implement specific information.
*/
namespace PKP\notification;
use APP\core\Application;
use APP\core\Request;
use APP\notification\Notification;
use APP\template\TemplateManager;
use Firebase\JWT\JWT;
use InvalidArgumentException;
use PKP\config\Config;
use PKP\core\Core;
use PKP\core\PKPApplication;
use PKP\core\PKPRequest;
use PKP\db\DAORegistry;
use PKP\facades\Locale;
use PKP\linkAction\LinkAction;
abstract class PKPNotificationOperationManager implements INotificationInfoProvider
{
//
// Implement INotificationInfoProvider with default values.
//
/**
* @copydoc INotificationInfoProvider::getNotificationUrl()
*/
public function getNotificationUrl($request, $notification)
{
return null;
}
/**
* @copydoc INotificationInfoProvider::getNotificationMessage()
*/
public function getNotificationMessage($request, $notification)
{
return null;
}
/**
* Provide the notification message as default content.
*
* @copydoc INotificationInfoProvider::getNotificationContents()
*/
public function getNotificationContents($request, $notification)
{
return $this->getNotificationMessage($request, $notification);
}
/**
* @copydoc INotificationInfoProvider::getNotificationTitle()
*/
public function getNotificationTitle($notification)
{
return __('notification.notification');
}
/**
* @copydoc INotificationInfoProvider::getStyleClass()
*/
public function getStyleClass($notification)
{
return '';
}
/**
* @copydoc INotificationInfoProvider::getIconClass()
*/
public function getIconClass($notification)
{
return '';
}
/**
* @copydoc INotificationInfoProvider::isVisibleToAllUsers()
*/
public function isVisibleToAllUsers($notificationType, $assocType, $assocId)
{
return false;
}
//
// Notification manager operations.
//
/**
* Iterate through the localized params for a notification's locale key.
* For each parameter, return (in preferred order) a value for the user's current locale,
* a param for the journal's default locale, or the first value (in case the value
* is not localized)
*
* @param array $params
*
* @return array
*/
public function getParamsForCurrentLocale($params)
{
$locale = Locale::getLocale();
$primaryLocale = Locale::getPrimaryLocale();
$localizedParams = [];
foreach ($params as $name => $value) {
if (!is_array($value)) {
// Non-localized text
$localizedParams[$name] = $value;
} elseif (isset($value[$locale])) {
// Check if the parameter is in the user's current locale
$localizedParams[$name] = $value[$locale];
} elseif (isset($value[$primaryLocale])) {
// Check if the parameter is in the default site locale
$localizedParams[$name] = $value[$primaryLocale];
} else {
$context = Application::get()->getRequest()->getContext();
// Otherwise, iterate over all supported locales and return the first match
$locales = $context->getSupportedLocaleNames();
foreach ($locales as $localeKey) {
if (isset($value[$localeKey])) {
$localizedParams[$name] = $value[$localeKey];
}
}
}
}
return $localizedParams;
}
/**
* Create a new notification with the specified arguments and insert into DB
*
* @param ?PKPRequest $request
* @param int $userId (optional)
* @param int $notificationType
* @param int $contextId
* @param int $assocType
* @param int $assocId
* @param int $level
* @param array $params
*
* @return ?Notification
*/
public function createNotification($request, $userId = null, $notificationType = null, $contextId = null, $assocType = null, $assocId = null, $level = Notification::NOTIFICATION_LEVEL_NORMAL, $params = null)
{
$blockedNotifications = $this->getUserBlockedNotifications($userId, $contextId);
if (!in_array($notificationType, $blockedNotifications)) {
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
$notification = $notificationDao->newDataObject(); /** @var Notification $notification */
$notification->setUserId((int) $userId);
$notification->setType((int) $notificationType);
$notification->setContextId((int) $contextId);
$notification->setAssocType((int) $assocType);
$notification->setAssocId((int) $assocId);
$notification->setLevel((int) $level);
$notificationId = $notificationDao->insertObject($notification);
if ($params) {
$notificationSettingsDao = DAORegistry::getDAO('NotificationSettingsDAO'); /** @var NotificationSettingsDAO $notificationSettingsDao */
foreach ($params as $name => $value) {
$notificationSettingsDao->updateNotificationSetting($notificationId, $name, $value);
}
}
return $notification;
}
}
/**
* Create a new notification with the specified arguments and insert into DB
* This is a static method
*
* @param int $userId
* @param int $notificationType
* @param array $params
*
* @return Notification object
*/
public function createTrivialNotification($userId, $notificationType = PKPNotification::NOTIFICATION_TYPE_SUCCESS, $params = null)
{
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
$notification = $notificationDao->newDataObject();
$notification->setUserId($userId);
$notification->setContextId(PKPApplication::CONTEXT_ID_NONE);
$notification->setType($notificationType);
$notification->setLevel(Notification::NOTIFICATION_LEVEL_TRIVIAL);
$notificationId = $notificationDao->insertObject($notification);
if ($params) {
$notificationSettingsDao = DAORegistry::getDAO('NotificationSettingsDAO'); /** @var NotificationSettingsDAO $notificationSettingsDao */
foreach ($params as $name => $value) {
$notificationSettingsDao->updateNotificationSetting($notificationId, $name, $value);
}
}
return $notification;
}
/**
* Deletes trivial notifications from database.
*
* @param array $notifications
*/
public function deleteTrivialNotifications($notifications)
{
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
foreach ($notifications as $notification) {
// Delete only trivial notifications.
if ($notification->getLevel() == Notification::NOTIFICATION_LEVEL_TRIVIAL) {
$notificationDao->deleteById($notification->getId(), $notification->getUserId());
}
}
}
/**
* General notification data formatting.
*
* @param PKPRequest $request
* @param array $notifications
*
* @return array
*/
public function formatToGeneralNotification($request, $notifications)
{
$formattedNotificationsData = [];
foreach ($notifications as $notification) { /** @var Notification $notification */
$formattedNotificationsData[$notification->getLevel()][$notification->getId()] = [
'title' => $this->getNotificationTitle($notification),
'text' => $this->getNotificationContents($request, $notification),
'addclass' => $this->getStyleClass($notification),
'notice_icon' => $this->getIconClass($notification),
'styling' => 'jqueryui',
];
}
return $formattedNotificationsData;
}
/**
* In place notification data formating.
*
* @param PKPRequest $request
* @param array $notifications
*
* @return array
*/
public function formatToInPlaceNotification($request, $notifications)
{
$formattedNotificationsData = null;
if (!empty($notifications)) {
$templateMgr = TemplateManager::getManager($request);
foreach ((array)$notifications as $notification) {
$formattedNotificationsData[$notification->getLevel()][$notification->getId()] = $this->formatNotification($request, $notification, 'controllers/notification/inPlaceNotificationContent.tpl');
}
}
return $formattedNotificationsData;
}
/**
* Get set of notifications types user does not want to be notified of.
*
* @param int $userId The notification user
* @param int $contextId
*
* @return array
*/
protected function getUserBlockedNotifications($userId, $contextId)
{
$notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO'); /** @var NotificationSubscriptionSettingsDAO $notificationSubscriptionSettingsDao */
return $notificationSubscriptionSettingsDao->getNotificationSubscriptionSettings(NotificationSubscriptionSettingsDAO::BLOCKED_NOTIFICATION_KEY, $userId, (int) $contextId);
}
/**
* Get set of notification types user will also be notified by email.
*
* @return array
*/
protected function getUserBlockedEmailedNotifications($userId, $contextId)
{
$notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO'); /** @var NotificationSubscriptionSettingsDAO $notificationSubscriptionSettingsDao */
return $notificationSubscriptionSettingsDao->getNotificationSubscriptionSettings(NotificationSubscriptionSettingsDAO::BLOCKED_EMAIL_NOTIFICATION_KEY, $userId, (int) $contextId);
}
/**
* Get a notification content with a link action.
*
* @param LinkAction $linkAction
* @param Request $request
*
* @return string
*/
protected function fetchLinkActionNotificationContent($linkAction, $request)
{
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign('linkAction', $linkAction);
return $templateMgr->fetch('controllers/notification/linkActionNotificationContent.tpl');
}
/**
* Return a fully formatted notification for display
*
* @param PKPRequest $request
* @param object $notification Notification
*
* @return string
*/
private function formatNotification($request, $notification, $notificationTemplate)
{
$templateMgr = TemplateManager::getManager($request);
// Set the date read if it isn't already set
if (!$notification->getDateRead()) {
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
$dateRead = $notificationDao->setDateRead($notification->getId(), Core::getCurrentDate());
$notification->setDateRead($dateRead);
}
$user = $request->getUser();
$templateMgr->assign([
'isUserLoggedIn' => $user,
'notificationDateCreated' => $notification->getDateCreated(),
'notificationId' => $notification->getId(),
'notificationContents' => $this->getNotificationContents($request, $notification),
'notificationTitle' => $this->getNotificationTitle($notification),
'notificationStyleClass' => $this->getStyleClass($notification),
'notificationIconClass' => $this->getIconClass($notification),
'notificationDateRead' => $notification->getDateRead(),
]);
if ($notification->getLevel() != Notification::NOTIFICATION_LEVEL_TRIVIAL) {
$templateMgr->assign('notificationUrl', $this->getNotificationUrl($request, $notification));
}
return $templateMgr->fetch($notificationTemplate);
}
/**
* Creates and returns a unique string for the given notification, that will be encoded and validated against.
*
* @param Notification $notification
*
* @return string
*/
public function createUnsubscribeUniqueKey($notification)
{
$uniqueKey = 'unsubscribe' . '-' . $notification->getContextId() . '-' . $notification->getUserId() . '-' . $notification->getId();
return $uniqueKey;
}
/**
* Creates and returns an encoded token that will be used to validate an unsubscribe url.
*
* @param Notification $notification
*
* @return string
*/
public function createUnsubscribeToken($notification)
{
$encodeString = $this->createUnsubscribeUniqueKey($notification);
$secret = Config::getVar('security', 'api_key_secret', '');
$jwt = '';
if ($secret !== '') {
$jwt = JWT::encode(json_encode($encodeString), $secret, 'HS256');
}
return $jwt;
}
/**
* The given notification is validated against the requested token.
*
* @param string $token
* @param Notification $notification
*
* @return bool
*/
public function validateUnsubscribeToken($token, $notification)
{
$encodeString = $this->createUnsubscribeUniqueKey($notification);
$secret = Config::getVar('security', 'api_key_secret', '');
$jwt = '';
if ($secret !== '') {
$jwt = json_decode(JWT::decode($token, $secret, ['HS256']));
}
if ($jwt == $encodeString) {
return true;
}
return false;
}
/**
* Returns the unsubscribe url for the given notification.
*
* @param PKPRequest $request
* @param Notification $notification
* @param null|mixed $context
*
* @return string
*/
public function getUnsubscribeNotificationUrl($request, $notification, $context = null)
{
$application = Application::get();
$dispatcher = $application->getDispatcher();
$contextPath = null;
if ($context) {
if ($context->getId() !== $notification->getContextId()) {
throw new InvalidArgumentException('Trying to build notification unsubscribe URL with the wrong context');
}
$contextPath = $context->getData('urlPath');
}
return $dispatcher->url(
$request,
PKPApplication::ROUTE_PAGE,
$contextPath,
'notification',
'unsubscribe',
null,
['validate' => $this->createUnsubscribeToken($notification), 'id' => $notification->getId()]
);
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\PKPNotificationOperationManager', '\PKPNotificationOperationManager');
}
@@ -0,0 +1,174 @@
<?php
/**
* @defgroup notification_form Notification Form
*/
/**
* @file classes/notification/form/NotificationSettingsForm.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 PKPNotificationSettingsForm
*
* @ingroup notification_form
*
* @brief Form to edit notification settings.
*/
namespace PKP\notification\form;
use APP\core\Application;
use APP\notification\NotificationManager;
use APP\template\TemplateManager;
use PKP\context\Context;
use PKP\db\DAORegistry;
use PKP\form\Form;
use PKP\notification\NotificationSubscriptionSettingsDAO;
use PKP\notification\PKPNotification;
use PKP\plugins\Hook;
class PKPNotificationSettingsForm extends Form
{
/**
* Constructor.
*/
public function __construct()
{
parent::__construct('user/notificationSettingsForm.tpl');
// Validation checks for this form
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
$userVars = [];
foreach ($this->getNotificationSettingsMap() as $notificationSetting) {
$userVars[] = $notificationSetting['settingName'];
$userVars[] = $notificationSetting['emailSettingName'];
}
$this->readUserVars($userVars);
}
/**
* Get all notification settings form names and their setting type values
*
* @return array
*/
protected function getNotificationSettingsMap()
{
$notificationManager = new NotificationManager();
return $notificationManager->getNotificationSettingsMap();
}
/**
* Get a list of notification category names (to display as headers)
* and the notification types under each category
*
* @return array
*/
public function getNotificationSettingCategories(?Context $context = null)
{
$result = [
// Changing the `categoryKey` for public notification types will disrupt
// the email notification opt-in/out feature during user registration
// @see RegistrationForm::execute()
['categoryKey' => 'notification.type.public',
'settings' => [
PKPNotification::NOTIFICATION_TYPE_NEW_ANNOUNCEMENT,
]
],
['categoryKey' => 'notification.type.submissions',
'settings' => [
PKPNotification::NOTIFICATION_TYPE_SUBMISSION_SUBMITTED,
PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_REQUIRED,
PKPNotification::NOTIFICATION_TYPE_NEW_QUERY,
PKPNotification::NOTIFICATION_TYPE_QUERY_ACTIVITY,
]
],
['categoryKey' => 'notification.type.reviewing',
'settings' => [
PKPNotification::NOTIFICATION_TYPE_REVIEWER_COMMENT,
]
],
['categoryKey' => 'user.role.editors',
'settings' => array_filter([
PKPNotification::NOTIFICATION_TYPE_EDITORIAL_REMINDER,
$context && $context->getData('editorialStatsEmail')
? PKPNotification::NOTIFICATION_TYPE_EDITORIAL_REPORT
: '',
])
],
];
$classNameParts = explode('\\', get_class($this)); // Separate namespace info from class name
Hook::call(strtolower_codesafe(end($classNameParts) . '::getNotificationSettingCategories'), [$this, &$result, $context]);
return $result;
}
/**
* @copydoc Form::fetch
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$context = $request->getContext();
$contextId = $context ? $context->getId() : null;
$userId = $request->getUser()->getId();
$notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO'); /** @var NotificationSubscriptionSettingsDAO $notificationSubscriptionSettingsDao */
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign([
'blockedNotifications' => $notificationSubscriptionSettingsDao->getNotificationSubscriptionSettings('blocked_notification', $userId, $contextId),
'emailSettings' => $notificationSubscriptionSettingsDao->getNotificationSubscriptionSettings('blocked_emailed_notification', $userId, $contextId),
'notificationSettingCategories' => $this->getNotificationSettingCategories($context),
'notificationSettings' => $this->getNotificationSettingsMap(),
]);
return parent::fetch($request, $template, $display);
}
/**
* @copydoc Form::execute
*/
public function execute(...$functionParams)
{
parent::execute(...$functionParams);
$request = Application::get()->getRequest();
$user = $request->getUser();
$userId = $user->getId();
$context = $request->getContext();
$contextId = $context ? $context->getId() : null;
$blockedNotifications = [];
$emailSettings = [];
foreach ($this->getNotificationSettingsMap() as $settingId => $notificationSetting) {
// Get notifications that the user wants blocked
if (!$this->getData($notificationSetting['settingName'])) {
$blockedNotifications[] = $settingId;
}
// Get notifications that the user wants to be notified of by email
if ($this->getData($notificationSetting['emailSettingName'])) {
$emailSettings[] = $settingId;
}
}
$notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO'); /** @var NotificationSubscriptionSettingsDAO $notificationSubscriptionSettingsDao */
$notificationSubscriptionSettingsDao->updateNotificationSubscriptionSettings($notificationSubscriptionSettingsDao::BLOCKED_NOTIFICATION_KEY, $blockedNotifications, $userId, $contextId);
$notificationSubscriptionSettingsDao->updateNotificationSubscriptionSettings($notificationSubscriptionSettingsDao::BLOCKED_EMAIL_NOTIFICATION_KEY, $emailSettings, $userId, $contextId);
return true;
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\form\PKPNotificationSettingsForm', '\PKPNotificationSettingsForm');
}
@@ -0,0 +1,136 @@
<?php
/**
* @defgroup notification_form Notification Form
*/
/**
* @file classes/notification/form/PKPNotificationsUnsubscribeForm.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 PKPNotificationsUnsubscribeForm
*
* @ingroup notification_form
*
* @brief Form to unsubscribe from email notifications.
*/
namespace PKP\notification\form;
use APP\facades\Repo;
use APP\notification\Notification;
use APP\notification\NotificationManager;
use APP\template\TemplateManager;
use PKP\db\DAORegistry;
use PKP\form\Form;
use PKP\notification\NotificationSubscriptionSettingsDAO;
class PKPNotificationsUnsubscribeForm extends Form
{
/** @var Notification The notification that triggered the unsubscribe event */
public $_notification;
/** @var string The unsubscribe validation token */
public $_validationToken;
/**
* Constructor.
*
* @param Notification $notification The notification that triggered the unsubscribe event
* @param string $validationToken $name The unsubscribe validation token
*/
public function __construct($notification, $validationToken)
{
parent::__construct('notification/unsubscribeNotificationsForm.tpl');
// Validation checks for this form
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
$this->_notification = $notification;
$this->_validationToken = $validationToken;
}
/**
* Assign form data to user-submitted data.
*/
public function readInputData()
{
$userVars = [];
foreach ($this->getNotificationSettingsMap() as $notificationSetting) {
$userVars[] = $notificationSetting['emailSettingName'];
}
$this->readUserVars($userVars);
}
/**
* Get all notification settings form names and their setting type values
*
* @return array
*/
protected function getNotificationSettingsMap()
{
$notificationManager = new NotificationManager();
return $notificationManager->getNotificationSettingsMap();
}
/**
* @copydoc Form::fetch
*
* @param null|mixed $template
*/
public function fetch($request, $template = null, $display = false)
{
$userId = $this->_notification->getUserId();
$contextId = $this->_notification->getContextId();
if ($contextId != $request->getContext()->getId()) {
$dispatcher = $request->getDispatcher();
$dispatcher->handle404();
}
$emailSettings = $this->getNotificationSettingsMap();
$user = Repo::user()->get($userId);
$context = $request->getContext();
$templateMgr = TemplateManager::getManager($request);
$templateMgr->assign([
'contextName' => $context->getLocalizedName(),
'userEmail' => $user->getEmail(),
'emailSettings' => $emailSettings,
'validationToken' => $this->_validationToken,
'notificationId' => $this->_notification->getId(),
]);
return parent::fetch($request, $template, $display);
}
/**
* @copydoc Form::execute
*/
public function execute(...$functionArgs)
{
$emailSettings = [];
foreach ($this->getNotificationSettingsMap() as $settingId => $notificationSetting) {
// Get notifications that the user wants to be notified of by email
if ($this->getData($notificationSetting['emailSettingName'])) {
$emailSettings[] = $settingId;
}
}
/** @var NotificationSubscriptionSettingsDAO */
$notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO');
$notificationSubscriptionSettingsDao->updateNotificationSubscriptionSettings('blocked_emailed_notification', $emailSettings, $this->_notification->getUserId(), $this->_notification->getContextId());
return true;
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\form\PKPNotificationsUnsubscribeForm', '\PKPNotificationsUnsubscribeForm');
}
@@ -0,0 +1,114 @@
<?php
/**
* @file classes/notification/managerDelegate/AnnouncementNotificationManager.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class AnnouncementNotificationManager
*
* @ingroup managerDelegate
*
* @brief New announcement notification manager.
*/
namespace PKP\notification\managerDelegate;
use APP\core\Application;
use APP\notification\Notification;
use PKP\announcement\Announcement;
use PKP\core\PKPApplication;
use PKP\emailTemplate\EmailTemplate;
use PKP\facades\Repo;
use PKP\notification\NotificationManagerDelegate;
use PKP\notification\PKPNotification;
use PKP\user\User;
class AnnouncementNotificationManager extends NotificationManagerDelegate
{
/** @var Announcement The announcement to send a notification about */
public $_announcement;
/**
* Initializes the class.
*
* @param Announcement $announcement The announcement to send
*/
public function initialize(Announcement $announcement): void
{
$this->_announcement = $announcement;
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationMessage()
*/
public function getNotificationMessage($request, $notification): string
{
return __('emails.announcement.subject');
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationMessage()
*/
public function getNotificationContents($request, $notification): EmailTemplate
{
return Repo::emailTemplate()->getByKey($notification->getContextId(), 'ANNOUNCEMENT');
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationUrl()
*/
public function getNotificationUrl($request, $notification)
{
return $request->getDispatcher()->url(
$request,
PKPApplication::ROUTE_PAGE,
$request->getContext()->getData('urlPath'),
'announcement',
'view',
$this->_announcement->getId()
);
}
/**
* @copydoc PKPNotificationManager::getIconClass()
*/
public function getIconClass($notification): string
{
return 'notifyIconInfo';
}
/**
* @copydoc PKPNotificationManager::getStyleClass()
*/
public function getStyleClass($notification): string
{
return NOTIFICATION_STYLE_CLASS_INFORMATION;
}
/**
* Sends a notification to the given user.
*
* @param User $user The user who will be notified
*
* @return PKPNotification|null The notification instance or null if no notification created
*/
public function notify(User $user): ?PKPNotification
{
return parent::createNotification(
Application::get()->getRequest(),
$user->getId(),
PKPNotification::NOTIFICATION_TYPE_NEW_ANNOUNCEMENT,
$this->_announcement->getAssocId(),
null,
null,
Notification::NOTIFICATION_LEVEL_NORMAL,
['contents' => $this->_announcement->getLocalizedTitle()]
);
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\managerDelegate\AnnouncementNotificationManager', '\AnnouncementNotificationManager');
}
@@ -0,0 +1,138 @@
<?php
/**
* @file classes/notification/managerDelegate/EditorAssignmentNotificationManager.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class EditorAssignmentNotificationManager
*
* @ingroup managerDelegate
*
* @brief Editor assignment notification types manager delegate.
*/
namespace PKP\notification\managerDelegate;
use APP\core\Application;
use APP\notification\Notification;
use PKP\db\DAORegistry;
use PKP\notification\NotificationManagerDelegate;
use PKP\notification\PKPNotification;
class EditorAssignmentNotificationManager extends NotificationManagerDelegate
{
/**
* @copydoc PKPNotificationOperationManager::getNotificationMessage($notification)
*/
public function getNotificationMessage($request, $notification)
{
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_SUBMISSION:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_INTERNAL_REVIEW:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EXTERNAL_REVIEW:
return __('notification.type.editorAssignment');
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EDITING:
return __('notification.type.editorAssignmentEditing');
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_PRODUCTION:
return __('notification.type.editorAssignmentProduction');
}
}
/**
* @copydoc PKPNotificationOperationManager::getStyleClass()
*/
public function getStyleClass($notification)
{
return NOTIFICATION_STYLE_CLASS_WARNING;
}
/**
* @copydoc PKPNotificationOperationManager::isVisibleToAllUsers()
*/
public function isVisibleToAllUsers($notificationType, $assocType, $assocId)
{
return true;
}
/**
* @copydoc NotificationManagerDelegate::updateNotification()
*
* If we have a stage without a manager role user, then
* a notification must be inserted or maintained for the submission.
* If a user with this role is assigned to the stage, the notification
* should be deleted.
* Every user that have access to the stage should see the notification.
*/
public function updateNotification($request, $userIds, $assocType, $assocId)
{
$context = $request->getContext();
$notificationType = $this->getNotificationType();
$submissionId = $assocId;
// Check for an existing NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_...
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
$notificationFactory = $notificationDao->getByAssoc(
Application::ASSOC_TYPE_SUBMISSION,
$submissionId,
null,
$notificationType,
$context->getId()
);
// Check for editor stage assignment.
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */
$editorAssigned = $stageAssignmentDao->editorAssignedToStage($submissionId, $this->_getStageIdByNotificationType());
// Decide if we have to create or delete a notification.
$notification = $notificationFactory->next();
if ($editorAssigned && $notification) {
// Delete the notification.
$notificationDao->deleteObject($notification);
} elseif (!$editorAssigned && !$notification) {
// Create a notification.
$this->createNotification(
$request,
null,
$notificationType,
$context->getId(),
Application::ASSOC_TYPE_SUBMISSION,
$submissionId,
Notification::NOTIFICATION_LEVEL_TASK
);
}
}
//
// Helper methods.
//
/**
* Return the correct stage id based on the notification type.
*
* @return int
*/
public function _getStageIdByNotificationType()
{
switch ($this->getNotificationType()) {
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_SUBMISSION:
return WORKFLOW_STAGE_ID_SUBMISSION;
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_INTERNAL_REVIEW:
return WORKFLOW_STAGE_ID_INTERNAL_REVIEW;
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EXTERNAL_REVIEW:
return WORKFLOW_STAGE_ID_EXTERNAL_REVIEW;
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_EDITING:
return WORKFLOW_STAGE_ID_EDITING;
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_PRODUCTION:
return WORKFLOW_STAGE_ID_PRODUCTION;
default:
return null;
}
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\managerDelegate\EditorAssignmentNotificationManager', '\EditorAssignmentNotificationManager');
}
@@ -0,0 +1,186 @@
<?php
/**
* @file classes/notification/managerDelegate/EditorDecisionNotificationManager.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class EditorDecisionNotificationManager
*
* @ingroup managerDelegate
*
* @brief Editor decision notification types manager delegate.
*/
namespace PKP\notification\managerDelegate;
use APP\core\Application;
use APP\facades\Repo;
use APP\notification\Notification;
use PKP\db\DAORegistry;
use PKP\notification\NotificationManagerDelegate;
use PKP\notification\PKPNotification;
class EditorDecisionNotificationManager extends NotificationManagerDelegate
{
/**
* @copydoc PKPNotificationOperationManager::getNotificationMessage()
*/
public function getNotificationMessage($request, $notification)
{
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_INTERNAL_REVIEW:
return __('notification.type.editorDecisionInternalReview');
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_ACCEPT:
return __('notification.type.editorDecisionAccept');
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_EXTERNAL_REVIEW:
return __('notification.type.editorDecisionExternalReview');
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_PENDING_REVISIONS:
return __('notification.type.editorDecisionPendingRevisions');
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_RESUBMIT:
return __('notification.type.editorDecisionResubmit');
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_NEW_ROUND:
return __('notification.type.editorDecisionNewRound');
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_DECLINE:
return __('notification.type.editorDecisionDecline');
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_REVERT_DECLINE:
return __('notification.type.editorDecisionRevertDecline');
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_SEND_TO_PRODUCTION:
return __('notification.type.editorDecisionSendToProduction');
default:
return null;
}
}
/**
* @copydoc PKPNotificationOperationManager::getStyleClass()
*/
public function getStyleClass($notification)
{
return NOTIFICATION_STYLE_CLASS_INFORMATION;
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationTitle()
*/
public function getNotificationTitle($notification)
{
return __('notification.type.editorDecisionTitle');
}
/**
* @copydoc NotificationManagerDelegate::updateNotification()
*/
public function updateNotification($request, $userIds, $assocType, $assocId)
{
$context = $request->getContext();
// Remove any existing editor decision notifications.
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var \PKP\notification\NotificationDAO $notificationDao */
$notificationFactory = $notificationDao->getByAssoc(
Application::ASSOC_TYPE_SUBMISSION,
$assocId,
null,
null,
$context->getId()
);
// Delete old notifications.
$editorDecisionNotificationTypes = $this->_getAllEditorDecisionNotificationTypes();
while ($notification = $notificationFactory->next()) {
// If a list of user IDs was specified, make sure we're respecting it.
if ($userIds !== null && !in_array($notification->getUserId(), $userIds)) {
continue;
}
// Check that the notification type is in the specified list.
if (!in_array($notification->getType(), $editorDecisionNotificationTypes)) {
continue;
}
$notificationDao->deleteObject($notification);
}
// (Re)create notifications, but dont send email, since we
// got here from the editor decision which sends its own email.
foreach ((array) $userIds as $userId) {
$this->createNotification(
$request,
$userId,
$this->getNotificationType(),
$context->getId(),
Application::ASSOC_TYPE_SUBMISSION,
$assocId,
$this->_getNotificationTaskLevel($this->getNotificationType())
);
}
}
/**
* @copydoc INotificationInfoProvider::getNotificationUrl()
*/
public function getNotificationUrl($request, $notification)
{
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_INTERNAL_REVIEW:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_ACCEPT:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_EXTERNAL_REVIEW:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_PENDING_REVISIONS:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_RESUBMIT:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_NEW_ROUND:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_DECLINE:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_SEND_TO_PRODUCTION:
$submission = Repo::submission()->get($notification->getAssocId());
return Repo::submission()->getWorkflowUrlByUserRoles($submission, $notification->getUserId());
default:
return '';
}
}
//
// Private helper methods
//
/**
* Get all notification types corresponding to editor decisions.
*
* @return array
*/
public function _getAllEditorDecisionNotificationTypes()
{
return [
PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_INTERNAL_REVIEW,
PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_ACCEPT,
PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_EXTERNAL_REVIEW,
PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_PENDING_REVISIONS,
PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_RESUBMIT,
PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_NEW_ROUND,
PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_DECLINE,
PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_REVERT_DECLINE,
PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_SEND_TO_PRODUCTION
];
}
/**
* Get the notification level for the type of notification being created.
*
* @param int $type
*
* @return int
*/
public function _getNotificationTaskLevel($type)
{
switch ($type) {
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_PENDING_REVISIONS:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_RESUBMIT:
return Notification::NOTIFICATION_LEVEL_TASK;
default:
return Notification::NOTIFICATION_LEVEL_NORMAL;
}
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\managerDelegate\EditorDecisionNotificationManager', '\EditorDecisionNotificationManager');
}
@@ -0,0 +1,109 @@
<?php
/**
* @file classes/notification/managerDelegate/EditorialReportNotificationManager.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class EditorialReportNotificationManager
*
* @ingroup managerDelegate
*
* @brief Editorial report notification manager.
*/
namespace PKP\notification\managerDelegate;
use APP\core\Application;
use APP\core\Request;
use APP\notification\Notification;
use PKP\context\Context;
use PKP\core\PKPApplication;
use PKP\notification\NotificationManagerDelegate;
use PKP\notification\PKPNotification;
use PKP\user\User;
class EditorialReportNotificationManager extends NotificationManagerDelegate
{
private Context $_context;
private Request $_request;
/**
* @copydoc NotificationManagerDelegate::__construct()
*/
public function __construct(int $notificationType)
{
parent::__construct($notificationType);
$this->_request = Application::get()->getRequest();
}
/**
* Initializes the class.
*
* @param Context $context The context from where the statistics shall be retrieved
*/
public function initialize(Context $context): void
{
$this->_context = $context;
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationMessage()
*/
public function getNotificationMessage($request, $notification): string
{
return __('notification.type.editorialReport', [], $this->_context->getPrimaryLocale());
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationUrl()
*/
public function getNotificationUrl($request, $notification)
{
$application = Application::get();
$context = $application->getContextDAO()->getById($notification->getContextId());
return $application->getDispatcher()->url($this->_request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'stats', 'editorial');
}
/**
* @copydoc PKPNotificationManager::getIconClass()
*/
public function getIconClass($notification): string
{
return 'notifyIconInfo';
}
/**
* @copydoc PKPNotificationManager::getStyleClass()
*/
public function getStyleClass($notification): string
{
return NOTIFICATION_STYLE_CLASS_INFORMATION;
}
/**
* Sends a notification to the given user.
*
* @param User $user The user who will be notified
*
* @return PKPNotification|null The notification instance
*/
public function notify(User $user): ?PKPNotification
{
return parent::createNotification(
$this->_request,
$user->getId(),
PKPNotification::NOTIFICATION_TYPE_EDITORIAL_REPORT,
$this->_context->getId(),
null,
null,
Notification::NOTIFICATION_LEVEL_TASK,
['contents' => __('notification.type.editorialReport.contents', [], $this->_context->getPrimaryLocale())]
);
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\managerDelegate\EditorialReportNotificationManager', '\EditorialReportNotificationManager');
}
@@ -0,0 +1,111 @@
<?php
/**
* @file classes/notification/managerDelegate/PKPApproveSubmissionNotificationManager.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class PKPApproveSubmissionNotificationManager
*
* @ingroup managerDelegate
*
* @brief Approve submission notification type manager delegate.
*/
namespace PKP\notification\managerDelegate;
use APP\core\Application;
use APP\facades\Repo;
use PKP\core\PKPApplication;
use PKP\db\DAORegistry;
use PKP\notification\NotificationDAO;
use PKP\notification\NotificationManagerDelegate;
use PKP\notification\PKPNotification;
class PKPApproveSubmissionNotificationManager extends NotificationManagerDelegate
{
/**
* @copydoc PKPNotificationOperationManager::getNotificationUrl()
*/
public function getNotificationUrl($request, $notification)
{
$dispatcher = Application::get()->getDispatcher();
$context = $request->getContext();
return $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'workflow', 'access', $notification->getAssocId());
}
/**
* @copydoc PKPNotificationOperationManager::getStyleClass()
*/
public function getStyleClass($notification)
{
return NOTIFICATION_STYLE_CLASS_INFORMATION;
}
/**
* @copydoc PKPNotificationOperationManager::isVisibleToAllUsers()
*/
public function isVisibleToAllUsers($notificationType, $assocType, $assocId)
{
return true;
}
/**
* @copydoc NotificationManagerDelegate::updateNotification()
*/
public function updateNotification($request, $userIds, $assocType, $assocId)
{
$submissionId = $assocId;
$submission = Repo::submission()->get($submissionId);
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
$notificationTypes = [
PKPNotification::NOTIFICATION_TYPE_APPROVE_SUBMISSION => false,
PKPNotification::NOTIFICATION_TYPE_FORMAT_NEEDS_APPROVED_SUBMISSION => false,
PKPNotification::NOTIFICATION_TYPE_VISIT_CATALOG => true,
];
$isPublished = (bool) $submission->getDatePublished();
foreach ($notificationTypes as $type => $forPublicationState) {
$notificationFactory = $notificationDao->getByAssoc(
Application::ASSOC_TYPE_SUBMISSION,
$submissionId,
null,
$type,
$submission->getData('contextId')
);
$notification = $notificationFactory->next();
if (!$notification && $isPublished == $forPublicationState) {
// Create notification.
$this->createNotification(
$request,
null,
$type,
$submission->getData('contextId'),
Application::ASSOC_TYPE_SUBMISSION,
$submissionId
);
} elseif ($notification && $isPublished != $forPublicationState) {
// Delete existing notification.
$notificationDao->deleteObject($notification);
}
}
}
/**
* @copydoc NotificationManagerDelegate.php
*/
protected function multipleTypesUpdate()
{
return true;
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\managerDelegate\PKPApproveSubmissionNotificationManager', '\PKPApproveSubmissionNotificationManager');
}
@@ -0,0 +1,262 @@
<?php
/**
* @file classes/notification/managerDelegate/PKPEditingProductionStatusNotificationManager.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class PKPEditingProductionStatusNotificationManager
*
* @ingroup classses_notification_managerDelegate
*
* @brief Editing and productionstatus notifications types manager delegate.
*/
namespace PKP\notification\managerDelegate;
use APP\core\Application;
use APP\facades\Repo;
use APP\notification\NotificationManager;
use PKP\core\PKPApplication;
use PKP\core\PKPRequest;
use PKP\db\DAORegistry;
use PKP\notification\NotificationDAO;
use PKP\notification\NotificationManagerDelegate;
use PKP\notification\PKPNotification;
use PKP\stageAssignment\StageAssignmentDAO;
use PKP\submissionFile\SubmissionFile;
class PKPEditingProductionStatusNotificationManager extends NotificationManagerDelegate
{
/**
* @copydoc PKPNotificationOperationManager::getNotificationMessage()
*/
public function getNotificationMessage($request, $notification)
{
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_ASSIGN_COPYEDITOR:
return __('notification.type.assignCopyeditors');
case PKPNotification::NOTIFICATION_TYPE_AWAITING_COPYEDITS:
return __('notification.type.awaitingCopyedits');
case PKPNotification::NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER:
return __('notification.type.assignProductionUser');
case PKPNotification::NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS:
return __('notification.type.awaitingRepresentations');
default:
assert(false);
}
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationUrl()
*/
public function getNotificationUrl($request, $notification)
{
$dispatcher = Application::get()->getDispatcher();
$contextDao = Application::getContextDAO();
$context = $contextDao->getById($notification->getContextId());
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_ASSIGN_COPYEDITOR:
case PKPNotification::NOTIFICATION_TYPE_AWAITING_COPYEDITS:
case PKPNotification::NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER:
case PKPNotification::NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS:
assert($notification->getAssocType() == Application::ASSOC_TYPE_SUBMISSION && is_numeric($notification->getAssocId()));
return $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'workflow', 'access', $notification->getAssocId());
default:
assert(false);
}
}
/**
* @copydoc PKPNotificationOperationManager::getStyleClass()
*/
public function getStyleClass($notification)
{
return NOTIFICATION_STYLE_CLASS_INFORMATION;
}
/**
* @copydoc NotificationManagerDelegate::updateNotification()
*/
public function updateNotification($request, $userIds, $assocType, $assocId)
{
assert($assocType == Application::ASSOC_TYPE_SUBMISSION);
$submissionId = $assocId;
$submission = Repo::submission()->get($submissionId);
$contextId = $submission->getContextId();
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */
$editorStageAssignments = $stageAssignmentDao->getEditorsAssignedToStage($submissionId, $submission->getStageId());
// Get the copyediting and production discussions
$queryDao = DAORegistry::getDAO('QueryDAO'); /** @var \PKP\query\QueryDAO $queryDao */
$productionQueries = $queryDao->getByAssoc(Application::ASSOC_TYPE_SUBMISSION, $submissionId, WORKFLOW_STAGE_ID_PRODUCTION);
$productionQuery = $productionQueries->next();
// Get the copyedited files
$countCopyeditedFiles = Repo::submissionFile()
->getCollector()
->filterBySubmissionIds([$submissionId])
->filterByFileStages([SubmissionFile::SUBMISSION_FILE_COPYEDIT])
->getCount();
// Get representations
if ($latestPublication = $submission->getLatestPublication()) {
$representationDao = Application::getRepresentationDAO(); /** @var \PKP\submission\RepresentationDAOInterface $representationDao */
$representations = $representationDao->getByPublicationId($latestPublication->getId());
} else {
$representations = [];
}
$notificationType = $this->getNotificationType();
foreach ($editorStageAssignments as $editorStageAssignment) {
switch ($submission->getStageId()) {
case WORKFLOW_STAGE_ID_PRODUCTION:
if ($notificationType == PKPNotification::NOTIFICATION_TYPE_ASSIGN_COPYEDITOR || $notificationType == PKPNotification::NOTIFICATION_TYPE_AWAITING_COPYEDITS) {
// Remove 'assign a copyeditor' and 'awaiting copyedits' notification
$this->_removeNotification($submissionId, $editorStageAssignment->getUserId(), $notificationType, $contextId);
} else {
// If there is a representation
if (count($representations)) {
// Remove 'assign a production user' and 'awaiting representations' notification
$this->_removeNotification($submissionId, $editorStageAssignment->getUserId(), $notificationType, $contextId);
} else {
// Remove 'assign a production user' and 'awaiting representations' notification
// If a production user is assigned i.e. there is a production discussion
if ($productionQuery) {
if ($notificationType == PKPNotification::NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS) {
// Add 'awaiting representations' notification
$this->_createNotification(
$request,
$submissionId,
$editorStageAssignment->getUserId(),
$notificationType,
$contextId
);
} elseif ($notificationType == PKPNotification::NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER) {
// Remove 'assign a production user' notification
$this->_removeNotification($submissionId, $editorStageAssignment->getUserId(), $notificationType, $contextId);
}
} else {
if ($notificationType == PKPNotification::NOTIFICATION_TYPE_ASSIGN_PRODUCTIONUSER) {
// Add 'assign a user' notification
$this->_createNotification(
$request,
$submissionId,
$editorStageAssignment->getUserId(),
$notificationType,
$contextId
);
} elseif ($notificationType == PKPNotification::NOTIFICATION_TYPE_AWAITING_REPRESENTATIONS) {
// Remove 'awaiting representations' notification
$this->_removeNotification($submissionId, $editorStageAssignment->getUserId(), $notificationType, $contextId);
}
}
}
}
break;
case WORKFLOW_STAGE_ID_EDITING:
if ($countCopyeditedFiles) {
// Remove 'assign a copyeditor' and 'awaiting copyedits' notification
$this->_removeNotification($submissionId, $editorStageAssignment->getUserId(), $notificationType, $contextId);
} else {
// If a copyeditor is assigned i.e. there is a copyediting discussion
$editingQueries = $queryDao->getByAssoc(Application::ASSOC_TYPE_SUBMISSION, $submissionId, WORKFLOW_STAGE_ID_EDITING);
if ($editingQueries->next()) {
if ($notificationType == PKPNotification::NOTIFICATION_TYPE_AWAITING_COPYEDITS) {
// Add 'awaiting copyedits' notification
$this->_createNotification(
$request,
$submissionId,
$editorStageAssignment->getUserId(),
$notificationType,
$contextId
);
} elseif ($notificationType == PKPNotification::NOTIFICATION_TYPE_ASSIGN_COPYEDITOR) {
// Remove 'assign a copyeditor' notification
$this->_removeNotification($submissionId, $editorStageAssignment->getUserId(), $notificationType, $contextId);
}
} else {
if ($notificationType == PKPNotification::NOTIFICATION_TYPE_ASSIGN_COPYEDITOR) {
// Add 'assign a copyeditor' notification
$this->_createNotification(
$request,
$submissionId,
$editorStageAssignment->getUserId(),
$notificationType,
$contextId
);
} elseif ($notificationType == PKPNotification::NOTIFICATION_TYPE_AWAITING_COPYEDITS) {
// Remove 'awaiting copyedits' notification
$this->_removeNotification($submissionId, $editorStageAssignment->getUserId(), $notificationType, $contextId);
}
}
}
break;
}
}
}
//
// Helper methods.
//
/**
* Remove a notification.
*
* @param int $submissionId
* @param int $userId
* @param int $notificationType NOTIFICATION_TYPE_
* @param int $contextId
*/
public function _removeNotification($submissionId, $userId, $notificationType, $contextId)
{
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
$notificationDao->deleteByAssoc(
Application::ASSOC_TYPE_SUBMISSION,
$submissionId,
$userId,
$notificationType,
$contextId
);
}
/**
* Create a notification if none exists.
*
* @param PKPRequest $request
* @param int $submissionId
* @param int $userId
* @param int $notificationType NOTIFICATION_TYPE_
* @param int $contextId
*/
public function _createNotification($request, $submissionId, $userId, $notificationType, $contextId)
{
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
$notificationFactory = $notificationDao->getByAssoc(
Application::ASSOC_TYPE_SUBMISSION,
$submissionId,
$userId,
$notificationType,
$contextId
);
if (!$notificationFactory->next()) {
$notificationMgr = new NotificationManager();
$notificationMgr->createNotification(
$request,
$userId,
$notificationType,
$contextId,
Application::ASSOC_TYPE_SUBMISSION,
$submissionId
);
}
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\managerDelegate\PKPEditingProductionStatusNotificationManager', '\PKPEditingProductionStatusNotificationManager');
}
@@ -0,0 +1,178 @@
<?php
/**
* @file classes/notification/managerDelegate/PendingRevisionsNotificationManager.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class PendingRevisionsNotificationManager
*
* @ingroup managerDelegate
*
* @brief Pending revision notification types manager delegate.
*/
namespace PKP\notification\managerDelegate;
use APP\core\Application;
use APP\decision\Decision;
use APP\facades\Repo;
use APP\notification\Notification;
use PKP\controllers\api\file\linkAction\AddRevisionLinkAction;
use PKP\db\DAORegistry;
use PKP\notification\NotificationDAO;
use PKP\notification\NotificationManagerDelegate;
use PKP\notification\PKPNotification;
use PKP\security\Role;
use PKP\submission\reviewRound\ReviewRoundDAO;
use PKP\workflow\WorkflowStageDAO;
class PendingRevisionsNotificationManager extends NotificationManagerDelegate
{
/**
* @copydoc PKPNotificationOperationManager::getStyleClass()
*/
public function getStyleClass($notification)
{
return NOTIFICATION_STYLE_CLASS_WARNING;
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationUrl()
*/
public function getNotificationUrl($request, $notification)
{
$submission = Repo::submission()->get($notification->getAssocId());
return Repo::submission()->getWorkflowUrlByUserRoles($submission, $notification->getUserId());
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationMessage()
*/
public function getNotificationMessage($request, $notification)
{
$stageData = $this->_getStageDataByType();
$stageKey = $stageData['translationKey'];
return __('notification.type.pendingRevisions', ['stage' => __($stageKey)]);
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationContents()
*/
public function getNotificationContents($request, $notification)
{
$stageData = $this->_getStageDataByType();
$stageId = $stageData['id'];
$submissionId = $notification->getAssocId();
$submission = Repo::submission()->get($submissionId);
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /** @var ReviewRoundDAO $reviewRoundDao */
$lastReviewRound = $reviewRoundDao->getLastReviewRoundBySubmissionId($submission->getId(), $stageId);
$uploadFileAction = new AddRevisionLinkAction(
$request,
$lastReviewRound,
[Role::ROLE_ID_AUTHOR]
);
return $this->fetchLinkActionNotificationContent($uploadFileAction, $request);
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationTitle()
*/
public function getNotificationTitle($notification)
{
$stageData = $this->_getStageDataByType();
$stageKey = $stageData['translationKey'];
return __('notification.type.pendingRevisions.title', ['stage' => __($stageKey)]);
}
/**
* @copydoc NotificationManagerDelegate::updateNotification()
*/
public function updateNotification($request, $userIds, $assocType, $assocId)
{
$userId = current($userIds);
$submissionId = $assocId;
$stageData = $this->_getStageDataByType();
if ($stageData == null) {
return;
}
$expectedStageId = $stageData['id'];
$pendingRevisionDecision = Repo::decision()->getActivePendingRevisionsDecision($submissionId, $expectedStageId, Decision::PENDING_REVISIONS);
$removeNotifications = false;
if ($pendingRevisionDecision) {
if (Repo::decision()->revisionsUploadedSinceDecision($pendingRevisionDecision, $submissionId)) {
// Some user already uploaded a revision. Flag to delete any existing notification.
$removeNotifications = true;
} else {
$context = $request->getContext();
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
$notificationFactory = $notificationDao->getByAssoc(
Application::ASSOC_TYPE_SUBMISSION,
$submissionId,
$userId,
PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_PENDING_REVISIONS,
$context->getId()
);
if (!$notificationFactory->next()) {
// Create or update a pending revision task notification.
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
$notificationDao->build(
$context->getId(),
Notification::NOTIFICATION_LEVEL_TASK,
$this->getNotificationType(),
Application::ASSOC_TYPE_SUBMISSION,
$submissionId,
$userId
);
}
}
} else {
// No pending revision decision or other later decision overriden it.
// Flag to delete any existing notification.
$removeNotifications = true;
}
if ($removeNotifications) {
$context = $request->getContext();
$notificationDao = DAORegistry::getDAO('NotificationDAO'); /** @var NotificationDAO $notificationDao */
$notificationDao->deleteByAssoc(Application::ASSOC_TYPE_SUBMISSION, $submissionId, $userId, $this->getNotificationType(), $context->getId());
$notificationDao->deleteByAssoc(Application::ASSOC_TYPE_SUBMISSION, $submissionId, $userId, PKPNotification::NOTIFICATION_TYPE_EDITOR_DECISION_PENDING_REVISIONS, $context->getId());
}
}
//
// Private helper methods.
//
/**
* Get the data for an workflow stage by
* pending revisions notification type.
*
* @return string
*/
private function _getStageDataByType()
{
$stagesData = WorkflowStageDAO::getWorkflowStageKeysAndPaths();
switch ($this->getNotificationType()) {
case PKPNotification::NOTIFICATION_TYPE_PENDING_INTERNAL_REVISIONS:
return $stagesData[WORKFLOW_STAGE_ID_INTERNAL_REVIEW] ?? null;
case PKPNotification::NOTIFICATION_TYPE_PENDING_EXTERNAL_REVISIONS:
return $stagesData[WORKFLOW_STAGE_ID_EXTERNAL_REVIEW] ?? null;
default:
assert(false);
}
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\managerDelegate\PendingRevisionsNotificationManager', '\PendingRevisionsNotificationManager');
}
@@ -0,0 +1,161 @@
<?php
/**
* @file classes/notification/managerDelegate/QueryNotificationManager.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class QueryNotificationManager
*
* @ingroup managerDelegate
*
* @brief Query notification types manager delegate.
*/
namespace PKP\notification\managerDelegate;
use APP\core\Application;
use APP\facades\Repo;
use APP\submission\Submission;
use PKP\core\PKPString;
use PKP\db\DAORegistry;
use PKP\note\NoteDAO;
use PKP\notification\NotificationManagerDelegate;
use PKP\notification\PKPNotification;
use PKP\query\Query;
use PKP\query\QueryDAO;
class QueryNotificationManager extends NotificationManagerDelegate
{
/**
* @copydoc NotificationManagerDelegate::getNotificationTitle()
*/
public function getNotificationTitle($notification)
{
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_NEW_QUERY:
assert(false);
break;
case PKPNotification::NOTIFICATION_TYPE_QUERY_ACTIVITY:
assert(false);
break;
default: assert(false);
}
}
/**
* @copydoc NotificationManagerDelegate::getNotificationMessage()
*/
public function getNotificationMessage($request, $notification)
{
assert($notification->getAssocType() == Application::ASSOC_TYPE_QUERY);
$queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */
$query = $queryDao->getById($notification->getAssocId());
$headNote = $query->getHeadNote();
assert(isset($headNote));
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_NEW_QUERY:
$user = $headNote->getUser();
return __('submission.query.new', [
'creatorName' => $user->getFullName(),
'noteContents' => substr(PKPString::html2text($headNote->getContents()), 0, 200),
'noteTitle' => substr($headNote->getTitle(), 0, 200),
]);
case PKPNotification::NOTIFICATION_TYPE_QUERY_ACTIVITY:
$notes = $query->getReplies(null, NoteDAO::NOTE_ORDER_ID, \PKP\db\DAO::SORT_DIRECTION_DESC);
$latestNote = $notes->first();
$user = $latestNote->getUser();
return __('submission.query.activity', [
'responderName' => $user->getFullName(),
'noteContents' => substr(PKPString::html2text($latestNote->getContents()), 0, 200),
'noteTitle' => substr($headNote->getTitle(), 0, 200),
]);
default: assert(false);
}
}
/**
* Get the submission for a query.
*
* @param Query $query
*
* @return Submission
*/
protected function getQuerySubmission($query)
{
switch ($query->getAssocType()) {
case Application::ASSOC_TYPE_SUBMISSION:
return Repo::submission()->get($query->getAssocId());
case Application::ASSOC_TYPE_REPRESENTATION:
$representationDao = Application::getRepresentationDAO();
$representation = $representationDao->getById($query->getAssocId());
$publication = Repo::publication()->get($representation->getData('publicationId'));
return Repo::submission()->get($publication->getData('submissionId'));
}
assert(false);
}
/**
* @copydoc NotificationManagerDelegate::getNotificationUrl()
*/
public function getNotificationUrl($request, $notification)
{
assert($notification->getAssocType() == Application::ASSOC_TYPE_QUERY);
$queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */
$query = $queryDao->getById($notification->getAssocId());
assert($query instanceof Query);
$submission = $this->getQuerySubmission($query);
return Repo::submission()->getWorkflowUrlByUserRoles($submission, $notification->getUserId());
}
/**
* @copydoc NotificationManagerDelegate::getNotificationContents()
*/
public function getNotificationContents($request, $notification)
{
assert($notification->getAssocType() == Application::ASSOC_TYPE_QUERY);
$queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */
$query = $queryDao->getById($notification->getAssocId());
assert($query instanceof Query);
$submission = $this->getQuerySubmission($query);
assert($submission instanceof Submission);
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_NEW_QUERY:
return __(
'submission.query.new.contents',
[
'queryTitle' => $query->getHeadNote()->getTitle(),
'submissionTitle' => $submission->getCurrentPublication()->getLocalizedTitle(null, 'html'),
]
);
case PKPNotification::NOTIFICATION_TYPE_QUERY_ACTIVITY:
return __(
'submission.query.activity.contents',
[
'queryTitle' => $query->getHeadNote()->getTitle(),
'submissionTitle' => $submission->getCurrentPublication()->getLocalizedTitle(null, 'html'),
]
);
default: assert(false);
}
}
/**
* @copydoc NotificationManagerDelegate::getStyleClass()
*/
public function getStyleClass($notification)
{
return NOTIFICATION_STYLE_CLASS_WARNING;
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\managerDelegate\QueryNotificationManager', '\QueryNotificationManager');
}
@@ -0,0 +1,107 @@
<?php
/**
* @file classes/notification/managerDelegate/SubmissionNotificationManager.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2003-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class SubmissionNotificationManager
*
* @ingroup managerDelegate
*
* @brief Submission notification types manager delegate.
*/
namespace PKP\notification\managerDelegate;
use APP\core\Application;
use APP\facades\Repo;
use APP\submission\Submission;
use PKP\core\PKPApplication;
use PKP\notification\NotificationManagerDelegate;
use PKP\notification\PKPNotification;
class SubmissionNotificationManager extends NotificationManagerDelegate
{
/**
* @copydoc PKPNotificationOperationManager::getNotificationMessage()
*/
public function getNotificationMessage($request, $notification)
{
assert($notification->getAssocType() == Application::ASSOC_TYPE_SUBMISSION && is_numeric($notification->getAssocId()));
$submission = Repo::submission()->get($notification->getAssocId()); /** @var Submission $submission */
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_SUBMISSION_SUBMITTED:
return __('notification.type.submissionSubmitted', ['title' => $submission->getCurrentPublication()->getLocalizedTitle(null, 'html')]);
case PKPNotification::NOTIFICATION_TYPE_SUBMISSION_NEW_VERSION:
return __('notification.type.submissionNewVersion');
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_REQUIRED:
return __('notification.type.editorAssignmentTask');
default:
assert(false);
}
}
/**
* @copydoc PKPNotificationOperationManager::getNotificationUrl()
*/
public function getNotificationUrl($request, $notification)
{
$router = $request->getRouter();
$dispatcher = $router->getDispatcher();
assert($notification->getAssocType() == Application::ASSOC_TYPE_SUBMISSION && is_numeric($notification->getAssocId()));
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_SUBMISSION_SUBMITTED:
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_REQUIRED:
$contextDao = Application::getContextDAO();
$context = $contextDao->getById($notification->getContextId());
return $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'workflow', 'submission', $notification->getAssocId());
case PKPNotification::NOTIFICATION_TYPE_SUBMISSION_NEW_VERSION:
$contextDao = Application::getContextDAO();
$context = $contextDao->getById($notification->getContextId());
return $dispatcher->url($request, PKPApplication::ROUTE_PAGE, $context->getPath(), 'workflow', 'production', $notification->getAssocId());
default:
assert(false);
}
}
/**
* @copydoc PKPNotificationManager::getIconClass()
*/
public function getIconClass($notification)
{
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_REQUIRED:
return 'notifyIconPageAlert';
case PKPNotification::NOTIFICATION_TYPE_SUBMISSION_SUBMITTED:
return 'notifyIconNewPage';
default:
assert(false);
}
}
/**
* @copydoc PKPNotificationManager::getStyleClass()
*/
public function getStyleClass($notification)
{
switch ($notification->getType()) {
case PKPNotification::NOTIFICATION_TYPE_EDITOR_ASSIGNMENT_REQUIRED:
return NOTIFICATION_STYLE_CLASS_INFORMATION;
case PKPNotification::NOTIFICATION_TYPE_SUBMISSION_SUBMITTED:
return '';
default:
assert(false);
}
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\notification\managerDelegate\SubmissionNotificationManager', '\SubmissionNotificationManager');
}