diff --git a/core/lib/Drupal/Core/Render/AttachmentsResponseProcessorInterface.php b/core/lib/Drupal/Core/Render/AttachmentsResponseProcessorInterface.php index 8257763..c0f9c65 100644 --- a/core/lib/Drupal/Core/Render/AttachmentsResponseProcessorInterface.php +++ b/core/lib/Drupal/Core/Render/AttachmentsResponseProcessorInterface.php @@ -9,6 +9,8 @@ /** * Defines an interface for processing attachments of responses that have them. * + * @see \Drupal\Core\Ajax\AjaxResponse + * @see \Drupal\Core\Ajax\AjaxResponseAttachmentsProcessor * @see \Drupal\Core\Render\HtmlResponse * @see \Drupal\Core\Render\HtmlResponseAttachmentsProcessor */ @@ -17,13 +19,38 @@ /** * Processes the attachments of a response that has attachments. * + * Libraries, JavaScript settings, feeds, HTML
tags, HTML links, + * HTTP headers, and the HTTP status code are attached to render arrays using + * the #attached property. The #attached property is an associative array, + * where the keys are the attachment types and the values are the attached + * data. For example: + * + * @code + * $build['#attached']['library'][] = [ + * 'library' => ['core/jquery'] + * ]; + * $build['#attached']['http_header'][] = [ + * ['Content-Type', 'application/rss+xml; charset=utf-8'], + * ]; + * @endcode + * + * The available keys are: + * - 'library' (asset libraries) + * - 'drupalSettings' (JavaScript settings) + * - 'feed' (RSS feeds) + * - 'html_head' (tags in HTML ) + * - 'html_head_link' ( tags in HTML ) + * - 'http_header' (HTTP headers and status code) + * * @param \Drupal\Core\Render\AttachmentsInterface $response - * The response to process the attachments for. + * The response to process. * * @return \Drupal\Core\Render\AttachmentsInterface * The processed response. * * @throws \InvalidArgumentException + * Thrown when the $response parameter is not a + * Drupal\Core\Render\HtmlResponse. */ public function processAttachments(AttachmentsInterface $response); diff --git a/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php b/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php index b5b3c27..f777a53 100644 --- a/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php +++ b/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php @@ -17,6 +17,15 @@ /** * Processes attachments of HTML responses. * + * This class is used by the rendering service to process the #attached part of + * the render array, for HTML responses. It replaces drupal_process_attached() + * and drupal_get_html_head() from Drupal 7. + * + * To render attachments to HTML for testing without a controller, use the + * 'bare_html_page_renderer' service to generate a + * Drupal\Core\Render\HtmlResponse object. Then use its getContent(), + * getStatusCode(), and/or the headers property to access the result. + * * @see template_preprocess_html() * @see \Drupal\Core\Render\AttachmentsResponseProcessorInterface * @see \Drupal\Core\Render\BareHtmlPageRenderer @@ -123,12 +132,12 @@ public function processAttachments(AttachmentsInterface $response) { // placeholder for it, we can safely avoid processing the render array if // it's not present. if (!empty($placeholders['head'])) { - - // feed is a special casse of html_head_link. We create an html_head_link - // for the RSS feed. + // 'feed' is a special case of 'html_head_link'. We create an + // 'html_head_link' for the RSS feed. if (!empty($attached['feed'])) { // @todo: Determine if feed is supposed to be a single structure or an - // array of structures. + // array of structures, and then refactor this array manipulation into + // a separate method if needed. $feed = $attached['feed']; if (is_array($feed[0])) { @@ -153,33 +162,37 @@ public function processAttachments(AttachmentsInterface $response) { } } - // html_head_link is a special case of html_head which can be present as - // a head element, but also as a Link: http header depending on settings - // in the render array. Processing it can add to both the html_head and - // http_header keys of #attached, so we must address it first. + // 'html_head_link' is a special case of 'html_head' which can be present + // as a head element, but also as a Link: HTTP header depending on + // settings in the render array. Processing it can add to both the + // 'html_head' and 'http_header' keys of '#attached', so we must address + // it first. if (!empty($attached['html_head_link'])) { - $link_attached = $this->processHtmlHeadLink($attached['html_head_link']); - // Merge $link_attached into $attached so that its html_head and - // http_header values are present for further processing. The merge - // requires a full render array, so we have to add #attached keys. + // Merge the processed 'html_head_link' into $attached so that its + // 'html_head' and 'http_header' values are present for further + // processing. The merge requires a full render array, so we have to add + // '#attached' keys. $attached = $this->renderer->mergeBubbleableMetadata( ['#attached' => $attached], - ['#attached' => $link_attached] + ['#attached' => $this->processHtmlHeadLink($attached['html_head_link'])] ); - // Unwrap the #attached key. + // Unwrap the '#attached' key. $attached = $attached['#attached']; } - // Now we can process html_head. + // Now we can process 'html_head', which contains both 'feed' and + // 'html_head_link'. if (!empty($attached['html_head'])) { - $head = $this->processHtmlHead($attached['html_head']); + $html_head = $this->processHtmlHead($attached['html_head']); // Invoke hook_html_head_alter(). - $this->moduleHandler->alter('html_head', $head); - $variables['head'] = $head; + $this->moduleHandler->alter('html_head', $html_head); + // Store the result in $variables so it can be inserted into the + // placeholder. + $variables['head'] = $html_head; } } - // Replace the placeholders in the response content with the real data. + // Replace the placeholders in the response content with our rendered HTML. $this->renderPlaceholders($response, $placeholders, $variables); // Set the HTTP headers on the response if any bubbled. diff --git a/core/lib/Drupal/Core/Render/theme.api.php b/core/lib/Drupal/Core/Render/theme.api.php index 689dce0..42fe60e 100644 --- a/core/lib/Drupal/Core/Render/theme.api.php +++ b/core/lib/Drupal/Core/Render/theme.api.php @@ -355,7 +355,10 @@ * Libraries, JavaScript settings, feeds, HTML tags and HTML links * are attached to elements using the #attached property. The #attached property * is an associative array, where the keys are the attachment types and the - * values are the attached data. For example: + * values are the attached data. + * + * The #attached property can also be used to specify HTTP headers and the + * response status code. * * The #attached property allows loading of asset libraries (which may contain * CSS assets, JavaScript assets, and JavaScript setting assets), JavaScript @@ -369,7 +372,8 @@ * $build['#attached']['feed'][] = ['aggregator/rss', $this->t('Feed title')]; * @endcode * - * See drupal_process_attached() for additional information. + * See \Drupal\Core\Render\AttachmentsResponseProcessorInterface for additional + * information. * * See \Drupal\Core\Asset\LibraryDiscoveryParser::parseLibraryInfo() for more * information on how to define libraries.