diff --git a/core/lib/Drupal/Core/Field/Entity/BaseFieldOverride.php b/core/lib/Drupal/Core/Field/Entity/BaseFieldOverride.php index 9dd33973bf45cc4096df034d42d856fed7ab6233..4a7c52d727b813b33304cfed3cb4df9287d6516c 100644 --- a/core/lib/Drupal/Core/Field/Entity/BaseFieldOverride.php +++ b/core/lib/Drupal/Core/Field/Entity/BaseFieldOverride.php @@ -95,10 +95,6 @@ public function __construct(array $values, $entity_type = 'base_field_override') throw new FieldException(String::format('Attempt to create a base field bundle override of field @field_name without a bundle', array('@field_name' => $values['field_name']))); } - // Discard the 'field_type' entry that is added in config records to ease - // schema generation. See self::toArray(). - unset($values['field_type']); - parent::__construct($values, $entity_type); } diff --git a/core/lib/Drupal/Core/Field/FieldConfigBase.php b/core/lib/Drupal/Core/Field/FieldConfigBase.php index af5760049dafa844de896bab4ff5953c64ffc8f1..1d124801a237ef562d3d6383a7be551ee4b16d5b 100644 --- a/core/lib/Drupal/Core/Field/FieldConfigBase.php +++ b/core/lib/Drupal/Core/Field/FieldConfigBase.php @@ -35,6 +35,19 @@ abstract class FieldConfigBase extends ConfigEntityBase implements FieldConfigIn */ public $field_name; + /** + * The field type. + * + * This property is denormalized from the field storage for optimization of + * the "entity and render cache hits" critical paths. If not present in the + * $values passed to create(), it is populated from the field storage in + * postCreate(), and saved in config records so that it is present on + * subsequent loads. + * + * @var string + */ + public $field_type; + /** * The name of the entity type the instance is attached to. * @@ -190,7 +203,7 @@ public function getName() { * {@inheritdoc} */ public function getType() { - return $this->getFieldStorageDefinition()->getType(); + return $this->field_type; } /** @@ -207,20 +220,6 @@ public function targetBundle() { return $this->bundle; } - /** - * {@inheritdoc} - */ - public function toArray() { - $properties = parent::toArray(); - // Additionally, include the field type, that is needed to be able to - // generate the field-type-dependant parts of the config schema and to - // allow for mapping settings from storage by field type. - // @see \Drupal\field\FieldInstanceConfigStorage::mapFromStorageRecords(). - $properties['field_type'] = $this->getType(); - - return $properties; - } - /** * {@inheritdoc} */ @@ -236,6 +235,19 @@ public function calculateDependencies() { return $this->dependencies; } + /** + * {@inheritdoc} + */ + public function postCreate(EntityStorageInterface $storage) { + parent::postCreate($storage); + // If it was not present in the $values passed to create(), (e.g. for + // programmatic creation), populate the denormalized field_type property + // from the field storage, so that it gets saved in the config record. + if (empty($this->field_type)) { + $this->field_type = $this->getFieldStorageDefinition()->getType(); + } + } + /** * {@inheritdoc} */ diff --git a/core/modules/field/src/Entity/FieldInstanceConfig.php b/core/modules/field/src/Entity/FieldInstanceConfig.php index 81b939669b98d6dd50e2e1fc866d526064fe1f7f..e07c4eda12631c511371a2fb5a02a2eff7d4001f 100644 --- a/core/modules/field/src/Entity/FieldInstanceConfig.php +++ b/core/modules/field/src/Entity/FieldInstanceConfig.php @@ -87,7 +87,9 @@ public function __construct(array $values, $entity_type = 'field_instance_config $field_storage = $values['field_storage']; $values['field_name'] = $field_storage->getName(); $values['entity_type'] = $field_storage->getTargetEntityTypeId(); - $this->fieldStorage = $field_storage; + // The internal property is fieldStorage, not field_storage. + unset($values['field_storage']); + $values['fieldStorage'] = $field_storage; } else { if (empty($values['field_name'])) { @@ -102,11 +104,6 @@ public function __construct(array $values, $entity_type = 'field_instance_config throw new FieldException(String::format('Attempt to create a field instance @field_name without a bundle.', array('@field_name' => $values['field_name']))); } - // Discard the 'field_type' entry that is added in config records to ease - // schema generation and mapping settings from storage. - // @see \Drupal\Core\Field\FieldConfigBase::toArray(). - unset($values['field_type']); - parent::__construct($values, $entity_type); } @@ -114,6 +111,8 @@ public function __construct(array $values, $entity_type = 'field_instance_config * {@inheritdoc} */ public function postCreate(EntityStorageInterface $storage) { + parent::postCreate($storage); + // Validate that we have a valid storage for this instance. This throws an // exception if the storage is invalid. $this->getFieldStorageDefinition(); diff --git a/core/modules/field/tests/src/FieldInstanceConfigEntityUnitTest.php b/core/modules/field/tests/src/FieldInstanceConfigEntityUnitTest.php index 1df4023445c795e3e9e0707aecf46cb0ec39d1b1..56f28579b2aa058adaebaa08b81679abfa05953e 100644 --- a/core/modules/field/tests/src/FieldInstanceConfigEntityUnitTest.php +++ b/core/modules/field/tests/src/FieldInstanceConfigEntityUnitTest.php @@ -125,9 +125,13 @@ public function testCalculateDependencies() { ->method('getConfigDependencyName') ->will($this->returnValue('field.storage.test_entity_type.test_field')); - $values = array('field_name' => $this->fieldStorage->getName(), 'entity_type' => 'test_entity_type', 'bundle' => 'test_bundle'); - $entity = new FieldInstanceConfig($values, $this->entityTypeId); - $dependencies = $entity->calculateDependencies(); + $instance = new FieldInstanceConfig(array( + 'field_name' => $this->fieldStorage->getName(), + 'entity_type' => 'test_entity_type', + 'bundle' => 'test_bundle', + 'field_type' => 'test_field', + ), $this->entityTypeId); + $dependencies = $instance->calculateDependencies(); $this->assertContains('field.storage.test_entity_type.test_field', $dependencies['entity']); $this->assertContains('test.test_entity_type.id', $dependencies['entity']); } @@ -136,8 +140,12 @@ public function testCalculateDependencies() { * @covers ::toArray() */ public function testToArray() { - $values = array('field_name' => $this->fieldStorage->getName(), 'entity_type' => 'test_entity_type', 'bundle' => 'test_bundle'); - $instance = new FieldInstanceConfig($values, $this->entityTypeId); + $instance = new FieldInstanceConfig(array( + 'field_name' => $this->fieldStorage->getName(), + 'entity_type' => 'test_entity_type', + 'bundle' => 'test_bundle', + 'field_type' => 'test_field', + ), $this->entityTypeId); $expected = array( 'id' => 'test_entity_type.test_bundle.field_test', @@ -171,4 +179,26 @@ public function testToArray() { $export = $instance->toArray(); $this->assertEquals($expected, $export); } + + /** + * @covers ::getType + */ + public function testGetType() { + // Ensure that FieldInstanceConfig::getType() is not delegated to + // FieldStorage. + $this->entityManager->expects($this->never()) + ->method('getFieldStorageDefinitions'); + $this->fieldStorage->expects($this->never()) + ->method('getType'); + + $instance = new FieldInstanceConfig(array( + 'field_name' => $this->fieldStorage->getName(), + 'entity_type' => 'test_entity_type', + 'bundle' => 'test_bundle', + 'field_type' => 'test_field', + ), $this->entityTypeId); + + $this->assertEquals('test_field', $instance->getType()); + } + }