Commit ae1a1d80 authored by catch's avatar catch

Issue #2336355 by alexpott, Cottser: Fixed Refactor Attribute rendering so...

Issue #2336355 by alexpott, Cottser: Fixed Refactor Attribute rendering so that class= is not printed.
parent 2f9c1bc3
...@@ -150,13 +150,9 @@ public function addClass() { ...@@ -150,13 +150,9 @@ public function addClass() {
if (isset($this->storage['class']) && $this->storage['class'] instanceOf AttributeArray) { if (isset($this->storage['class']) && $this->storage['class'] instanceOf AttributeArray) {
// Merge the values passed in from the class value array. // Merge the values passed in from the class value array.
$classes = array_merge($this->storage['class']->value(), $classes); $classes = array_merge($this->storage['class']->value(), $classes);
// Filter out any duplicate values.
$classes = array_unique($classes);
$this->storage['class']->exchangeArray($classes); $this->storage['class']->exchangeArray($classes);
} }
else { else {
// Filter out any duplicate values.
$classes = array_unique($classes);
$this->offsetSet('class', $classes); $this->offsetSet('class', $classes);
} }
} }
...@@ -184,8 +180,9 @@ public function removeClass() { ...@@ -184,8 +180,9 @@ public function removeClass() {
$classes = array_merge($classes, (array) $arg); $classes = array_merge($classes, (array) $arg);
} }
// Remove the values passed in from the value array. // Remove the values passed in from the value array. Use array_values() to
$classes = array_diff($this->storage['class']->value(), $classes); // ensure that the array index remains sequential.
$classes = array_values(array_diff($this->storage['class']->value(), $classes));
$this->storage['class']->exchangeArray($classes); $this->storage['class']->exchangeArray($classes);
} }
return $this; return $this;
......
...@@ -29,6 +29,14 @@ ...@@ -29,6 +29,14 @@
*/ */
class AttributeArray extends AttributeValueBase implements \ArrayAccess, \IteratorAggregate { class AttributeArray extends AttributeValueBase implements \ArrayAccess, \IteratorAggregate {
/**
* Ensures empty array as a result of array_filter will not print '$name=""'.
*
* @see \Drupal\Core\Template\AttributeArray::__toString()
* @see \Drupal\Core\Template\AttributeValueBase::render()
*/
const RENDER_EMPTY_ATTRIBUTE = FALSE;
/** /**
* Implements ArrayAccess::offsetGet(). * Implements ArrayAccess::offsetGet().
*/ */
...@@ -67,7 +75,7 @@ public function offsetExists($offset) { ...@@ -67,7 +75,7 @@ public function offsetExists($offset) {
*/ */
public function __toString() { public function __toString() {
// Filter out any empty values before printing. // Filter out any empty values before printing.
$this->value = array_filter($this->value); $this->value = array_unique(array_filter($this->value));
return String::checkPlain(implode(' ', $this->value)); return String::checkPlain(implode(' ', $this->value));
} }
......
...@@ -16,6 +16,13 @@ ...@@ -16,6 +16,13 @@
*/ */
abstract class AttributeValueBase { abstract class AttributeValueBase {
/**
* Renders '$name=""' if $value is an empty string.
*
* @see \Drupal\Core\Template\AttributeValueBase::render()
*/
const RENDER_EMPTY_ATTRIBUTE = TRUE;
/** /**
* The value itself. * The value itself.
* *
...@@ -48,8 +55,9 @@ public function __construct($name, $value) { ...@@ -48,8 +55,9 @@ public function __construct($name, $value) {
* The string representation of the attribute. * The string representation of the attribute.
*/ */
public function render() { public function render() {
if (isset($this->value)) { $value = (string) $this;
return String::checkPlain($this->name) . '="' . $this . '"'; if (isset($this->value) && static::RENDER_EMPTY_ATTRIBUTE || !empty($value)) {
return String::checkPlain($this->name) . '="' . $value . '"';
} }
} }
......
...@@ -69,6 +69,25 @@ public function testAddClasses() { ...@@ -69,6 +69,25 @@ public function testAddClasses() {
$attribute->addClass(); $attribute->addClass();
$this->assertEmpty($attribute['class']); $this->assertEmpty($attribute['class']);
// Test various permutations of adding values to empty Attribute objects.
foreach (array(NULL, FALSE, '', []) as $value) {
// Single value.
$attribute->addClass($value);
$this->assertEmpty((string) $attribute);
// Multiple values.
$attribute->addClass($value, $value);
$this->assertEmpty((string) $attribute);
// Single value in array.
$attribute->addClass([$value]);
$this->assertEmpty((string) $attribute);
// Single value in arrays.
$attribute->addClass([$value], [$value]);
$this->assertEmpty((string) $attribute);
}
// Add one class on empty attribute. // Add one class on empty attribute.
$attribute->addClass('banana'); $attribute->addClass('banana');
$this->assertArrayEquals(array('banana'), $attribute['class']->value()); $this->assertArrayEquals(array('banana'), $attribute['class']->value());
...@@ -87,7 +106,7 @@ public function testAddClasses() { ...@@ -87,7 +106,7 @@ public function testAddClasses() {
// Add an array of duplicate classes. // Add an array of duplicate classes.
$attribute->addClass(array('red', 'green', 'blue'), array('aa', 'aa', 'banana'), 'yy'); $attribute->addClass(array('red', 'green', 'blue'), array('aa', 'aa', 'banana'), 'yy');
$this->assertArrayEquals(array('banana', 'aa', 'xx', 'yy', 'red', 'green', 'blue'), $attribute['class']->value()); $this->assertEquals('banana aa xx yy red green blue', (string) $attribute['class']);
} }
/** /**
...@@ -95,7 +114,8 @@ public function testAddClasses() { ...@@ -95,7 +114,8 @@ public function testAddClasses() {
* @covers ::removeClass() * @covers ::removeClass()
*/ */
public function testRemoveClasses() { public function testRemoveClasses() {
$classes = array('example-class', 'aa', 'xx', 'yy', 'red', 'green', 'blue'); // Add duplicate class to ensure that both duplicates are removed.
$classes = array('example-class', 'aa', 'xx', 'yy', 'red', 'green', 'blue', 'red');
$attribute = new Attribute(array('class' => $classes)); $attribute = new Attribute(array('class' => $classes));
// Remove one class. // Remove one class.
...@@ -109,6 +129,15 @@ public function testRemoveClasses() { ...@@ -109,6 +129,15 @@ public function testRemoveClasses() {
// Remove an array of classes. // Remove an array of classes.
$attribute->removeClass(array('red', 'green', 'blue')); $attribute->removeClass(array('red', 'green', 'blue'));
$this->assertNotContains(array('red', 'green', 'blue'), $attribute['class']->value()); $this->assertNotContains(array('red', 'green', 'blue'), $attribute['class']->value());
// Remove a class that does not exist.
$attribute->removeClass('gg');
$this->assertNotContains(array('gg'), $attribute['class']->value());
// Test that the array index remains sequential.
$this->assertArrayEquals(array('aa'), $attribute['class']->value());
$attribute->removeClass('aa');
$this->assertEmpty((string) $attribute);
} }
/** /**
......
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