%PDF- %PDF-
Direktori : /proc/985914/root/www/varak.net/losik.varak.net/vendor/nette/routing/src/Routing/ |
Current File : //proc/985914/root/www/varak.net/losik.varak.net/vendor/nette/routing/src/Routing/RouteList.php |
<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Routing; use Nette; /** * The router broker. */ class RouteList implements Router { use Nette\SmartObject; /** @var self|null */ protected $parent; /** @var array of [Router, flags] */ private $list = []; /** @var Router[][]|null */ private $ranks; /** @var string */ private $cacheKey; /** @var string|null */ private $domain; /** @var string|null */ private $path; /** @var \SplObjectStorage|null */ private $refUrlCache; public function __construct() { } /** * Maps HTTP request to an array. */ public function match(Nette\Http\IRequest $httpRequest): ?array { if ($this->domain) { $host = $httpRequest->getUrl()->getHost(); if ($host !== $this->expandDomain($host)) { return null; } } if ($this->path) { $url = $httpRequest->getUrl(); if (strncmp($url->getRelativePath(), $this->path, strlen($this->path))) { return null; } $url = $url->withPath($url->getPath(), $url->getBasePath() . $this->path); $httpRequest = $httpRequest->withUrl($url); } foreach ($this->list as [$router]) { $params = $router->match($httpRequest); if ($params !== null) { return $params; } } return null; } /** * Constructs absolute URL from array. */ public function constructUrl(array $params, Nette\Http\UrlScript $refUrl): ?string { if ($this->domain) { if (!isset($this->refUrlCache[$refUrl])) { $this->refUrlCache[$refUrl] = $refUrl->withHost( $this->expandDomain($refUrl->getHost()) ); } $refUrl = $this->refUrlCache[$refUrl]; } if ($this->path) { if (!isset($this->refUrlCache[$refUrl])) { $this->refUrlCache[$refUrl] = $refUrl->withPath($refUrl->getBasePath() . $this->path); } $refUrl = $this->refUrlCache[$refUrl]; } if ($this->ranks === null) { $this->warmupCache(); } $key = $params[$this->cacheKey] ?? null; if (!is_scalar($key) || !isset($this->ranks[$key])) { $key = '*'; } foreach ($this->ranks[$key] as $router) { $url = $router->constructUrl($params, $refUrl); if ($url !== null) { return $url; } } return null; } public function warmupCache(): void { // find best key $candidates = []; $routers = []; foreach ($this->list as [$router, $flags]) { if ($flags & self::ONE_WAY) { continue; } elseif ($router instanceof self) { $router->warmupCache(); } $params = $router instanceof Route ? $router->getConstantParameters() : []; foreach (array_filter($params, 'is_scalar') as $name => $value) { $candidates[$name][$value] = true; } $routers[] = [$router, $params]; } $this->cacheKey = $count = null; foreach ($candidates as $name => $items) { if (count($items) > $count) { $count = count($items); $this->cacheKey = $name; } } // classify routers $ranks = ['*' => []]; foreach ($routers as [$router, $params]) { $value = $params[$this->cacheKey] ?? null; $values = $value === null ? array_keys($ranks) : [is_scalar($value) ? $value : '*']; foreach ($values as $value) { if (!isset($ranks[$value])) { $ranks[$value] = $ranks['*']; } $ranks[$value][] = $router; } } $this->ranks = $ranks; } /** * Adds a router. * @return static */ public function add(Router $router, int $flags = 0) { $this->list[] = [$router, $flags]; $this->ranks = null; return $this; } /** * Prepends a router. */ public function prepend(Router $router, int $flags = 0): void { array_splice($this->list, 0, 0, [[$router, $flags]]); $this->ranks = null; } /** @internal */ protected function modify(int $index, ?Router $router): void { if (!isset($this->list[$index])) { throw new Nette\OutOfRangeException('Offset invalid or out of range'); } elseif ($router) { $this->list[$index] = [$router, 0]; } else { array_splice($this->list, $index, 1); } $this->ranks = null; } /** * @param string $mask e.g. '<presenter>/<action>/<id \d{1,3}>' * @param array $metadata default values or metadata * @return static */ public function addRoute(string $mask, $metadata = [], int $flags = 0) { $this->add(new Route($mask, $metadata), $flags); return $this; } /** * Returns an iterator over all routers. * @return static */ public function withDomain(string $domain) { $router = new static; $router->domain = $domain; $router->refUrlCache = new \SplObjectStorage; $router->parent = $this; $this->add($router); return $router; } /** * @return static */ public function withPath(string $path) { $router = new static; $router->path = rtrim($path, '/') . '/'; $router->refUrlCache = new \SplObjectStorage; $router->parent = $this; $this->add($router); return $router; } /** * @return ?static */ public function end() { return $this->parent; } /** * @return Router[] */ public function getRouters(): array { return array_column($this->list, 0); } /** * @return int[] */ public function getFlags(): array { return array_column($this->list, 1); } public function getDomain(): ?string { return $this->domain; } public function getPath(): ?string { return $this->path; } private function expandDomain(string $host): string { $parts = ip2long($host) ? [$host] : array_reverse(explode('.', $host)); return strtr($this->domain, [ '%tld%' => $parts[0], '%domain%' => isset($parts[1]) ? "$parts[1].$parts[0]" : $parts[0], '%sld%' => $parts[1] ?? '', ]); } }