You are here

protected function BigPipe::getPlaceholderOrder in Drupal 8

Same name and namespace in other branches
  1. 9 core/modules/big_pipe/src/Render/BigPipe.php \Drupal\big_pipe\Render\BigPipe::getPlaceholderOrder()
  2. 10 core/modules/big_pipe/src/Render/BigPipe.php \Drupal\big_pipe\Render\BigPipe::getPlaceholderOrder()

Gets the BigPipe placeholder order.

Determines the order in which BigPipe placeholders must be replaced.

Parameters

string $html: HTML markup.

array $placeholders: Associative array; the BigPipe placeholders. Keys are the BigPipe placeholder IDs.

Return value

array Indexed array; the order in which the BigPipe placeholders must be sent. Values are the BigPipe placeholder IDs. Note that only unique placeholders are kept: if the same placeholder occurs multiple times, we only keep the first occurrence.

1 call to BigPipe::getPlaceholderOrder()
BigPipe::sendContent in core/modules/big_pipe/src/Render/BigPipe.php
Sends an HTML response in chunks using the BigPipe technique.

File

core/modules/big_pipe/src/Render/BigPipe.php, line 713

Class

BigPipe
Service for sending an HTML response in chunks (to get faster page loads).

Namespace

Drupal\big_pipe\Render

Code

protected function getPlaceholderOrder($html, $placeholders) {
  $fragments = explode('<span data-big-pipe-placeholder-id="', $html);
  array_shift($fragments);
  $placeholder_ids = [];
  foreach ($fragments as $fragment) {
    $t = explode('"></span>', $fragment, 2);
    $placeholder_id = $t[0];
    $placeholder_ids[] = $placeholder_id;
  }
  $placeholder_ids = array_unique($placeholder_ids);

  // The 'status messages' placeholder needs to be special cased, because it
  // depends on global state that can be modified when other placeholders are
  // being rendered: any code can add messages to render.
  // This violates the principle that each lazy builder must be able to render
  // itself in isolation, and therefore in any order. However, we cannot
  // change the way \Drupal\Core\Messenger\MessengerInterface::addMessage()
  // works in the Drupal 8 cycle. So we have to accommodate its special needs.
  // Allowing placeholders to be rendered in a particular order (in this case:
  // last) would violate this isolation principle. Thus a monopoly is granted
  // to this one special case, with this hard-coded solution.
  // @see \Drupal\Core\Render\Element\StatusMessages
  // @see \Drupal\Core\Render\Renderer::replacePlaceholders()
  // @see https://www.drupal.org/node/2712935#comment-11368923
  $message_placeholder_ids = [];
  foreach ($placeholders as $placeholder_id => $placeholder_element) {
    if (isset($placeholder_element['#lazy_builder']) && $placeholder_element['#lazy_builder'][0] === 'Drupal\\Core\\Render\\Element\\StatusMessages::renderMessages') {
      $message_placeholder_ids[] = $placeholder_id;
    }
  }

  // Return placeholder IDs in DOM order, but with the 'status messages'
  // placeholders at the end, if they are present.
  $ordered_placeholder_ids = array_merge(array_diff($placeholder_ids, $message_placeholder_ids), array_intersect($placeholder_ids, $message_placeholder_ids));
  return $ordered_placeholder_ids;
}