<?php
namespace Aqarmap\Bundle\NotificationBundle;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Twig\Environment;
class NotificationSubscriber implements EventSubscriberInterface
{
public NotificationManager $manager;
/**
* [$action description].
*
* @var string
*/
public $action;
private Environment $templating;
/**
* Create a notification subscriber instance.
*/
public function __construct(NotificationManager $manager, NotificationLogger $logger, Environment $templating)
{
$this->manager = $manager;
$this->logger = $logger;
$this->templating = $templating;
}
/**
* Register the listeners for the subscriber.
*/
public static function getSubScribedEvents()
{
$path = __DIR__.'/Types';
$events = [];
$AllFileIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path));
$PhpFileIterator = new \RegexIterator($AllFileIterator, '/^.+\.php$/i', \RecursiveRegexIterator::GET_MATCH);
foreach ($PhpFileIterator as $file => $object) {
$file = pathinfo($file);
$event = strtolower(preg_replace('~(?<=\\w)([A-Z])~', '.$1', $file['filename']));
$events[$event] = 'handle';
}
return $events;
}
/**
* Handel notification.
*
* @throws \ReflectionException
*/
public function handle(NotificationInterface $notification): void
{
$notification
->manager($this->manager)
->twig($this->templating)
->translator($this->manager->get('translator'));
// force sending a particular channel
if ($notification->isForce) {
$notificationHandler = $this->manager->getHandler($notification);
if (
!($notification->forceSend ?? false)
&& $notificationHandler
&& method_exists($notification, $notificationHandler)
) {
$notification->$notificationHandler();
return;
}
$this->send($notification, $notification->channel);
return;
}
if ($notification->getChannel()) {
$this->hasChannel($notification, $notification->getChannel())
? $this->queue($notification, $notification->getChannel())
: $this->send($notification, $notification->getChannel());
return;
}
foreach ($this->manager->getChannel($notification) as $channel) {
$this->hasChannel($notification, $channel)
? $this->queue($notification, $channel)
: $this->send($notification, $channel);
}
}
/**
* Send notification.
*
* @param string $channel
*
* @throws Exceptions\DriverNotFoundException
*/
public function send(NotificationInterface $notification, $channel): void
{
$notifiables = $notification->getNotifiables();
if (!\count($notifiables)) {
$notifiables = $notification->getUsers();
}
foreach ($notifiables as $user) {
if (!$user->isEnabled()) {
continue;
}
$user = $notification->to($user);
$this->manager->send($user, $notification, $channel);
}
/** @var EntityManagerInterface $em */
$em = $this->manager->get('doctrine')->getManager();
$em->flush();
}
/**
* Queue notification.
*
* @param string $channel
*
* @throws \ReflectionException
*/
public function queue(NotificationInterface $notification, $channel): void
{
$message = [
'event' => strtolower(
preg_replace(
'~(?<=\\w)([A-Z])~',
'.$1',
(new \ReflectionClass($notification))->getShortName()
)
),
'class' => (new \ReflectionClass($notification))->getName(),
'entity' => (new \ReflectionClass($notification->getSubject()))->getName(),
'id' => $notification->getSubject()->getId(),
'channel' => $channel,
'sent_at' => date('d-m-Y \@ h:i A'),
];
$this->manager->queue(json_encode($message), $notification->getHandoverDetails());
}
/**
* Check that notification has channel.
*
* @throws \ReflectionException
*/
public function hasChannel(NotificationInterface $notification, $channel): bool
{
return \in_array($channel, $this->manager->getQueue($notification));
}
}