3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Mvc\Router\Http
;
14 use Zend\Mvc\Router\Exception
;
15 use Zend\Mvc\Router\PriorityList
;
16 use Zend\Mvc\Router\RoutePluginManager
;
17 use Zend\Stdlib\ArrayUtils
;
18 use Zend\Stdlib\RequestInterface
as Request
;
23 class Part
extends TreeRouteStack
implements RouteInterface
26 * RouteInterface to match.
33 * Whether the route may terminate.
37 protected $mayTerminate;
44 protected $childRoutes;
47 * Create a new part route.
50 * @param bool $mayTerminate
51 * @param RoutePluginManager $routePlugins
52 * @param array|null $childRoutes
53 * @param ArrayObject|null $prototypes
54 * @throws Exception\InvalidArgumentException
56 public function __construct($route, $mayTerminate, RoutePluginManager
$routePlugins, array $childRoutes = null, ArrayObject
$prototypes = null)
58 $this->routePluginManager
= $routePlugins;
60 if (!$route instanceof RouteInterface
) {
61 $route = $this->routeFromArray($route);
64 if ($route instanceof self
) {
65 throw new Exception\
InvalidArgumentException('Base route may not be a part route');
68 $this->route
= $route;
69 $this->mayTerminate
= $mayTerminate;
70 $this->childRoutes
= $childRoutes;
71 $this->prototypes
= $prototypes;
72 $this->routes
= new PriorityList();
76 * factory(): defined by RouteInterface interface.
78 * @see \Zend\Mvc\Router\RouteInterface::factory()
79 * @param mixed $options
81 * @throws Exception\InvalidArgumentException
83 public static function factory($options = array())
85 if ($options instanceof Traversable
) {
86 $options = ArrayUtils
::iteratorToArray($options);
87 } elseif (!is_array($options)) {
88 throw new Exception\
InvalidArgumentException(__METHOD__
. ' expects an array or Traversable set of options');
91 if (!isset($options['route'])) {
92 throw new Exception\
InvalidArgumentException('Missing "route" in options array');
95 if (!isset($options['route_plugins'])) {
96 throw new Exception\
InvalidArgumentException('Missing "route_plugins" in options array');
99 if (!isset($options['prototypes'])) {
100 $options['prototypes'] = null;
103 if (!isset($options['may_terminate'])) {
104 $options['may_terminate'] = false;
107 if (!isset($options['child_routes']) ||
!$options['child_routes']) {
108 $options['child_routes'] = null;
111 if ($options['child_routes'] instanceof Traversable
) {
112 $options['child_routes'] = ArrayUtils
::iteratorToArray($options['child_routes']);
117 $options['may_terminate'],
118 $options['route_plugins'],
119 $options['child_routes'],
120 $options['prototypes']
125 * match(): defined by RouteInterface interface.
127 * @see \Zend\Mvc\Router\RouteInterface::match()
128 * @param Request $request
129 * @param integer|null $pathOffset
130 * @param array $options
131 * @return RouteMatch|null
133 public function match(Request
$request, $pathOffset = null, array $options = array())
135 if ($pathOffset === null) {
139 $match = $this->route
->match($request, $pathOffset, $options);
141 if ($match !== null && method_exists($request, 'getUri')) {
142 if ($this->childRoutes
!== null) {
143 $this->addRoutes($this->childRoutes
);
144 $this->childRoutes
= null;
147 $nextOffset = $pathOffset +
$match->getLength();
149 $uri = $request->getUri();
150 $pathLength = strlen($uri->getPath());
152 if ($this->mayTerminate
&& $nextOffset === $pathLength) {
153 $query = $uri->getQuery();
154 if ('' == trim($query) ||
!$this->hasQueryChild()) {
159 foreach ($this->routes
as $name => $route) {
160 if (($subMatch = $route->match($request, $nextOffset, $options)) instanceof RouteMatch
) {
161 if ($match->getLength() +
$subMatch->getLength() +
$pathOffset === $pathLength) {
162 return $match->merge($subMatch)->setMatchedRouteName($name);
172 * assemble(): Defined by RouteInterface interface.
174 * @see \Zend\Mvc\Router\RouteInterface::assemble()
175 * @param array $params
176 * @param array $options
178 * @throws Exception\RuntimeException
180 public function assemble(array $params = array(), array $options = array())
182 if ($this->childRoutes
!== null) {
183 $this->addRoutes($this->childRoutes
);
184 $this->childRoutes
= null;
187 $options['has_child'] = (isset($options['name']));
189 $path = $this->route
->assemble($params, $options);
190 $params = array_diff_key($params, array_flip($this->route
->getAssembledParams()));
192 if (!isset($options['name'])) {
193 if (!$this->mayTerminate
) {
194 throw new Exception\
RuntimeException('Part route may not terminate');
200 unset($options['has_child']);
201 $options['only_return_path'] = true;
202 $path .= parent
::assemble($params, $options);
208 * getAssembledParams(): defined by RouteInterface interface.
210 * @see RouteInterface::getAssembledParams
213 public function getAssembledParams()
215 // Part routes may not occur as base route of other part routes, so we
216 // don't have to return anything here.
221 * Is one of the child routes a query route?
225 protected function hasQueryChild()
227 foreach ($this->routes
as $route) {
228 if ($route instanceof Query
) {