1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Application;
9:
10: use Nette;
11:
12:
13: 14: 15:
16: class LinkGenerator
17: {
18: use Nette\SmartObject;
19:
20:
21: private $router;
22:
23:
24: private $refUrl;
25:
26:
27: private $presenterFactory;
28:
29:
30: public function __construct(IRouter $router, Nette\Http\Url $refUrl, IPresenterFactory $presenterFactory = null)
31: {
32: $this->router = $router;
33: $this->refUrl = $refUrl;
34: $this->presenterFactory = $presenterFactory;
35: }
36:
37:
38: 39: 40: 41: 42: 43:
44: public function link($dest, array $params = [])
45: {
46: if (!preg_match('~^([\w:]+):(\w*+)(#.*)?()\z~', $dest, $m)) {
47: throw new UI\InvalidLinkException("Invalid link destination '$dest'.");
48: }
49: list(, $presenter, $action, $frag) = $m;
50:
51: try {
52: $class = $this->presenterFactory ? $this->presenterFactory->getPresenterClass($presenter) : null;
53: } catch (InvalidPresenterException $e) {
54: throw new UI\InvalidLinkException($e->getMessage(), 0, $e);
55: }
56:
57: if (is_subclass_of($class, UI\Presenter::class)) {
58: if ($action === '') {
59: $action = UI\Presenter::DEFAULT_ACTION;
60: }
61: if (
62: method_exists($class, $method = $class::formatActionMethod($action))
63: || method_exists($class, $method = $class::formatRenderMethod($action))
64: ) {
65: UI\Presenter::argsToParams($class, $method, $params, [], $missing);
66: if ($missing) {
67: $rp = $missing[0];
68: throw new UI\InvalidLinkException("Missing parameter \${$rp->getName()} required by {$rp->getDeclaringClass()->getName()}::{$rp->getDeclaringFunction()->getName()}()");
69: }
70:
71: } elseif (array_key_exists(0, $params)) {
72: throw new UI\InvalidLinkException("Unable to pass parameters to action '$presenter:$action', missing corresponding method.");
73: }
74: }
75:
76: if ($action !== '') {
77: $params[UI\Presenter::ACTION_KEY] = $action;
78: }
79:
80: $url = $this->router->constructUrl(new Request($presenter, null, $params), $this->refUrl);
81: if ($url === null) {
82: unset($params[UI\Presenter::ACTION_KEY]);
83: $params = urldecode(http_build_query($params, null, ', '));
84: throw new UI\InvalidLinkException("No route for $dest($params)");
85: }
86: return $url . $frag;
87: }
88: }
89: