<?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');
}
|