diff --git a/core/core.services.yml b/core/core.services.yml index c158be4..281c39e 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/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php index 5cc1a95..3bac265 100644 --- a/core/lib/Drupal/Core/Config/ConfigImporter.php +++ b/core/lib/Drupal/Core/Config/ConfigImporter.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Config; use Drupal\Core\Config\ConfigEvents; +use Drupal\Core\Config\Entity\ConfigDependencyManager; use Drupal\Core\DependencyInjection\DependencySerialization; use Drupal\Core\Lock\LockBackendInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -334,4 +335,13 @@ public function alreadyImporting() { return !$this->lock->lockMayBeAvailable(static::LOCK_ID); } + protected function prioritize() { + $dependency_manager = new ConfigDependencyManager(); + $storage = $this->storageComparer->getSourceStorage(); + $data = array_filter($storage->readMultiple($storage->listAll()), function($config) { + return isset($config['uuid']); + }); + $dependency_manager->setData($data); + $sorted_list = $dependency_manager->sortAll(); + } } diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php index 2bb06b3..6a5094e 100644 --- a/core/lib/Drupal/Core/Config/ConfigInstaller.php +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Config; use Drupal\Component\Utility\Unicode; +use Drupal\Core\Config\Entity\ConfigDependencyManager; use Symfony\Component\EventDispatcher\EventDispatcherInterface; class ConfigInstaller implements ConfigInstallerInterface { @@ -105,25 +106,44 @@ public function installDefaultConfig($type, $name) { } if (!empty($config_to_install)) { + // Order the configuration to install in the order of dependencies. + $data = $source_storage->readMultiple($config_to_install); + $dependency_manager = new ConfigDependencyManager(); + $sorted_config = $dependency_manager + ->setData($data) + ->sortAll(); + $old_state = $this->configFactory->getOverrideState(); $this->configFactory->setOverrideState(FALSE); - foreach ($config_to_install as $name) { - // Only import new config. - if ($this->activeStorage->exists($name)) { - continue; - } + // Only import new config. However allow updates of config that is going + // to be updated as a result of a secondary write so remove existing + // configuration before saving any new configuration. + $sorted_config = array_diff($sorted_config, $this->activeStorage->listAll()); + + foreach ($sorted_config as $name) { $new_config = new Config($name, $this->activeStorage, $this->eventDispatcher, $this->typedConfig); - $data = $source_storage->read($name); - if ($data !== FALSE) { - $new_config->setData($data); + if ($data[$name] !== FALSE) { + $new_config->setData($data[$name]); } if ($entity_type = $this->configManager->getEntityTypeIdByName($name)) { - $this->configManager + $entity_storage = $this->configManager ->getEntityManager() - ->getStorageController($entity_type) - ->create($new_config->get()) - ->save(); + ->getStorageController($entity_type); + // If the entity has been created already - update it. + if ($this->activeStorage->exists($name)) { + $id = $entity_storage->getIDFromConfigName($name, $entity_storage->getEntityType()->getConfigPrefix()); + $entity = $entity_storage->load($id); + foreach ($new_config->get() as $property => $value) { + $entity->set($property, $value); + } + $entity->save(); + } + else { + $entity_storage + ->create($new_config->get()) + ->save(); + } } else { $new_config->save(); @@ -131,6 +151,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 d52e806..31d6e60 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,6 +47,13 @@ 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 @@ -57,11 +65,12 @@ class ConfigManager implements ConfigManagerInterface { * @param \Drupal\Core\StringTranslation\TranslationManager $string_translation * The string translation service. */ - 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; } /** @@ -125,6 +134,16 @@ public function createSnapshot(StorageInterface $source_storage, StorageInterfac * {@inheritdoc} */ public function uninstall($type, $name) { + // Remove all dependent configuration entities. + $dependent_entities = $this->findConfigEntityDependentsAsEntities($type, array($name)); + + // Reverse the array to that entities are removed in the correct order of + // dependence. This ensures that field instances are removed before fields. + foreach (array_reverse($dependent_entities) as $entity) { + $entity->setUninstalling(TRUE); + $entity->delete(); + } + $config_names = $this->configFactory->listAll($name . '.'); foreach ($config_names as $config_name) { $this->configFactory->get($config_name)->delete(); @@ -137,4 +156,55 @@ public function uninstall($type, $name) { } } + /** + * {@inheritdoc} + */ + public function findConfigEntityDependents($type, array $names) { + $dependency_manager = new ConfigDependencyManager(); + // 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. Assume data with UUID + // is a config entity. Only configuration entities can be depended on so we + // can ignore everything else. + $data = array_filter($this->activeStorage->readMultiple($this->activeStorage->listAll()), function($config) { + return isset($config['uuid']); + }); + $dependency_manager->setData($data); + $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); + // It is possible that the a non configuration entity will be returned if + // a simple configuration object has a uuid key. This would occur if the + // dependents of the system module are calculated since system.site has + // a uuid key. + if ($entity_type_id) { + $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); + // Remove the keys since there are potential ID clashes from different + // configuration entity types. + $entities_to_return = array_merge($entities_to_return, array_values($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 d78b358..587540d 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 full configuration object names. + * + * @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 full configuration object names. + * + * @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..fc76841 --- /dev/null +++ b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php @@ -0,0 +1,174 @@ +data, function (ConfigEntityDependency $entity) use ($type, $name) { + return $entity->hasDependency($type, $name); + }); + } + + $entities_to_check = array(); + if ($type == 'entity') { + $entities_to_check[] = $name; + } + else { + // If checking module or theme dependencies then discover which entities + // are dependent on the entities that have a direct dependency. + foreach ($dependent_entities as $entity) { + $entities_to_check[] = $entity->getConfigDependencyName(); + } + } + + return array_merge($dependent_entities, $this->graphConfigEntityDependencies($entities_to_check)); + } + + /** + * Sorts the dependencies in order of most dependent last. + * + * @return array + * The list of entities in order of most dependent last otherwise + * alphabetical. + */ + public function sortAll() { + $graph = $this->getGraph(); + // Sort by reverse weight and alphabetically. So the most dependent entities + // are last but entities with the same weight are alphabetically ordered in + // the same way file system reads often are. + uasort($graph, array($this, 'sortGraph')); + return array_keys($graph); + } + + /** + * Sorts the dependency graph by reverse weight and alphabetically. + * + * @param array $a + * First item for comparison. The compared items should be associative + * arrays that include a 'weight' and a 'component' key. + * @param array $b + * Second item for comparison. + * + * @return int + * The comparison result for uasort(). + */ + public function sortGraph(array $a, array $b) { + $weight_cmp = SortArray::sortByKeyInt($a, $b, 'weight') * -1; + + if ($weight_cmp === 0) { + return SortArray::sortByKeyString($a, $b, 'component'); + } + return $weight_cmp; + } + + /** + * Creates a graph of config entity dependencies. + * + * @param array $entities_to_check + * The entities to supply dependencies for. + * + * @return \Drupal\Core\Config\Entity\ConfigEntityDependency[] + * An array of config entity dependency objects that are dependent on the + * supplied entities to check. + */ + protected function graphConfigEntityDependencies($entities_to_check) { + $dependent_entities = array(); + $graph = $this->getGraph(); + + foreach ($entities_to_check as $entity) { + if (isset($graph[$entity]) && !empty($graph[$entity]['reverse_paths'])){ + foreach ($graph[$entity]['reverse_paths'] as $dependency => $value) { + $dependent_entities[$dependency] = $this->data[$dependency]; + } + } + } + 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)) { + $graph = array(); + foreach ($this->data 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; + } + + /** + * Sets data to calculate dependencies for. + * + * The data is converted into lightweight ConfigEntityDependency objects. + * + * @param array $data + * Configuration data keyed by configuration object name. Typically the + * output of \Drupal\Core\Config\StorageInterface::loadMultiple(). + * + * @return self + */ + public function setData(array $data) { + array_walk($data, function (&$config, $name) { + $config = new ConfigEntityDependency($name, $config); + }); + $this->data = $data; + return $this; + } + +} diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index 87b43f7..1c6f499 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -64,6 +64,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) { @@ -173,6 +187,20 @@ public function isSyncing() { /** * {@inheritdoc} */ + public function setUninstalling($uninstalling) { + $this->isUninstalling = $uninstalling; + } + + /** + * {@inheritdoc} + */ + public function isUninstalling() { + return $this->isUninstalling; + } + + /** + * {@inheritdoc} + */ public function createDuplicate() { $duplicate = clone $this; $duplicate->set($this->getEntityType()->getKey('id'), NULL); @@ -211,6 +239,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,7 +257,16 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { if ($this instanceof EntityWithPluginBagInterface) { // Any changes to the plugin configuration must be saved to the entity's // copy as well. - $this->set($this->pluginConfigKey, $this->getPluginBag()->getConfiguration()); + $plugin_bag = $this->getPluginBag(); + $this->set($this->pluginConfigKey, $plugin_bag->getConfiguration()); + + // Configuration entities need to depend on the providers of any plugins + // that they store the configuration for. + $plugin_bag->rewind(); + foreach($plugin_bag as $instance) { + $definition = $instance->getPluginDefinition(); + $this->createDependency('module', $definition['provider']); + } } // Ensure this entity's UUID does not exist with a different ID, regardless @@ -268,4 +309,40 @@ public function url($rel = 'edit-form', $options = array()) { return parent::url($rel, $options); } + /** + * {@inheritdoc} + */ + public function createDependency($type, $name) { + // A config entity is always dependent on it's provider. There is no need to + // explicitly declared the dependency. + // @see \Drupal\Core\Config\Entity\ConfigEntityDependency::hasDependency() + if ($type == 'module' && $this->getEntityType()->getProvider() == $name) { + return $this; + } + 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(); + } } 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..d364921 --- /dev/null +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityDependency.php @@ -0,0 +1,107 @@ +name = $name; + if (isset($values['dependencies'])) { + $this->dependencies = $values['dependencies']; + } + else { + $this->dependencies = array(); + } + } + + /** + * 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) { + $dependencies = array(); + if (isset($this->dependencies[$type])) { + $dependencies = $this->dependencies[$type]; + } + if ($type == 'module') { + $dependencies[] = substr($this->name,0, strpos($this->name, '.')); + } + return $dependencies; + } + + /** + * 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 + * the full configuration object name. + * + * @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 configuration entity's configuration dependency name. + * + * @return string + * The configuration dependency name for the entity. + */ + public function getConfigDependencyName() { + return $this->getName(); + } + +} diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php index 5aa737d..3b12897 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,44 @@ 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 the full + * configuration object name. + * + * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::getConfigDependencyName() + * + * @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 the full + * configuration object name. + * + * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::getConfigDependencyName() + * + * @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 1dd6f21..46e7160 100644 --- a/core/lib/Drupal/Core/Extension/ModuleHandler.php +++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php @@ -725,14 +725,16 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) { // Uninstall the module. module_load_install($module); $this->invoke($module, 'uninstall'); + + // Remove all configuration belonging to the module. + \Drupal::service('config.manager')->uninstall('module', $module); + + // Remove the schema. drupal_uninstall_schema($module); // Remove the module's entry from the config. $module_config->clear("enabled.$module")->save(); - // Remove all configuration belonging to the module. - \Drupal::service('config.manager')->uninstall('module', $module); - // Update the module handler to remove the module. // The current ModuleHandler instance is obsolete with the kernel rebuild // below. @@ -824,4 +826,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 c15b24a..d22fdcb 100644 --- a/core/modules/aggregator/config/views.view.aggregator_rss_feed.yml +++ b/core/modules/aggregator/config/views.view.aggregator_rss_feed.yml @@ -144,7 +144,10 @@ display: defaults: arguments: true label: 'Aggregator RSS feed' -module: views +module: aggregator id: aggregator_rss_feed tag: aggregator langcode: en +dependencies: + module: + - aggregator diff --git a/core/modules/block/config/schema/block.schema.yml b/core/modules/block/config/schema/block.schema.yml index 1ed3f49..3db3aaa 100644 --- a/core/modules/block/config/schema/block.schema.yml +++ b/core/modules/block/config/schema/block.schema.yml @@ -90,3 +90,6 @@ block.block.*: langcode: type: string label: 'Default language' + dependencies: + type: config_dependency + label: 'Dependencies' diff --git a/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml b/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml index ba11a62..2987629 100644 --- a/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml +++ b/core/modules/block/custom_block/config/entity.view_mode.custom_block.full.yml @@ -3,3 +3,6 @@ label: Full status: false cache: true targetEntityType: custom_block +dependencies: + module: + - custom_block diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php index 36ed74a..23a9213 100644 --- a/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php +++ b/core/modules/block/lib/Drupal/block/Tests/BlockStorageUnitTest.php @@ -95,6 +95,7 @@ protected function createTests() { 'weight' => NULL, 'status' => TRUE, 'langcode' => language_default()->id, + 'dependencies' => array('module' => array('block_test')), 'theme' => 'stark', 'region' => '-1', 'plugin' => 'test_html', diff --git a/core/modules/book/config/entity.view_mode.node.print.yml b/core/modules/book/config/entity.view_mode.node.print.yml index 7854ec1..512d581 100644 --- a/core/modules/book/config/entity.view_mode.node.print.yml +++ b/core/modules/book/config/entity.view_mode.node.print.yml @@ -3,3 +3,6 @@ label: Print status: false cache: true targetEntityType: node +dependencies: + module: + - node diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php index f3807af..dce7ce0 100644 --- a/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php +++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php @@ -214,6 +214,7 @@ public function getExportProperties() { 'sourceType', 'status', 'langcode', + 'dependencies', ); $properties = array(); foreach ($names as $name) { diff --git a/core/modules/comment/config/entity.view_mode.comment.full.yml b/core/modules/comment/config/entity.view_mode.comment.full.yml index fd623d4..c30d77d 100644 --- a/core/modules/comment/config/entity.view_mode.comment.full.yml +++ b/core/modules/comment/config/entity.view_mode.comment.full.yml @@ -3,3 +3,6 @@ label: 'Full comment' status: false cache: true targetEntityType: comment +dependencies: + module: + - comment diff --git a/core/modules/comment/config/system.action.comment_publish_action.yml b/core/modules/comment/config/system.action.comment_publish_action.yml index ae9d93a..e1e12ad 100644 --- a/core/modules/comment/config/system.action.comment_publish_action.yml +++ b/core/modules/comment/config/system.action.comment_publish_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: comment plugin: comment_publish_action +dependencies: + module: + - comment diff --git a/core/modules/comment/config/system.action.comment_save_action.yml b/core/modules/comment/config/system.action.comment_save_action.yml index e98a92a..8c605b0 100644 --- a/core/modules/comment/config/system.action.comment_save_action.yml +++ b/core/modules/comment/config/system.action.comment_save_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: comment plugin: comment_save_action +dependencies: + module: + - comment diff --git a/core/modules/comment/config/system.action.comment_unpublish_action.yml b/core/modules/comment/config/system.action.comment_unpublish_action.yml index 61b8e24..5e8e169 100644 --- a/core/modules/comment/config/system.action.comment_unpublish_action.yml +++ b/core/modules/comment/config/system.action.comment_unpublish_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: comment plugin: comment_unpublish_action +dependencies: + module: + - comment diff --git a/core/modules/comment/config/views.view.comments_recent.yml b/core/modules/comment/config/views.view.comments_recent.yml index dc16d8d..15993f8 100644 --- a/core/modules/comment/config/views.view.comments_recent.yml +++ b/core/modules/comment/config/views.view.comments_recent.yml @@ -234,3 +234,6 @@ module: views id: comments_recent tag: default langcode: en +dependencies: + module: + - comment diff --git a/core/modules/comment/lib/Drupal/comment/Tests/Views/WizardTest.php b/core/modules/comment/lib/Drupal/comment/Tests/Views/WizardTest.php index 764a51a..997fb50 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/Views/WizardTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/Views/WizardTest.php @@ -21,7 +21,7 @@ class WizardTest extends WizardTestBase { * * @var array */ - public static $modules = array('node', 'comment'); + public static $modules = array('node', 'comment', 'comment_test_views'); public static function getInfo() { diff --git a/core/modules/comment/tests/modules/comment_test_views/config/node.type.page.yml b/core/modules/comment/tests/modules/comment_test_views/config/node.type.page.yml new file mode 100644 index 0000000..f72d0c6 --- /dev/null +++ b/core/modules/comment/tests/modules/comment_test_views/config/node.type.page.yml @@ -0,0 +1,17 @@ +type: page +name: 'Basic page' +description: 'Use basic pages for your static content, such as an ''About us'' page.' +help: '' +has_title: true +title_label: Title +settings: + node: + preview: 1 + options: + status: true + promote: false + sticky: false + revision: false + submitted: false +status: true +langcode: en diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigDependencyTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigDependencyTest.php new file mode 100644 index 0000000..a893de7 --- /dev/null +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigDependencyTest.php @@ -0,0 +1,171 @@ + 'Configuration dependency tests', + 'description' => 'Tests for configuration dependencies.', + 'group' => 'Configuration', + ); + } + + /** + * Tests that calculating dependencies for system module. + */ + public function testNonEntity() { + $this->installConfig(array('system')); + $config_manager = \Drupal::service('config.manager'); + $dependents = $config_manager->findConfigEntityDependents('module', array('system')); + $this->assertTrue(isset($dependents['system.site']), 'Simple configuration which '); + // Ensure that calling + // \Drupal\Core\Config\ConfigManager::findConfigEntityDependentsAsEntities() + // does not try to load system.site as an entity. + $config_manager->findConfigEntityDependentsAsEntities('module', array('system')); + } + + /** + * Tests creating dependencies on configuration entities. + */ + public function testDependencyMangement() { + $config_manager = \Drupal::service('config.manager'); + $storage = $this->container->get('entity.manager')->getStorageController('config_test'); + // Test dependencies between modules. + $entity1 = $storage->create(array('id' => 'entity1')); + $entity1->createDependency('module', 'node'); + $entity1->createDependency('module', 'config_test'); + $entity1->save(); + + $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.'); + $dependents = $config_manager->findConfigEntityDependents('module', array('config_test')); + $this->assertTrue(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 has a dependency on the config_test module.'); + $dependents = $config_manager->findConfigEntityDependents('module', array('views')); + $this->assertFalse(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 does not have a dependency on the Views module.'); + // Ensure that the provider of the config entity is not actually written to + // the dependencies array. + $raw_config = \Drupal::config('config_test.dynamic.entity1'); + $this->assertTrue(array_search('config_test', $raw_config->get('dependencies.module')) === FALSE, 'Module that the provides the configuration entity is not written to the dependencies array as this is implicit.'); + $this->assertTrue(array_search('node', $raw_config->get('dependencies.module')) !== FALSE, 'Node module is written to the dependencies array as this has to be explicit.'); + + // Create additional entities to test dependencies on config entities. + $entity2 = $storage->create(array('id' => 'entity2')); + $entity3 = $storage->create(array('id' => 'entity3')); + $entity4 = $storage->create(array('id' => 'entity4')); + + $entity4->createDependency('entity', $entity3->getConfigDependencyName()); + $entity3->createDependency('entity', $entity2->getConfigDependencyName()); + $entity2->createDependency('entity', $entity1->getConfigDependencyName()); + + $entity2->save(); + $entity3->save(); + $entity4->save(); + + // 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())); + $dependent_ids = $this->getDependentIds($dependents); + $this->assertFalse(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity2 does not have a dependency on config_test.dynamic.entity1.'); + $this->assertFalse(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 does not have a dependency on itself.'); + $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity2 has a dependency on config_test.dynamic.entity2.'); + $this->assertTrue(in_array('config_test:entity4', $dependent_ids), 'config_test.dynamic.entity2 has a dependency on config_test.dynamic.entity2.'); + + // 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.'); + + // Create an configuration entity of a different type with the same ID as + // one of the entities already created. + $alt_storage = $this->container->get('entity.manager')->getStorageController('config_query_test'); + $alt_storage->create(array('id' => 'entity1')) + ->createDependency('entity', $entity1->getConfigDependencyName()) + ->save(); + $alt_storage->create(array('id' => 'entity2')) + ->createDependency('module', 'views') + ->save(); + + $dependents = $config_manager->findConfigEntityDependentsAsEntities('entity', array($entity1->getConfigDependencyName())); + $dependent_ids = $this->getDependentIds($dependents); + $this->assertFalse(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity1 does not have a dependency on itself.'); + $this->assertTrue(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 has a dependency on config_test.dynamic.entity1.'); + $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity3 has a dependency on config_test.dynamic.entity1.'); + $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity4 has a dependency on config_test.dynamic.entity1.'); + $this->assertTrue(in_array('config_query_test:entity1', $dependent_ids), 'config_query_test.dynamic.entity1 has a dependency on config_test.dynamic.entity1.'); + $this->assertFalse(in_array('config_query_test:entity2', $dependent_ids), 'config_query_test.dynamic.entity2 does not have a dependency on config_test.dynamic.entity1.'); + + $dependents = $config_manager->findConfigEntityDependentsAsEntities('module', array('node', 'views')); + $dependent_ids = $this->getDependentIds($dependents); + $this->assertFalse(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity1 does not have a dependency on Views or Node.'); + $this->assertFalse(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 does not have a dependency on Views or Node.'); + $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity3 has a dependency on Views or Node.'); + $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity4 has a dependency on Views or Node.'); + $this->assertFalse(in_array('config_query_test:entity1', $dependent_ids), 'config_test.query.entity1 does not have a dependency on Views or Node.'); + $this->assertTrue(in_array('config_query_test:entity2', $dependent_ids), 'config_test.query.entity2 has a dependency on Views or Node.'); + + $dependents = $config_manager->findConfigEntityDependentsAsEntities('module', array('config_test')); + $dependent_ids = $this->getDependentIds($dependents); + $this->assertTrue(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity1 has a dependency on config_test module.'); + $this->assertTrue(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 has a dependency on config_test module.'); + $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity3 has a dependency on config_test module.'); + $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity4 has a dependency on config_test module.'); + $this->assertTrue(in_array('config_query_test:entity1', $dependent_ids), 'config_test.query.entity1 has a dependency on config_test module.'); + $this->assertTrue(in_array('config_query_test:entity2', $dependent_ids), 'config_test.query.entity2 has a dependency on config_test module.'); + + } + + /** + * Gets a list of identifiers from an array of configuration entities. + * + * @param \Drupal\Core\Config\Entity\ConfigEntityInterface[] $dependents + * An array of configuration entities. + * + * @return array + * An array with values of entity_type_id:ID + */ + protected function getDependentIds(array $dependents) { + $dependent_ids = array(); + foreach($dependents as $dependent) { + $dependent_ids[] = $dependent->getEntityTypeId() . ':' . $dependent->id(); + } + return $dependent_ids; + } +} 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/config/tests/config_test/lib/Drupal/config_test/TestInstallStorage.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/TestInstallStorage.php index 954036e..cefb13f 100644 --- a/core/modules/config/tests/config_test/lib/Drupal/config_test/TestInstallStorage.php +++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/TestInstallStorage.php @@ -25,6 +25,8 @@ protected function getAllFolders() { if (!isset($this->folders)) { // @todo Refactor getComponentNames() to use the extension list directly. $listing = new ExtensionDiscovery(); + // Test all profiles. + $listing->setProfileDirectories(array()); $this->folders = $this->getComponentNames('profile', array_keys($listing->scan('profile'))); $this->folders += $this->getComponentNames('module', array_keys($listing->scan('module'))); $this->folders += $this->getComponentNames('theme', array_keys($listing->scan('theme'))); diff --git a/core/modules/editor/config/schema/editor.schema.yml b/core/modules/editor/config/schema/editor.schema.yml index 086abf6..136ecaf 100644 --- a/core/modules/editor/config/schema/editor.schema.yml +++ b/core/modules/editor/config/schema/editor.schema.yml @@ -44,3 +44,6 @@ editor.editor.*: langcode: type: string label: 'Default language' + dependencies: + type: config_dependency + label: 'Dependencies' diff --git a/core/modules/editor/lib/Drupal/editor/Entity/Editor.php b/core/modules/editor/lib/Drupal/editor/Entity/Editor.php index 0053de4..3e84657 100644 --- a/core/modules/editor/lib/Drupal/editor/Entity/Editor.php +++ b/core/modules/editor/lib/Drupal/editor/Entity/Editor.php @@ -8,6 +8,7 @@ namespace Drupal\editor\Entity; use Drupal\Core\Config\Entity\ConfigEntityBase; +use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\editor\EditorInterface; /** @@ -75,4 +76,14 @@ public function __construct(array $values, $entity_type) { $this->settings += $default_settings; } + /** + * {@inheritdoc} + */ + public function preSave(EntityStorageControllerInterface $storage_controller) { + // Create a dependency of the linked filter. + $filter = entity_load('filter_format', $this->format); + $this->createDependency('entity', $filter->getConfigDependencyName()); + parent::preSave($storage_controller); + } + } diff --git a/core/modules/entity/config/schema/entity.schema.yml b/core/modules/entity/config/schema/entity.schema.yml index a2d0b43..d96cf4c 100644 --- a/core/modules/entity/config/schema/entity.schema.yml +++ b/core/modules/entity/config/schema/entity.schema.yml @@ -25,6 +25,9 @@ entity.view_mode.*.*: langcode: type: string label: 'Default language' + dependencies: + type: config_dependency + label: 'Dependencies' entity.form_mode.*.*: type: mapping @@ -51,6 +54,9 @@ entity.form_mode.*.*: langcode: type: string label: 'Default language' + dependencies: + type: config_dependency + label: 'Dependencies' # Overview configuration information for view mode or form mode displays. entity.view_display.*.*.*: @@ -86,6 +92,9 @@ entity.view_display.*.*.*: sequence: - type: boolean label: 'Value' + dependencies: + type: config_dependency + label: 'Dependencies' # Overview configuration information for form mode displays. entity.form_display.*.*.*: @@ -115,6 +124,9 @@ entity.form_display.*.*.*: status: type: boolean label: 'Enabled' + dependencies: + type: config_dependency + label: 'Dependencies' # Default schema for entity display field with undefined type. entity_view_display.field.*: diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php index 93d132d..bd8698e 100644 --- a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php @@ -11,6 +11,7 @@ use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Entity\Display\EntityDisplayInterface; +use Drupal\field\Field; /** * Provides a common base class for entity view and form displays. @@ -150,6 +151,26 @@ public function id() { public function preSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) { // Sort elements by weight before saving. uasort($this->content, 'Drupal\Component\Utility\SortArray::sortByWeightElement'); + + $target_entity_type = \Drupal::entityManager()->getDefinition($this->targetEntityType); + //$this->createDependency('module', $target_entity_type->getProvider()); + $bundle_entity_type_id = $target_entity_type->getBundleEntityType(); + if ($bundle_entity_type_id != 'bundle') { + // If the target entity type uses bundles the depend on the bundle entity. + $bundle_entity = entity_load($bundle_entity_type_id, $this->bundle); + $this->createDependency('entity', $bundle_entity->getConfigDependencyName()); + } + foreach ($this->content as $field_name => $value) { + $field_instance = Field::fieldInfo()->getInstance($this->targetEntityType, $this->bundle, $field_name); + if ($field_instance) { + $this->createDependency('entity', $field_instance->getConfigDependencyName()); + } + } + // Depend on configured modes. + if ($this->mode != 'default') { + $mode_entity = entity_load($this->displayContext . '_mode', $target_entity_type->id() . '.' . $this->mode); + $this->createDependency('entity', $mode_entity->getConfigDependencyName()); + } } /** @@ -175,6 +196,7 @@ public function getExportProperties() { 'content', 'hidden', 'status', + 'dependencies' ); $properties = array(); foreach ($names as $name) { diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php index 1541143..f6122d2 100644 --- a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php @@ -8,6 +8,7 @@ namespace Drupal\entity; use Drupal\Core\Config\Entity\ConfigEntityBase; +use Drupal\Core\Entity\EntityStorageControllerInterface; /** * Base class for config entity types that hold settings for form and view modes. @@ -82,4 +83,12 @@ public function getTargetType() { return $this->targetEntityType; } + /** + * {@inheritdoc} + */ + public function preSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) { + $target_entity_type = \Drupal::entityManager()->getDefinition($this->targetEntityType); + $this->createDependency('module', $target_entity_type->getProvider()); + } + } 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/lib/Drupal/field/Entity/FieldConfig.php b/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php index 3388c95..e205199 100644 --- a/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php +++ b/core/modules/field/lib/Drupal/field/Entity/FieldConfig.php @@ -261,6 +261,7 @@ public function getExportProperties() { 'cardinality', 'translatable', 'indexes', + 'dependencies', ); $properties = array(); foreach ($names as $name) { @@ -332,6 +333,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); } @@ -415,6 +419,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/FieldInstanceConfig.php b/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php index 6024061..180cf06 100644 --- a/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php +++ b/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php @@ -311,6 +311,7 @@ public function getExportProperties() { 'default_value', 'default_value_function', 'settings', + 'dependencies', ); $properties = array(); foreach ($names as $name) { @@ -360,6 +361,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()); } /** @@ -409,7 +413,7 @@ public static function postDelete(EntityStorageControllerInterface $storage_cont $fields_to_delete = array(); foreach ($instances as $instance) { $field = $instance->getField(); - if (!$instance->deleted && empty($instance->noFieldDelete) && count($field->getBundles()) == 0) { + if (!$instance->deleted && empty($instance->noFieldDelete) && !$instance->isUninstalling() && count($field->getBundles()) == 0) { // Key by field UUID to avoid deleting the same field twice. $fields_to_delete[$instance->field_uuid] = $field; } 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 ea17b1e..cc7d114 100644 --- a/core/modules/file/config/views.view.files.yml +++ b/core/modules/file/config/views.view.files.yml @@ -1050,3 +1050,6 @@ module: file id: files tag: default langcode: en +dependencies: + module: + - file diff --git a/core/modules/forum/config/entity.form_display.taxonomy_term.forums.default.yml b/core/modules/forum/config/entity.form_display.taxonomy_term.forums.default.yml index 91ea8ec..ff9133f 100644 --- a/core/modules/forum/config/entity.form_display.taxonomy_term.forums.default.yml +++ b/core/modules/forum/config/entity.form_display.taxonomy_term.forums.default.yml @@ -8,3 +8,6 @@ content: weight: -5 description: weight: 0 +dependencies: + entity: + - taxonomy.vocabulary.forums diff --git a/core/modules/forum/config/entity.view_display.taxonomy_term.forums.default.yml b/core/modules/forum/config/entity.view_display.taxonomy_term.forums.default.yml index 4e3733a..cefa753 100644 --- a/core/modules/forum/config/entity.view_display.taxonomy_term.forums.default.yml +++ b/core/modules/forum/config/entity.view_display.taxonomy_term.forums.default.yml @@ -8,3 +8,6 @@ content: weight: 0 hidden: { } status: true +dependencies: + entity: + - taxonomy.vocabulary.forums 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 4c20672..af5ebf2 100644 --- a/core/modules/forum/config/field.field.forum.forum_container.yml +++ b/core/modules/forum/config/field.field.forum.forum_container.yml @@ -14,3 +14,6 @@ locked: true cardinality: 1 translatable: false indexes: { } +dependencies: + module: + - options diff --git a/core/modules/forum/config/field.instance.taxonomy_term.forums.forum_container.yml b/core/modules/forum/config/field.instance.taxonomy_term.forums.forum_container.yml index 66feae9..e91a93b 100644 --- a/core/modules/forum/config/field.instance.taxonomy_term.forums.forum_container.yml +++ b/core/modules/forum/config/field.instance.taxonomy_term.forums.forum_container.yml @@ -13,3 +13,6 @@ default_value: default_value_function: '' settings: { } field_type: list_boolean +dependencies: + entity: + - field.field.forum.forum_container diff --git a/core/modules/language/lib/Drupal/language/Entity/Language.php b/core/modules/language/lib/Drupal/language/Entity/Language.php index 7c92351..090583a 100644 --- a/core/modules/language/lib/Drupal/language/Entity/Language.php +++ b/core/modules/language/lib/Drupal/language/Entity/Language.php @@ -105,7 +105,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/node/config/entity.view_mode.node.full.yml b/core/modules/node/config/entity.view_mode.node.full.yml index fce4bf4..3a8654a 100644 --- a/core/modules/node/config/entity.view_mode.node.full.yml +++ b/core/modules/node/config/entity.view_mode.node.full.yml @@ -3,3 +3,6 @@ label: 'Full content' status: false cache: true targetEntityType: node +dependencies: + module: + - node diff --git a/core/modules/node/config/entity.view_mode.node.rss.yml b/core/modules/node/config/entity.view_mode.node.rss.yml index 3e7414c..6a79ca5 100644 --- a/core/modules/node/config/entity.view_mode.node.rss.yml +++ b/core/modules/node/config/entity.view_mode.node.rss.yml @@ -3,3 +3,6 @@ label: RSS status: false cache: true targetEntityType: node +dependencies: + module: + - node diff --git a/core/modules/node/config/entity.view_mode.node.teaser.yml b/core/modules/node/config/entity.view_mode.node.teaser.yml index 875d61f..be00b8d 100644 --- a/core/modules/node/config/entity.view_mode.node.teaser.yml +++ b/core/modules/node/config/entity.view_mode.node.teaser.yml @@ -3,3 +3,6 @@ label: Teaser status: true cache: true targetEntityType: node +dependencies: + module: + - node diff --git a/core/modules/node/config/search.page.node_search.yml b/core/modules/node/config/search.page.node_search.yml index e4ea66e..76456e5 100644 --- a/core/modules/node/config/search.page.node_search.yml +++ b/core/modules/node/config/search.page.node_search.yml @@ -7,3 +7,6 @@ weight: -10 plugin: node_search configuration: rankings: { } +dependencies: + module: + - node \ No newline at end of file diff --git a/core/modules/node/config/system.action.node_delete_action.yml b/core/modules/node/config/system.action.node_delete_action.yml index deceb87..af4ce28 100644 --- a/core/modules/node/config/system.action.node_delete_action.yml +++ b/core/modules/node/config/system.action.node_delete_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: node plugin: node_delete_action +dependencies: + module: + - node diff --git a/core/modules/node/config/system.action.node_make_sticky_action.yml b/core/modules/node/config/system.action.node_make_sticky_action.yml index 104f92c..04276c0 100644 --- a/core/modules/node/config/system.action.node_make_sticky_action.yml +++ b/core/modules/node/config/system.action.node_make_sticky_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: node plugin: node_make_sticky_action +dependencies: + module: + - node diff --git a/core/modules/node/config/system.action.node_make_unsticky_action.yml b/core/modules/node/config/system.action.node_make_unsticky_action.yml index 2207e7d..03a99c5 100644 --- a/core/modules/node/config/system.action.node_make_unsticky_action.yml +++ b/core/modules/node/config/system.action.node_make_unsticky_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: node plugin: node_make_unsticky_action +dependencies: + module: + - node diff --git a/core/modules/node/config/system.action.node_save_action.yml b/core/modules/node/config/system.action.node_save_action.yml index 0864be5..4dc2073 100644 --- a/core/modules/node/config/system.action.node_save_action.yml +++ b/core/modules/node/config/system.action.node_save_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: node plugin: node_save_action +dependencies: + module: + - node diff --git a/core/modules/node/config/system.action.node_unpromote_action.yml b/core/modules/node/config/system.action.node_unpromote_action.yml index 2b9cc1f..21c0ae8 100644 --- a/core/modules/node/config/system.action.node_unpromote_action.yml +++ b/core/modules/node/config/system.action.node_unpromote_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: node plugin: node_unpromote_action +dependencies: + module: + - node diff --git a/core/modules/node/config/system.action.node_unpublish_action.yml b/core/modules/node/config/system.action.node_unpublish_action.yml index 1b70c4f..2e01fae 100644 --- a/core/modules/node/config/system.action.node_unpublish_action.yml +++ b/core/modules/node/config/system.action.node_unpublish_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: node plugin: node_unpublish_action +dependencies: + module: + - node 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 d64c243..1151b1a 100644 --- a/core/modules/views/config/views.view.archive.yml +++ b/core/modules/node/config/views.view.archive.yml @@ -171,3 +171,6 @@ module: node id: archive tag: default 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 cb0ec4f..074c5b5 100644 --- a/core/modules/node/config/views.view.content.yml +++ b/core/modules/node/config/views.view.content.yml @@ -349,6 +349,7 @@ display: hide_alter_empty: true link_to_node: false comments: false + optional: true plugin_id: history_user_timestamp provider: history filters: @@ -558,3 +559,7 @@ module: node id: content tag: default langcode: en +dependencies: + module: + - node + - user diff --git a/core/modules/node/config/views.view.content_recent.yml b/core/modules/node/config/views.view.content_recent.yml index 45edb2f..09993b7 100644 --- a/core/modules/node/config/views.view.content_recent.yml +++ b/core/modules/node/config/views.view.content_recent.yml @@ -207,6 +207,7 @@ display: hide_alter_empty: true link_to_node: false comments: false + optional: true plugin_id: history_user_timestamp provider: history name: @@ -462,7 +463,11 @@ display: link_url: admin/content block_category: 'Lists (Views)' label: 'Recent content' -module: views +module: node id: content_recent tag: default langcode: en +dependencies: + module: + - node + - user diff --git a/core/modules/node/config/views.view.frontpage.yml b/core/modules/node/config/views.view.frontpage.yml index 9efe139..a6928ab 100644 --- a/core/modules/node/config/views.view.frontpage.yml +++ b/core/modules/node/config/views.view.frontpage.yml @@ -238,3 +238,6 @@ module: node id: frontpage tag: default langcode: en +dependencies: + module: + - node 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 882012e..0edc991 100644 --- a/core/modules/views/config/views.view.glossary.yml +++ b/core/modules/node/config/views.view.glossary.yml @@ -379,3 +379,7 @@ module: node id: glossary tag: default langcode: en +dependencies: + module: + - node + - user diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAccessPagerTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAccessPagerTest.php index 74cd9c7..ee9f7cd 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeAccessPagerTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeAccessPagerTest.php @@ -35,6 +35,7 @@ public function setUp() { parent::setUp(); node_access_rebuild(); + $this->drupalCreateContentType(array('type' => 'page', 'name' => t('Basic page'))); $this->container->get('comment.manager')->addDefaultField('node', 'page'); $this->web_user = $this->drupalCreateUser(array('access content', 'access comments', 'node test view')); } diff --git a/core/modules/rdf/config/schema/rdf.schema.yml b/core/modules/rdf/config/schema/rdf.schema.yml index 570d602..b743ce3 100644 --- a/core/modules/rdf/config/schema/rdf.schema.yml +++ b/core/modules/rdf/config/schema/rdf.schema.yml @@ -26,3 +26,6 @@ rdf.mapping.*.*: label: 'Field mappings' sequence: - type: rdf_field_mapping + dependencies: + type: config_dependency + label: 'Dependencies' diff --git a/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php b/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php index 1916320..6e4e8df 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php +++ b/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php @@ -156,12 +156,31 @@ public function getExportProperties() { foreach ($names as $name) { $properties[$name] = $this->get($name); } + if (!empty($this->dependencies)) { + // Add protected dependencies property if set. + $properties['dependencies'] = $this->dependencies; + } return $properties; } /** * {@inheritdoc} */ + public function preSave(EntityStorageControllerInterface $storage_controller) { + parent::preSave($storage_controller); + $entity_type = \Drupal::entityManager()->getDefinition($this->targetEntityType); + $this->createDependency('module', $entity_type->getProvider()); + $bundle_entity_type_id = $entity_type->getBundleEntityType(); + if ($bundle_entity_type_id != 'bundle') { + // If the target entity type uses bundles the depend on the bundle entity. + $bundle_entity = entity_load($bundle_entity_type_id, $this->bundle); + $this->createDependency('entity', $bundle_entity->getConfigDependencyName()); + } + } + + /** + * {@inheritdoc} + */ public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) { parent::postSave($storage_controller, $update); diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaAttributesTest.php index 03500bd..726e78b 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaAttributesTest.php +++ b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaAttributesTest.php @@ -135,9 +135,8 @@ function testRel() { * The data to pass into the datatype callback, if specified. */ protected function _testAttributes($expected_attributes, $field_mapping, $data = NULL) { - $this->saveMapping($field_mapping); - $mapping = rdf_get_mapping('node', 'article') + ->setFieldMapping('field_test', $field_mapping) ->getPreparedFieldMapping('field_test'); $attributes = rdf_rdfa_attributes($mapping, $data); ksort($expected_attributes); @@ -145,15 +144,4 @@ protected function _testAttributes($expected_attributes, $field_mapping, $data = $this->assertEqual($expected_attributes, $attributes); } - /** - * Helper function to save mapping using config system. - * - * @param array $field_mapping - * The field mapping. - */ - protected function saveMapping($field_mapping) { - rdf_get_mapping('node', 'article') - ->setFieldMapping('field_test', $field_mapping) - ->save(); - } } diff --git a/core/modules/search/config/entity.view_mode.node.search_index.yml b/core/modules/search/config/entity.view_mode.node.search_index.yml index af5fd59..c5d9706 100644 --- a/core/modules/search/config/entity.view_mode.node.search_index.yml +++ b/core/modules/search/config/entity.view_mode.node.search_index.yml @@ -3,3 +3,7 @@ label: 'Search index' status: false cache: true targetEntityType: node +dependencies: + module: + - node + - search diff --git a/core/modules/search/config/entity.view_mode.node.search_result.yml b/core/modules/search/config/entity.view_mode.node.search_result.yml index 178a11c..a95eda0 100644 --- a/core/modules/search/config/entity.view_mode.node.search_result.yml +++ b/core/modules/search/config/entity.view_mode.node.search_result.yml @@ -3,3 +3,7 @@ label: 'Search result' status: false cache: true targetEntityType: node +dependencies: + module: + - node + - search diff --git a/core/modules/search/config/schema/search.schema.yml b/core/modules/search/config/schema/search.schema.yml index 68e6877..2d9d39e 100644 --- a/core/modules/search/config/schema/search.schema.yml +++ b/core/modules/search/config/schema/search.schema.yml @@ -94,3 +94,6 @@ search.page.*: label: 'Plugin' configuration: type: search.plugin.[%parent.plugin] + dependencies: + type: config_dependency + label: 'Dependencies' diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml index 6b82e60..f8d0143 100644 --- a/core/modules/system/config/schema/system.schema.yml +++ b/core/modules/system/config/schema/system.schema.yml @@ -337,6 +337,9 @@ system.action.*: label: 'Plugin' configuration: type: action.configuration.[plugin] + dependencies: + type: config_dependency + label: 'Dependencies' system.file: type: mapping 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/Entity/EntityCrudHookTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php index 5928304..c6d7fe7 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php @@ -133,6 +133,10 @@ public function testBlockHooks() { public function testCommentHooks() { $account = $this->createUser(); $this->enableModules(array('entity', 'filter')); + entity_create('node_type', array( + 'type' => 'article', + 'name' => 'Article', + ))->save(); $this->container->get('comment.manager')->addDefaultField('node', 'article', 'comment', COMMENT_OPEN); $node = entity_create('node', array( 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 b644c19..12ee30c 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/system/tests/modules/entity_test/config/entity.view_mode.entity_test.full.yml b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.full.yml index 412942c..321b372 100644 --- a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.full.yml +++ b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.full.yml @@ -3,3 +3,6 @@ label: Full status: false cache: true targetEntityType: entity_test +dependencies: + module: + - entity_test diff --git a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.test.yml b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.test.yml index baeed36..37534a3 100644 --- a/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.test.yml +++ b/core/modules/system/tests/modules/entity_test/config/entity.view_mode.entity_test.test.yml @@ -3,3 +3,6 @@ label: Test status: false cache: false targetEntityType: entity_test +dependencies: + module: + - entity_test diff --git a/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml b/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml index fb7b59c..50b1854 100644 --- a/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml +++ b/core/modules/taxonomy/config/entity.view_mode.taxonomy_term.full.yml @@ -3,3 +3,6 @@ label: 'Taxonomy term page' status: false cache: true targetEntityType: taxonomy_term +dependencies: + module: + - taxonomy diff --git a/core/modules/views/config/views.view.taxonomy_term.yml b/core/modules/taxonomy/config/views.view.taxonomy_term.yml similarity index 99% rename from core/modules/views/config/views.view.taxonomy_term.yml rename to core/modules/taxonomy/config/views.view.taxonomy_term.yml index beac139..10ce059 100644 --- a/core/modules/views/config/views.view.taxonomy_term.yml +++ b/core/modules/taxonomy/config/views.view.taxonomy_term.yml @@ -246,3 +246,7 @@ module: taxonomy id: taxonomy_term tag: default langcode: en +dependencies: + module: + - node + - taxonomy diff --git a/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerNodeAccessTest.php b/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerNodeAccessTest.php index 57828bf..7469377 100644 --- a/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerNodeAccessTest.php +++ b/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerNodeAccessTest.php @@ -32,6 +32,7 @@ public static function getInfo() { public function setUp() { parent::setUp(); node_access_rebuild(); + $this->drupalCreateContentType(array('type' => 'page')); $this->container->get('comment.manager')->addDefaultField('node', 'page', 'comment', COMMENT_OPEN); \Drupal::state()->set('node_access_test.private', TRUE); } diff --git a/core/modules/user/config/entity.form_mode.user.register.yml b/core/modules/user/config/entity.form_mode.user.register.yml index c720f19..06919cd 100644 --- a/core/modules/user/config/entity.form_mode.user.register.yml +++ b/core/modules/user/config/entity.form_mode.user.register.yml @@ -2,3 +2,6 @@ id: user.register label: Register status: true targetEntityType: user +dependencies: + module: + - user diff --git a/core/modules/user/config/entity.view_mode.user.compact.yml b/core/modules/user/config/entity.view_mode.user.compact.yml index 4522e10..6e0b13d 100644 --- a/core/modules/user/config/entity.view_mode.user.compact.yml +++ b/core/modules/user/config/entity.view_mode.user.compact.yml @@ -3,3 +3,6 @@ label: Compact status: true cache: true targetEntityType: user +dependencies: + module: + - user diff --git a/core/modules/user/config/entity.view_mode.user.full.yml b/core/modules/user/config/entity.view_mode.user.full.yml index a282b0c..2f0f250 100644 --- a/core/modules/user/config/entity.view_mode.user.full.yml +++ b/core/modules/user/config/entity.view_mode.user.full.yml @@ -3,3 +3,6 @@ label: 'User account' status: false cache: true targetEntityType: user +dependencies: + module: + - user diff --git a/core/modules/user/config/rdf.mapping.user.user.yml b/core/modules/user/config/rdf.mapping.user.user.yml index ad082a9..f052a1a 100644 --- a/core/modules/user/config/rdf.mapping.user.user.yml +++ b/core/modules/user/config/rdf.mapping.user.user.yml @@ -7,3 +7,6 @@ fieldMappings: name: properties: - 'schema:name' +dependencies: + module: + - user diff --git a/core/modules/user/config/search.page.user_search.yml b/core/modules/user/config/search.page.user_search.yml index bb130c2..50b0113 100644 --- a/core/modules/user/config/search.page.user_search.yml +++ b/core/modules/user/config/search.page.user_search.yml @@ -5,3 +5,6 @@ langcode: en path: user plugin: user_search configuration: { } +dependencies: + module: + - user diff --git a/core/modules/user/config/system.action.user_block_user_action.yml b/core/modules/user/config/system.action.user_block_user_action.yml index 57b69e9..d7e15c6 100644 --- a/core/modules/user/config/system.action.user_block_user_action.yml +++ b/core/modules/user/config/system.action.user_block_user_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: user plugin: user_block_user_action +dependencies: + module: + - user diff --git a/core/modules/user/config/system.action.user_cancel_user_action.yml b/core/modules/user/config/system.action.user_cancel_user_action.yml index 875ecee..bcc03ed 100644 --- a/core/modules/user/config/system.action.user_cancel_user_action.yml +++ b/core/modules/user/config/system.action.user_cancel_user_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: user plugin: user_cancel_user_action +dependencies: + module: + - user diff --git a/core/modules/user/config/system.action.user_unblock_user_action.yml b/core/modules/user/config/system.action.user_unblock_user_action.yml index 749e61b..0d313ea 100644 --- a/core/modules/user/config/system.action.user_unblock_user_action.yml +++ b/core/modules/user/config/system.action.user_unblock_user_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: user plugin: user_unblock_user_action +dependencies: + module: + - user 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 86f49be..89d1e4e 100644 --- a/core/modules/user/config/views.view.user_admin_people.yml +++ b/core/modules/user/config/views.view.user_admin_people.yml @@ -561,6 +561,7 @@ display: empty_zero: false hide_alter_empty: true text: Translate + optional: true plugin_id: content_translation_link provider: content_translation dropbutton: @@ -951,7 +952,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 4653796..f5bee58 100644 --- a/core/modules/user/config/views.view.who_s_new.yml +++ b/core/modules/user/config/views.view.who_s_new.yml @@ -167,7 +167,10 @@ display: relationships: { } arguments: { } label: 'Who''s new' -module: views +module: user id: who_s_new tag: default 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 040e2f9..efe344f 100644 --- a/core/modules/user/config/views.view.who_s_online.yml +++ b/core/modules/user/config/views.view.who_s_online.yml @@ -198,7 +198,10 @@ 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 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 62e5536..f219f7f 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/Entity/FieldEntityTest.php b/core/modules/views/lib/Drupal/views/Tests/Entity/FieldEntityTest.php index 95e661e..0d4ace2 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Entity/FieldEntityTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Entity/FieldEntityTest.php @@ -45,6 +45,7 @@ public function testGetEntity() { $account = entity_create('user', array('name' => $this->randomName(), 'bundle' => 'user')); $account->save(); + $this->drupalCreateContentType(array('type' => 'page')); $this->container->get('comment.manager')->addDefaultField('node', 'page'); // Force a flush of the in-memory storage. $this->container->get('views.views_data')->clear(); diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerAllTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerAllTest.php index 5f73592..a7dc428 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerAllTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerAllTest.php @@ -53,6 +53,7 @@ public static function getInfo() { * Tests most of the handlers. */ public function testHandlers() { + $this->drupalCreateContentType(array('type' => 'article')); $this->container->get('comment.manager')->addDefaultField('node', 'article'); $object_types = array_keys(ViewExecutable::viewsHandlerTypes()); diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerTest.php index c719fce..fae3c53 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerTest.php @@ -41,6 +41,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); + $this->drupalCreateContentType(array('type' => 'page')); $this->container->get('comment.manager')->addDefaultField('node', 'page'); $this->enableViewsTestModule(); } 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/ViewExecutableTest.php b/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php index fadc421..65bd43a 100644 --- a/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php @@ -88,6 +88,10 @@ protected function setUpFixtures() { $this->installSchema('node', array('node', 'node_field_data')); $this->installSchema('comment', array('comment', 'comment_entity_statistics')); $this->installConfig(array('field')); + entity_create('node_type', array( + 'type' => 'page', + 'name' => 'Page', + ))->save(); $this->container->get('comment.manager')->addDefaultField('node', 'page'); parent::setUpFixtures(); 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 1ea7ee2..840fa27 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..b58e1b3 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,10 @@ 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') { + // EntityInterface::isUninstalling() is only called during uninstallation + // process. ConfigEntityInterface::getConfigDependencyName is only used + // during dependency management. + if ($reflection_method->getName() != 'isNew' && $reflection_method->getName() != 'isSyncing' && $reflection_method->getName() != 'isUninstalling' && $reflection_method->getName() != 'getConfigDependencyName') { if (count($reflection_method->getParameters()) == 0) { $method_args[$reflection_method->getName()] = array(); } diff --git a/core/profiles/standard/config/block.block.bartik_breadcrumbs.yml b/core/profiles/standard/config/block.block.bartik_breadcrumbs.yml index 3465368..6431804 100644 --- a/core/profiles/standard/config/block.block.bartik_breadcrumbs.yml +++ b/core/profiles/standard/config/block.block.bartik_breadcrumbs.yml @@ -20,3 +20,6 @@ visibility: types: article: '0' page: '0' +dependencies: + module: + - system diff --git a/core/profiles/standard/config/block.block.bartik_content.yml b/core/profiles/standard/config/block.block.bartik_content.yml index 8146a54..25d595a 100644 --- a/core/profiles/standard/config/block.block.bartik_content.yml +++ b/core/profiles/standard/config/block.block.bartik_content.yml @@ -20,3 +20,6 @@ visibility: types: article: '0' page: '0' +dependencies: + module: + - system diff --git a/core/profiles/standard/config/block.block.bartik_footer.yml b/core/profiles/standard/config/block.block.bartik_footer.yml index 76f9508..fa9ba9b 100644 --- a/core/profiles/standard/config/block.block.bartik_footer.yml +++ b/core/profiles/standard/config/block.block.bartik_footer.yml @@ -20,3 +20,6 @@ visibility: types: article: '0' page: '0' +dependencies: + module: + - system \ No newline at end of file diff --git a/core/profiles/standard/config/block.block.bartik_help.yml b/core/profiles/standard/config/block.block.bartik_help.yml index 5806db7..9c95845 100644 --- a/core/profiles/standard/config/block.block.bartik_help.yml +++ b/core/profiles/standard/config/block.block.bartik_help.yml @@ -20,3 +20,6 @@ visibility: types: article: '0' page: '0' +dependencies: + module: + - system \ No newline at end of file diff --git a/core/profiles/standard/config/block.block.bartik_login.yml b/core/profiles/standard/config/block.block.bartik_login.yml index 7fc17cb..dc67c21 100644 --- a/core/profiles/standard/config/block.block.bartik_login.yml +++ b/core/profiles/standard/config/block.block.bartik_login.yml @@ -20,3 +20,6 @@ visibility: types: article: '0' page: '0' +dependencies: + module: + - user diff --git a/core/profiles/standard/config/block.block.bartik_powered.yml b/core/profiles/standard/config/block.block.bartik_powered.yml index 0e3ebab..66bd2de 100644 --- a/core/profiles/standard/config/block.block.bartik_powered.yml +++ b/core/profiles/standard/config/block.block.bartik_powered.yml @@ -20,3 +20,6 @@ visibility: types: article: '0' page: '0' +dependencies: + module: + - system \ No newline at end of file diff --git a/core/profiles/standard/config/block.block.bartik_search.yml b/core/profiles/standard/config/block.block.bartik_search.yml index f68adbc..72537b5 100644 --- a/core/profiles/standard/config/block.block.bartik_search.yml +++ b/core/profiles/standard/config/block.block.bartik_search.yml @@ -20,3 +20,6 @@ visibility: types: article: '0' page: '0' +dependencies: + module: + - search diff --git a/core/profiles/standard/config/block.block.bartik_tools.yml b/core/profiles/standard/config/block.block.bartik_tools.yml index 257990d..2a9f70b 100644 --- a/core/profiles/standard/config/block.block.bartik_tools.yml +++ b/core/profiles/standard/config/block.block.bartik_tools.yml @@ -20,3 +20,6 @@ visibility: types: article: '0' page: '0' +dependencies: + module: + - system \ No newline at end of file diff --git a/core/profiles/standard/config/block.block.seven_breadcrumbs.yml b/core/profiles/standard/config/block.block.seven_breadcrumbs.yml index b56f633..3984da8 100644 --- a/core/profiles/standard/config/block.block.seven_breadcrumbs.yml +++ b/core/profiles/standard/config/block.block.seven_breadcrumbs.yml @@ -20,3 +20,6 @@ visibility: types: article: '0' page: '0' +dependencies: + module: + - system diff --git a/core/profiles/standard/config/block.block.seven_content.yml b/core/profiles/standard/config/block.block.seven_content.yml index 23a6568..7d668d5 100644 --- a/core/profiles/standard/config/block.block.seven_content.yml +++ b/core/profiles/standard/config/block.block.seven_content.yml @@ -20,3 +20,6 @@ visibility: types: article: '0' page: '0' +dependencies: + module: + - system diff --git a/core/profiles/standard/config/block.block.seven_help.yml b/core/profiles/standard/config/block.block.seven_help.yml index 77918e5..84e6c5d 100644 --- a/core/profiles/standard/config/block.block.seven_help.yml +++ b/core/profiles/standard/config/block.block.seven_help.yml @@ -20,3 +20,6 @@ visibility: types: article: '0' page: '0' +dependencies: + module: + - system diff --git a/core/profiles/standard/config/block.block.seven_login.yml b/core/profiles/standard/config/block.block.seven_login.yml index 239bd36..fc8b1aa 100644 --- a/core/profiles/standard/config/block.block.seven_login.yml +++ b/core/profiles/standard/config/block.block.seven_login.yml @@ -20,3 +20,6 @@ visibility: types: article: '0' page: '0' +dependencies: + module: + - user diff --git a/core/profiles/standard/config/editor.editor.basic_html.yml b/core/profiles/standard/config/editor.editor.basic_html.yml index 155c5fb..ae23b38 100644 --- a/core/profiles/standard/config/editor.editor.basic_html.yml +++ b/core/profiles/standard/config/editor.editor.basic_html.yml @@ -41,3 +41,6 @@ image_upload: height: 0 status: true langcode: en +dependencies: + entity: + - filter.format.basic_html diff --git a/core/profiles/standard/config/editor.editor.full_html.yml b/core/profiles/standard/config/editor.editor.full_html.yml index cd17f03..52d6e4a 100644 --- a/core/profiles/standard/config/editor.editor.full_html.yml +++ b/core/profiles/standard/config/editor.editor.full_html.yml @@ -53,3 +53,6 @@ image_upload: height: 0 status: true langcode: en +dependencies: + entity: + - filter.format.full_html diff --git a/core/profiles/standard/config/entity.form_display.node.article.default.yml b/core/profiles/standard/config/entity.form_display.node.article.default.yml index ff157a9..af284c9 100644 --- a/core/profiles/standard/config/entity.form_display.node.article.default.yml +++ b/core/profiles/standard/config/entity.form_display.node.article.default.yml @@ -2,25 +2,40 @@ id: node.article.default targetEntityType: node bundle: article mode: default -status: true content: + title: + type: text_textfield + weight: 0 + settings: + size: 60 + placeholder: '' body: type: text_textarea_with_summary - weight: 0 + weight: 1 settings: rows: 9 summary_rows: 3 placeholder: '' + comment: + type: comment_default + weight: 2 + settings: { } field_tags: type: taxonomy_autocomplete - weight: -4 - settings: - size: 60 - autocomplete_route_name: taxonomy.autocomplete - placeholder: '' + weight: 3 + settings: { } field_image: type: image_image + weight: 4 settings: progress_indicator: throbber preview_image_style: thumbnail - weight: -1 +hidden: { } +status: true +dependencies: + entity: + - node.type.article + - field.instance.node.article.body + - field.instance.node.article.comment + - field.instance.node.article.field_tags + - field.instance.node.article.field_image diff --git a/core/profiles/standard/config/entity.view_display.node.article.default.yml b/core/profiles/standard/config/entity.view_display.node.article.default.yml index 6d76c36..3791d23 100644 --- a/core/profiles/standard/config/entity.view_display.node.article.default.yml +++ b/core/profiles/standard/config/entity.view_display.node.article.default.yml @@ -21,3 +21,6 @@ content: image_style: large image_link: '' weight: -1 +dependencies: + entity: + - node.type.article diff --git a/core/profiles/standard/config/entity.view_display.node.article.teaser.yml b/core/profiles/standard/config/entity.view_display.node.article.teaser.yml index 75bf6d0..b106352 100644 --- a/core/profiles/standard/config/entity.view_display.node.article.teaser.yml +++ b/core/profiles/standard/config/entity.view_display.node.article.teaser.yml @@ -22,3 +22,10 @@ content: image_style: medium image_link: content weight: -1 +dependencies: + entity: + - node.type.article + - field.instance.node.article.field_image + - field.instance.node.article.body + - field.instance.node.article.field_tags + - entity.view_mode.node.teaser 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 b397ecd..a0b1966 100644 --- a/core/profiles/standard/config/field.field.node.field_image.yml +++ b/core/profiles/standard/config/field.field.node.field_image.yml @@ -32,3 +32,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 55eac77..7018e87 100644 --- a/core/profiles/standard/config/field.field.node.field_tags.yml +++ b/core/profiles/standard/config/field.field.node.field_tags.yml @@ -16,3 +16,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 ecbe2c4..7becb75 100644 --- a/core/profiles/standard/config/field.field.user.user_picture.yml +++ b/core/profiles/standard/config/field.field.user.user_picture.yml @@ -32,3 +32,6 @@ translatable: false indexes: target_id: - target_id +dependencies: + module: + - image diff --git a/core/profiles/standard/config/field.instance.node.article.field_image.yml b/core/profiles/standard/config/field.instance.node.article.field_image.yml index 69d8593..11cbbd4 100644 --- a/core/profiles/standard/config/field.instance.node.article.field_image.yml +++ b/core/profiles/standard/config/field.instance.node.article.field_image.yml @@ -26,3 +26,6 @@ settings: status: true langcode: und field_type: image +dependencies: + entity: + - field.field.node.field_image diff --git a/core/profiles/standard/config/field.instance.node.article.field_tags.yml b/core/profiles/standard/config/field.instance.node.article.field_tags.yml index ed4e166..ed175f7 100644 --- a/core/profiles/standard/config/field.instance.node.article.field_tags.yml +++ b/core/profiles/standard/config/field.instance.node.article.field_tags.yml @@ -10,3 +10,6 @@ default_value_function: '' settings: { } status: true langcode: und +dependencies: + entity: + - field.field.node.field_tags diff --git a/core/profiles/standard/config/field.instance.user.user.user_picture.yml b/core/profiles/standard/config/field.instance.user.user.user_picture.yml index f31efe6..6469300 100644 --- a/core/profiles/standard/config/field.instance.user.user.user_picture.yml +++ b/core/profiles/standard/config/field.instance.user.user.user_picture.yml @@ -26,3 +26,6 @@ settings: alt_field_required: false title_field_required: false field_type: image +dependencies: + entity: + - field.field.user.user_picture diff --git a/core/profiles/standard/config/rdf.mapping.comment.node__comment.yml b/core/profiles/standard/config/rdf.mapping.comment.node__comment.yml index 42d8f34..70f25b1 100644 --- a/core/profiles/standard/config/rdf.mapping.comment.node__comment.yml +++ b/core/profiles/standard/config/rdf.mapping.comment.node__comment.yml @@ -24,3 +24,6 @@ fieldMappings: properties: - 'schema:author' mapping_type: 'rel' +dependencies: + module: + - comment diff --git a/core/profiles/standard/config/rdf.mapping.node.article.yml b/core/profiles/standard/config/rdf.mapping.node.article.yml index a87edaf..bf94488 100644 --- a/core/profiles/standard/config/rdf.mapping.node.article.yml +++ b/core/profiles/standard/config/rdf.mapping.node.article.yml @@ -40,3 +40,8 @@ fieldMappings: field_tags: properties: - 'schema:about' +dependencies: + module: + - node + entity: + - node.type.article diff --git a/core/profiles/standard/config/rdf.mapping.node.page.yml b/core/profiles/standard/config/rdf.mapping.node.page.yml index 967449c..1b4f61b 100644 --- a/core/profiles/standard/config/rdf.mapping.node.page.yml +++ b/core/profiles/standard/config/rdf.mapping.node.page.yml @@ -31,3 +31,8 @@ fieldMappings: callable: 'Drupal\rdf\SchemaOrgDataConverter::interactionCount' arguments: interaction_type: 'UserComments' +dependencies: + module: + - node + entity: + - node.type.page diff --git a/core/profiles/standard/config/rdf.mapping.taxonomy_term.tags.yml b/core/profiles/standard/config/rdf.mapping.taxonomy_term.tags.yml index 051795c..71cc138 100644 --- a/core/profiles/standard/config/rdf.mapping.taxonomy_term.tags.yml +++ b/core/profiles/standard/config/rdf.mapping.taxonomy_term.tags.yml @@ -10,3 +10,8 @@ fieldMappings: description: properties: - 'schema:description' +dependencies: + module: + - taxonomy + entity: + - taxonomy.vocabulary.tags diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigDependencyManagerTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigDependencyManagerTest.php new file mode 100644 index 0000000..a200148 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigDependencyManagerTest.php @@ -0,0 +1,44 @@ + 'ConfigDependencyManager test', + 'description' => 'Tests the ConfigDependencyManager class.', + 'group' => 'Configuration' + ); + } + + public function testNoConfiguration() { + $dep_manger = new ConfigDependencyManager(); + $this->assertEmpty($dep_manger->getDependentEntities('entity', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84')); + } + + public function testNoConfigEntities() { + $dep_manger = new ConfigDependencyManager(); + $dep_manger->setData(array( + 'simple.config' => array( + 'key' => 'value', + ), + )); + $this->assertEmpty($dep_manger->getDependentEntities('entity', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84')); + + // Configuration is always dependent on its provider. + $dependencies = $dep_manger->getDependentEntities('module', 'simple'); + $this->assertArrayHasKey('simple.config', $dependencies); + $this->assertCount(1, $dependencies); + } + +} diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityDependencyTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityDependencyTest.php new file mode 100644 index 0000000..ad68ab0 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityDependencyTest.php @@ -0,0 +1,62 @@ + 'ConfigEntityDependency test', + 'description' => 'Tests the ConfigEntityDependency class.', + 'group' => 'Configuration' + ); + } + + public function testEmptyDependencies() { + $dep = new ConfigEntityDependency('config_test.dynamic.entity_id', array()); + + $this->assertEquals('config_test.dynamic.entity_id', $dep->getName()); + $this->assertEquals('config_test.dynamic.entity_id', $dep->getConfigDependencyName()); + $this->assertEquals(array(), $dep->getDependencies('theme')); + $this->assertEquals(array(), $dep->getDependencies('entity')); + $this->assertEquals(array('config_test'), $dep->getDependencies('module')); + $this->assertTrue($dep->hasDependency('module', 'config_test')); + $this->assertFalse($dep->hasDependency('module', 'views')); + } + + public function testWithDependencies() { + $values = array( + 'uuid' => '60db47f4-54fb-4c86-a439-5769fbda4bd1', + 'dependencies' => array( + 'module' => array( + 'node', + 'views' + ), + 'entity' => array( + 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84', + ), + ), + ); + $dep = new ConfigEntityDependency('config_test.dynamic.entity_id', $values); + + $this->assertEquals(array(), $dep->getDependencies('theme')); + $this->assertEquals(array('config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84'), $dep->getDependencies('entity')); + $this->assertEquals(array('node', 'views', 'config_test'), $dep->getDependencies('module')); + $this->assertTrue($dep->hasDependency('module', 'config_test')); + $this->assertTrue($dep->hasDependency('module', 'views')); + $this->assertTrue($dep->hasDependency('module', 'node')); + $this->assertFalse($dep->hasDependency('module', 'block')); + $this->assertTrue($dep->hasDependency('entity', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84')); + $this->assertFalse($dep->hasDependency('entity', 'config_test.dynamic.another_id:7dfa5cb7-2248-4d52-8c00-cd8e02d1e78e')); + } + +}