protected BigPipe::sendPlaceholders(array $placeholders, array $placeholder_order, AttachedAssetsInterface $cumulative_assets)
Sends BigPipe placeholders' replacements as embedded AJAX responses.
Parameters
array $placeholders: Associative array; the BigPipe placeholders. Keys are the BigPipe placeholder IDs.
array $placeholder_order: Indexed array; the order in which the BigPipe placeholders must be sent. Values are the BigPipe placeholder IDs. (These values correspond to keys in $placeholders.)
\Drupal\Core\Asset\AttachedAssetsInterface $cumulative_assets: The cumulative assets sent so far; to be updated while rendering BigPipe placeholders.
Throws
\Exception If an exception is thrown during the rendering of a placeholder, it is caught to allow the other placeholders to still be replaced. But when error logging is configured to be verbose, the exception is rethrown to simplify debugging.
File
- core/modules/big_pipe/src/Render/BigPipe.php, line 365
Class
- BigPipe
- The default BigPipe service.
Namespace
Drupal\big_pipe\Render
Code
protected function sendPlaceholders(array $placeholders, array $placeholder_order, AttachedAssetsInterface $cumulative_assets) { // Return early if there are no BigPipe placeholders to send. if (empty($placeholders)) { return; } // Send the start signal. print "\n"; print static::START_SIGNAL; print "\n"; flush(); // A BigPipe response consists of a HTML response plus multiple embedded // AJAX responses. To process the attachments of those AJAX responses, we // need a fake request that is identical to the master request, but with // one change: it must have the right Accept header, otherwise the work- // around for a bug in IE9 will cause not JSON, but <textarea>-wrapped JSON // to be returned. // @see \Drupal\Core\EventSubscriber\AjaxResponseSubscriber::onResponse() $fake_request = $this->requestStack->getMasterRequest()->duplicate(); $fake_request->headers->set('Accept', 'application/vnd.drupal-ajax'); foreach ($placeholder_order as $placeholder_id) { if (!isset($placeholders[$placeholder_id])) { continue; } // Render the placeholder. $placeholder_render_array = $placeholders[$placeholder_id]; try { $elements = $this->renderPlaceholder($placeholder_id, $placeholder_render_array); } catch (\Exception $e) { if ($this->configFactory->get('system.logging')->get('error_level') === ERROR_REPORTING_DISPLAY_VERBOSE) { throw $e; } else { trigger_error($e, E_USER_ERROR); continue; } } // Create a new AjaxResponse. $ajax_response = new AjaxResponse(); // JavaScript's querySelector automatically decodes HTML entities in // attributes, so we must decode the entities of the current BigPipe // placeholder ID (which has HTML entities encoded since we use it to find // the placeholders). $big_pipe_js_placeholder_id = Html::decodeEntities($placeholder_id); $ajax_response->addCommand(new ReplaceCommand(sprintf('[data-big-pipe-placeholder-id="%s"]', $big_pipe_js_placeholder_id), $elements['#markup'])); $ajax_response->setAttachments($elements['#attached']); // Push a fake request with the asset libraries loaded so far and dispatch // KernelEvents::RESPONSE event. This results in the attachments for the // AJAX response being processed by AjaxResponseAttachmentsProcessor and // hence: // - the necessary AJAX commands to load the necessary missing asset // libraries and updated AJAX page state are added to the AJAX response // - the attachments associated with the response are finalized, which // allows us to track the total set of asset libraries sent in the // initial HTML response plus all embedded AJAX responses sent so far. $fake_request->request->set('ajax_page_state', ['libraries' => implode(',', $cumulative_assets->getAlreadyLoadedLibraries())] + $cumulative_assets->getSettings()['ajaxPageState']); try { $ajax_response = $this->filterEmbeddedResponse($fake_request, $ajax_response); } catch (\Exception $e) { if ($this->configFactory->get('system.logging')->get('error_level') === ERROR_REPORTING_DISPLAY_VERBOSE) { throw $e; } else { trigger_error($e, E_USER_ERROR); continue; } } // Send this embedded AJAX response. $json = $ajax_response->getContent(); $output = <<<EOF <script type="application/vnd.drupal-ajax" data-big-pipe-replacement-for-placeholder-with-id="$placeholder_id"> $json </script> EOF; print $output; flush(); // Another placeholder was rendered and sent, track the set of asset // libraries sent so far. Any new settings are already sent; we don't need // to track those. if (isset($ajax_response->getAttachments()['drupalSettings']['ajaxPageState']['libraries'])) { $cumulative_assets->setAlreadyLoadedLibraries(explode(',', $ajax_response->getAttachments()['drupalSettings']['ajaxPageState']['libraries'])); } } // Send the stop signal. print "\n"; print static::STOP_SIGNAL; print "\n"; flush(); }
Please login to continue.