Problem/Motivation
EntityUpdateAddRevisionTranslationAffectedTest::testDeleteEntityType()
breaks loading of field configuration in post-update hook implementation,
#3052467-23: System update 8702 fails with " Error: Call to a member function getKey() on null in core\modules\system\system.install" →
. Any entity CRUD operations should be safe in post-update hook, but when we iterate over config entities (see patch for
🐛
Cannot load entity by uuid after rename
Needs work
) and try loading them by UUID through EntityRepositoryInterface::loadEntityByUuid()
, that triggers loading field definitions and results in PluginNotFoundException 'The entity_test_update entity type does not exist.'
being thrown.
The very same test fails now in
#2928906-35: The field schema incorrectly stores serial fields as int →
.
\Drupal\Tests\workspaces\Functional\Update\WorkspacesUpdateTest::testWorkspaceAssociationRemoval()
and EntityUpdateAddRevisionTranslationAffectedTest::testDeleteEntityType()
also failed in
#2928906-35: The field schema incorrectly stores serial fields as int →
.
The solution was to rewrite the update to:
function system_update_8901() {
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();
$entity_type_manager = \Drupal::entityTypeManager();
foreach ($definition_update_manager->getEntityTypes() as $entity_type_id => $entity_type) {
// Ensure that we are dealing with a non-deleted entity type.
if (!$entity_type || !($entity_type instanceof ContentEntityTypeInterface) || !$entity_type_manager->hasDefinition($entity_type_id)) {
continue;
}
which ensures that we will not touch deleted entity types during the update. However this is not a solution for an update doing something similar to
#3052467-23: System update 8702 fails with " Error: Call to a member function getKey() on null in core\modules\system\system.install" →
, where the entity type is retrieved indirectly by loading a field config through EntityRepositoryInterface::loadEntityByUuid()
which triggers
\Drupal\field\FieldConfigStorage::loadByProperties() ->
\Drupal\field\Entity\FieldConfig::getFieldStorageDefinition() ->
\Drupal\Core\Entity\EntityFieldManager::getFieldStorageDefinitions() ->
\Drupal\Core\Entity\EntityFieldManager::getBaseFieldDefinitions() ->
\Drupal\Core\Entity\EntityFieldManager::buildBaseFieldDefinitions() ->
\Drupal\Core\Entity\EntityTypeManager::getDefinition()
So here we have 2 problems.
- Retrieving a deleted entity type through the entity definition update manager, which does not have a definition in the entity type manager.
- Loading a deleted entity type from the entity type manager indirectly by loading a field config for it through
EntityRepositoryInterface::loadEntityByUuid()
.
The failing patch demonstrates both problems.
Proposed resolution
Maybe for the first problem we should prevent \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface::getEntityTypes()
from returning entity types with deleted definitions and make this possible only through a parameter.
How to solve the second problem?
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet