Reduce preprocess hooks usage by adding add_class() & set_attributes() filters

Created on 23 September 2022, about 2 years ago
Updated 23 June 2023, over 1 year ago

Problem/Motivation

We use preprocess hooks in UI Suite themes and it appears we are always doing the 2 same stuff:

Preprocess are PHP function and are not expected to be written by the front developer, so they reduce the ownership of the design system maintainer, so let's remove them.

Proposed resolution for: the theme base path

We can take inspiration from ECA module and its use of tokens: https://www.drupal.org/project/eca/issues/3278918 โ†’
However, there is token to get theme path in Drupal Core and we may need take inspiration from: https://www.drupal.org/project/theme_filter โ†’

card:
  label: Card
  fields:
    media:
      label: Media
      preview:
        - type: html_tag
          tag: img
          attributes:
            src: "[path-to-theme:absolute]assets/card.png"

Proposed resolution for: adding attributes to a children component

It may be managed by โœจ Create twig filters: |add_class and |set_attribute Fixed so we need to evaluate those new filters.

We can also introduce new properties (add_class, set_attribute...) and namespacing in pattern definitions. Example:

card:
  label: Card
  fields:
    action_buttons:
      type: render
      add_class: 
      - mdc-card__action
      set_attribute: 
        role: action
      preview:
        - type: "pattern_preview"
          id: "button"
        - type: "pattern_preview"
          id: "button"
 
โœจ Feature request
Status

Fixed

Version

2.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

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris

    Evaluation of the 2 filters proposed by โœจ Create twig filters: |add_class and |set_attribute Fixed and planned for Drupal 10.1.

    They work correctly only when the twig variable is a single render array, and not a list of render arrays (which is a very common use case).

    So, I will propose un patch for https://git.drupalcode.org/issue/drupal-3301853/-/blob/3301853-create-tw... to loop on array items is the array is a list:

      public function addClass(array $element, ...$classes): array {
        if (array_is_list($element)) {
          foreach ($element as $index => $item) {
            $element[$index] = $this->addClass($item, $classes);
          }
          return $element;
        }
        $attributes = new Attribute($element['#attributes'] ?? []);
        $attributes->addClass(...$classes);
        $element['#attributes'] = $attributes->toArray();
    
        // Make sure element gets rendered again.
        unset($element['#printed']);
    
        return $element;
      }
    
      public function setAttribute(array $element, string $name, mixed $value = NULL): array {
        if (array_is_list($element)) {
          foreach ($element as $index => $item) {
            $element[$index] = $this->setAttribute($item, $name, $value);
          }
          return $element;
        }
        $element['#attributes'] = AttributeHelper::mergeCollections(
          $element['#attributes'] ?? [],
          new Attribute([$name => $value])
        );
    
        // Make sure element gets rendered again.
        unset($element['#printed']);
    
        return $element;
      }
    

    If this patch is accepted, there is nothing to do on ui_patterns side.

    For example, for https://git.drupalcode.org/project/ui_suite_bootstrap/-/tree/4.0.x/templ... we can replace the preprocess by the add_class filter:

    <figure{{ attributes.addClass('figure') }}>
      {{ image|add_class(figure-img) }}
      <figcaption class="figure-caption">
        {{ caption }}
      </figcaption>
    </figure>
    
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris

    Maybe the 2 new Drupal 10.1 Twig filters are not such a good idea, even if our patch is accepted.

    A lot of filters are "typed": they must be applied on specific types. Examples:

    • capitalize on string variables
    • column on array variables
    • abs on number variables

    We tests several Twig filters on UI Patterns fields ("slots"), applying them to the wrong type:

    • either it looks weird. Example: clean_class on a render array
    • either it makes a fatal PHP error. Example: column on a string

    We are fortunate the UI Suite themes are currently only using filters on settings ("props"),not on "fields" ("props")
    Except DSFR, but there is a ticket about that: ๐Ÿ› [beta1] โš ๏ธ Fix compatibility with layout builder Fixed

    We can therefore promote this ("no filters on slots") as an official good practice

    So, let's explore the new YAML definitions properties (add_class, set_attribute...) again.

  • @pdureau opened merge request.
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris

    First MR: https://git.drupalcode.org/project/ui_patterns/-/merge_requests/22

    It is just an humble proposal for now. Let's discuss.

    Wih this MR, its is possible to replace an hook like ui_suite_bootstrap_preprocess_pattern_figure by :

    figure:
      label: "Figure"
      description: "Anytime you need to display a piece of contentโ€”like an image with an optional caption, consider using figure. https://getbootstrap.com/docs/4.6/content/figures/"
      fields:
        image:
          type: "render"
          label: "Image"
          description: "Figure image"
          add_class:
           - 'figure-img'
          preview:
            - theme: "image"
              uri: assets/figure-image.png
        caption:
          type: "render"
          label: "Caption"
          description: "A caption under the image."
          preview: "A caption for the above image."
    
  • Status changed to Needs review over 1 year ago
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris

    Feel free to share feedbacks

  • Status changed to Needs work over 1 year ago
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris

    Because we are considering filters on slots again in โœจ Make the Twig loops safer Postponed we can propsoe a Twig filrer instead of altering the render element.

    Instead of relying on โœจ Create twig filters: |add_class and |set_attribute Fixed which will have those issues:

    • the filters donโ€™t loop, Pierre has proposed a patch but it seesm it will not be accepted.
    • they accept only array, so they break on strings, so they are not suitable for slots.
    • the filters will not be available on D9

    We implement our own versions in UI Patterns:

    • Testing if array and if list (with PHP 7.4 compatibility)
    • Overriding the Drupal core implementation
    • Compatible with the Drupal core implementation

    So :

    • We donโ€™t need to introduce new pattern fields properties and the template owner keep the control
    • We will be compatible with D9
  • @pdureau opened merge request.
  • Assigned to Grimreaper
  • Status changed to Needs review over 1 year ago
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris

    New MR: https://git.drupalcode.org/project/ui_patterns/-/merge_requests/25

    First commit, 1e4d214a3d9 : Add set_attribute and add_class filters, exactly as proposed in โœจ Create twig filters: |add_class and |set_attribute Fixed , included the unit tests.

    Second commit, 7874e0c5e90 : with expected changes for UI Patterns:

    • Slot friendly: the filter loop on lists and don't break on scalars
    • Override the Drupal core implementation when both are present, and stay compatible with it

    Compliant with feedbacks from Grimpreaper:

    • Compatible with PHP 8.0 and Drupal 9
    • Moved to a trait so it can be used in custom code or somewhere else.

    This MR replace the one from comment #10, and its branch ("3311480-remove-the-need") replace "pierre_proposal" branch.

  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris

    I rename the issue, because we haven't deal with the theme base path subject for a long time. Let's create a new specific issue if there are some progress.

  • Assigned to pdureau
  • Status changed to Needs work over 1 year ago
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance Grimreaper France ๐Ÿ‡ซ๐Ÿ‡ท

    @pdureau thanks for your work in this issue.

    Maybe an additional test to add and some minor comments to update.

    For the PHPCS part, I will do it when the other review points are done.

  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    72 pass
  • Assigned to Grimreaper
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris

    Done.

    2 new tests:

    $ ../vendor/bin/phpunit -c core/ modules/local/ui_patterns-3311480/tests/src/Unit/Template/TwigExtensionTest.php 
    Testing Drupal\Tests\ui_patterns\Unit\Template\TwigExtensionTest
    ..........                                                        10 / 10 (100%)
    Time: 00:00.012, Memory: 10.00 MB
    

    PHPCS is OK:

    $ ../vendor/bin/phpcs --standard=Drupal modules/local/ui_patterns-3311480/tests/src/
    $ ../vendor/bin/phpcs --standard=Drupal modules/local/ui_patterns-3311480/src/Template/
    
  • Status changed to Needs review over 1 year ago
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris
  • Assigned to pdureau
  • Status changed to Needs work over 1 year ago
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance Grimreaper France ๐Ÿ‡ซ๐Ÿ‡ท
  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    72 pass
  • Assigned to Grimreaper
  • Status changed to Needs review over 1 year ago
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris

    Finally, I have removed TwigExtensionTestString which is not used for testing.

    Tests are still OK:

    $ ../vendor/bin/phpunit -c core/ modules/local/ui_patterns-3311480/tests/src/Unit/Template/TwigExtensionTest.php 
    Testing Drupal\Tests\ui_patterns\Unit\Template\TwigExtensionTest
    ..........                                                        10 / 10 (100%)
    Time: 00:00.012, Memory: 10.00 MB
    

    PHPCS is still OK:

    $ ../vendor/bin/phpcs --standard=Drupal modules/local/ui_patterns-3311480/tests/src/
    $ ../vendor/bin/phpcs --standard=Drupal modules/local/ui_patterns-3311480/src/Template/
    
  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    72 pass
  • Assigned to pdureau
  • Status changed to Needs work over 1 year ago
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance Grimreaper France ๐Ÿ‡ซ๐Ÿ‡ท

    Some review comments remains.

  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    72 pass
  • Assigned to Grimreaper
  • Status changed to Needs review over 1 year ago
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance pdureau Paris
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance Grimreaper France ๐Ÿ‡ซ๐Ÿ‡ท

    Merged on 8.x-1.x. Cherry-picking on 2.0.x.

  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    60 pass
  • @grimreaper opened merge request.
  • Issue was unassigned.
  • Status changed to Fixed over 1 year ago
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance duaelfr Montpellier, France
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance Grimreaper France ๐Ÿ‡ซ๐Ÿ‡ท

    Merged on 2.0.x too.

  • Automatically closed - issue fixed for 2 weeks with no activity.

  • Status changed to Fixed over 1 year ago
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia Sharique

    Documentation and examples update is required for this.

Production build 0.71.5 2024