/web/core/modules/rest/src/Entity/ConfigDependencies.php
https://gitlab.com/andecode/theme-spark · PHP · 275 lines · 130 code · 20 blank · 125 comment · 27 complexity · 729b47230afc9418feb09f65f0ae5ea4 MD5 · raw file
- <?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;
- }
- }