Security update to Drupal 8.4.6
[yaffs-website] / web / core / modules / big_pipe / src / EventSubscriber / HtmlResponseBigPipeSubscriber.php
1 <?php
2
3 namespace Drupal\big_pipe\EventSubscriber;
4
5 use Drupal\Core\Render\HtmlResponse;
6 use Drupal\big_pipe\Render\BigPipe;
7 use Drupal\big_pipe\Render\BigPipeResponse;
8 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
9 use Symfony\Component\HttpKernel\KernelEvents;
10 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
11
12 /**
13  * Response subscriber to replace the HtmlResponse with a BigPipeResponse.
14  *
15  * @see \Drupal\big_pipe\Render\BigPipe
16  *
17  * @todo Refactor once https://www.drupal.org/node/2577631 lands.
18  */
19 class HtmlResponseBigPipeSubscriber implements EventSubscriberInterface {
20
21   /**
22    * The BigPipe service.
23    *
24    * @var \Drupal\big_pipe\Render\BigPipe
25    */
26   protected $bigPipe;
27
28   /**
29    * Constructs a HtmlResponseBigPipeSubscriber object.
30    *
31    * @param \Drupal\big_pipe\Render\BigPipe $big_pipe
32    *   The BigPipe service.
33    */
34   public function __construct(BigPipe $big_pipe) {
35     $this->bigPipe = $big_pipe;
36   }
37
38   /**
39    * Adds markers to the response necessary for the BigPipe render strategy.
40    *
41    * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
42    *   The event to process.
43    */
44   public function onRespondEarly(FilterResponseEvent $event) {
45     $response = $event->getResponse();
46     if (!$response instanceof HtmlResponse) {
47       return;
48     }
49
50     // Wrap the scripts_bottom placeholder with a marker before and after,
51     // because \Drupal\big_pipe\Render\BigPipe needs to be able to extract that
52     // markup if there are no-JS BigPipe placeholders.
53     // @see \Drupal\big_pipe\Render\BigPipe::sendPreBody()
54     $attachments = $response->getAttachments();
55     if (isset($attachments['html_response_attachment_placeholders']['scripts_bottom'])) {
56       $scripts_bottom_placeholder = $attachments['html_response_attachment_placeholders']['scripts_bottom'];
57       $content = $response->getContent();
58       $content = str_replace($scripts_bottom_placeholder, '<drupal-big-pipe-scripts-bottom-marker>' . $scripts_bottom_placeholder . '<drupal-big-pipe-scripts-bottom-marker>', $content);
59       $response->setContent($content);
60     }
61   }
62
63   /**
64    * Transforms a HtmlResponse to a BigPipeResponse.
65    *
66    * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
67    *   The event to process.
68    */
69   public function onRespond(FilterResponseEvent $event) {
70     $response = $event->getResponse();
71     if (!$response instanceof HtmlResponse) {
72       return;
73     }
74
75     $attachments = $response->getAttachments();
76
77     // If there are no no-JS BigPipe placeholders, unwrap the scripts_bottom
78     // markup.
79     // @see onRespondEarly()
80     // @see \Drupal\big_pipe\Render\BigPipe::sendPreBody()
81     if (empty($attachments['big_pipe_nojs_placeholders'])) {
82       $content = $response->getContent();
83       $content = str_replace('<drupal-big-pipe-scripts-bottom-marker>', '', $content);
84       $response->setContent($content);
85     }
86
87     // If there are neither BigPipe placeholders nor no-JS BigPipe placeholders,
88     // there isn't anything dynamic in this response, and we can return early:
89     // there is no point in sending this response using BigPipe.
90     if (empty($attachments['big_pipe_placeholders']) && empty($attachments['big_pipe_nojs_placeholders'])) {
91       return;
92     }
93
94     $big_pipe_response = new BigPipeResponse($response);
95     $big_pipe_response->setBigPipeService($this->getBigPipeService($event));
96     $event->setResponse($big_pipe_response);
97   }
98
99   /**
100    * Returns the BigPipe service to use to send the current response.
101    *
102    * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
103    *   A response event.
104    *
105    * @return \Drupal\big_pipe\Render\BigPipe
106    *   The BigPipe service.
107    */
108   protected function getBigPipeService(FilterResponseEvent $event) {
109     return $this->bigPipe;
110   }
111
112   /**
113    * {@inheritdoc}
114    */
115   public static function getSubscribedEvents() {
116     // Run after HtmlResponsePlaceholderStrategySubscriber (priority 5), i.e.
117     // after BigPipeStrategy has been applied, but before normal (priority 0)
118     // response subscribers have been applied, because by then it'll be too late
119     // to transform it into a BigPipeResponse.
120     $events[KernelEvents::RESPONSE][] = ['onRespondEarly', 3];
121
122     // Run as the last possible subscriber.
123     $events[KernelEvents::RESPONSE][] = ['onRespond', -10000];
124
125     return $events;
126   }
127
128 }