Commit 7a2948aa authored by alexpott's avatar alexpott
Browse files

Issue #552478 by markcarver, sun, effulgentsia, jhedstrom, ohnobinki: Restrict...

Issue #552478 by markcarver, sun, effulgentsia, jhedstrom, ohnobinki: Restrict "self-closing" tags to only void elements in drupal_pre_render_html_tag
parent 466759dc
......@@ -17,6 +17,16 @@
*/
class HtmlTag extends RenderElement {
/**
* Void elements do not contain values or closing tags.
* @see http://www.w3.org/TR/html5/syntax.html#syntax-start-tag
* @see http://www.w3.org/TR/html5/syntax.html#void-elements
*/
static protected $voidElements = array(
'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',
'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr',
);
/**
* {@inheritdoc}
*/
......@@ -59,13 +69,16 @@ public function getInfo() {
*/
public static function preRenderHtmlTag($element) {
$attributes = isset($element['#attributes']) ? new Attribute($element['#attributes']) : '';
if (!isset($element['#value'])) {
// Construct a void element.
if (in_array($element['#tag'], self::$voidElements)) {
// This function is intended for internal use, so we assume that no unsafe
// values are passed in #tag. The attributes are already safe because
// Attribute output is already automatically sanitized.
// @todo Escape this properly instead? https://www.drupal.org/node/2296101
$markup = SafeMarkup::set('<' . $element['#tag'] . $attributes . " />\n");
}
// Construct all other elements.
else {
$markup = '<' . $element['#tag'] . $attributes . '>';
if (isset($element['#value_prefix'])) {
......
......@@ -86,22 +86,42 @@ function testContainer() {
* Tests system #type 'html_tag'.
*/
function testHtmlTag() {
// Test auto-closure meta tag generation.
// Test void element.
$this->assertElements(array(
'#type' => 'html_tag',
'#tag' => 'meta',
'#value' => 'ignored',
'#value_prefix' => 'ignored',
'#value_suffix' => 'ignored',
'#attributes' => array(
'name' => 'description',
'content' => 'Drupal test',
),
), '<meta name="description" content="Drupal test" />' . "\n", "#type 'html_tag' auto-closure meta tag generation");
), '<meta name="description" content="Drupal test" />' . "\n", "#type 'html_tag', void element renders properly");
// Test title tag generation.
// Test non-void element.
$this->assertElements(array(
'#type' => 'html_tag',
'#tag' => 'title',
'#value' => 'title test',
), "<title>title test</title>\n", "#type 'html_tag' title tag generation");
'#tag' => 'section',
'#value' => 'value',
'#value_prefix' => 'value_prefix|',
'#value_suffix' => '|value_suffix',
'#attributes' => array(
'class' => array('unicorns'),
),
), '<section class="unicorns">value_prefix|value|value_suffix</section>' . "\n", "#type 'html_tag', non-void element renders properly");
// Test empty void element tag.
$this->assertElements(array(
'#type' => 'html_tag',
'#tag' => 'link',
), "<link />\n", "#type 'html_tag' empty void element renders properly");
// Test empty non-void element tag.
$this->assertElements(array(
'#type' => 'html_tag',
'#tag' => 'section',
), "<section></section>\n", "#type 'html_tag' empty non-void element renders properly");
}
/**
......
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Render\Element\HtmlTagTest.
*/
namespace Drupal\Tests\Core\Render\Element;
use Drupal\Tests\UnitTestCase;
use Drupal\Core\Render\Element\HtmlTag;
/**
* @coversDefaultClass \Drupal\Core\Render\Element\HtmlTag
* @group Render
*/
class HtmlTagTest extends UnitTestCase {
/**
* @covers ::getInfo
*/
public function testGetInfo() {
$htmlTag = new HtmlTag(array(), 'test', 'test');
$info = $htmlTag->getInfo();
$this->assertArrayHasKey('#pre_render', $info);
$this->assertArrayHasKey('#attributes', $info);
$this->assertArrayHasKey('#value', $info);
}
/**
* @covers ::preRenderHtmlTag
* @dataProvider providerPreRenderHtmlTag
*/
public function testPreRenderHtmlTag($element, $expected) {
$result = HtmlTag::preRenderHtmlTag($element);
$this->assertArrayHasKey('#markup', $result);
$this->assertSame($expected, $result['#markup']);
}
/**
* Data provider for preRenderHtmlTag test.
*/
public function providerPreRenderHtmlTag() {
$tags = array();
// Value prefix/suffix.
$element = array(
'#value_prefix' => 'value_prefix|',
'#value_suffix' => '|value_suffix',
'#value' => 'value',
'#tag' => 'p',
);
$tags[] = array($element, '<p>value_prefix|value|value_suffix</p>' . "\n");
// Normal element without a value should not result in a void element.
$element = array(
'#tag' => 'p',
'#value' => NULL,
);
$tags[] = array($element, "<p></p>\n");
// A void element.
$element = array(
'#tag' => 'br',
);
$tags[] = array($element, "<br />\n");
// Attributes.
$element = array(
'#tag' => 'div',
'#attributes' => array('class' => 'test', 'id' => 'id'),
'#value' => 'value',
);
$tags[] = array($element, '<div class="test" id="id">value</div>' . "\n");
// No script tags.
$element['#noscript'] = TRUE;
$tags[] = array($element, '<noscript><div class="test" id="id">value</div>' . "\n" . '</noscript>');
return $tags;
}
/**
* @covers ::preRenderConditionalComments
* @dataProvider providerPreRenderConditionalComments
*/
public function testPreRenderConditionalComments($element, $expected) {
$this->assertSame($expected, HtmlTag::preRenderConditionalComments($element));
}
/**
* Data provider for conditional comments test.
*/
public function providerPreRenderConditionalComments() {
// No browser specification.
$element = array(
'#tag' => 'link',
);
$tags[] = array($element, $element);
// Specify all browsers.
$element['#browsers'] = array(
'IE' => TRUE,
'!IE' => TRUE,
);
$tags[] = array($element, $element);
// All IE.
$element = array(
'#tag' => 'link',
'#browsers' => array(
'IE' => TRUE,
'!IE' => FALSE,
),
);
$expected = $element;
$expected['#prefix'] = "\n<!--[if IE]>\n";
$expected['#suffix'] = "<![endif]-->\n";
$tags[] = array($element, $expected);
// Exclude IE.
$element = array(
'#tag' => 'link',
'#browsers' => array(
'IE' => FALSE,
),
);
$expected = $element;
$expected['#prefix'] = "\n<!--[if !IE]><!-->\n";
$expected['#suffix'] = "<!--<![endif]-->\n";
$tags[] = array($element, $expected);
// IE gt 8
$element = array(
'#tag' => 'link',
'#browsers' => array(
'IE' => 'gt IE 8',
),
);
$expected = $element;
$expected['#prefix'] = "\n<!--[if gt IE 8]><!-->\n";
$expected['#suffix'] = "<!--<![endif]-->\n";
$tags[] = array($element, $expected);
return $tags;
}
}
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