a12s-1.0.0-beta7/src/EventSubscriber/PhpErrorsSubscriber.php
src/EventSubscriber/PhpErrorsSubscriber.php
<?php
namespace Drupal\a12s_core\EventSubscriber;
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Render\BareHtmlPageRendererInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Service for handling some PHP errors.
*
* The maintenance page is displayed when possible, instead of a raw page.
*/
class PhpErrorsSubscriber implements EventSubscriberInterface {
use StringTranslationTrait;
/**
* Constructs a new MaintenanceModeSubscriber.
*
* @param \Drupal\Core\Render\BareHtmlPageRendererInterface $bareHtmlPageRenderer
* The bare HTML page renderer.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @param \Drupal\Core\Cache\CacheBackendInterface $cacheDiscovery
* The cache backend for plugin discovery.
*/
public function __construct(
protected BareHtmlPageRendererInterface $bareHtmlPageRenderer,
protected EntityTypeManagerInterface $entityTypeManager,
protected CacheBackendInterface $cacheDiscovery
) {}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array {
// Take care of errors that have not been handled by other subscribers, but
// just before the last subscriber (256).
$events[KernelEvents::EXCEPTION][] = ['onException', -255];
return $events;
}
/**
* Take care of errors that are not handled by anyone.
*
* @param \Symfony\Component\HttpKernel\Event\ExceptionEvent $event
* The event to process.
*/
public function onException(ExceptionEvent $event): void {
if (!$event->isMainRequest()) {
return;
}
$exception = $event->getThrowable();
// There is a very old issue with paragraph entity type, where the
// "translation" handler is missing from the entity type definition.
// In such case, a simple rebuild of the entity cache fixes the issue.
// It seems that the "content_translation_entity_type_alter()" hook
// is missing for some unclear reasons.
// @see https://www.drupal.org/project/paragraphs/issues/3031598
if ($exception instanceof InvalidPluginDefinitionException && $exception->getPluginId() === 'paragraph') {
try {
$entityType = $this->entityTypeManager->getDefinition('paragraph');
if (!$entityType->hasHandlerClass('translation')) {
// Rebuild the entity_type cache discovery, so the definition of the
// paragraph entity type will be rebuilt on next call.
$this->cacheDiscovery->delete('entity_type');
// Reload current page. Note that we loose the anchor part if any.
$request = $event->getRequest();
$format = $request->query->get(MainContentViewSubscriber::WRAPPER_FORMAT, $request->getRequestFormat());
// Do not try to redirect non-HTML request, as it may lead to bigger
// errors than the one we try to fix.
if ($format == 'html') {
$url = $request->getSchemeAndHttpHost() . $request->getRequestUri();
if (!empty($request->getQueryString())) {
$url .= '?' . $request->getQueryString();
}
$response = new RedirectResponse($url, 302, ['Cache-Control' => 'no-cache']);
$event->setResponse($response);
return;
}
}
}
catch (PluginNotFoundException $e) {
// Pass through.
}
}
$request = $event->getRequest();
$format = $request->query->get(MainContentViewSubscriber::WRAPPER_FORMAT, $request->getRequestFormat());
if ($format === 'html') {
drupal_maintenance_theme();
$response = $this->bareHtmlPageRenderer->renderBarePage(
['#markup' => $this->t('The website encountered an unexpected error. Please try again later.')],
$this->t('Unexpected error'),
'maintenance_page'
);
$event->setResponse($response);
}
}
}
