3 * @link http://github.com/zendframework/zend-router for the canonical source repository
4 * @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
5 * @license http://framework.zend.com/license/new-bsd New BSD License
8 namespace Zend\Router\Http
;
12 use Zend\Router\Exception
;
13 use Zend\Router\PriorityList
;
14 use Zend\Router\RoutePluginManager
;
15 use Zend\Stdlib\ArrayUtils
;
16 use Zend\Stdlib\RequestInterface
as Request
;
21 class Chain
extends TreeRouteStack
implements RouteInterface
28 protected $chainRoutes;
31 * List of assembled parameters.
35 protected $assembledParams = [];
38 * Create a new part route.
40 * @param array $routes
41 * @param RoutePluginManager $routePlugins
42 * @param ArrayObject|null $prototypes
44 public function __construct(array $routes, RoutePluginManager
$routePlugins, ArrayObject
$prototypes = null)
46 $this->chainRoutes
= array_reverse($routes);
47 $this->routePluginManager
= $routePlugins;
48 $this->routes
= new PriorityList();
49 $this->prototypes
= $prototypes;
53 * factory(): defined by RouteInterface interface.
55 * @see \Zend\Router\RouteInterface::factory()
56 * @param mixed $options
57 * @throws Exception\InvalidArgumentException
60 public static function factory($options = [])
62 if ($options instanceof Traversable
) {
63 $options = ArrayUtils
::iteratorToArray($options);
64 } elseif (!is_array($options)) {
65 throw new Exception\
InvalidArgumentException(sprintf(
66 '%s expects an array or Traversable set of options',
71 if (!isset($options['routes'])) {
72 throw new Exception\
InvalidArgumentException('Missing "routes" in options array');
75 if (!isset($options['prototypes'])) {
76 $options['prototypes'] = null;
79 if ($options['routes'] instanceof Traversable
) {
80 $options['routes'] = ArrayUtils
::iteratorToArray($options['child_routes']);
83 if (!isset($options['route_plugins'])) {
84 throw new Exception\
InvalidArgumentException('Missing "route_plugins" in options array');
89 $options['route_plugins'],
90 $options['prototypes']
95 * match(): defined by RouteInterface interface.
97 * @see \Zend\Router\RouteInterface::match()
98 * @param Request $request
99 * @param int|null $pathOffset
100 * @param array $options
101 * @return RouteMatch|null
103 public function match(Request
$request, $pathOffset = null, array $options = [])
105 if (!method_exists($request, 'getUri')) {
109 if ($pathOffset === null) {
110 $mustTerminate = true;
113 $mustTerminate = false;
116 if ($this->chainRoutes
!== null) {
117 $this->addRoutes($this->chainRoutes
);
118 $this->chainRoutes
= null;
121 $match = new RouteMatch([]);
122 $uri = $request->getUri();
123 $pathLength = strlen($uri->getPath());
125 foreach ($this->routes
as $route) {
126 $subMatch = $route->match($request, $pathOffset, $options);
128 if ($subMatch === null) {
132 $match->merge($subMatch);
133 $pathOffset +
= $subMatch->getLength();
136 if ($mustTerminate && $pathOffset !== $pathLength) {
144 * assemble(): Defined by RouteInterface interface.
146 * @see \Zend\Router\RouteInterface::assemble()
147 * @param array $params
148 * @param array $options
151 public function assemble(array $params = [], array $options = [])
153 if ($this->chainRoutes
!== null) {
154 $this->addRoutes($this->chainRoutes
);
155 $this->chainRoutes
= null;
158 $this->assembledParams
= [];
160 $routes = ArrayUtils
::iteratorToArray($this->routes
);
163 $lastRouteKey = key($routes);
166 foreach ($routes as $key => $route) {
167 $chainOptions = $options;
168 $hasChild = isset($options['has_child']) ?
$options['has_child'] : false;
170 $chainOptions['has_child'] = ($hasChild ||
$key !== $lastRouteKey);
172 $path .= $route->assemble($params, $chainOptions);
173 $params = array_diff_key($params, array_flip($route->getAssembledParams()));
175 $this->assembledParams +
= $route->getAssembledParams();
182 * getAssembledParams(): defined by RouteInterface interface.
184 * @see RouteInterface::getAssembledParams
187 public function getAssembledParams()
189 return $this->assembledParams
;