- Issue created by @Christian.wiedemann
- 🇫🇷France pdureau Paris
Hi Christian,
Thanks for this issue. I hope I am understand what you are trying to do achieve here. I not, I will move this to its own ticket.
They are 3 levels in Field API and 3 kinds of prop types:
Indeed, we use
typed_data
property only with scalar prop types nowadays:$ grep -r typed_data src/Plugin/UiPatterns/PropType src/Plugin/UiPatterns/PropType/UrlPropType.php: typed_data: ['uri'] src/Plugin/UiPatterns/PropType/StringPropType.php: typed_data: ['string'] src/Plugin/UiPatterns/PropType/NumberPropType.php: typed_data: ['decimal', 'float', 'integer'] src/Plugin/UiPatterns/PropType/EnumPropType.php: typed_data: ['float', 'integer', 'string'], src/Plugin/UiPatterns/PropType/BooleanPropType.php: typed_data: ['boolean']
Let's focus on the 3 red crosses (❌) instead
So we have much to do to cover the full field API.
Every component prop type has a (JSON) schema, every prop type has a (Typed data) schema. They may be matchable.
Example: Icon field with an Icon prop
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition): array { $properties = []; $properties['target_id'] = DataDefinition::create('string') ->setLabel(new TranslatableMarkup('Icon ID')) ->setRequired(TRUE); return $properties; }
is converted to JSON schema:
type: object properties: target_id: type: string
type: object properties: pack_id: "$ref": ui-patterns://identifier icon_id: type: string settings: type: object required: - pack_id - icon_id
Not easy to map because it seems icon field has a single property (
target_id
) for 2 prop types properties (pack_id
andicon_id
). Maybe with a separator. Let's check that with UI Icon team.Example: LinkItem field to Links prop
LinkItem field type :
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) { $properties['uri'] = DataDefinition::create('uri')->setLabel(new TranslatableMarkup('URI')); $properties['title'] = DataDefinition::create('string')->setLabel(new TranslatableMarkup('Link text')); $properties['options'] = MapDataDefinition::create()->setLabel(new TranslatableMarkup('Options')); return $properties; }
is converted to JSON schema:
type: object properties: title: type: string uri: "$ref": ui-patterns://url options: type: object
Links prop type:
type: array items: type: object properties: title: type: string url: "$ref": ui-patterns://url attributes: "$ref": ui-patterns://attributes link_attributes: "$ref": ui-patterns://attributes below: type: array items: type: object
Not bad :) But
url
anduri
property names don't match, so we can have 2 strategies:- We don't care about the property names ("title", "uri", "options"), we care only about the type and we let the builder do the mapping.
- Can we use a PropTypeAdapter plugin transforming
uri
andurl
for that? They were not made for this kind of flow, but it may work.
Example: Multivalued StringItem field to List prop
StringItem field:
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) { $properties['value'] = DataDefinition::create('string') ->setLabel(new TranslatableMarkup('Text value')) ->setSetting('case_sensitive', $field_definition->getSetting('case_sensitive')) ->setRequired(TRUE); return $properties; }
Is converted to this JSON schema:
type: object properties: value: type: string
So this when multivalued:
type: array items: type: object properties: value: type: string
List prop type:
type: array items: type: ['string', 'number', 'integer']
It doesn't seem obvious at first, but it may be good match if we flat the single "value" field property.
Conclusion
None of my examples were a perfect match. But each of them is showing mechanism worth to study. There is something smart to do here.
- 🇩🇪Germany Christian.wiedemann
So to handle icons the ui icon module needs three sources. One for pack_id, icon_id and one for settings.
/** * Plugin implementation of the source_provider. */ #[Source( id: 'icon_pack_id', label: new TranslatableMarkup('Foo Field(ui_patterns_test)'), description: new TranslatableMarkup('Foo description.'), prop_types: ['string'], deriver: CustomEntityPropertySourceDeriver::class, metadata: [ 'field_type' => ['icon'], 'field_property' => ['target_id'] ], )] final class IconPackId extends SourcePluginBase { DO MAGIC TARGET EXPLODE HERE