Skip to content

Add a DynamicReturnTypeExtension + fieldDefinitionMapping for BaseFieldDefinition::create() #874

@voxpelli

Description

@voxpelli

The type support when doing something like this is quite lacking currently:

BaseFieldDefinition::create('list_string')
      ->setLabel('Test field')
      ->setSetting('allowed_values', ['foo' => 'Foo])
      ->setDefaultValue($bar);

PR:s like #784 and the tracking issue of #359 keeps an eye on the addition of stubs for \Drupal\comment\Plugin\Field\FieldType\CommentItem etc, but to tie all those field types back into BaseFieldDefinition::create() I believe we would need to mimic the parameters.drupal.entityMapping and add a new one:

parameters:
	drupal:
		fieldTypeMapping:
			comment:
				class: Drupal\comment\Plugin\Field\FieldType\CommentItem
			list_string:
				class: Drupal\options\Plugin\Field\FieldType\ListStringItem

That paired with a new FieldTypeDataRepository similar to EntityDataRepository, dynamically registering that the same way and lastly a DynamicReturnTypeExtension for BaseFieldDefinition::create() that's similar to eg. EntityTypeManagerGetStorageDynamicReturnTypeExtension – that would get us pretty far.

Last tricky part is that BaseFieldDefinition::create() does not create eg. Drupal\options\Plugin\Field\FieldType\ListStringItem.

Instead it creates a BaseFieldDefinition instance that extends ListDataDefinition and implements eg. FieldDefinitionInterface and to that instance it attaches a FieldItemDataDefinition as itemDefinition and then resolves default storage and field settings from the FieldTypePluginManager service and sets them using itemDefinition->setSettings().

The solution would probably be to make BaseFieldDefinition a generic that takes a field type id and implements a ClassReflectionExtension to dynamically resolve the setSettings() / setDefaultValue() using something like:

parameters:
    drupal:
        fieldTypeMapping:
            list_string:
                class: Drupal\options\Plugin\Field\FieldType\ListStringItem
                default_value_type: string
                schema:
                    allowed_values: array<string, string>
                    allowed_values_function: string|null

We're still left with trying to narrow setDefaultValue() based on ->setSetting('allowed_values', ['foo' => 'Foo]).

Not sure if this is a fruitful rabbit hole or just a way to inflict pain on oneself, but if you think its fruitful I can try to make a stab at this approach.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions