Issue #3093577 by dww, Krzysztof Domański, lauriii, Charlie ChX Negyesi, Fabianx: Let Twig without() filter take both arrays and strings as arguments

(cherry picked from commit 12dcba2532)
merge-requests/64/head
Alex Pott 2020-01-13 11:43:05 +00:00
parent 9f847ae766
commit d6ee61eaeb
No known key found for this signature in database
GPG Key ID: 31905460D4A69276
3 changed files with 30 additions and 6 deletions

View File

@ -651,8 +651,9 @@ class TwigExtension extends \Twig_Extension {
*
* @param array|object $element
* The parent renderable array to exclude the child items.
* @param string[] ...
* The string keys of $element to prevent printing.
* @param string[]|string ...
* The string keys of $element to prevent printing. Arguments can include
* string keys directly, or arrays of string keys to hide.
*
* @return array
* The filtered renderable array.
@ -666,10 +667,12 @@ class TwigExtension extends \Twig_Extension {
}
$args = func_get_args();
unset($args[0]);
foreach ($args as $arg) {
if (isset($filtered_element[$arg])) {
unset($filtered_element[$arg]);
}
// Since the remaining arguments can be a mix of arrays and strings, we use
// some native PHP iterator classes to allow us to recursively iterate over
// everything in a single pass.
$iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($args));
foreach ($iterator as $key) {
unset($filtered_element[$key]);
}
return $filtered_element;
}

View File

@ -19,6 +19,11 @@
<div><span {{ attributes.checked }}{{ attributes|without('checked') }}>Without boolean attribute.</span></div>
<div><span data-id="{{ attributes.id }}"{{ attributes|without('id') }}>Without string attribute.</span></div>
<div><span{{ attributes|without('id', 'class') }}>Without id and class attributes.</span></div>
{% set without_args = ['id', 'class'] %}
<div><span{{ attributes|without(without_args) }}>Without id and class attributes via an array.</span></div>
<div><span{{ attributes|without(without_args, 'checked') }}>Without any attributes via mixed array and string.</span></div>
<div><span{{ attributes|without('checked', without_args) }}>Without any attributes via mixed string then array.</span></div>
<div><span{{ attributes|without(without_args, ['id', 'checked']) }}>Without any attributes with duplicate "id" key.</span></div>
<div><span{{ attributes }}>All attributes again.</span></div>
<div id="{{ 'quotes Here!'|clean_id }}"><span class="{{ 'Gray like a bunny!'|clean_class }} {{ 'BEM__ized--Top Feature'|clean_class }}" id="{{ 'quotes Here!'|clean_id }}">ID and class. Having the same ID twice is not valid markup but we want to make sure the filter doesn't use \Drupal\Component\Utility\Html::getUniqueId().</span></div>
<div><strong>Rendered author string length:</strong> {{ quote.author|render|length }}.</div>

View File

@ -102,6 +102,22 @@ class TwigFilterTest extends KernelTestBase {
'expected' => '<div><span checked>Without id and class attributes.</span></div>',
'message' => 'Attributes printed without id and class attributes.',
],
[
'expected' => '<div><span checked>Without id and class attributes via an array.</span></div>',
'message' => 'Attributes printed without an array of things (id and class).',
],
[
'expected' => '<div><span>Without any attributes via mixed array and string.</span></div>',
'message' => 'Attributes printed without an array of keys then a string key.',
],
[
'expected' => '<div><span>Without any attributes via mixed string then array.</span></div>',
'message' => 'Attributes printed without a string key then an array of keys.',
],
[
'expected' => '<div><span>Without any attributes with duplicate "id" key.</span></div>',
'message' => 'Attributes printed without two arrays of keys with a duplicate key present in both arrays.',
],
[
'expected' => '<div><span id="quotes" checked class="red green blue">All attributes again.</span></div>',
'message' => 'All attributes printed again.',