View source
<?php
namespace Drupal\webform\EventSubscriber;
use Drupal\Core\Cache\CacheableResponseInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\EventSubscriber\DefaultExceptionHtmlSubscriber;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Routing\RedirectDestinationInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\webform\Element\WebformHtmlEditor;
use Drupal\webform\Entity\Webform;
use Drupal\webform\Entity\WebformSubmission;
use Drupal\webform\WebformInterface;
use Drupal\webform\WebformTokenManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
class WebformExceptionHtmlSubscriber extends DefaultExceptionHtmlSubscriber {
use StringTranslationTrait;
protected $account;
protected $configFactory;
protected $renderer;
protected $tokenManager;
protected $messenger;
public function __construct(HttpKernelInterface $http_kernel, LoggerInterface $logger, RedirectDestinationInterface $redirect_destination, UrlMatcherInterface $access_unaware_router, AccountInterface $account, ConfigFactoryInterface $config_factory, RendererInterface $renderer, MessengerInterface $messenger, WebformTokenManagerInterface $token_manager) {
parent::__construct($http_kernel, $logger, $redirect_destination, $access_unaware_router);
$this->account = $account;
$this->configFactory = $config_factory;
$this->renderer = $renderer;
$this->messenger = $messenger;
$this->tokenManager = $token_manager;
}
protected static function getPriority() {
return -49;
}
public function on403(GetResponseForExceptionEvent $event) {
if ($event
->getRequestType() !== HttpKernelInterface::MASTER_REQUEST) {
return;
}
$this
->on403RedirectEntityAccess($event);
$this
->on403RedirectPrivateFileAccess($event);
}
public function on403RedirectPrivateFileAccess(GetResponseForExceptionEvent $event) {
$path = $event
->getRequest()
->getPathInfo();
if (strpos($path, '/system/files/webform/') !== 0) {
return;
}
if (strpos($path, '/_sid_/') !== FALSE) {
return;
}
if (!$this->configFactory
->get('webform.settings')
->get('file.file_private_redirect')) {
return;
}
$message = $this->configFactory
->get('webform.settings')
->get('file.file_private_redirect_message');
$this
->redirectToLogin($event, $message);
}
public function on403RedirectEntityAccess(GetResponseForExceptionEvent $event) {
$url = Url::fromUserInput($event
->getRequest()
->getPathInfo());
if (!$url) {
return;
}
$route_parameters = $url
->isRouted() ? $url
->getRouteParameters() : [];
if (empty($route_parameters['webform']) && empty($route_parameters['webform_submission'])) {
return;
}
$config = $this->configFactory
->get('webform.settings');
if (!empty($route_parameters['webform_submission'])) {
$webform_submission = WebformSubmission::load($route_parameters['webform_submission']);
$webform = $webform_submission
->getWebform();
$submission_access_denied_message = $webform
->getSetting('submission_access_denied_message') ?: $config
->get('settings.default_submission_access_denied_message');
switch ($webform
->getSetting('submission_access_denied')) {
case WebformInterface::ACCESS_DENIED_LOGIN:
$this
->redirectToLogin($event, $submission_access_denied_message, $webform_submission);
break;
case WebformInterface::ACCESS_DENIED_PAGE:
$this
->makeSubrequest($event, '/admin/structure/webform/manage/' . $webform
->id() . '/submission/' . $webform_submission
->id() . '/access-denied', Response::HTTP_FORBIDDEN);
break;
case WebformInterface::ACCESS_DENIED_DEFAULT:
default:
$this
->makeSubrequest($event, $this
->getSystemSite403Path(), Response::HTTP_FORBIDDEN);
break;
}
$response = $event
->getResponse();
if ($response instanceof CacheableResponseInterface) {
$response
->addCacheableDependency($webform);
$response
->addCacheableDependency($webform_submission);
$response
->addCacheableDependency($config);
}
return;
}
if (!empty($route_parameters['webform'])) {
$webform = Webform::load($route_parameters['webform']);
$webform_access_denied_message = $webform
->getSetting('form_access_denied_message') ?: $config
->get('settings.default_form_access_denied_message');
switch ($webform
->getSetting('form_access_denied')) {
case WebformInterface::ACCESS_DENIED_LOGIN:
$this
->redirectToLogin($event, $webform_access_denied_message, $webform);
break;
case WebformInterface::ACCESS_DENIED_PAGE:
$this
->makeSubrequest($event, '/webform/' . $webform
->id() . '/access-denied', Response::HTTP_FORBIDDEN);
break;
case WebformInterface::ACCESS_DENIED_MESSAGE:
$this
->setMessage($webform_access_denied_message, $webform);
$this
->makeSubrequest($event, $this
->getSystemSite403Path(), Response::HTTP_FORBIDDEN);
break;
case WebformInterface::ACCESS_DENIED_DEFAULT:
default:
$this
->makeSubrequest($event, $this
->getSystemSite403Path(), Response::HTTP_FORBIDDEN);
break;
}
$response = $event
->getResponse();
if ($response instanceof CacheableResponseInterface) {
$response
->addCacheableDependency($webform);
$response
->addCacheableDependency($config);
}
return;
}
}
protected function getHandledFormats() {
return [
'html',
];
}
public function onException(GetResponseForExceptionEvent $event) {
$exception = $event
->getException();
if ($exception instanceof HttpExceptionInterface && $exception
->getStatusCode() === 403) {
parent::onException($event);
}
}
protected function getSystemSite403Path() {
return $this->configFactory
->get('system.site')
->get('page.403') ?: '/system/403';
}
protected function redirectToLogin(GetResponseForExceptionEvent $event, $message = NULL, EntityInterface $entity = NULL) {
if ($message) {
$this
->setMessage($message, $entity);
}
if ($this->account
->isAuthenticated()) {
return;
}
$redirect_url = Url::fromRoute('user.login', [], [
'absolute' => TRUE,
'query' => $this->redirectDestination
->getAsArray(),
]);
$event
->setResponse(new RedirectResponse($redirect_url
->toString()));
}
protected function setMessage($message, EntityInterface $entity = NULL) {
$message = $this->tokenManager
->replace($message, $entity);
$build = WebformHtmlEditor::checkMarkup($message);
$this->messenger
->addStatus($this->renderer
->renderPlain($build));
}
}