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 | /** |
||
4 | * |
||
5 | * This file is part of the Apix Project. |
||
6 | * |
||
7 | * (c) Franck Cassedanne <franck at ouarz.net> |
||
8 | * |
||
9 | * @license http://opensource.org/licenses/BSD-3-Clause New BSD License |
||
10 | * |
||
11 | */ |
||
12 | |||
13 | namespace Apix; |
||
14 | |||
15 | /** |
||
16 | * Apix Router class |
||
17 | * |
||
18 | * @example $rules = array('/resource/:keyname/:id' => array('controller'=>'someController', 'action'=>'someAction')); |
||
19 | * $router = Router($rules); |
||
20 | * $router->init( $_SERVER['REQUEST_URI'] ); // execute router |
||
21 | */ |
||
22 | class Router |
||
23 | { |
||
24 | /** |
||
25 | * Holds the controller string. |
||
26 | * @var string |
||
27 | */ |
||
28 | protected $controller = null; |
||
29 | |||
30 | /** |
||
31 | * Holds the current method. |
||
32 | * @var string |
||
33 | */ |
||
34 | protected $method = null; |
||
35 | |||
36 | /** |
||
37 | * Holds the current action. |
||
38 | * @var string |
||
39 | */ |
||
40 | protected $action = null; |
||
41 | |||
42 | /** |
||
43 | * Holds the current action. |
||
44 | * @var string |
||
45 | */ |
||
46 | protected $name = null; |
||
47 | |||
48 | /** |
||
49 | * Holds all the actions (HTTP methods to CRUD verbs). |
||
50 | * TODO: refactor this!! |
||
51 | * @var array |
||
52 | */ |
||
53 | public static $actions = array( |
||
54 | 'POST' => 'onCreate', |
||
55 | 'GET' => 'onRead', |
||
56 | 'PUT' => 'onUpdate', |
||
57 | 'DELETE' => 'onDelete', |
||
58 | 'PATCH' => 'onModify', |
||
59 | 'OPTIONS' => 'onHelp', |
||
60 | 'HEAD' => 'onTest', |
||
61 | 'TRACE' => 'onTrace' |
||
62 | ); |
||
63 | |||
64 | /** |
||
65 | * Holds an array of router params |
||
66 | * @var array |
||
67 | */ |
||
68 | protected $params = array(); |
||
69 | |||
70 | private $_rules = array(); |
||
71 | private $_defaults = array(); |
||
72 | |||
73 | /** |
||
74 | * The constructor, set the default routing rules. |
||
75 | * |
||
76 | * @param array $rules |
||
77 | * @param array $defaults |
||
78 | * @throws \InvalidArgumentException |
||
79 | */ |
||
80 | public function __construct(array $rules=array(), array $defaults=array()) |
||
81 | { |
||
82 | foreach ($rules as $key => $rule) { |
||
83 | if ( is_int($key) ) { |
||
84 | throw new \InvalidArgumentException( |
||
85 | 'Invalid rules array specified (not associative)' |
||
86 | ); |
||
87 | } |
||
88 | $this->_rules[$key] = $rule; |
||
89 | } |
||
90 | |||
91 | // merges defaults with required props |
||
92 | $this->_defaults = $defaults+array('controller'=>null, 'action'=>null); |
||
93 | |||
94 | // set default properties |
||
95 | foreach ($this->_defaults as $prop => $value) { |
||
96 | $this->$prop = $value; |
||
97 | } |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * Sets the public properties e.g. controller, action, method and params |
||
102 | * in order as per the following: |
||
103 | * - router rules, |
||
104 | * - router params, |
||
105 | * - then router defauls. |
||
106 | * |
||
107 | * @param string $route |
||
0 ignored issues
–
show
|
|||
108 | * @param array $rules |
||
109 | * @param array $params |
||
110 | * @return void |
||
111 | */ |
||
112 | public function setAsProperties(array $rules, array $params) |
||
113 | { |
||
114 | foreach (array_keys($this->_defaults) as $k) { |
||
115 | $value = isset($rules[$k]) ? $rules[$k] // rules |
||
116 | : (isset($params[$k]) ? $params[$k] // params |
||
117 | : $this->_defaults[$k]); // defaults |
||
118 | |||
119 | if (property_exists($this, $k)) { |
||
120 | $this->$k = $value; |
||
121 | } |
||
122 | // else { |
||
123 | // echo 'TEMP'; |
||
124 | // $this->temp->$k = $value; |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
55% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
125 | // } |
||
126 | } |
||
127 | $this->params = $params; |
||
128 | } |
||
129 | |||
130 | /** |
||
131 | * Maps an URI against the routing table. |
||
132 | * |
||
133 | * @param string $uri |
||
134 | * @param array $params Additional params to merge with the current set (optional) |
||
135 | * @return void |
||
136 | */ |
||
137 | public function map($uri, array $params=null) |
||
138 | { |
||
139 | if (!is_null($params)) { |
||
140 | // merge with existing, precedence! |
||
141 | $this->setParams( $this->params+$params ); |
||
142 | } |
||
143 | |||
144 | foreach ($this->_rules as $route => $rules) { |
||
145 | $params = $this->routeToParamsMatcher($route, $uri); |
||
146 | if ($uri == $route || $params) { |
||
147 | $this->name = $route; |
||
0 ignored issues
–
show
It seems like
$route can also be of type integer . However, the property $name is declared as type string . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
![]() |
|||
148 | |||
149 | if(is_object($rules)) $rules = $rules->toArray(); |
||
150 | |||
151 | return $this->setAsProperties($rules, $params); |
||
0 ignored issues
–
show
It seems like
$params defined by $this->routeToParamsMatcher($route, $uri) on line 145 can also be of type false ; however, Apix\Router::setAsProperties() does only seem to accept array , did you maybe forget to handle an error condition?
This check looks for type mismatches where the missing type is Consider the follow example <?php
function getDate($date)
{
if ($date !== null) {
return new DateTime($date);
}
return false;
}
This function either returns a new ![]() |
|||
152 | } |
||
153 | } |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * Tries to match a route to an URI params (version with REGEX). |
||
158 | * |
||
159 | * @param string $route |
||
160 | * @param string $uri |
||
161 | * @return array |
||
162 | */ |
||
163 | public function routeToParamsMatcher($route, $uri) |
||
164 | { |
||
165 | $bits = explode('/', $route); |
||
166 | $paths = explode('/', $uri); |
||
167 | $result = array(); |
||
168 | |||
169 | // match 1st URI element not a param |
||
170 | if (count($paths) == 2 && count($bits) >2 ) { |
||
171 | if ($paths[1] == $bits[1]) { |
||
172 | return array($paths[1]); |
||
173 | } |
||
174 | } |
||
175 | |||
176 | // params |
||
177 | foreach ($bits as $key => $value) { |
||
178 | |||
179 | if ( |
||
180 | preg_match('/^:[\w]+$/', $value)) { |
||
181 | if (isset($paths[$key])) { |
||
182 | $value = substr($value, 1); // rm ':' |
||
183 | $result[$value] = $paths[$key]; |
||
184 | } |
||
185 | //} elseif (!isset($paths[$key]) || strcmp($value, $paths[$key]) != 0) { |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
71% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
186 | } elseif ( //Regex based! |
||
187 | isset($paths[$key]) |
||
188 | && preg_match('/^:(?P<key>[\w]+)(?:<(?P<regex>.+)>)?/', $value, $m) |
||
189 | && isset($m['regex']) |
||
190 | && preg_match('/^'.$m['regex'].'$/', $paths[$key], $n) |
||
191 | ) { |
||
192 | if(count($n)>1) array_shift($n); |
||
193 | $result[$m['key']] = implode('', $n); |
||
194 | } elseif (strcmp($value, $paths[$key]) != 0) { |
||
195 | return false; |
||
196 | } |
||
197 | } |
||
198 | |||
199 | return $result; |
||
200 | } |
||
201 | |||
202 | /** |
||
203 | * Sets the current action from a specified method |
||
204 | * or use the method in the current scope. |
||
205 | * |
||
206 | * @param string $method The method to set the action (optional) |
||
207 | * @return void |
||
208 | */ |
||
209 | public function setAction($method=null) |
||
210 | { |
||
211 | if (!is_null($method)) { |
||
212 | $this->setMethod($method); |
||
213 | } |
||
214 | $this->action = isset(self::$actions[$this->method]) |
||
215 | ? self::$actions[$this->method] |
||
216 | : null; |
||
217 | } |
||
218 | |||
219 | /** |
||
220 | * Returns the current action, or as specified. |
||
221 | * |
||
222 | * @param string $method A method key (optional) |
||
223 | * @return string |
||
224 | */ |
||
225 | public function getAction($method=null) |
||
226 | { |
||
227 | if (isset($method)) { |
||
228 | return isset(self::$actions[$method]) |
||
229 | ? self::$actions[$method] |
||
230 | : null; |
||
231 | } |
||
232 | if (null === $this->action) { |
||
233 | $this->setAction(); |
||
234 | } |
||
235 | |||
236 | return $this->action; |
||
237 | } |
||
238 | |||
239 | /** |
||
240 | * Returns all the actions. |
||
241 | * |
||
242 | * @return array |
||
243 | */ |
||
244 | public function getActions() |
||
245 | { |
||
246 | return self::$actions; |
||
247 | } |
||
248 | |||
249 | /** |
||
250 | * Sets the router's params. |
||
251 | * |
||
252 | * @param array $params |
||
253 | * @return void |
||
254 | */ |
||
255 | public function setParams(array $params) |
||
256 | { |
||
257 | $this->params = $params; |
||
258 | } |
||
259 | |||
260 | /** |
||
261 | * Returns all the router's params. |
||
262 | * |
||
263 | * @return array |
||
264 | */ |
||
265 | public function getParams() |
||
266 | { |
||
267 | return $this->params; |
||
268 | } |
||
269 | |||
270 | /** |
||
271 | * Sets the specified router param. |
||
272 | * |
||
273 | * @param string $key |
||
274 | * @param string $value |
||
275 | * @return void |
||
276 | */ |
||
277 | public function setParam($key, $value) |
||
278 | { |
||
279 | $this->params[$key] = $value; |
||
280 | } |
||
281 | |||
282 | /** |
||
283 | * Returns the specified router param. |
||
284 | * |
||
285 | * @param string $key |
||
286 | * @return array |
||
287 | * @throws \InvalidArgumentException |
||
288 | */ |
||
289 | public function getParam($key) |
||
290 | { |
||
291 | if (isset($this->params[$key])) { |
||
292 | return $this->params[$key]; |
||
293 | } |
||
294 | |||
295 | throw new \InvalidArgumentException( |
||
296 | sprintf('Invalid parameter "%s" requested.', $key) |
||
297 | ); |
||
298 | } |
||
299 | |||
300 | /** |
||
301 | * Checks a specified router param exists. |
||
302 | * |
||
303 | * @param string $key A key to check |
||
304 | * @return bolean |
||
305 | */ |
||
306 | public function hasParam($key) |
||
307 | { |
||
308 | return isset($this->params[$key]); |
||
309 | } |
||
310 | |||
311 | /** |
||
312 | * Sets the controller. |
||
313 | * |
||
314 | * @param string $controller |
||
315 | * @return void |
||
316 | */ |
||
317 | public function setController($controller) |
||
318 | { |
||
319 | $this->controller = $controller; |
||
320 | } |
||
321 | |||
322 | /** |
||
323 | * Returns the current controller. |
||
324 | * |
||
325 | * @return string |
||
326 | */ |
||
327 | public function getController() |
||
328 | { |
||
329 | return $this->controller; |
||
330 | } |
||
331 | |||
332 | /** |
||
333 | * Sets the method. |
||
334 | * |
||
335 | * @param string $method |
||
336 | * @return void |
||
337 | */ |
||
338 | public function setMethod($method) |
||
339 | { |
||
340 | $this->method = strtoupper($method); |
||
341 | } |
||
342 | |||
343 | /** |
||
344 | * Returns the current method. |
||
345 | * |
||
346 | * @return string |
||
347 | */ |
||
348 | public function getMethod() |
||
349 | { |
||
350 | return $this->method; |
||
351 | } |
||
352 | |||
353 | /** |
||
354 | * Returns, if set, the current route name. |
||
355 | * Alternatively, return the current path in scope. |
||
356 | * |
||
357 | * @return string|null |
||
358 | */ |
||
359 | public function getName() |
||
360 | { |
||
361 | return isset($this->name) ? $this->name : $this->getPath(); |
||
362 | } |
||
363 | |||
364 | /** |
||
365 | * Returns, if set, the current route path. |
||
366 | * |
||
367 | * @return string|null |
||
368 | */ |
||
369 | public function getPath() |
||
370 | { |
||
371 | return isset($this->path) ? $this->path : null; |
||
0 ignored issues
–
show
The property
path does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
372 | } |
||
373 | |||
374 | /** |
||
375 | * Sets the route name. |
||
376 | * |
||
377 | * @param $name |
||
378 | * @return string|null |
||
379 | */ |
||
380 | public function setName($name) |
||
381 | { |
||
382 | $this->name = $name; |
||
383 | } |
||
384 | |||
385 | } |
||
386 |
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.
Consider the following example. The parameter
$italy
is not defined by the methodfinale(...)
.The most likely cause is that the parameter was removed, but the annotation was not.