Problem/Motivation
Except for "standard" variables like attributes, content_attributes... it is not easy to know if a variable value is already an Attribute object or a still a mapping to convert with create_attribute().
This is an issue because it is very easy to trigger errors:
- if we put an attribute object in the constructor of
create_attribute()
function, a WSOD TypeError error is raised. - if we print a mapping, we got an user error: "invalid render array key in Drupal\Core\Render\Element::children()"
- if we execute a method on a mapping, nothing is happening (silent error)
This can be avoided by ugly (and often forgotten) workarounds like this one:{% set link_attributes = link_attributes.storage() is defined ? link_attributes : create_attribute(link_attributes) %}
So, we need to find a way of avoiding any error.
Steps to reproduce
Twig code: {{ create_attribute(create_attribute()) }}
Result: TypeError: "Drupal\Core\Template\TwigExtension::createAttribute(): Argument #1 ($attributes) must be of type array, Drupal\Core\Template\Attribute given
Proposed resolution
Something like that (non tested code draft):
/**
* Creates an Attribute object.
*
* @param Attribute|array $attributes
* (optional) An existing attribute object. Or an associative array of key-value pairs to be converted to
* HTML attributes.
*
* @return \Drupal\Core\Template\Attribute
* An attributes object that has the given attributes.
*/
public function createAttribute(Attribute|array $attributes = []) {
if (\is_array($attributes)) {
return new Attribute($attributes);
}
return new $attributes;
}
With maybe some changes to do in TwigExtensionTest.
User interface changes
No
API changes
Nothing breakable
Data model changes
No