routePluginManager = $routePlugins; if (!$route instanceof RouteInterface) { $route = $this->routeFromArray($route); } if ($route instanceof self) { throw new Exception\InvalidArgumentException('Base route may not be a part route'); } $this->route = $route; $this->mayTerminate = $mayTerminate; $this->childRoutes = $childRoutes; $this->prototypes = $prototypes; $this->routes = new PriorityList(); } /** * factory(): defined by RouteInterface interface. * * @see \Zend\Router\RouteInterface::factory() * @param mixed $options * @return Part * @throws Exception\InvalidArgumentException */ public static function factory($options = []) { if ($options instanceof Traversable) { $options = ArrayUtils::iteratorToArray($options); } elseif (!is_array($options)) { throw new Exception\InvalidArgumentException(sprintf( '%s expects an array or Traversable set of options', __METHOD__ )); } if (!isset($options['route'])) { throw new Exception\InvalidArgumentException('Missing "route" in options array'); } if (!isset($options['route_plugins'])) { throw new Exception\InvalidArgumentException('Missing "route_plugins" in options array'); } if (!isset($options['prototypes'])) { $options['prototypes'] = null; } if (!isset($options['may_terminate'])) { $options['may_terminate'] = false; } if (!isset($options['child_routes']) || !$options['child_routes']) { $options['child_routes'] = null; } if ($options['child_routes'] instanceof Traversable) { $options['child_routes'] = ArrayUtils::iteratorToArray($options['child_routes']); } return new static( $options['route'], $options['may_terminate'], $options['route_plugins'], $options['child_routes'], $options['prototypes'] ); } /** * match(): defined by RouteInterface interface. * * @see \Zend\Router\RouteInterface::match() * @param Request $request * @param integer|null $pathOffset * @param array $options * @return RouteMatch|null */ public function match(Request $request, $pathOffset = null, array $options = []) { if ($pathOffset === null) { $pathOffset = 0; } $match = $this->route->match($request, $pathOffset, $options); if ($match !== null && method_exists($request, 'getUri')) { if ($this->childRoutes !== null) { $this->addRoutes($this->childRoutes); $this->childRoutes = null; } $nextOffset = $pathOffset + $match->getLength(); $uri = $request->getUri(); $pathLength = strlen($uri->getPath()); if ($this->mayTerminate && $nextOffset === $pathLength) { $query = $uri->getQuery(); if ('' == trim($query) || !$this->hasQueryChild()) { return $match; } } if (isset($options['translator']) && !isset($options['locale']) && null !== ($locale = $match->getParam('locale', null)) ) { $options['locale'] = $locale; } foreach ($this->routes as $name => $route) { if (($subMatch = $route->match($request, $nextOffset, $options)) instanceof RouteMatch) { if ($match->getLength() + $subMatch->getLength() + $pathOffset === $pathLength) { return $match->merge($subMatch)->setMatchedRouteName($name); } } } } return; } /** * assemble(): Defined by RouteInterface interface. * * @see \Zend\Router\RouteInterface::assemble() * @param array $params * @param array $options * @return mixed * @throws Exception\RuntimeException */ public function assemble(array $params = [], array $options = []) { if ($this->childRoutes !== null) { $this->addRoutes($this->childRoutes); $this->childRoutes = null; } $options['has_child'] = (isset($options['name'])); if (isset($options['translator']) && !isset($options['locale']) && isset($params['locale'])) { $options['locale'] = $params['locale']; } $path = $this->route->assemble($params, $options); $params = array_diff_key($params, array_flip($this->route->getAssembledParams())); if (!isset($options['name'])) { if (!$this->mayTerminate) { throw new Exception\RuntimeException('Part route may not terminate'); } else { return $path; } } unset($options['has_child']); $options['only_return_path'] = true; $path .= parent::assemble($params, $options); return $path; } /** * getAssembledParams(): defined by RouteInterface interface. * * @see RouteInterface::getAssembledParams * @return array */ public function getAssembledParams() { // Part routes may not occur as base route of other part routes, so we // don't have to return anything here. return []; } /** * Is one of the child routes a query route? * * @return bool */ protected function hasQueryChild() { foreach ($this->routes as $route) { if ($route instanceof Query) { return true; } } return false; } }