Problem/Motivation
Right now the TypedDataInterface sits on all the objects and adds confusing methods there, e.g. $entity->getDefinition(), $entity->getValue().
Proposed resolution
Avoid typed data enforcing generic methods on your objects by implementing adapters instead, that translate generic typed data interface to use-case specific methods. E.g. $field->getEntity() could be translated to getRoot().
Patch summary :
- ContentEntityInterface no more extends ComplexDataInterface (i.e is no more a TypedData object)
- A first set of methods are removed from ContentEntityBase:
getDataDefinition()
getValue()
setValue()
getString()
applyDefaultValue()
isEmpty()
getConstraints()
getName()
getRoot()
getPropertyPath()
getParent()
setContext()
- Most of those go into a new TypedData\EntityAdapter class, that extends TypedData (or we just rely on the default implementation in TypedData)
- A second set of methods remain in ContentEntityBase, and are added to ContentEntityInterface directly, in some cases with more specific docs / param names :
get($field_name)
set($field_name, $value, $notify = TRUE)
getFields($include_computed = FALSE)
onChange()
validate()
- EntityInterface::getTypedData() is added to obtain the TypedData\EntityAdapter for an entity
- Adds TypedDataInterface::createInstance() static factory, and a default implementation in TypedData
TypedDataManager::createInstance() now uses that instead of new $class();
- moves TypedData\ReadOnlyException to TypedData\Exception\ReadOnlyException
renames/move TypedData\MissingContextException to TypedData\Exception\MissingDataException
removes DataDefinitionException (was actually not used anywhere)
Remaining tasks
None
User interface changes
None
API changes
Since TypedDataInterface is not on ContentEntityInterface any more, most of its methods got removed from entities, while some got replacements - e.g. getProperties() got replaced by getFields(). For any usage of a removed method, one now has to fetch the typed data adapter object for the entity and invoke the method on it like the following:
$definition = $entity->getDataDefinition();
// becomes
$definition = $entity->getTypedData()->getDataDefinition();
This is for example needed by the FieldItemList class which has to work with the parent typed data object - however those usages are mostly obsolete once/if we'd fix #2227227: FieldTypePluginManager cannot instantiate FieldType plugins, good thing TypedDataManager can instantiate just about anything and improve the field item list's implementation to be field-related primarily.
In detail the API changes are:
- ContentEntityInterface no more extends ComplexDataInterface (i.e is no more a TypedData object)
- A first set of methods are removed from ContentEntityBase:
Removed:
- getDataDefinition()
- getValue()
- setValue()
- getString()
- applyDefaultValue()
- isEmpty()
- getConstraints()
- getName()
- getRoot()
- getPropertyPath()
- getParent()
- setContext()
Re-moved but re-added to ContentEntityInterface methods with a new name or docs are:
- get($field_name)
- set($field_name, $value, $notify = TRUE)
- getFields($include_computed = FALSE)
- onChange()
- validate()
Further TypedData-related smaller API changes are:
- TypedDataInterface::createInstance() is added, however most implementations extend TypedData and do not need to be changed.
- The TypedData exceptions change a bit:
- TypedData\ReadOnlyException -> TypedData\Exception\ReadOnlyException (moves into new sub-namespace Exception)
- TypedData\Exception\MissingDataException gets added
- The unused DataDefinitionException is removed
Related Issues
#2047229: Make use of classes for entity field and data definitions moves typed data definitions from arrays to objects based upon a defined interface
Original report by @fago
Let's remove the typed data interface and rely checking interfaces instead of doing $data->getType(). We'll probably need to separate out a ValidatableInterface also
This depends on doing #2002102: Move TypedData primitive types to interfaces first.