From 534ac7c4c92318be7e7f7a96c47114dfef666ed8 Mon Sep 17 00:00:00 2001 From: Puleeno Nguyen <puleeno@gmail.com> Date: Sun, 22 Oct 2023 10:11:38 +0700 Subject: [PATCH] Load simple service provider --- app/Console/Application.php | 4 +- app/Constracts/ApplicationConstract.php | 8 +- app/Core/Application.php | 146 ++++++++++++++++++++- app/Core/Cookies/CookieServiceProvider.php | 12 ++ app/Core/Log/LogServiceProvider.php | 88 +++++++++++++ app/Facades/UserServiceFacade.php | 3 +- app/Http/Kernel.php | 5 +- app/Http/Middleware/AuthGuard.php | 2 +- app/Providers/AbstractServiceProvider.php | 20 --- app/Providers/ServiceProvider.php | 35 +++++ app/Providers/UserServiceProvider.php | 4 +- app/Repository/UserRepository.php | 47 +++++++ app/bootstrap.php | 60 +-------- app/helpers.php | 9 ++ configs/app.php | 3 +- 15 files changed, 356 insertions(+), 90 deletions(-) create mode 100644 app/Core/Cookies/CookieServiceProvider.php create mode 100644 app/Core/Log/LogServiceProvider.php delete mode 100644 app/Providers/AbstractServiceProvider.php create mode 100644 app/Providers/ServiceProvider.php create mode 100644 app/Repository/UserRepository.php diff --git a/app/Console/Application.php b/app/Console/Application.php index e1233d7..c5b844b 100644 --- a/app/Console/Application.php +++ b/app/Console/Application.php @@ -1,7 +1,9 @@ <?php namespace App\Console; + use Slim\Console\App; -class Application extends App { +class Application extends App +{ } diff --git a/app/Constracts/ApplicationConstract.php b/app/Constracts/ApplicationConstract.php index afe6efd..4932a4b 100644 --- a/app/Constracts/ApplicationConstract.php +++ b/app/Constracts/ApplicationConstract.php @@ -2,6 +2,12 @@ namespace App\Constracts; -interface ApplicationConstract +use Psr\Http\Server\RequestHandlerInterface; +use Slim\Interfaces\RouteCollectorProxyInterface; + +interface ApplicationConstract extends RouteCollectorProxyInterface, RequestHandlerInterface { + public function booted(); + + public function isBooted(); } diff --git a/app/Core/Application.php b/app/Core/Application.php index a27e852..446ffe4 100644 --- a/app/Core/Application.php +++ b/app/Core/Application.php @@ -10,9 +10,6 @@ namespace App\Core; -use App\Constracts\ApplicationConstract; -use App\Core\Routing\RouteCollector; -use App\Http\ResponseEmitter\ResponseEmitter; use Psr\Container\ContainerInterface; use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ResponseInterface; @@ -20,7 +17,7 @@ use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; use Psr\Log\LoggerInterface; -use PuleenoCMS\Exceptions\InvalidApplicationException; +use Tightenco\Collect\Support\Arr; use Slim\App; use Slim\CallableResolver; use Slim\Factory\ServerRequestCreatorFactory; @@ -33,6 +30,12 @@ use Slim\Middleware\RoutingMiddleware; use Slim\Routing\RouteResolver; use Slim\Routing\RouteRunner; +use App\Constracts\ApplicationConstract; +use App\Core\Routing\RouteCollector; +use App\Http\ResponseEmitter\ResponseEmitter; +use App\Providers\ServiceProvider; +use App\Core\Log\LogServiceProvider; +use PuleenoCMS\Exceptions\InvalidApplicationException; use function strtoupper; @@ -51,6 +54,19 @@ class Application extends App implements RequestHandlerInterface, ApplicationCon protected static $instance; + protected $isBooted = false; + + + /** + * @var \App\Providers\ServiceProvider[] + */ + protected $serviceProviders = []; + + /** + * @var boolean[] + */ + protected $loadedProviders = []; + public function __construct( ResponseFactoryInterface $responseFactory, ?ContainerInterface $container = null, @@ -83,6 +99,19 @@ public function __construct( if (is_null(static::$instance)) { static::$instance = &$this; } + + // Register base providers + $this->registerBaseServiceProviders(); + } + + public function booted() + { + $this->isBooted = true; + } + + public function isBooted() + { + return $this->isBooted; } /** @@ -235,4 +264,113 @@ public static function getInstance() } return static::$instance; } + + + /** + * Get the registered service provider instances if any exist. + * + * @param \App\Providers\ServiceProvider|string $provider + * @return array + */ + public function getProviders($provider) + { + $name = is_string($provider) ? $provider : get_class($provider); + + return Arr::where($this->serviceProviders, function ($value) use ($name) { + return $value instanceof $name; + }); + } + + /** + * Resolve a service provider instance from the class name. + * + * @param string $provider + * @return \App\Providers\ServiceProvider + */ + public function resolveProvider($provider) + { + return new $provider($this); + } + + /** + * Mark the given provider as registered. + * + * @param \App\Providers\ServiceProvider $provider + * @return void + */ + protected function markAsRegistered($provider) + { + $this->serviceProviders[] = $provider; + + $this->loadedProviders[get_class($provider)] = true; + } + + /** + * Get the registered service provider instance if it exists. + * + * @param \App\Providers\ServiceProvider|string $provider + * @return \App\Providers\ServiceProvider|null + */ + public function getProvider($provider) + { + return array_values($this->getProviders($provider))[0] ?? null; + } + + + /** + * Boot the given service provider. + * + * @param \App\Providers\ServiceProvider $provider + * @return mixed + */ + protected function bootProvider(ServiceProvider $provider) + { + if (method_exists($provider, 'boot')) { + return call_user_func([$provider, 'boot']); + } + } + + /** + * Register a service provider with the application. + * + * @param \App\Providers\ServiceProvider|string $provider + * @param bool $force + * @return \App\Providers\ServiceProvider + */ + public function register($provider, $force = false) + { + if (($registered = $this->getProvider($provider)) && ! $force) { + return $registered; + } + + // If the given "provider" is a string, we will resolve it, passing in the + // application instance automatically for the developer. This is simply + // a more convenient way of specifying your service provider classes. + if (is_string($provider)) { + $provider = $this->resolveProvider($provider); + } + + $provider->register(); + + $this->markAsRegistered($provider); + + // If the application has already booted, we will call this boot method on + // the provider class so it has an opportunity to do its boot logic and + // will be ready for any usage by this developer's application logic. + if ($this->isBooted()) { + $this->bootProvider($provider); + } + + return $provider; + } + + /** + * Register all of the base service providers. + * + * @return void + */ + protected function registerBaseServiceProviders() + { + $this->register(new LogServiceProvider($this)); + } } diff --git a/app/Core/Cookies/CookieServiceProvider.php b/app/Core/Cookies/CookieServiceProvider.php new file mode 100644 index 0000000..b774200 --- /dev/null +++ b/app/Core/Cookies/CookieServiceProvider.php @@ -0,0 +1,12 @@ +<?php + +namespace App\Core\Cookies; + +use App\Providers\ServiceProvider; + +class CookieServiceProvider extends ServiceProvider +{ + public function register() + { + } +} diff --git a/app/Core/Log/LogServiceProvider.php b/app/Core/Log/LogServiceProvider.php new file mode 100644 index 0000000..8f341ae --- /dev/null +++ b/app/Core/Log/LogServiceProvider.php @@ -0,0 +1,88 @@ +<?php + +namespace App\Core\Log; + +use App\Core\Helper; +use App\Core\Settings\SettingsInterface; +use App\Http\Handlers\HttpErrorHandler; +use App\Http\Handlers\ShutdownHandler; +use App\Providers\ServiceProvider; +use Psr\Container\ContainerInterface; +use ReflectionClass; +use Slim\Factory\ServerRequestCreatorFactory; + +class LogServiceProvider extends ServiceProvider +{ + protected function setupDashboardEnvironment($isDashboard) + { + $helperRelf = new ReflectionClass(Helper::class); + $isDashboardProperty = $helperRelf->getProperty('isDashboard'); + $isDashboardProperty->setAccessible(true); + $isDashboardProperty->setValue($isDashboardProperty, $isDashboard); + $isDashboardProperty->setAccessible(false); + } + + protected function setupHttpErrorHandle() + { + /** + * @var ContainerInterface + */ + $container = $this->app->getContainer(); + + /** @var SettingsInterface $settings */ + $settings = $container->get(SettingsInterface::class); + + $displayErrorDetails = $settings->get('displayErrorDetails'); + + // Create Request object from globals + $serverRequestCreator = ServerRequestCreatorFactory::create(); + $request = $serverRequestCreator->createServerRequestFromGlobals(); + + $requestPath = $request->getUri() != null ? $request->getUri()->getPath() : '/'; + $isDashboard = $requestPath === $settings->get('admin_prefix', '/dashboard') + || strpos($requestPath, $settings->get('admin_prefix', '/dashboard') . '/') === 0; + + $container->set('is_dashboard', $isDashboard); + + $this->setupDashboardEnvironment($isDashboard); + + $responseFactory = $this->app->getResponseFactory(); + $callableResolver = $this->app->getCallableResolver(); + $errorHandler = new HttpErrorHandler($callableResolver, $responseFactory); + + // Create Shutdown Handler + $shutdownHandler = new ShutdownHandler($request, $errorHandler, $displayErrorDetails); + register_shutdown_function($shutdownHandler); + + return $errorHandler; + } + + protected function writeErrorLogs(HttpErrorHandler $errorHandler) + { + /** + * @var ContainerInterface + */ + $container = $this->app->getContainer(); + $settings = $container->get(SettingsInterface::class); + + $displayErrorDetails = $settings->get('displayErrorDetails'); + $logError = $settings->get('logError'); + $logErrorDetails = $settings->get('logErrorDetails'); + + // Add Error Middleware + $errorMiddleware = $this->app->addErrorMiddleware($displayErrorDetails, $logError, $logErrorDetails); + $errorMiddleware->setDefaultErrorHandler($errorHandler); + } + + public function register() + { + $this->writeErrorLogs( + $this->setupHttpErrorHandle() + ); + } + + public function boot() + { + die('zo'); + } +} diff --git a/app/Facades/UserServiceFacade.php b/app/Facades/UserServiceFacade.php index dc2a50f..e589c30 100644 --- a/app/Facades/UserServiceFacade.php +++ b/app/Facades/UserServiceFacade.php @@ -1,6 +1,7 @@ <?php namespace App\Facades; + use Psr\Container\ContainerInterface; class UserServiceFacade extends Facade @@ -18,4 +19,4 @@ public function __get($name) { return $this->container->get(self::FACADE_ACCESSOR); } -} \ No newline at end of file +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 419d4f5..2aa6e6f 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -12,7 +12,7 @@ class Kernel { /** - * @var App + * @var \App\Constracts\ApplicationConstract */ private $app; @@ -31,6 +31,8 @@ public function __construct(App $app) */ public function configure() { + $this->app->booted(); + $this->app->addRoutingMiddleware(); $this->app->addErrorMiddleware(true, true, true); @@ -51,4 +53,3 @@ private function mapRoutes() }); } } - diff --git a/app/Http/Middleware/AuthGuard.php b/app/Http/Middleware/AuthGuard.php index 0fbdec4..1fdb85d 100644 --- a/app/Http/Middleware/AuthGuard.php +++ b/app/Http/Middleware/AuthGuard.php @@ -51,4 +51,4 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res return $next($request, $response); } -} \ No newline at end of file +} diff --git a/app/Providers/AbstractServiceProvider.php b/app/Providers/AbstractServiceProvider.php deleted file mode 100644 index 97286fc..0000000 --- a/app/Providers/AbstractServiceProvider.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -namespace App\Providers; - -use Psr\Container\ContainerInterface; -use App\Services\UserService; - -abstract class AbstractServiceProvider -{ - protected ContainerInterface $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - abstract public function register(); - - abstract public function boot(); -} diff --git a/app/Providers/ServiceProvider.php b/app/Providers/ServiceProvider.php new file mode 100644 index 0000000..9de9e07 --- /dev/null +++ b/app/Providers/ServiceProvider.php @@ -0,0 +1,35 @@ +<?php + +namespace App\Providers; + +use App\Core\Application; + +abstract class ServiceProvider +{ + /** + * The application instance. + * + * @var \App\Core\Application + */ + protected $app; + + + /** + * @var \Psr\Container\ContainerInterface + */ + protected $container; + + + public function __construct(Application $app) + { + $this->app = $app; + $this->container = $app->getContainer(); + } + + public function boot() + { + // empty function + } + + abstract public function register(); +} diff --git a/app/Providers/UserServiceProvider.php b/app/Providers/UserServiceProvider.php index b135be9..840ee2e 100644 --- a/app/Providers/UserServiceProvider.php +++ b/app/Providers/UserServiceProvider.php @@ -4,7 +4,7 @@ use App\Services\UserService; -class UserServiceProvider extends AbstractServiceProvider +class UserServiceProvider extends ServiceProvider { public function register() { @@ -17,4 +17,4 @@ public function boot() { // ... } -} \ No newline at end of file +} diff --git a/app/Repository/UserRepository.php b/app/Repository/UserRepository.php new file mode 100644 index 0000000..bb06514 --- /dev/null +++ b/app/Repository/UserRepository.php @@ -0,0 +1,47 @@ +<?php + +namespace App\Repositories; + +use OPIS\ORM\EntityManager; +use App\Models\User; + +class UserRepository +{ + /** + * @var \OPIS\ORM\EntityManager + */ + private $entityManager; + + public function __construct(EntityManager $entityManager) + { + $this->entityManager = $entityManager; + } + + public function all(): array + { + return $this->entityManager->getRepository(User::class)->findAll(); + } + + public function find(int $id): User + { + return $this->entityManager->getRepository(User::class)->find($id); + } + + public function create(User $user): void + { + $this->entityManager->persist($user); + $this->entityManager->flush(); + } + + public function update(User $user): void + { + $this->entityManager->merge($user); + $this->entityManager->flush(); + } + + public function delete(User $user): void + { + $this->entityManager->remove($user); + $this->entityManager->flush(); + } +} diff --git a/app/bootstrap.php b/app/bootstrap.php index 050e35e..1e5117b 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -133,10 +133,6 @@ protected function setup() $this->app = AppFactory::createApp(); - $this->writeErrorLogs( - $this->setupHttpErrorHandle() - ); - $kernel = new Kernel($this->app); $kernel->configure(); @@ -193,6 +189,9 @@ public function boot() $this->initAssets(); $this->initExtensions(); $this->loadExtensions(); + + $this->app->booted(); + $this->run(); } @@ -253,59 +252,6 @@ protected function run() ); } - // Create Error Handler - protected function setupHttpErrorHandle() - { - /** @var SettingsInterface $settings */ - $settings = $this->container->get(SettingsInterface::class); - - $displayErrorDetails = $settings->get('displayErrorDetails'); - - // Create Request object from globals - $serverRequestCreator = ServerRequestCreatorFactory::create(); - $this->request = $serverRequestCreator->createServerRequestFromGlobals(); - - $requestPath = $this->request->getUri() != null ? $this->request->getUri()->getPath() : '/'; - $isDashboard = $requestPath === $settings->get('admin_prefix', '/dashboard') - || strpos($requestPath, $settings->get('admin_prefix', '/dashboard') . '/') === 0; - - $this->container->set('is_dashboard', $isDashboard); - - $this->setupDashboardEnvironment($isDashboard); - - $responseFactory = $this->app->getResponseFactory(); - $callableResolver = $this->app->getCallableResolver(); - $errorHandler = new HttpErrorHandler($callableResolver, $responseFactory); - - // Create Shutdown Handler - $shutdownHandler = new ShutdownHandler($this->request, $errorHandler, $displayErrorDetails); - register_shutdown_function($shutdownHandler); - - return $errorHandler; - } - - protected function setupDashboardEnvironment($isDashboard) - { - $helperRelf = new ReflectionClass(Helper::class); - $isDashboardProperty = $helperRelf->getProperty('isDashboard'); - $isDashboardProperty->setAccessible(true); - $isDashboardProperty->setValue($isDashboardProperty, $isDashboard); - $isDashboardProperty->setAccessible(false); - } - - protected function writeErrorLogs(HttpErrorHandler $errorHandler) - { - $settings = $this->container->get(SettingsInterface::class); - - $displayErrorDetails = $settings->get('displayErrorDetails'); - $logError = $settings->get('logError'); - $logErrorDetails = $settings->get('logErrorDetails'); - - // Add Error Middleware - $errorMiddleware = $this->app->addErrorMiddleware($displayErrorDetails, $logError, $logErrorDetails); - $errorMiddleware->setDefaultErrorHandler($errorHandler); - } - public function getApp(): App { return $this->app; diff --git a/app/helpers.php b/app/helpers.php index 6276a0c..9c6d698 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -3,6 +3,7 @@ use App\Common\Constants; use App\Common\Option; use App\Core\Application; +use App\Core\Env; use App\Core\Helper; use App\Core\HookManager; use Psr\Container\ContainerInterface; @@ -66,3 +67,11 @@ function get_container(): ContainerInterface return Helper::getContainer(); } } + + +if (!function_exists('env')) { + function env($name, $defaultValue = null) + { + return Env::get($name, $defaultValue); + } +} diff --git a/configs/app.php b/configs/app.php index 6985862..1b29fea 100644 --- a/configs/app.php +++ b/configs/app.php @@ -29,7 +29,8 @@ */ 'middleware' => [ - // ... + \App\Http\Middleware\SessionMiddleware::class, + \App\Http\Middleware\AssetsMiddleware::class, ], 'aliases' => [