Problem/Motivation
Twig's built-in merge filter does a shallow merge which makes it very difficult to alter a deeply-nested element in a render array. (You have to do repeated set statements with merge filters for each level of the nesting.)
Component module's set and add filters were supposed to fix this problem. And they do, except for one problem. You can't replace a target that is an array, the new array gets recursively merged with the targeted array. We even mention that the add filter is better at merging numeric arrays, but we forgot about the use case of replacing an array.
There is only one work-around right now which I just discovered. Set the original array to null (replace the array with a non-array) and then set a new array at that same location.
{% set item = item|set({
'content': {
'children': {
'#items': null,
},
},
}) %}
{% set item = item|set({
'content': {
'children': {
'#items': new_child_items,
},
},
}) %}
This is awkward.
Proposed resolution
Rename the current set implementation to recursive_merge And create a new set filter that uses the same syntax as the add filter.
{% set item = item|set('content.children.#items', new_child_items) %}
API changes
For 2.x and 3.x, make the set filter automatically call the recursive_merge filter if given an array for its argument. Or use the new set filter if given a string and a value. The 3.x branch can log a deprecation warning. And we can remove this backwards-compatibility in 4.x.
Issue fork components-3209440
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
johnalbinComment #5
johnalbinComment #6
johnalbinComment #8
johnalbinComment #10
johnalbinComment #11
johnalbin