class ConfigDependencies
Same name in other branches
- 9 core/modules/rest/src/Entity/ConfigDependencies.php \Drupal\rest\Entity\ConfigDependencies
- 8.9.x core/modules/rest/src/Entity/ConfigDependencies.php \Drupal\rest\Entity\ConfigDependencies
- 10 core/modules/rest/src/Entity/ConfigDependencies.php \Drupal\rest\Entity\ConfigDependencies
Calculates rest resource config dependencies.
@internal
Hierarchy
- class \Drupal\rest\Entity\ConfigDependencies implements \Drupal\Core\DependencyInjection\ContainerInjectionInterface
Expanded class hierarchy of ConfigDependencies
1 file declares its use of ConfigDependencies
- ConfigDependenciesTest.php in core/
modules/ rest/ tests/ src/ Kernel/ Entity/ ConfigDependenciesTest.php
File
-
core/
modules/ rest/ src/ Entity/ ConfigDependencies.php, line 14
Namespace
Drupal\rest\EntityView source
class ConfigDependencies implements ContainerInjectionInterface {
/**
* The serialization format providers, keyed by format.
*
* @var string[]
*/
protected $formatProviders;
/**
* The authentication providers, keyed by ID.
*
* @var string[]
*/
protected $authProviders;
/**
* Creates a new ConfigDependencies instance.
*
* @param string[] $format_providers
* The serialization format providers, keyed by format.
* @param string[] $auth_providers
* The authentication providers, keyed by ID.
*/
public function __construct(array $format_providers, array $auth_providers) {
$this->formatProviders = $format_providers;
$this->authProviders = $auth_providers;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->getParameter('serializer.format_providers'), $container->getParameter('authentication_providers'));
}
/**
* Calculates dependencies of a specific rest resource configuration.
*
* This function returns dependencies in a non-sorted, non-unique manner. It
* is therefore the caller's responsibility to sort and remove duplicates
* from the result prior to saving it with the configuration or otherwise
* using it in a way that requires that. For example,
* \Drupal\rest\Entity\RestResourceConfig::calculateDependencies() does this
* via its \Drupal\Core\Entity\DependencyTrait::addDependency() method.
*
* @param \Drupal\rest\RestResourceConfigInterface $rest_config
* The rest configuration.
*
* @return string[][]
* Dependencies keyed by dependency type.
*
* @see \Drupal\rest\Entity\RestResourceConfig::calculateDependencies()
*/
public function calculateDependencies(RestResourceConfigInterface $rest_config) {
$granularity = $rest_config->get('granularity');
// Dependency calculation is the same for either granularity, the most
// notable difference is that for the 'resource' granularity, the same
// authentication providers and formats are supported for every method.
switch ($granularity) {
case RestResourceConfigInterface::METHOD_GRANULARITY:
$methods = $rest_config->getMethods();
break;
case RestResourceConfigInterface::RESOURCE_GRANULARITY:
$methods = array_slice($rest_config->getMethods(), 0, 1);
break;
default:
throw new \InvalidArgumentException('Invalid granularity specified.');
}
// The dependency lists for authentication providers and formats
// generated on container build.
$dependencies = [];
foreach ($methods as $request_method) {
// Add dependencies based on the supported authentication providers.
foreach ($rest_config->getAuthenticationProviders($request_method) as $auth) {
if (isset($this->authProviders[$auth])) {
$module_name = $this->authProviders[$auth];
$dependencies['module'][] = $module_name;
}
}
// Add dependencies based on the supported authentication formats.
foreach ($rest_config->getFormats($request_method) as $format) {
if (isset($this->formatProviders[$format])) {
$module_name = $this->formatProviders[$format];
$dependencies['module'][] = $module_name;
}
}
}
return $dependencies;
}
/**
* Informs the entity that entities it depends on will be deleted.
*
* @param \Drupal\rest\RestResourceConfigInterface $rest_config
* The rest configuration.
* @param array $dependencies
* An array of dependencies that will be deleted keyed by dependency type.
* Dependency types are, for example, entity, module and theme.
*
* @return bool
* TRUE if the entity has been changed as a result, FALSE if not.
*
* @see \Drupal\Core\Config\Entity\ConfigEntityInterface::onDependencyRemoval()
*/
public function onDependencyRemoval(RestResourceConfigInterface $rest_config, array $dependencies) {
$granularity = $rest_config->get('granularity');
switch ($granularity) {
case RestResourceConfigInterface::METHOD_GRANULARITY:
return $this->onDependencyRemovalForMethodGranularity($rest_config, $dependencies);
case RestResourceConfigInterface::RESOURCE_GRANULARITY:
return $this->onDependencyRemovalForResourceGranularity($rest_config, $dependencies);
default:
throw new \InvalidArgumentException('Invalid granularity specified.');
}
}
/**
* Informs the entity that entities it depends on will be deleted.
*
* @param \Drupal\rest\RestResourceConfigInterface $rest_config
* The rest configuration.
* @param array $dependencies
* An array of dependencies that will be deleted keyed by dependency type.
* Dependency types are, for example, entity, module and theme.
*
* @return bool
* TRUE if the entity has been changed as a result, FALSE if not.
*/
protected function onDependencyRemovalForMethodGranularity(RestResourceConfigInterface $rest_config, array $dependencies) {
$changed = FALSE;
// Only module-related dependencies can be fixed. All other types of
// dependencies cannot, because they were not generated based on supported
// authentication providers or formats.
if (isset($dependencies['module'])) {
// Try to fix dependencies.
$removed_auth = array_keys(array_intersect($this->authProviders, $dependencies['module']));
$removed_formats = array_keys(array_intersect($this->formatProviders, $dependencies['module']));
$configuration_before = $configuration = $rest_config->get('configuration');
if (!empty($removed_auth) || !empty($removed_formats)) {
// Try to fix dependency problems by removing affected
// authentication providers and formats.
foreach (array_keys($rest_config->get('configuration')) as $request_method) {
foreach ($removed_formats as $format) {
if (in_array($format, $rest_config->getFormats($request_method), TRUE)) {
$configuration[$request_method]['supported_formats'] = array_diff($configuration[$request_method]['supported_formats'], $removed_formats);
}
}
foreach ($removed_auth as $auth) {
if (in_array($auth, $rest_config->getAuthenticationProviders($request_method), TRUE)) {
$configuration[$request_method]['supported_auth'] = array_diff($configuration[$request_method]['supported_auth'], $removed_auth);
}
}
if (empty($configuration[$request_method]['supported_auth'])) {
// Remove the key if there are no more authentication providers
// supported by this request method.
unset($configuration[$request_method]['supported_auth']);
}
if (empty($configuration[$request_method]['supported_formats'])) {
// Remove the key if there are no more formats supported by this
// request method.
unset($configuration[$request_method]['supported_formats']);
}
if (empty($configuration[$request_method])) {
// Remove the request method altogether if it no longer has any
// supported authentication providers or formats.
unset($configuration[$request_method]);
}
}
}
if ($configuration_before != $configuration && !empty($configuration)) {
$rest_config->set('configuration', $configuration);
// Only mark the dependencies problems as fixed if there is any
// configuration left.
$changed = TRUE;
}
}
// If the dependency problems are not marked as fixed at this point they
// should be related to the resource plugin and the config entity should
// be deleted.
return $changed;
}
/**
* Informs the entity that entities it depends on will be deleted.
*
* @param \Drupal\rest\RestResourceConfigInterface $rest_config
* The rest configuration.
* @param array $dependencies
* An array of dependencies that will be deleted keyed by dependency type.
* Dependency types are, for example, entity, module and theme.
*
* @return bool
* TRUE if the entity has been changed as a result, FALSE if not.
*/
protected function onDependencyRemovalForResourceGranularity(RestResourceConfigInterface $rest_config, array $dependencies) {
$changed = FALSE;
// Only module-related dependencies can be fixed. All other types of
// dependencies cannot, because they were not generated based on supported
// authentication providers or formats.
if (isset($dependencies['module'])) {
// Try to fix dependencies.
$removed_auth = array_keys(array_intersect($this->authProviders, $dependencies['module']));
$removed_formats = array_keys(array_intersect($this->formatProviders, $dependencies['module']));
$configuration_before = $configuration = $rest_config->get('configuration');
if (!empty($removed_auth) || !empty($removed_formats)) {
// All methods support the same formats and authentication providers, so
// get those for whichever the first listed method is.
$first_method = $rest_config->getMethods()[0];
// Try to fix dependency problems by removing affected
// authentication providers and formats.
foreach ($removed_formats as $format) {
if (in_array($format, $rest_config->getFormats($first_method), TRUE)) {
$configuration['formats'] = array_diff($configuration['formats'], $removed_formats);
}
}
foreach ($removed_auth as $auth) {
if (in_array($auth, $rest_config->getAuthenticationProviders($first_method), TRUE)) {
$configuration['authentication'] = array_diff($configuration['authentication'], $removed_auth);
}
}
if (empty($configuration['authentication'])) {
// Remove the key if there are no more authentication providers
// supported.
unset($configuration['authentication']);
}
if (empty($configuration['formats'])) {
// Remove the key if there are no more formats supported.
unset($configuration['formats']);
}
if (empty($configuration['authentication']) || empty($configuration['formats'])) {
// If there no longer are any supported authentication providers or
// formats, this REST resource can no longer function, and so we
// cannot fix this config entity to keep it working.
$configuration = [];
}
}
if ($configuration_before != $configuration && !empty($configuration)) {
$rest_config->set('configuration', $configuration);
// Only mark the dependencies problems as fixed if there is any
// configuration left.
$changed = TRUE;
}
}
// If the dependency problems are not marked as fixed at this point they
// should be related to the resource plugin and the config entity should
// be deleted.
return $changed;
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overriden Title |
---|---|---|---|---|
ConfigDependencies::$authProviders | protected | property | The authentication providers, keyed by ID. | |
ConfigDependencies::$formatProviders | protected | property | The serialization format providers, keyed by format. | |
ConfigDependencies::calculateDependencies | public | function | Calculates dependencies of a specific rest resource configuration. | |
ConfigDependencies::create | public static | function | Instantiates a new instance of this class. | Overrides ContainerInjectionInterface::create |
ConfigDependencies::onDependencyRemoval | public | function | Informs the entity that entities it depends on will be deleted. | |
ConfigDependencies::onDependencyRemovalForMethodGranularity | protected | function | Informs the entity that entities it depends on will be deleted. | |
ConfigDependencies::onDependencyRemovalForResourceGranularity | protected | function | Informs the entity that entities it depends on will be deleted. | |
ConfigDependencies::__construct | public | function | Creates a new ConfigDependencies instance. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.