Skip to content

Commit 8cefa65

Browse files
committed
added feature "link aliases"
1 parent 300adab commit 8cefa65

File tree

5 files changed

+97
-2
lines changed

5 files changed

+97
-2
lines changed

src/Application/LinkGenerator.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
namespace Nette\Application;
1111

12+
use Nette;
1213
use Nette\Http\UrlScript;
1314
use Nette\Routing\Router;
1415

@@ -33,11 +34,18 @@ public function __construct(
3334
*/
3435
public function link(string $dest, array $params = []): string
3536
{
36-
if (!preg_match('~^([\w:]+):(\w*+)(#.*)?()$~D', $dest, $m)) {
37+
if (!preg_match('~^(@[\w:-]++|[\w:]+:\w*+)(#.*)?()$~D', $dest, $m)) {
3738
throw new UI\InvalidLinkException("Invalid link destination '$dest'.");
3839
}
3940

40-
[, $presenter, $action, $frag] = $m;
41+
[, $path, $frag] = $m;
42+
if ($path[0] === '@') {
43+
if (!$this->presenterFactory instanceof PresenterFactory) {
44+
throw new Nette\InvalidStateException('Link aliasing requires PresenterFactory service.');
45+
}
46+
$path = $this->presenterFactory->getAlias(substr($path, 1));
47+
}
48+
[$presenter, $action] = Helpers::splitName($path);
4149

4250
try {
4351
$class = $this->presenterFactory?->getPresenterClass($presenter);

src/Application/PresenterFactory.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class PresenterFactory implements IPresenterFactory
2323
'Nette' => ['NetteModule\\', '*\\', '*Presenter'],
2424
];
2525

26+
private array $aliases = [];
2627
private array $cache = [];
2728

2829
/** @var callable */
@@ -117,4 +118,20 @@ public function formatPresenterClass(string $presenter): string
117118

118119
return $mapping[0];
119120
}
121+
122+
123+
/**
124+
* Sets pairs [alias => destination]
125+
*/
126+
public function setAliases(array $aliases): static
127+
{
128+
$this->aliases = $aliases;
129+
return $this;
130+
}
131+
132+
133+
public function getAlias(string $alias): string
134+
{
135+
return $this->aliases[$alias] ?? throw new Nette\InvalidStateException("Link alias '$alias' was not found.");
136+
}
120137
}

src/Application/UI/Presenter.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,13 @@ protected function createRequest(
856856
$path = 'this';
857857
}
858858

859+
if ($path[0] === '@') {
860+
if (!($this->presenterFactory ?? null) instanceof Application\PresenterFactory) {
861+
throw new Nette\InvalidStateException('Link aliasing requires PresenterFactory service.');
862+
}
863+
$path = ':' . $this->presenterFactory->getAlias(substr($path, 1));
864+
}
865+
859866
$current = false;
860867
[$presenter, $action] = Helpers::splitName($path);
861868
if ($presenter === '') {

src/Bridges/ApplicationDI/ApplicationExtension.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public function getConfigSchema(): Nette\Schema\Schema
5252
Expect::string(),
5353
Expect::arrayOf('string|array'),
5454
),
55+
'aliases' => Expect::arrayOf('string'),
5556
'scanDirs' => Expect::anyOf(
5657
Expect::arrayOf('string')->default($this->scanDirs)->mergeDefaults(),
5758
false,
@@ -101,6 +102,10 @@ public function loadConfiguration(): void
101102
]);
102103
}
103104

105+
if ($config->aliases) {
106+
$presenterFactory->addSetup('setAliases', [$config->aliases]);
107+
}
108+
104109
$builder->addDefinition($this->prefix('linkGenerator'))
105110
->setFactory(Nette\Application\LinkGenerator::class, [
106111
1 => new Definitions\Statement([new Definitions\Statement('@Nette\Http\IRequest::getUrl'), 'withoutUserInfo']),

tests/Routers/link-aliases.phpt

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/**
4+
* Test: Nette\Application\UI\Component::redirect()
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
use Nette\Application;
10+
use Nette\Application\PresenterFactory;
11+
use Nette\Http;
12+
use Tester\Assert;
13+
14+
require __DIR__ . '/../bootstrap.php';
15+
16+
17+
class TestPresenter extends Application\UI\Presenter
18+
{
19+
}
20+
21+
22+
$factory = new PresenterFactory;
23+
$factory->setAliases([
24+
'a' => 'Test:a',
25+
'b' => 'Test:b',
26+
]);
27+
28+
Assert::same('Test:a', $factory->getAlias('a'));
29+
Assert::same('Test:b', $factory->getAlias('b'));
30+
Assert::exception(
31+
fn() => $factory->getAlias('c'),
32+
Nette\InvalidStateException::class,
33+
"Link alias 'c' was not found.",
34+
);
35+
36+
37+
38+
// link generator
39+
$generator = new Application\LinkGenerator(
40+
new Application\Routers\SimpleRouter,
41+
new Http\UrlScript('http://localhost'),
42+
$factory,
43+
);
44+
45+
Assert::same('http://localhost/?action=a&presenter=Test', $generator->link('@a'));
46+
47+
48+
// presenter
49+
$presenter = new TestPresenter;
50+
$presenter->injectPrimary(
51+
new Http\Request(new Http\UrlScript('http://localhost')),
52+
new Http\Response,
53+
$factory,
54+
new Application\Routers\SimpleRouter,
55+
);
56+
57+
58+
Assert::same('/?action=a&presenter=Test', $presenter->link('@a'));

0 commit comments

Comments
 (0)