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 FrankDeJonge\SymfonyI18nRouting\Routing\Loader; |
||
4 | |||
5 | use Generator; |
||
6 | use InvalidArgumentException; |
||
7 | use Symfony\Component\Config\Loader\FileLoader; |
||
8 | use Symfony\Component\Config\Resource\FileResource; |
||
9 | use Symfony\Component\Routing\Route; |
||
10 | use Symfony\Component\Routing\RouteCollection; |
||
11 | use Symfony\Component\Yaml\Exception\ParseException; |
||
12 | use Symfony\Component\Yaml\Parser as YamlParser; |
||
13 | use function is_array; |
||
14 | |||
15 | /** |
||
16 | * YamlFileLoader loads Yaml routing files. |
||
17 | * |
||
18 | * @author Fabien Potencier <[email protected]> |
||
19 | * @author Tobias Schultze <http://tobion.de> |
||
20 | */ |
||
21 | class YamlFileLoader extends FileLoader |
||
22 | { |
||
23 | private $yamlParser; |
||
24 | |||
25 | private static $availableKeys = [ |
||
26 | 'locales', 'resource', 'type', 'prefix', 'path', |
||
27 | 'host', 'schemes', 'methods', 'defaults', 'requirements', |
||
28 | 'options', 'condition', 'controller', |
||
29 | ]; |
||
30 | |||
31 | /** |
||
32 | * Loads a Yaml file. |
||
33 | * |
||
34 | * @param string $file A Yaml file path |
||
35 | * @param string|null $type The resource type |
||
36 | * |
||
37 | * @return RouteCollection A RouteCollection instance |
||
38 | * |
||
39 | * @throws InvalidArgumentException When a route can't be parsed because YAML is invalid |
||
40 | */ |
||
41 | 36 | public function load($file, $type = null) |
|
42 | { |
||
43 | 36 | $path = $this->locator->locate($file, null, true); |
|
44 | |||
45 | 36 | if ( ! stream_is_local($path)) { |
|
46 | 2 | throw new InvalidArgumentException(sprintf('This is not a local file "%s".', $path)); |
|
47 | } |
||
48 | |||
49 | 34 | if ( ! file_exists($path)) { |
|
50 | 2 | throw new InvalidArgumentException(sprintf('File "%s" not found.', $path)); |
|
51 | } |
||
52 | |||
53 | 32 | if (null === $this->yamlParser) { |
|
54 | 32 | $this->yamlParser = new YamlParser(); |
|
55 | } |
||
56 | |||
57 | try { |
||
58 | 32 | $parsedConfig = $this->yamlParser->parseFile($path); |
|
59 | 2 | } catch (ParseException $e) { |
|
60 | 2 | throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); |
|
61 | } |
||
62 | |||
63 | 30 | $collection = new RouteCollection(); |
|
64 | 30 | $collection->addResource(new FileResource($path)); |
|
0 ignored issues
–
show
|
|||
65 | |||
66 | // empty file |
||
67 | 30 | if (null === $parsedConfig) { |
|
68 | 2 | return $collection; |
|
69 | } |
||
70 | |||
71 | // not an array |
||
72 | 28 | if ( ! is_array($parsedConfig)) { |
|
73 | 2 | throw new InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path)); |
|
74 | } |
||
75 | |||
76 | 26 | foreach ($parsedConfig as $name => $config) { |
|
77 | 26 | $this->validate($config, $name, $path); |
|
0 ignored issues
–
show
It seems like
$path defined by $this->locator->locate($file, null, true) on line 43 can also be of type array ; however, FrankDeJonge\SymfonyI18n...lFileLoader::validate() does only seem to accept string , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. ![]() |
|||
78 | |||
79 | 14 | if (isset($config['resource'])) { |
|
80 | 12 | $this->parseImport($collection, $config, $path, $file); |
|
81 | } else { |
||
82 | 14 | $this->parseRoute($collection, $name, $config, $path); |
|
0 ignored issues
–
show
It seems like
$path defined by $this->locator->locate($file, null, true) on line 43 can also be of type array ; however, FrankDeJonge\SymfonyI18n...ileLoader::parseRoute() does only seem to accept string , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. ![]() |
|||
83 | } |
||
84 | } |
||
85 | |||
86 | 14 | return $collection; |
|
87 | } |
||
88 | |||
89 | 14 | public function supports($resource, $type = null) |
|
90 | { |
||
91 | 14 | return $type === 'i18n_routes' |
|
92 | 14 | && is_string($resource) |
|
93 | 14 | && in_array(pathinfo($resource, PATHINFO_EXTENSION), ['yml', 'yaml'], true); |
|
94 | } |
||
95 | |||
96 | /** |
||
97 | * Parses a route and adds it to the RouteCollection. |
||
98 | * |
||
99 | * @param RouteCollection $collection A RouteCollection instance |
||
100 | * @param string $name Route name |
||
101 | * @param array $config Route definition |
||
102 | * @param string $path Full path of the YAML file being processed |
||
103 | */ |
||
104 | 14 | protected function parseRoute(RouteCollection $collection, $name, array $config, $path) |
|
0 ignored issues
–
show
|
|||
105 | { |
||
106 | 14 | $defaults = isset($config['defaults']) ? $config['defaults'] : []; |
|
107 | 14 | $requirements = isset($config['requirements']) ? $config['requirements'] : []; |
|
108 | 14 | $options = isset($config['options']) ? $config['options'] : []; |
|
109 | 14 | $host = isset($config['host']) ? $config['host'] : ''; |
|
110 | 14 | $schemes = isset($config['schemes']) ? $config['schemes'] : []; |
|
111 | 14 | $methods = isset($config['methods']) ? $config['methods'] : []; |
|
112 | 14 | $condition = isset($config['condition']) ? $config['condition'] : null; |
|
113 | |||
114 | 14 | if (isset($config['controller'])) { |
|
115 | 14 | $defaults['_controller'] = $config['controller']; |
|
116 | } |
||
117 | |||
118 | 14 | if (isset($config['locales'])) { |
|
119 | 12 | $routes = $this->generateLocaleRoutes( |
|
120 | 12 | $name, |
|
121 | 12 | $config['locales'], |
|
122 | 12 | new Route('', $defaults, $requirements, $options, $host, $schemes, $methods, $condition) |
|
123 | ); |
||
124 | 12 | foreach ($routes as $routeName => $route) { |
|
125 | 12 | $collection->add($routeName, $route); |
|
126 | } |
||
127 | } else { |
||
128 | 12 | $route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition); |
|
129 | 12 | $collection->add($name, $route); |
|
130 | } |
||
131 | 14 | } |
|
132 | |||
133 | 12 | protected function parseImport(RouteCollection $collection, array $config, $path, $file) |
|
134 | { |
||
135 | 12 | $type = isset($config['type']) ? $config['type'] : 'i18n_routes'; |
|
136 | 12 | $prefix = isset($config['prefix']) ? $config['prefix'] : ''; |
|
137 | 12 | $defaults = isset($config['defaults']) ? $config['defaults'] : []; |
|
138 | 12 | $requirements = isset($config['requirements']) ? $config['requirements'] : []; |
|
139 | 12 | $options = isset($config['options']) ? $config['options'] : []; |
|
140 | 12 | $host = isset($config['host']) ? $config['host'] : null; |
|
141 | 12 | $condition = isset($config['condition']) ? $config['condition'] : null; |
|
142 | 12 | $schemes = isset($config['schemes']) ? $config['schemes'] : null; |
|
143 | 12 | $methods = isset($config['methods']) ? $config['methods'] : null; |
|
144 | |||
145 | 12 | if (isset($config['controller'])) { |
|
146 | 2 | $defaults['_controller'] = $config['controller']; |
|
147 | } |
||
148 | |||
149 | 12 | $this->setCurrentDir(dirname($path)); |
|
150 | |||
151 | /* @var $subCollection RouteCollection */ |
||
152 | 12 | $subCollection = $this->import($config['resource'], $type, false, $file); |
|
153 | 12 | $prefixIsLocalized = is_array($prefix); |
|
154 | |||
155 | |||
156 | 12 | foreach ($subCollection->all() as $routeName => $route) { |
|
157 | 12 | $routeLocale = $route->getDefault('_locale'); |
|
158 | 12 | if ($prefixIsLocalized && null === $routeLocale) { |
|
159 | 2 | throw new InvalidArgumentException("Route {$routeName} doesn't have a locale."); |
|
160 | } |
||
161 | 10 | if ($prefixIsLocalized && false === isset($prefix[$routeLocale])) { |
|
162 | 2 | throw new InvalidArgumentException("Route {$routeName} with locale {$routeLocale} does not have a prefix defined in {$file}"); |
|
163 | } |
||
164 | |||
165 | 10 | $localePrefix = is_array($prefix) ? $prefix[$routeLocale] : $prefix; |
|
166 | 10 | $route->setPath($localePrefix . $route->getPath()); |
|
167 | } |
||
168 | |||
169 | 8 | if (null !== $host) { |
|
170 | 2 | $subCollection->setHost($host); |
|
171 | } |
||
172 | 8 | if (null !== $condition) { |
|
173 | 2 | $subCollection->setCondition($condition); |
|
174 | } |
||
175 | 8 | if (null !== $schemes) { |
|
176 | 2 | $subCollection->setSchemes($schemes); |
|
177 | } |
||
178 | 8 | if (null !== $methods) { |
|
179 | 2 | $subCollection->setMethods($methods); |
|
180 | } |
||
181 | 8 | $subCollection->addDefaults($defaults); |
|
182 | 8 | $subCollection->addRequirements($requirements); |
|
183 | 8 | $subCollection->addOptions($options); |
|
184 | |||
185 | 8 | $collection->addCollection($subCollection); |
|
186 | 8 | } |
|
187 | |||
188 | /** |
||
189 | * Validates the route configuration. |
||
190 | * |
||
191 | * @param array $config A resource config |
||
192 | * @param string $name The config key |
||
193 | * @param string $path The loaded file path |
||
194 | * |
||
195 | * @throws InvalidArgumentException If one of the provided config keys is not supported, |
||
196 | * something is missing or the combination is nonsense |
||
197 | */ |
||
198 | 26 | protected function validate($config, $name, $path) |
|
199 | { |
||
200 | 26 | if ( ! is_array($config)) { |
|
201 | 2 | throw new InvalidArgumentException(sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path)); |
|
202 | } |
||
203 | 24 | if ($extraKeys = array_diff(array_keys($config), self::$availableKeys)) { |
|
204 | 2 | throw new InvalidArgumentException(sprintf( |
|
205 | 2 | 'The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', |
|
206 | 2 | $path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys) |
|
207 | )); |
||
208 | } |
||
209 | 22 | if (isset($config['resource']) && (isset($config['path']) || isset($config['locales']))) { |
|
210 | 2 | throw new InvalidArgumentException(sprintf( |
|
211 | 2 | 'The routing file "%s" must not specify both the "resource" key and the "path" or "locales" key for "%s". Choose between an import and a route definition.', |
|
212 | 2 | $path, $name |
|
213 | )); |
||
214 | } |
||
215 | 20 | View Code Duplication | if ( ! isset($config['resource']) && isset($config['type'])) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
216 | 2 | throw new InvalidArgumentException(sprintf( |
|
217 | 2 | 'The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', |
|
218 | 2 | $name, $path |
|
219 | )); |
||
220 | } |
||
221 | 18 | View Code Duplication | if ( ! isset($config['resource']) && ! isset($config['path']) && ! isset($config['locales'])) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
222 | 2 | throw new InvalidArgumentException(sprintf( |
|
223 | 2 | 'You must define a "path" or "locales" for the route "%s" in file "%s".', |
|
224 | 2 | $name, $path |
|
225 | )); |
||
226 | } |
||
227 | 16 | if (isset($config['controller']) && isset($config['defaults']['_controller'])) { |
|
228 | 2 | throw new InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name)); |
|
229 | } |
||
230 | 14 | } |
|
231 | |||
232 | 12 | private function generateLocaleRoutes(string $name, array $locales, Route $route): Generator |
|
233 | { |
||
234 | 12 | foreach ($locales as $locale => $path) { |
|
235 | 12 | $localeRoute = clone $route; |
|
236 | 12 | $localeRoute->setPath($path); |
|
237 | 12 | $localeRoute->setDefault('_locale', $locale); |
|
238 | 12 | yield "{$name}.{$locale}" => $localeRoute; |
|
239 | } |
||
240 | } |
||
241 | } |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.