[2.0.0-beta2] Attributes normalization

Created on 26 August 2024, 21 days ago
Updated 15 September 2024, 1 day ago

Problem/Motivation

ComponentElementAlter is looping on each prop and applying the normalization:

    foreach ($element["#props"] as $prop_id => $prop) {
      if (!isset($props[$prop_id])) {
        continue;
      }
      $prop_type = $props[$prop_id]['ui_patterns']['type_definition'];
      $element["#props"][$prop_id] = $prop_type->normalize($prop);
    }

However, attributes is not processed when not defined in the component definition (which is the usual case, because it is magically added by SDC).

Like variant with VariantPropType, attributes has always the same type: AttributesPropType

Proposed resolution

2 proposals

Early alteration in ComponentPluginManager::annotateProps()

$definition['props']['properties']['attributes'] = $this->buildAttributesProp($definition);

Doing that, attributes will be considered as a normal prop, automatically show up everywhere there are props (component library, form builder...). A bit like what variant do.

This will also fix πŸ“Œ [2.0.0-beta2] Expose default attributes prop in forms Closed: duplicate

(If we hide it from component library in this MR, let's also do that for "variant")

Late alteration in ComponentElementAlter

Tested:

    if (isset($element["#props"]["attributes"])) {
      $element["#props"]["attributes"] = AttributesPropType::normalize($element["#props"]["attributes"]);
    }     

Doing that, we keep attributes special and we only alter the specific thing we need to fix.

πŸ“Œ Task
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

Merge Requests

Comments & Activities

  • Issue created by @pdureau
  • Issue was unassigned.
  • Status changed to Needs review 20 days ago
  • πŸ‡«πŸ‡·France G4MBINI BΓ¨gles
  • πŸ‡«πŸ‡·France Grimreaper France πŸ‡«πŸ‡·
  • πŸ‡«πŸ‡·France pdureau Paris

    Let's do the early alteration in ComponentPluginManager::annotateProps().

    πŸ“Œ [2.0.0-beta2] Expose default attributes prop in forms Closed: duplicate is now obsolete and can be closed

  • Assigned to pdureau
  • Status changed to Needs work 18 days ago
  • πŸ‡«πŸ‡·France pdureau Paris

    We have this PHP Unit error in the pipeline: Drupal\Core\Render\Component\Exception\InvalidComponentException: [attributes] String value found, but an object is required

    It may be related to πŸ› [2.0.0-beta2] Check PropTypeInterface::normalize() Active

  • πŸ‡«πŸ‡·France pdureau Paris

    Checked with Mikael

    It is SDC's ComponentValidator::validateProps() which is calling a dependency method which is executing json_encode() which is casting the attribute object into a string.

    So, we may need 2 different methods:

    • keep PropTypeInterface::normalize() before the ComponentValidator, which is always returning data conform to JSON Schema, so which is keeping the associative array for attributes
    • add a new method (PropTypeInterface::preprocess() ?) in between the ComponentValidator and the injection to Twig template, which is instantiating the Attribute object

    Unfortunately, ComponentValidator may be executed very late, from a Twig extension, so we may need to add our own Twig extension to be executed after.

  • πŸ‡«πŸ‡·France pdureau Paris

    SDC implementation looks a bit messy IMHO:

    ComponentsTwigExtension is adding 2 twig functions:

    • add_component_context which is adding the attribute Attribute object if missing
    • validate_component_props which is executing the JSON schema validator

    Why are they Twig functions instead of living in the rendering process? Who will ever use them in the template? I don't know

    Then, ComponentNodeVisitor is ever more problematic, because it prints those Twig functions on every template, which will be executed on rendering:

    • attach_library
    • add_component_context
    • validate_component_props

    And this is making all the mess. What we are paying here is the cost of the use of "template to template" Twig functions or tags (include and embed) instead of a dedicated mechanism which is loading the Render API and leveraging the render element. For example, attach_library is used here because #attached is not executed.

    All this part of SDC would be to be removed and redone, but it will take time.

    What can we do now, in this ticket, to overcome this?

  • πŸ‡«πŸ‡·France pdureau Paris

    DRAFT - WORK IN PROGRESS: WILL BE UPDATED WITH BETTER INFO

    So, let's see every possible situation.

    No attribute in template context

    No attribute in JSON schema

    1. add_component_context is adding an Attribute object
    2. validate_component_props is skipping the validation, so it is OK βœ…

    Attribute as a namespaced PHP class in JSON schema

    The same:

    1. add_component_context is adding an Attribute object
    2. validate_component_props is skipping the validation, so it is OK βœ…

    Attribute as a proper JSON schema definition (the UI Patterns 2.x way)

    1. add_component_context is adding an Attribute object
    2. validate_component_props is doing the validation, and it is supposed to be KO ❌

    attribute as a PHP object in template context

    No attribute in JSON schema

    1. add_component_context is altering the Attribute object
    2. validate_component_props is skipping the validation, so it is OK βœ…

    attribute as a namespaced PHP class in JSON schema

    The same:

    1. add_component_context is altering the Attribute object
    2. validate_component_props is skipping the validation, so it is OK βœ…

    Attribute as a proper JSON schema definition (the UI Patterns 2.x way)

    1. add_component_context is doing nothing
    2. validate_component_props is doing the validation, because a ❌

    attribute as a PHP array in template context

    This will be the situation if we remove AttributePropType::normalize()

    No attribute in JSON schema

    1. add_component_context is doing nothing
    2. validate_component_props is skipping the validation, so it is OK βœ…

    Attribute as a namespaced PHP class in JSON schema

    The same:

    1. add_component_context is doing nothing
    2. validate_component_props is skipping the validation, so it is OK βœ…

    Attribute as a proper JSON schema definition (the UI Patterns 2.x way)

    1. add_component_context is doing nothing
    2. validate_component_props is doing the validation, and it i supposed to be KO because a ❌
  • πŸ‡«πŸ‡·France pdureau Paris
  • Issue was unassigned.
  • Status changed to Needs review 10 days ago
  • πŸ‡«πŸ‡·France pdureau Paris
  • Status changed to Fixed 7 days ago
  • πŸ‡«πŸ‡·France pdureau Paris
  • Status changed to Fixed 1 day ago
  • πŸ‡«πŸ‡·France pdureau Paris
Production build 0.71.5 2024