Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

Instead of calling drupal_add_*() directly, all feeds, html head, html head link and http headers should be set via using #attached on render arrays.

Before:

drupal_add_feed() 
drupal_add_html_head()
drupal_add_html_link()
drupal_add_http_header()

After:


$build['#attached']['feed'][] = array(
...
);
$build['#attached']['html_head'][] = array(
...
);

$build['#attached']['html_head_link'][] = array(
...
);

$build['#attached']['http_header'][] = array(
...
);

Assets should also use attached, there is a dedicated change notice dealing with this since it is the more common usage: https://www.drupal.org/node/2169605

Attached elements can also be added using hook_page_attachments() and hook_page_attachments_alter(). These functions are not cached, so should be avoided where possible for performance reasons. hook_page_attachments_alter() can be used as a direct replacement for hook_html_head_alter.

Impacts: 
Module developers
Themers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done

Comments

karolus’s picture

Since the release of Drupal 8 Beta 2 a few days ago, I've been working with some themes in alleviating the WSOD issue created when deprecated code was no longer supported. Unless I'm totally misinterpreting things, the code needed to create this output:

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

Would be this:

  $build['#attached']['html_head'][] = array(
    '#tag' => 'meta',
    '#attributes' => array(
    'http-equiv' => 'X-UA-Compatible',
    'content' => 'IE=edge,chrome=1',
    ),
  );

But so far, no dice. Any examples or suggestions?

Danny Englander’s picture

Here's working code (with drupal 8 dev, not Beta 2).

function MYTHEME_page_attachments_alter(array &$page) {
    $viewport = array(
      '#type' => 'html_tag',
      '#tag' => 'meta',
      '#attributes' => array(
        'name' => 'viewport',
        'content' => 'width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no',
      ),
    );
    $page['#attached']['html_head'][] = [$viewport, 'viewport'];
  }

There is an issue though that there are two viewport tags now, one from core and the one added from my theme so I am not sure how to handle that. I would have thought that the theme's tag would overwrite core's?

pavithra.raman’s picture

I have a D7 module being ported to D8 and it defines a CGi for integration with a 3rd party service/software. Software in question is an Icecast2 Audio streaming server. Now the CGI call from icecast is expecting some headers in the response, which in D7 was done using drupal_add_http_header(). How to accomplished this in D8, in the module level as there will not be a theme layer involved in the CGI call.?

Mile23’s picture

Not sure what icecast expects, but if you are creating a response in a render array, you can just add the headers you need in ['#attached']['http_header'][] = ['HeaderName', 'Value'];

This will be rendered into an appropriate response header.