diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index d21932f..6e16c64 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -92,6 +92,13 @@ class EntityManager extends PluginManagerBase implements EntityManagerInterface protected $fieldDefinitions; /** + * Static cache of storage field definitions per entity type. + * + * @var array + */ + protected $storageFieldDefinitions; + + /** * The root paths. * * @see self::__construct(). @@ -480,16 +487,18 @@ protected function buildBundleFieldDefinitions($entity_type_id, $bundle, array $ */ public function getStorageFieldDefinitions($entity_type_id) { if (!isset($this->storageFieldDefinitions[$entity_type_id])) { + $base_field_definitions = $this->getBaseFieldDefinitions($entity_type_id); // Not prepared, try to load from cache. $cid = 'entity_storage_field_definitions:' . $entity_type_id . ':' . $this->languageManager->getCurrentLanguage()->id; if ($cache = $this->cache->get($cid)) { - $this->storageFieldDefinitions[$entity_type_id] = $cache->data; + $storage_field_definitions = $cache->data; } else { // Rebuild the definitions and put it into the cache. - $this->storageFieldDefinitions[$entity_type_id] = $this->buildStorageFieldDefinitions($entity_type_id); - $this->cache->set($cid, $this->storageFieldDefinitions[$entity_type_id], Cache::PERMANENT, array('entity_types' => TRUE, 'entity_field_info' => TRUE)); + $storage_field_definitions = $this->buildStorageFieldDefinitions($entity_type_id); + $this->cache->set($cid, $storage_field_definitions, Cache::PERMANENT, array('entity_types' => TRUE, 'entity_field_info' => TRUE)); } + $this->storageFieldDefinitions[$entity_type_id] = $base_field_definitions + $storage_field_definitions; } return $this->storageFieldDefinitions[$entity_type_id]; } @@ -537,6 +546,7 @@ protected function buildStorageFieldDefinitions($entity_type_id) { public function clearCachedFieldDefinitions() { $this->baseFieldDefinitions = array(); $this->fieldDefinitions = array(); + $this->storageFieldDefinitions = array(); Cache::deleteTags(array('entity_field_info' => TRUE)); } diff --git a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php index 424af7d..389c320 100644 --- a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php @@ -57,6 +57,28 @@ public function getBaseFieldDefinitions($entity_type_id); public function getFieldDefinitions($entity_type_id, $bundle); /** + * Gets the storage field definitions for a content entity type. + * + * This returns all storage field definitions for base fields and bundle + * fields of an entity type. Note that storage field definitions of a base + * fields equal the full base field definition (i.e. they implement + * \Drupal\Core\Field\FieldDefinitionInterface), while the storage fields for + * bundle fields may implement + * \Drupal\Core\Field\FieldStorageDefinitionInterface only. + * + * @param string $entity_type_id + * The entity type ID. Only entity types that implement + * \Drupal\Core\Entity\ContentEntityInterface are supported. + * + * @return \Drupal\Core\Field\FieldStorageDefinitionInterface[] + * The array of storage field definitions for the entity type, keyed by + * field name. + * + * @see \Drupal\Core\Field\FieldStorageDefinitionInterface + */ + public function getStorageFieldDefinitions($entity_type_id); + + /** * Creates a new access controller instance. * * @param string $entity_type diff --git a/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php b/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php index 506f272..645ef55 100644 --- a/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php +++ b/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php @@ -15,6 +15,8 @@ * stored. While field definitions may differ by entity bundle, all of those * bundle fields have to share the same common field storage definition. Thus, * field storage definitions can be defined by entity type only. + * + * @see hook_entity_storage_field_info() */ interface FieldStorageDefinitionInterface { diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 52f3996..6970468 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -174,6 +174,15 @@ function field_system_info_alter(&$info, Extension $file, $type) { } /** + * Implements hook_entity_storage_field_info(). + */ +function field_entity_storage_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) { + if ($entity_type->isFieldable()) { + return Field::fieldInfo()->getFields(); + } +} + +/** * Implements hook_entity_bundle_field_info(). */ function field_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) { diff --git a/core/modules/system/entity.api.php b/core/modules/system/entity.api.php index c960371..f2b41c2 100644 --- a/core/modules/system/entity.api.php +++ b/core/modules/system/entity.api.php @@ -705,6 +705,9 @@ function hook_entity_base_field_info_alter(&$fields, \Drupal\Core\Entity\EntityT /** * Provides field definitions for a specific bundle within an entity type. * + * Bundles fields either have to override an existing base field, or need to + * provide a storage field via hook_entity_storage_field_info(). + * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type * The entity type definition. * @param string $bundle @@ -717,6 +720,8 @@ function hook_entity_base_field_info_alter(&$fields, \Drupal\Core\Entity\EntityT * * @see hook_entity_base_field_info() * @see hook_entity_base_field_info_alter() + * @see hook_entity_storage_field_info() + * @see hook_entity_storage_field_info_alter() * @see hook_entity_bundle_field_info_alter() * @see \Drupal\Core\Field\FieldDefinitionInterface * @see \Drupal\Core\Entity\EntityManagerInterface::getFieldDefinitions() @@ -755,6 +760,49 @@ function hook_entity_bundle_field_info_alter(&$fields, \Drupal\Core\Entity\Entit } /** + * Provides storage field definitions for a content entity type. + * + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type definition. + * + * @return \Drupal\Core\Field\FieldStorageDefinitionInterface[] + * An array of storage field definitions, keyed by field name. + * + * @see hook_entity_storage_field_info_alter() + * @see \Drupal\Core\Field\FieldStorageDefinitionInterface + * @see \Drupal\Core\Entity\EntityManagerInterface::getStorageFieldDefinitions() + */ +function hook_entity_storage_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) { + if ($entity_type->id() == 'node') { + $fields = array(); + $fields['mymodule_text'] = FieldDefinition::create('string') + ->setLabel(t('The text')) + ->setDescription(t('A text property added by mymodule.')) + ->setComputed(TRUE) + ->setClass('\Drupal\mymodule\EntityComputedText'); + + return $fields; + } +} + +/** + * Alters storage field definitions for a content entity type. + * + * @param \Drupal\Core\Field\FieldStorageDefinitionInterface[] $fields + * The array of storage field definitions for the entity type. + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type definition. + * + * @see hook_entity_storage_field_info() + */ +function hook_entity_storage_field_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type) { + // Alter the max_length setting. + if ($entity_type->id() == 'node' && !empty($fields['mymodule_text'])) { + $fields['mymodule_text']->setSetting('max_length', 128); + } +} + +/** * Alter entity operations. * * @param array $operations