pimcore/lib/Pimcore/Bundle/CoreBundle/EventListener/ResponseExceptionListener.php line 76

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Enterprise License (PEL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  * @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  * @license    http://www.pimcore.org/license     GPLv3 and PEL
  13.  */
  14. namespace Pimcore\Bundle\CoreBundle\EventListener;
  15. use Pimcore\Bundle\CoreBundle\EventListener\Traits\PimcoreContextAwareTrait;
  16. use Pimcore\Config;
  17. use Pimcore\Db\Connection;
  18. use Pimcore\Document\Renderer\DocumentRenderer;
  19. use Pimcore\FeatureToggles\Features\DebugMode;
  20. use Pimcore\Http\Exception\ResponseException;
  21. use Pimcore\Http\Request\Resolver\PimcoreContextResolver;
  22. use Pimcore\Model\Document;
  23. use Pimcore\Model\Site;
  24. use Pimcore\Templating\Renderer\ActionRenderer;
  25. use Psr\Log\LoggerAwareTrait;
  26. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  27. use Symfony\Component\HttpFoundation\Response;
  28. use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
  29. use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
  30. use Symfony\Component\HttpKernel\KernelEvents;
  31. class ResponseExceptionListener implements EventSubscriberInterface
  32. {
  33.     use LoggerAwareTrait;
  34.     use PimcoreContextAwareTrait;
  35.     /**
  36.      * @var ActionRenderer
  37.      */
  38.     protected $documentRenderer;
  39.     /**
  40.      * @var bool
  41.      */
  42.     protected $renderErrorPage true;
  43.     /**
  44.      * @var Connection
  45.      */
  46.     protected $db;
  47.     /**
  48.      * @param DocumentRenderer $documentRenderer
  49.      * @param Connection $db
  50.      * @param bool $renderErrorPage
  51.      */
  52.     public function __construct(DocumentRenderer $documentRendererConnection $db$renderErrorPage true)
  53.     {
  54.         $this->documentRenderer  $documentRenderer;
  55.         $this->renderErrorPage = (bool)$renderErrorPage;
  56.         $this->db $db;
  57.     }
  58.     /**
  59.      * @inheritDoc
  60.      */
  61.     public static function getSubscribedEvents()
  62.     {
  63.         return [
  64.             KernelEvents::EXCEPTION => 'onKernelException'
  65.         ];
  66.     }
  67.     public function onKernelException(GetResponseForExceptionEvent $event)
  68.     {
  69.         $exception $event->getException();
  70.         // handle ResponseException (can be used from any context)
  71.         if ($exception instanceof ResponseException) {
  72.             $event->setResponse($exception->getResponse());
  73.             // a response was explicitely set -> do not continue to error page
  74.             return;
  75.         }
  76.         // further checks are only valid for default context
  77.         $request $event->getRequest();
  78.         if ($this->matchesPimcoreContext($requestPimcoreContextResolver::CONTEXT_DEFAULT)) {
  79.             if ($this->renderErrorPage) {
  80.                 $this->handleErrorPage($event);
  81.             }
  82.         }
  83.     }
  84.     protected function handleErrorPage(GetResponseForExceptionEvent $event)
  85.     {
  86.         if (\Pimcore::inDebugMode(DebugMode::NO_ERROR_PAGE)) {
  87.             return;
  88.         }
  89.         $exception $event->getException();
  90.         $statusCode 500;
  91.         $headers    = [];
  92.         if ($exception instanceof HttpExceptionInterface) {
  93.             $statusCode $exception->getStatusCode();
  94.             $headers    $exception->getHeaders();
  95.         }
  96.         $errorPath Config::getSystemConfig()->documents->error_pages->default;
  97.         if (Site::isSiteRequest()) {
  98.             $site      Site::getCurrentSite();
  99.             $errorPath $site->getErrorDocument();
  100.         }
  101.         // HTTP Error Log
  102.         $uri $event->getRequest()->getUri();
  103.         $exists $this->db->fetchOne('SELECT date FROM http_error_log WHERE uri = ?'$uri);
  104.         if ($exists) {
  105.             $this->db->query('UPDATE http_error_log SET `count` = `count` + 1, date = ? WHERE uri = ?', [time(), $uri]);
  106.         } else {
  107.             $this->db->insert('http_error_log', [
  108.                 'uri' => $uri,
  109.                 'code' => (int) $statusCode,
  110.                 'parametersGet' => serialize($_GET),
  111.                 'parametersPost' => serialize($_POST),
  112.                 'cookies' => serialize($_COOKIE),
  113.                 'serverVars' => serialize($_SERVER),
  114.                 'date' => time(),
  115.                 'count' => 1
  116.             ]);
  117.         }
  118.         // Error page rendering
  119.         if (empty($errorPath)) {
  120.             $errorPath '/';
  121.         }
  122.         $document Document::getByPath($errorPath);
  123.         if (!$document instanceof Document\Page) {
  124.             // default is home
  125.             $document Document::getById(1);
  126.         }
  127.         try {
  128.             $response $this->documentRenderer->render($document, [
  129.                 'exception' => $exception
  130.             ]);
  131.         } catch (\Exception $e) {
  132.             // we are even not able to render the error page, so we send the client a unicorn
  133.             $response 'Page not found. ðŸ¦„';
  134.             $this->logger->emergency('Unable to render error page, exception thrown');
  135.             $this->logger->emergency($e);
  136.         }
  137.         $event->setResponse(new Response($response$statusCode$headers));
  138.     }
  139. }