Spaces:
No application file
No application file
namespace Mautic\CoreBundle\Model; | |
use DateTime; | |
use Doctrine\ORM\EntityManager; | |
use Mautic\CoreBundle\Entity\Notification; | |
use Mautic\CoreBundle\Entity\NotificationRepository; | |
use Mautic\CoreBundle\Helper\CoreParametersHelper; | |
use Mautic\CoreBundle\Helper\EmojiHelper; | |
use Mautic\CoreBundle\Helper\InputHelper; | |
use Mautic\CoreBundle\Helper\PathsHelper; | |
use Mautic\CoreBundle\Helper\UpdateHelper; | |
use Mautic\CoreBundle\Helper\UserHelper; | |
use Mautic\CoreBundle\Security\Permissions\CorePermissions; | |
use Mautic\CoreBundle\Translation\Translator; | |
use Mautic\UserBundle\Entity\User; | |
use Psr\Log\LoggerInterface; | |
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |
use Symfony\Component\HttpFoundation\RequestStack; | |
use Symfony\Component\HttpFoundation\Session\Session; | |
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | |
/** | |
* @extends FormModel<Notification> | |
*/ | |
class NotificationModel extends FormModel | |
{ | |
/** | |
* @var bool | |
*/ | |
protected $disableUpdates; | |
public function __construct( | |
protected PathsHelper $pathsHelper, | |
protected UpdateHelper $updateHelper, | |
CoreParametersHelper $coreParametersHelper, | |
EntityManager $em, | |
CorePermissions $security, | |
EventDispatcherInterface $dispatcher, | |
UrlGeneratorInterface $router, | |
Translator $translator, | |
UserHelper $userHelper, | |
LoggerInterface $mauticLogger, | |
private RequestStack $requestStack, | |
) { | |
parent::__construct($em, $security, $dispatcher, $router, $translator, $userHelper, $mauticLogger, $coreParametersHelper); | |
} | |
private function getSession(): Session | |
{ | |
$session = $this->requestStack->getSession(); | |
\assert($session instanceof Session); | |
return $session; | |
} | |
/** | |
* @param bool $disableUpdates | |
*/ | |
public function setDisableUpdates($disableUpdates): void | |
{ | |
$this->disableUpdates = $disableUpdates; | |
} | |
/** | |
* @return NotificationRepository | |
*/ | |
public function getRepository() | |
{ | |
return $this->em->getRepository(Notification::class); | |
} | |
/** | |
* Write a notification. | |
* | |
* @param string $message Message of the notification | |
* @param string|null $type Optional $type to ID the source of the notification | |
* @param bool|true $isRead Add unread indicator | |
* @param string|null $header Header for message | |
* @param string|null $iconClass Font Awesome CSS class for the icon (e.g. ri-eye-line) | |
* @param \DateTime|null $datetime Date the item was created | |
* @param User|null $user User object; defaults to current user | |
* @param string|null $deduplicateValue When supplied, notification will not be added if another notification with tha same $deduplicateValue exists within last 24 hours | |
* @param \DateTime|null $deduplicateDateTimeFrom This argument is applied only when $deduplicateValue is supplied. If default deduplication time span (last 24 hours) does not fit your needs you can change it here. | |
* E.g. $deduplicateDateTimeFrom = new DateTime('-3 hours') means that the notification is considered duplicate only if there is a notification with the same $deduplicateValue and is not older than 3 hours. | |
*/ | |
public function addNotification( | |
$message, | |
$type = null, | |
$isRead = false, | |
$header = null, | |
$iconClass = null, | |
\DateTime $datetime = null, | |
User $user = null, | |
string $deduplicateValue = null, | |
\DateTime $deduplicateDateTimeFrom = null | |
): void { | |
if (null === $user) { | |
$user = $this->userHelper->getUser(); | |
} | |
if (null === $user || !$user->getId()) { | |
// ensure notifications aren't written for non users | |
return; | |
} | |
if (null !== $deduplicateValue) { | |
$deduplicateValue = md5($deduplicateValue); | |
if ($this->isDuplicate($user->getId(), $deduplicateValue, $deduplicateDateTimeFrom)) { | |
return; | |
} | |
} | |
$notification = new Notification(); | |
$notification->setType($type); | |
$notification->setIsRead($isRead); | |
$notification->setHeader(EmojiHelper::toHtml(InputHelper::strict_html($header))); | |
$notification->setMessage(EmojiHelper::toHtml(InputHelper::strict_html($message))); | |
$notification->setIconClass($iconClass); | |
$notification->setUser($user); | |
if (null == $datetime) { | |
$datetime = new \DateTime(); | |
} | |
$notification->setDateAdded($datetime); | |
$notification->setDeduplicate($deduplicateValue); | |
$this->saveAndDetachEntity($notification); | |
} | |
/** | |
* Mark notifications read for a user. | |
*/ | |
public function markAllRead(): void | |
{ | |
$this->getRepository()->markAllReadForUser($this->userHelper->getUser()->getId()); | |
} | |
/** | |
* Clears a notification for a user. | |
* | |
* @param $id Notification to clear; will clear all if empty | |
* @param $limit Maximum number of notifications to clear if $id is empty | |
*/ | |
public function clearNotification($id, $limit = null): void | |
{ | |
$this->getRepository()->clearNotificationsForUser($this->userHelper->getUser()->getId(), $id, $limit); | |
} | |
/** | |
* Get content for notifications. | |
* | |
* @param bool $includeRead | |
* @param int $limit | |
*/ | |
public function getNotificationContent($afterId = null, $includeRead = false, $limit = null): array | |
{ | |
if ($this->userHelper->getUser()->isGuest()) { | |
return [[], false, '']; | |
} | |
$showNewIndicator = false; | |
$userId = ($this->userHelper->getUser()) ? $this->userHelper->getUser()->getId() : 0; | |
$notifications = $this->getRepository()->getNotifications($userId, $afterId, $includeRead, null, $limit); | |
// determine if the new message indicator should be shown | |
foreach ($notifications as $n) { | |
if (!$n['isRead']) { | |
$showNewIndicator = true; | |
break; | |
} | |
} | |
// Check for updates | |
$updateMessage = ''; | |
$newUpdate = false; | |
if (!$this->disableUpdates && $this->userHelper->getUser()->isAdmin()) { | |
$updateData = []; | |
$cacheFile = $this->pathsHelper->getSystemPath('cache').'/lastUpdateCheck.txt'; | |
// check to see when we last checked for an update | |
$lastChecked = $this->getSession()->get('mautic.update.checked', 0); | |
if (time() - $lastChecked > 3600) { | |
$this->getSession()->set('mautic.update.checked', time()); | |
$updateData = $this->updateHelper->fetchData(); | |
} elseif (file_exists($cacheFile)) { | |
$updateData = json_decode(file_get_contents($cacheFile), true); | |
} | |
// If the version key is set, we have an update | |
if (isset($updateData['version'])) { | |
$announcement = $this->translator->trans( | |
'mautic.core.updater.update.announcement_link', | |
['%announcement%' => $updateData['announcement']] | |
); | |
$updateMessage = $this->translator->trans( | |
$updateData['message'], | |
['%version%' => $updateData['version'], '%announcement%' => $announcement] | |
); | |
$alreadyNotified = $this->getSession()->get('mautic.update.notified'); | |
if (empty($alreadyNotified) || $alreadyNotified != $updateData['version']) { | |
$newUpdate = true; | |
$this->getSession()->set('mautic.update.notified', $updateData['version']); | |
} | |
} | |
} | |
return [$notifications, $showNewIndicator, ['isNew' => $newUpdate, 'message' => $updateMessage]]; | |
} | |
private function isDuplicate(int $userId, string $deduplicate, \DateTime $from = null): bool | |
{ | |
return $this->getRepository()->isDuplicate($userId, $deduplicate, $from ?? new \DateTime('-1 day')); | |
} | |
} | |