A free, self-hostable aggregator…
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

245 lines
5.9 KiB

12 years ago
<?php
/**
* MINZ - Copyright 2011 Marien Fressinaud
* Sous licence AGPL3 <http://www.gnu.org/licenses/>
*/
/**
* La classe Router gère le routage de l'application
* Les routes sont définies dans APP_PATH.'/configuration/routes.php'
*/
class Router {
const ROUTES_PATH_NAME = '/configuration/routes.php';
private $routes = array ();
/**
* Constructeur
* @exception FileNotExistException si ROUTES_PATH_NAME n'existe pas
* et que l'on utilise l'url rewriting
*/
public function __construct () {
if (Configuration::useUrlRewriting ()) {
if (file_exists (APP_PATH . self::ROUTES_PATH_NAME)) {
$routes = include (
APP_PATH . self::ROUTES_PATH_NAME
);
if (!is_array ($routes)) {
$routes = array ();
}
$this->routes = array_map (
array ('Url', 'checkUrl'),
$routes
);
} else {
throw new FileNotExistException (
self::ROUTES_PATH_NAME,
MinzException::ERROR
);
}
}
}
/**
* Initialise le Router en déterminant le couple Controller / Action
* Mets à jour la Request
* @exception RouteNotFoundException si l'uri n'est pas présente dans
* > la table de routage
*/
public function init () {
$url = array ();
if (Configuration::useUrlRewriting ()) {
try {
$url = $this->buildWithRewriting ();
} catch (RouteNotFoundException $e) {
throw $e;
}
} else {
$url = $this->buildWithoutRewriting ();
}
$url['params'] = array_merge (
$url['params'],
Request::fetchPOST ()
);
Request::forward ($url);
}
/**
* Retourne un tableau représentant l'url passée par la barre d'adresses
* Ne se base PAS sur la table de routage
* @return tableau représentant l'url
*/
public function buildWithoutRewriting () {
$url = array ();
$url['c'] = Request::fetchGET (
'c',
Request::defaultControllerName ()
);
$url['a'] = Request::fetchGET (
'a',
Request::defaultActionName ()
);
$url['params'] = Request::fetchGET ();
// post-traitement
unset ($url['params']['c']);
unset ($url['params']['a']);
return $url;
}
/**
* Retourne un tableau représentant l'url passée par la barre d'adresses
* Se base sur la table de routage
* @return tableau représentant l'url
* @exception RouteNotFoundException si l'uri n'est pas présente dans
* > la table de routage
*/
public function buildWithRewriting () {
$url = array ();
$uri = Request::getURI ();
$find = false;
foreach ($this->routes as $route) {
$regex = '*^' . $route['route'] . '$*';
if (preg_match ($regex, $uri, $matches)) {
$url['c'] = $route['controller'];
$url['a'] = $route['action'];
$url['params'] = $this->getParams (
$route['params'],
$matches
);
$find = true;
break;
}
}
if (!$find && $uri != '/') {
throw new RouteNotFoundException (
$uri,
MinzException::ERROR
);
}
// post-traitement
$url = Url::checkUrl ($url);
return $url;
}
/**
* Retourne l'uri d'une url en se basant sur la table de routage
* @param l'url sous forme de tableau
* @return l'uri formatée (string) selon une route trouvée
*/
public function printUriRewrited ($url) {
$route = $this->searchRoute ($url);
if ($route !== false) {
return $this->replaceParams ($route, $url);
}
return '';
}
/**
* Recherche la route correspondante à une url
* @param l'url sous forme de tableau
* @return la route telle que spécifiée dans la table de routage,
* false si pas trouvée
*/
public function searchRoute ($url) {
foreach ($this->routes as $route) {
if ($route['controller'] == $url['c']
&& $route['action'] == $url['a']) {
// calcule la différence des tableaux de params
$params = array_flip ($route['params']);
$difference_params = array_diff_key (
$params,
$url['params']
);
// vérifie que pas de différence
// et le cas où $params est vide et pas $url['params']
if (empty ($difference_params)
&& (!empty ($params) || empty ($url['params']))) {
return $route;
}
}
}
return false;
}
/**
* Récupère un tableau dont
* - les clés sont définies dans $params_route
* - les valeurs sont situées dans $matches
* Le tableau $matches est décalé de +1 par rapport à $params_route
*/
private function getParams($params_route, $matches) {
$params = array ();
for ($i = 0; $i < count ($params_route); $i++) {
$param = $params_route[$i];
$params[$param] = $matches[$i + 1];
}
return $params;
}
/**
* Remplace les éléments de la route par les valeurs contenues dans $url
* TODO Fonction très sale ! À revoir (preg_replace ?)
*/
private function replaceParams ($route, $url) {
$uri = '';
$in_brackets = false;
$backslash = false;
$num_param = 0;
// parcourt caractère par caractère
for ($i = 0; $i < strlen ($route['route']); $i++) {
// on détecte qu'on rentre dans des parenthèses
// on va devoir changer par la valeur d'un paramètre
if ($route['route'][$i] == '(' && !$backslash) {
$in_brackets = true;
}
// on sort des parenthèses
// ok, on change le paramètre maintenant
if ($route['route'][$i] == ')' && !$backslash) {
$in_brackets = false;
$param = $route['params'][$num_param];
$uri .= $url['params'][$param];
$num_param++;
}
if (!$in_brackets
&& ($route['route'][$i] != '\\' || $backslash)
&& ($route['route'][$i] != '(' || $backslash)
&& ($route['route'][$i] != ')' || $backslash)
&& ($route['route'][$i] != '?' || $backslash)) {
// on est pas dans les parenthèses
// on recopie simplement le caractère
$uri .= $route['route'][$i];
}
// on détecte un backslash, on n'en veut pas
// sauf si on en avait déjà un juste avant
if ($route['route'][$i] == '\\' && !$backslash) {
$backslash = true;
} else {
$backslash = false;
}
}
return str_replace ('&', '&amp;', $uri);
12 years ago
}
}