You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
3.5 KiB
PHP

<?php
namespace CubiStore\Web\Utils;
class Route
{
const TYPE_ROOT = 'root';
const TYPE_GROUP = 'group';
const TYPE_CALL = 'call';
/**
* @var string
*/
private $type;
/**
* @var string
*/
private $path;
/**
* @var string
*/
private $fullPath;
/**
* @var Route[]|null
*/
private $children;
/**
* @var string|null
*/
private $method;
/**
* @var string|null
*/
private $call;
private static function new(Route $parent, string $path, string $type): Route
{
if (strlen($path) > 0 && $path[0] !== '/') {
throw new \RuntimeException("path should start with /");
}
if ($parent->type !== self::TYPE_GROUP && $parent->type !== self::TYPE_ROOT) {
throw new \RuntimeException("Can only add child routes to a group or root route");
}
$route = new Route();
$parent->add($route);
$route->path = $path;
$route->fullPath = $parent->fullPath . $path;
$route->type = $type;
return $route;
}
public static function group(Route $parent, string $path): Route
{
$route = static::new($parent, $path, self::TYPE_GROUP);
$route->children = [];
return $route;
}
/**
* @param Route $parent
* @param string $method
* @param string $path
* @param string $call
* @return Route
*/
public static function call(Route $parent, string $method, string $path, string $call): Route
{
$route = static::new($parent, $path, self::TYPE_CALL);
$route->method = $method;
$route->call = $call;
return $route;
}
public static function root(): Route
{
$route = new Route();
$route->type = self::TYPE_ROOT;
$route->fullPath = $route->path = '/';
$route->children = [];
return $route;
}
public function add(Route $child): void
{
if ($this->type !== self::TYPE_GROUP && $this->type !== self::TYPE_ROOT) {
throw new \RuntimeException("Only a group route can have child routes");
}
$this->children[] = $child;
}
private function json($value)
{
return json_encode($value, JSON_UNESCAPED_SLASHES);
}
public function compileRoute($var, $indent = 4): string
{
if ($this->type === self::TYPE_CALL) {
return str_repeat(' ', $indent) . "${var}->map([" . $this->json($this->method) . "], " . $this->json($this->path) . ", " . $this->json($this->call) . ");";
}
if ($this->type === self::TYPE_GROUP) {
$name = "\$group" . strlen($this->fullPath);
$code = str_repeat(' ', $indent) . "${var}->group(" . $this->json($this->path) . ", function (RouteCollectorProxy $name) {\n";
if ($this->children === null) {
$this->children = [];
}
foreach ($this->children as $child) {
$code .= $child->compileRoute($name, $indent + 4) . "\n";
}
return $code . str_repeat(' ', $indent) . "});";
}
if ($this->type === self::TYPE_ROOT) {
$code = '';
if ($this->children === null) {
$this->children = [];
}
foreach ($this->children as $child) {
$code .= $child->compileRoute($var, $indent) . "\n";
}
return $code;
}
throw new \RuntimeException("invalid type for route");
}
}