diff -u b/core/core.services.yml b/core/core.services.yml --- b/core/core.services.yml +++ b/core/core.services.yml @@ -281,10 +281,15 @@ arguments: ['@config.factory', '@module_handler', '@state', '@info_parser', '@logger.channel.default', '@asset.css.collection_optimizer', '@config.installer', '@router.builder'] entity.manager: class: Drupal\Core\Entity\EntityManager - arguments: ['@container.namespaces', '@module_handler', '@cache.discovery', '@language_manager', '@string_translation', '@class_resolver', '@typed_data_manager', '@state'] + arguments: ['@container.namespaces', '@module_handler', '@cache.discovery', '@language_manager', '@string_translation', '@class_resolver', '@typed_data_manager', '@entity.definitions.installed'] parent: container.trait tags: - { name: plugin_manager_cache_clear } + entity.definitions.installed: + class: Drupal\Core\KeyValueStore\KeyValueStoreInterface + factory_method: get + factory_service: keyvalue + arguments: ['entity.definitions.installed'] entity.definition_update_manager: class: Drupal\Core\Entity\EntityDefinitionUpdateManager arguments: ['@entity.manager'] diff -u b/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php --- b/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -22,7 +22,7 @@ use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Plugin\DefaultPluginManager; -use Drupal\Core\State\StateInterface; +use Drupal\Core\KeyValueStore\KeyValueStoreInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\Core\TypedData\TranslatableInterface; @@ -116,11 +116,11 @@ protected $languageManager; /** - * The state service. + * The keyvalue collection for tracking installed definitions. * - * @var \Drupal\Core\State\StateInterface + * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface */ - protected $state; + protected $installedDefinitions; /** * Static cache of bundle information. @@ -181,10 +181,10 @@ * The class resolver. * @param \Drupal\Core\TypedData\TypedDataManager $typed_data_manager * The typed data manager. - * @param \Drupal\Core\State\StateInterface $state - * The state service. + * @param \Drupal\Core\KeyValueStore\KeyValueStoreInterface $installed_definitions + * The keyvalue collection for tracking installed definitions. */ - public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, TranslationInterface $translation_manager, ClassResolverInterface $class_resolver, TypedDataManager $typed_data_manager, StateInterface $state) { + public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, TranslationInterface $translation_manager, ClassResolverInterface $class_resolver, TypedDataManager $typed_data_manager, KeyValueStoreInterface $installed_definitions) { parent::__construct('Entity', $namespaces, $module_handler, 'Drupal\Core\Entity\EntityInterface', 'Drupal\Core\Entity\Annotation\EntityType'); $this->setCacheBackend($cache, 'entity_type', array('entity_types' => TRUE)); @@ -194,7 +194,7 @@ $this->translationManager = $translation_manager; $this->classResolver = $class_resolver; $this->typedDataManager = $typed_data_manager; - $this->state = $state; + $this->installedDefinitions = $installed_definitions; } /** @@ -1133,7 +1133,7 @@ * {@inheritdoc} */ public function getLastInstalledDefinition($entity_type_id) { - return $this->state->get('entity.manager.' . $entity_type_id . '.entity_type'); + return $this->installedDefinitions->get($entity_type_id . '.entity_type'); } /** @@ -1144,7 +1144,7 @@ */ protected function setLastInstalledDefinition(EntityTypeInterface $entity_type) { $entity_type_id = $entity_type->id(); - $this->state->set('entity.manager.' . $entity_type_id . '.entity_type', $entity_type); + $this->installedDefinitions->set($entity_type_id . '.entity_type', $entity_type); } /** @@ -1154,18 +1154,18 @@ * The entity type definition identifier. */ protected function deleteLastInstalledDefinition($entity_type_id) { - $this->state->delete('entity.manager.' . $entity_type_id . '.entity_type'); + $this->installedDefinitions->delete($entity_type_id . '.entity_type'); // Clean up field storage definitions as well. Even if the entity type // isn't currently fieldable, there might be legacy definitions or an // empty array stored from when it was. - $this->state->delete('entity.manager.' . $entity_type_id . '.field_storage_definitions'); + $this->installedDefinitions->delete($entity_type_id . '.field_storage_definitions'); } /** * {@inheritdoc} */ public function getLastInstalledFieldStorageDefinitions($entity_type_id) { - return $this->state->get('entity.manager.' . $entity_type_id . '.field_storage_definitions'); + return $this->installedDefinitions->get($entity_type_id . '.field_storage_definitions'); } /** @@ -1177,7 +1177,7 @@ * An array of field storage definitions. */ protected function setLastInstalledFieldStorageDefinitions($entity_type_id, array $storage_definitions) { - $this->state->set('entity.manager.' . $entity_type_id . '.field_storage_definitions', $storage_definitions); + $this->installedDefinitions->set($entity_type_id . '.field_storage_definitions', $storage_definitions); } /** diff -u b/core/modules/system/system.module b/core/modules/system/system.module --- b/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -1055,7 +1055,7 @@ $storage_definitions = $entity_manager->getFieldStorageDefinitions($entity_type_id); // @todo Make it easier to query if there are entities: // https://www.drupal.org/node/2337753. - $has_data = $entity_manager->getStorage($entity_type_id)->countFieldData($storage_definitions[$entity_type->getKey('id')], TRUE); + $has_data = $entity_type->hasKey('id') && $entity_manager->getStorage($entity_type_id)->countFieldData($storage_definitions[$entity_type->getKey('id')], TRUE); if ($has_data) { foreach ($storage_definitions as $storage_definition) { if ($storage_definition->getProvider() == $module_name) { diff -u b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php --- b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php @@ -94,11 +94,11 @@ protected $typedDataManager; /** - * The state service. + * The keyvalue collection for tracking installed definitions. * - * @var \Drupal\Core\State\StateInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $state; + protected $installedDefinitions; /** * {@inheritdoc} @@ -136,7 +136,7 @@ ->disableOriginalConstructor() ->getMock(); - $this->state = $this->getMock('Drupal\Core\State\StateInterface'); + $this->installedDefinitions = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreInterface'); } /** @@ -167,7 +167,7 @@ ->method('getDefinitions') ->will($this->returnValue($definitions)); - $this->entityManager = new TestEntityManager(new \ArrayObject(), $this->moduleHandler, $this->cache, $this->languageManager, $this->translationManager, $this->getClassResolverStub(), $this->typedDataManager, $this->state); + $this->entityManager = new TestEntityManager(new \ArrayObject(), $this->moduleHandler, $this->cache, $this->languageManager, $this->translationManager, $this->getClassResolverStub(), $this->typedDataManager, $this->installedDefinitions); $this->entityManager->setContainer($this->container); $this->entityManager->setDiscovery($this->discovery); } only in patch2: unchanged: --- a/core/profiles/standard/standard.install +++ b/core/profiles/standard/standard.install @@ -14,6 +14,12 @@ * @see system_install() */ function standard_install() { + // Now that all modules are installed, make sure the entity storage and other + // handlers are up to date with the current entity and field definitions. For + // example, Path module adds a base field to nodes and taxonomy terms after + // those modules are already installed. + \Drupal::service('entity.definition_update_manager')->applyUpdates(); + // Set front page to "node". \Drupal::config('system.site')->set('page.front', 'node')->save();