This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Knp\RadBundle\Routing\Loader; |
||
4 | |||
5 | use Symfony\Component\Routing\RouteCollection; |
||
6 | use Symfony\Component\Routing\Route; |
||
7 | use Symfony\Component\Routing\Loader\YamlFileLoader; |
||
8 | use Symfony\Component\Config\Resource\FileResource; |
||
9 | use Symfony\Component\Config\FileLocatorInterface; |
||
10 | |||
11 | class ConventionalLoader extends YamlFileLoader |
||
12 | { |
||
13 | private static $supportedControllerKeys = array( |
||
14 | 'prefix', 'defaults', 'requirements', 'options', 'collections', 'resources' |
||
15 | ); |
||
16 | private static $supportedActionKeys = array( |
||
17 | 'pattern', 'defaults', 'requirements', 'options', 'methods' |
||
18 | ); |
||
19 | private $yaml; |
||
20 | |||
21 | public function __construct(FileLocatorInterface $locator, YamlParser $yaml = null) |
||
22 | { |
||
23 | parent::__construct($locator); |
||
24 | |||
25 | $this->yaml = $yaml ?: new YamlParser; |
||
26 | } |
||
27 | |||
28 | public function supports($resource, $type = null) |
||
29 | { |
||
30 | return 'rad_convention' === $type; |
||
31 | } |
||
32 | |||
33 | public function load($file, $type = null) |
||
34 | { |
||
35 | $path = $this->locator->locate($file); |
||
36 | $config = $this->yaml->parse($path); |
||
37 | |||
38 | $collection = new RouteCollection(); |
||
39 | $collection->addResource(new FileResource($file)); |
||
40 | |||
41 | if (null === $config) { |
||
42 | return $collection; |
||
43 | } |
||
44 | |||
45 | if (!is_array($config)) { |
||
46 | throw new \InvalidArgumentException(sprintf( |
||
47 | 'The file "%s" must contain a YAML array.', $path |
||
48 | )); |
||
49 | } |
||
50 | |||
51 | foreach ($config as $shortname => $mapping) { |
||
52 | $parts = explode(':', $shortname); |
||
53 | |||
54 | if (3 == count($parts)) { |
||
55 | list($bundle, $class, $action) = $parts; |
||
56 | |||
57 | $routeName = $this->getRouteName($bundle, $class, $action); |
||
58 | $route = $this->getCustomCollectionRoute($bundle, $class, $action); |
||
59 | |||
60 | $this->overrideRouteParams($shortname, $route, $mapping); |
||
61 | $collection->add($routeName, $route); |
||
62 | |||
63 | continue; |
||
64 | } |
||
65 | |||
66 | if (1 == count($parts)) { |
||
67 | $this->parseClassical($collection, $shortname, $mapping, $path, $file); |
||
68 | |||
69 | continue; |
||
70 | } |
||
71 | |||
72 | if (is_array($mapping)) { |
||
73 | foreach ($mapping as $key => $val) { |
||
74 | if (in_array($key, self::$supportedControllerKeys)) { |
||
75 | continue; |
||
76 | } |
||
77 | |||
78 | if ('pattern' === $key) { |
||
79 | throw new \InvalidArgumentException( |
||
80 | 'The `pattern` is only supported for actions, if you want to prefix '. |
||
81 | 'all the routes of the controller, use `prefix` instead.' |
||
82 | ); |
||
83 | } |
||
84 | |||
85 | throw new \InvalidArgumentException(sprintf( |
||
86 | '`%s` parameter is not supported by `%s` controller route. Use one of [%s].', |
||
87 | $key, $shortname, implode(', ', self::$supportedControllerKeys) |
||
88 | )); |
||
89 | } |
||
90 | } |
||
91 | |||
92 | list($bundle, $class) = $parts; |
||
93 | |||
94 | $prefix = $this->getPatternPrefix($class, $mapping); |
||
95 | $collectionDefaults = $this->getDefaultsFromMapping($mapping, 'collections'); |
||
96 | $collectionRequirements = $this->getRequirementsFromMapping($mapping, 'collections'); |
||
97 | $collectionOptions = $this->getOptionsFromMapping($mapping, 'collections'); |
||
98 | $resourceDefaults = $this->getDefaultsFromMapping($mapping, 'resources'); |
||
99 | $resourceRequirements = $this->getRequirementsFromMapping($mapping, 'resources'); |
||
100 | $resourceOptions = $this->getOptionsFromMapping($mapping, 'resources'); |
||
101 | |||
102 | $collectionRoutes = $this->getCollectionRoutesFromMapping($shortname, $mapping, $bundle, $class); |
||
103 | $resourceRoutes = $this->getResourceRoutesFromMapping($shortname, $mapping, $bundle, $class); |
||
104 | |||
105 | $controllerCollection = new RouteCollection(); |
||
106 | foreach ($collectionRoutes as $name => $route) { |
||
107 | $route->setDefaults(array_merge($collectionDefaults, $route->getDefaults())); |
||
108 | $route->setRequirements(array_merge( |
||
109 | $collectionRequirements, $route->getRequirements() |
||
110 | )); |
||
111 | $route->setOptions(array_merge( |
||
112 | $collectionOptions, $route->getOptions() |
||
113 | )); |
||
114 | $controllerCollection->add($name, $route); |
||
115 | } |
||
116 | foreach ($resourceRoutes as $name => $route) { |
||
117 | $route->setDefaults(array_merge($resourceDefaults, $route->getDefaults())); |
||
118 | $route->setRequirements(array_merge( |
||
119 | $resourceRequirements, $route->getRequirements() |
||
120 | )); |
||
121 | $route->setOptions(array_merge( |
||
122 | $resourceOptions, $route->getOptions() |
||
123 | )); |
||
124 | $controllerCollection->add($name, $route); |
||
125 | } |
||
126 | $controllerCollection->addPrefix($prefix); |
||
127 | $collection->addCollection($controllerCollection); |
||
128 | } |
||
129 | |||
130 | return $collection; |
||
131 | } |
||
132 | |||
133 | protected function parseClassical(RouteCollection $collection, $shortname, |
||
0 ignored issues
–
show
Coding Style
introduced
by
![]() |
|||
134 | array $mapping, $path, $file) |
||
0 ignored issues
–
show
|
|||
135 | { |
||
0 ignored issues
–
show
|
|||
136 | // Symfony 2.2+ |
||
137 | if (method_exists($this, 'validate')) { |
||
138 | if (isset($mapping['pattern'])) { |
||
139 | if (isset($mapping['path'])) { |
||
140 | throw new \InvalidArgumentException(sprintf( |
||
141 | 'The file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', |
||
142 | $path |
||
143 | )); |
||
144 | } |
||
145 | |||
146 | $mapping['path'] = $mapping['pattern']; |
||
147 | unset($mapping['pattern']); |
||
148 | } |
||
149 | |||
150 | $this->validate($mapping, $shortname, $path); |
||
151 | // Symfony 2.0, 2.1 |
||
152 | } else { |
||
153 | foreach ($mapping as $key => $value) { |
||
154 | if (!in_array($key, $expected = array( |
||
155 | 'type', 'resource', 'prefix', 'pattern', 'options', |
||
156 | 'defaults', 'requirements' |
||
157 | ))) { |
||
158 | throw new \InvalidArgumentException(sprintf( |
||
159 | 'Yaml routing loader does not support given key: "%s". Expected one of the (%s).', |
||
160 | $key, implode(', ', $expected) |
||
161 | )); |
||
162 | } |
||
163 | } |
||
164 | } |
||
165 | |||
166 | if (isset($mapping['resource'])) { |
||
167 | // Symfony 2.2+ |
||
168 | if (method_exists($this, 'parseImport')) { |
||
169 | $this->parseImport($collection, $mapping, $path, $file); |
||
170 | // Symfony 2.1 |
||
171 | } else { |
||
172 | $getOr = function ($key, $def) use ($mapping) { |
||
173 | return isset($mapping[$key]) ? $mapping[$key] : $def; |
||
174 | }; |
||
175 | |||
176 | $type = $getOr('type', null); |
||
177 | $prefix = $getOr('prefix', null); |
||
178 | $defaults = $getOr('defaults', array()); |
||
179 | $requirements = $getOr('requirements', array()); |
||
180 | $options = $getOr('options', array()); |
||
181 | |||
182 | $this->setCurrentDir(dirname($path)); |
||
183 | $resourceCollection = $this->import($mapping['resource'], $type, false, $file); |
||
184 | $resourceCollection->addPrefix($prefix, $defaults, $requirements); |
||
185 | $resourceCollection->addOptions($options); |
||
186 | $collection->addCollection($resourceCollection); |
||
187 | } |
||
188 | } else { |
||
189 | $this->parseRoute($collection, $shortname, $mapping, $path); |
||
190 | } |
||
191 | } |
||
192 | |||
193 | private function getDefaultsFromMapping($mapping, $routeType = 'collections') |
||
194 | { |
||
195 | $defaults = array(); |
||
196 | |||
197 | if (!is_array($mapping)) { |
||
198 | return $defaults; |
||
199 | } |
||
200 | |||
201 | if (isset($mapping['defaults'])) { |
||
202 | $defaults = $mapping['defaults']; |
||
203 | } |
||
204 | |||
205 | if (isset($mapping[$routeType]) && is_array($mapping[$routeType])) { |
||
206 | if (isset($mapping[$routeType]['defaults'])) { |
||
207 | $defaults = array_merge($defaults, $mapping[$routeType]['defaults']); |
||
208 | } |
||
209 | } |
||
210 | |||
211 | return $defaults; |
||
212 | } |
||
213 | |||
214 | private function getRequirementsFromMapping($mapping, $routeType = 'collections') |
||
215 | { |
||
216 | $requirements = array(); |
||
217 | |||
218 | if (!is_array($mapping)) { |
||
219 | return $requirements; |
||
220 | } |
||
221 | |||
222 | if (isset($mapping['requirements'])) { |
||
223 | $requirements = $mapping['requirements']; |
||
224 | } |
||
225 | |||
226 | if (isset($mapping[$routeType]) && is_array($mapping[$routeType])) { |
||
227 | if (isset($mapping[$routeType]['requirements'])) { |
||
228 | $requirements = array_merge($requirements, $mapping[$routeType]['requirements']); |
||
229 | } |
||
230 | } |
||
231 | |||
232 | return $requirements; |
||
233 | } |
||
234 | |||
235 | private function getOptionsFromMapping($mapping, $routeType = 'collections') |
||
236 | { |
||
237 | $options = array(); |
||
238 | |||
239 | if (!is_array($mapping)) { |
||
240 | return $options; |
||
241 | } |
||
242 | |||
243 | if (isset($mapping['options'])) { |
||
244 | $options = $mapping['options']; |
||
245 | } |
||
246 | |||
247 | if (isset($mapping[$routeType]) && is_array($mapping[$routeType])) { |
||
248 | if (isset($mapping[$routeType]['options'])) { |
||
249 | $options = array_merge($options, $mapping[$routeType]['options']); |
||
250 | } |
||
251 | } |
||
252 | |||
253 | return $options; |
||
254 | } |
||
255 | |||
256 | private function getCollectionRoutesFromMapping($shortname, $mapping, $bundle, $class) |
||
257 | { |
||
258 | $defaults = $this->getDefaultCollectionRoutes($bundle, $class); |
||
259 | if (!is_array($mapping) || !isset($mapping['collections'])) { |
||
260 | return $defaults; |
||
261 | } |
||
262 | |||
263 | $collections = $mapping['collections']; |
||
264 | unset($collections['defaults']); |
||
265 | unset($collections['requirements']); |
||
266 | unset($collections['options']); |
||
267 | |||
268 | if (0 == count($collections)) { |
||
269 | return $defaults; |
||
270 | } |
||
271 | |||
272 | if (false === $collections) { |
||
273 | return array(); |
||
274 | } |
||
275 | |||
276 | $routes = array(); |
||
277 | foreach ($collections as $action => $params) { |
||
278 | if (is_integer($action)) { |
||
279 | $action = $params; |
||
280 | $params = null; |
||
281 | } |
||
282 | |||
283 | $routeName = $this->getRouteName($bundle, $class, $action); |
||
284 | if (isset($defaults[$routeName])) { |
||
285 | $route = $defaults[$routeName]; |
||
286 | } else { |
||
287 | $route = $this->getCustomCollectionRoute($bundle, $class, $action); |
||
288 | } |
||
289 | |||
290 | $this->overrideRouteParams($shortname, $route, $params); |
||
291 | |||
292 | $routes[$routeName] = $route; |
||
293 | } |
||
294 | |||
295 | return $routes; |
||
296 | } |
||
297 | |||
298 | private function getResourceRoutesFromMapping($shortname, $mapping, $bundle, $class) |
||
299 | { |
||
300 | $defaults = $this->getDefaultResourceRoutes($bundle, $class); |
||
301 | if (!is_array($mapping) || !isset($mapping['resources'])) { |
||
302 | return $defaults; |
||
303 | } |
||
304 | |||
305 | $resources = $mapping['resources']; |
||
306 | unset($resources['defaults']); |
||
307 | unset($resources['requirements']); |
||
308 | unset($resources['options']); |
||
309 | |||
310 | if (0 == count($resources)) { |
||
311 | return $defaults; |
||
312 | } |
||
313 | |||
314 | if (false === $resources) { |
||
315 | return array(); |
||
316 | } |
||
317 | |||
318 | $routes = array(); |
||
319 | foreach ($resources as $action => $params) { |
||
320 | if (is_integer($action)) { |
||
321 | $action = $params; |
||
322 | $params = null; |
||
323 | } |
||
324 | |||
325 | $routeName = $this->getRouteName($bundle, $class, $action); |
||
326 | if (isset($defaults[$routeName])) { |
||
327 | $route = $defaults[$routeName]; |
||
328 | } else { |
||
329 | $route = $this->getCustomResourceRoute($bundle, $class, $action); |
||
330 | } |
||
331 | |||
332 | $this->overrideRouteParams($shortname, $route, $params); |
||
333 | |||
334 | $routes[$routeName] = $route; |
||
335 | } |
||
336 | |||
337 | return $routes; |
||
338 | } |
||
339 | |||
340 | private function overrideRouteParams($shortname, Route $route, $params) |
||
341 | { |
||
342 | if (is_array($params)) { |
||
343 | foreach ($params as $key => $val) { |
||
344 | if (in_array($key, self::$supportedActionKeys)) { |
||
345 | continue; |
||
346 | } |
||
347 | |||
348 | throw new \InvalidArgumentException(sprintf( |
||
349 | '`%s` parameter is not supported by `%s` action route. Use one of [%s].', |
||
350 | $key, $shortname, implode(', ', self::$supportedActionKeys) |
||
351 | )); |
||
352 | } |
||
353 | } |
||
354 | |||
355 | if (is_string($params)) { |
||
356 | $route->setPattern($params); |
||
0 ignored issues
–
show
The method
Symfony\Component\Routing\Route::setPattern() has been deprecated with message: since version 2.2, to be removed in 3.0. Use setPath instead.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
357 | } |
||
358 | if (is_array($params)) { |
||
359 | if (isset($params['pattern'])) { |
||
360 | $route->setPattern($params['pattern']); |
||
0 ignored issues
–
show
The method
Symfony\Component\Routing\Route::setPattern() has been deprecated with message: since version 2.2, to be removed in 3.0. Use setPath instead.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
361 | } |
||
362 | if (isset($params['defaults'])) { |
||
363 | $route->setDefaults(array_merge( |
||
364 | $route->getDefaults(), $params['defaults'] |
||
365 | )); |
||
366 | } |
||
367 | if (isset($params['requirements'])) { |
||
368 | $route->setRequirements($params['requirements']); |
||
369 | } |
||
370 | if (isset($params['options'])) { |
||
371 | $route->setOptions($params['options']); |
||
372 | } |
||
373 | if (isset($params['methods'])) { |
||
374 | $route->setMethods($params['methods']); |
||
375 | } |
||
376 | } |
||
377 | } |
||
378 | |||
379 | private function getDefaultCollectionRoutes($bundle, $class) |
||
380 | { |
||
381 | return array( |
||
382 | $this->getRouteName($bundle, $class, 'index') => new Route( |
||
383 | '/', |
||
384 | array('_controller' => sprintf('%s:%s:index', $bundle, $class)), |
||
385 | array('_method' => 'GET') |
||
386 | ), |
||
387 | $this->getRouteName($bundle, $class, 'new') => new Route( |
||
388 | '/new', |
||
389 | array('_controller' => sprintf('%s:%s:new', $bundle, $class)), |
||
390 | array('_method' => 'GET') |
||
391 | ), |
||
392 | $this->getRouteName($bundle, $class, 'create') => new Route( |
||
393 | '/', |
||
394 | array('_controller' => sprintf('%s:%s:new', $bundle, $class)), |
||
395 | array('_method' => 'POST') |
||
396 | ), |
||
397 | ); |
||
398 | } |
||
399 | |||
400 | private function getCustomCollectionRoute($bundle, $class, $action) |
||
401 | { |
||
402 | return new Route( |
||
403 | '/'.$action, |
||
404 | array('_controller' => sprintf('%s:%s:%s', $bundle, $class, $action)), |
||
405 | array('_method' => 'GET') |
||
406 | ); |
||
407 | } |
||
408 | |||
409 | private function getDefaultResourceRoutes($bundle, $class) |
||
410 | { |
||
411 | return array( |
||
412 | $this->getRouteName($bundle, $class, 'show') => new Route( |
||
413 | '/{id}', |
||
414 | array('_controller' => sprintf('%s:%s:show', $bundle, $class)), |
||
415 | array('_method' => 'GET') |
||
416 | ), |
||
417 | $this->getRouteName($bundle, $class, 'edit') => new Route( |
||
418 | '/{id}/edit', |
||
419 | array('_controller' => sprintf('%s:%s:edit', $bundle, $class)), |
||
420 | array('_method' => 'GET') |
||
421 | ), |
||
422 | $this->getRouteName($bundle, $class, 'update') => new Route( |
||
423 | '/{id}', |
||
424 | array('_controller' => sprintf('%s:%s:edit', $bundle, $class)), |
||
425 | array('_method' => 'PUT') |
||
426 | ), |
||
427 | $this->getRouteName($bundle, $class, 'delete') => new Route( |
||
428 | '/{id}', |
||
429 | array('_controller' => sprintf('%s:%s:delete', $bundle, $class)), |
||
430 | array('_method' => 'DELETE') |
||
431 | ), |
||
432 | ); |
||
433 | } |
||
434 | |||
435 | private function getCustomResourceRoute($bundle, $class, $action) |
||
436 | { |
||
437 | return new Route( |
||
438 | '/{id}/'.$action, |
||
439 | array('_controller' => sprintf('%s:%s:%s', $bundle, $class, $action)), |
||
440 | array('_method' => 'PUT') |
||
441 | ); |
||
442 | } |
||
443 | |||
444 | private function getPatternPrefix($class, $mapping) |
||
445 | { |
||
446 | if (is_string($mapping)) { |
||
447 | return $mapping; |
||
448 | } elseif (is_array($mapping) && isset($mapping['prefix'])) { |
||
449 | return $mapping['prefix']; |
||
450 | } |
||
451 | |||
452 | return '/'.strtolower(str_replace('\\', '/', $class)); |
||
453 | } |
||
454 | |||
455 | private function getRouteName($bundle, $class, $action) |
||
456 | { |
||
457 | $group = implode('_', array_map('lcfirst', explode('\\', $class))); |
||
458 | |||
459 | return sprintf('%s_%s_%s', lcfirst($bundle), $group, lcfirst($action)); |
||
460 | } |
||
461 | } |
||
462 |