PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Libs/Zend/Controller/Router/Rewrite.php

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