|
|
|
<?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");
|
|
|
|
}
|
|
|
|
}
|