PageRenderTime 29ms CodeModel.GetById 12ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 1ms

/src/frapi/library/Zend/Controller/Router/Rewrite.php

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