diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php
index b14653b8bd7..9694d00556f 100644
--- a/core/lib/Drupal/Core/Template/TwigExtension.php
+++ b/core/lib/Drupal/Core/Template/TwigExtension.php
@@ -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;
}
diff --git a/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.filter.html.twig b/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.filter.html.twig
index ea0b7afd7b0..3b312389215 100644
--- a/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.filter.html.twig
+++ b/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.filter.html.twig
@@ -19,6 +19,11 @@
Without boolean attribute.
Without string attribute.
Without id and class attributes.
+{% set without_args = ['id', 'class'] %}
+Without id and class attributes via an array.
+Without any attributes via mixed array and string.
+Without any attributes via mixed string then array.
+Without any attributes with duplicate "id" key.
All attributes again.
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().
Rendered author string length: {{ quote.author|render|length }}.
diff --git a/core/modules/system/tests/src/Kernel/Theme/TwigFilterTest.php b/core/modules/system/tests/src/Kernel/Theme/TwigFilterTest.php
index 60951bafcf4..00bb8350c8d 100644
--- a/core/modules/system/tests/src/Kernel/Theme/TwigFilterTest.php
+++ b/core/modules/system/tests/src/Kernel/Theme/TwigFilterTest.php
@@ -102,6 +102,22 @@ class TwigFilterTest extends KernelTestBase {
'expected' => 'Without id and class attributes.
',
'message' => 'Attributes printed without id and class attributes.',
],
+ [
+ 'expected' => 'Without id and class attributes via an array.
',
+ 'message' => 'Attributes printed without an array of things (id and class).',
+ ],
+ [
+ 'expected' => 'Without any attributes via mixed array and string.
',
+ 'message' => 'Attributes printed without an array of keys then a string key.',
+ ],
+ [
+ 'expected' => 'Without any attributes via mixed string then array.
',
+ 'message' => 'Attributes printed without a string key then an array of keys.',
+ ],
+ [
+ 'expected' => 'Without any attributes with duplicate "id" key.
',
+ 'message' => 'Attributes printed without two arrays of keys with a duplicate key present in both arrays.',
+ ],
[
'expected' => 'All attributes again.
',
'message' => 'All attributes printed again.',