Drupal Association members fund grants that make connections all over the world.
Having generic metadata introspection is necessary for use-cases like the configuration of required context, but our current implementation has the following problems:
- The metadata introspection methods are generic, and pollute our objects with generic and confusing terminology - e.g. getPropertyDefinitions() on entities
- Getting metadata does right not require run-time objects. That's unfortunate when you do not have a run-time object and e.g. need to instantiate an entity just to have one, but moreover it's not able to properly handle cases where not enough metadata is available to instantiate a run-time object - e.g. when you do not know the bundle of a node, or even not the entity type.
The patch makes metadata accessible without the need for run time objects, and consequently frees us from having respective generally named methods like getPropertyDefinitions() our data objects. As we've recently moved to class based data definitions, the patch builds upon this classes and extends them - so those can be used for deriving metadata without the need for run time data objects.
In detail this means:
1) In HEAD, we've got only
FieldDefinition. The patch extends this with some additional definition classes that implement the also newly added
DataReferenceDefinitionInterface. Those interfaces represent the methods needed for deriving metadata, i.e. are the result of moving respective run-time methods like
2) As suggested independently, we want to be able to get property definitions for fields without having actual field items. The patch implements this and lets people define the field item properties in a static method instead (see API changes).
Still, field items implement a respective field item definition that complies with the typed data interfaces and make the property definitions of field items available via the definition class. In addition to that, it's the goal to make
FieldDefinitionInterface being the primary definition objects for fields - independently of typed data. This patch does not do that yet, but it works towards that by letting the FieldDefinition know about contained properties already + making the FieldItemDefinition implementation just a dumb wrapper around it, just needed for typed-data purposes. Field items should be using the field definition object directly, so they do not have to worry about the typed data implementation. -> todo for and it's spin-offs.
3)So, as the patch frees us from having ContentEntityInterface::getPropertyDefinitions() it renames that method to go with a more straight forward naming, i.e.
getFieldDefinitions(), as seen at the list of API changes.
4) Some definition classes added are
- The MapDefinition class allows one to specify to describe how a map would look like independently from having a map + work with that. Right now, typed data maps are just used as dump containers for any arrays, but given the MapDefinition it's now possible to add meaningful metadata for those as well.
EntityDefintionis used for describing entities and retrieving further metadata from them, see 5.
DataReferenceDefinitionserves for describing the DataReference data types we have, two quite special data types for representing references in a generic typed-data fashion. We only have a "language" and a "entity" references right now. As for the others this class just splits the metadata part of the implementation out and takes it to the definition classes. It lets us to know e.g. $node->author->entity is a regular user entity without having to ask the data instances :-)
5) The patch finally allows us to derive metadata from entities without having actually instantiated entity objects, what is an quite important, necessary feature for use cases like ctools / block&layouts and rules. That's now solved by an
EntityDefinition class implementing the respective interfaces, and works e.g. as the following:
$user_definition = $entity_definition->getPropertyDefinition('user_id') ->getPropertyDefinition('entity') ->getTargetDefinition(); print $user_definition->getDataType(); // entity:user $value_definition = $user_definition->getPropertyDefinition('name') ->getPropertyDefinition('value'); print $value_definition->getDataType(); // string
6) As there are now multiple, different definition classes like
DataDefinition the problem of having to know the right class comes up (and exists already in HEAD). To solve this, the patch adds a factory for definition class that gives you the right definition class for any data type, e.g:
$node_definition = $this->typedDataManager->createDataDefinition('entity:node');
That's necessary for generically working modules like Rules, PageManager, etc. to work from the data type string only. If you know you'll work with an entity, or a field up-front - developers can still instantiate the classes directly for improved DX, i.e. keep using:
Given that, the patch fixes the existing typed data implementation to allow for deriving metadata about e.g. something with data type "entity:node".
Finally, the patch adds test-coverage for the new/moved APIs.
User interface changes
- Field types need to specify their field item properties in
ComplexDataInterface::getPropertyDefinitions()got removed in favor of the respective methods on the newly added
ComplexDataDefinitionInterface. There aren't many usages of the previous methods in core, but converting is as easy as replacing
$data->getDataDefinition()->getPropertyDefinitions(). That's mostly the case on field items.
getFieldDefinitions()is added to the
ContentEntityinterface, which replaces the previously inherited
TypedDataInterface::getDefinition() has been renamed to
TypedDataInterface::getDataDefinition() to better distinguish it from plugin definitions and field definitions.
PASSED: [[SimpleTest]]: [MySQL] 64,642 pass(es). View
PASSED: [[SimpleTest]]: [MySQL] 64,696 pass(es). View
PASSED: [[SimpleTest]]: [MySQL] 64,680 pass(es). View