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.

150 lines
4.5 KiB

<?php
declare(strict_types = 1);
/**
* @author Robert Strutts
* @copyright (c) 2025, Robert Strutts
* @license MIT
*/
namespace IOcornerstone\Framework\Http;
use IOcornerstone\Framework\{
Registry as Reg,
Console,
};
use IOcornerstone\Framework\Http\{
App\App,
HttpContainer,
Routing\RoutingHandler,
Routing\Router,
App\AppHandler,
Exception\NoRouteProviderFoundException,
Exception\RouteProviderException,
};
use IOcornerstone\Framework\Middleware\{
ErrorMiddleware,
RequestLoggerMiddleware
};
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class Kernel {
protected ContainerInterface $psrContainer;
protected array $middleware = [];
protected array $serviceProviders = [];
public function __construct() {
$this->psrContainer = Reg::get('container');
}
private function registerRoutes(Router $router): void
{
if (! defined("IO_CORNERSTONE_PROJECT")) {
return; // Running CLI from Framework test script
}
if (! class_exists(\Project\Providers\RouteServiceProvider::class)) {
throw new NoRouteProviderFoundException("Class NOT found: Project\Providers\RouteServiceProvider");
}
try {
$routeProviders = new \Project\Providers\RouteServiceProvider();
} catch (\Throwable $e) {
throw new RouteProviderException("Unable to INIT RouteServiceProvider class \r\n" . $e->getMessage());
}
if (! method_exists($routeProviders, "register")) {
throw new NoRouteProviderFoundException("Method NOT found: Project\Providers\RouteServiceProvider::register");
}
try {
$routeProviders->register($router);
} catch (\Throwable $e) {
throw new RouteProviderException("Unable to call register on Route ServiceProvider \r\n" . $e->getMessage());
}
}
private function buildKernel()
{
$router = new Router();
$this->registerRoutes($router);
// Get App instance
$app = $this->psrContainer->get(App::class);
// Create AppHandler with middleware support
$appHandler = $this->createAppHandler($app);
// Create routing handler
$routingHandler = new RoutingHandler(
$router,
$this->psrContainer,
$appHandler
);
// Combine global middleware
$globalMiddleware = $this->getGlobalMiddleware();
// Add app-specific middleware if any
$appMiddleware = $app->getMiddleware();
if (!empty($appMiddleware)) {
array_splice($globalMiddleware, -1, 0, $appMiddleware);
}
return new MiddlewareQueueHandler(
$globalMiddleware,
$routingHandler
);
}
private function createAppHandler(App $app): RequestHandlerInterface
{
return new AppHandler($app);
}
private function getGlobalMiddleware(): array
{
return [
$this->psrContainer->get(ErrorMiddleware::class),
$this->psrContainer->get(RequestLoggerMiddleware::class),
];
}
private function dispatch($kernel): Response
{
$httpFactory = new HttpFactory();
if (Console::isConsole()) {
$createPsr7Request = $httpFactory->createCliRequest();
} else {
$createPsr7Request = $httpFactory->createServerRequestFromGlobals();
}
return $kernel->handle($createPsr7Request);
}
private function emit(Response $response): void
{
if (! Console::isConsole()) {
http_response_code($response->getStatusCode());
}
foreach ($response->getHeaders() as $name => $values) {
if (! is_array($values) && ! is_object($values)) {
header("$name: $values", false);
continue;
}
foreach ($values as $value) {
header("$name: $value", false);
}
}
if (function_exists('session_status') && session_status() == PHP_SESSION_ACTIVE) {
session_write_close();
}
echo $response->getBody();
}
public function run(): void {
$kernel = $this->buildKernel();
$response = $this->dispatch($kernel);
$this->emit($response);
}
}
//dd($createPsr7Request->getQueryParams()['name']);
//dd($createPsr7Request->getVar()->get("name"));