diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php index d2f4208..707474a 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php @@ -19,60 +19,57 @@ * order. For example, node types are created before their field storages and * the field storages are created before their fields. * - * Dependencies in configuration do not supersede dependencies of containing - * modules/themes/profiles. For example if a view is shipped with an install - * profile and the view requires a 3rd party field module, the configuration - * will still be installed even if the profile does not require the module - * providing the field type. It is the responsibility of the containing project - * to depend on required modules. To include configuration that depends on - * optional 3rd party modules, add submodules that depend on that module in your - * project. The configuration dependency system is only used to manage ordering - * in the install/import processes and remove configuration in the module - * uninstall process. + * 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. * - * 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. + * 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. * - * 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. + * 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. * - * \Drupal\Core\Plugin\PluginDependencyTrait is also provided for convenience - * to calculate plugin based dependencies. Also used by configuration entities, - * this lets system menu blocks to depend on the displayed menu entity. This is - * crucial to ensure a configuration import will import the menu first before - * the block is saved on the system. - * - * The configuration manager service provides methods to find dependencies for - * a specified module, theme or configuration entity. - * - * When dependent items are removed (such a module providing a field type is - * uninstalled), configuration that was dependent will also be removed. This - * may lead to unintended side effects (eg. node types and displays being - * removed on uninstall of a field), so a more fine grained mechanism is - * provided to respond to dependency removal. - * \Drupal\Core\Config\Entity\ConfigEntityInterface::onDependencyRemoval() is - * invoked to allow configuration entities to respond if any of their - * dependencies is going to be removed (ie. if an entity is going to be deleted - * or a module uninstalled). This method allows configuration entities to remove - * dependencies instead of being deleted themselves. When a module is being - * uninstalled, configuration entities can use this method to avoid being - * unnecessarily deleted. Implementations should save the entity if dependencies - * have been successfully removed. - * - * For example, entity displays remove references to widgets and formatters if - * the plugin that supplies them depends on a module that is being uninstalled. + * 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() 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 3b18c0a..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 @@ -190,8 +190,7 @@ 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 */ 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.