PageRenderTime 79ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/web/core/modules/rest/src/Entity/ConfigDependencies.php

https://gitlab.com/mohamed_hussein/prodt
PHP | 275 lines | 130 code | 20 blank | 125 comment | 27 complexity | 729b47230afc9418feb09f65f0ae5ea4 MD5 | raw file
  1. <?php
  2. namespace Drupal\rest\Entity;
  3. use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
  4. use Drupal\rest\RestResourceConfigInterface;
  5. use Symfony\Component\DependencyInjection\ContainerInterface;
  6. /**
  7. * Calculates rest resource config dependencies.
  8. *
  9. * @internal
  10. */
  11. class ConfigDependencies implements ContainerInjectionInterface {
  12. /**
  13. * The serialization format providers, keyed by format.
  14. *
  15. * @var string[]
  16. */
  17. protected $formatProviders;
  18. /**
  19. * The authentication providers, keyed by ID.
  20. *
  21. * @var string[]
  22. */
  23. protected $authProviders;
  24. /**
  25. * Creates a new ConfigDependencies instance.
  26. *
  27. * @param string[] $format_providers
  28. * The serialization format providers, keyed by format.
  29. * @param string[] $auth_providers
  30. * The authentication providers, keyed by ID.
  31. */
  32. public function __construct(array $format_providers, array $auth_providers) {
  33. $this->formatProviders = $format_providers;
  34. $this->authProviders = $auth_providers;
  35. }
  36. /**
  37. * {@inheritdoc}
  38. */
  39. public static function create(ContainerInterface $container) {
  40. return new static(
  41. $container->getParameter('serializer.format_providers'),
  42. $container->getParameter('authentication_providers')
  43. );
  44. }
  45. /**
  46. * Calculates dependencies of a specific rest resource configuration.
  47. *
  48. * This function returns dependencies in a non-sorted, non-unique manner. It
  49. * is therefore the caller's responsibility to sort and remove duplicates
  50. * from the result prior to saving it with the configuration or otherwise
  51. * using it in a way that requires that. For example,
  52. * \Drupal\rest\Entity\RestResourceConfig::calculateDependencies() does this
  53. * via its \Drupal\Core\Entity\DependencyTrait::addDependency() method.
  54. *
  55. * @param \Drupal\rest\RestResourceConfigInterface $rest_config
  56. * The rest configuration.
  57. *
  58. * @return string[][]
  59. * Dependencies keyed by dependency type.
  60. *
  61. * @see \Drupal\rest\Entity\RestResourceConfig::calculateDependencies()
  62. */
  63. public function calculateDependencies(RestResourceConfigInterface $rest_config) {
  64. $granularity = $rest_config->get('granularity');
  65. // Dependency calculation is the same for either granularity, the most
  66. // notable difference is that for the 'resource' granularity, the same
  67. // authentication providers and formats are supported for every method.
  68. switch ($granularity) {
  69. case RestResourceConfigInterface::METHOD_GRANULARITY:
  70. $methods = $rest_config->getMethods();
  71. break;
  72. case RestResourceConfigInterface::RESOURCE_GRANULARITY:
  73. $methods = array_slice($rest_config->getMethods(), 0, 1);
  74. break;
  75. default:
  76. throw new \InvalidArgumentException('Invalid granularity specified.');
  77. }
  78. // The dependency lists for authentication providers and formats
  79. // generated on container build.
  80. $dependencies = [];
  81. foreach ($methods as $request_method) {
  82. // Add dependencies based on the supported authentication providers.
  83. foreach ($rest_config->getAuthenticationProviders($request_method) as $auth) {
  84. if (isset($this->authProviders[$auth])) {
  85. $module_name = $this->authProviders[$auth];
  86. $dependencies['module'][] = $module_name;
  87. }
  88. }
  89. // Add dependencies based on the supported authentication formats.
  90. foreach ($rest_config->getFormats($request_method) as $format) {
  91. if (isset($this->formatProviders[$format])) {
  92. $module_name = $this->formatProviders[$format];
  93. $dependencies['module'][] = $module_name;
  94. }
  95. }
  96. }
  97. return $dependencies;
  98. }
  99. /**
  100. * Informs the entity that entities it depends on will be deleted.
  101. *
  102. * @param \Drupal\rest\RestResourceConfigInterface $rest_config
  103. * The rest configuration.
  104. * @param array $dependencies
  105. * An array of dependencies that will be deleted keyed by dependency type.
  106. * Dependency types are, for example, entity, module and theme.
  107. *
  108. * @return bool
  109. * TRUE if the entity has been changed as a result, FALSE if not.
  110. *
  111. * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::onDependencyRemoval()
  112. */
  113. public function onDependencyRemoval(RestResourceConfigInterface $rest_config, array $dependencies) {
  114. $granularity = $rest_config->get('granularity');
  115. switch ($granularity) {
  116. case RestResourceConfigInterface::METHOD_GRANULARITY:
  117. return $this->onDependencyRemovalForMethodGranularity($rest_config, $dependencies);
  118. case RestResourceConfigInterface::RESOURCE_GRANULARITY:
  119. return $this->onDependencyRemovalForResourceGranularity($rest_config, $dependencies);
  120. default:
  121. throw new \InvalidArgumentException('Invalid granularity specified.');
  122. }
  123. }
  124. /**
  125. * Informs the entity that entities it depends on will be deleted.
  126. *
  127. * @param \Drupal\rest\RestResourceConfigInterface $rest_config
  128. * The rest configuration.
  129. * @param array $dependencies
  130. * An array of dependencies that will be deleted keyed by dependency type.
  131. * Dependency types are, for example, entity, module and theme.
  132. *
  133. * @return bool
  134. * TRUE if the entity has been changed as a result, FALSE if not.
  135. */
  136. protected function onDependencyRemovalForMethodGranularity(RestResourceConfigInterface $rest_config, array $dependencies) {
  137. $changed = FALSE;
  138. // Only module-related dependencies can be fixed. All other types of
  139. // dependencies cannot, because they were not generated based on supported
  140. // authentication providers or formats.
  141. if (isset($dependencies['module'])) {
  142. // Try to fix dependencies.
  143. $removed_auth = array_keys(array_intersect($this->authProviders, $dependencies['module']));
  144. $removed_formats = array_keys(array_intersect($this->formatProviders, $dependencies['module']));
  145. $configuration_before = $configuration = $rest_config->get('configuration');
  146. if (!empty($removed_auth) || !empty($removed_formats)) {
  147. // Try to fix dependency problems by removing affected
  148. // authentication providers and formats.
  149. foreach (array_keys($rest_config->get('configuration')) as $request_method) {
  150. foreach ($removed_formats as $format) {
  151. if (in_array($format, $rest_config->getFormats($request_method), TRUE)) {
  152. $configuration[$request_method]['supported_formats'] = array_diff($configuration[$request_method]['supported_formats'], $removed_formats);
  153. }
  154. }
  155. foreach ($removed_auth as $auth) {
  156. if (in_array($auth, $rest_config->getAuthenticationProviders($request_method), TRUE)) {
  157. $configuration[$request_method]['supported_auth'] = array_diff($configuration[$request_method]['supported_auth'], $removed_auth);
  158. }
  159. }
  160. if (empty($configuration[$request_method]['supported_auth'])) {
  161. // Remove the key if there are no more authentication providers
  162. // supported by this request method.
  163. unset($configuration[$request_method]['supported_auth']);
  164. }
  165. if (empty($configuration[$request_method]['supported_formats'])) {
  166. // Remove the key if there are no more formats supported by this
  167. // request method.
  168. unset($configuration[$request_method]['supported_formats']);
  169. }
  170. if (empty($configuration[$request_method])) {
  171. // Remove the request method altogether if it no longer has any
  172. // supported authentication providers or formats.
  173. unset($configuration[$request_method]);
  174. }
  175. }
  176. }
  177. if ($configuration_before != $configuration && !empty($configuration)) {
  178. $rest_config->set('configuration', $configuration);
  179. // Only mark the dependencies problems as fixed if there is any
  180. // configuration left.
  181. $changed = TRUE;
  182. }
  183. }
  184. // If the dependency problems are not marked as fixed at this point they
  185. // should be related to the resource plugin and the config entity should
  186. // be deleted.
  187. return $changed;
  188. }
  189. /**
  190. * Informs the entity that entities it depends on will be deleted.
  191. *
  192. * @param \Drupal\rest\RestResourceConfigInterface $rest_config
  193. * The rest configuration.
  194. * @param array $dependencies
  195. * An array of dependencies that will be deleted keyed by dependency type.
  196. * Dependency types are, for example, entity, module and theme.
  197. *
  198. * @return bool
  199. * TRUE if the entity has been changed as a result, FALSE if not.
  200. */
  201. protected function onDependencyRemovalForResourceGranularity(RestResourceConfigInterface $rest_config, array $dependencies) {
  202. $changed = FALSE;
  203. // Only module-related dependencies can be fixed. All other types of
  204. // dependencies cannot, because they were not generated based on supported
  205. // authentication providers or formats.
  206. if (isset($dependencies['module'])) {
  207. // Try to fix dependencies.
  208. $removed_auth = array_keys(array_intersect($this->authProviders, $dependencies['module']));
  209. $removed_formats = array_keys(array_intersect($this->formatProviders, $dependencies['module']));
  210. $configuration_before = $configuration = $rest_config->get('configuration');
  211. if (!empty($removed_auth) || !empty($removed_formats)) {
  212. // All methods support the same formats and authentication providers, so
  213. // get those for whichever the first listed method is.
  214. $first_method = $rest_config->getMethods()[0];
  215. // Try to fix dependency problems by removing affected
  216. // authentication providers and formats.
  217. foreach ($removed_formats as $format) {
  218. if (in_array($format, $rest_config->getFormats($first_method), TRUE)) {
  219. $configuration['formats'] = array_diff($configuration['formats'], $removed_formats);
  220. }
  221. }
  222. foreach ($removed_auth as $auth) {
  223. if (in_array($auth, $rest_config->getAuthenticationProviders($first_method), TRUE)) {
  224. $configuration['authentication'] = array_diff($configuration['authentication'], $removed_auth);
  225. }
  226. }
  227. if (empty($configuration['authentication'])) {
  228. // Remove the key if there are no more authentication providers
  229. // supported.
  230. unset($configuration['authentication']);
  231. }
  232. if (empty($configuration['formats'])) {
  233. // Remove the key if there are no more formats supported.
  234. unset($configuration['formats']);
  235. }
  236. if (empty($configuration['authentication']) || empty($configuration['formats'])) {
  237. // If there no longer are any supported authentication providers or
  238. // formats, this REST resource can no longer function, and so we
  239. // cannot fix this config entity to keep it working.
  240. $configuration = [];
  241. }
  242. }
  243. if ($configuration_before != $configuration && !empty($configuration)) {
  244. $rest_config->set('configuration', $configuration);
  245. // Only mark the dependencies problems as fixed if there is any
  246. // configuration left.
  247. $changed = TRUE;
  248. }
  249. }
  250. // If the dependency problems are not marked as fixed at this point they
  251. // should be related to the resource plugin and the config entity should
  252. // be deleted.
  253. return $changed;
  254. }
  255. }