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 (method_exists($class, $method = $class::formatActionMethod($action))
62: || method_exists($class, $method = $class::formatRenderMethod($action))
63: ) {
64: UI\Presenter::argsToParams($class, $method, $params, [], $missing);
65: if ($missing) {
66: $rp = $missing[0];
67: throw new UI\InvalidLinkException("Missing parameter \${$rp->getName()} required by {$rp->getDeclaringClass()->getName()}::{$rp->getDeclaringFunction()->getName()}()");
68: }
69:
70: } elseif (array_key_exists(0, $params)) {
71: throw new UI\InvalidLinkException("Unable to pass parameters to action '$presenter:$action', missing corresponding method.");
72: }
73: }
74:
75: if ($action !== '') {
76: $params[UI\Presenter::ACTION_KEY] = $action;
77: }
78:
79: $url = $this->router->constructUrl(new Request($presenter, null, $params), $this->refUrl);
80: if ($url === null) {
81: unset($params[UI\Presenter::ACTION_KEY]);
82: $params = urldecode(http_build_query($params, null, ', '));
83: throw new UI\InvalidLinkException("No route for $dest($params)");
84: }
85: return $url . $frag;
86: }
87: }
88: