[later phase] Support matching `{type: array, …}` prop shapes

Created on 13 August 2024, 7 months ago

Overview

Quoting \Drupal\experience_builder\SdcPropToFieldTypePropMatcher::iterateJsonSchema():

…
      throw new \LogicException('Support for "array" props is not yet implemented.');
…

Proposed resolution

Support it.

User interface changes

TBD

πŸ“Œ Task
Status

Postponed

Component

Page builder

Created by

πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

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

Merge Requests

Comments & Activities

  • Issue created by @wim leers
  • πŸ‡ΊπŸ‡ΈUnited States Kristen Pol Santa Cruz, CA, USA

    To be clear, this is so you can have a multivalue prop? Like multiple links?

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί
  • πŸ‡ΊπŸ‡ΈUnited States Kristen Pol Santa Cruz, CA, USA

    Gotcha πŸ‘ thanks for the clarification

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    While this does need design, I think we can lay the shape matching foundations. A conversation with @catch about ✨ JSON-based data storage proposal for component-based page building Active yesterday made me realize that:

    1. this is more within reach since πŸ“Œ Support complex SDC prop shapes: introduce (Storable)PropShape to compute field type storage settings Fixed than I thought
    2. having this working for at least type: array, items: integer and type: array, items: string, maxItems: 2 would actually help the discussion over at #3440578
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    wim leers β†’ changed the visibility of the branch 3467870-support-generating-not to hidden.

  • πŸ‡¬πŸ‡§United Kingdom catch
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    I've made progress today on updating FieldTypePropExpression, StaticPropSource and Evaluator to support type: array.

    How?

    By changing StaticPropSource to not be required to contain a FieldItemInterface (i.e. a single field delta), but instead allowing a FieldItemListInterface too (i.e. multiple field deltas).

    It's too unorganized right now to push; expect an update tomorrow 😊

    Thanks @catch for nudging me in this direction πŸ˜„

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Just pushed initial test coverage in PropSourceTest::testStaticPropSource(), to test it with multiple cardinality:

        // A simple (expression targeting a simple prop) array example (with
        // cardinality specified, rather than the default of `cardinality=1`).
        $simple_array_example = StaticPropSource::parse([
          'sourceType' => 'static:field_item:integer',
          'sourceTypeSettings' => [
            'storage' => [
              'cardinality' => 5,
            ],
          ],
          'value' => [
            20,
            06,
            1,
            88,
            92,
          ],
          'expression' => 'β„ΉοΈŽinteger␟value',
        ]);
    

    It should now fail like this:

    1) Drupal\Tests\experience_builder\Kernel\PropSourceTest::testStaticPropSource
    Failed asserting that two strings are identical.
    --- Expected
    +++ Actual
    @@ @@
    -'{"sourceType":"static:field_item:integer","value":[20,6,1,88,92],"expression":"β„ΉοΈŽinteger␟value","sourceTypeSettings":{"storage":{"cardinality":5}}}'
    +'{"sourceType":"static:field_item:integer","value":null,"expression":"β„ΉοΈŽinteger␟value","sourceTypeSettings":{"storage":{"cardinality":5}}}'
    
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Yay, from:

    1) Drupal\Tests\experience_builder\Kernel\HookStoragePropAlterTest::testPropShapesYieldWorkingStaticPropSources
    Sample value 88 generated by field type integer for type=array&items[type]=integer is invalid!
    Failed asserting that two arrays are identical.
    --- Expected
    +++ Actual
    @@ @@
    -Array &0 ()
    +Array &0 (
    +    0 => Array &1 (
    +        'property' => 'ds032jpb'
    +        'pointer' => '/ds032jpb'
    +        'message' => 'Integer value found, but an array is required'
    +        'constraint' => 'type'
    +        'context' => 1
    +    )
    +)
    

    (IOW: a single integer is passed, when an array of integers is needed)

    to … that test passing πŸ€“

    More coming.

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    I was chasing a heisenbug for a few hours today. I then eventually found the root cause.

    It happens only for a list_string field type with one of its allowed values the empty string:

            [
              'allowed_values' => [
                ['value' => '', 'label' => ''],
                ['value' => '_blank', 'label' => '_blank'],
              ],
            ]
    

    … because somewhere '' gets cast to NULL πŸ˜…

    XB's tests generate a random value to verify the static prop source works end-to-end, and due to the changes in this MR (introducing the use of FieldItemList and hence calling FieldItemList::isEmpty(), which we didn't call before), this:

    now resulted in

    which is obviously wrong, but count() works fine:

    … this is valid configuration for the list_string field type: its config schema type field.storage_settings.list_string does not forbid this.

    But the UI does forbid it:

    which causes:

    So probably a fixed ListStringItem::isEmpty() that is more strict than the inherited \Drupal\options\Plugin\Field\FieldType\ListItemBase::isEmpty()'s implementation:

      public function isEmpty() {
        return empty($this->value) && (string) $this->value !== '0';
      }
    

    … would not even be accepted by Drupal core maintainers! 😬

    Unfortunately, I lost hours today because of this. If there was config schema validation in place, this would've been sorted out in minutes. 😭

    So: not filing a Drupal core issue, ← I can't justify that, because it's a valid use case for SDC, and we can make it work.

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    To make #13 discoverable.

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    I actually think that matching field instances should be possible too, so broadening the issue title/scope πŸ€“

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    type: array breakthrough β€” it’s starting to work end-to-end! πŸ˜„

    Soon: πŸ–ΌοΈπŸ–ΌοΈπŸ–ΌοΈπŸ–ΌοΈ aka image galleries!

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    100% of remaining test failures are due to not yet supporting finding DynamicPropSources (aka existing entity field instances) for the type: array prop shape.

    That's why I widened the scope in #15 β€” because I first thought it'd be an order of magnitude harder than supporting StaticPropSources (which is the only thing the XB UI currently supports). But it'd be a shame to let that part "fall behind", so trying to tackle this while my head is in this space 😊

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    1% of remaining test failures are in the Cypress E2E tests, which makes sense: the Redux integration has only been built with single-cardinality props in mind, that's changing here.

    IOW: having this in also empowers 🌱 [META] Redux sync on ALL prop types, not just ones with a single [value] property Active to design a more complete solution.

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Merged in all upstream changes.

    We may also need to consider this in πŸ› Some components cannot be used in XB because UI prevents SDC props being named `name` Active .

  • πŸ‡ΊπŸ‡ΈUnited States tedbow Ithaca, NY, USA

    going to review

  • πŸ‡ΊπŸ‡ΈUnited States tedbow Ithaca, NY, USA

    @Wim Leers the direction looks good to me!

  • Assigned to wim leers
  • Status changed to Needs work about 2 months ago
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί
Production build 0.71.5 2024