[later phase] Add support for matching+adapting existing field instances against complex SDC prop shapes like {type: string, enum: โ€ฆ}

Created on 20 June 2024, 5 months ago
Updated 25 July 2024, 4 months ago

Problem/Motivation

SdcPropToFieldTypePropMatcher was developed in https://git.drupalcode.org/project/experience_builder/-/tree/research__d... and was merged into 0.x as one of the starting points.

It proved matching SDC's prop's JSON schema shapes against Field Type's props + validation constraints was possible. But it didn't implement everything.

One example that was never implemented SDC props with type: string restricted to limited choices through enum:

    target:
      type: string
      title: Target
      enum:
        - ''
        - _blank

โ€” core/modules/system/tests/modules/sdc_test/components/my-cta/my-cta.component.yml

    iconType:
      type: string
      title: Icon Type
      enum:
        - power
        - like
        - external

Expected:

  1. This should match against the list_string field type (\Drupal\options\Plugin\Field\FieldType\ListStringItem), with precisely matching available options.
  2. This should be matched using
  3.         'โฟฒsdc_test_all_props:all-propsโŸtest-string-enum' => [
              'storage' => $all_string_storage_props,
              'format_any_prop' => [
                // @todo Make this work using the `list_string` field type
              ],
              'format_main_prop' => [],
              'instances' => [],
              'adapter_matches_field_type' => [],
              'adapter_matches_instance' => [],
            ],
    

    โ€” core/modules/system/tests/modules/sdc_test_replacements/components/my-button/my-button.component.yml

    Steps to reproduce

    Proposed resolution

    1. Match existing field instances (DynamicPropSource) using the Choice constraint? Note that \Drupal\experience_builder\SdcPropJsonSchemaType::toDataTypeShapeRequirements() already does this:
      โ€ฆ
            SdcPropJsonSchemaType::STRING => match (TRUE) {
              array_key_exists('enum', $schema) => new DataTypeShapeRequirement('Choice', [
                'choices' => $schema['enum'],
              ], NULL),
      โ€ฆ
      

      โ†’ what's missing is that the list_string field type does not yet generate the appropriate validation constraints! Even though It does implement \Drupal\options\Plugin\Field\FieldType\ListItemBase::getPossibleValues(), which is supported not by the Choice constraint, but by the AllowedValues constraint, which is almost the same. So perhaps the code above should be updated to match against that constraint instead?

    2. ๐Ÿ‘† This is the easy part. The harder part: ๐Ÿ‘‡
    3. Support generating a StaticPropSource for these, by updating the logic in SdcPropToFieldTypePropMatcher (put a breakpoint where it starts evaluating list_string inside ::findFieldTypeFormatCandidates()).
      This will need to dynamically generate the field settings that make the necessary allowed values/choices available.
    4. Propose a way to represent this โ€” probably you'll need something like:
      diff --git a/src/PropSource/StaticPropSource.php b/src/PropSource/StaticPropSource.php
      index 643f1b5..e00c561 100644
      --- a/src/PropSource/StaticPropSource.php
      +++ b/src/PropSource/StaticPropSource.php
      @@ -38,6 +38,9 @@ final class StaticPropSource extends PropSource {
           // @phpstan-ignore-next-line
           return json_encode([
             'sourceType' => 'static:' . $this->fieldItem->getDataDefinition()->getDataType(),
      +      'fieldTypeSettings' => [
      +        // @todo
      +      ],
             'expression' => (string) $this->expression,
           ], JSON_UNESCAPED_UNICODE);
         }
      @@ -52,6 +55,7 @@ final class StaticPropSource extends PropSource {
           $data_type = "field_item:" . $field_type;
           $field_item_definition = $typed_data_manager->createDataDefinition($data_type);
           assert($field_item_definition instanceof FieldItemDataDefinitionInterface);
      +    $field_item_definition->setSettings([/* @todo */]);
           $field_item = $typed_data_manager->createInstance($data_type, [
             'name' => NULL,
             'parent' => NULL,
      @@ -73,7 +77,7 @@ final class StaticPropSource extends PropSource {
          */
         public static function parse(array $sdc_prop_source): static {
           // `sourceType = static` requires a value and an expression to be specified.
      -    $missing = array_diff(['value', 'expression'], array_keys($sdc_prop_source));
      +    $missing = array_diff(['value', 'expression', 'fieldTypeSettings'], array_keys($sdc_prop_source));
           if (!empty($missing)) {
             throw new \LogicException(sprintf('Missing the keys %s.', implode(',', $missing)));
           }
      @@ -130,7 +134,7 @@ final class StaticPropSource extends PropSource {
         }
       
         public function getSourceType(): string {
      -    return sprintf("static:%s", $this->fieldItem->getDataDefinition()->getDataType());
      +    return sprintf("static:%s", $this->fieldItem->getDataDefinition()->getDataType() . '@todo field type settings');
         }
       
         private function conjureFieldDefinition(string $sdc_prop_name): FieldDefinitionInterface {
      

    Remaining tasks

    All points above.

    User interface changes

    New choices appear in TwoTerribleTextAreasWidget for sdc_test:my-cta.

    API changes

    None.

    Data model changes

    None.

๐Ÿ“Œ 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

Production build 0.71.5 2024