From 83bc1a1661b70fe4d517b9c7bd55ccfb11ac4e95 Mon Sep 17 00:00:00 2001 From: Maarten Date: Tue, 26 Nov 2024 14:20:46 +0100 Subject: [PATCH] Add bootstrap factory for framework loading --- app/Application.php | 14 +++ composer.json | 6 +- public/index.php | 13 +-- src/Bootstrap.php | 45 +++++++++ .../{Exceptions.php => ExceptionHandler.php} | 40 +++++--- .../Exceptions/ClassNotFoundException.php | 5 + src/Factory/BootstrapFactory.php | 94 +++++++++++++++++++ src/Helpers/helpers.php | 51 ++++++++++ src/Http/Request.php | 5 - src/Routing/RouteDispatcher.php | 24 ++--- src/View/Render/HtmlRender.php | 2 +- 11 files changed, 254 insertions(+), 45 deletions(-) create mode 100644 app/Application.php create mode 100644 src/Bootstrap.php rename src/Exceptions/{Exceptions.php => ExceptionHandler.php} (63%) create mode 100644 src/Exceptions/Exceptions/ClassNotFoundException.php create mode 100644 src/Factory/BootstrapFactory.php create mode 100644 src/Helpers/helpers.php diff --git a/app/Application.php b/app/Application.php new file mode 100644 index 0000000..46d8c93 --- /dev/null +++ b/app/Application.php @@ -0,0 +1,14 @@ +handle(); \ No newline at end of file diff --git a/src/Bootstrap.php b/src/Bootstrap.php new file mode 100644 index 0000000..f434d27 --- /dev/null +++ b/src/Bootstrap.php @@ -0,0 +1,45 @@ +run(); + + return Bootstrap::getInstance(); + } + + /** + * Get the instance + * + * @return \Core\Factory\BootstrapFactory + */ + public static function getInstance(): BootstrapFactory + { + return self::$instance; + } + + /** + * Create new factory instance + * + * @return \Core\Factory\BootstrapFactory + */ + protected function run(): BootstrapFactory + { + return new BootstrapFactory(); + } +} \ No newline at end of file diff --git a/src/Exceptions/Exceptions.php b/src/Exceptions/ExceptionHandler.php similarity index 63% rename from src/Exceptions/Exceptions.php rename to src/Exceptions/ExceptionHandler.php index ec0f033..77f5355 100644 --- a/src/Exceptions/Exceptions.php +++ b/src/Exceptions/ExceptionHandler.php @@ -2,7 +2,6 @@ namespace Core\Exceptions; -use Core\Env\Env; use Core\Http\Request; use Throwable; use Whoops\Handler\Handler; @@ -11,7 +10,7 @@ use Whoops\Handler\PlainTextHandler; use Whoops\Handler\PrettyPageHandler; use Whoops\Run as Whoops; -class Exceptions +class ExceptionHandler { /** * Exceptions handler instance @@ -41,13 +40,12 @@ class Exceptions /** * Get correct handler * - * @param \Core\Http\Request|null $request * @return \Whoops\Handler\Handler */ - private static function handler(Request|null $request): Handler + private static function handler(): Handler { - if (Env::get('debug')) { - if ($request?->is('post')) { + if (env('debug')) { + if (request()?->is('post')) { return new JsonResponseHandler(); } @@ -60,24 +58,44 @@ class Exceptions /** * Catch all exceptions * - * @param \Core\Http\Request $request * @return void */ - public static function catch(Request $request): void + public static function catch(): void { - self::instance($request)->register(); + self::instance()->register(); } /** * Catch single exception * * @param \Throwable $exception - * @return void + * @return never */ - public static function catchOne(Throwable $exception): void + public static function catchOne(Throwable $exception): never { self::instance()->handleException($exception); exit(0); } + + /** + * Make new exception + * + * @param null $abstract + * @param string|null $message + * @return never + */ + public static function make(mixed $abstract = null, string|null $message = null): never + { + if(is_string($abstract)) { + $abstract = app()->make($abstract, $message); + } + + if(is_subclass_of($abstract, 'Exception')) { + self::catchOne($abstract); + } + + exit(0); + } + } \ No newline at end of file diff --git a/src/Exceptions/Exceptions/ClassNotFoundException.php b/src/Exceptions/Exceptions/ClassNotFoundException.php new file mode 100644 index 0000000..494b2b4 --- /dev/null +++ b/src/Exceptions/Exceptions/ClassNotFoundException.php @@ -0,0 +1,5 @@ +request = app()->make(Request::class, [$_POST + $_FILES]); + + // Capture all exceptions + ExceptionHandler::catch(); + + // Load routes + require '../config/routes.php'; + + try { + // Boot application + app()->make(Application::class)->bootstrap(); + + // Dispatch router + app()->make(RouteDispatcher::class)->dispatch($this->request, RouteCollection::retrieve()); + } catch (\Exception $e) { + ExceptionHandler::catchOne($e); + } + } + + /** + * @param string $abstract + * @param array $arguments + * @return mixed + */ + public function make(string $abstract, mixed $arguments = []): mixed + { + return $this->resolve($abstract, $arguments); + } + + /** + * @param string $abstract + * @param array $arguments + * @return mixed|null + */ + private function resolve(string $abstract, mixed $arguments = []): mixed + { + if (class_exists($abstract)) { + try { + $reflection = new \ReflectionClass($abstract); + return $reflection->newInstanceArgs($arguments); + } catch (\ReflectionException $e) { + ExceptionHandler::catchOne($e); + } + } + + ExceptionHandler::make(ClassNotFoundException::class, sprintf("Class '%s' not found", $abstract)); + } + + /** + * Get the request instance + * + * @return \Core\Http\Request + */ + public function request(): Request + { + return $this->request; + } + + /** + * Get path to file/folder in resources folder + * + * @param string $path + * @return string + */ + public function resourcePath(string $path = ''): string + { + return "../resources/" . $path; + } +} \ No newline at end of file diff --git a/src/Helpers/helpers.php b/src/Helpers/helpers.php new file mode 100644 index 0000000..9d3c5c4 --- /dev/null +++ b/src/Helpers/helpers.php @@ -0,0 +1,51 @@ +make($abstract, $arguments); + } +} + +if(!function_exists('env')) +{ + /** + * Get env variable + * + * @param string $key + * @return bool + */ + function env(string $key): mixed + { + return Env::get($key); + } +} + +if (!function_exists('request')) { + /** + * Get the request instance + * + * @return \Core\Http\Request + */ + function request(): Request + { + return app()->request(); + } +} diff --git a/src/Http/Request.php b/src/Http/Request.php index 8bbe2d9..7422c90 100644 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -2,8 +2,6 @@ namespace Core\Http; -use Core\Exceptions\Exceptions; - class Request { private array $data = []; @@ -16,9 +14,6 @@ class Request public function __construct(array $data) { $this->data = $data; - - // Capture all exceptions - Exceptions::catch($this); } /** diff --git a/src/Routing/RouteDispatcher.php b/src/Routing/RouteDispatcher.php index b700682..5ced2a4 100644 --- a/src/Routing/RouteDispatcher.php +++ b/src/Routing/RouteDispatcher.php @@ -2,8 +2,7 @@ namespace Core\Routing; -use Core\Env\Env; -use Core\Exceptions\Exceptions; +use Core\Exceptions\ExceptionHandler; use Core\Exceptions\Exceptions\NotFoundHttpException; use Core\Http\Request; use Core\View\Render; @@ -26,10 +25,13 @@ class RouteDispatcher private array $routeCollection; /** + * Dispatch the router dispatcher + * * @param \Core\Http\Request $request * @param array $routeCollection + * @return void */ - public function __construct(Request $request, array $routeCollection) + public function dispatch(Request $request, array $routeCollection): void { $this->request = $request; $this->routeCollection = $routeCollection; @@ -48,18 +50,6 @@ class RouteDispatcher } } - /** - * Dispatch the router dispatcher - * - * @param \Core\Http\Request $request - * @param array $routeCollection - * @return void - */ - public static function dispatch(Request $request, array $routeCollection): void - { - new self($request, $routeCollection); - } - /** * Locate a matching route for the incoming request. * @@ -153,8 +143,8 @@ class RouteDispatcher */ private function handleException(Exception $e, int $statusCode, string $message): void { - if (Env::get('debug')) { - Exceptions::catchOne($e); + if (env('debug')) { + ExceptionHandler::catchOne($e); } http_response_code($statusCode); diff --git a/src/View/Render/HtmlRender.php b/src/View/Render/HtmlRender.php index e0a53d7..2c9224d 100644 --- a/src/View/Render/HtmlRender.php +++ b/src/View/Render/HtmlRender.php @@ -13,7 +13,7 @@ class HtmlRender extends Render public function render(): void { $basePath = $_SERVER['DOCUMENT_ROOT']; - $viewsPath = $basePath . '/../resources/views/' . str_replace('.', '/', $this->view) . '.php'; + $viewsPath = app()->resourcePath('views/' . str_replace('.', '/', $this->view) . '.php'); if (file_exists($viewsPath)) { extract($this->data);