Mercurial > hg > isophonics-drupal-site
comparison core/modules/rest/src/Plugin/ResourceBase.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\Plugin; | |
4 | |
5 use Drupal\Core\Plugin\ContainerFactoryPluginInterface; | |
6 use Drupal\Core\Plugin\PluginBase; | |
7 use Psr\Log\LoggerInterface; | |
8 use Symfony\Component\DependencyInjection\ContainerInterface; | |
9 use Symfony\Component\Routing\Route; | |
10 use Symfony\Component\Routing\RouteCollection; | |
11 | |
12 /** | |
13 * Common base class for resource plugins. | |
14 * | |
15 * Note that this base class' implementation of the permissions() method | |
16 * generates a permission for every method for a resource. If your resource | |
17 * already has its own access control mechanism, you should opt out from this | |
18 * default permissions() method by overriding it. | |
19 * | |
20 * @see \Drupal\rest\Annotation\RestResource | |
21 * @see \Drupal\rest\Plugin\Type\ResourcePluginManager | |
22 * @see \Drupal\rest\Plugin\ResourceInterface | |
23 * @see plugin_api | |
24 * | |
25 * @ingroup third_party | |
26 */ | |
27 abstract class ResourceBase extends PluginBase implements ContainerFactoryPluginInterface, ResourceInterface { | |
28 | |
29 /** | |
30 * The available serialization formats. | |
31 * | |
32 * @var array | |
33 */ | |
34 protected $serializerFormats = []; | |
35 | |
36 /** | |
37 * A logger instance. | |
38 * | |
39 * @var \Psr\Log\LoggerInterface | |
40 */ | |
41 protected $logger; | |
42 | |
43 /** | |
44 * Constructs a Drupal\rest\Plugin\ResourceBase object. | |
45 * | |
46 * @param array $configuration | |
47 * A configuration array containing information about the plugin instance. | |
48 * @param string $plugin_id | |
49 * The plugin_id for the plugin instance. | |
50 * @param mixed $plugin_definition | |
51 * The plugin implementation definition. | |
52 * @param array $serializer_formats | |
53 * The available serialization formats. | |
54 * @param \Psr\Log\LoggerInterface $logger | |
55 * A logger instance. | |
56 */ | |
57 public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger) { | |
58 parent::__construct($configuration, $plugin_id, $plugin_definition); | |
59 $this->serializerFormats = $serializer_formats; | |
60 $this->logger = $logger; | |
61 } | |
62 | |
63 /** | |
64 * {@inheritdoc} | |
65 */ | |
66 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { | |
67 return new static( | |
68 $configuration, | |
69 $plugin_id, | |
70 $plugin_definition, | |
71 $container->getParameter('serializer.formats'), | |
72 $container->get('logger.factory')->get('rest') | |
73 ); | |
74 } | |
75 | |
76 /** | |
77 * Implements ResourceInterface::permissions(). | |
78 * | |
79 * Every plugin operation method gets its own user permission. Example: | |
80 * "restful delete entity:node" with the title "Access DELETE on Node | |
81 * resource". | |
82 */ | |
83 public function permissions() { | |
84 $permissions = []; | |
85 $definition = $this->getPluginDefinition(); | |
86 foreach ($this->availableMethods() as $method) { | |
87 $lowered_method = strtolower($method); | |
88 $permissions["restful $lowered_method $this->pluginId"] = [ | |
89 'title' => $this->t('Access @method on %label resource', ['@method' => $method, '%label' => $definition['label']]), | |
90 ]; | |
91 } | |
92 return $permissions; | |
93 } | |
94 | |
95 /** | |
96 * {@inheritdoc} | |
97 */ | |
98 public function routes() { | |
99 $collection = new RouteCollection(); | |
100 | |
101 $definition = $this->getPluginDefinition(); | |
102 $canonical_path = isset($definition['uri_paths']['canonical']) ? $definition['uri_paths']['canonical'] : '/' . strtr($this->pluginId, ':', '/') . '/{id}'; | |
103 $create_path = isset($definition['uri_paths']['create']) ? $definition['uri_paths']['create'] : '/' . strtr($this->pluginId, ':', '/'); | |
104 // BC: the REST module originally created the POST URL for a resource by | |
105 // reading the 'https://www.drupal.org/link-relations/create' URI path from | |
106 // the plugin annotation. For consistency with entity type definitions, that | |
107 // then changed to reading the 'create' URI path. For any REST Resource | |
108 // plugins that were using the old mechanism, we continue to support that. | |
109 if (!isset($definition['uri_paths']['create']) && isset($definition['uri_paths']['https://www.drupal.org/link-relations/create'])) { | |
110 $create_path = $definition['uri_paths']['https://www.drupal.org/link-relations/create']; | |
111 } | |
112 | |
113 $route_name = strtr($this->pluginId, ':', '.'); | |
114 | |
115 $methods = $this->availableMethods(); | |
116 foreach ($methods as $method) { | |
117 $route = $this->getBaseRoute($canonical_path, $method); | |
118 | |
119 switch ($method) { | |
120 case 'POST': | |
121 $route->setPath($create_path); | |
122 $collection->add("$route_name.$method", $route); | |
123 break; | |
124 | |
125 case 'GET': | |
126 case 'HEAD': | |
127 // Restrict GET and HEAD requests to the media type specified in the | |
128 // HTTP Accept headers. | |
129 foreach ($this->serializerFormats as $format_name) { | |
130 // Expose one route per available format. | |
131 $format_route = clone $route; | |
132 $format_route->addRequirements(['_format' => $format_name]); | |
133 $collection->add("$route_name.$method.$format_name", $format_route); | |
134 } | |
135 break; | |
136 | |
137 default: | |
138 $collection->add("$route_name.$method", $route); | |
139 break; | |
140 } | |
141 } | |
142 | |
143 return $collection; | |
144 } | |
145 | |
146 /** | |
147 * Provides predefined HTTP request methods. | |
148 * | |
149 * Plugins can override this method to provide additional custom request | |
150 * methods. | |
151 * | |
152 * @return array | |
153 * The list of allowed HTTP request method strings. | |
154 */ | |
155 protected function requestMethods() { | |
156 return [ | |
157 'HEAD', | |
158 'GET', | |
159 'POST', | |
160 'PUT', | |
161 'DELETE', | |
162 'TRACE', | |
163 'OPTIONS', | |
164 'CONNECT', | |
165 'PATCH', | |
166 ]; | |
167 } | |
168 | |
169 /** | |
170 * {@inheritdoc} | |
171 */ | |
172 public function availableMethods() { | |
173 $methods = $this->requestMethods(); | |
174 $available = []; | |
175 foreach ($methods as $method) { | |
176 // Only expose methods where the HTTP request method exists on the plugin. | |
177 if (method_exists($this, strtolower($method))) { | |
178 $available[] = $method; | |
179 } | |
180 } | |
181 return $available; | |
182 } | |
183 | |
184 /** | |
185 * Gets the base route for a particular method. | |
186 * | |
187 * @param string $canonical_path | |
188 * The canonical path for the resource. | |
189 * @param string $method | |
190 * The HTTP method to be used for the route. | |
191 * | |
192 * @return \Symfony\Component\Routing\Route | |
193 * The created base route. | |
194 */ | |
195 protected function getBaseRoute($canonical_path, $method) { | |
196 return new Route($canonical_path, [ | |
197 '_controller' => 'Drupal\rest\RequestHandler::handle', | |
198 ], | |
199 $this->getBaseRouteRequirements($method), | |
200 [], | |
201 '', | |
202 [], | |
203 // The HTTP method is a requirement for this route. | |
204 [$method] | |
205 ); | |
206 } | |
207 | |
208 /** | |
209 * Gets the base route requirements for a particular method. | |
210 * | |
211 * @param $method | |
212 * The HTTP method to be used for the route. | |
213 * | |
214 * @return array | |
215 * An array of requirements for parameters. | |
216 */ | |
217 protected function getBaseRouteRequirements($method) { | |
218 $lower_method = strtolower($method); | |
219 // Every route MUST have requirements that result in the access manager | |
220 // having access checks to check. If it does not, the route is made | |
221 // inaccessible. So, we default to granting access to everyone. If a | |
222 // permission exists, then we add that below. The access manager requires | |
223 // that ALL access checks must grant access, so this still results in | |
224 // correct behavior. | |
225 $requirements = [ | |
226 '_access' => 'TRUE', | |
227 ]; | |
228 | |
229 // Only specify route requirements if the default permission exists. For any | |
230 // more advanced route definition, resource plugins extending this base | |
231 // class must override this method. | |
232 $permission = "restful $lower_method $this->pluginId"; | |
233 if (isset($this->permissions()[$permission])) { | |
234 $requirements['_permission'] = $permission; | |
235 } | |
236 | |
237 return $requirements; | |
238 } | |
239 | |
240 } |