diff --git a/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php index 2365f1a..22cf527 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php @@ -9,7 +9,7 @@ use Drupal\Core\Database\Connection; use Drupal\Core\Entity\Query\QueryInterface; -use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Language\Language; use Drupal\field\FieldInfo; use Drupal\field\FieldConfigUpdateForbiddenException; @@ -822,7 +822,7 @@ protected function doLoadFieldItems($entities, $age) { $delta_count[$row->entity_id][$row->langcode] = 0; } - if ($field->getCardinality() == FieldDefinitionInterface::CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field->getCardinality()) { + if ($field->getCardinality() == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field->getCardinality()) { $item = array(); // For each column declared by the field, populate the item from the // prefixed database column. @@ -908,7 +908,7 @@ protected function doSaveFieldItems(EntityInterface $entity, $update) { $query->values($record); $revision_query->values($record); - if ($field->getCardinality() != FieldDefinitionInterface::CARDINALITY_UNLIMITED && ++$delta_count == $field->getCardinality()) { + if ($field->getCardinality() != FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED && ++$delta_count == $field->getCardinality()) { break; } } diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index bb9605e..f0df059 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -99,7 +99,7 @@ class EntityManager extends PluginManagerBase implements EntityManagerInterface protected $fieldDefinitions; /** - * Static cache of storage field definitions per entity type. + * Static cache of field storage definitions per entity type. * * Elements of the array: * - $entity_type_id: \Drupal\Core\Field\FieldDefinition[] @@ -521,14 +521,14 @@ public function getFieldStorageDefinitions($entity_type_id) { } /** - * Builds storage field definitions for an entity type. + * Builds field storage definitions for an entity type. * * @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[] - * An array of storage field definitions, keyed by field name. + * An array of field storage definitions, keyed by field name. */ protected function buildFieldStorageDefinitions($entity_type_id) { $entity_type = $this->getDefinition($entity_type_id); diff --git a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php index bd9dc35..da36a36 100644 --- a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php @@ -57,21 +57,19 @@ public function getBaseFieldDefinitions($entity_type_id); public function getFieldDefinitions($entity_type_id, $bundle); /** - * Gets the storage field definitions for a content entity type. + * Gets the field storage 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. + * This returns all field storage definitions for base fields and bundle + * fields of an entity type. Note that field storage definitions of a base + * field equal the full base field definition (i.e. they implement + * FieldDefinitionInterface), while the storage definitions for bundle fields + * may implement FieldStorageDefinitionInterface only. * * @param string $entity_type_id - * The entity type ID. Only entity types that implement - * \Drupal\Core\Entity\ContentEntityInterface are supported. + * The entity type ID. Only content entities are supported. * * @return \Drupal\Core\Field\FieldStorageDefinitionInterface[] - * The array of storage field definitions for the entity type, keyed by + * The array of field storage definitions for the entity type, keyed by * field name. * * @see \Drupal\Core\Field\FieldStorageDefinitionInterface diff --git a/core/lib/Drupal/Core/Field/FieldDefinition.php b/core/lib/Drupal/Core/Field/FieldDefinition.php index 68e7518..8d36fba 100644 --- a/core/lib/Drupal/Core/Field/FieldDefinition.php +++ b/core/lib/Drupal/Core/Field/FieldDefinition.php @@ -76,7 +76,7 @@ public static function create($type) { * definition in places where a full field definition is required; e.g., with * widgets or formatters. * - * @param FieldStorageDefinitionInterface $definition + * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $definition * The field storage definition to base the new field definition upon. * * @return $this diff --git a/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php b/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php index adf88a0..aa1d90e 100644 --- a/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php +++ b/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php @@ -10,17 +10,18 @@ /** * Defines an interface for entity field storage definitions. * - * Field storage definitions represent the part of a full field definition (see - * FieldDefintionInterface), which is responsible for defining how the field is + * Field storage definitions represent the part of full field definitions (see + * FieldDefinitionInterface) that is responsible for defining how the field is * 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. - * The bundle fields corresponding to a storage field may provide additional - * information; e.g., they may provide bundle-specific settings or constraints - * that are not present in the storage field. However bundle fields may not - * override or alter any information provided by the storage field except for - * the label and the description; e.g., any constraints and settings on the - * storage field must be present on the bundle field as well. + * the storage definitions can be defined by entity type only. + * The bundle fields corresponding to a field storage definition may provide + * additional information; e.g., they may provide bundle-specific settings or + * constraints that are not present in the storage definition. However bundle + * fields may not override or alter any information provided by the storage + * definition except for the label and the description; e.g., any constraints + * and settings on the storage definition must be present on the bundle field as + * well. * * @see hook_entity_field_storage_info() */ diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 8a3ae72..029db41 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -177,9 +177,21 @@ function field_system_info_alter(&$info, Extension $file, $type) { * Implements hook_entity_field_storage_info(). */ function field_entity_field_storage_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) { - // Expose storage fields for all exposed bundle fields. + // Expose storage definitions for all exposed bundle fields. if ($entity_type->isFieldable()) { - return Field::fieldInfo()->getFields(); + // Query by filtering on the ID as this is more efficient than filtering + // on the entity_type property directly. + $ids = \Drupal::entityQuery('field_config') + ->condition('id', $entity_type->id() . '.', 'STARTS_WITH') + ->execute(); + + // Fetch all fields and key them by field name. + $field_configs = entity_load_multiple('field_config', $ids); + $result = array(); + foreach ($field_configs as $field_config) { + $result[$field_config->getName()] = $field_config; + } + return $result; } } diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php b/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php index 22e1811..da29536 100644 --- a/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php +++ b/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php @@ -10,7 +10,7 @@ use Drupal\Component\Utility\Unicode; use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\Core\Entity\EntityStorageInterface; -use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\field\FieldException; use Drupal\field\FieldConfigInterface; @@ -100,10 +100,10 @@ class FieldConfig extends ConfigEntityBase implements FieldConfigInterface { * The field cardinality. * * The maximum number of values the field can hold. Possible values are - * positive integers or FieldDefinitionInterface::CARDINALITY_UNLIMITED. - * Defaults to 1. + * positive integers or + * FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED. Defaults to 1. * - * @var integer + * @var int */ public $cardinality = 1; @@ -620,7 +620,7 @@ public function isRequired() { */ public function isMultiple() { $cardinality = $this->getCardinality(); - return ($cardinality == FieldDefinitionInterface::CARDINALITY_UNLIMITED) || ($cardinality > 1); + return ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) || ($cardinality > 1); } /** diff --git a/core/modules/field/lib/Drupal/field/Tests/ConfigFieldDefinitionTest.php b/core/modules/field/lib/Drupal/field/Tests/ConfigFieldDefinitionTest.php new file mode 100644 index 0000000..d1b712c --- /dev/null +++ b/core/modules/field/lib/Drupal/field/Tests/ConfigFieldDefinitionTest.php @@ -0,0 +1,75 @@ + 'Config field definitions', + 'description' => 'Tests exposing field definitions for configurable fields.', + 'group' => 'Field API', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + + // Create a field and instance of type 'test_field', on the 'entity_test' + // entity type. + $this->entityType = 'entity_test'; + $this->bundle = 'entity_test'; + $this->createFieldWithInstance('', $this->entityType, $this->bundle); + $this->entityManager = $this->container->get('entity.manager'); + + // Create a second instance on 'entity_test_rev'. + $this->createFieldWithInstance('_rev', 'entity_test_rev', 'entity_test_rev'); + } + + /** + * Makes sure a field definition is exposed for a configurable field. + */ + public function testBundleFieldDefinition() { + $definitions = $this->entityManager->getFieldDefinitions($this->entityType, $this->bundle); + $this->assertTrue(isset($definitions[$this->instance->getName()])); + $this->assertTrue($definitions[$this->instance->getName()] instanceof FieldStorageDefinitionInterface); + // Make sure no field for the instance on another entity type is exposed. + $this->assertFalse(isset($definitions[$this->instance_rev->getName()])); + } + + /** + * Makes sure a field storage definition is exposed for a configurable field. + */ + public function testFieldStorageDefinition() { + $storage_definitions = $this->entityManager->getFieldStorageDefinitions($this->entityType); + $this->assertTrue(isset($storage_definitions[$this->instance->getName()])); + $this->assertTrue($storage_definitions[$this->instance->getName()] instanceof FieldStorageDefinitionInterface); + // Make sure no storage field for the instance on another entity type is + // exposed. + $this->assertFalse(isset($storage_definitions[$this->instance_rev->getName()])); + } + +} diff --git a/core/modules/system/entity.api.php b/core/modules/system/entity.api.php index 0337ef2..c53444b 100644 --- a/core/modules/system/entity.api.php +++ b/core/modules/system/entity.api.php @@ -708,8 +708,8 @@ function hook_entity_base_field_info_alter(&$fields, \Drupal\Core\Entity\EntityT * Provides field definitions for a specific bundle within an entity type. * * Bundle fields either have to override an existing base field, or need to - * provide a storage field via hook_entity_field_storage_info() unless they are - * computed. + * provide a field storage definition via hook_entity_field_storage_info() + * unless they are computed. * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type * The entity type definition. @@ -763,30 +763,42 @@ function hook_entity_bundle_field_info_alter(&$fields, \Drupal\Core\Entity\Entit } /** - * Provides storage field definitions for a content entity type. + * Provides field storage 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. + * An array of field storage definitions, keyed by field name. * * @see hook_entity_field_storage_info_alter() * @see \Drupal\Core\Field\FieldStorageDefinitionInterface * @see \Drupal\Core\Entity\EntityManagerInterface::getFieldStorageDefinitions() */ function hook_entity_field_storage_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) { - // Expose storage fields for all exposed bundle fields. + // Expose storage definitions for all exposed bundle fields. if ($entity_type->isFieldable()) { - return Field::fieldInfo()->getFields(); + // Query by filtering on the ID as this is more efficient than filtering + // on the entity_type property directly. + $ids = \Drupal::entityQuery('field_config') + ->condition('id', $entity_type->id() . '.', 'STARTS_WITH') + ->execute(); + + // Fetch all fields and key them by field name. + $field_configs = entity_load_multiple('field_config', $ids); + $result = array(); + foreach ($field_configs as $field_config) { + $result[$field_config->getName()] = $field_config; + } + return $result; } } /** - * Alters storage field definitions for a content entity type. + * Alters field storage definitions for a content entity type. * * @param \Drupal\Core\Field\FieldStorageDefinitionInterface[] $fields - * The array of storage field definitions for the entity type. + * The array of field storage definitions for the entity type. * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type * The entity type definition. *