PageRenderTime 23ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/ railoapacheportable/php/PEAR/Zend/Controller/Router/Rewrite.php

http://railoapacheportable.googlecode.com/
PHP | 484 lines | 224 code | 65 blank | 195 comment | 39 complexity | c1a2060abede6c5d5057e42903f66c38 MD5 | raw file
Possible License(s): BSD-2-Clause, Apache-2.0, EPL-1.0, LGPL-3.0, GPL-3.0, AGPL-1.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, GPL-2.0, LGPL-2.1, BSD-3-Clause, AGPL-3.0, CC-BY-SA-3.0
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Controller
  17. * @subpackage Router
  18. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @version $Id: Rewrite.php 16644 2009-07-11 14:12:17Z dasprid $
  20. * @license http://framework.zend.com/license/new-bsd New BSD License
  21. */
  22. /** Zend_Controller_Router_Abstract */
  23. require_once 'Zend/Controller/Router/Abstract.php';
  24. /** Zend_Controller_Router_Route */
  25. require_once 'Zend/Controller/Router/Route.php';
  26. /**
  27. * Ruby routing based Router.
  28. *
  29. * @package Zend_Controller
  30. * @subpackage Router
  31. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  32. * @license http://framework.zend.com/license/new-bsd New BSD License
  33. * @see http://manuals.rubyonrails.com/read/chapter/65
  34. */
  35. class Zend_Controller_Router_Rewrite extends Zend_Controller_Router_Abstract
  36. {
  37. /**
  38. * Whether or not to use default routes
  39. *
  40. * @var boolean
  41. */
  42. protected $_useDefaultRoutes = true;
  43. /**
  44. * Array of routes to match against
  45. *
  46. * @var array
  47. */
  48. protected $_routes = array();
  49. /**
  50. * Currently matched route
  51. *
  52. * @var Zend_Controller_Router_Route_Interface
  53. */
  54. protected $_currentRoute = null;
  55. /**
  56. * Global parameters given to all routes
  57. *
  58. * @var array
  59. */
  60. protected $_globalParams = array();
  61. /**
  62. * Separator to use with chain names
  63. *
  64. * @var string
  65. */
  66. protected $_chainNameSeparator = '-';
  67. /**
  68. * Add default routes which are used to mimic basic router behaviour
  69. *
  70. * @return Zend_Controller_Router_Rewrite
  71. */
  72. public function addDefaultRoutes()
  73. {
  74. if (!$this->hasRoute('default')) {
  75. $dispatcher = $this->getFrontController()->getDispatcher();
  76. $request = $this->getFrontController()->getRequest();
  77. require_once 'Zend/Controller/Router/Route/Module.php';
  78. $compat = new Zend_Controller_Router_Route_Module(array(), $dispatcher, $request);
  79. $this->_routes = array_merge(array('default' => $compat), $this->_routes);
  80. }
  81. return $this;
  82. }
  83. /**
  84. * Add route to the route chain
  85. *
  86. * If route contains method setRequest(), it is initialized with a request object
  87. *
  88. * @param string $name Name of the route
  89. * @param Zend_Controller_Router_Route_Interface $route Instance of the route
  90. * @return Zend_Controller_Router_Rewrite
  91. */
  92. public function addRoute($name, Zend_Controller_Router_Route_Interface $route)
  93. {
  94. if (method_exists($route, 'setRequest')) {
  95. $route->setRequest($this->getFrontController()->getRequest());
  96. }
  97. $this->_routes[$name] = $route;
  98. return $this;
  99. }
  100. /**
  101. * Add routes to the route chain
  102. *
  103. * @param array $routes Array of routes with names as keys and routes as values
  104. * @return Zend_Controller_Router_Rewrite
  105. */
  106. public function addRoutes($routes) {
  107. foreach ($routes as $name => $route) {
  108. $this->addRoute($name, $route);
  109. }
  110. return $this;
  111. }
  112. /**
  113. * Create routes out of Zend_Config configuration
  114. *
  115. * Example INI:
  116. * routes.archive.route = "archive/:year/*"
  117. * routes.archive.defaults.controller = archive
  118. * routes.archive.defaults.action = show
  119. * routes.archive.defaults.year = 2000
  120. * routes.archive.reqs.year = "\d+"
  121. *
  122. * routes.news.type = "Zend_Controller_Router_Route_Static"
  123. * routes.news.route = "news"
  124. * routes.news.defaults.controller = "news"
  125. * routes.news.defaults.action = "list"
  126. *
  127. * And finally after you have created a Zend_Config with above ini:
  128. * $router = new Zend_Controller_Router_Rewrite();
  129. * $router->addConfig($config, 'routes');
  130. *
  131. * @param Zend_Config $config Configuration object
  132. * @param string $section Name of the config section containing route's definitions
  133. * @throws Zend_Controller_Router_Exception
  134. * @return Zend_Controller_Router_Rewrite
  135. */
  136. public function addConfig(Zend_Config $config, $section = null)
  137. {
  138. if ($section !== null) {
  139. if ($config->{$section} === null) {
  140. require_once 'Zend/Controller/Router/Exception.php';
  141. throw new Zend_Controller_Router_Exception("No route configuration in section '{$section}'");
  142. }
  143. $config = $config->{$section};
  144. }
  145. foreach ($config as $name => $info) {
  146. $route = $this->_getRouteFromConfig($info);
  147. if ($route instanceof Zend_Controller_Router_Route_Chain) {
  148. if (!isset($info->chain)) {
  149. require_once 'Zend/Controller/Router/Exception.php';
  150. throw new Zend_Controller_Router_Exception("No chain defined");
  151. }
  152. if ($info->chain instanceof Zend_Config) {
  153. $childRouteNames = $info->chain;
  154. } else {
  155. $childRouteNames = explode(',', $info->chain);
  156. }
  157. foreach ($childRouteNames as $childRouteName) {
  158. $childRoute = $this->getRoute(trim($childRouteName));
  159. $route->chain($childRoute);
  160. }
  161. $this->addRoute($name, $route);
  162. } elseif (isset($info->chains) && $info->chains instanceof Zend_Config) {
  163. $this->_addChainRoutesFromConfig($name, $route, $info->chains);
  164. } else {
  165. $this->addRoute($name, $route);
  166. }
  167. }
  168. return $this;
  169. }
  170. /**
  171. * Get a route frm a config instance
  172. *
  173. * @param Zend_Config $info
  174. * @return Zend_Controller_Router_Route_Interface
  175. */
  176. protected function _getRouteFromConfig(Zend_Config $info)
  177. {
  178. $class = (isset($info->type)) ? $info->type : 'Zend_Controller_Router_Route';
  179. if (!class_exists($class)) {
  180. require_once 'Zend/Loader.php';
  181. Zend_Loader::loadClass($class);
  182. }
  183. $route = call_user_func(array($class, 'getInstance'), $info);
  184. if (isset($info->abstract) && $info->abstract && method_exists($route, 'isAbstract')) {
  185. $route->isAbstract(true);
  186. }
  187. return $route;
  188. }
  189. /**
  190. * Add chain routes from a config route
  191. *
  192. * @param string $name
  193. * @param Zend_Controller_Router_Route_Interface $route
  194. * @param Zend_Config $childRoutesInfo
  195. * @return void
  196. */
  197. protected function _addChainRoutesFromConfig($name,
  198. Zend_Controller_Router_Route_Interface $route,
  199. Zend_Config $childRoutesInfo)
  200. {
  201. foreach ($childRoutesInfo as $childRouteName => $childRouteInfo) {
  202. if (is_string($childRouteInfo)) {
  203. $childRouteName = $childRouteInfo;
  204. $childRoute = $this->getRoute($childRouteName);
  205. } else {
  206. $childRoute = $this->_getRouteFromConfig($childRouteInfo);
  207. }
  208. if ($route instanceof Zend_Controller_Router_Route_Chain) {
  209. $chainRoute = clone $route;
  210. $chainRoute->chain($childRoute);
  211. } else {
  212. $chainRoute = $route->chain($childRoute);
  213. }
  214. $chainName = $name . $this->_chainNameSeparator . $childRouteName;
  215. if (isset($childRouteInfo->chains)) {
  216. $this->_addChainRoutesFromConfig($chainName, $chainRoute, $childRouteInfo->chains);
  217. } else {
  218. $this->addRoute($chainName, $chainRoute);
  219. }
  220. }
  221. }
  222. /**
  223. * Remove a route from the route chain
  224. *
  225. * @param string $name Name of the route
  226. * @throws Zend_Controller_Router_Exception
  227. * @return Zend_Controller_Router_Rewrite
  228. */
  229. public function removeRoute($name)
  230. {
  231. if (!isset($this->_routes[$name])) {
  232. require_once 'Zend/Controller/Router/Exception.php';
  233. throw new Zend_Controller_Router_Exception("Route $name is not defined");
  234. }
  235. unset($this->_routes[$name]);
  236. return $this;
  237. }
  238. /**
  239. * Remove all standard default routes
  240. *
  241. * @param Zend_Controller_Router_Route_Interface Route
  242. * @return Zend_Controller_Router_Rewrite
  243. */
  244. public function removeDefaultRoutes()
  245. {
  246. $this->_useDefaultRoutes = false;
  247. return $this;
  248. }
  249. /**
  250. * Check if named route exists
  251. *
  252. * @param string $name Name of the route
  253. * @return boolean
  254. */
  255. public function hasRoute($name)
  256. {
  257. return isset($this->_routes[$name]);
  258. }
  259. /**
  260. * Retrieve a named route
  261. *
  262. * @param string $name Name of the route
  263. * @throws Zend_Controller_Router_Exception
  264. * @return Zend_Controller_Router_Route_Interface Route object
  265. */
  266. public function getRoute($name)
  267. {
  268. if (!isset($this->_routes[$name])) {
  269. require_once 'Zend/Controller/Router/Exception.php';
  270. throw new Zend_Controller_Router_Exception("Route $name is not defined");
  271. }
  272. return $this->_routes[$name];
  273. }
  274. /**
  275. * Retrieve a currently matched route
  276. *
  277. * @throws Zend_Controller_Router_Exception
  278. * @return Zend_Controller_Router_Route_Interface Route object
  279. */
  280. public function getCurrentRoute()
  281. {
  282. if (!isset($this->_currentRoute)) {
  283. require_once 'Zend/Controller/Router/Exception.php';
  284. throw new Zend_Controller_Router_Exception("Current route is not defined");
  285. }
  286. return $this->getRoute($this->_currentRoute);
  287. }
  288. /**
  289. * Retrieve a name of currently matched route
  290. *
  291. * @throws Zend_Controller_Router_Exception
  292. * @return Zend_Controller_Router_Route_Interface Route object
  293. */
  294. public function getCurrentRouteName()
  295. {
  296. if (!isset($this->_currentRoute)) {
  297. require_once 'Zend/Controller/Router/Exception.php';
  298. throw new Zend_Controller_Router_Exception("Current route is not defined");
  299. }
  300. return $this->_currentRoute;
  301. }
  302. /**
  303. * Retrieve an array of routes added to the route chain
  304. *
  305. * @return array All of the defined routes
  306. */
  307. public function getRoutes()
  308. {
  309. return $this->_routes;
  310. }
  311. /**
  312. * Find a matching route to the current PATH_INFO and inject
  313. * returning values to the Request object.
  314. *
  315. * @throws Zend_Controller_Router_Exception
  316. * @return Zend_Controller_Request_Abstract Request object
  317. */
  318. public function route(Zend_Controller_Request_Abstract $request)
  319. {
  320. if (!$request instanceof Zend_Controller_Request_Http) {
  321. require_once 'Zend/Controller/Router/Exception.php';
  322. throw new Zend_Controller_Router_Exception('Zend_Controller_Router_Rewrite requires a Zend_Controller_Request_Http-based request object');
  323. }
  324. if ($this->_useDefaultRoutes) {
  325. $this->addDefaultRoutes();
  326. }
  327. // Find the matching route
  328. foreach (array_reverse($this->_routes) as $name => $route) {
  329. // TODO: Should be an interface method. Hack for 1.0 BC
  330. if (method_exists($route, 'isAbstract') && $route->isAbstract()) {
  331. continue;
  332. }
  333. // TODO: Should be an interface method. Hack for 1.0 BC
  334. if (!method_exists($route, 'getVersion') || $route->getVersion() == 1) {
  335. $match = $request->getPathInfo();
  336. } else {
  337. $match = $request;
  338. }
  339. if ($params = $route->match($match)) {
  340. $this->_setRequestParams($request, $params);
  341. $this->_currentRoute = $name;
  342. break;
  343. }
  344. }
  345. return $request;
  346. }
  347. protected function _setRequestParams($request, $params)
  348. {
  349. foreach ($params as $param => $value) {
  350. $request->setParam($param, $value);
  351. if ($param === $request->getModuleKey()) {
  352. $request->setModuleName($value);
  353. }
  354. if ($param === $request->getControllerKey()) {
  355. $request->setControllerName($value);
  356. }
  357. if ($param === $request->getActionKey()) {
  358. $request->setActionName($value);
  359. }
  360. }
  361. }
  362. /**
  363. * Generates a URL path that can be used in URL creation, redirection, etc.
  364. *
  365. * @param array $userParams Options passed by a user used to override parameters
  366. * @param mixed $name The name of a Route to use
  367. * @param bool $reset Whether to reset to the route defaults ignoring URL params
  368. * @param bool $encode Tells to encode URL parts on output
  369. * @throws Zend_Controller_Router_Exception
  370. * @return string Resulting absolute URL path
  371. */
  372. public function assemble($userParams, $name = null, $reset = false, $encode = true)
  373. {
  374. if ($name == null) {
  375. try {
  376. $name = $this->getCurrentRouteName();
  377. } catch (Zend_Controller_Router_Exception $e) {
  378. $name = 'default';
  379. }
  380. }
  381. $params = array_merge($this->_globalParams, $userParams);
  382. $route = $this->getRoute($name);
  383. $url = $route->assemble($params, $reset, $encode);
  384. if (!preg_match('|^[a-z]+://|', $url)) {
  385. $url = rtrim($this->getFrontController()->getBaseUrl(), '/') . '/' . $url;
  386. }
  387. return $url;
  388. }
  389. /**
  390. * Set a global parameter
  391. *
  392. * @param string $name
  393. * @param mixed $value
  394. * @return Zend_Controller_Router_Rewrite
  395. */
  396. public function setGlobalParam($name, $value)
  397. {
  398. $this->_globalParams[$name] = $value;
  399. return $this;
  400. }
  401. /**
  402. * Set the separator to use with chain names
  403. *
  404. * @param string $separator The separator to use
  405. * @return Zend_Controller_Router_Rewrite
  406. */
  407. public function setChainNameSeparator($separator) {
  408. $this->_chainNameSeparator = $separator;
  409. return $this;
  410. }
  411. /**
  412. * Get the separator to use for chain names
  413. *
  414. * @return string
  415. */
  416. public function getChainNameSeparator() {
  417. return $this->_chainNameSeparator;
  418. }
  419. }