From ac376f18d9fa44a892719dfeca4afc58948f7b09 Mon Sep 17 00:00:00 2001 From: Jan Tvrdik Date: Sat, 27 Jun 2015 13:18:01 +0200 Subject: [PATCH 1/2] IRouter: added (commented) getTargetPresenters() to speed-up link generation --- src/Application/IRouter.php | 6 ++ src/Application/Routers/Route.php | 3 +- src/Application/Routers/RouteList.php | 63 +++++++++++++------ .../RouteList.getTargetPresenters().phpt | 53 ++++++++++++++++ 4 files changed, 104 insertions(+), 21 deletions(-) create mode 100644 tests/Application.Routers/RouteList.getTargetPresenters().phpt diff --git a/src/Application/IRouter.php b/src/Application/IRouter.php index 5a051ac27..394898553 100644 --- a/src/Application/IRouter.php +++ b/src/Application/IRouter.php @@ -35,4 +35,10 @@ function match(Nette\Http\IRequest $httpRequest); */ function constructUrl(Request $appRequest, Nette\Http\Url $refUrl); + /** + * Returns list of possible target presenters or NULL if the list is dynamic. + * @return string[]|NULL + */ + // function getTargetPresenters(); + } diff --git a/src/Application/Routers/Route.php b/src/Application/Routers/Route.php index 836a6a49e..f392a9c4b 100644 --- a/src/Application/Routers/Route.php +++ b/src/Application/Routers/Route.php @@ -653,8 +653,7 @@ public function getFlags() /** - * Proprietary cache aim. - * @internal + * Returns list of possible target presenters or NULL if the list is dynamic. * @return string[]|NULL */ public function getTargetPresenters() diff --git a/src/Application/Routers/RouteList.php b/src/Application/Routers/RouteList.php index e80b4b078..5f33183f5 100644 --- a/src/Application/Routers/RouteList.php +++ b/src/Application/Routers/RouteList.php @@ -57,25 +57,6 @@ public function match(Nette\Http\IRequest $httpRequest) */ public function constructUrl(Nette\Application\Request $appRequest, Nette\Http\Url $refUrl) { - if ($this->cachedRoutes === NULL) { - $routes = []; - $routes['*'] = []; - - foreach ($this as $route) { - $presenters = $route instanceof Route && is_array($tmp = $route->getTargetPresenters()) - ? $tmp : array_keys($routes); - - foreach ($presenters as $presenter) { - if (!isset($routes[$presenter])) { - $routes[$presenter] = $routes['*']; - } - $routes[$presenter][] = $route; - } - } - - $this->cachedRoutes = $routes; - } - if ($this->module) { if (strncmp($tmp = $appRequest->getPresenterName(), $this->module, strlen($this->module)) === 0) { $appRequest = clone $appRequest; @@ -86,6 +67,10 @@ public function constructUrl(Nette\Application\Request $appRequest, Nette\Http\U } $presenter = $appRequest->getPresenterName(); + if ($this->cachedRoutes === NULL) { + $this->cachedRoutes = $this->buildCache(); + } + if (!isset($this->cachedRoutes[$presenter])) { $presenter = '*'; } @@ -112,6 +97,7 @@ public function offsetSet($index, $route) if (!$route instanceof Nette\Application\IRouter) { throw new Nette\InvalidArgumentException('Argument must be IRouter descendant.'); } + $this->cachedRoutes = NULL; parent::offsetSet($index, $route); } @@ -124,4 +110,43 @@ public function getModule() return $this->module; } + + /** + * Returns list of possible target presenters or NULL if the list is dynamic. + * @return string[]|NULL + */ + public function getTargetPresenters() + { + if ($this->cachedRoutes === NULL) { + $this->cachedRoutes = $this->buildCache(); + } + + if (empty($this->cachedRoutes['*'])) { + $presenters = array_keys($this->cachedRoutes); + return array_slice($presenters, 1); // remove '*' + } + + return NULL; + } + + + /** + * @return array + */ + private function buildCache() + { + $routes = ['*' => []]; + foreach ($this as $route) { + $presenters = method_exists($route, 'getTargetPresenters') ? $route->getTargetPresenters() : NULL; + $keys = is_array($presenters) ? $presenters : array_keys($routes); + foreach ($keys as $key) { + if (!isset($routes[$key])) { + $routes[$key] = $routes['*']; + } + $routes[$key][] = $route; + } + } + return $routes; + } + } diff --git a/tests/Application.Routers/RouteList.getTargetPresenters().phpt b/tests/Application.Routers/RouteList.getTargetPresenters().phpt new file mode 100644 index 000000000..73edbdb2b --- /dev/null +++ b/tests/Application.Routers/RouteList.getTargetPresenters().phpt @@ -0,0 +1,53 @@ +getTargetPresenters()); +}); + + +test(function () { + $list = new RouteList(); + $list[] = new Route('about', 'About:default'); + Assert::same(['About'], $list->getTargetPresenters()); +}); + + +test(function () { + $list = new RouteList(); + $list[] = new Route('about', 'About:default'); + $list[] = new Route('/'); + Assert::same(NULL, $list->getTargetPresenters()); +}); + + +test(function () { + $list = new RouteList(); + $list[] = new Route('about', 'About:default'); + $list[] = new RouteList(); + $list[1][] = new Route('homepage', 'Homepage:default'); + Assert::same(['About', 'Homepage'], $list->getTargetPresenters()); +}); + + +test(function () { + $list = new RouteList(); + $list[] = new Route('about', 'About:default'); + $list[] = new RouteList(); + $list[1][] = new Route('/'); + Assert::same(NULL, $list->getTargetPresenters()); +}); From a200dd82f087be50b9b1c723694b7e4f8ccc3498 Mon Sep 17 00:00:00 2001 From: Jan Tvrdik Date: Sat, 27 Jun 2015 13:19:11 +0200 Subject: [PATCH 2/2] RouteList: disallow any modification once the cache is built (WIP) --- src/Application/Routers/RouteList.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Application/Routers/RouteList.php b/src/Application/Routers/RouteList.php index 5f33183f5..4aebfbf3c 100644 --- a/src/Application/Routers/RouteList.php +++ b/src/Application/Routers/RouteList.php @@ -96,8 +96,9 @@ public function offsetSet($index, $route) { if (!$route instanceof Nette\Application\IRouter) { throw new Nette\InvalidArgumentException('Argument must be IRouter descendant.'); + } elseif ($this->cachedRoutes !== NULL) { + throw new \LogicException('No!'); // TODO: we need some LogicException from Nette namespace } - $this->cachedRoutes = NULL; parent::offsetSet($index, $route); }