Commit 7a695724 authored by webchick's avatar webchick

Issue #2152207 by steveoliver, joelpittet, gnuget, idflood, hussainweb,...

Issue #2152207 by steveoliver, joelpittet, gnuget, idflood, hussainweb, shanethehat, jenlampton, kpa, AnythonyR, EVIIILJ, kgoel, Cottser, dsdeiz, hanpersand: Convert theme_details() to Twig
parent 062127e7
......@@ -979,44 +979,34 @@ function theme_fieldset($variables) {
}
/**
* Returns HTML for a details form element and its children.
* Prepares variables for details element templates.
*
* @param $variables
* Default template: details.html.twig.
*
* @param array $variables
* An associative array containing:
* - element: An associative array containing the properties of the element.
* Properties used: #attributes, #children, #collapsed, #description, #id,
* #title, #value.
* Properties used: #attributes, #children, #collapsed, #collapsible,
* #description, #id, #title, #value.
*
* @ingroup themeable
*/
function theme_details($variables) {
function template_preprocess_details(&$variables) {
$element = $variables['element'];
element_set_attributes($element, array('id'));
_form_set_attributes($element, array('form-wrapper'));
$output = '<details' . new Attribute($element['#attributes']) . '>';
$variables['attributes'] = $element['#attributes'];
$variables['summary_attributes'] = new Attribute();
if (!empty($element['#title'])) {
$summary_attributes = new Attribute(array(
'role' => 'button',
));
$variables['summary_attributes']['role'] = 'button';
if (!empty($element['#attributes']['id'])) {
$summary_attributes['aria-controls'] = $element['#attributes']['id'];
$variables['summary_attributes']['aria-controls'] = $element['#attributes']['id'];
}
$summary_attributes['aria-expanded'] = empty($element['#attributes']['open']) ? FALSE : TRUE;
$summary_attributes['aria-pressed'] = $summary_attributes['aria-expanded'];
$output .= '<summary' . $summary_attributes . '>' . $element['#title'] . '</summary>';
}
$output .= '<div class="details-wrapper">';
if (!empty($element['#description'])) {
$output .= '<div class="details-description">' . $element['#description'] . '</div>';
$variables['summary_attributes']['aria-expanded'] = empty($element['#attributes']['open']) ? FALSE : TRUE;
$variables['summary_attributes']['aria-pressed'] = $variables['summary_attributes']['aria-expanded'];
}
$output .= $element['#children'];
if (isset($element['#value'])) {
$output .= $element['#value'];
}
$output .= '</div>';
$output .= "</details>\n";
return $output;
$variables['title'] = (!empty($element['#title'])) ? $element['#title'] : '';
$variables['description'] = (!empty($element['#description'])) ? $element['#description'] : '';
$variables['children'] = (isset($element['#children'])) ? $element['#children'] : '';
$variables['value'] = (isset($element['#value'])) ? $element['#value'] : '';
}
/**
......@@ -1980,11 +1970,11 @@ function form_process_group(&$element, &$form_state) {
* The modified element.
*/
function form_pre_render_details($element) {
element_set_attributes($element, array('id'));
// The .form-wrapper class is required for #states to treat details like
// containers.
if (!isset($element['#attributes']['class'])) {
$element['#attributes']['class'] = array();
}
_form_set_attributes($element, array('form-wrapper'));
// Collapsible details.
$element['#attached']['library'][] = array('system', 'drupal.collapse');
......
......@@ -2682,6 +2682,7 @@ function drupal_common_theme() {
),
'details' => array(
'render element' => 'element',
'template' => 'details',
),
'radios' => array(
'render element' => 'element',
......
......@@ -598,9 +598,6 @@ function testDrupalRenderChildrenPostRenderCache() {
$element = array('#cache' => $element['#cache']);
$cached_element = cache()->get(drupal_render_cid_create($element))->data;
$expected_element = array(
'#markup' => '<details class="form-wrapper" open="open"><summary role="button" aria-expanded>Parent</summary><div class="details-wrapper"><details class="form-wrapper" open="open"><summary role="button" aria-expanded>Child</summary><div class="details-wrapper">Subchild</div></details>
</div></details>
',
'#attached' => array(
'js' => array(
array('type' => 'setting', 'data' => array('foo' => 'bar'))
......@@ -618,7 +615,17 @@ function testDrupalRenderChildrenPostRenderCache() {
)
),
);
$this->assertIdentical($cached_element, $expected_element, 'The correct data is cached: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
$dom = filter_dom_load($cached_element['#markup']);
$xpath = new \DOMXPath($dom);
$parent = $xpath->query('//details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Parent"]')->length;
$child = $xpath->query('//details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper"]/details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Child"]')->length;
$subchild = $xpath->query('//details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper"]/details[@class="form-wrapper" and @open="open"]/div [@class="details-wrapper" and text()="Subchild"]')->length;
$this->assertTrue($parent && $child && $subchild, 'The correct data is cached: the stored #markup is not affected by #post_render_cache callbacks.');
// Remove markup because it's compared above in the xpath.
unset($cached_element['#markup']);
$this->assertIdentical($cached_element, $expected_element, 'The correct data is cached: the stored #attached properties are not affected by #post_render_cache callbacks.');
// GET request: #cache enabled, cache hit.
drupal_static_reset('_drupal_add_js');
......@@ -674,9 +681,6 @@ function testDrupalRenderChildrenPostRenderCache() {
$cached_parent_element = cache()->get(drupal_render_cid_create($element))->data;
$cached_child_element = cache()->get(drupal_render_cid_create($element['child']))->data;
$expected_parent_element = array(
'#markup' => '<details class="form-wrapper" open="open"><summary role="button" aria-expanded>Parent</summary><div class="details-wrapper"><details class="form-wrapper" open="open"><summary role="button" aria-expanded>Child</summary><div class="details-wrapper">Subchild</div></details>
</div></details>
',
'#attached' => array(
'js' => array(
array('type' => 'setting', 'data' => array('foo' => 'bar'))
......@@ -694,10 +698,19 @@ function testDrupalRenderChildrenPostRenderCache() {
)
),
);
$this->assertIdentical($cached_parent_element, $expected_parent_element, 'The correct data is cached for the parent: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
$dom = filter_dom_load($cached_parent_element['#markup']);
$xpath = new \DOMXPath($dom);
$parent = $xpath->query('//details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Parent"]')->length;
$child = $xpath->query('//details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper"]/details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Child"]')->length;
$subchild = $xpath->query('//details[@class="form-wrapper" and @open="open"]/div[@class="details-wrapper"]/details[@class="form-wrapper" and @open="open"]/div [@class="details-wrapper" and text()="Subchild"]')->length;
$this->assertTrue($parent && $child && $subchild, 'The correct data is cached for the parent: the stored #markup is not affected by #post_render_cache callbacks.');
// Remove markup because it's compared above in the xpath.
unset($cached_parent_element['#markup']);
$this->assertIdentical($cached_parent_element, $expected_parent_element, 'The correct data is cached for the parent: the stored #attached properties are not affected by #post_render_cache callbacks.');
$expected_child_element = array(
'#markup' => '<details class="form-wrapper" open="open"><summary role="button" aria-expanded>Child</summary><div class="details-wrapper">Subchild</div></details>
',
'#attached' => array(
'library' => array(
array('system', 'drupal.collapse'),
......@@ -710,7 +723,16 @@ function testDrupalRenderChildrenPostRenderCache() {
)
),
);
$this->assertIdentical($cached_child_element, $expected_child_element, 'The correct data is cached for the child: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
$dom = filter_dom_load($cached_child_element['#markup']);
$xpath = new \DOMXPath($dom);
$child = $xpath->query('//details[@class="form-wrapper" and @open="open"]/summary[@role="button" and @aria-expanded and text()="Child"]')->length;
$subchild = $xpath->query('//details[@class="form-wrapper" and @open="open"]/div [@class="details-wrapper" and text()="Subchild"]')->length;
$this->assertTrue($child && $subchild, 'The correct data is cached for the child: the stored #markup is not affected by #post_render_cache callbacks.');
// Remove markup because it's compared above in the xpath.
unset($cached_child_element['#markup']);
$this->assertIdentical($cached_child_element, $expected_child_element, 'The correct data is cached for the child: the stored #attached properties are not affected by #post_render_cache callbacks.');
// GET request: #cache enabled, cache hit, parent element.
drupal_static_reset('_drupal_add_js');
......
{#
/**
* @file
* Default theme implementation for a details element.
*
* Available variables
* - attributes: A list of HTML attributes for the details element.
* - title: (optional) The title of the element, may not be set.
* - description: (optional) The description of the element, may not be set.
* - children: (optional) The children of the element, may not be set.
* - value: (optional) The value of the element, may not be set.
*
* @see template_preprocess_details()
*
* @ingroup themeable
*/
#}
<details{{ attributes }}>
{%- if title -%}
<summary{{ summary_attributes }}>{{ title }}</summary>
{%- endif -%}
<div class="details-wrapper">
{%- if description -%}
<div class="details-description">{{ description }}</div>
{%- endif -%}
{%- if children -%}
{{ children }}
{%- endif -%}
{%- if value -%}
{{ value }}
{%- endif -%}
</div>
</details>
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