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