ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Router.php
Go to the documentation of this file.
1<?php
9namespace Slim;
10
13use InvalidArgumentException;
14use RuntimeException;
18use FastRoute\RouteParser\Std as StdParser;
22
31class Router implements RouterInterface
32{
38 protected $container;
39
45 protected $routeParser;
46
52 protected $basePath = '';
53
59 protected $cacheFile = false;
60
66 protected $routes = [];
67
72 protected $routeCounter = 0;
73
79 protected $routeGroups = [];
80
84 protected $dispatcher;
85
91 public function __construct(RouteParser $parser = null)
92 {
93 $this->routeParser = $parser ?: new StdParser;
94 }
95
103 public function setBasePath($basePath)
104 {
105 if (!is_string($basePath)) {
106 throw new InvalidArgumentException('Router basePath must be a string');
107 }
108
109 $this->basePath = $basePath;
110
111 return $this;
112 }
113
121 public function setCacheFile($cacheFile)
122 {
123 if (!is_string($cacheFile) && $cacheFile !== false) {
124 throw new InvalidArgumentException('Router cacheFile must be a string or false');
125 }
126
127 $this->cacheFile = $cacheFile;
128
129 if ($cacheFile !== false && !is_writable(dirname($cacheFile))) {
130 throw new RuntimeException('Router cacheFile directory must be writable');
131 }
132
133
134 return $this;
135 }
136
141 {
142 $this->container = $container;
143 }
144
156 public function map($methods, $pattern, $handler)
157 {
158 if (!is_string($pattern)) {
159 throw new InvalidArgumentException('Route pattern must be a string');
160 }
161
162 // Prepend parent group pattern(s)
163 if ($this->routeGroups) {
164 $pattern = $this->processGroups() . $pattern;
165 }
166
167 // According to RFC methods are defined in uppercase (See RFC 7231)
168 $methods = array_map("strtoupper", $methods);
169
170 // Add route
171 $route = $this->createRoute($methods, $pattern, $handler);
172 $this->routes[$route->getIdentifier()] = $route;
173 $this->routeCounter++;
174
175 return $route;
176 }
177
188 {
189 $uri = '/' . ltrim($request->getUri()->getPath(), '/');
190
191 return $this->createDispatcher()->dispatch(
192 $request->getMethod(),
193 $uri
194 );
195 }
196
206 protected function createRoute($methods, $pattern, $callable)
207 {
208 $route = new Route($methods, $pattern, $callable, $this->routeGroups, $this->routeCounter);
209 if (!empty($this->container)) {
210 $route->setContainer($this->container);
211 }
212
213 return $route;
214 }
215
219 protected function createDispatcher()
220 {
221 if ($this->dispatcher) {
222 return $this->dispatcher;
223 }
224
225 $routeDefinitionCallback = function (RouteCollector $r) {
226 foreach ($this->getRoutes() as $route) {
227 $r->addRoute($route->getMethods(), $route->getPattern(), $route->getIdentifier());
228 }
229 };
230
231 if ($this->cacheFile) {
232 $this->dispatcher = \FastRoute\cachedDispatcher($routeDefinitionCallback, [
233 'routeParser' => $this->routeParser,
234 'cacheFile' => $this->cacheFile,
235 ]);
236 } else {
237 $this->dispatcher = \FastRoute\simpleDispatcher($routeDefinitionCallback, [
238 'routeParser' => $this->routeParser,
239 ]);
240 }
241
242 return $this->dispatcher;
243 }
244
248 public function setDispatcher(Dispatcher $dispatcher)
249 {
250 $this->dispatcher = $dispatcher;
251 }
252
258 public function getRoutes()
259 {
260 return $this->routes;
261 }
262
272 public function getNamedRoute($name)
273 {
274 foreach ($this->routes as $route) {
275 if ($name == $route->getName()) {
276 return $route;
277 }
278 }
279 throw new RuntimeException('Named route does not exist for name: ' . $name);
280 }
281
289 public function removeNamedRoute($name)
290 {
291 $route = $this->getNamedRoute($name);
292
293 // no exception, route exists, now remove by id
294 unset($this->routes[$route->getIdentifier()]);
295 }
296
302 protected function processGroups()
303 {
304 $pattern = "";
305 foreach ($this->routeGroups as $group) {
306 $pattern .= $group->getPattern();
307 }
308 return $pattern;
309 }
310
319 public function pushGroup($pattern, $callable)
320 {
321 $group = new RouteGroup($pattern, $callable);
322 array_push($this->routeGroups, $group);
323 return $group;
324 }
325
331 public function popGroup()
332 {
333 $group = array_pop($this->routeGroups);
334 return $group instanceof RouteGroup ? $group : false;
335 }
336
341 public function lookupRoute($identifier)
342 {
343 if (!isset($this->routes[$identifier])) {
344 throw new RuntimeException('Route not found, looks like your route cache is stale.');
345 }
346 return $this->routes[$identifier];
347 }
348
361 public function relativePathFor($name, array $data = [], array $queryParams = [])
362 {
363 $route = $this->getNamedRoute($name);
364 $pattern = $route->getPattern();
365
366 $routeDatas = $this->routeParser->parse($pattern);
367 // $routeDatas is an array of all possible routes that can be made. There is
368 // one routedata for each optional parameter plus one for no optional parameters.
369 //
370 // The most specific is last, so we look for that first.
371 $routeDatas = array_reverse($routeDatas);
372
373 $segments = [];
374 foreach ($routeDatas as $routeData) {
375 foreach ($routeData as $item) {
376 if (is_string($item)) {
377 // this segment is a static string
378 $segments[] = $item;
379 continue;
380 }
381
382 // This segment has a parameter: first element is the name
383 if (!array_key_exists($item[0], $data)) {
384 // we don't have a data element for this segment: cancel
385 // testing this routeData item, so that we can try a less
386 // specific routeData item.
387 $segments = [];
388 $segmentName = $item[0];
389 break;
390 }
391 $segments[] = $data[$item[0]];
392 }
393 if (!empty($segments)) {
394 // we found all the parameters for this route data, no need to check
395 // less specific ones
396 break;
397 }
398 }
399
400 if (empty($segments)) {
401 throw new InvalidArgumentException('Missing data for URL segment: ' . $segmentName);
402 }
403 $url = implode('', $segments);
404
405 if ($queryParams) {
406 $url .= '?' . http_build_query($queryParams);
407 }
408
409 return $url;
410 }
411
412
425 public function pathFor($name, array $data = [], array $queryParams = [])
426 {
427 $url = $this->relativePathFor($name, $data, $queryParams);
428
429 if ($this->basePath) {
430 $url = $this->basePath . $url;
431 }
432
433 return $url;
434 }
435
450 public function urlFor($name, array $data = [], array $queryParams = [])
451 {
452 trigger_error('urlFor() is deprecated. Use pathFor() instead.', E_USER_DEPRECATED);
453 return $this->pathFor($name, $data, $queryParams);
454 }
455}
$parser
Definition: BPMN2Parser.php:23
foreach($paths as $path) $request
Definition: asyncclient.php:32
An exception for terminatinating execution or to throw for unit testing.
Parses route strings of the following form:
Definition: Std.php:14
Route.
Definition: Route.php:22
Router.
Definition: Router.php:32
setContainer(ContainerInterface $container)
Definition: Router.php:140
lookupRoute($identifier)
Definition: Router.php:341
getRoutes()
Get route objects.
Definition: Router.php:258
getNamedRoute($name)
Get named route object.
Definition: Router.php:272
processGroups()
Process route groups.
Definition: Router.php:302
map($methods, $pattern, $handler)
Add route.
Definition: Router.php:156
pushGroup($pattern, $callable)
Add a route group to the array.
Definition: Router.php:319
pathFor($name, array $data=[], array $queryParams=[])
Build the path for a named route including the base path.
Definition: Router.php:425
createRoute($methods, $pattern, $callable)
Create a new Route object.
Definition: Router.php:206
setBasePath($basePath)
Set the base path used in pathFor()
Definition: Router.php:103
setDispatcher(Dispatcher $dispatcher)
Definition: Router.php:248
__construct(RouteParser $parser=null)
Create new router.
Definition: Router.php:91
createDispatcher()
Definition: Router.php:219
popGroup()
Removes the last route group from the array.
Definition: Router.php:331
dispatch(ServerRequestInterface $request)
Dispatch router for HTTP request.
Definition: Router.php:187
setCacheFile($cacheFile)
Set path to fast route cache file.
Definition: Router.php:121
urlFor($name, array $data=[], array $queryParams=[])
Build the path for a named route.
Definition: Router.php:450
relativePathFor($name, array $data=[], array $queryParams=[])
Build the path for a named route excluding the base path.
Definition: Router.php:361
removeNamedRoute($name)
Remove named route.
Definition: Router.php:289
$r
Definition: example_031.php:79
Describes the interface of a container that exposes methods to read its entries.
Describes the interface of a container that exposes methods to read its entries.
Representation of an incoming, server-side HTTP request.
Slim Framework (https://slimframework.com)
Definition: App.php:9
$url
$handler
$data
Definition: bench.php:6
$container
Definition: wac.php:13