From f7d8fe6f1db5c04ee8ca7a80f9e7ef8500cfe5c1 Mon Sep 17 00:00:00 2001 From: catch <catch@35733.no-reply.drupal.org> Date: Wed, 28 Sep 2022 10:39:07 +0100 Subject: [PATCH] Issue #3266287 by lind101, alexpott, joachim, larowlan, quietone: Make buildBundleFieldDefinitions use Bundle Classes for building bundleFieldDefinitions --- .../Drupal/Core/Entity/EntityFieldManager.php | 4 +- .../Core/Entity/EntityFieldManagerTest.php | 90 ++++++++++++++++++- 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/core/lib/Drupal/Core/Entity/EntityFieldManager.php b/core/lib/Drupal/Core/Entity/EntityFieldManager.php index 8ccdb86a0ab9..1e7052a47de0 100644 --- a/core/lib/Drupal/Core/Entity/EntityFieldManager.php +++ b/core/lib/Drupal/Core/Entity/EntityFieldManager.php @@ -373,7 +373,9 @@ public function getFieldDefinitions($entity_type_id, $bundle) { */ protected function buildBundleFieldDefinitions($entity_type_id, $bundle, array $base_field_definitions) { $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); - $class = $entity_type->getClass(); + + // Use a bundle specific class if one is defined. + $class = $this->entityTypeManager->getStorage($entity_type_id)->getEntityClass($bundle); // Allow the entity class to provide bundle fields and bundle-specific // overrides of base fields. diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php index df404f8e7fcb..bfcd5ef67b24 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php @@ -11,13 +11,13 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Cache\CacheTagsInvalidatorInterface; -use Drupal\Core\Config\Entity\ConfigEntityStorageInterface; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\ContentEntityTypeInterface; use Drupal\Core\Entity\EntityDisplayRepositoryInterface; use Drupal\Core\Entity\EntityFieldManager; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface; +use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; @@ -247,8 +247,54 @@ public function testGetBaseFieldDefinitions() { public function testGetFieldDefinitions() { $field_definition = $this->setUpEntityWithFieldDefinition(); + $bundle_field_definition = $this->prophesize() + ->willImplement(FieldDefinitionInterface::class) + ->willImplement(FieldStorageDefinitionInterface::class); + + // Define bundle fields to be stored on the default Entity class. + $bundle_fields = [ + 'the_entity_id' => [ + 'test_entity_bundle' => [ + 'id_bundle' => $bundle_field_definition->reveal(), + ], + 'test_entity_bundle_class' => [ + 'some_extra_field' => $bundle_field_definition->reveal(), + ], + ], + ]; + + // Define bundle fields to be stored on the bundle class. + $bundle_class_fields = [ + 'the_entity_id' => [ + 'test_entity_bundle_class' => [ + 'id_bundle_class' => $bundle_field_definition->reveal(), + ], + ], + ]; + + EntityTypeManagerTestEntity::$bundleFieldDefinitions = $bundle_fields; + EntityTypeManagerTestEntityBundle::$bundleClassFieldDefinitions = $bundle_class_fields; + + // Test that only base fields are retrieved. $expected = ['id' => $field_definition]; + $this->assertSame($expected, $this->entityFieldManager->getFieldDefinitions('test_entity_type', 'some_other_bundle')); + + // Test that base fields and bundle fields from the default entity class are + // retrieved. + $expected = [ + 'id' => $field_definition, + 'id_bundle' => $bundle_fields['the_entity_id']['test_entity_bundle']['id_bundle'], + ]; $this->assertSame($expected, $this->entityFieldManager->getFieldDefinitions('test_entity_type', 'test_entity_bundle')); + + // Test that base fields and bundle fields from the bundle class and + // entity class are retrieved + $expected = [ + 'id' => $field_definition, + 'some_extra_field' => $bundle_fields['the_entity_id']['test_entity_bundle_class']['some_extra_field'], + 'id_bundle_class' => $bundle_class_fields['the_entity_id']['test_entity_bundle_class']['id_bundle_class'], + ]; + $this->assertSame($expected, $this->entityFieldManager->getFieldDefinitions('test_entity_type', 'test_entity_bundle_class')); } /** @@ -575,8 +621,18 @@ protected function setUpEntityWithFieldDefinition($custom_invoke_all = FALSE, $f $this->entityType = $this->prophesize(EntityTypeInterface::class); $this->setUpEntityTypeDefinitions(['test_entity_type' => $this->entityType, 'base_field_override' => $override_entity_type]); - $storage = $this->prophesize(ConfigEntityStorageInterface::class); + $storage = $this->prophesize(EntityStorageInterface::class); $storage->loadMultiple(Argument::type('array'))->willReturn([]); + + // By default, make the storage entity class lookup return the + // EntityTypeManagerTestEntity class + $storage->getEntityClass(NULL)->willReturn(EntityTypeManagerTestEntity::class); + $storage->getEntityClass(Argument::type('string'))->willReturn(EntityTypeManagerTestEntity::class); + // When using the "test_entity_bundle_class" bundle, return the + // EntityTypeManagerTestEntityBundle class + $storage->getEntityClass('test_entity_bundle_class')->willReturn(EntityTypeManagerTestEntityBundle::class); + + $this->entityTypeManager->getStorage('test_entity_type')->willReturn($storage->reveal()); $this->entityTypeManager->getStorage('base_field_override')->willReturn($storage->reveal()); $this->entityType->getClass()->willReturn($entity_class); @@ -864,3 +920,33 @@ public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, } } + +/** + * Provides a bundle specific class with dummy static method implementations. + */ +abstract class EntityTypeManagerTestEntityBundle extends EntityTypeManagerTestEntity { + + /** + * The bundle class field definitions. + * + * @var array[] + * Keys are entity type IDs, values are arrays of which the keys are bundle + * names and the values are field definitions. + */ + public static $bundleClassFieldDefinitions = []; + + /** + * {@inheritdoc} + */ + public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) { + $definitions = parent::bundleFieldDefinitions($entity_type, $bundle, $base_field_definitions); + + if (isset(static::$bundleClassFieldDefinitions[$entity_type->id()][$bundle])) { + $definitions += static::$bundleClassFieldDefinitions[$entity_type->id()][$bundle]; + } + + return $definitions; + + } + +} -- GitLab