Location: PHPKode > projects > PHP on Trax > vendor/trax/router.php
<?php
/**
 *  File containing the Router class
 *
 *  (PHP 5)
 *
 *  @package PHPonTrax
 *  @version $Id: router.php 174 2006-03-14 04:10:15Z haas $
 *  @copyright (c) 2005 John Peterson
 *  
 *  Permission is hereby granted, free of charge, to any person obtaining
 *  a copy of this software and associated documentation files (the
 *  "Software"), to deal in the Software without restriction, including
 *  without limitation the rights to use, copy, modify, merge, publish,
 *  distribute, sublicense, and/or sell copies of the Software, and to
 *  permit persons to whom the Software is furnished to do so, subject to
 *  the following conditions:
 *
 *  The above copyright notice and this permission notice shall be
 *  included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 *  Convert a URL to an action
 *  @tutorial PHPonTrax/Router.cls
 */
class Router {

    /**
     *  Route table
     *
     *  For a description of the structure, see
     *  {@tutorial PHPonTrax/Router.cls#table the Router tutorial}.
     *  Routes are added by calling {@link connect()} and looked up
     *  by calling {@link find_route()}.
     *  <b>FIXME:</b> Should we have a Route class to describe an
     *  entry in the route table?
     *  @var string[][]
     */
    private $routes = array();

    /**
     *  Last route found by a call to find_route()
     *  @var string[]
     */
    private $selected_route = null;

    /**
     *  Default route path
     *
     *  This route path is added to the route table if the table is
     *  empty when find_route() is called.
     *  @var string constant
     */
    private $default_route_path = ":controller/:action/:id";

    /**
     *  Count of the number of elements in $routes
     *  @var integer
     */
    public $routes_count = 0;

    /**
     *  Accessor method to return contents of $selected_route
     *  @return string[] Contents of $selected_route
     *  @uses $selected_route
     */
    function get_selected_route() {
        return $this->selected_route;
    }

    /**
     *  Accessor method to add a route to the route table
     *
     *  The route is added to the end of
     *  {@link $routes the route table}. If $params is not an array,
     *  NULL is stored in the route parameter area.
     *  @param string $path
     *  @param mixed[] $params
     *  @uses $routes
     *  @uses $routes_count
     */
    function connect($path, $params = null) {
        if(!is_array($params)) $params = null;
        $this->routes[$this->routes_count]['path'] = $path;
        $this->routes[$this->routes_count]['params'] = $params;
        $this->routes_count = count($this->routes);
    }

    /**
     *  Find first route in route table with path that matches argument
     *
     *  First, assure that the route table {@link $routes} has at
     *  least one route by adding
     *  {@link $default_route_path the default route} if the table is
     *  empty.  Then search the table to find the first route in the
     *  table whose path matches the argument $url. If $url is an
     *  empty string, it matches a path that is an empty string.
     *  Otherwise, try to match $url to the path part of the table
     *  entry according to
     *  {@link http://www.php.net/manual/en/ref.pcre.php Perl regular expression}
     *  rules.  If a matching route is found, return it any to the caller, and
     *  also save a copy in {@link $selected_route}; if no matching
     *  route is found return null.
     *  @param string $url
     *  @uses build_route_regexp()
     *  @uses $default_route_path
     *  @uses $routes
     *  @uses $routes_count
     *  @uses $selected_route
     *  @return mixed Matching route or null.  Path is in return['path'],
     *                   params in return['params'],
     */
    function find_route($url) {
        //error_log('url='.$url);
        // ensure at least one route (the default route) exists
        if($this->routes_count == 0) {
            $this->connect($this->default_route_path);
        }

        $this->selected_route = null;

        foreach($this->routes as $route) {
            unset($route_regexp);
            unset($reg_exp);
            $route_regexp = $this->build_route_regexp($route['path']);
            //error_log("route regexp=/$route_regexp/");
            if($url == "" && $route_regexp == "") {
                //error_log('selected');
                $this->selected_route = $route;
                break;
            } elseif(preg_match("/$route_regexp/",$url) && $route_regexp != "") {
                //error_log('selected');
                $this->selected_route = $route;
                break;
            } elseif($route['path'] == $this->default_route_path) {
                //error_log('defaulted');
                $this->selected_route = $route;
                break;
            }
        }
        //error_log('selected route='.var_export($this->selected_route,true));
        return $this->selected_route;
    }                                 // function find_route($url)

    /**
     *  Build a regular expression that matches a route
     *
     *  @todo <b>FIXME:</b> Should this method be private?
     *  @todo <b>FIXME:</b> Shouldn't the regexp match be the same as
     *  for a PHP variable name? '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
     *  @param string $route_path  A route path.
     *  @return string Regular expression that matches the route in
     *                $route_path 
     */
    function build_route_regexp($route_path) {
        //        echo "entering build_route_regexp(), \$route_path is '$route_path'\n";

        $route_regexp = null;

        if(!is_array($route_path)) {
            $route_path = explode("/",$route_path);
        }
        //error_log("route path:\n".var_export($route_path,true));
        if(count($route_path) > 0) {
            foreach($route_path as $path_element) {
                if(preg_match('/:[a-z0-9_\-]+/',$path_element)) {
                    $reg_exp[] = '[a-z0-9_\-]+';
                } else {
                    $reg_exp[] = $path_element;
                }
            }
            if(is_array($reg_exp)) {
                $route_regexp = "^".implode("\/",$reg_exp)."$";
            }
        }
        return $route_regexp;
    }

}

// -- set Emacs parameters --
// Local variables:
// tab-width: 4
// c-basic-offset: 4
// c-hanging-comment-ender-p: nil
// indent-tabs-mode: nil
// End:
?>
Return current item: PHP on Trax