Commit 246e95d4 authored by catch's avatar catch

Issue #2976103 by amateescu, tstoeckler, alexpott: Make it possible to...

Issue #2976103 by amateescu, tstoeckler, alexpott: Make it possible to retrieve all the last installed entity type definitions at once from the update manager
parent e2651fce
...@@ -575,7 +575,7 @@ services: ...@@ -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 ...@@ -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 @@ public function getChangeSummary() { ...@@ -63,7 +78,7 @@ public function getChangeSummary() {
// 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 @@ public function applyUpdates() { ...@@ -108,7 +123,7 @@ public function applyUpdates() {
// 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 @@ public function applyUpdates() { ...@@ -123,10 +138,17 @@ public function applyUpdates() {
* {@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 @@ public function installFieldStorageDefinition($name, $entity_type_id, $provider, ...@@ -173,7 +195,7 @@ public function installFieldStorageDefinition($name, $entity_type_id, $provider,
* {@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 @@ protected function doEntityUpdate($op, $entity_type_id) { ...@@ -211,7 +233,7 @@ protected function doEntityUpdate($op, $entity_type_id) {
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 @@ protected function getChangeList() { ...@@ -262,7 +284,7 @@ protected function getChangeList() {
$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 @@ protected function getChangeList() { ...@@ -277,7 +299,7 @@ protected function getChangeList() {
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 @@ public function applyUpdates(); ...@@ -108,6 +108,18 @@ public function applyUpdates();
*/ */
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,27 @@ public function getLastInstalledDefinition($entity_type_id) { ...@@ -34,6 +34,27 @@ public function getLastInstalledDefinition($entity_type_id) {
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.
$entity_type_definitions = array_filter($all_definitions, function ($key) {
return substr($key, -12) === '.entity_type';
}, ARRAY_FILTER_USE_KEY);
// 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 { ...@@ -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 @@ ...@@ -20,6 +20,8 @@
/** /**
* 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 @@ public function testInitialValueFromFieldErrorHandling() { ...@@ -1180,4 +1182,18 @@ public function testInitialValueFromFieldErrorHandling() {
} }
} }
/**
* @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);
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment