<?php declare(strict_types=1); namespace Lean; use Dotenv\Dotenv; use DI\ContainerBuilder, DI\Container; use League\Route\Strategy\ApplicationStrategy; use Psr\Http\Message\ServerRequestInterface; use Ulmus\Container\AdapterProxy; use Zend\Diactoros\ServerRequestFactory, Zend\HttpHandlerRunner\Emitter\EmitterInterface; class Kernel { protected Container $container; protected string $locale; public array $paths = []; public int $errorReporting = E_ALL & ~E_USER_DEPRECATED & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE; public string $definitionFilePath; public string $errorLogPath; public string $projectPath; public string $routeDefinitionList = 'routes.list'; public function __construct(string $projectPath) { $this->projectPath = $projectPath; $this->setEnvironment(); $this->initializeEngine(); $this->setupContainer(); $this->serviceContainer(); $this->handleRequest(); } public static function putenv($var, $value) { putenv("$var=$value"); $_ENV[$var] = $value; } protected function setEnvironment() { static::putenv('PROJECT_PATH', $this->projectPath); // Environment vars (accessible from \DI\env(), getenv(), $_ENV and $_SERVER) Dotenv::create(getenv("PROJECT_PATH"))->load(); // Paths and directories foreach($this->paths as $name => $envkey) { static::putenv($name, realpath(getenv("PROJECT_PATH") . DIRECTORY_SEPARATOR . getenv($envkey))); } // Override using headers foreach(['APP_ENV', 'DEBUG', ] as $env) { if ( null !== $value = $_SERVER["HTTP_$env"] ?? null ) { static::putenv($env, $value); } } } protected function initializeEngine() : self { # Defining default locale and timezone date_default_timezone_set(getenv("DEFAULT_TIMEZONE")); setlocale(LC_ALL, $this->locale = getenv("DEFAULT_LOCAL")); setlocale(LC_TIME, getenv("DEFAULT_TIME"), getenv("DEFAULT_TIME_FALLBACK")); ini_set("log_errors", "1"); ini_set("error_log", $this->errorLogPath); ini_set('display_errors', getenv("DEBUG") ? 'on' : 'off'); error_reporting($this->errorReporting); return $this; } protected function setupContainer() : self { $containerBuilder = new ContainerBuilder(); if (getenv("APP_ENV") === "prod") { if (getenv("CACHE_PATH")) { $containerBuilder->enableCompilation(getenv("CACHE_PATH") . "/di/"); $containerBuilder->writeProxiesToFile(true); } } $containerBuilder->useAnnotations(false); if ($this->definitionFilePath ?? false) { $containerBuilder->addDefinitions(require($this->definitionFilePath)); } $this->container = $containerBuilder->build(); return $this; } protected function serviceContainer() : self { $this->container->has(AdapterProxy::class) and $this->container->get(AdapterProxy::class); return $this; } protected function handleRequest() : self { ServerRequestFactory::fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES); // Router $routeFactory = $this->container->get($this->routeDefinitionList); $router = $routeFactory($this->container); $router->setStrategy($this->container->get(ApplicationStrategy::class)); // Handle requests $response = $router->dispatch($this->container->get(ServerRequestInterface::class)); // Reply to clients $this->container->get(EmitterInterface::class)->emit($response); return $this; } };