root/trunk/trax/vendor/trax/router.php

Revision 174, 6.7 KB (checked in by haas, 4 years ago)

ActionController? doc done

  • Property svn:keywords set to Id
Line 
1<?php
2/**
3 *  File containing the Router class
4 *
5 *  (PHP 5)
6 *
7 *  @package PHPonTrax
8 *  @version $Id$
9 *  @copyright (c) 2005 John Peterson
10 * 
11 *  Permission is hereby granted, free of charge, to any person obtaining
12 *  a copy of this software and associated documentation files (the
13 *  "Software"), to deal in the Software without restriction, including
14 *  without limitation the rights to use, copy, modify, merge, publish,
15 *  distribute, sublicense, and/or sell copies of the Software, and to
16 *  permit persons to whom the Software is furnished to do so, subject to
17 *  the following conditions:
18 *
19 *  The above copyright notice and this permission notice shall be
20 *  included in all copies or substantial portions of the Software.
21 *
22 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31/**
32 *  Convert a URL to an action
33 *  @tutorial PHPonTrax/Router.cls
34 */
35class Router {
36
37    /**
38     *  Route table
39     *
40     *  For a description of the structure, see
41     *  {@tutorial PHPonTrax/Router.cls#table the Router tutorial}.
42     *  Routes are added by calling {@link connect()} and looked up
43     *  by calling {@link find_route()}.
44     *  <b>FIXME:</b> Should we have a Route class to describe an
45     *  entry in the route table?
46     *  @var string[][]
47     */
48    private $routes = array();
49
50    /**
51     *  Last route found by a call to find_route()
52     *  @var string[]
53     */
54    private $selected_route = null;
55
56    /**
57     *  Default route path
58     *
59     *  This route path is added to the route table if the table is
60     *  empty when find_route() is called.
61     *  @var string constant
62     */
63    private $default_route_path = ":controller/:action/:id";
64
65    /**
66     *  Count of the number of elements in $routes
67     *  @var integer
68     */
69    public $routes_count = 0;
70
71    /**
72     *  Accessor method to return contents of $selected_route
73     *  @return string[] Contents of $selected_route
74     *  @uses $selected_route
75     */
76    function get_selected_route() {
77        return $this->selected_route;
78    }
79
80    /**
81     *  Accessor method to add a route to the route table
82     *
83     *  The route is added to the end of
84     *  {@link $routes the route table}. If $params is not an array,
85     *  NULL is stored in the route parameter area.
86     *  @param string $path
87     *  @param mixed[] $params
88     *  @uses $routes
89     *  @uses $routes_count
90     */
91    function connect($path, $params = null) {
92        if(!is_array($params)) $params = null;
93        $this->routes[$this->routes_count]['path'] = $path;
94        $this->routes[$this->routes_count]['params'] = $params;
95        $this->routes_count = count($this->routes);
96    }
97
98    /**
99     *  Find first route in route table with path that matches argument
100     *
101     *  First, assure that the route table {@link $routes} has at
102     *  least one route by adding
103     *  {@link $default_route_path the default route} if the table is
104     *  empty.  Then search the table to find the first route in the
105     *  table whose path matches the argument $url. If $url is an
106     *  empty string, it matches a path that is an empty string.
107     *  Otherwise, try to match $url to the path part of the table
108     *  entry according to
109     *  {@link http://www.php.net/manual/en/ref.pcre.php Perl regular expression}
110     *  rules.  If a matching route is found, return it any to the caller, and
111     *  also save a copy in {@link $selected_route}; if no matching
112     *  route is found return null.
113     *  @param string $url
114     *  @uses build_route_regexp()
115     *  @uses $default_route_path
116     *  @uses $routes
117     *  @uses $routes_count
118     *  @uses $selected_route
119     *  @return mixed Matching route or null.  Path is in return['path'],
120     *                   params in return['params'],
121     */
122    function find_route($url) {
123        //error_log('url='.$url);
124        // ensure at least one route (the default route) exists
125        if($this->routes_count == 0) {
126            $this->connect($this->default_route_path);
127        }
128
129        $this->selected_route = null;
130
131        foreach($this->routes as $route) {
132            unset($route_regexp);
133            unset($reg_exp);
134            $route_regexp = $this->build_route_regexp($route['path']);
135            //error_log("route regexp=/$route_regexp/");
136            if($url == "" && $route_regexp == "") {
137                //error_log('selected');
138                $this->selected_route = $route;
139                break;
140            } elseif(preg_match("/$route_regexp/",$url) && $route_regexp != "") {
141                //error_log('selected');
142                $this->selected_route = $route;
143                break;
144            } elseif($route['path'] == $this->default_route_path) {
145                //error_log('defaulted');
146                $this->selected_route = $route;
147                break;
148            }
149        }
150        //error_log('selected route='.var_export($this->selected_route,true));
151        return $this->selected_route;
152    }                                 // function find_route($url)
153
154    /**
155     *  Build a regular expression that matches a route
156     *
157     *  @todo <b>FIXME:</b> Should this method be private?
158     *  @todo <b>FIXME:</b> Shouldn't the regexp match be the same as
159     *  for a PHP variable name? '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
160     *  @param string $route_path  A route path.
161     *  @return string Regular expression that matches the route in
162     *                $route_path
163     */
164    function build_route_regexp($route_path) {
165        //        echo "entering build_route_regexp(), \$route_path is '$route_path'\n";
166
167        $route_regexp = null;
168
169        if(!is_array($route_path)) {
170            $route_path = explode("/",$route_path);
171        }
172        //error_log("route path:\n".var_export($route_path,true));
173        if(count($route_path) > 0) {
174            foreach($route_path as $path_element) {
175                if(preg_match('/:[a-z0-9_\-]+/',$path_element)) {
176                    $reg_exp[] = '[a-z0-9_\-]+';
177                } else {
178                    $reg_exp[] = $path_element;
179                }
180            }
181            if(is_array($reg_exp)) {
182                $route_regexp = "^".implode("\/",$reg_exp)."$";
183            }
184        }
185        return $route_regexp;
186    }
187
188}
189
190// -- set Emacs parameters --
191// Local variables:
192// tab-width: 4
193// c-basic-offset: 4
194// c-hanging-comment-ender-p: nil
195// indent-tabs-mode: nil
196// End:
197?>
Note: See TracBrowser for help on using the browser.