From 97f3280afa4c681b18c438ae1f975df8cf70c3a9 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 7 Apr 2024 03:47:36 +0200 Subject: [PATCH] added feature "link aliases" --- src/Application/LinkGenerator.php | 13 ++++- src/Application/PresenterFactory.php | 17 ++++++ .../ApplicationDI/ApplicationExtension.php | 5 ++ tests/Routers/link-aliases.phpt | 58 +++++++++++++++++++ 4 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 tests/Routers/link-aliases.phpt diff --git a/src/Application/LinkGenerator.php b/src/Application/LinkGenerator.php index 8e9cc32ee..ad2a70e7a 100644 --- a/src/Application/LinkGenerator.php +++ b/src/Application/LinkGenerator.php @@ -33,7 +33,7 @@ public function __construct( /** * Generates URL to presenter. - * @param string $destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]" + * @param string $destination in format "[//] [[[module:]presenter:]action | signal! | this | @alias] [#fragment]" * @throws UI\InvalidLinkException */ public function link( @@ -54,7 +54,7 @@ public function link( /** - * @param string $destination in format "[[[module:]presenter:]action | signal! | this]" + * @param string $destination in format "[[[module:]presenter:]action | signal! | this | @alias]" * @param string $mode forward|redirect|link * @throws UI\InvalidLinkException * @internal @@ -85,6 +85,13 @@ public function createRequest( $path = 'this'; } + if ($path[0] === '@') { + if (!$this->presenterFactory instanceof PresenterFactory) { + throw new \LogicException('Link aliasing requires PresenterFactory service.'); + } + $path = ':' . $this->presenterFactory->getAlias(substr($path, 1)); + } + $current = false; [$presenter, $action] = Helpers::splitName($path); if ($presenter === '') { @@ -223,7 +230,7 @@ public function createRequest( /** - * Parse destination in format "[//] [[[module:]presenter:]action | signal! | this] [?query] [#fragment]" + * Parse destination in format "[//] [[[module:]presenter:]action | signal! | this | @alias] [?query] [#fragment]" * @throws UI\InvalidLinkException * @return array{absolute: bool, path: string, signal: bool, args: ?array, fragment: string} * @internal diff --git a/src/Application/PresenterFactory.php b/src/Application/PresenterFactory.php index c35c7aab8..225f04768 100644 --- a/src/Application/PresenterFactory.php +++ b/src/Application/PresenterFactory.php @@ -23,6 +23,7 @@ class PresenterFactory implements IPresenterFactory 'Nette' => ['NetteModule\\', '*\\', '*Presenter'], ]; + private array $aliases = []; private array $cache = []; /** @var callable */ @@ -117,4 +118,20 @@ public function formatPresenterClass(string $presenter): string return $mapping[0]; } + + + /** + * Sets pairs [alias => destination] + */ + public function setAliases(array $aliases): static + { + $this->aliases = $aliases; + return $this; + } + + + public function getAlias(string $alias): string + { + return $this->aliases[$alias] ?? throw new Nette\InvalidStateException("Link alias '$alias' was not found."); + } } diff --git a/src/Bridges/ApplicationDI/ApplicationExtension.php b/src/Bridges/ApplicationDI/ApplicationExtension.php index 663650ed1..a874f55f4 100644 --- a/src/Bridges/ApplicationDI/ApplicationExtension.php +++ b/src/Bridges/ApplicationDI/ApplicationExtension.php @@ -52,6 +52,7 @@ public function getConfigSchema(): Nette\Schema\Schema Expect::string(), Expect::arrayOf('string|array'), ), + 'aliases' => Expect::arrayOf('string'), 'scanDirs' => Expect::anyOf( Expect::arrayOf('string')->default($this->scanDirs)->mergeDefaults(), false, @@ -101,6 +102,10 @@ public function loadConfiguration(): void ]); } + if ($config->aliases) { + $presenterFactory->addSetup('setAliases', [$config->aliases]); + } + $builder->addDefinition($this->prefix('linkGenerator')) ->setFactory(Nette\Application\LinkGenerator::class, [ 1 => new Definitions\Statement([new Definitions\Statement('@Nette\Http\IRequest::getUrl'), 'withoutUserInfo']), diff --git a/tests/Routers/link-aliases.phpt b/tests/Routers/link-aliases.phpt new file mode 100644 index 000000000..0f2b75324 --- /dev/null +++ b/tests/Routers/link-aliases.phpt @@ -0,0 +1,58 @@ +setAliases([ + 'a' => 'Test:a', + 'b' => 'Test:b', +]); + +Assert::same('Test:a', $factory->getAlias('a')); +Assert::same('Test:b', $factory->getAlias('b')); +Assert::exception( + fn() => $factory->getAlias('c'), + Nette\InvalidStateException::class, + "Link alias 'c' was not found.", +); + + + +// link generator +$generator = new Application\LinkGenerator( + new Application\Routers\SimpleRouter, + new Http\UrlScript('http://localhost'), + $factory, +); + +Assert::same('http://localhost/?action=a&presenter=Test', $generator->link('@a')); + + +// presenter +$presenter = new TestPresenter; +$presenter->injectPrimary( + new Http\Request(new Http\UrlScript('http://localhost')), + new Http\Response, + $factory, + new Application\Routers\SimpleRouter, +); + + +Assert::same('/?action=a&presenter=Test', $presenter->link('@a'));