<?php
namespace App\EventListener;
use App\Component\Communicator\Provider\Mailer;
use App\Component\Authenticator\Authenticator;
use Exception;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Throwable;
class ServerError
{
/**
* @var Authenticator
*/
private $authenticator;
/**
* @var ParameterBagInterface
*/
private $parameters;
/**
* @var Mailer
*/
private $mailer;
function __construct(Authenticator $authenticator, ParameterBagInterface $parameters, Mailer $mailer)
{
$this->authenticator = $authenticator;
$this->parameters = $parameters;
$this->mailer = $mailer;
}
/**
* Determines action on kernel exception.
*
* @param ExceptionEvent $event
*
* @throws Exception
*/
public function onKernelException(ExceptionEvent $event)
{
if(!$this->parameters->get('server_error_notifications')) {
return;
}
$request = $event->getRequest();
$exception = $event->getThrowable();
$this->sendNotifications($exception, $request);
}
/**
* Sends e-mail to the webmasters with server error details.
*
* @param Exception $exception
*
* @throws Exception
*/
public function sendNotifications(Throwable $exception, Request $request) {
$webmasters = $this->parameters->get('webmasters');
if(!is_array($webmasters) || !$this->isWorthNotifying($exception)) {
return;
}
foreach($webmasters as $webmaster) {
$this->mailer->send($webmaster, 'Trocado: server error', 'error', [
'endpoint' => $request->getMethod() . ' ' . $request->getRequestUri(),
'environment' => $this->parameters->get('kernel.environment'),
'exception' => $exception,
'trace' => $exception->getTrace(),
'user' => $this->authenticator->getUser(),
'read_unrestricted' => $this->authenticator->hasPermissionWithCodeName('read_unrestricted')
], true);
}
}
/**
* Determine whether the exception is not worth notifying.
*
* @param Throwable $exception
*
* @return bool
*/
private function isWorthNotifying(Throwable $exception): bool
{
if($this->isWindows() && (
strpos($exception->getMessage(), 'Warning: copy') !== false ||
strpos($exception->getMessage(), 'Cannot rename') !== false ||
strpos($exception->getMessage(), 'Compile Error: Doctrine\Common\Proxy\AbstractProxyFactory::getProxyDefinition()') !== false ||
strpos($exception->getMessage(), 'Attempted to load class') !== false
)) {
return false;
}
if(
strpos($exception->getMessage(), 'No route found for') !== false ||
strpos($exception->getMessage(), 'statelesscheck') !== false
) {
return false;
}
return true;
}
/**
* Determine whether the OS is Windows.
*/
private function isWindows(): bool
{
return PHP_OS_FAMILY === 'Windows';
}
}