Move into nested docroot

This commit is contained in:
Rob Davies 2017-02-13 15:31:17 +00:00
parent 83a0d3a149
commit c8b70abde9
13405 changed files with 0 additions and 0 deletions

View 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;
}
}

View 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);
}
}