PageRenderTime 24ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/library/Zend/Mvc/Router/Http/Part.php

http://github.com/zendframework/zf2
PHP | 242 lines | 133 code | 35 blank | 74 comment | 32 complexity | 8d8758aa23da3a397747aadc48a7fa66 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Mvc\Router\Http;
  10. use ArrayObject;
  11. use Traversable;
  12. use Zend\Mvc\Router\Exception;
  13. use Zend\Mvc\Router\PriorityList;
  14. use Zend\Mvc\Router\RoutePluginManager;
  15. use Zend\Stdlib\ArrayUtils;
  16. use Zend\Stdlib\RequestInterface as Request;
  17. /**
  18. * Part route.
  19. */
  20. class Part extends TreeRouteStack implements RouteInterface
  21. {
  22. /**
  23. * RouteInterface to match.
  24. *
  25. * @var RouteInterface
  26. */
  27. protected $route;
  28. /**
  29. * Whether the route may terminate.
  30. *
  31. * @var bool
  32. */
  33. protected $mayTerminate;
  34. /**
  35. * Child routes.
  36. *
  37. * @var mixed
  38. */
  39. protected $childRoutes;
  40. /**
  41. * Create a new part route.
  42. *
  43. * @param mixed $route
  44. * @param bool $mayTerminate
  45. * @param RoutePluginManager $routePlugins
  46. * @param array|null $childRoutes
  47. * @param ArrayObject|null $prototypes
  48. * @throws Exception\InvalidArgumentException
  49. */
  50. public function __construct($route, $mayTerminate, RoutePluginManager $routePlugins, array $childRoutes = null, ArrayObject $prototypes = null)
  51. {
  52. $this->routePluginManager = $routePlugins;
  53. if (!$route instanceof RouteInterface) {
  54. $route = $this->routeFromArray($route);
  55. }
  56. if ($route instanceof self) {
  57. throw new Exception\InvalidArgumentException('Base route may not be a part route');
  58. }
  59. $this->route = $route;
  60. $this->mayTerminate = $mayTerminate;
  61. $this->childRoutes = $childRoutes;
  62. $this->prototypes = $prototypes;
  63. $this->routes = new PriorityList();
  64. }
  65. /**
  66. * factory(): defined by RouteInterface interface.
  67. *
  68. * @see \Zend\Mvc\Router\RouteInterface::factory()
  69. * @param mixed $options
  70. * @return Part
  71. * @throws Exception\InvalidArgumentException
  72. */
  73. public static function factory($options = array())
  74. {
  75. if ($options instanceof Traversable) {
  76. $options = ArrayUtils::iteratorToArray($options);
  77. } elseif (!is_array($options)) {
  78. throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable set of options');
  79. }
  80. if (!isset($options['route'])) {
  81. throw new Exception\InvalidArgumentException('Missing "route" in options array');
  82. }
  83. if (!isset($options['route_plugins'])) {
  84. throw new Exception\InvalidArgumentException('Missing "route_plugins" in options array');
  85. }
  86. if (!isset($options['prototypes'])) {
  87. $options['prototypes'] = null;
  88. }
  89. if (!isset($options['may_terminate'])) {
  90. $options['may_terminate'] = false;
  91. }
  92. if (!isset($options['child_routes']) || !$options['child_routes']) {
  93. $options['child_routes'] = null;
  94. }
  95. if ($options['child_routes'] instanceof Traversable) {
  96. $options['child_routes'] = ArrayUtils::iteratorToArray($options['child_routes']);
  97. }
  98. return new static(
  99. $options['route'],
  100. $options['may_terminate'],
  101. $options['route_plugins'],
  102. $options['child_routes'],
  103. $options['prototypes']
  104. );
  105. }
  106. /**
  107. * match(): defined by RouteInterface interface.
  108. *
  109. * @see \Zend\Mvc\Router\RouteInterface::match()
  110. * @param Request $request
  111. * @param integer|null $pathOffset
  112. * @param array $options
  113. * @return RouteMatch|null
  114. */
  115. public function match(Request $request, $pathOffset = null, array $options = array())
  116. {
  117. if ($pathOffset === null) {
  118. $pathOffset = 0;
  119. }
  120. $match = $this->route->match($request, $pathOffset, $options);
  121. if ($match !== null && method_exists($request, 'getUri')) {
  122. if ($this->childRoutes !== null) {
  123. $this->addRoutes($this->childRoutes);
  124. $this->childRoutes = null;
  125. }
  126. $nextOffset = $pathOffset + $match->getLength();
  127. $uri = $request->getUri();
  128. $pathLength = strlen($uri->getPath());
  129. if ($this->mayTerminate && $nextOffset === $pathLength) {
  130. $query = $uri->getQuery();
  131. if ('' == trim($query) || !$this->hasQueryChild()) {
  132. return $match;
  133. }
  134. }
  135. if (isset($options['translator']) && !isset($options['locale']) && null !== ($locale = $match->getParam('locale', null))) {
  136. $options['locale'] = $locale;
  137. }
  138. foreach ($this->routes as $name => $route) {
  139. if (($subMatch = $route->match($request, $nextOffset, $options)) instanceof RouteMatch) {
  140. if ($match->getLength() + $subMatch->getLength() + $pathOffset === $pathLength) {
  141. return $match->merge($subMatch)->setMatchedRouteName($name);
  142. }
  143. }
  144. }
  145. }
  146. return;
  147. }
  148. /**
  149. * assemble(): Defined by RouteInterface interface.
  150. *
  151. * @see \Zend\Mvc\Router\RouteInterface::assemble()
  152. * @param array $params
  153. * @param array $options
  154. * @return mixed
  155. * @throws Exception\RuntimeException
  156. */
  157. public function assemble(array $params = array(), array $options = array())
  158. {
  159. if ($this->childRoutes !== null) {
  160. $this->addRoutes($this->childRoutes);
  161. $this->childRoutes = null;
  162. }
  163. $options['has_child'] = (isset($options['name']));
  164. if (isset($options['translator']) && !isset($options['locale']) && isset($params['locale'])) {
  165. $options['locale'] = $params['locale'];
  166. }
  167. $path = $this->route->assemble($params, $options);
  168. $params = array_diff_key($params, array_flip($this->route->getAssembledParams()));
  169. if (!isset($options['name'])) {
  170. if (!$this->mayTerminate) {
  171. throw new Exception\RuntimeException('Part route may not terminate');
  172. } else {
  173. return $path;
  174. }
  175. }
  176. unset($options['has_child']);
  177. $options['only_return_path'] = true;
  178. $path .= parent::assemble($params, $options);
  179. return $path;
  180. }
  181. /**
  182. * getAssembledParams(): defined by RouteInterface interface.
  183. *
  184. * @see RouteInterface::getAssembledParams
  185. * @return array
  186. */
  187. public function getAssembledParams()
  188. {
  189. // Part routes may not occur as base route of other part routes, so we
  190. // don't have to return anything here.
  191. return array();
  192. }
  193. /**
  194. * Is one of the child routes a query route?
  195. *
  196. * @return bool
  197. */
  198. protected function hasQueryChild()
  199. {
  200. foreach ($this->routes as $route) {
  201. if ($route instanceof Query) {
  202. return true;
  203. }
  204. }
  205. return false;
  206. }
  207. }