Created
October 24, 2022 07:28
-
-
Save nonom/f9f39b3372ce5413712bd7c7c62c0b1d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Drupal\boost\EventSubscriber; | |
use Drupal\boost\BoostCacheInterface; | |
use Drupal\Component\Plugin\Factory\FactoryInterface; | |
use Drupal\Core\Config\ConfigFactoryInterface; | |
use Drupal\Core\Config\ImmutableConfig; | |
use Drupal\Core\Render\HtmlResponse; | |
use Drupal\Core\Render\AttachmentsResponseProcessorInterface; | |
use Drupal\Core\Session\AccountProxy; | |
use Drupal\system\Plugin\Condition\RequestPath; | |
use Symfony\Component\HttpKernel\Event\RequestEvent; | |
use Symfony\Component\HttpKernel\Event\ResponseEvent; | |
use Symfony\Component\HttpKernel\KernelEvents; | |
use Symfony\Component\HttpFoundation\Response; | |
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
/** | |
* Class to return cached pages if eligible. | |
*/ | |
class BoostResponseSubscriber implements EventSubscriberInterface { | |
/** | |
* The HTML response attachments processor service. | |
* | |
* @var AttachmentsResponseProcessorInterface | |
*/ | |
protected AttachmentsResponseProcessorInterface $htmlResponseAttachmentsProcessor; | |
/** | |
* The current account. | |
* | |
* @var AccountProxy | |
*/ | |
protected AccountProxy $account; | |
/** | |
* The Boost cache service. | |
* | |
* @var BoostCacheInterface | |
*/ | |
protected BoostCacheInterface $boostCache; | |
/** | |
* The boost cache settings. | |
* | |
* @var ImmutableConfig | |
*/ | |
protected ImmutableConfig $boostConfig; | |
/** | |
* The request path condition plugin. | |
* | |
* @var RequestPath | |
*/ | |
protected RequestPath $condition; | |
/** | |
* Constructs a HtmlResponseSubscriber object. | |
* | |
* @param AttachmentsResponseProcessorInterface $html_response_attachments_processor | |
* The HTML response attachments processor service. | |
* @param AccountProxy $account | |
* Current user service. | |
* @param ConfigFactoryInterface $config_factory | |
* Config factory to get boost settings. | |
* @param BoostCacheInterface $boost_cache | |
* Plugin factory to get request_path. | |
* @param FactoryInterface $plugin_factory | |
* Plugin factory to get request_path. | |
*/ | |
public function __construct(AttachmentsResponseProcessorInterface $html_response_attachments_processor, | |
AccountProxy $account, | |
ConfigFactoryInterface $config_factory, | |
BoostCacheInterface $boost_cache, | |
FactoryInterface $plugin_factory) { | |
$this->htmlResponseAttachmentsProcessor = $html_response_attachments_processor; | |
$this->account = $account; | |
$this->boostConfig = $config_factory->get('boost.settings'); | |
$this->boostCache = $boost_cache; | |
$this->condition = $plugin_factory->createInstance('request_path'); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public static function getSubscribedEvents() { | |
return [ | |
KernelEvents::REQUEST => [ | |
['onRequest', 100], | |
], | |
KernelEvents::RESPONSE => [ | |
['onRespond', -100], | |
], | |
]; | |
} | |
/** | |
* Process a GetResponseEvent instance. | |
*/ | |
public function onRequest(RequestEvent $event) { | |
if ($this->account->isAuthenticated()) { | |
return; | |
} | |
if (!$this->checkPageCacheability()) { | |
return; | |
} | |
$method = $event->getRequest()->getMethod(); | |
// Only cache GET requests. | |
if ($method != 'GET') { | |
return; | |
} | |
// Check for existing cached response. | |
if (($content = $this->boostCache->retrieve()) && (!$event->getRequest()->headers->get('X-Boost-Cache'))) { | |
$response = new Response(); | |
$response->setContent($content); | |
$response->setStatusCode(Response::HTTP_OK); | |
$response->headers->set('X-Boost-Cache', 'partial'); | |
$event->setResponse($response); | |
} | |
} | |
/** | |
* Processes HtmlResponse event. | |
* | |
* @param ResponseEvent $event | |
* The event to process. | |
* | |
* @todo , split things off into the class. | |
*/ | |
public function onRespond(ResponseEvent $event) { | |
if ($this->account->isAuthenticated()) { | |
return; | |
} | |
if (!$this->checkPageCacheability()) { | |
return; | |
} | |
$response = $event->getResponse(); | |
if (!$response instanceof HtmlResponse) { | |
return; | |
} | |
if ($response->isRedirect() || $response->isForbidden() || | |
$response->isNotFound()) { | |
return; | |
} | |
$this->htmlResponseAttachmentsProcessor->processAttachments($response); | |
$content = $response->getContent(); | |
// Create a cached response on the local file system. | |
$this->boostCache->index($content); | |
} | |
/** | |
* Check page cacheaability. | |
* | |
* @return bool | |
* Whether the page should be cached or not. | |
*/ | |
public function checkPageCacheability(): bool | |
{ | |
$visibility = $this->boostConfig->get('cacheability_pages') ?? [ | |
'id' => 'request_path', | |
'pages' => '', | |
'negate' => 1, | |
]; | |
$this->condition->setConfiguration($visibility); | |
return $this->condition->evaluate(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
services:
boost.subscriber:
class: Drupal\boost\EventSubscriber\BoostResponseSubscriber
arguments: ['@html_response.attachments_processor', '@current_user', '@config.factory', '@boost.cache', '@plugin.manager.condition']
tags:
- {name: event_subscriber}