Skip to content

Instantly share code, notes, and snippets.

@fritz0705
Created January 20, 2010 19:59
Show Gist options
  • Save fritz0705/282181 to your computer and use it in GitHub Desktop.
Save fritz0705/282181 to your computer and use it in GitHub Desktop.
<?php
namespace ActionController\Routing;
class Routes {
public static $map = null;
public static function draw(\Closure $lambda) {
$lambda->__invoke(self::$map);
}
public static function extract_params($path, $route = null) {
if ($route == null) {
$route = self::find_route($path);
}
$extracted_params = array();
$route_path = self::normalize_path($route->path);
$route_path_parts = preg_split("/[".preg_quote(ACTION_CONTROLLER_ROUTING_PATH_SEPARATORS, "/")."]/", $route_path);
$route_options = $route->options;
$path = self::normalize_path($path);
$path_parts = preg_split("/[".preg_quote(ACTION_CONTROLLER_ROUTING_PATH_SEPARATORS, "/")."]/", $path);
foreach ($route_path_parts as $route_path_part_key => $route_path_part) {
$path_part = $path_parts[$route_path_part_key];
if (substr($route_path_part, 0, 1) == ":") {
$route_path_part_name = substr($route_path_part, 1);
$extracted_params[$route_path_part_name] = $path_part;
}
}
foreach ($route_options as $route_option_key => $route_option) {
if (substr($route_option, 0, 1) != "/") {
$extracted_params[$route_option_key] = $route_option;
}
}
return $extracted_params;
}
public static function find_route($path) {
$path_separators_expr = preg_quote(ACTION_CONTROLLER_ROUTING_PATH_SEPARATORS, "/");
$routes = self::$map->routes;
$path = self::normalize_path($path);
$path_parts_split_expr = "/[".$path_separators_expr."]/";
$path_parts = preg_split($path_parts_split_expr, $path);
$path_part_separators = self::extract_separators($path);
foreach ($routes as $route) {
if (!strstr($route->path, ":") && $route->path == $path) {
return $route;
}
$route_options = $route->options;
$route_path = self::normalize_path($route->path);
$route_path_parts_split_expr = "/[".$path_separators_expr."]/";
$route_path_parts = preg_split($route_path_parts_split_expr, $route_path);
$route_path_part_separators = self::extract_separators($route_path);
if (count($route_path_parts) != count($path_parts)) {
continue;
}
$matches = true;
foreach ($route_path_parts as $key => $route_path_part) {
if (array_key_exists($key, $path_part_separators)) {
if ($path_part_separators[$key] != $route_path_part_separators[$key]) {
$matches &= false;
break;
}
}
if (substr($route_path_part, 0, 1) == ":") {
$route_path_part_name = substr($route_path_part, 1);
if (array_key_exists($route_path_part_name, $route_options)) {
$route_path_part_option = $route_options[$route_path_part_name];
if (substr($route_path_part_option, 0, 1) == "/") {
if (!preg_match($route_path_part_option, $path_parts[$key])) {
$matches = false;
break;
} else {
$matches &= true;
continue;
}
} else {
if ($route_path_part_option == $path_parts) {
$matches &= true;
continue;
}
}
}
$matches &= true;
} else {
if ($route_path_part == $path_parts[$key]) {
$matches &= true;
} else {
$matches &= false;
break;
}
}
}
if ($matches) {
return $route;
}
}
throw new Exception("No route found!");
}
public static function generate($options = array()) {
foreach (self::$map->routes as $route) {
$route_options = $route->options;
$route_path = self::normalize_path($route->path);
foreach ($route_options as $key => $route_option) {
if (!array_key_exists($key, $options)) {
if (substr($route_option, 0, 1) == "/") {
continue 2;
}
}
if (substr($route_option, 0, 1) == "/") {
if (!preg_match($route_option, $options[$key])) {
continue 2;
}
} else if ($route_option != $options[$key]) {
continue 2;
}
}
$generated_route_path = $route_path;
foreach ($options as $key => $value) {
$generated_route_path = str_replace(":" . $key, $value, $generated_route_path);
}
return "/" . $generated_route_path;
}
$url_query = array();
foreach ($options as $name => $option) {
$url_query[] = $name . "=" . $option;
}
return "/?" . implode("&", $url_query);
}
private static function normalize_path($path) {
$path = str_replace("//", "/", $path);
$path = substr($path, -1) == "/" ? substr($path, 0, strlen($path) - 1) : $path;
$path = substr($path, 0, 1) == "/" ? substr($path, 1) : $path;
$path = str_replace("::", ":", $path);
return $path;
}
private static function extract_separators($path) {
$result = array();
$separators_array = str_split(ACTION_CONTROLLER_ROUTING_PATH_SEPARATORS);
foreach (str_split($path) as $char) {
if (in_array($char, $separators_array)) {
$result[] = $char;
}
}
return $result;
}
}
Routes::$map = new Map();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment