Commit credits so far : yched, fago, plach, effulgentsia, swentel, amateescu
(hope I didn't forget anyone)
- Work takes place in the 'field-types-as-datatypes-1969728' branch in the sandbox.
- is a testbot playground helper issue.
This patch moves the "field type" API from "pseudo hooks" to plugins / OO classes.
Most of all, and according to the plan summarized in , this patches unifies Field API "field types" and Entity NG "typed data": the "field type" plugin classes, implementing the behavior of the field type previously held in the various hook_field_[op]() implementations, are the *same* classes as TypedData's "field item" classes (that all field types currently need to implement anyway already).
In short, the logic about the field type (which is mostly about describing / massaging the values) is held in methods on the "field value" objects.
- solves DX WTFs of currently having to write on top of two entirely different APIs and data structures to provide a new field type
- stops the constant back and forth converstions of "field values" between TypedData and dumb arrays when going in and out of the Field API functions.
- brings field-level validation to REST entity writes.
- Introduces a new "configurable field type" plugin type (ConfigFieldTypePluginManager).
Discovery is annotations based.
The "configurable field types" are added as "data type" plugins through a derivative (field_data_type_info() / ConfigFieldDataTypeDerivative)
- The old hooks are migrated as such:
hook_field_info() -> Plugin annotations
hook_field_schema() -> ConfigFieldItemInterface::schema() (static method)
hook_field_settings_form() -> ConfigFieldItemInterface::settingsForm()
hook_field_instance_settings_form() -> ConfigFieldItemInterface::instanceSettingsForm()
hook_field_is_empty() -> ComplexDataInterface::isEmpty() (already exists)
hook_field_presave() -> FieldItemInterface::preSave()
hook_field_insert() -> FieldItemInterface::insert()
hook_field_update() -> FieldItemInterface::update()
hook_field_delete() -> FieldItemInterface::delete()
hook_field_delete_revision() -> FieldItemInterface::deleteRevision()
hook_field_validate() -> TypedDataInterface::getConstraints() (field validation moves on top of the existing Entity validation w/ Symfony constraints)
hook_field_load() -> PrepareCacheInterface (extends ConfigFieldItemInterface) ::prepareCache()
hook_field_prepare_view() -> removed, in favour of prepareView() on Formatters.
hook_field_prepare_translation() -> Dropped - was only related to the old (node-only) translation model. Also see
- Patch migrates the three "text" field types, and provides a "legacy" BC layer that keeps the other core field types working:
FieldTypePluginManager's discovery includes a LegacyFieldTypeDiscoveryDecorator for the field types still exposed in hook_field_info().
LegacyConfigField / LegacyConfigFieldItem plugin classes proxies method calls to the old callbacks.
- TextProcessed::setValue() raises an exception when something tries to set the computed 'processed" property of a FieldItem. - That's exactly what invokeFieldMethod() & friends do when they need to work on BC entities, though.added as point to the follow-up
So for now I left that "throw new ReadOnlyException" line commented out :-/
- @fago left a "@todo: Pass $violation->arrayPropertyPath as property path." in WidgetBase, but I'm not sure what he meant ;-) - created follow-up
Related patches / blockers
- a small subpart of , to fix testNestedFieldForm() / field_test_entity_nested_form() by having it run on the NG entity_test rather than test_entity - no biggie if this gets committed as part of this patch IMO
PASSED: [[SimpleTest]]: [MySQL] 57,959 pass(es). View
PASSED: [[SimpleTest]]: [MySQL] 57,939 pass(es). View