Empty field values when not renderable

Created on 26 August 2023, 10 months ago
Updated 5 March 2024, 4 months ago

Problem/Motivation

There is a huge issue in Drupal about evaluating a render array as true or false from a Twig template: 🌱 [meta] Themes improperly check renderable arrays when determining visibility Needs work
Very annoying but, after 13 years, still no fix.

UI Patterns users are sometimes confronted to this issue: 🐛 Drupal entities containing optional or multiple fields do not render patterns correctly Closed: won't fix
It looks very hard to fix at a Drupal level, but we are lucky it may be doable at UI Patterns level.

Steps to reproduce

Let's do some tests on Drupal 10.1.1 with this slot:

{% if description %}<p class="fr-tile__desc">{{ description }}</p>{% endif %}

From https://git.drupalcode.org/project/ui_suite_dsfr/-/blob/1.0.x/templates/...

We expect description to be false.

Test 1: empty array

$variables['description'] = [];

OK: description is false, because in PHP an empty array is false

Test 2: non renderable properties

$variables['description'] = [
  "#cache" => [
    "contexts" => [
      "user.permissions"
    ],
    "tags" => [],
    "max-age" => -1
  ]
]

KO: description is true

Test 3: non renderable properties wrapped in a sequence

$variables['description'] = [
 [
  "#cache" => [
    "contexts" => [
      "user.permissions"
    ],
    "tags" => [],
    "max-age" => -1
  ]
]
]

KO: description is true

Test 4: non renderable properties wrapped in a mapping

Layout Builder is sometimes wrapping the render array in a mapping where the key is the block UUID:

$variables['description'] = [
"cf124739-3274-41cc-829d-c3465ee4eaa5" => [
  "#cache" => [
    "contexts" => [
      "user.permissions"
    ],
    "tags" => [],
    "max-age" => -1
  ]
]
]

KO: description is true.

Test 5: empty mapping

$variables['description'] = [
    "whatever" => []
];

KO: description is true.

Proposed resolution

So, it may be fixable at UI Patterns level because:

  • we know which Twig variables are expecting a render array : fields ("slots") with an array
  • we know where to put the bubbled properties: the component render array

So, in Pattern::processFields() for each component slot:

  1. if the array is not a render array, do a recursive loop on items
  2. if the array is a render array where all the children are empty AND where all properties are non-printable or empty:
    • move the non-printable properties (#cache, #attached... what else?) to the component render element if they are bubbable
    • remove the non-printable properties (#weight... what else?) if they are not bubbable
  3. unset the keys of empty children & empty properties

Other tasks

Once fixed, share the solution with 🌱 [meta] Themes improperly check renderable arrays when determining visibility Needs work

Later, we will need to port this solution to UI Patterns 2. Hopefully, SDC allows ComponentElement to be overridden.

Feature request
Status

Active

Version

1.0

Component

Code

Created by

🇫🇷France pdureau Paris

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Production build 0.69.0 2024