Пример #1
0
 public static function routeRequest($request)
 {
     $path_pieces = array_map(function ($piece) {
         return urldecode($piece);
     }, explode("/", $request->path));
     $chosen_route = null;
     /* find and take the first matching route, storing route components in
      * $params */
     if ($request->path == "") {
         if (empty(parent::instance()->rootRoutes)) {
             throw new RoutingException("no root route defined");
         }
         foreach (parent::instance()->rootRoutes as $route) {
             /* verify virtual host matches if there's a condition on it */
             if (isset($route["conditions"]["hostname"])) {
                 if (!Utils::strcasecmp_or_preg_match($route["conditions"]["hostname"], $request->host)) {
                     continue;
                 }
             }
             $chosen_route = $route;
             break;
         }
     } else {
         foreach (parent::instance()->routes as $route) {
             /* verify virtual host matches if there's a condition on it */
             if (isset($route["conditions"]["hostname"])) {
                 if (!Utils::strcasecmp_or_preg_match($route["conditions"]["hostname"], $request->host)) {
                     continue;
                 }
             }
             /* trim slashes from route definition and bust it up into
              * components */
             $route_pieces = explode("/", trim(preg_replace("/^\\/*/", "", preg_replace("/\\/\$/", "", trim($route["url"])))));
             $match = true;
             for ($x = 0; $x < count($route_pieces); $x++) {
                 /* look for a condition */
                 if (preg_match("/^:(.+)\$/", $route_pieces[$x], $m)) {
                     $regex_or_string = isset($route["conditions"]) ? @Utils::A((array) $route["conditions"], $m[1]) : NULL;
                     /* if the corresponding path piece isn't there and
                      * there is either no condition, or a condition that
                      * matches against a blank string, it's ok.  this lets
                      * controller/:action/:id match when the route is just
                      * "controller", assigning :action and :id to nothing */
                     if ($regex_or_string == NULL || Utils::strcasecmp_or_preg_match($regex_or_string, Utils::is_blank($path_pieces[$x]) ? "" : $path_pieces[$x])) {
                         if (isset($route[$m[1]]) && preg_match("/^(.*):(.+)\$/", $route[$m[1]], $n)) {
                             /* route has a set parameter, but it wants to
                              * include the matching piece from the path in
                              * its parameter */
                             $route[$m[1]] = $n[1] . (isset($path_pieces[$x]) ? $path_pieces[$x] : static::$DEFAULT_ACTION);
                         } else {
                             /* store this named parameter (e.g. "/:blah"
                              * route on a path of "/hi" defines
                              * $route["blah"] to be "hi") */
                             $route[$m[1]] = @$path_pieces[$x];
                         }
                     } else {
                         $match = false;
                     }
                 } elseif (preg_match("/^\\*(.+)\$/", $route_pieces[$x], $m)) {
                     $regex_or_string = isset($route["conditions"]) ? @Utils::A((array) $route["conditions"], $m[1]) : NULL;
                     /* concatenate the rest of the path as this one param */
                     $u = "";
                     for ($j = $x; $j < count($path_pieces); $j++) {
                         $u .= ($u == "" ? "" : "/") . $path_pieces[$j];
                     }
                     if ($regex_or_string == NULL || Utils::strcasecmp_or_preg_match($regex_or_string, $u)) {
                         $route[$m[1]] = $u;
                     } else {
                         $match = false;
                     }
                     break;
                 } elseif (@strcasecmp($route_pieces[$x], $path_pieces[$x]) != 0) {
                     $match = false;
                 }
                 if (!$match) {
                     break;
                 }
             }
             if ($match) {
                 /* we need at least a valid controller */
                 if ($route["controller"] == "") {
                     continue;
                 }
                 /* note that we pass the action to the controller even if it
                  * doesn't exist, that way at least the backtrace will show
                  * what controller we resolved it to */
                 $chosen_route = $route;
                 break;
             }
         }
     }
     if (!$chosen_route) {
         throw new RoutingException("no route for url \"" . $request->path . "\"");
     }
     /* we need at least a controller */
     if ($chosen_route["controller"] == "") {
         throw new RoutingException("no controller specified");
     }
     /* and a valid controller name */
     if (!preg_match("/^[a-zA-Z_][a-zA-Z0-9_]*\$/", $chosen_route["controller"])) {
         throw new RoutingException("invalid controller matched");
     }
     /* but we can deal with no action by calling the index action */
     if (!isset($chosen_route["action"]) || $chosen_route["action"] == "") {
         $chosen_route["action"] = static::$DEFAULT_ACTION;
     }
     return $chosen_route;
 }