Issue #3246150 by dww, larowlan, Berdir, alexpott, craigra: Bundle class changes mean the entity class is now determined by the active entity-type definition

merge-requests/1185/merge
catch 2021-10-28 20:54:30 +01:00
parent 3eba4b3c58
commit cefb93c5f0
7 changed files with 56 additions and 14 deletions

View File

@ -60,16 +60,16 @@ abstract class EntityStorageBase extends EntityHandlerBase implements EntityStor
protected $uuidService;
/**
* Name of the entity class (if set directly via deprecated means).
* Name of the base entity class.
*
* This is a private property since it's not meant to be set by child classes.
* It holds the name of the entity class defined in the entity type that is
* passed in to the constructor when instantiating an entity storage class.
*
* This is a private property since it's only here to support backwards
* compatibility for deprecated code paths in contrib and custom code.
* Normally, the entity class is defined via an annotation when defining an
* entity type, via hook_entity_bundle_info() or via
* hook_entity_bundle_info_alter().
*
* @todo Remove this in Drupal 10.
* @see https://www.drupal.org/project/drupal/issues/3244802
* hook_entity_bundle_info_alter(). However, due to how this property works,
* the entity class can also be controlled via hook_entity_type_alter().
*
* @var string|null
*/
@ -100,6 +100,7 @@ abstract class EntityStorageBase extends EntityHandlerBase implements EntityStor
public function __construct(EntityTypeInterface $entity_type, MemoryCacheInterface $memory_cache) {
$this->entityTypeId = $entity_type->id();
$this->entityType = $entity_type;
$this->baseEntityClass = $entity_type->getClass();
$this->idKey = $this->entityType->getKey('id');
$this->uuidKey = $this->entityType->getKey('uuid');
$this->langcodeKey = $this->entityType->getKey('langcode');
@ -111,9 +112,7 @@ abstract class EntityStorageBase extends EntityHandlerBase implements EntityStor
* {@inheritdoc}
*/
public function getEntityClass(?string $bundle = NULL): string {
// @todo Simplify this in Drupal 10 to return $this->entityType->getClass().
// @see https://www.drupal.org/project/drupal/issues/3244802
return $this->baseEntityClass ?? $this->entityType->getClass();
return $this->baseEntityClass;
}
/**

View File

@ -8,6 +8,7 @@
use Drupal\entity_test_bundle_class\Entity\EntityTestAmbiguousBundleClass;
use Drupal\entity_test_bundle_class\Entity\EntityTestBundleClass;
use Drupal\entity_test_bundle_class\Entity\EntityTestUserClass;
use Drupal\entity_test_bundle_class\Entity\EntityTestVariant;
use Drupal\entity_test_bundle_class\Entity\NonInheritingBundleClass;
/**
@ -32,3 +33,13 @@ function entity_test_bundle_class_entity_bundle_info_alter(&$bundles) {
$bundles['user']['user']['class'] = EntityTestUserClass::class;
}
}
/**
* Implements hook_entity_type_alter().
*/
function entity_test_bundle_class_entity_type_alter(&$entity_types) {
/** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
if (\Drupal::state()->get('entity_test_bundle_class_override_base_class', FALSE) && isset($entity_types['entity_test'])) {
$entity_types['entity_test']->setClass(EntityTestVariant::class);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Drupal\entity_test_bundle_class\Entity;
use Drupal\entity_test\Entity\EntityTest;
/**
* Defines a custom class to use for EntityTest.
*
* @see entity_test_bundle_class_entity_type_alter()
*/
class EntityTestVariant extends EntityTest {}

View File

@ -6,6 +6,9 @@ use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
/**
* Class for testing deprecation warnings from EntityStorageBase.
*
* @todo Remove this in Drupal 10.
* @see https://www.drupal.org/project/drupal/issues/3244802
*/
class DeprecatedEntityStorage extends SqlContentEntityStorage {

View File

@ -8,6 +8,7 @@ use Drupal\entity_test\Entity\EntityTest;
use Drupal\entity_test_bundle_class\Entity\EntityTestAmbiguousBundleClass;
use Drupal\entity_test_bundle_class\Entity\EntityTestBundleClass;
use Drupal\entity_test_bundle_class\Entity\EntityTestUserClass;
use Drupal\entity_test_bundle_class\Entity\EntityTestVariant;
use Drupal\user\Entity\User;
/**
@ -248,4 +249,17 @@ class BundleClassTest extends EntityKernelTestBase {
$this->storage->create(['type' => 'bundle_class']);
}
/**
* Tests that a module can override an entity-type class.
*
* Ensures a module can implement hook_entity_info_alter() and alter the
* entity's class without needing to write to the last installed
* definitions repository.
*/
public function testEntityClassNotTakenFromActiveDefinitions(): void {
$this->container->get('state')->set('entity_test_bundle_class_override_base_class', TRUE);
$this->entityTypeManager->clearCachedDefinitions();
$this->assertEquals(EntityTestVariant::class, $this->entityTypeManager->getStorage('entity_test')->getEntityClass());
}
}

View File

@ -15,6 +15,9 @@ use Drupal\entity_test_deprecated_storage\Storage\DeprecatedEntityStorage;
* @coversDefaultClass \Drupal\Core\Entity\EntityStorageBase
* @group Entity
* @group legacy
*
* @todo Remove this in Drupal 10.
* @see https://www.drupal.org/project/drupal/issues/3244802
*/
class EntityStorageDeprecationTest extends UnitTestCase {

View File

@ -150,7 +150,7 @@ class KeyValueEntityStorageTest extends UnitTestCase {
* @covers ::doCreate
*/
public function testCreateWithPredefinedUuid() {
$this->entityType->expects($this->exactly(2))
$this->entityType->expects($this->once())
->method('getClass')
->will($this->returnValue(get_class($this->getMockEntity())));
$this->setUpKeyValueEntityStorage();
@ -173,7 +173,7 @@ class KeyValueEntityStorageTest extends UnitTestCase {
*/
public function testCreateWithoutUuidKey() {
// Set up the entity storage to expect no UUID key.
$this->entityType->expects($this->exactly(2))
$this->entityType->expects($this->once())
->method('getClass')
->will($this->returnValue(get_class($this->getMockEntity())));
$this->setUpKeyValueEntityStorage(NULL);
@ -198,7 +198,7 @@ class KeyValueEntityStorageTest extends UnitTestCase {
*/
public function testCreate() {
$entity = $this->getMockEntity('Drupal\Core\Entity\EntityBase', [], ['toArray']);
$this->entityType->expects($this->exactly(2))
$this->entityType->expects($this->once())
->method('getClass')
->will($this->returnValue(get_class($entity)));
$this->setUpKeyValueEntityStorage();
@ -512,7 +512,7 @@ class KeyValueEntityStorageTest extends UnitTestCase {
public function testLoadMultipleAll() {
$expected['foo'] = $this->getMockEntity('Drupal\Core\Entity\EntityBase', [['id' => 'foo']]);
$expected['bar'] = $this->getMockEntity('Drupal\Core\Entity\EntityBase', [['id' => 'bar']]);
$this->entityType->expects($this->exactly(2))
$this->entityType->expects($this->once())
->method('getClass')
->will($this->returnValue(get_class(reset($expected))));
$this->setUpKeyValueEntityStorage();