Mercurial > hg > isophonics-drupal-site
comparison core/modules/rest/src/Routing/ResourceRoutes.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 1fec387a4317 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\rest\Routing; | |
4 | |
5 use Drupal\Core\Entity\EntityTypeManagerInterface; | |
6 use Drupal\Core\Routing\RouteBuildEvent; | |
7 use Drupal\Core\Routing\RoutingEvents; | |
8 use Drupal\rest\Plugin\Type\ResourcePluginManager; | |
9 use Drupal\rest\RestResourceConfigInterface; | |
10 use Psr\Log\LoggerInterface; | |
11 use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
12 use Symfony\Component\Routing\RouteCollection; | |
13 | |
14 /** | |
15 * Subscriber for REST-style routes. | |
16 */ | |
17 class ResourceRoutes implements EventSubscriberInterface { | |
18 | |
19 /** | |
20 * The plugin manager for REST plugins. | |
21 * | |
22 * @var \Drupal\rest\Plugin\Type\ResourcePluginManager | |
23 */ | |
24 protected $manager; | |
25 | |
26 /** | |
27 * The REST resource config storage. | |
28 * | |
29 * @var \Drupal\Core\Entity\EntityManagerInterface | |
30 */ | |
31 protected $resourceConfigStorage; | |
32 | |
33 /** | |
34 * A logger instance. | |
35 * | |
36 * @var \Psr\Log\LoggerInterface | |
37 */ | |
38 protected $logger; | |
39 | |
40 /** | |
41 * Constructs a RouteSubscriber object. | |
42 * | |
43 * @param \Drupal\rest\Plugin\Type\ResourcePluginManager $manager | |
44 * The resource plugin manager. | |
45 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager | |
46 * The entity type manager | |
47 * @param \Psr\Log\LoggerInterface $logger | |
48 * A logger instance. | |
49 */ | |
50 public function __construct(ResourcePluginManager $manager, EntityTypeManagerInterface $entity_type_manager, LoggerInterface $logger) { | |
51 $this->manager = $manager; | |
52 $this->resourceConfigStorage = $entity_type_manager->getStorage('rest_resource_config'); | |
53 $this->logger = $logger; | |
54 } | |
55 | |
56 /** | |
57 * Alters existing routes for a specific collection. | |
58 * | |
59 * @param \Drupal\Core\Routing\RouteBuildEvent $event | |
60 * The route build event. | |
61 * @return array | |
62 */ | |
63 public function onDynamicRouteEvent(RouteBuildEvent $event) { | |
64 // Iterate over all enabled REST resource config entities. | |
65 /** @var \Drupal\rest\RestResourceConfigInterface[] $resource_configs */ | |
66 $resource_configs = $this->resourceConfigStorage->loadMultiple(); | |
67 foreach ($resource_configs as $resource_config) { | |
68 if ($resource_config->status()) { | |
69 $resource_routes = $this->getRoutesForResourceConfig($resource_config); | |
70 $event->getRouteCollection()->addCollection($resource_routes); | |
71 } | |
72 } | |
73 } | |
74 | |
75 /** | |
76 * Provides all routes for a given REST resource config. | |
77 * | |
78 * This method determines where a resource is reachable, what path | |
79 * replacements are used, the required HTTP method for the operation etc. | |
80 * | |
81 * @param \Drupal\rest\RestResourceConfigInterface $rest_resource_config | |
82 * The rest resource config. | |
83 * | |
84 * @return \Symfony\Component\Routing\RouteCollection | |
85 * The route collection. | |
86 */ | |
87 protected function getRoutesForResourceConfig(RestResourceConfigInterface $rest_resource_config) { | |
88 $plugin = $rest_resource_config->getResourcePlugin(); | |
89 $collection = new RouteCollection(); | |
90 | |
91 foreach ($plugin->routes() as $name => $route) { | |
92 /** @var \Symfony\Component\Routing\Route $route */ | |
93 // @todo: Are multiple methods possible here? | |
94 $methods = $route->getMethods(); | |
95 // Only expose routes where the method is enabled in the configuration. | |
96 if ($methods && ($method = $methods[0]) && $supported_formats = $rest_resource_config->getFormats($method)) { | |
97 $route->setRequirement('_csrf_request_header_token', 'TRUE'); | |
98 | |
99 // Check that authentication providers are defined. | |
100 if (empty($rest_resource_config->getAuthenticationProviders($method))) { | |
101 $this->logger->error('At least one authentication provider must be defined for resource @id', [':id' => $rest_resource_config->id()]); | |
102 continue; | |
103 } | |
104 | |
105 // Check that formats are defined. | |
106 if (empty($rest_resource_config->getFormats($method))) { | |
107 $this->logger->error('At least one format must be defined for resource @id', [':id' => $rest_resource_config->id()]); | |
108 continue; | |
109 } | |
110 | |
111 // If the route has a format requirement, then verify that the | |
112 // resource has it. | |
113 $format_requirement = $route->getRequirement('_format'); | |
114 if ($format_requirement && !in_array($format_requirement, $rest_resource_config->getFormats($method))) { | |
115 continue; | |
116 } | |
117 | |
118 // The configuration has been validated, so we update the route to: | |
119 // - set the allowed request body content types/formats for methods that | |
120 // allow request bodies to be sent | |
121 // - set the allowed authentication providers | |
122 if (in_array($method, ['POST', 'PATCH', 'PUT'], TRUE)) { | |
123 // Restrict the incoming HTTP Content-type header to the allowed | |
124 // formats. | |
125 $route->addRequirements(['_content_type_format' => implode('|', $rest_resource_config->getFormats($method))]); | |
126 } | |
127 $route->setOption('_auth', $rest_resource_config->getAuthenticationProviders($method)); | |
128 $route->setDefault('_rest_resource_config', $rest_resource_config->id()); | |
129 $collection->add("rest.$name", $route); | |
130 } | |
131 | |
132 } | |
133 return $collection; | |
134 } | |
135 | |
136 /** | |
137 * {@inheritdoc} | |
138 */ | |
139 public static function getSubscribedEvents() { | |
140 $events[RoutingEvents::DYNAMIC] = 'onDynamicRouteEvent'; | |
141 return $events; | |
142 } | |
143 | |
144 } |