ec-europa / atomium

The very base theme
https://drupal.org/project/atomium
European Union Public License 1.1
9 stars 5 forks source link

Attributes->setAttribute(*, *, FALSE) does not correctly unpack nested arrays. #174

Open donquixote opened 6 years ago

donquixote commented 6 years ago

Symptoms

In the original Attributes class: Attributes->setAttribute(, , TRUE) does unpack nested arrays. Attributes->setAttribute(, , FALSE) does not, or not in the same way. Attributes->offsetSet(, ) also does not correctly unpack nested arrays.

$attributes = new Attributes();
$attributes->offsetSet('name', [1, ['two', [3, 'x' => [4]]]]);
assert(' name="3 4"' === $attributes->__toString());

How does it happen?

In the original Attributes class, the nested values are, at first, stored directly in the $this->storage variable.

Then $this->getStorage() processes the nested values, using this code:

$value_iterator = new \RecursiveIteratorIterator(
  new \RecursiveArrayIterator((array) $member)
);
$member = array_values(array_unique(iterator_to_array($value_iterator)));

The problem here is iterator_to_array() combined with the recursive iterators on this specific array structure.

The recursive iterators return multiple values WITH THE SAME KEY.

Basically they behave like this:

yield 0 => 1;
yield 0 => 'two';
yield 0 => 3;
yield 'x' => 4;

The first 3 entries all overwrite one another.

Solution

Use iterator_to_array(*, FALSE); to reindex the array.

drupol commented 6 years ago

I agree with the solution.