<?php
/**
* Lys
*
* GNU General Public License
*
* Copyright © 2007 - 2023, Yohann Schwan. All rights reserved.
*/
namespace Lys {
class Route
{
/**
* @var array
*/
protected static $parameters = array();
/**
* @args string $name, string $path, array $args = array(), array $keys = array()
* @return void
*/
static function set($name, $path, $args = array(), array $keys = array(), $method = 'POST')
{
if(empty($path))
{
unset(self::$parameters[$name]);
# Ok !
return;
}
if(isset(self::$parameters[$name]))
{
throw new LogicException('(Route) Unable to redefine route');
}
foreach(array_intersect($args, array_keys($keys)) as $k)
{
throw new LogicException('(Route) Unable to redefine key');
}
self::$parameters[$name] = array(
'name' => $name,
'base' => $path,
'base_length' => $pl = strlen($path),
'args' => $args,
'args_separator' => $path[$pl - 1],
'args_size' => count($args),
'keys' => $keys,
'method' => $method
);
}
/**
* @args string $name
* @return array
*/
static function parameters()
{
return self::$parameters;
}
/**
* @args string $name
* @return array
*/
static function keys()
{
return array_keys(self::$parameters);
}
/**
* @args string $name
* @return array
*/
static function get($name)
{
if(isset(self::$parameters[$name]))
{
return self::$parameters[$name];
}
throw new LogicException('(Route) Undefined route: ' . $name);
}
/**
* @args string $name, array $row = array())
* @return string
*/
static function path($name, array $row = array())
{
if(isset(self::$parameters[$name]))
{
$p = self::$parameters[$name];
}
else {
return '';
}
$q = array();
foreach($p['args'] as $k)
{
if(isset($row[$k]))
{
$q[] = rawurlencode($row[$k]);
}
else {
throw new LogicException('(Route) Missing path component: ' . $k);
}
}
return $p['base'] . implode($a = $p['args_separator'], $q);// . (('/' == $a) && !is_empty($q) ? '/' : '');
}
/**
* @args string $name, array $row = array())
* @return string
*/
static function uri($name, array $row = array())
{
if(isset(self::$parameters[$name]))
{
$p = self::$parameters[$name];
}
else {
return '';
}
$q = array();
foreach($p['keys'] as $k => $n)
{
if(isset($row[$k]) && !empty($row[$k]))
{
$q[$n] = $row[$k];
}
}
return self::path($name, $row) . (empty($q) ? '' : '?' . http_build_query($q));
}
/**
* Callback
*
* @args array $r_1, array $r_2
* @return int
*/
private static function compare($r_1, $r_2)
{
if($s = $r_2['base_length'] - $r_1['base_length'])
{
return $s;
}
return $r_2['args_size'] - $r_1['args_size'];
}
/**
* @args string $path
* @return array
*/
static function analyse($path)
{
if(uasort(self::$parameters, array('self', 'compare')))
{
foreach(self::$parameters as $n => $r)
{
if($r['args_size'])
{
if(($r['base_length'] < strlen($path)) && ($r['base'] == substr($path, 0, $r['base_length'])))
{
$a = explode($r['args_separator'], substr($path, $r['base_length']));
$last = array_pop($a);
if(empty($last))
{
# ...
}
else {
$a[] = $last;
}
if(count($a) == $r['args_size'])
{
return $r + array(
'vars' => array_combine($r['args'], $a),
);
}
}
}
elseif($r['base'] == $path)
{
return $r + array(
'vars' => array(
),
);
}
elseif($r['base'] == ($path . '/'))
{
throw new HttpException('(Route) Return to directory', 301, $r['base']);
}
}
return array();
}
throw new LogicException('(Route) Unable to sort routes');
}
}
}