/** * 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; }
/** * Provides all routes for a given REST resource config. * * This method determines where a resource is reachable, what path * replacements are used, the required HTTP method for the operation etc. * * @param \Drupal\rest\RestResourceConfigInterface $rest_resource_config * The rest resource config. * * @return \Symfony\Component\Routing\RouteCollection * The route collection. */ protected function getRoutesForResourceConfig(RestResourceConfigInterface $rest_resource_config) { $plugin = $rest_resource_config->getResourcePlugin(); $collection = new RouteCollection(); foreach ($plugin->routes() as $name => $route) { /** @var \Symfony\Component\Routing\Route $route */ // @todo: Are multiple methods possible here? $methods = $route->getMethods(); // Only expose routes where the method is enabled in the configuration. if ($methods && ($method = $methods[0]) && ($supported_formats = $rest_resource_config->getFormats($method))) { $route->setRequirement('_csrf_request_header_token', 'TRUE'); // Check that authentication providers are defined. if (empty($rest_resource_config->getAuthenticationProviders($method))) { $this->logger->error('At least one authentication provider must be defined for resource @id', array(':id' => $rest_resource_config->id())); continue; } // Check that formats are defined. if (empty($rest_resource_config->getFormats($method))) { $this->logger->error('At least one format must be defined for resource @id', array(':id' => $rest_resource_config->id())); continue; } // If the route has a format requirement, then verify that the // resource has it. $format_requirement = $route->getRequirement('_format'); if ($format_requirement && !in_array($format_requirement, $rest_resource_config->getFormats($method))) { continue; } // The configuration seems legit at this point, so we set the // authentication provider and add the route. $route->setOption('_auth', $rest_resource_config->getAuthenticationProviders($method)); $route->setDefault('_rest_resource_config', $rest_resource_config->id()); $collection->add("rest.{$name}", $route); } } return $collection; }