PHP on T R A X
Rapid Application Development Made Easy

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

Revision 174, 6.7 kB (checked in by haas, 3 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  */
35 class 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.