ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Router.php
Go to the documentation of this file.
1 <?php
9 namespace Slim;
10 
18 use FastRoute\RouteParser\Std as StdParser;
22 
31 class 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 }
getMethod()
Retrieves the HTTP method of the request.
dispatch(ServerRequestInterface $request)
Dispatch router for HTTP request.
Definition: Router.php:187
Route.
Definition: Route.php:21
Representation of an incoming, server-side HTTP request.
foreach($paths as $path) $request
Definition: asyncclient.php:32
getNamedRoute($name)
Get named route object.
Definition: Router.php:272
pushGroup($pattern, $callable)
Add a route group to the array.
Definition: Router.php:319
getRoutes()
Get route objects.
Definition: Router.php:258
__construct(RouteParser $parser=null)
Create new router.
Definition: Router.php:91
relativePathFor($name, array $data=[], array $queryParams=[])
Build the path for a named route excluding the base path.
Definition: Router.php:361
setCacheFile($cacheFile)
Set path to fast route cache file.
Definition: Router.php:121
Parses route strings of the following form:
Definition: Std.php:13
createDispatcher()
Definition: Router.php:219
$container
Definition: wac.php:13
setDispatcher(Dispatcher $dispatcher)
Definition: Router.php:248
Describes the interface of a container that exposes methods to read its entries.
$r
Definition: example_031.php:79
getUri()
Retrieves the URI instance.
urlFor($name, array $data=[], array $queryParams=[])
Build the path for a named route.
Definition: Router.php:450
removeNamedRoute($name)
Remove named route.
Definition: Router.php:289
popGroup()
Removes the last route group from the array.
Definition: Router.php:331
map($methods, $pattern, $handler)
Add route.
Definition: Router.php:156
createRoute($methods, $pattern, $callable)
Create a new Route object.
Definition: Router.php:206
processGroups()
Process route groups.
Definition: Router.php:302
$parser
Definition: BPMN2Parser.php:23
pathFor($name, array $data=[], array $queryParams=[])
Build the path for a named route including the base path.
Definition: Router.php:425
Slim Framework (https://slimframework.com)
Definition: App.php:9
$url
Router.
Definition: Router.php:31
$handler
setBasePath($basePath)
Set the base path used in pathFor()
Definition: Router.php:103
lookupRoute($identifier)
Definition: Router.php:341
setContainer(ContainerInterface $container)
Definition: Router.php:140
$data
Definition: bench.php:6