1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
declare(strict_types=1);
namespace Laminas\View\Helper;
use Laminas\Mvc\ModuleRouteListener;
use Laminas\Router\RouteMatch;
use Laminas\Router\RouteStackInterface;
use Laminas\View\Exception;
use Traversable;
use function array_merge;
use function func_num_args;
use function get_class;
use function gettype;
use function is_array;
use function is_bool;
use function is_object;
use function iterator_to_array;
use function sprintf;
/**
* Helper for making easy links and getting urls that depend on the routes and router.
*/
class Url extends AbstractHelper
{
/**
* Router instance.
*
* @var RouteStackInterface|null
*/
protected $router;
/**
* Route matches returned by the router.
*
* @var RouteMatch|null
*/
protected $routeMatch;
/**
* Generates an url given the name of a route.
*
* @see \Laminas\Router\RouteInterface::assemble()
*
* @param string|null $name Name of the route
* @param array $params Parameters for the link
* @param array|Traversable $options Options for the route
* @param bool $reuseMatchedParams Whether to reuse matched parameters
* @return string Url For the link href attribute
* @throws Exception\RuntimeException If no RouteStackInterface was provided.
* @throws Exception\RuntimeException If no RouteMatch was provided.
* @throws Exception\RuntimeException If RouteMatch didn't contain a matched route name.
* @throws Exception\InvalidArgumentException If the params object was not an array or Traversable object.
*/
public function __invoke($name = null, $params = [], $options = [], $reuseMatchedParams = false)
{
if (null === $this->router) {
throw new Exception\RuntimeException('No RouteStackInterface instance provided');
}
if (3 === func_num_args() && is_bool($options)) {
$reuseMatchedParams = $options;
$options = [];
}
if ($name === null) {
if ($this->routeMatch === null) {
throw new Exception\RuntimeException('No RouteMatch instance provided');
}
/** @psalm-suppress RedundantCastGivenDocblockType */
$name = (string) $this->routeMatch->getMatchedRouteName();
if ($name === '') {
throw new Exception\RuntimeException('RouteMatch does not contain a matched route name');
}
}
if (! is_array($params)) {
if (! $params instanceof Traversable) {
throw new Exception\InvalidArgumentException(
'Params is expected to be an array or a Traversable object'
);
}
$params = iterator_to_array($params);
}
if ($reuseMatchedParams && $this->routeMatch !== null) {
$routeMatchParams = $this->routeMatch->getParams();
if (isset($routeMatchParams[ModuleRouteListener::ORIGINAL_CONTROLLER])) {
$routeMatchParams['controller'] = $routeMatchParams[ModuleRouteListener::ORIGINAL_CONTROLLER];
unset($routeMatchParams[ModuleRouteListener::ORIGINAL_CONTROLLER]);
}
if (isset($routeMatchParams[ModuleRouteListener::MODULE_NAMESPACE])) {
unset($routeMatchParams[ModuleRouteListener::MODULE_NAMESPACE]);
}
$params = array_merge($routeMatchParams, $params);
}
$options['name'] = $name;
return (string) $this->router->assemble($params, $options);
}
/**
* Set the router to use for assembling.
*
* @param RouteStackInterface $router
* @return Url
* @throws Exception\InvalidArgumentException For invalid router types.
* @psalm-suppress RedundantConditionGivenDocblockType, DocblockTypeContradiction
*/
public function setRouter($router)
{
if (! $router instanceof RouteStackInterface) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a %s instance; received %s',
__METHOD__,
RouteStackInterface::class,
is_object($router) ? get_class($router) : gettype($router)
));
}
$this->router = $router;
return $this;
}
/**
* Set route match returned by the router.
*
* @param RouteMatch $routeMatch
* @return Url
* @psalm-suppress RedundantConditionGivenDocblockType, DocblockTypeContradiction
*/
public function setRouteMatch($routeMatch)
{
if (! $routeMatch instanceof RouteMatch) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a %s instance; received %s',
__METHOD__,
RouteMatch::class,
is_object($routeMatch) ? get_class($routeMatch) : gettype($routeMatch)
));
}
$this->routeMatch = $routeMatch;
return $this;
}
}