<?php
namespace App\Services;
use PhpParser\Comment\Doc;
use Pimcore\Bundle\CoreBundle\EventListener\PimcoreContextListener;
use Pimcore\Bundle\CoreBundle\EventListener\Traits\PimcoreContextAwareTrait;
use Pimcore\Config;
use Pimcore\Db\ConnectionInterface;
use Pimcore\Document\Renderer\DocumentRenderer;
use Pimcore\Http\Request\Resolver\PimcoreContextResolver;
use Pimcore\Model\Document;
use Pimcore\Model\Site;
use Psr\Log\LoggerAwareTrait;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Pimcore\Http\Exception\ResponseException;
class ErrorService implements EventSubscriberInterface
{
use LoggerAwareTrait;
use PimcoreContextAwareTrait;
/**
* @var DocumentRenderer
*/
protected $documentRenderer;
/**
* @var bool
*/
protected $renderErrorPage = true;
/**
* @var Config
*/
protected $config;
/**
* @var ConnectionInterface
*/
protected $db;
/**
* @param DocumentRenderer $documentRenderer
* @param ConnectionInterface $db
* @param bool $renderErrorPage
*/
public function __construct(DocumentRenderer $documentRenderer, ConnectionInterface $db, Config $config, $renderErrorPage = true)
{
$this->documentRenderer = $documentRenderer;
$this->renderErrorPage = (bool)$renderErrorPage;
$this->db = $db;
$this->config = $config;
}
public static function getSubscribedEvents() :array
{
return [
KernelEvents::EXCEPTION => [
['onKernelException', 128]
]
];
}
public function onKernelException(ExceptionEvent $event)
{
if ($_ENV['APP_ENV'] == 'dev') return;
// $exception = $event->getThrowable();
// $exception->getStatusCode();
// // handle ResponseException (can be used from any context)
// if ($exception instanceof ResponseException) {
// $event->setResponse($exception->getResponse());
//
// // a response was explicitely set -> do not continue to error page
// return;
// }
// further checks are only valid for default context
$request = $event->getRequest();
if ($this->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_DEFAULT)) {
if ($this->renderErrorPage) {
$this->handleErrorPage($event);
}
}
}
protected function handleErrorPage(ExceptionEvent $event)
{
//TODO: uncomment me for production
// if (\Pimcore::inDebugMode()) {
// return;
// }
$exception = $event->getThrowable();
if (is_callable([$exception, 'getStatusCode'])) {
$statusCode = 404;
$uri = $_SERVER['REQUEST_URI'];
if (strstr($uri, '/en/')) {
$errorPath = '/en/404';
} else if (strstr($uri, '/hr/')) {
$errorPath = '/hr/404';
} else {
$errorPath = $this->config['documents']['error_pages']['default'];
}
} else {
$statusCode = 500;
$uri = $_SERVER['REQUEST_URI'];
if (strstr($uri, '/en/')) {
$errorPath = '/en/500';
} else if (strstr($uri, '/hr/')) {
$errorPath = '/hr/500';
} else {
$errorPath = '/en/500';
}
}
//
// $statusCode = 500;
// $headers = [];
// if ($exception instanceof HttpExceptionInterface) {
// $statusCode = $exception->getStatusCode();
// $headers = $exception->getHeaders();
// } else {
// // only log exception if it's not intentional (like a NotFoundHttpException)
// $this->logger->error($exception);
// }
// $errorPath = $this->config['documents']['error_pages']['default'];
//
// if (Site::isSiteRequest()) {
// $site = Site::getCurrentSite();
// $errorPath = $site->getErrorDocument();
// }
//
// $this->logToHttpErrorLog($event->getRequest(), $statusCode);
//
// // Error page rendering
// if (empty($errorPath)) {
// $errorPath = '/';
// }
$document = Document::getByPath($errorPath);
// echo $document->getId();
// if (!$document instanceof Document\Page) {
// // default is home
// $document = Document::getById(1);
// } else {
// $document = $this->getDocumentVersion($document);
// }
try {
$response = $this->documentRenderer->render($document, [
'exception' => $exception,
PimcoreContextListener::ATTRIBUTE_PIMCORE_CONTEXT_FORCE_RESOLVING => true,
]);
//echo "suces";
} catch (\Exception $e) {
// we are even not able to render the error page, so we send the client a unicorn
$response = 'Page not found. 🦄';
$this->logger->emergency('Unable to render error page, exception thrown');
$this->logger->emergency($e);
}
$event->setResponse(new Response($response, $statusCode, []));
}
protected function logToHttpErrorLog(Request $request, $statusCode)
{
$uri = $request->getUri();
$exists = $this->db->fetchOne('SELECT date FROM http_error_log WHERE uri = ?', $uri);
if ($exists) {
$this->db->query('UPDATE http_error_log SET `count` = `count` + 1, date = ? WHERE uri = ?', [time(), $uri]);
} else {
$this->db->insert('http_error_log', [
'uri' => $uri,
'code' => (int) $statusCode,
'parametersGet' => serialize($_GET),
'parametersPost' => serialize($_POST),
'cookies' => serialize($_COOKIE),
'serverVars' => serialize($_SERVER),
'date' => time(),
'count' => 1,
]);
}
}
}