Mercurial > hg > isophonics-drupal-site
diff core/modules/rest/src/Entity/ConfigDependencies.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/rest/src/Entity/ConfigDependencies.php Wed Nov 29 16:09:58 2017 +0000 @@ -0,0 +1,271 @@ +<?php + +namespace Drupal\rest\Entity; + +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\rest\RestResourceConfigInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Calculates rest resource config dependencies. + * + * @internal + */ +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; + } + +}