Issue #2976103 by amateescu, catch, tstoeckler, alexpott: Make it possible to retrieve all the last installed entity type definitions at once from the update manager
parent
7410ab4ab0
commit
5e908886e9
|
@ -575,7 +575,7 @@ services:
|
||||||
- { name: event_subscriber }
|
- { name: event_subscriber }
|
||||||
entity.definition_update_manager:
|
entity.definition_update_manager:
|
||||||
class: Drupal\Core\Entity\EntityDefinitionUpdateManager
|
class: Drupal\Core\Entity\EntityDefinitionUpdateManager
|
||||||
arguments: ['@entity.manager']
|
arguments: ['@entity.manager', '@entity.last_installed_schema.repository']
|
||||||
entity.last_installed_schema.repository:
|
entity.last_installed_schema.repository:
|
||||||
class: Drupal\Core\Entity\EntityLastInstalledSchemaRepository
|
class: Drupal\Core\Entity\EntityLastInstalledSchemaRepository
|
||||||
arguments: ['@keyvalue']
|
arguments: ['@keyvalue']
|
||||||
|
|
|
@ -21,14 +21,29 @@ class EntityDefinitionUpdateManager implements EntityDefinitionUpdateManagerInte
|
||||||
*/
|
*/
|
||||||
protected $entityManager;
|
protected $entityManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last installed schema repository.
|
||||||
|
*
|
||||||
|
* @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface
|
||||||
|
*/
|
||||||
|
protected $entityLastInstalledSchemaRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new EntityDefinitionUpdateManager.
|
* Constructs a new EntityDefinitionUpdateManager.
|
||||||
*
|
*
|
||||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||||
* The entity manager.
|
* The entity manager.
|
||||||
|
* @param \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $entity_last_installed_schema_repository
|
||||||
|
* The last installed schema repository service.
|
||||||
*/
|
*/
|
||||||
public function __construct(EntityManagerInterface $entity_manager) {
|
public function __construct(EntityManagerInterface $entity_manager, EntityLastInstalledSchemaRepositoryInterface $entity_last_installed_schema_repository = NULL) {
|
||||||
$this->entityManager = $entity_manager;
|
$this->entityManager = $entity_manager;
|
||||||
|
|
||||||
|
if (!isset($entity_last_installed_schema_repository)) {
|
||||||
|
@trigger_error('The $entity_last_installed_schema_repository parameter was added in Drupal 8.6.x and will be required in 9.0.0. See https://www.drupal.org/node/2973262.', E_USER_DEPRECATED);
|
||||||
|
$entity_last_installed_schema_repository = \Drupal::service('entity.last_installed_schema.repository');
|
||||||
|
}
|
||||||
|
$this->entityLastInstalledSchemaRepository = $entity_last_installed_schema_repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +78,7 @@ class EntityDefinitionUpdateManager implements EntityDefinitionUpdateManagerInte
|
||||||
// Process field storage definition changes.
|
// Process field storage definition changes.
|
||||||
if (!empty($change_list['field_storage_definitions'])) {
|
if (!empty($change_list['field_storage_definitions'])) {
|
||||||
$storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
|
$storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
|
||||||
$original_storage_definitions = $this->entityManager->getLastInstalledFieldStorageDefinitions($entity_type_id);
|
$original_storage_definitions = $this->entityLastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions($entity_type_id);
|
||||||
|
|
||||||
foreach ($change_list['field_storage_definitions'] as $field_name => $change) {
|
foreach ($change_list['field_storage_definitions'] as $field_name => $change) {
|
||||||
switch ($change) {
|
switch ($change) {
|
||||||
|
@ -108,7 +123,7 @@ class EntityDefinitionUpdateManager implements EntityDefinitionUpdateManagerInte
|
||||||
// Process field storage definition changes.
|
// Process field storage definition changes.
|
||||||
if (!empty($change_list['field_storage_definitions'])) {
|
if (!empty($change_list['field_storage_definitions'])) {
|
||||||
$storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
|
$storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
|
||||||
$original_storage_definitions = $this->entityManager->getLastInstalledFieldStorageDefinitions($entity_type_id);
|
$original_storage_definitions = $this->entityLastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions($entity_type_id);
|
||||||
|
|
||||||
foreach ($change_list['field_storage_definitions'] as $field_name => $change) {
|
foreach ($change_list['field_storage_definitions'] as $field_name => $change) {
|
||||||
$storage_definition = isset($storage_definitions[$field_name]) ? $storage_definitions[$field_name] : NULL;
|
$storage_definition = isset($storage_definitions[$field_name]) ? $storage_definitions[$field_name] : NULL;
|
||||||
|
@ -123,10 +138,17 @@ class EntityDefinitionUpdateManager implements EntityDefinitionUpdateManagerInte
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function getEntityType($entity_type_id) {
|
public function getEntityType($entity_type_id) {
|
||||||
$entity_type = $this->entityManager->getLastInstalledDefinition($entity_type_id);
|
$entity_type = $this->entityLastInstalledSchemaRepository->getLastInstalledDefinition($entity_type_id);
|
||||||
return $entity_type ? clone $entity_type : NULL;
|
return $entity_type ? clone $entity_type : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getEntityTypes() {
|
||||||
|
return $this->entityLastInstalledSchemaRepository->getLastInstalledDefinitions();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
@ -173,7 +195,7 @@ class EntityDefinitionUpdateManager implements EntityDefinitionUpdateManagerInte
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function getFieldStorageDefinition($name, $entity_type_id) {
|
public function getFieldStorageDefinition($name, $entity_type_id) {
|
||||||
$storage_definitions = $this->entityManager->getLastInstalledFieldStorageDefinitions($entity_type_id);
|
$storage_definitions = $this->entityLastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions($entity_type_id);
|
||||||
return isset($storage_definitions[$name]) ? clone $storage_definitions[$name] : NULL;
|
return isset($storage_definitions[$name]) ? clone $storage_definitions[$name] : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +233,7 @@ class EntityDefinitionUpdateManager implements EntityDefinitionUpdateManagerInte
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case static::DEFINITION_UPDATED:
|
case static::DEFINITION_UPDATED:
|
||||||
$original = $this->entityManager->getLastInstalledDefinition($entity_type_id);
|
$original = $this->entityLastInstalledSchemaRepository->getLastInstalledDefinition($entity_type_id);
|
||||||
$this->entityManager->onEntityTypeUpdate($entity_type, $original);
|
$this->entityManager->onEntityTypeUpdate($entity_type, $original);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -262,7 +284,7 @@ class EntityDefinitionUpdateManager implements EntityDefinitionUpdateManagerInte
|
||||||
$change_list = [];
|
$change_list = [];
|
||||||
|
|
||||||
foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) {
|
foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) {
|
||||||
$original = $this->entityManager->getLastInstalledDefinition($entity_type_id);
|
$original = $this->entityLastInstalledSchemaRepository->getLastInstalledDefinition($entity_type_id);
|
||||||
|
|
||||||
// @todo Support non-storage-schema-changing definition updates too:
|
// @todo Support non-storage-schema-changing definition updates too:
|
||||||
// https://www.drupal.org/node/2336895.
|
// https://www.drupal.org/node/2336895.
|
||||||
|
@ -277,7 +299,7 @@ class EntityDefinitionUpdateManager implements EntityDefinitionUpdateManagerInte
|
||||||
if ($this->entityManager->getStorage($entity_type_id) instanceof DynamicallyFieldableEntityStorageInterface) {
|
if ($this->entityManager->getStorage($entity_type_id) instanceof DynamicallyFieldableEntityStorageInterface) {
|
||||||
$field_changes = [];
|
$field_changes = [];
|
||||||
$storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
|
$storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
|
||||||
$original_storage_definitions = $this->entityManager->getLastInstalledFieldStorageDefinitions($entity_type_id);
|
$original_storage_definitions = $this->entityLastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions($entity_type_id);
|
||||||
|
|
||||||
// Detect created field storage definitions.
|
// Detect created field storage definitions.
|
||||||
foreach (array_diff_key($storage_definitions, $original_storage_definitions) as $field_name => $storage_definition) {
|
foreach (array_diff_key($storage_definitions, $original_storage_definitions) as $field_name => $storage_definition) {
|
||||||
|
|
|
@ -108,6 +108,18 @@ interface EntityDefinitionUpdateManagerInterface {
|
||||||
*/
|
*/
|
||||||
public function getEntityType($entity_type_id);
|
public function getEntityType($entity_type_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the entity type definitions, ready to be manipulated.
|
||||||
|
*
|
||||||
|
* When needing to apply updates to existing entity type definitions, this
|
||||||
|
* method should always be used to retrieve all the definitions ready to be
|
||||||
|
* manipulated.
|
||||||
|
*
|
||||||
|
* @return \Drupal\Core\Entity\EntityTypeInterface[]
|
||||||
|
* The last installed entity type definitions, keyed by the entity type ID.
|
||||||
|
*/
|
||||||
|
public function getEntityTypes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installs a new entity type definition.
|
* Installs a new entity type definition.
|
||||||
*
|
*
|
||||||
|
|
|
@ -34,6 +34,28 @@ class EntityLastInstalledSchemaRepository implements EntityLastInstalledSchemaRe
|
||||||
return $this->keyValueFactory->get('entity.definitions.installed')->get($entity_type_id . '.entity_type');
|
return $this->keyValueFactory->get('entity.definitions.installed')->get($entity_type_id . '.entity_type');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getLastInstalledDefinitions() {
|
||||||
|
$all_definitions = $this->keyValueFactory->get('entity.definitions.installed')->getAll();
|
||||||
|
|
||||||
|
// Filter out field storage definitions.
|
||||||
|
$filtered_keys = array_filter(array_keys($all_definitions), function ($key) {
|
||||||
|
return substr($key, -12) === '.entity_type';
|
||||||
|
});
|
||||||
|
$entity_type_definitions = array_intersect_key($all_definitions, array_flip($filtered_keys));
|
||||||
|
|
||||||
|
// Ensure that the returned array is keyed by the entity type ID.
|
||||||
|
$keys = array_keys($entity_type_definitions);
|
||||||
|
$keys = array_map(function ($key) {
|
||||||
|
$parts = explode('.', $key);
|
||||||
|
return $parts[0];
|
||||||
|
}, $keys);
|
||||||
|
|
||||||
|
return array_combine($keys, $entity_type_definitions);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -41,6 +41,34 @@ interface EntityLastInstalledSchemaRepositoryInterface {
|
||||||
*/
|
*/
|
||||||
public function getLastInstalledDefinition($entity_type_id);
|
public function getLastInstalledDefinition($entity_type_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the entity type definitions in their most recently installed state.
|
||||||
|
*
|
||||||
|
* During the application lifetime, entity type definitions can change. For
|
||||||
|
* example, updated code can be deployed. The
|
||||||
|
* \Drupal\Core\Entity\EntityTypeManagerInterface::getDefinitions() method
|
||||||
|
* will always return the definitions as determined by the current codebase.
|
||||||
|
* This method returns the definitions from the last time that a
|
||||||
|
* \Drupal\Core\Entity\EntityTypeListener event was completed. In other words,
|
||||||
|
* the definitions that the entity type's handlers have incorporated into the
|
||||||
|
* application state. For example, if the entity type's storage handler is
|
||||||
|
* SQL-based, the definition for which database tables were created.
|
||||||
|
*
|
||||||
|
* Application management code can check if
|
||||||
|
* \Drupal\Core\Entity\EntityTypeManagerInterface::getDefinitions() differs
|
||||||
|
* from getLastInstalledDefinitions() and decide whether to:
|
||||||
|
* - Invoke the appropriate \Drupal\Core\Entity\EntityTypeListenerInterface
|
||||||
|
* event so that handlers react to the new definitions.
|
||||||
|
* - Raise a warning that the application state is incompatible with the
|
||||||
|
* codebase.
|
||||||
|
* - Perform some other action.
|
||||||
|
*
|
||||||
|
* @return \Drupal\Core\Entity\EntityTypeInterface[]
|
||||||
|
* An array containing the installed definition for all entity types, keyed
|
||||||
|
* by the entity type ID.
|
||||||
|
*/
|
||||||
|
public function getLastInstalledDefinitions();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the entity type definition in the application state.
|
* Stores the entity type definition in the application state.
|
||||||
*
|
*
|
||||||
|
|
|
@ -20,6 +20,8 @@ use Drupal\Tests\system\Functional\Entity\Traits\EntityDefinitionTestTrait;
|
||||||
/**
|
/**
|
||||||
* Tests EntityDefinitionUpdateManager functionality.
|
* Tests EntityDefinitionUpdateManager functionality.
|
||||||
*
|
*
|
||||||
|
* @coversDefaultClass \Drupal\Core\Entity\EntityDefinitionUpdateManager
|
||||||
|
*
|
||||||
* @group Entity
|
* @group Entity
|
||||||
*/
|
*/
|
||||||
class EntityDefinitionUpdateTest extends EntityKernelTestBase {
|
class EntityDefinitionUpdateTest extends EntityKernelTestBase {
|
||||||
|
@ -1180,4 +1182,18 @@ class EntityDefinitionUpdateTest extends EntityKernelTestBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::getEntityTypes
|
||||||
|
*/
|
||||||
|
public function testGetEntityTypes() {
|
||||||
|
$entity_type_definitions = $this->entityDefinitionUpdateManager->getEntityTypes();
|
||||||
|
|
||||||
|
// Ensure that we have at least one entity type to check below.
|
||||||
|
$this->assertGreaterThanOrEqual(1, count($entity_type_definitions));
|
||||||
|
|
||||||
|
foreach ($entity_type_definitions as $entity_type_id => $entity_type) {
|
||||||
|
$this->assertEquals($this->entityDefinitionUpdateManager->getEntityType($entity_type_id), $entity_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue