Move into nested docroot
This commit is contained in:
parent
83a0d3a149
commit
c8b70abde9
13405 changed files with 0 additions and 0 deletions
271
web/core/modules/rest/src/Entity/ConfigDependencies.php
Normal file
271
web/core/modules/rest/src/Entity/ConfigDependencies.php
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
258
web/core/modules/rest/src/Entity/RestResourceConfig.php
Normal file
258
web/core/modules/rest/src/Entity/RestResourceConfig.php
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\rest\Entity;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityBase;
|
||||
use Drupal\Core\Plugin\DefaultSingleLazyPluginCollection;
|
||||
use Drupal\rest\RestResourceConfigInterface;
|
||||
|
||||
/**
|
||||
* Defines a RestResourceConfig configuration entity class.
|
||||
*
|
||||
* @ConfigEntityType(
|
||||
* id = "rest_resource_config",
|
||||
* label = @Translation("REST resource configuration"),
|
||||
* config_prefix = "resource",
|
||||
* admin_permission = "administer rest resources",
|
||||
* label_callback = "getLabelFromPlugin",
|
||||
* entity_keys = {
|
||||
* "id" = "id"
|
||||
* },
|
||||
* config_export = {
|
||||
* "id",
|
||||
* "plugin_id",
|
||||
* "granularity",
|
||||
* "configuration"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class RestResourceConfig extends ConfigEntityBase implements RestResourceConfigInterface {
|
||||
|
||||
/**
|
||||
* The REST resource config id.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* The REST resource plugin id.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_id;
|
||||
|
||||
/**
|
||||
* The REST resource configuration granularity.
|
||||
*
|
||||
* Currently either:
|
||||
* - \Drupal\rest\RestResourceConfigInterface::METHOD_GRANULARITY
|
||||
* - \Drupal\rest\RestResourceConfigInterface::RESOURCE_GRANULARITY
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $granularity;
|
||||
|
||||
/**
|
||||
* The REST resource configuration.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $configuration;
|
||||
|
||||
/**
|
||||
* The rest resource plugin manager.
|
||||
*
|
||||
* @var \Drupal\Component\Plugin\PluginManagerInterface
|
||||
*/
|
||||
protected $pluginManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $values, $entity_type) {
|
||||
parent::__construct($values, $entity_type);
|
||||
// The config entity id looks like the plugin id but uses __ instead of :
|
||||
// because : is not valid for config entities.
|
||||
if (!isset($this->plugin_id) && isset($this->id)) {
|
||||
// Generate plugin_id on first entity creation.
|
||||
$this->plugin_id = str_replace('.', ':', $this->id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The label callback for this configuration entity.
|
||||
*
|
||||
* @return string The label.
|
||||
*/
|
||||
protected function getLabelFromPlugin() {
|
||||
$plugin_definition = $this->getResourcePluginManager()
|
||||
->getDefinition(['id' => $this->plugin_id]);
|
||||
return $plugin_definition['label'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource plugin manager.
|
||||
*
|
||||
* @return \Drupal\Component\Plugin\PluginManagerInterface
|
||||
*/
|
||||
protected function getResourcePluginManager() {
|
||||
if (!isset($this->pluginManager)) {
|
||||
$this->pluginManager = \Drupal::service('plugin.manager.rest');
|
||||
}
|
||||
return $this->pluginManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getResourcePlugin() {
|
||||
return $this->getPluginCollections()['resource']->get($this->plugin_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMethods() {
|
||||
switch ($this->granularity) {
|
||||
case RestResourceConfigInterface::METHOD_GRANULARITY:
|
||||
return $this->getMethodsForMethodGranularity();
|
||||
case RestResourceConfigInterface::RESOURCE_GRANULARITY:
|
||||
return $this->configuration['methods'];
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid granularity specified.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of supported HTTP methods for this resource.
|
||||
*
|
||||
* @return string[]
|
||||
* A list of supported HTTP methods.
|
||||
*/
|
||||
protected function getMethodsForMethodGranularity() {
|
||||
$methods = array_keys($this->configuration);
|
||||
return array_map([$this, 'normalizeRestMethod'], $methods);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAuthenticationProviders($method) {
|
||||
switch ($this->granularity) {
|
||||
case RestResourceConfigInterface::METHOD_GRANULARITY:
|
||||
return $this->getAuthenticationProvidersForMethodGranularity($method);
|
||||
case RestResourceConfigInterface::RESOURCE_GRANULARITY:
|
||||
return $this->configuration['authentication'];
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid granularity specified.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of supported authentication providers.
|
||||
*
|
||||
* @param string $method
|
||||
* The request method e.g GET or POST.
|
||||
*
|
||||
* @return string[]
|
||||
* A list of supported authentication provider IDs.
|
||||
*/
|
||||
public function getAuthenticationProvidersForMethodGranularity($method) {
|
||||
$method = $this->normalizeRestMethod($method);
|
||||
if (in_array($method, $this->getMethods()) && isset($this->configuration[$method]['supported_auth'])) {
|
||||
return $this->configuration[$method]['supported_auth'];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormats($method) {
|
||||
switch ($this->granularity) {
|
||||
case RestResourceConfigInterface::METHOD_GRANULARITY:
|
||||
return $this->getFormatsForMethodGranularity($method);
|
||||
case RestResourceConfigInterface::RESOURCE_GRANULARITY:
|
||||
return $this->configuration['formats'];
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid granularity specified.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of supported response formats.
|
||||
*
|
||||
* @param string $method
|
||||
* The request method e.g GET or POST.
|
||||
*
|
||||
* @return string[]
|
||||
* A list of supported format IDs.
|
||||
*/
|
||||
protected function getFormatsForMethodGranularity($method) {
|
||||
$method = $this->normalizeRestMethod($method);
|
||||
if (in_array($method, $this->getMethods()) && isset($this->configuration[$method]['supported_formats'])) {
|
||||
return $this->configuration[$method]['supported_formats'];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPluginCollections() {
|
||||
return [
|
||||
'resource' => new DefaultSingleLazyPluginCollection($this->getResourcePluginManager(), $this->plugin_id, [])
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* (@inheritdoc)
|
||||
*/
|
||||
public function calculateDependencies() {
|
||||
parent::calculateDependencies();
|
||||
|
||||
foreach ($this->getRestResourceDependencies()->calculateDependencies($this) as $type => $dependencies) {
|
||||
foreach ($dependencies as $dependency) {
|
||||
$this->addDependency($type, $dependency);
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onDependencyRemoval(array $dependencies) {
|
||||
$parent = parent::onDependencyRemoval($dependencies);
|
||||
|
||||
// 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.
|
||||
$changed = $this->getRestResourceDependencies()->onDependencyRemoval($this, $dependencies);
|
||||
return $parent || $changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the REST resource dependencies.
|
||||
*
|
||||
* @return \Drupal\rest\Entity\ConfigDependencies
|
||||
*/
|
||||
protected function getRestResourceDependencies() {
|
||||
return \Drupal::service('class_resolver')->getInstanceFromDefinition(ConfigDependencies::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the method.
|
||||
*
|
||||
* @param string $method
|
||||
* The request method.
|
||||
*
|
||||
* @return string
|
||||
* The normalized request method.
|
||||
*/
|
||||
protected function normalizeRestMethod($method) {
|
||||
return strtoupper($method);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in a new issue