diff --git a/core/core.services.yml b/core/core.services.yml index 2b31f93..11e999c 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -70,7 +70,7 @@ services: factory_method: getActive config.manager: class: Drupal\Core\Config\ConfigManager - arguments: ['@entity.manager', '@config.factory', '@config.typed', '@string_translation'] + arguments: ['@entity.manager', '@config.factory', '@config.typed', '@string_translation', '@config.storage'] config.storage: class: Drupal\Core\Config\CachedStorage arguments: ['@config.cachedstorage.storage', '@cache.config'] diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php index 2bb06b3..1aec4ed 100644 --- a/core/lib/Drupal/Core/Config/ConfigInstaller.php +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php @@ -131,6 +131,8 @@ public function installDefaultConfig($type, $name) { } $this->configFactory->setOverrideState($old_state); } + // Reset all the static caches and list caches. + $this->configFactory->reset(); } } diff --git a/core/lib/Drupal/Core/Config/ConfigManager.php b/core/lib/Drupal/Core/Config/ConfigManager.php index 65a7846..2c69497 100644 --- a/core/lib/Drupal/Core/Config/ConfigManager.php +++ b/core/lib/Drupal/Core/Config/ConfigManager.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Config; +use Drupal\Core\Config\Entity\ConfigDependencyManager; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\StringTranslation\TranslationManager; @@ -46,16 +47,24 @@ class ConfigManager implements ConfigManagerInterface { protected $stringTranslation; /** + * The active configuration storage. + * + * @var \Drupal\Core\Config\StorageInterface + */ + protected $activeStorage; + + /** * Creates ConfigManager objects. * * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager. */ - public function __construct(EntityManagerInterface $entity_manager, ConfigFactoryInterface $config_factory, TypedConfigManager $typed_config_manager, TranslationManager $string_translation) { + public function __construct(EntityManagerInterface $entity_manager, ConfigFactoryInterface $config_factory, TypedConfigManager $typed_config_manager, TranslationManager $string_translation, StorageInterface $active_storage) { $this->entityManager = $entity_manager; $this->configFactory = $config_factory; $this->typedConfigManager = $typed_config_manager; $this->stringTranslation = $string_translation; + $this->activeStorage = $active_storage; } /** @@ -121,10 +130,11 @@ function createSnapshot(StorageInterface $source_storage, StorageInterface $snap * @param string $type * The extension type; e.g., 'module' or 'theme'. * @param string $name - * The name of the module or theme to install default configuration for. + * The name of the module or theme to uninstall default configuration for. */ function uninstall($type, $name) { $config_names = $this->configFactory->listAll($name . '.'); + // @todo this should also use the entity api, no ? foreach ($config_names as $config_name) { $this->configFactory->get($config_name)->delete(); } @@ -135,4 +145,38 @@ function uninstall($type, $name) { $this->typedConfigManager->clearCachedDefinitions(); } } + + /** + * {@inheritdoc} + */ + public function findConfigEntityDependents($type, array $names) { + $dependency_manager = new ConfigDependencyManager($this->activeStorage); + $dependencies = array(); + foreach ($names as $name) { + $dependencies = array_merge($dependencies, $dependency_manager->getDependentEntities($type, $name)); + } + return $dependencies; + } + + /** + * {@inheritdoc} + */ + public function findConfigEntityDependentsAsEntities($type, array $names) { + $dependencies = $this->findConfigEntityDependents($type, $names); + $entities = array(); + $definitions = $this->entityManager->getDefinitions(); + foreach ($dependencies as $config_name => $dependency) { + // Group by entity type so we can use load multiple. + $entity_type_id = $this->getEntityTypeIdByName($config_name); + $id = substr($config_name, strlen($definitions[$entity_type_id]->getConfigPrefix()) + 1); + $entities[$entity_type_id][] = $id; + } + $entities_to_return = array(); + foreach ($entities as $entity_type_id => $entities_to_load) { + $storage_controller = $this->entityManager->getStorageController($entity_type_id); + $entities_to_return = $entities_to_return + $storage_controller->loadMultiple($entities_to_load); + } + return $entities_to_return; + } + } diff --git a/core/lib/Drupal/Core/Config/ConfigManagerInterface.php b/core/lib/Drupal/Core/Config/ConfigManagerInterface.php index e63108d..fbe46d6 100644 --- a/core/lib/Drupal/Core/Config/ConfigManagerInterface.php +++ b/core/lib/Drupal/Core/Config/ConfigManagerInterface.php @@ -68,4 +68,35 @@ public function createSnapshot(StorageInterface $source_storage, StorageInterfac */ public function uninstall($type, $name); + /** + * Finds config entities that are dependent on the supplied extensions or entities. + * + * @param string $type + * The type of dependency being checked. Either 'module', 'theme', 'entity'. + * @param array $names + * The specific names to check. If $type equals 'module' or 'theme' then it + * should be a list of module names or theme names. In the case of entity it + * should be a list of entity_type:uuid. + * + * @return \Drupal\Core\Config\Entity\ConfigEntityDependency[] + * An array of configuration entity dependency objects. + */ + public function findConfigEntityDependents($type, array $names); + + /** + * Finds config entities that are dependent on the supplied extensions or entities. + * + * @param string $type + * The type of dependency being checked. Either 'module', 'theme', 'entity'. + * @param array $names + * The specific names to check. If $type equals 'module' or 'theme' then it + * should be a list of module names or theme names. In the case of entity it + * should be a list of entity_type:uuid. + * + * @return \Drupal\Core\Config\Entity\ConfigEntityInterface[] + * An array of dependencies as configuration entities. + */ + public function findConfigEntityDependentsAsEntities($type, array $names); + + } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php new file mode 100644 index 0000000..a0af1b7 --- /dev/null +++ b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php @@ -0,0 +1,153 @@ +storage = $storage; + } + + /** + * @todo + */ + public function getDependentEntities($type, $name) { + $dependent_entities = array(); + // Load all the entities and check the dependency. No graph needed. + if ($type == 'module' || $type == 'theme') { + $dependent_entities = array_filter($this->loadAllTheThingies(TRUE), function (ConfigEntityDependency $entity) use ($type, $name) { + return $entity->hasDependency($type, $name); + }); + } + + $entities_to_check = array(); + if ($type == 'entity') { + $entities_to_check[] = $name; + } + else { + foreach ($dependent_entities as $entity) { + $entities_to_check[] = $entity->getConfigDependencyName(); + } + } + + return array_merge($dependent_entities, $this->graphConfigEntityDependencies($entities_to_check)); + } + + /** + * Creates a graph of config entity dependencies. + * + * @param array $entities_to_check + * The entities to supply dependencies for. + * @param string $direction + * The direction of the dependencies to check. Defaults to + * ConfigDependencyManager::DIRECTION_DEPENDENTS, alternate value is + * ConfigDependencyManager::DIRECTION_REQUIREMENTS. + */ + protected function graphConfigEntityDependencies($entities_to_check, $direction = ConfigDependencyManager::DIRECTION_DEPENDENTS) { + $dependent_entities = array(); + $graph = $this->getGraph(); + $all_the_thingies = $this->loadAllTheThingies(); + + foreach ($entities_to_check as $entity) { + if (isset($graph[$entity]) && !empty($graph[$entity][$direction])){ + foreach ($graph[$entity][$direction] as $dependency => $value) { + $config_name = substr($dependency, 0, strpos($dependency, ':')); + $dependent_entities[$config_name] = $all_the_thingies[$config_name]; + } + } + } + return $dependent_entities; + } + + /** + * Gets the dependency graph of all the config entities. + * + * @return array + * The dependency graph of all the config entities. + */ + protected function getGraph() { + if (!isset($this->graph)) { + $all_the_thingies = $this->loadAllTheThingies(); + foreach ($all_the_thingies as $entity) { + $graph_key = $entity->getConfigDependencyName(); + $graph[$graph_key]['edges'] = array(); + $dependencies = $entity->getDependencies('entity'); + if (!empty($dependencies)) { + foreach ($dependencies as $dependency) { + $graph[$graph_key]['edges'][$dependency] = TRUE; + } + } + } + $graph_object = new Graph($graph); + $this->graph = $graph_object->searchAndSort(); + } + return $this->graph; + } + + /** + * Loads all the thingies. + * + * This uses the configuration storage directly to avoid blowing the static + * caches in the configuration factory and the configuration entity system. + * Additionally this ensures that configuration entity dependency discovery + * has no dependencies on the config entity classes. + * + * @return \Drupal\Core\Config\Entity\ConfigEntityDependency[] + */ + protected function loadAllTheThingies () { + if (empty($this->allTheThingies)) { + // Load all the configuration and filter out configuration which does not + // have the special keys 'dependencies' and 'uuid'. + $this->allTheThingies = array_filter( + $this->storage->readMultiple($this->storage->listAll()), + function ($config) { + return isset($config['uuid']); + } + ); + array_walk($this->allTheThingies, function (&$config, $name) { + $config = new ConfigEntityDependency($name, $config); + }); + } + return $this->allTheThingies; + } + +} diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index cd870f2..5b5c01e 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -43,6 +43,20 @@ private $isSyncing = FALSE; /** + * Whether the config is deleted through the uninstall process. + * + * @var bool + */ + private $isUninstalling = FALSE; + + /** + * The configuration entity's dependencies. + * + * @var array + */ + protected $dependencies = array(); + + /** * Overrides Entity::__construct(). */ public function __construct(array $values, $entity_type) { @@ -143,6 +157,20 @@ public function isSyncing() { /** * {@inheritdoc} */ + public function setUninstalling($uninstalling) { + $this->isUninstalling = $uninstalling; + } + + /** + * {@inheritdoc} + */ + public function isUninstalling() { + return $this->isUninstalling; + } + + /** + * {@inheritdoc} + */ public function createDuplicate() { $duplicate = parent::createDuplicate(); // Prevent the new duplicate from being misinterpreted as a rename. @@ -176,6 +204,10 @@ public function getExportProperties() { $name = $property->getName(); $properties[$name] = $this->get($name); } + if (!empty($this->dependencies)) { + // Add protected dependencies property if set. + $properties['dependencies'] = $this->dependencies; + } return $properties; } @@ -225,4 +257,34 @@ public function url($rel = 'edit-form', $options = array()) { return parent::url($rel, $options); } + /** + * {@inheritdoc} + */ + public function createDependency($type, $name) { + if (empty($this->dependencies[$type])) { + $this->dependencies[$type] = array($name); + } + elseif (!in_array($name, $this->dependencies[$type])) { + $this->dependencies[$type][] = $name; + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function removeDependency($type, $name) { + $key = array_search($name, $this->dependencies[$type]); + if ($key !== FALSE) { + unset($this->dependencies[$type][$key]); + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function getConfigDependencyName() { + return $this->getEntityType()->getConfigPrefix() . '.' . $this->id() . ':' . $this->uuid(); + } } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityDependency.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityDependency.php new file mode 100644 index 0000000..ef9b28f --- /dev/null +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityDependency.php @@ -0,0 +1,153 @@ +name = $name; + $this->uuid = $values['uuid']; + $this->entityType = $this->setEntityType($name); + if (isset($values['dependencies'])) { + $this->dependencies = $values['dependencies']; + } + else { + $this->dependencies = array(); + } + } + + /** + * Gets the configuration entity's UUID. + * + * @return string + * The configuration entity's UUID. + */ + public function uuid() { + return $this->uuid; + } + + /** + * Gets the configuration entity's dependencies of the supplied type. + * + * @param string $type + * The type of dependency to return. Either 'module', 'theme', 'entity'. + * + * @return array + * The list of dependencies of the supplied type. + */ + public function getDependencies($type) { + if (isset($this->dependencies[$type])) { + return $this->dependencies[$type]; + } + return array(); + } + + /** + * Determines if the entity is dependent on the supplied extensions or entities. + * + * @param string $type + * The type of dependency being checked. Either 'module', 'theme', 'entity'. + * @param string $name + * The specific name to check. If $type equals 'module' or 'theme' then it + * should be a module name or theme name. In the case of entity it + * should be configuration_name:uuid. + * + * @return bool + */ + public function hasDependency($type, $name) { + // A config entity is always dependent on it's provider. + if ($type == 'module' && strpos($this->name, $name . '.') === 0) { + return TRUE; + } + return isset($this->dependencies[$type]) && array_search($name, $this->dependencies[$type]) !== FALSE; + } + + /** + * Gets the configuration entity's configuration object name. + * + * @return string + * The configuration object name. + */ + public function getName() { + return $this->name; + } + + /** + * Gets the entity type of this object. + * + * @return string + * The entity type. + */ + public function getEntityType() { + return $this->entityType; + } + + public function setEntityType($name) { + // @todo copied from ConfigManager::getEntityTypeIdByName() + $entities = array_filter(\Drupal::entityManager()->getDefinitions(), function (EntityTypeInterface $entity_type) use ($name) { + return ($config_prefix = $entity_type->getConfigPrefix()) && strpos($name, $config_prefix . '.') === 0; + }); + return key($entities); + + } + + /** + * Gets the configuration entity's configuration dependency name. + * + * @return string + * The configuration dependency name for the entity. + */ + public function getConfigDependencyName() { + return $this->getName() . ':' . $this->uuid(); + } + + // @todo copied from ConfigStorageController::getIDFromConfigName() + function getIDFromConfigName() { + return substr($this->name, strlen(\Drupal::entityManager()->getDefinition($this->getEntityType())->getConfigPrefix() . '.')); + } + +} diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php index 5aa737d..7145310 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php @@ -92,6 +92,14 @@ public function status(); public function isSyncing(); /** + * Returns whether the configuration entity is deleted through the import + * process. + * + * @return bool + */ + public function isUninstalling(); + + /** * Returns the value of a property. * * @param string $property_name @@ -122,4 +130,38 @@ public function set($property_name, $value); */ public function getExportProperties(); + /** + * Creates a dependency. + * + * @param string $type + * The type of dependency being checked. Either 'module', 'theme', 'entity'. + * @param string $name + * If $type equals 'module' or 'theme' then it should be the name of the + * module or theme. In the case of entity it should be entity_type:uuid. + * + * @return $this + */ + public function createDependency($type, $name); + + /** + * Removes a dependency. + * + * @param string $type + * The type of dependency being checked. Either 'module', 'theme', 'entity'. + * @param string $name + * If $type equals 'module' or 'theme' then it should be the name of the + * module or theme. In the case of entity it should be entity_type:uuid. + * + * @return $this + */ + public function removeDependency($type, $name); + + /** + * Gets the configuration dependency name. + * + * @return string + * The configuration dependency name. + */ + public function getConfigDependencyName(); + } diff --git a/core/lib/Drupal/Core/Config/Schema/core.data_types.schema.yml b/core/lib/Drupal/Core/Config/Schema/core.data_types.schema.yml index 5395c16..47d3e09 100644 --- a/core/lib/Drupal/Core/Config/Schema/core.data_types.schema.yml +++ b/core/lib/Drupal/Core/Config/Schema/core.data_types.schema.yml @@ -136,3 +136,24 @@ route: sequence: - type: string label: 'Param' + +# Config dependencies. +config_dependency: + type: mapping + label: 'Configuration dependencies' + mapping: + entity: + type: sequence + label: 'Entity dependencies' + sequence: + - type: string + module: + type: sequence + label: 'Module dependencies' + sequence: + - type: string + theme: + type: sequence + label: 'Theme dependencies' + sequence: + - type: string diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php index 001e278..72534a7 100644 --- a/core/lib/Drupal/Core/Extension/ModuleHandler.php +++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php @@ -724,6 +724,24 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) { // Uninstall the module. module_load_install($module); $this->invoke($module, 'uninstall'); + + // Remove all dependent configuration entities. + // @todo maybe move the call to configManager::uninstall() to here + // and move this code in that method ? + // @todo start a batch purge any leftover field data. Field API does one + // purge call anyway, so in case there was no data in the tables, this + // will be fast. + $dependent_entities = \Drupal::service('config.manager')->findConfigEntityDependents('module', array($module)); + foreach ($dependent_entities as $dependent_entity) { + $entity = \Drupal::entityManager()->getStorageController($dependent_entity->getEntityType())->load($dependent_entity->getIDFromConfigName()); + // Sometimes entities can be deleted already, e.g. field instances. + if ($entity) { + $entity->setUninstalling(TRUE); + $entity->delete(); + } + } + + // Remove the schema. drupal_uninstall_schema($module); // Remove the module's entry from the config. @@ -820,4 +838,5 @@ public function getModuleDirectories() { } return $dirs; } + } diff --git a/core/modules/aggregator/config/views.view.aggregator_rss_feed.yml b/core/modules/aggregator/config/views.view.aggregator_rss_feed.yml index 2590960..39d11ca 100644 --- a/core/modules/aggregator/config/views.view.aggregator_rss_feed.yml +++ b/core/modules/aggregator/config/views.view.aggregator_rss_feed.yml @@ -137,8 +137,11 @@ display: defaults: arguments: true label: 'Aggregator RSS feed' -module: views +module: aggregator id: aggregator_rss_feed tag: aggregator uuid: 7dfa5cb7-2248-4d52-8c00-cd8e02d1e78e langcode: en +dependencies: + module: + - aggregator diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php index f038cb1..a4bc5cd 100644 --- a/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php +++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php @@ -219,6 +219,7 @@ public function getExportProperties() { 'sourceType', 'status', 'langcode', + 'dependencies', ); $properties = array(); foreach ($names as $name) { diff --git a/core/modules/comment/config/views.view.comments_recent.yml b/core/modules/comment/config/views.view.comments_recent.yml index e6559fe..c51fd7f 100644 --- a/core/modules/comment/config/views.view.comments_recent.yml +++ b/core/modules/comment/config/views.view.comments_recent.yml @@ -228,3 +228,7 @@ id: comments_recent tag: default langcode: en uuid: 67212880-6a63-453b-a902-2d13580f7d1c +dependencies: + module: + - comment + - views diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php index df6c96d..117e213 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php @@ -100,4 +100,60 @@ protected function testGetOriginalId() { $this->assertIdentical($entity->getOriginalId(), $id); } + /** + * Tests setDependency(), hasDependency() and removeDependency(). + */ + public function testDependencyMangement() { + // Test dependencies between entities. + $entity1 = $this->storage->create(array('id' => 'entity1')); + $entity2 = $this->storage->create(array('id' => 'entity2')); + $entity3 = $this->storage->create(array('id' => 'entity3')); + $entity4 = $this->storage->create(array('id' => 'entity4')); + + $entity1->createDependency('module', 'node'); + $entity4->createDependency('entity', $entity3->getConfigDependencyName()); + $entity3->createDependency('entity', $entity2->getConfigDependencyName()); + $entity2->createDependency('entity', $entity1->getConfigDependencyName()); + + $entity1->save(); + $entity2->save(); + $entity3->save(); + $entity4->save(); + + $config_manager = \Drupal::service('config.manager'); + + // Test getting $entity1's dependencies as configuration dependency objects. + $dependents = $config_manager->findConfigEntityDependents('entity', array($entity1->getConfigDependencyName())); + $this->assertFalse(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 does not have a dependency on itself.'); + $this->assertTrue(isset($dependents['config_test.dynamic.entity2']), 'config_test.dynamic.entity1 has a dependency on config_test.dynamic.entity1.'); + $this->assertTrue(isset($dependents['config_test.dynamic.entity3']), 'config_test.dynamic.entity1 has a dependency on config_test.dynamic.entity1.'); + $this->assertTrue(isset($dependents['config_test.dynamic.entity4']), 'config_test.dynamic.entity1 has a dependency on config_test.dynamic.entity1.'); + + // Test getting $entity2's dependencies as entities. + $dependents = $config_manager->findConfigEntityDependentsAsEntities('entity', array($entity2->getConfigDependencyName())); + $this->assertFalse(isset($dependents['entity1']), 'config_test.dynamic.entity2 does not have a dependency on config_test.dynamic.entity1.'); + $this->assertFalse(isset($dependents['entity2']), 'config_test.dynamic.entity2 does not have a dependency on itself.'); + $this->assertTrue(isset($dependents['entity3']), 'config_test.dynamic.entity2 has a dependency on config_test.dynamic.entity3.'); + $this->assertTrue(isset($dependents['entity4']), 'config_test.dynamic.entity2 has a dependency on config_test.dynamic.entity3.'); + + // Test getting node module's dependencies as configuration dependency + // objects. + $dependents = $config_manager->findConfigEntityDependents('module', array('node')); + $this->assertTrue(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 has a dependency on the Node module.'); + $this->assertTrue(isset($dependents['config_test.dynamic.entity2']), 'config_test.dynamic.entity2 has a dependency on the Node module.'); + $this->assertTrue(isset($dependents['config_test.dynamic.entity3']), 'config_test.dynamic.entity3 has a dependency on the Node module.'); + $this->assertTrue(isset($dependents['config_test.dynamic.entity4']), 'config_test.dynamic.entity4 has a dependency on the Node module.'); + + // Test getting node module's dependencies as configuration dependency + // objects after making $entity3 also dependent on node. + $entity1->removeDependency('module', 'node')->save(); + $entity3->createDependency('module', 'node')->save(); + $dependents = $config_manager->findConfigEntityDependents('module', array('node')); + $this->assertFalse(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 does not have a dependency on the Node module.'); + $this->assertFalse(isset($dependents['config_test.dynamic.entity2']), 'config_test.dynamic.entity2 does not have a dependency on the Node module.'); + $this->assertTrue(isset($dependents['config_test.dynamic.entity3']), 'config_test.dynamic.entity3 has a dependency on the Node module.'); + $this->assertTrue(isset($dependents['config_test.dynamic.entity4']), 'config_test.dynamic.entity4 has a dependency on the Node module.'); + + } + } diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigOtherModuleTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigOtherModuleTest.php index 90915fc..3342808 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigOtherModuleTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigOtherModuleTest.php @@ -93,4 +93,16 @@ public function testInstallConfigEnityModuleFirst() { $this->assertTrue(entity_load('config_test', 'other_module', TRUE), 'Default configuration provided by config_other_module_config has been installed.'); } + /** + * Tests uninstalling node removes views which are dependent on them. + */ + public function testUninstall() { + $this->moduleHandler->install(array('views')); + $this->assertTrue(entity_load('view', 'frontpage', TRUE) === NULL, 'After installing Views, frontpage view which is dependant on the Node and Views modules does not exist.'); + $this->moduleHandler->install(array('node')); + $this->assertTrue(entity_load('view', 'frontpage', TRUE) !== NULL, 'After installing Node, frontpage view which is dependant on the Node and Views modules exists.'); + $this->moduleHandler->uninstall(array('node')); + $this->assertTrue(entity_load('view', 'frontpage', TRUE) === NULL, 'After uninstalling Node, frontpage view which is dependant on the Node and Views modules does not exist.'); + } + } diff --git a/core/modules/field/config/schema/field.schema.yml b/core/modules/field/config/schema/field.schema.yml index 66a1444..5cfc8cb 100644 --- a/core/modules/field/config/schema/field.schema.yml +++ b/core/modules/field/config/schema/field.schema.yml @@ -56,6 +56,9 @@ field.field.*.*: sequence: - type: string label: 'Column' + dependencies: + type: config_dependency + label: 'Dependencies' field.instance.*.*.*: type: mapping @@ -104,6 +107,9 @@ field.instance.*.*.*: field_type: type: string label: 'Field type' + dependencies: + type: config_dependency + label: 'Dependencies' entity_form_display.field.hidden: type: entity_field_form_display_base diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 6a8b941..bec8166 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -144,45 +144,6 @@ function field_cron() { } /** - * Implements hook_system_info_alter(). - * - * Goes through a list of all modules that provide a field type and makes them - * required if there are any active fields of that type. - */ -function field_system_info_alter(&$info, $file, $type) { - // It is not safe to call entity_load_multiple_by_properties() during - // maintenance mode. - if ($type == 'module' && !defined('MAINTENANCE_MODE')) { - $fields = entity_load_multiple_by_properties('field_entity', array('module' => $file->name, 'include_deleted' => TRUE)); - if ($fields) { - $info['required'] = TRUE; - - // Provide an explanation message (only mention pending deletions if there - // remains no actual, non-deleted fields) - $non_deleted = FALSE; - foreach ($fields as $field) { - if (empty($field->deleted)) { - $non_deleted = TRUE; - break; - } - } - if ($non_deleted) { - if (\Drupal::moduleHandler()->moduleExists('field_ui')) { - $explanation = t('Field type(s) in use - see Field list', array('@fields-page' => url('admin/reports/fields'))); - } - else { - $explanation = t('Fields type(s) in use'); - } - } - else { - $explanation = t('Fields pending deletion'); - } - $info['explanation'] = $explanation; - } - } -} - -/** * Implements hook_entity_field_info() to define all configured fields. */ function field_entity_field_info($entity_type) { diff --git a/core/modules/field/lib/Drupal/field/Entity/Field.php b/core/modules/field/lib/Drupal/field/Entity/Field.php index 69c7551..ae2c050 100644 --- a/core/modules/field/lib/Drupal/field/Entity/Field.php +++ b/core/modules/field/lib/Drupal/field/Entity/Field.php @@ -262,6 +262,7 @@ public function getExportProperties() { 'cardinality', 'translatable', 'indexes', + 'dependencies', ); $properties = array(); foreach ($names as $name) { @@ -336,6 +337,9 @@ protected function preSaveNew(EntityStorageControllerInterface $storage_controll // definition is passed to the various hooks and written to config. $this->settings += $field_type['settings']; + // Ensure the field is dependent on the providing module. + $this->createDependency('module', $this->module); + // Notify the entity storage controller. $entity_manager->getStorageController($this->entity_type)->onFieldCreate($this); } @@ -419,6 +423,7 @@ public static function preDelete(EntityStorageControllerInterface $storage_contr $deleted_fields[$field->uuid] = $config; } } + $state->set('field.field.deleted', $deleted_fields); } diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php index 620e48c..cc9e1b6 100644 --- a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php +++ b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php @@ -318,6 +318,7 @@ public function getExportProperties() { 'default_value', 'default_value_function', 'settings', + 'dependencies', ); $properties = array(); foreach ($names as $name) { @@ -367,6 +368,9 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { // Notify the entity storage controller. $entity_manager->getStorageController($this->entity_type)->onInstanceUpdate($this); } + + // Manage dependencies. + $this->createDependency('entity', $this->field->getConfigDependencyName()); } /** diff --git a/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import.yml b/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import.yml index 20b5662..28036f9 100644 --- a/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import.yml +++ b/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import.yml @@ -12,3 +12,6 @@ translatable: false indexes: format: - format +dependencies: + module: + - text diff --git a/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import_2.yml b/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import_2.yml index a94a715..4c2042b 100644 --- a/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import_2.yml +++ b/core/modules/field/tests/modules/field_test_config/config/field.field.entity_test.field_test_import_2.yml @@ -12,3 +12,6 @@ translatable: false indexes: format: - format +dependencies: + module: + - text diff --git a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging.yml b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging.yml index 127a97a..f4b6e1a 100644 --- a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging.yml +++ b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging.yml @@ -13,3 +13,6 @@ translatable: '0' indexes: format: - format +dependencies: + module: + - text diff --git a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging_2.yml b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging_2.yml index 017e9db..8bb4272 100644 --- a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging_2.yml +++ b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.field_test_import_staging_2.yml @@ -13,3 +13,6 @@ translatable: '0' indexes: format: - format +dependencies: + module: + - text diff --git a/core/modules/file/config/views.view.files.yml b/core/modules/file/config/views.view.files.yml index e192361..6c65416 100644 --- a/core/modules/file/config/views.view.files.yml +++ b/core/modules/file/config/views.view.files.yml @@ -1041,3 +1041,7 @@ id: files tag: default uuid: 4b47e09e-16e0-494b-b447-7166191dbb6e langcode: en +dependencies: + module: + - file + - views diff --git a/core/modules/forum/config/field.field.forum.forum_container.yml b/core/modules/forum/config/field.field.forum.forum_container.yml index f13aa4d..64e822c 100644 --- a/core/modules/forum/config/field.field.forum.forum_container.yml +++ b/core/modules/forum/config/field.field.forum.forum_container.yml @@ -15,3 +15,6 @@ locked: true cardinality: 1 translatable: false indexes: { } +dependencies: + module: + - options diff --git a/core/modules/language/lib/Drupal/language/Entity/Language.php b/core/modules/language/lib/Drupal/language/Entity/Language.php index 63e8542..bd4a8f6 100644 --- a/core/modules/language/lib/Drupal/language/Entity/Language.php +++ b/core/modules/language/lib/Drupal/language/Entity/Language.php @@ -107,7 +107,7 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { public static function preDelete(EntityStorageControllerInterface $storage_controller, array $entities) { $default_language = \Drupal::service('language.default')->get(); foreach ($entities as $entity) { - if ($entity->id() == $default_language->id) { + if ($entity->id() == $default_language->id && !$entity->isUninstalling()) { throw new DeleteDefaultLanguageException('Can not delete the default language'); } } diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php index f7c64bf..c4c5be2 100644 --- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php +++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php @@ -131,7 +131,7 @@ function testConfigTranslation() { // Enable the image module. $this->drupalPostForm('admin/modules', array('modules[Field types][image][enable]' => "1"), t('Save configuration')); - $this->resetAll(); + $this->rebuildContainer(); $string = $this->storage->findString(array('source' => 'Medium (220x220)', 'context' => '', 'type' => 'configuration')); $this->assertTrue($string, 'Configuration strings have been created upon installation.'); diff --git a/core/modules/views/config/views.view.archive.yml b/core/modules/node/config/views.view.archive.yml similarity index 99% rename from core/modules/views/config/views.view.archive.yml rename to core/modules/node/config/views.view.archive.yml index b9bb1fc..8b8372b 100644 --- a/core/modules/views/config/views.view.archive.yml +++ b/core/modules/node/config/views.view.archive.yml @@ -163,3 +163,6 @@ id: archive tag: default uuid: 39fb337d-c126-446c-8345-6908b45313ca langcode: en +dependencies: + module: + - node diff --git a/core/modules/node/config/views.view.content.yml b/core/modules/node/config/views.view.content.yml index c985545..43eb097 100644 --- a/core/modules/node/config/views.view.content.yml +++ b/core/modules/node/config/views.view.content.yml @@ -342,6 +342,7 @@ display: hide_alter_empty: true link_to_node: false comments: false + optional: true plugin_id: history_user_timestamp provider: history filters: @@ -552,3 +553,8 @@ id: content tag: default uuid: 914eaf17-0b90-4fcd-a312-18b51e9dac77 langcode: en +dependencies: + module: + - node + - user + - views diff --git a/core/modules/node/config/views.view.content_recent.yml b/core/modules/node/config/views.view.content_recent.yml index 26be0d7..d498dae 100644 --- a/core/modules/node/config/views.view.content_recent.yml +++ b/core/modules/node/config/views.view.content_recent.yml @@ -200,6 +200,7 @@ display: hide_alter_empty: true link_to_node: false comments: false + optional: true plugin_id: history_user_timestamp provider: history name: @@ -455,8 +456,13 @@ display: link_url: admin/content block_category: 'Lists (Views)' label: 'Recent content' -module: views +module: node id: content_recent tag: default uuid: 22208367-bde8-4977-ae04-4f1a34383ae3 langcode: en +dependencies: + module: + - node + - user + - views diff --git a/core/modules/node/config/views.view.frontpage.yml b/core/modules/node/config/views.view.frontpage.yml index a7526a1..b3b6c48 100644 --- a/core/modules/node/config/views.view.frontpage.yml +++ b/core/modules/node/config/views.view.frontpage.yml @@ -231,3 +231,7 @@ id: frontpage tag: default uuid: 5c8da842-af9f-4a6e-bd00-af738b26ec3c langcode: en +dependencies: + module: + - node + - views diff --git a/core/modules/views/config/views.view.glossary.yml b/core/modules/node/config/views.view.glossary.yml similarity index 99% rename from core/modules/views/config/views.view.glossary.yml rename to core/modules/node/config/views.view.glossary.yml index 7d5f284..55d9106 100644 --- a/core/modules/views/config/views.view.glossary.yml +++ b/core/modules/node/config/views.view.glossary.yml @@ -371,3 +371,8 @@ id: glossary tag: default uuid: da0cfcf2-3e94-436f-a900-0dd0c2310cd7 langcode: en +dependencies: + module: + - node + - user + - views diff --git a/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php b/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php index 662f44d..675e8e3 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php +++ b/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php @@ -155,6 +155,7 @@ public function getExportProperties() { 'bundle', 'types', 'fieldMappings', + 'dependencies', ); $properties = array(); foreach ($names as $name) { diff --git a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php index 738dda2..78a466b 100644 --- a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php +++ b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallConfirmForm.php @@ -121,6 +121,33 @@ public function buildForm(array $form, array &$form_state) { }, $this->modules), ); + $form['entities'] = array( + '#type' => 'details', + '#title' => $this->t('Further information'), + '#description' => $this->t('The listed entities will be deleted.'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#access' => FALSE, + ); + + // Get the dependent entities. + $dependent_entities = \Drupal::service('config.manager')->findConfigEntityDependentsAsEntities('module', $this->modules); + if (!empty($dependent_entities)) { + $form['entities']['#access'] = TRUE; + } + foreach ($dependent_entities as $entity) { + $entity_type_id = $entity->getEntityTypeId(); + if (!isset($form['entities'][$entity_type_id])) { + $entity_type = \Drupal::entityManager()->getDefinition($entity_type_id); + $form['entities'][$entity_type_id] = array( + '#theme' => 'item_list', + '#title' => $entity_type->getLabel(), + '#items' => array(), + ); + } + $form['entities'][$entity_type_id]['#items'][] = $entity->label(); + } + return parent::buildForm($form, $form_state); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/ModuleTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Module/ModuleTestBase.php index 95844f6..d420cdc 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Module/ModuleTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Module/ModuleTestBase.php @@ -193,6 +193,6 @@ function assertLogMessage($type, $message, $variables = array(), $severity = WAT ->countQuery() ->execute() ->fetchField(); - $this->assertTrue($count > 0, format_string('watchdog table contains @count rows for @message', array('@count' => $count, '@message' => $message))); + $this->assertTrue($count > 0, format_string('watchdog table contains @count rows for @message', array('@count' => $count, '@message' => format_string($message, $variables)))); } } diff --git a/core/modules/views/config/views.view.taxonomy_term.yml b/core/modules/taxonomy/config/views.view.taxonomy_term.yml similarity index 98% rename from core/modules/views/config/views.view.taxonomy_term.yml rename to core/modules/taxonomy/config/views.view.taxonomy_term.yml index ed7c0ba..4b1cf08 100644 --- a/core/modules/views/config/views.view.taxonomy_term.yml +++ b/core/modules/taxonomy/config/views.view.taxonomy_term.yml @@ -235,3 +235,8 @@ id: taxonomy_term tag: default uuid: e0dea92e-a4c9-4442-a518-2499bfe17d73 langcode: en +dependencies: + module: + - node + - taxonomy + - views diff --git a/core/modules/user/config/views.view.user_admin_people.yml b/core/modules/user/config/views.view.user_admin_people.yml index 50506c6..2afff6a 100644 --- a/core/modules/user/config/views.view.user_admin_people.yml +++ b/core/modules/user/config/views.view.user_admin_people.yml @@ -944,7 +944,10 @@ display: defaults: show_admin_links: false label: People -module: views +module: user id: user_admin_people tag: default langcode: und +dependencies: + module: + - user diff --git a/core/modules/user/config/views.view.who_s_new.yml b/core/modules/user/config/views.view.who_s_new.yml index e3f9e2b..670234c 100644 --- a/core/modules/user/config/views.view.who_s_new.yml +++ b/core/modules/user/config/views.view.who_s_new.yml @@ -160,8 +160,11 @@ display: relationships: { } arguments: { } label: 'Who''s new' -module: views +module: user id: who_s_new tag: default uuid: 8b2c05e3-046b-447f-922b-43a832220667 langcode: en +dependencies: + module: + - user diff --git a/core/modules/user/config/views.view.who_s_online.yml b/core/modules/user/config/views.view.who_s_online.yml index 8665ae0..a5588cf 100644 --- a/core/modules/user/config/views.view.who_s_online.yml +++ b/core/modules/user/config/views.view.who_s_online.yml @@ -191,8 +191,11 @@ display: block_description: 'Who''s online' display_description: 'A list of users that are currently logged in.' label: 'Who''s online block' -module: views +module: user id: who_s_online tag: default uuid: 67a78cad-cf14-4f0d-9705-05d50cd84eaa langcode: en +dependencies: + module: + - user diff --git a/core/modules/views/config/schema/views.schema.yml b/core/modules/views/config/schema/views.schema.yml index a9a7eaf..933d839 100644 --- a/core/modules/views/config/schema/views.schema.yml +++ b/core/modules/views/config/schema/views.schema.yml @@ -117,3 +117,6 @@ views.view.*: label: 'Position' display_options: type: views.display.[%parent.display_plugin] + dependencies: + type: config_dependency + label: 'Dependencies' diff --git a/core/modules/views/lib/Drupal/views/Entity/View.php b/core/modules/views/lib/Drupal/views/Entity/View.php index f96fbd0..a721c43 100644 --- a/core/modules/views/lib/Drupal/views/Entity/View.php +++ b/core/modules/views/lib/Drupal/views/Entity/View.php @@ -22,7 +22,7 @@ * id = "view", * label = @Translation("View"), * controllers = { - * "storage" = "Drupal\views\ViewStorageController", + * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "access" = "Drupal\views\ViewAccessController" * }, * admin_permission = "administer views", @@ -265,6 +265,7 @@ public function getExportProperties() { 'tag', 'uuid', 'langcode', + 'dependencies', ); $properties = array(); foreach ($names as $name) { @@ -276,6 +277,40 @@ public function getExportProperties() { /** * {@inheritdoc} */ + public function preSave(EntityStorageControllerInterface $storage_controller) { + parent::preSave($storage_controller); + // Clear out the dependencies since we're going to recalculate them. + $this->dependencies = array(); + + // Ensure that the view is dependant on the module that implements the view. + $this->createDependency('module', $this->module); + // Ensure that the view is dependant on the module that provides the schema + // for the base table. + $schema = drupal_get_schema($this->base_table); + if ($this->module != $schema['module']) { + $this->createDependency('module', $schema['module']); + } + + $handler_types = array(); + foreach (ViewExecutable::viewsHandlerTypes() as $type) { + $handler_types[] = $type['plural']; + } + foreach ($this->get('display') as $display) { + foreach ($handler_types as $handler_type) { + if (!empty($display['display_options'][$handler_type])) { + foreach ($display['display_options'][$handler_type] as $handler) { + if (isset($handler['provider']) && empty($handler['optional'])) { + $this->createDependency('module', $handler['provider']); + } + } + } + } + } + } + + /** + * {@inheritdoc} + */ public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) { parent::postSave($storage_controller, $update); diff --git a/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php b/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php index 8c31874..ed194cf 100644 --- a/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/ModuleTest.php @@ -151,6 +151,7 @@ public function customErrorHandler($error_level, $message, $filename, $line, $co */ public function testLoadFunctions() { $this->enableModules(array('node')); + $this->installConfig(array('node')); $controller = $this->container->get('entity.manager')->getStorageController('view'); // Test views_view_is_enabled/disabled. diff --git a/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php b/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php index ba67b0a..37d5ca7 100644 --- a/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php @@ -8,17 +8,17 @@ namespace Drupal\views\Tests; use Drupal\Core\Entity\EntityTypeInterface; -use Drupal\views\ViewStorageController; +use Drupal\Core\Config\Entity\ConfigStorageController; use Drupal\views\Entity\View; use Drupal\views\Plugin\views\display\Page; use Drupal\views\Plugin\views\display\DefaultDisplay; use Drupal\views\Plugin\views\display\Feed; /** - * Tests the functionality of View and ViewStorageController. + * Tests the functionality of View and ConfigStorageController. * * @see \Drupal\views\Entity\View - * @see \Drupal\views\ViewStorageController + * @see \Drupal\Core\Config\Entity\ConfigStorageController */ class ViewStorageTest extends ViewUnitTestBase { @@ -49,7 +49,7 @@ class ViewStorageTest extends ViewUnitTestBase { /** * The configuration entity storage controller. * - * @var \Drupal\views\ViewStorageController + * @var \Drupal\Core\Config\Entity\ConfigStorageController */ protected $controller; @@ -80,7 +80,7 @@ function testConfigurationEntityCRUD() { $this->assertTrue($this->entityType instanceof EntityTypeInterface, 'The View info array is loaded.'); // Confirm we have the correct controller class. - $this->assertTrue($this->controller instanceof ViewStorageController, 'The correct controller is loaded.'); + $this->assertTrue($this->controller instanceof ConfigStorageController, 'The correct controller is loaded.'); // CRUD tests. $this->loadTests(); diff --git a/core/modules/views/lib/Drupal/views/ViewStorageController.php b/core/modules/views/lib/Drupal/views/ViewStorageController.php deleted file mode 100644 index a418fb1..0000000 --- a/core/modules/views/lib/Drupal/views/ViewStorageController.php +++ /dev/null @@ -1,33 +0,0 @@ -moduleExists($entity->get('module'))) { - return TRUE; - } - return FALSE; - }); - } - -} diff --git a/core/modules/views/tests/Drupal/views/Tests/EventSubscriber/RouteSubscriberTest.php b/core/modules/views/tests/Drupal/views/Tests/EventSubscriber/RouteSubscriberTest.php index e5d6c69..cccd842 100644 --- a/core/modules/views/tests/Drupal/views/Tests/EventSubscriber/RouteSubscriberTest.php +++ b/core/modules/views/tests/Drupal/views/Tests/EventSubscriber/RouteSubscriberTest.php @@ -61,7 +61,7 @@ public static function getInfo() { protected function setUp() { $this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface'); - $this->viewStorageController = $this->getMockBuilder('\Drupal\views\ViewStorageController') + $this->viewStorageController = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigStorageController') ->disableOriginalConstructor() ->getMock(); $this->entityManager->expects($this->any()) diff --git a/core/modules/views/tests/Drupal/views/Tests/Plugin/Block/ViewsBlockTest.php b/core/modules/views/tests/Drupal/views/Tests/Plugin/Block/ViewsBlockTest.php index 15d4d6e..51254b5 100644 --- a/core/modules/views/tests/Drupal/views/Tests/Plugin/Block/ViewsBlockTest.php +++ b/core/modules/views/tests/Drupal/views/Tests/Plugin/Block/ViewsBlockTest.php @@ -101,7 +101,7 @@ protected function setUp() { ->with($this->view) ->will($this->returnValue($this->executable)); - $this->storageController = $this->getMockBuilder('Drupal\views\ViewStorageController') + $this->storageController = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigStorageController') ->disableOriginalConstructor() ->getMock(); diff --git a/core/modules/views/tests/Drupal/views/Tests/Routing/ViewPageControllerTest.php b/core/modules/views/tests/Drupal/views/Tests/Routing/ViewPageControllerTest.php index 2cdd6e1..0daf925 100644 --- a/core/modules/views/tests/Drupal/views/Tests/Routing/ViewPageControllerTest.php +++ b/core/modules/views/tests/Drupal/views/Tests/Routing/ViewPageControllerTest.php @@ -53,7 +53,7 @@ public static function getInfo() { } protected function setUp() { - $this->storageController = $this->getMockBuilder('Drupal\views\ViewStorageController') + $this->storageController = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigStorageController') ->disableOriginalConstructor() ->getMock(); $this->executableFactory = $this->getMockBuilder('Drupal\views\ViewExecutableFactory') diff --git a/core/modules/views/tests/Drupal/views/Tests/ViewsTest.php b/core/modules/views/tests/Drupal/views/Tests/ViewsTest.php index 9466c0b..1ebf244 100644 --- a/core/modules/views/tests/Drupal/views/Tests/ViewsTest.php +++ b/core/modules/views/tests/Drupal/views/Tests/ViewsTest.php @@ -35,7 +35,7 @@ protected function setUp() { $this->view = new View(array('id' => 'test_view'), 'view'); - $view_storage_controller = $this->getMockBuilder('Drupal\views\ViewStorageController') + $view_storage_controller = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigStorageController') ->disableOriginalConstructor() ->getMock(); $view_storage_controller->expects($this->once()) diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php index 965f676..a61b152 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php @@ -149,6 +149,13 @@ class ViewUI implements ViewStorageInterface { private $isSyncing = FALSE; /** + * Whether the config is being deleted through the uninstall process. + * + * @var bool + */ + private $isUninstalling = FALSE; + + /** * Constructs a View UI object. * * @param \Drupal\views\ViewStorageInterface $storage @@ -207,11 +214,25 @@ public function setSyncing($syncing) { /** * {@inheritdoc} */ + public function setUninstalling($isUninstalling) { + $this->isUninstalling = $isUninstalling; + } + + /** + * {@inheritdoc} + */ public function isSyncing() { return $this->isSyncing; } /** + * {@inheritdoc} + */ + public function isUninstalling() { + return $this->isUninstalling; + } + + /** * Basic submit handler applicable to all 'standard' forms. * * This submit handler determines whether the user wants the submitted changes @@ -1179,4 +1200,22 @@ public function hasLinkTemplate($key) { return $this->storage->hasLinkTemplate($key); } + /** + * {@inheritdoc} + */ + public function createDependency($type, $name){ + } + + /** + * {@inheritdoc} + */ + public function removeDependency($type, $name){ + } + + /** + * {@inheritdoc} + */ + public function getConfigDependencyName() { + } + } diff --git a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php index 534f824..62a1586 100644 --- a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php +++ b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php @@ -30,7 +30,7 @@ public static function getInfo() { * @see \Drupal\views_ui\ViewListController::getDisplaysList(). */ public function testBuildRowEntityList() { - $storage_controller = $this->getMockBuilder('Drupal\views\ViewStorageController') + $storage_controller = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigStorageController') ->disableOriginalConstructor() ->getMock(); $display_manager = $this->getMockBuilder('\Drupal\views\Plugin\ViewsPluginManager') diff --git a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUIObjectTest.php b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUIObjectTest.php index b8256a5..a94d599 100644 --- a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUIObjectTest.php +++ b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUIObjectTest.php @@ -47,7 +47,9 @@ public function testEntityDecoration() { // EntityInterface::isNew() is missing from the list of methods, because it // calls id(), which breaks the ->expect($this->once()) call. Call it later. // EntityInterface::isSyncing() is only called during syncing process. - if ($reflection_method->getName() != 'isNew' && $reflection_method->getName() != 'isSyncing') { + // ConfigEntityInterface::getConfigDependencyName is only used during + // dependency management. + if ($reflection_method->getName() != 'isNew' && $reflection_method->getName() != 'isSyncing' && $reflection_method->getName() != 'getConfigDependencyName') { if (count($reflection_method->getParameters()) == 0) { $method_args[$reflection_method->getName()] = array(); } diff --git a/core/profiles/standard/config/field.field.node.field_image.yml b/core/profiles/standard/config/field.field.node.field_image.yml index 71d28d6..bff5fd0 100644 --- a/core/profiles/standard/config/field.field.node.field_image.yml +++ b/core/profiles/standard/config/field.field.node.field_image.yml @@ -33,3 +33,6 @@ indexes: - target_id status: true langcode: und +dependencies: + module: + - image diff --git a/core/profiles/standard/config/field.field.node.field_tags.yml b/core/profiles/standard/config/field.field.node.field_tags.yml index 08527c3..64bed8a 100644 --- a/core/profiles/standard/config/field.field.node.field_tags.yml +++ b/core/profiles/standard/config/field.field.node.field_tags.yml @@ -17,3 +17,6 @@ indexes: - target_id status: true langcode: und +dependencies: + module: + - taxonomy diff --git a/core/profiles/standard/config/field.field.user.user_picture.yml b/core/profiles/standard/config/field.field.user.user_picture.yml index 41aaf5e..cc25e2c 100644 --- a/core/profiles/standard/config/field.field.user.user_picture.yml +++ b/core/profiles/standard/config/field.field.user.user_picture.yml @@ -33,3 +33,6 @@ translatable: false indexes: target_id: - target_id +dependencies: + module: + - image