Commit 1efaefb1 authored by webchick's avatar webchick

Issue #2235363 by jhodgdon, jessebeach, alexpott, Gábor Hojtsy: Document config dependencies.

parent 068bb1a0
......@@ -14,37 +14,69 @@
* 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,
* uninstallation, and synchronization to ensure that configuration entities are
* handled in the correct order. For example, node types are created before
* their fields, and both are created before the view display configuration.
*
* 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.
* If a configuration entity is provided as default configuration by an
* extension (module, theme, or profile), the extension has to depend on any
* modules or themes that the configuration depends on. For example, if a view
* configuration entity is provided by an installation profile and the view will
* not work without a certain module, the profile must declare a dependency on
* this module in its info.yml file. If you do not want your extension to always
* depend on a particular module that one of its default configuration entities
* depends on, you can use a sub-module: move the configuration entity 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
* 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. In this method, use
* \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.
* dependencies. Most implementations call
* \Drupal\Core\Config\Entity\ConfigEntityBase::calculateDependencies() since it
* provides a generic implementation that will discover dependencies due to
* plugins and third party settings. To get a configuration entity's current
* dependencies without forcing a recalculation use
* \Drupal\Core\Config\Entity\ConfigEntityInterface::getDependencies().
*
* The configuration manager service provides methods to find dependencies for
* a specified module, theme or configuration entity.
* Classes for configurable plugins are a special case. They can either declare
* their configuration dependencies using the calculateDependencies() method
* described in the paragraph above, or if they have only static dependencies,
* these can be declared using the 'config_dependencies' annotation key.
*
* 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 uninstalling a module or a theme, configuration entities that are
* dependent will also be removed. This default behavior can lead to undesirable
* side effects, such as a node view mode being entirely removed when the module
* defining a field or formatter it uses 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 view mode configuration entity class
* should implement this method to remove references to 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\ConfigInstallerInterface::installDefaultConfig()
* @see \Drupal\Core\Config\ConfigManagerInterface::uninstall()
* @see \Drupal\Core\Config\Entity\ConfigEntityDependency
* @see \Drupal\Core\Plugin\PluginDependencyTrait
*/
class ConfigDependencyManager {
......
......@@ -365,13 +365,18 @@ public function link($text = NULL, $rel = 'edit-form', array $options = []) {
}
/**
* {@inheritdoc}
* Overrides \Drupal\Core\Entity\DependencyTrait:addDependency().
*
* Note that this function should only be called from implementations of
* \Drupal\Core\Config\Entity\ConfigEntityInterface::calculateDependencies(),
* as dependencies are recalculated during every entity save.
*
* @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;
}
......
......@@ -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();
......
......@@ -20,14 +20,13 @@ trait DependencyTrait {
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) {
......
......@@ -19,7 +19,12 @@ trait PluginDependencyTrait {
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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment