Remove the use of layout.getRegionNames() method in templates

Created on 21 January 2023, over 1 year ago
Updated 15 March 2024, 4 months ago

Problem/Motivation

Many themes using layout options are using a layout object and the getRegionNames method:

{% for region in layout.getRegionNames %}

Examples:

It is not a good practice to manipulate PHP objects in a Twig templates because:

  • PHP objects can have states and be business related. Templates are stateless and business agnostic.
  • Templates must be reproductible. The same data context must always render the same results.
  • Those methods can do harmful actions, which defeat the security purpose of Twig templating

Proposed resolution

Investigate an other way of looping the layout's regions.

Maybe, no change will be needed on the layout_options side.

πŸ“Œ Task
Status

Postponed

Version

1.1

Component

Code

Created by

πŸ‡«πŸ‡·France pdureau Paris

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

Comments & Activities

  • Issue created by @pdureau
  • πŸ‡«πŸ‡·France Grimreaper France πŸ‡«πŸ‡·
  • πŸ‡«πŸ‡·France pdureau Paris

    This issue is already present in Drupal Core: https://git.drupalcode.org/project/drupal/-/blob/10.1.x/core/modules/lay...

    {%
      set classes = [
        'layout',
        'layout--' ~ layout.id|clean_class,
      ]
    %}
    {% if content %}
      <div{{ attributes.addClass(classes) }}>
        {% for region in layout.getRegionNames %}
          {% if content[region] %}
            <div {{ region_attributes[region].addClass('layout__region', 'layout__region--' ~ region|clean_class) }}>
              {{ content[region] }}
            </div>
          {% endif %}
        {% endfor %}
      </div>
    {% endif %}

    But only for the default layout template, with "dynamic" regions.

    The other templates don't loop on regions, they "statically print" each region in the Twig code, avoiding to use a PHP object and its method.

    Example: https://git.drupalcode.org/project/drupal/-/blob/10.1.x/core/modules/lay...

      <div{{ attributes.addClass(classes) }}>
    ...
        {% if content.first %}
          <div {{ region_attributes.first.addClass('layout__region', 'layout__region--first') }}>
            {{ content.first }}
          </div>
        {% endif %}
    
        {% if content.second %}
          <div {{ region_attributes.second.addClass('layout__region', 'layout__region--second') }}>
            {{ content.second }}
          </div>
        {% endif %}
    ...
      </div>
    

    So, this may be the solution.

  • πŸ‡«πŸ‡·France Grimreaper France πŸ‡«πŸ‡·

    Hi,

    Ok for this solution.

    In this case this would mean that in the themes we would have 4 templates instead of one for the layout 1, 2, 3, 4 columns, maybe with some duplicated code snippet between the templates but that is ok.

    Maybe it will also improve the readability for newcomers in those themes and not having the habits of layouts and Layout Options.

  • Issue was unassigned.
  • Status changed to Postponed 4 months ago
  • πŸ‡«πŸ‡·France pdureau Paris

    If we merge layout options into the upcoming UI Patterns 2.x module, we will not need to do that anymore.

Production build 0.69.0 2024