eee
This commit is contained in:
+163
-5
@@ -14,6 +14,7 @@ use Throwable;
|
||||
use Traversable;
|
||||
use Kiri\Router\Base\Middleware;
|
||||
use Kiri\Router\Format\ResponseFormat;
|
||||
use Kiri\Router\Validator\ValidatorMiddleware;
|
||||
|
||||
|
||||
/**
|
||||
@@ -42,7 +43,7 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
||||
|
||||
|
||||
/**
|
||||
* @var array<string, Handler>
|
||||
* @var array<string, Handler|RouteEntry>
|
||||
*/
|
||||
private array $methods = [];
|
||||
|
||||
@@ -69,7 +70,7 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
||||
|
||||
|
||||
/**
|
||||
* @return Handler[]
|
||||
* @return array<string, Handler|RouteEntry>
|
||||
*/
|
||||
public function getMethods(): array
|
||||
{
|
||||
@@ -77,6 +78,16 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
||||
}
|
||||
|
||||
|
||||
public function clear(): void
|
||||
{
|
||||
$this->_item = [];
|
||||
$this->dump = [];
|
||||
$this->groupTack = [];
|
||||
$this->methods = [];
|
||||
$this->httpHandler = [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param HttpRequestHandler $handler
|
||||
@@ -171,14 +182,26 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
||||
if (is_string($closure[0])) {
|
||||
$closure[0] = $container->get($closure[0]);
|
||||
}
|
||||
return $interpreter->addRouteByString(... $closure);
|
||||
$handler = $interpreter->addRouteByString(... $closure);
|
||||
$sourceFile = Router::getCurrentSourceFile();
|
||||
if ($sourceFile !== null) {
|
||||
$handler->setSourceFile($sourceFile);
|
||||
$handler->setSourceKind('route_file');
|
||||
}
|
||||
return $handler;
|
||||
}
|
||||
if (!str_contains($closure, '@')) {
|
||||
$closure .= '@';
|
||||
}
|
||||
[$className, $method] = explode('@', $closure);
|
||||
$class = $container->get($this->resetName($className));
|
||||
return $interpreter->addRouteByString($class, $method);
|
||||
$handler = $interpreter->addRouteByString($class, $method);
|
||||
$sourceFile = Router::getCurrentSourceFile();
|
||||
if ($sourceFile !== null) {
|
||||
$handler->setSourceFile($sourceFile);
|
||||
$handler->setSourceKind('route_file');
|
||||
}
|
||||
return $handler;
|
||||
}
|
||||
|
||||
|
||||
@@ -205,11 +228,99 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
||||
*/
|
||||
public function register(string $path, string $method, Handler $handler): void
|
||||
{
|
||||
if ($handler->getSourceFile() === null && $handler->getClass() !== null) {
|
||||
$reflect = \Kiri::getDi()->getReflectionClass($handler->getClass());
|
||||
$handler->setSourceFile($this->normalizePath((string)$reflect->getFileName()));
|
||||
$handler->setSourceKind('attribute');
|
||||
}
|
||||
|
||||
$this->methods[$method . '_' . $path] = $handler;
|
||||
$handler->setMiddlewares($this->registerMiddleware($handler->getClass(), $handler->getMethod()));
|
||||
}
|
||||
|
||||
|
||||
public function exportArtifact(): array
|
||||
{
|
||||
$entries = [];
|
||||
$hasClosureRoutes = false;
|
||||
|
||||
foreach ($this->methods as $methodPath => $handler) {
|
||||
if ($handler instanceof Handler && $handler->isClosure()) {
|
||||
$hasClosureRoutes = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
[$requestMethod, $path] = explode('_', $methodPath, 2);
|
||||
$class = $handler instanceof Handler ? $handler->getClass() : $handler->class;
|
||||
$method = $handler instanceof Handler ? $handler->getMethod() : $handler->method;
|
||||
$middlewares = $handler instanceof Handler ? $handler->getMiddlewares() : $handler->middlewares;
|
||||
$sourceFile = $handler instanceof Handler ? $handler->getSourceFile() : $handler->sourceFile;
|
||||
$sourceKind = $handler instanceof Handler ? $handler->getSourceKind() : $handler->sourceKind;
|
||||
|
||||
$entries[] = [
|
||||
'request_method' => $requestMethod,
|
||||
'path' => $path,
|
||||
'class' => $class,
|
||||
'method' => $method,
|
||||
'middlewares' => $middlewares,
|
||||
'source_file' => $sourceFile,
|
||||
'source_kind' => $sourceKind,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'has_closure_routes' => $hasClosureRoutes,
|
||||
'entries' => $entries,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function importArtifact(array $artifact, array $excludeSourceFiles = []): bool
|
||||
{
|
||||
if (($artifact['has_closure_routes'] ?? false) === true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$entries = $artifact['entries'] ?? null;
|
||||
if (!is_array($entries)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$exclude = array_fill_keys(array_map([$this, 'normalizePath'], $excludeSourceFiles), true);
|
||||
foreach ($entries as $entry) {
|
||||
if (!is_array($entry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sourceFile = $entry['source_file'] ?? null;
|
||||
if (is_string($sourceFile) && isset($exclude[$this->normalizePath($sourceFile)])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$class = $entry['class'] ?? null;
|
||||
$method = $entry['method'] ?? null;
|
||||
$requestMethod = $entry['request_method'] ?? null;
|
||||
$path = $entry['path'] ?? null;
|
||||
|
||||
if (!is_string($class) || !is_string($method) || !is_string($requestMethod) || !is_string($path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->methods[$requestMethod . '_' . $path] = new RouteEntry(
|
||||
requestMethod: $requestMethod,
|
||||
path: $path,
|
||||
class: $class,
|
||||
method: $method,
|
||||
middlewares: is_array($entry['middlewares'] ?? null) ? $entry['middlewares'] : [],
|
||||
sourceFile: is_string($sourceFile) ? $this->normalizePath($sourceFile) : null,
|
||||
sourceKind: is_string($entry['source_kind'] ?? null) ? $entry['source_kind'] : 'attribute',
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $method
|
||||
@@ -289,7 +400,12 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
||||
*/
|
||||
public function query(string $path, string $method): HttpRequestHandler
|
||||
{
|
||||
return $this->httpHandler[$method . '_' . $path] ?? $this->not_found_handler();
|
||||
$key = $method . '_' . $path;
|
||||
if (!isset($this->httpHandler[$key]) && isset($this->methods[$key])) {
|
||||
$this->httpHandler[$key] = $this->compileHandler($this->methods[$key]);
|
||||
}
|
||||
|
||||
return $this->httpHandler[$key] ?? $this->not_found_handler();
|
||||
}
|
||||
|
||||
|
||||
@@ -309,6 +425,14 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
||||
}
|
||||
|
||||
|
||||
public function warmHttpHandlers(): void
|
||||
{
|
||||
foreach ($this->methods as $name => $method) {
|
||||
$this->httpHandler[$name] = $this->compileHandler($method);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $route
|
||||
* @return string
|
||||
@@ -324,6 +448,40 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
||||
}
|
||||
|
||||
|
||||
private function normalizePath(string $path): string
|
||||
{
|
||||
$resolved = realpath($path) ?: $path;
|
||||
return str_replace('\\', '/', $resolved);
|
||||
}
|
||||
|
||||
|
||||
private function compileHandler(Handler|RouteEntry $method): HttpRequestHandler
|
||||
{
|
||||
if ($method instanceof RouteEntry) {
|
||||
$controller = \Kiri::getDi()->get($method->class);
|
||||
$handler = di(ControllerInterpreter::class)->addRouteByString($controller, $method->method);
|
||||
$handler->setRequestMethod($method->requestMethod);
|
||||
$handler->setMiddlewares($method->middlewares);
|
||||
$handler->setSourceFile($method->sourceFile);
|
||||
$handler->setSourceKind($method->sourceKind);
|
||||
$method = $handler;
|
||||
}
|
||||
|
||||
$middlewares = $method->getMiddlewares();
|
||||
foreach ($middlewares as $key => $middleware) {
|
||||
$middlewares[$key] = di($middleware);
|
||||
}
|
||||
|
||||
$requestHandler = new HttpRequestHandler($middlewares, $method);
|
||||
$validator = Middleware::getValidator($method->getClass(), $method->getMethod());
|
||||
if ($validator !== null) {
|
||||
$requestHandler->withValidatorMiddleware(new ValidatorMiddleware(di(\Psr\Http\Message\ResponseInterface::class), $method->getClass(), $method->getMethod()));
|
||||
}
|
||||
|
||||
return $requestHandler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @return bool
|
||||
|
||||
Reference in New Issue
Block a user