Commit 2b3c728a authored by Dries's avatar Dries

- Patch #859602 by catch, bfroehle: #cache does not record the #attached...

- Patch #859602 by catch, bfroehle: #cache does not record the #attached declared in child elements.
parent 25a4309e
......@@ -5827,14 +5827,58 @@ function drupal_render_cache_set(&$markup, $elements) {
// be retrieved and used.
$data['#markup'] = &$markup;
// Persist attached data associated with this element.
if (isset($elements['#attached'])) {
$data['#attached'] = $elements['#attached'];
$attached = drupal_render_collect_attached($elements, TRUE);
if ($attached) {
$data['#attached'] = $attached;
}
$bin = isset($elements['#cache']['bin']) ? $elements['#cache']['bin'] : 'cache';
$expire = isset($elements['#cache']['expire']) ? $elements['#cache']['expire'] : CACHE_PERMANENT;
cache_set($cid, $data, $bin, $expire);
}
/**
* Collect #attached for an element and all child elements into a single array.
*
* When caching elements, it is necessary to collect all libraries, javascript
* and CSS into a single array, from both the element itself and all child
* elements. This allows drupal_render() to add these back to the page when the
* element is returned from cache.
*
* @param $elements
* The element to collect #attached from.
* @param $return
* Whether to return the attached elements and reset the internal static.
*
* @return
* The #attached array for this element and its descendants.
*/
function drupal_render_collect_attached($elements, $return = FALSE) {
$attached = &drupal_static(__FUNCTION__, array());
// Collect all #attached for this element.
if (isset($elements['#attached'])) {
foreach ($elements['#attached'] as $key => $value) {
if (!isset($attached[$key])) {
$attached[$key] = array();
}
$attached[$key] = array_merge($attached[$key], $value);
}
}
if ($children = element_children($elements)) {
foreach ($children as $child) {
drupal_render_collect_attached($elements[$child]);
}
}
// If this was the first call to the function, return all attached elements
// and reset the static cache.
if ($return) {
$return = $attached;
$attached = array();
return $return;
}
}
/**
* Prepare an element for caching based on a query. This smart caching strategy
* saves Drupal from querying and rendering to HTML when the underlying query is
......
......@@ -1521,6 +1521,56 @@ class DrupalRenderTestCase extends DrupalWebTestCase {
$this->assertTrue(strpos($output, $second) < strpos($output, $first), t('Elements were not sorted.'));
}
/**
* Test #attached functionality in children elements.
*/
function testDrupalRenderChildrenAttached() {
// The cache system is turned off for POST requests.
$request_method = $_SERVER['REQUEST_METHOD'];
$_SERVER['REQUEST_METHOD'] = 'GET';
// Create an element with a child and subchild. Each element loads a
// different JavaScript file using #attached.
$parent_js = drupal_get_path('module', 'user') . '/user.js';
$child_js = drupal_get_path('module', 'forum') . '/forum.js';
$subchild_js = drupal_get_path('module', 'book') . '/book.js';
$element = array(
'#type' => 'fieldset',
'#cache' => array(
'keys' => array('simpletest', 'drupal_render', 'children_attached'),
),
'#attached' => array('js' => array($parent_js)),
'#title' => 'Parent',
);
$element['child'] = array(
'#type' => 'fieldset',
'#attached' => array('js' => array($child_js)),
'#title' => 'Child',
);
$element['child']['subchild'] = array(
'#attached' => array('js' => array($subchild_js)),
'#markup' => 'Subchild',
);
// Render the element and verify the presence of #attached JavaScript.
drupal_render($element);
$scripts = drupal_get_js();
$this->assertTrue(strpos($scripts, $parent_js), t('The element #attached JavaScript was included.'));
$this->assertTrue(strpos($scripts, $child_js), t('The child #attached JavaScript was included.'));
$this->assertTrue(strpos($scripts, $subchild_js), t('The subchild #attached JavaScript was included.'));
// Load the element from cache and verify the presence of the #attached
// JavaScript.
drupal_static_reset('drupal_add_js');
$this->assertTrue(drupal_render_cache_get($element), t('The element was retrieved from cache.'));
$scripts = drupal_get_js();
$this->assertTrue(strpos($scripts, $parent_js), t('The element #attached JavaScript was included when loading from cache.'));
$this->assertTrue(strpos($scripts, $child_js), t('The child #attached JavaScript was included when loading from cache.'));
$this->assertTrue(strpos($scripts, $subchild_js), t('The subchild #attached JavaScript was included when loading from cache.'));
$_SERVER['REQUEST_METHOD'] = $request_method;
}
/**
* Test passing arguments to the theme function.
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment