<?php declare(strict_types=1);
namespace App\EventSubscriber;
use App\Service\SiteManager;
use Symfony\Component\Mime\Email;
use App\Repository\PageRepository;
use App\Repository\UserRepository;
use Symfony\Component\Mime\Address;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent;
use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
class ErrorSubscriber implements EventSubscriberInterface
{
private $params;
private $mailer;
private $userRepository;
private $pageRepository;
private $siteManager;
private $request;
/**
* Constructor.
*/
public function __construct(ContainerBagInterface $params, MailerInterface $mailer, UserRepository $userRepository, PageRepository $pageRepository, SiteManager $siteManager, RequestStack $requestStack)
{
$this->params = $params;
$this->mailer = $mailer;
$this->userRepository = $userRepository;
$this->pageRepository = $pageRepository;
$this->siteManager = $siteManager;
$this->request = $requestStack->getCurrentRequest();
}
public static function getSubscribedEvents(): array
{
return [
// Needs to be triggered after Symfony\Component\Security\Http\Firewall\ExceptionListener::onKernelException()
KernelEvents::EXCEPTION => ['onInternalServerError', -1],
WorkerMessageFailedEvent::class => ['onMessageFailed'],
];
}
/**
* Gets an array of Super Admin addresses.
*/
private function getSuperAdminAddresses(): ?array {
if (!$superAdmins = $this->userRepository->findByRole('ROLE_SUPER_ADMIN')) {
return null;
}
$recipients = [];
foreach ($superAdmins as $superAdmin) {
$recipients[] = new Address($superAdmin->getEmail(), $superAdmin->getFullName());
}
return $recipients;
}
/**
* Sends email to Super Admins on HTTP internal server error (500).
*/
public function onInternalServerError(ExceptionEvent $event): void
{
if (
'dev' == $this->params->get('env')
|| !$recipients = $this->getSuperAdminAddresses()
) {
return;
}
$e = FlattenException::createFromThrowable($event->getThrowable());
if ($e->getStatusCode() == Response::HTTP_INTERNAL_SERVER_ERROR) {
// Find the current site page.
$page = $this->pageRepository->findOneBy([
'site' => $this->siteManager->getCurrent(),
'pathAlias' => $this->request->getPathInfo(),
]);
$test_subject = 'test' == $this->params->get('env') ? 'MAIL DE TEST ' : '';
// To change default sender, @see config/packages/mailer.yaml
$mail = (new TemplatedEmail())
->subject($test_subject.'Chordflow : Erreur 500')
->to(...$recipients)
->htmlTemplate('email/error.html.twig')
->context([
'error' => $e,
'page' => $page,
]);
$this->mailer->send($mail);
}
}
/**
* Sends email to Super Admins on message failed.
*/
public function onMessageFailed(WorkerMessageFailedEvent $event): void
{
if (
'dev' == $this->params->get('env')
|| $event->willRetry()
|| !$recipients = $this->getSuperAdminAddresses()
) {
return;
}
$message = get_class($event->getEnvelope()->getMessage());
$trace = $event->getThrowable()->getTraceAsString();
$test_subject = 'test' == $this->params->get('env') ? 'MAIL DE TEST ' : '';
// To change default sender, @see config/packages/mailer.yaml
$mail = (new Email())
->subject($test_subject.'Chordflow : Erreur lors d\'une tâche Messenger')
->to(...$recipients)
->text(<<<TEXT
Une erreur est servenue lors du traitement d'une tâche Messenger dans : {$message}
Message d'erreur détaillé :
{$trace}
TEXT);
$this->mailer->send($mail);
}
}