diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php index f52aad0..707474a 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php @@ -14,37 +14,70 @@ * Provides a class to discover configuration entity dependencies. * * Configuration entities can depend on modules, themes and other configuration - * entities. The dependency system is used during configuration installation to - * ensure that configuration entities are imported in the correct order. For - * example, node types are created before their field storages and the field - * storages are created before their fields. + * entities. The dependency system is used during configuration installation + * and removal to ensure that configuration entities are handled in the correct + * order. For example, node types are created before their field storages and + * the field storages are created before their fields. * - * Dependencies are stored to the configuration entity's configuration object so - * that they can be checked without the module that provides the configuration - * entity class being installed. This is important for configuration - * synchronization which needs to be able to validate configuration in the - * staging directory before the synchronization has occurred. + * Configuration entites need to declare their dependencies, and if they are + * part of extensions (modules, themes, or profiles), the extension also needs + * to ensure that the extensions the configuration depends on are present. For + * example, if a view configuration is part of a profile and the view will not + * work without a certain field module, the profile must declare a dependency on + * this field module in its info file. If you find that you do not want your + * extension to always depend on a particular module that one of your + * configuration items depends on, you can use a sub-module: move the + * configuration item to the sub-module, instead of including it in the main + * extension, and declare the module dependency in the sub-module only. * - * Configuration entities determine their dependencies by implementing - * \Drupal\Core\Config\Entity\ConfigEntityInterface::calculateDependencies(). - * This method should be called from the configuration entity's implementation - * of \Drupal\Core\Entity\EntityInterface::preSave(). Implementations should use - * the helper method - * \Drupal\Core\Config\Entity\ConfigEntityBase::addDependency() to add - * dependencies. All the implementations in core call the parent method - * \Drupal\Core\Config\Entity\ConfigEntityBase::calculateDependencies() which - * resets the dependencies and provides an implementation to determine the - * plugin providers for configuration entities that implement - * \Drupal\Core\Entity\EntityWithPluginBagsInterface. + * Classes for configuration entities with dependencies normally extend + * \Drupal\Core\Config\Entity\ConfigEntityBase or at least use + * \Drupal\Core\Plugin\PluginDependencyTrait to manage dependencies. The class + * must implement + * \Drupal\Core\Config\Entity\ConfigEntityInterface::calculateDependencies(), + * which should calculate (and return) the dependencies, and also call the + * \Drupal\Core\Config\Entity\ConfigEntityBase::addDependency() method for each + * calculated dependency. + * \Drupal\Core\Config\Entity\ConfigEntityBase::calculateDependencies() provides + * a good starting point to call from your implementation, as it will discover + * dependencies coming from plugin bags and third party settings (and as one + * further note, plugins can declare configuration dependencies in their plugin + * definitions, with a 'config_dependencies' key). During dependency checking, + * the entity class's implementation of + * \Drupal\Core\Config\Entity\ConfigEntityInterface::getDependencies() will be + * called; the base implementation will return the array of all dependencies + * added by calls to addDependency() methods. * - * The configuration manager service provides methods to find dependencies for - * a specified module, theme or configuration entity. + * Once declared properly, dependencies are saved to the configuration entity's + * configuration object so that they can be checked without the module that + * provides the configuration entity class being installed. This is important + * for configuration synchronization, which needs to be able to validate + * configuration in the staging directory before the synchronization has + * occurred. + * + * When an item that configuration can depend on is removed, such as when + * uninstalling a module, configuration that is dependent will also be + * removed. This default behavior could lead to undesirable side effects, such + * as a node type configuration being entirely removed when the module defining + * a field it contains is uninstalled. To prevent this, configuration entity + * classes can implement + * \Drupal\Core\Config\Entity\ConfigEntityInterface::onDependencyRemoval(), + * which allows the entity class to remove dependencies instead of being deleted + * themselves. Implementations should save the entity if dependencies have been + * successfully removed, in order to register the newly cleaned-out dependency + * list. So, in the above example, the node type configuration entity class + * should implement this method to remove field configurations when field + * modules are uninstalled, and entity display configuration classes should + * remove references to widgets and formatters if the plugin that supplies them + * depends on a module that is being uninstalled. * * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::calculateDependencies() * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::getConfigDependencyName() + * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::onDependencyRemoval() * @see \Drupal\Core\Config\Entity\ConfigEntityBase::addDependency() * @see \Drupal\Core\Config\ConfigInstaller::installDefaultConfig() * @see \Drupal\Core\Config\Entity\ConfigEntityDependency + * @see \Drupal\Core\Plugin\PluginDependencyTrait */ class ConfigDependencyManager { diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index c329032..f530fc8 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -358,13 +358,14 @@ public function url($rel = 'edit-form', $options = array()) { } /** - * {@inheritdoc} + * Overrides \Drupal\Core\Entity\DependencyTrait:addDependency(). + * + * @see \Drupal\Core\Config\Entity\ConfigEntityDependency::hasDependency() */ protected function addDependency($type, $name) { // A config entity is always dependent on its provider. There is no need to // explicitly declare the dependency. An explicit dependency on Core, which // provides some plugins, is also not needed. - // @see \Drupal\Core\Config\Entity\ConfigEntityDependency::hasDependency() if ($type == 'module' && ($name == $this->getEntityType()->getProvider() || $name == 'core')) { return $this; } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php index b15498e..b83df5d 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php @@ -10,7 +10,7 @@ use Drupal\Core\Entity\EntityInterface; /** - * Defines the interface common for all configuration entities. + * Defines a common interface for configuration entities. * * @ingroup config_api * @ingroup entity_api @@ -146,6 +146,8 @@ public function set($property_name, $value); * * @return array * An array of dependencies grouped by type (module, theme, entity). + * + * @see \Drupal\Core\Config\Entity\ConfigDependencyManager */ public function calculateDependencies(); @@ -154,6 +156,8 @@ public function calculateDependencies(); * * @return string * The configuration dependency name. + * + * @see \Drupal\Core\Config\Entity\ConfigDependencyManager */ public function getConfigDependencyName(); @@ -176,6 +180,7 @@ public function getConfigDependencyName(); * An array of dependencies that will be deleted keyed by dependency type. * Dependency types are, for example, entity, module and theme. * + * @see \Drupal\Core\Config\Entity\ConfigDependencyManager * @see \Drupal\Core\Config\ConfigManager::uninstall() * @see \Drupal\Core\Entity\EntityDisplayBase::onDependencyRemoval() */ @@ -185,8 +190,9 @@ public function onDependencyRemoval(array $dependencies); * Gets the configuration dependencies. * * @return array - * An array of dependencies. If $type not set all dependencies will be - * returned keyed by $type. + * An array of dependencies, keyed by $type. + * + * @see \Drupal\Core\Config\Entity\ConfigDependencyManager */ public function getDependencies(); diff --git a/core/lib/Drupal/Core/Entity/DependencyTrait.php b/core/lib/Drupal/Core/Entity/DependencyTrait.php index 2c77834..5815ab1 100644 --- a/core/lib/Drupal/Core/Entity/DependencyTrait.php +++ b/core/lib/Drupal/Core/Entity/DependencyTrait.php @@ -20,14 +20,13 @@ protected $dependencies = array(); /** - * Creates a dependency. + * Adds a dependency. * * @param string $type - * The type of dependency being checked. Either 'module', 'theme', 'entity'. + * The type of dependency being added: 'module', 'theme', or '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. + * If $type is 'module' or 'theme', the name of the module or theme. If + * $type is 'entity', the full configuration object name. * * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::getConfigDependencyName() * @@ -54,17 +53,17 @@ protected function addDependency($type, $name) { * * @param array $dependencies. * An array of dependencies keyed by the type of dependency. One example: - * @code - * array( - * 'module' => array( - * 'node', - * 'field', - * 'image' - * ), - * ); - * @endcode + * @code + * array( + * 'module' => array( + * 'node', + * 'field', + * 'image', + * ), + * ); + * @endcode * - * @see ::addDependency + * @see \Drupal\Core\Entity\DependencyTrait::addDependency */ protected function addDependencies(array $dependencies) { foreach ($dependencies as $dependency_type => $list) { diff --git a/core/lib/Drupal/Core/Plugin/PluginDependencyTrait.php b/core/lib/Drupal/Core/Plugin/PluginDependencyTrait.php index 21ec3ba..2114d38 100644 --- a/core/lib/Drupal/Core/Plugin/PluginDependencyTrait.php +++ b/core/lib/Drupal/Core/Plugin/PluginDependencyTrait.php @@ -19,7 +19,12 @@ use DependencyTrait; /** - * Calculates the dependencies of a specific plugin instance. + * Calculates and adds dependencies of a specific plugin instance. + * + * Dependencies are added for the module that provides the plugin, as well + * as any dependencies declared by the instance's calculateDependencies() + * method, if it implements + * \Drupal\Component\Plugin\ConfigurablePluginInterface. * * @param \Drupal\Component\Plugin\PluginInspectionInterface $instance * The plugin instance.