Mercurial > hg > isophonics-drupal-site
diff core/modules/big_pipe/src/EventSubscriber/HtmlResponseBigPipeSubscriber.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/big_pipe/src/EventSubscriber/HtmlResponseBigPipeSubscriber.php Wed Nov 29 16:09:58 2017 +0000 @@ -0,0 +1,128 @@ +<?php + +namespace Drupal\big_pipe\EventSubscriber; + +use Drupal\Core\Render\HtmlResponse; +use Drupal\big_pipe\Render\BigPipe; +use Drupal\big_pipe\Render\BigPipeResponse; +use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +/** + * Response subscriber to replace the HtmlResponse with a BigPipeResponse. + * + * @see \Drupal\big_pipe\Render\BigPipe + * + * @todo Refactor once https://www.drupal.org/node/2577631 lands. + */ +class HtmlResponseBigPipeSubscriber implements EventSubscriberInterface { + + /** + * The BigPipe service. + * + * @var \Drupal\big_pipe\Render\BigPipe + */ + protected $bigPipe; + + /** + * Constructs a HtmlResponseBigPipeSubscriber object. + * + * @param \Drupal\big_pipe\Render\BigPipe $big_pipe + * The BigPipe service. + */ + public function __construct(BigPipe $big_pipe) { + $this->bigPipe = $big_pipe; + } + + /** + * Adds markers to the response necessary for the BigPipe render strategy. + * + * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event + * The event to process. + */ + public function onRespondEarly(FilterResponseEvent $event) { + $response = $event->getResponse(); + if (!$response instanceof HtmlResponse) { + return; + } + + // Wrap the scripts_bottom placeholder with a marker before and after, + // because \Drupal\big_pipe\Render\BigPipe needs to be able to extract that + // markup if there are no-JS BigPipe placeholders. + // @see \Drupal\big_pipe\Render\BigPipe::sendPreBody() + $attachments = $response->getAttachments(); + if (isset($attachments['html_response_attachment_placeholders']['scripts_bottom'])) { + $scripts_bottom_placeholder = $attachments['html_response_attachment_placeholders']['scripts_bottom']; + $content = $response->getContent(); + $content = str_replace($scripts_bottom_placeholder, '<drupal-big-pipe-scripts-bottom-marker>' . $scripts_bottom_placeholder . '<drupal-big-pipe-scripts-bottom-marker>', $content); + $response->setContent($content); + } + } + + /** + * Transforms a HtmlResponse to a BigPipeResponse. + * + * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event + * The event to process. + */ + public function onRespond(FilterResponseEvent $event) { + $response = $event->getResponse(); + if (!$response instanceof HtmlResponse) { + return; + } + + $attachments = $response->getAttachments(); + + // If there are no no-JS BigPipe placeholders, unwrap the scripts_bottom + // markup. + // @see onRespondEarly() + // @see \Drupal\big_pipe\Render\BigPipe::sendPreBody() + if (empty($attachments['big_pipe_nojs_placeholders'])) { + $content = $response->getContent(); + $content = str_replace('<drupal-big-pipe-scripts-bottom-marker>', '', $content); + $response->setContent($content); + } + + // If there are neither BigPipe placeholders nor no-JS BigPipe placeholders, + // there isn't anything dynamic in this response, and we can return early: + // there is no point in sending this response using BigPipe. + if (empty($attachments['big_pipe_placeholders']) && empty($attachments['big_pipe_nojs_placeholders'])) { + return; + } + + $big_pipe_response = new BigPipeResponse($response); + $big_pipe_response->setBigPipeService($this->getBigPipeService($event)); + $event->setResponse($big_pipe_response); + } + + /** + * Returns the BigPipe service to use to send the current response. + * + * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event + * A response event. + * + * @return \Drupal\big_pipe\Render\BigPipe + * The BigPipe service. + */ + protected function getBigPipeService(FilterResponseEvent $event) { + return $this->bigPipe; + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + // Run after HtmlResponsePlaceholderStrategySubscriber (priority 5), i.e. + // after BigPipeStrategy has been applied, but before normal (priority 0) + // response subscribers have been applied, because by then it'll be too late + // to transform it into a BigPipeResponse. + $events[KernelEvents::RESPONSE][] = ['onRespondEarly', 3]; + + // Run as the last possible subscriber. + $events[KernelEvents::RESPONSE][] = ['onRespond', -10000]; + + return $events; + } + +}