lupus_decoupled-1.x-dev/modules/lupus_decoupled_ce_api/src/EventSubscriber/FrontendRedirectSubscriber.php
modules/lupus_decoupled_ce_api/src/EventSubscriber/FrontendRedirectSubscriber.php
<?php
namespace Drupal\lupus_decoupled_ce_api\EventSubscriber;
use Drupal\Core\Cache\CacheableResponseInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\lupus_decoupled_ce_api\BaseUrlProviderTrait;
use Drupal\lupus_decoupled_ce_api\LupusDecoupledCeApiSettingsTrait;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use drunomics\ServiceUtils\Core\Routing\CurrentRouteMatchTrait;
use drunomics\ServiceUtils\Symfony\HttpFoundation\RequestStackTrait;
/**
* Redirects routes to the decoupled frontend when access without /ce-api.
*/
class FrontendRedirectSubscriber implements EventSubscriberInterface {
use BaseUrlProviderTrait;
use CurrentRouteMatchTrait;
use LupusDecoupledCeApiSettingsTrait;
use RequestStackTrait;
/**
* An array of routes to redirect to the frontend.
*
* Contains 'entity.node.canonical' and possibly others.
*
* If a new route is added to frontend_routes,
* also add its path to lupus_decoupled_ce_api.frontend_paths.
* You can register a new frontend route by implementing
* a custom service provider.
*
* @var string[]
*/
protected $frontendRoutes;
/**
* The config factory service.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* FrontendRedirectSubscriber constructor.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* The config factory service.
* @param string[] $frontendRoutes
* The routes to redirect.
*/
public function __construct(ConfigFactoryInterface $configFactory, array $frontendRoutes) {
$this->configFactory = $configFactory;
$this->frontendRoutes = $frontendRoutes;
}
/**
* Redirects frontend routes to the frontend base URL.
*
* @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
* The request event.
*/
public function onKernelRequest(RequestEvent $event) {
if ($this->getCurrentRequest()->getRequestFormat() != 'html') {
// Do not redirect API responses.
return;
}
if ($this->getBaseUrlProvider()->getFrontendBaseUrl() == NULL || !$this->getLupusDecoupledCeApiSettings()->get('frontend_routes_redirect')) {
// Exit if frontend_base_url is not set
// or if frontend redirect is disabled.
return;
}
if (in_array($this->getCurrentRouteMatch()->getRouteName(), $this->frontendRoutes)
&& ($event->getRequest()->getMethod()) != 'POST') {
$route_match = $this->getCurrentRouteMatch();
$redirect_url = NULL;
// For entity routes, get entity-specific frontend base URLs.
if (preg_match('/entity\.[a-z]+\.canonical/', $route_match->getRouteName())) {
$parameters = $route_match->getParameters()->all();
$entity = reset($parameters);
if ($entity && $entity instanceof EntityInterface) {
$options['query'] = $this->requestStack->getCurrentRequest()->query->all();
$options['absolute'] = TRUE;
$redirect_url = $entity->toUrl('canonical', $options)->toString();
}
}
// For other routes just forward to the frontend by keeping the current
// request URL.
if (!isset($redirect_url)) {
if ($frontend_base_url = $this->getBaseUrlProvider()->getFrontendBaseUrl()) {
// For sites with more than one frontend url there this method has to
// be overridden and a mechanism to decide frontend url
// should be put in place.
$redirect_url = $frontend_base_url . $this->getCurrentRequest()->getRequestUri();
}
}
if (isset($redirect_url)) {
// Prevent Core's RedirectResponseSubscriber from redirecting back
// to the original request's destination, ignoring our response.
$request_query_parameters = $this->requestStack->getCurrentRequest()->query;
$destination = $request_query_parameters->get('destination');
if ($destination) {
$request_query_parameters->remove('destination');
}
// Set the redirect response.
$event->setResponse(new TrustedRedirectResponse($redirect_url));
$event->stopPropagation();
}
}
}
/**
* Handles the response.
*
* @param \Symfony\Component\HttpKernel\Event\ResponseEvent $event
* The event to process.
*/
public function onResponse(ResponseEvent $event) {
$response = $event->getResponse();
if ($response instanceof CacheableResponseInterface) {
$response->addCacheableDependency($this->getLupusDecoupledCeApiSettings());
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
KernelEvents::REQUEST => ['onKernelRequest', 0],
KernelEvents::RESPONSE => ['onResponse', 5],
];
}
}
