From bfc14c936c65409a85b8802db658c241607d47e9 Mon Sep 17 00:00:00 2001 From: ArrayIterator Date: Thu, 19 Oct 2023 02:51:26 +0700 Subject: [PATCH] add bulk change --- src/Console/Application.php | 42 ++++++---- src/Console/Command/ChecksumGenerator.php | 26 +++---- src/Console/Command/CommandGenerator.php | 36 +++++---- src/Console/Command/ControllerGenerator.php | 38 +++++---- .../Command/DatabaseEventGenerator.php | 22 +++--- src/Console/Command/EntityGenerator.php | 38 ++++----- src/Console/Command/MiddlewareGenerator.php | 37 +++++---- src/Console/Command/ModuleGenerator.php | 37 +++++---- src/Console/Command/SchedulerGenerator.php | 38 +++++---- src/HttpKernel/BaseKernel.php | 26 +++---- src/HttpKernel/Helper/AbstractHelper.php | 27 ++++--- .../Helper/AbstractLoaderNameBased.php | 15 ++-- src/HttpKernel/Helper/KernelCommandLoader.php | 35 ++++++--- .../Helper/KernelControllerLoader.php | 30 ++++--- .../Helper/KernelDatabaseEventLoader.php | 25 ++++-- .../Helper/KernelMiddlewareLoader.php | 25 ++++-- src/HttpKernel/Helper/KernelModuleLoader.php | 25 ++++-- .../Helper/KernelSchedulerLoader.php | 16 +++- src/Routing/AbstractController.php | 9 +-- src/Util/Filter/Consolidation.php | 78 ++++++++++++++----- src/Util/Filter/DataType.php | 32 ++++++++ 21 files changed, 422 insertions(+), 235 deletions(-) diff --git a/src/Console/Application.php b/src/Console/Application.php index afa8141..f4d0c54 100644 --- a/src/Console/Application.php +++ b/src/Console/Application.php @@ -203,26 +203,36 @@ private function configureTheCommands(): void if ((debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['class']??null) !== __CLASS__) { return; } - $this->configureDBCommands(); - foreach ($this->factoryCommands as $command) { - try { - if (isset($this->registered[$command])) { + $manager = $this->getManager(); + // @dispatch(console.beforeConfigureCommands) + $manager?->dispatch('console.beforeConfigureCommands', $this); + try { + $this->configureDBCommands(); + foreach ($this->factoryCommands as $command) { + try { + if (isset($this->registered[$command])) { + continue; + } + $className = $command; + $command = new $command; + parent::add($this->appendDefaultContainer($command)); + $this->registered[$className] = true; + } catch (Throwable $e) { + $this->errors[$command] = $e; + } + } + foreach ($this->queue as $commandName => $command) { + unset($this->queue[$commandName]); + if (isset($this->registered[$commandName])) { continue; } - $className = $command; - $command = new $command; parent::add($this->appendDefaultContainer($command)); - $this->registered[$className] = true; - } catch (Throwable $e) { - $this->errors[$command] = $e; - } - } - foreach ($this->queue as $commandName => $command) { - unset($this->queue[$commandName]); - if (isset($this->registered[$commandName])) { - continue; } - parent::add($this->appendDefaultContainer($command)); + // @dispatch(console.configureCommands) + $manager?->dispatch('console.configureCommands', $this); + } finally { + // @dispatch(console.afterConfigureCommands) + $manager?->dispatch('console.afterConfigureCommands', $this); } } diff --git a/src/Console/Command/ChecksumGenerator.php b/src/Console/Command/ChecksumGenerator.php index 9e5357d..3431102 100644 --- a/src/Console/Command/ChecksumGenerator.php +++ b/src/Console/Command/ChecksumGenerator.php @@ -5,20 +5,21 @@ use ArrayAccess\TrayDigita\Exceptions\InvalidArgument\InteractiveArgumentException; use ArrayAccess\TrayDigita\Exceptions\Runtime\UnsupportedRuntimeException; +use ArrayAccess\TrayDigita\HttpKernel\BaseKernel; +use ArrayAccess\TrayDigita\Kernel\Interfaces\KernelInterface; +use ArrayAccess\TrayDigita\PossibleRoot; use ArrayAccess\TrayDigita\Traits\Container\ContainerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Service\TranslatorTrait; use ArrayAccess\TrayDigita\Util\Filter\Consolidation; -use Composer\Autoload\ClassLoader; +use ArrayAccess\TrayDigita\Util\Filter\ContainerHelper; use FilesystemIterator; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; -use ReflectionClass; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use Throwable; use function basename; use function date; use function dirname; @@ -91,17 +92,16 @@ protected function execute(InputInterface $input, OutputInterface $output): int 'Application should be run in CLI mode' ); } - $srcDirectory = dirname(__DIR__, 2); - try { - $ref = new ReflectionClass(ClassLoader::class); - $checksumDirectory = dirname($ref->getFileName(), 3) - . DIRECTORY_SEPARATOR - . 'checksums'; - } catch (Throwable) { - $checksumDirectory = dirname($srcDirectory) - . DIRECTORY_SEPARATOR - . 'checksums'; + $kernel = ContainerHelper::use(KernelInterface::class, $this->getContainer()); + if ($kernel instanceof BaseKernel) { + $rootDirectory = $kernel->getRootDirectory(); + } else { + $rootDirectory = PossibleRoot::getPossibleRootDirectory(); } + $srcDirectory = dirname(__DIR__, 2); + $checksumDirectory = $rootDirectory + . DIRECTORY_SEPARATOR + . 'checksums'; $io = new SymfonyStyle($input, $output); // $input->setInteractive(true); diff --git a/src/Console/Command/CommandGenerator.php b/src/Console/Command/CommandGenerator.php index 86500ac..07077dd 100644 --- a/src/Console/Command/CommandGenerator.php +++ b/src/Console/Command/CommandGenerator.php @@ -7,7 +7,8 @@ use ArrayAccess\TrayDigita\Container\Interfaces\ContainerAllocatorInterface; use ArrayAccess\TrayDigita\Event\Interfaces\ManagerAllocatorInterface; use ArrayAccess\TrayDigita\Exceptions\InvalidArgument\InteractiveArgumentException; -use ArrayAccess\TrayDigita\Kernel\Decorator; +use ArrayAccess\TrayDigita\HttpKernel\BaseKernel; +use ArrayAccess\TrayDigita\Kernel\Interfaces\KernelInterface; use ArrayAccess\TrayDigita\Traits\Container\ContainerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Manager\ManagerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Service\TranslatorTrait; @@ -51,10 +52,16 @@ class CommandGenerator extends Command implements ContainerAllocatorInterface, M private ?string $commandDir = null; private string $commandNamespace; - public function __construct(string $name = null) + protected function configure() : void { - $commandNamespace = Decorator::kernel()?->getCommandNamespace(); - if (!$commandNamespace) { + $kernel = ContainerHelper::use( + KernelInterface::class, + $this->getContainer() + ); + if ($kernel instanceof BaseKernel) { + $this->commandNamespace = $kernel->getCommandNameSpace(); + $this->commandDir = $kernel->getRegisteredDirectories()[$this->commandNamespace]??null; + } else { $namespace = dirname( str_replace( '\\', @@ -63,14 +70,9 @@ public function __construct(string $name = null) ) ); $appNameSpace = str_replace('/', '\\', dirname($namespace)) . '\\App'; - $commandNamespace = "$appNameSpace\\Commands\\"; + $this->commandNamespace = "$appNameSpace\\Commands\\"; } - $this->commandNamespace = $commandNamespace; - parent::__construct($name); - } - protected function configure() : void - { $namespace = rtrim($this->commandNamespace, '\\'); $this ->setName('app:generate:command') @@ -239,12 +241,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int $input->setInteractive(true); $container = $this->getContainer(); - $config = ContainerHelper::getNull(Config::class, $container)??new Config(); - $path = $config->get('path'); - $path = $path instanceof Config ? $path : null; - $commandDir = $path?->get('command'); - if (is_string($commandDir) && is_dir($commandDir)) { - $this->commandDir = realpath($commandDir)??$commandDir; + if (!$this->commandDir) { + $config = ContainerHelper::getNull(Config::class, $container) ?? new Config(); + $path = $config->get('path'); + $path = $path instanceof Config ? $path : null; + $commandDir = $path?->get('command'); + if (is_string($commandDir) && is_dir($commandDir)) { + $this->commandDir = realpath($commandDir) ?? $commandDir; + } } if (!$this->commandDir) { diff --git a/src/Console/Command/ControllerGenerator.php b/src/Console/Command/ControllerGenerator.php index b8f80e2..805974f 100644 --- a/src/Console/Command/ControllerGenerator.php +++ b/src/Console/Command/ControllerGenerator.php @@ -7,7 +7,8 @@ use ArrayAccess\TrayDigita\Container\Interfaces\ContainerAllocatorInterface; use ArrayAccess\TrayDigita\Event\Interfaces\ManagerAllocatorInterface; use ArrayAccess\TrayDigita\Exceptions\InvalidArgument\InteractiveArgumentException; -use ArrayAccess\TrayDigita\Kernel\Decorator; +use ArrayAccess\TrayDigita\HttpKernel\BaseKernel; +use ArrayAccess\TrayDigita\Kernel\Interfaces\KernelInterface; use ArrayAccess\TrayDigita\Traits\Container\ContainerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Manager\ManagerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Service\TranslatorTrait; @@ -49,12 +50,19 @@ class ControllerGenerator extends Command implements ContainerAllocatorInterface TranslatorTrait; private ?string $controllerDir = null; + private string $controllerNameSpace; - public function __construct(string $name = null) + protected function configure() : void { - $controllerNameSpace = Decorator::kernel()?->getControllerNameSpace(); - if (!$controllerNameSpace) { + $kernel = ContainerHelper::use( + KernelInterface::class, + $this->getContainer() + ); + if ($kernel instanceof BaseKernel) { + $this->controllerNameSpace = $kernel->getControllerNameSpace(); + $this->controllerDir = $kernel->getRegisteredDirectories()[$this->controllerNameSpace]??null; + } else { $namespace = dirname( str_replace( '\\', @@ -63,14 +71,8 @@ public function __construct(string $name = null) ) ); $appNameSpace = str_replace('/', '\\', dirname($namespace)) . '\\App'; - $controllerNameSpace = "$appNameSpace\\Controllers\\"; + $this->controllerNameSpace = "$appNameSpace\\Controllers\\"; } - $this->controllerNameSpace = $controllerNameSpace; - parent::__construct($name); - } - - protected function configure() : void - { $namespace = rtrim($this->controllerNameSpace, '\\'); $this ->setName('app:generate:controller') @@ -209,12 +211,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int $input->setInteractive(true); $container = $this->getContainer(); - $config = ContainerHelper::getNull(Config::class, $container)??new Config(); - $path = $config->get('path'); - $path = $path instanceof Config ? $path : null; - $controllerDir = $path?->get('controller'); - if (is_string($controllerDir) && is_dir($controllerDir)) { - $this->controllerDir = realpath($controllerDir)??$controllerDir; + if (!$this->controllerDir) { + $config = ContainerHelper::getNull(Config::class, $container) ?? new Config(); + $path = $config->get('path'); + $path = $path instanceof Config ? $path : null; + $controllerDir = $path?->get('controller'); + if (is_string($controllerDir) && is_dir($controllerDir)) { + $this->controllerDir = realpath($controllerDir) ?? $controllerDir; + } } if (!$this->controllerDir) { diff --git a/src/Console/Command/DatabaseEventGenerator.php b/src/Console/Command/DatabaseEventGenerator.php index 04ae2c7..6f94173 100644 --- a/src/Console/Command/DatabaseEventGenerator.php +++ b/src/Console/Command/DatabaseEventGenerator.php @@ -7,7 +7,9 @@ use ArrayAccess\TrayDigita\Container\Interfaces\ContainerAllocatorInterface; use ArrayAccess\TrayDigita\Event\Interfaces\ManagerAllocatorInterface; use ArrayAccess\TrayDigita\Exceptions\InvalidArgument\InteractiveArgumentException; +use ArrayAccess\TrayDigita\HttpKernel\BaseKernel; use ArrayAccess\TrayDigita\Kernel\Decorator; +use ArrayAccess\TrayDigita\Kernel\Interfaces\KernelInterface; use ArrayAccess\TrayDigita\Traits\Container\ContainerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Manager\ManagerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Service\TranslatorTrait; @@ -51,10 +53,16 @@ class DatabaseEventGenerator extends Command implements ContainerAllocatorInterf private ?string $databaseEventDir = null; private string $databaseEventNamespace; - public function __construct(string $name = null) + protected function configure() : void { - $databaseEventNamespace = Decorator::kernel()?->getDatabaseEventNamespace(); - if (!$databaseEventNamespace) { + $kernel = ContainerHelper::use( + KernelInterface::class, + $this->getContainer() + ); + if ($kernel instanceof BaseKernel) { + $this->databaseEventNamespace = $kernel->getDatabaseEventNameSpace(); + $this->databaseEventDir = $kernel->getRegisteredDirectories()[$this->databaseEventNamespace]??null; + } else { $namespace = dirname( str_replace( '\\', @@ -63,14 +71,8 @@ public function __construct(string $name = null) ) ); $appNameSpace = str_replace('/', '\\', dirname($namespace)) . '\\App'; - $databaseEventNamespace = "$appNameSpace\\DatabaseEvents\\"; + $this->databaseEventNamespace = "$appNameSpace\\DatabaseEvents\\"; } - $this->databaseEventNamespace = $databaseEventNamespace; - parent::__construct($name); - } - - protected function configure() : void - { $namespace = rtrim($this->databaseEventNamespace, '\\'); $this ->setName('app:generate:database-event') diff --git a/src/Console/Command/EntityGenerator.php b/src/Console/Command/EntityGenerator.php index bf0fcc1..2fcead5 100644 --- a/src/Console/Command/EntityGenerator.php +++ b/src/Console/Command/EntityGenerator.php @@ -7,7 +7,8 @@ use ArrayAccess\TrayDigita\Container\Interfaces\ContainerAllocatorInterface; use ArrayAccess\TrayDigita\Event\Interfaces\ManagerAllocatorInterface; use ArrayAccess\TrayDigita\Exceptions\InvalidArgument\InteractiveArgumentException; -use ArrayAccess\TrayDigita\Kernel\Decorator; +use ArrayAccess\TrayDigita\HttpKernel\BaseKernel; +use ArrayAccess\TrayDigita\Kernel\Interfaces\KernelInterface; use ArrayAccess\TrayDigita\Traits\Container\ContainerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Manager\ManagerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Service\TranslatorTrait; @@ -51,10 +52,16 @@ class EntityGenerator extends Command implements ContainerAllocatorInterface, Ma private ?string $entityDir = null; private string $entityNamespace; - public function __construct(string $name = null) + protected function configure() : void { - $entityNamespace = Decorator::kernel()?->getEntityNamespace(); - if (!$entityNamespace) { + $kernel = ContainerHelper::use( + KernelInterface::class, + $this->getContainer() + ); + if ($kernel instanceof BaseKernel) { + $this->entityNamespace = $kernel->getEntityNamespace(); + $this->entityDir = $kernel->getRegisteredDirectories()[$this->entityNamespace]??null; + } else { $namespace = dirname( str_replace( '\\', @@ -63,14 +70,8 @@ public function __construct(string $name = null) ) ); $appNameSpace = str_replace('/', '\\', dirname($namespace)) . '\\App'; - $entityNamespace = "$appNameSpace\\Entities\\"; + $this->entityNamespace = "$appNameSpace\\Entities\\"; } - $this->entityNamespace = $entityNamespace; - parent::__construct($name); - } - - protected function configure() : void - { $namespace = rtrim($this->entityNamespace, '\\'); $this ->setName('app:generate:entity') @@ -224,14 +225,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int $input->setInteractive(true); $container = $this->getContainer(); - $config = ContainerHelper::use(Config::class, $container)??new Config(); - $path = $config->get('path'); - $path = $path instanceof Config ? $path : null; - $entityDir = $path?->get('entity'); - if (is_string($entityDir) && is_dir($entityDir)) { - $this->entityDir = realpath($entityDir)??$entityDir; + if (!$this->entityDir) { + $config = ContainerHelper::use(Config::class, $container) ?? new Config(); + $path = $config->get('path'); + $path = $path instanceof Config ? $path : null; + $entityDir = $path?->get('entity'); + if (is_string($entityDir) && is_dir($entityDir)) { + $this->entityDir = realpath($entityDir) ?? $entityDir; + } } - if (!$this->entityDir) { $output->writeln( sprintf( diff --git a/src/Console/Command/MiddlewareGenerator.php b/src/Console/Command/MiddlewareGenerator.php index 096c2a0..bfe2389 100644 --- a/src/Console/Command/MiddlewareGenerator.php +++ b/src/Console/Command/MiddlewareGenerator.php @@ -7,7 +7,9 @@ use ArrayAccess\TrayDigita\Container\Interfaces\ContainerAllocatorInterface; use ArrayAccess\TrayDigita\Event\Interfaces\ManagerAllocatorInterface; use ArrayAccess\TrayDigita\Exceptions\InvalidArgument\InteractiveArgumentException; +use ArrayAccess\TrayDigita\HttpKernel\BaseKernel; use ArrayAccess\TrayDigita\Kernel\Decorator; +use ArrayAccess\TrayDigita\Kernel\Interfaces\KernelInterface; use ArrayAccess\TrayDigita\Traits\Container\ContainerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Manager\ManagerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Service\TranslatorTrait; @@ -49,12 +51,19 @@ class MiddlewareGenerator extends Command implements ContainerAllocatorInterface TranslatorTrait; private ?string $middlewareDir = null; + private string $middlewareNamespace; - public function __construct(string $name = null) + protected function configure() : void { - $middlewareNamespace = Decorator::kernel()?->getMiddlewareNamespace(); - if (!$middlewareNamespace) { + $kernel = ContainerHelper::use( + KernelInterface::class, + $this->getContainer() + ); + if ($kernel instanceof BaseKernel) { + $this->middlewareNamespace = $kernel->getMiddlewareNamespace(); + $this->middlewareDir = $kernel->getRegisteredDirectories()[$this->middlewareNamespace]??null; + } else { $namespace = dirname( str_replace( '\\', @@ -63,14 +72,8 @@ public function __construct(string $name = null) ) ); $appNameSpace = str_replace('/', '\\', dirname($namespace)) . '\\App'; - $middlewareNamespace = "$appNameSpace\\Middlewares\\"; + $this->middlewareNamespace = "$appNameSpace\\Middlewares\\"; } - $this->middlewareNamespace = $middlewareNamespace; - parent::__construct($name); - } - - protected function configure() : void - { $namespace = rtrim($this->middlewareNamespace, '\\'); $this ->setName('app:generate:middleware') @@ -233,12 +236,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int $input->setInteractive(true); $container = $this->getContainer(); - $config = ContainerHelper::use(Config::class, $container)??new Config(); - $path = $config->get('path'); - $path = $path instanceof Config ? $path : null; - $middlewareDir = $path?->get('middleware'); - if (is_string($middlewareDir) && is_dir($middlewareDir)) { - $this->middlewareDir = realpath($middlewareDir)??$middlewareDir; + if (!$this->middlewareDir) { + $config = ContainerHelper::use(Config::class, $container) ?? new Config(); + $path = $config->get('path'); + $path = $path instanceof Config ? $path : null; + $middlewareDir = $path?->get('middleware'); + if (is_string($middlewareDir) && is_dir($middlewareDir)) { + $this->middlewareDir = realpath($middlewareDir) ?? $middlewareDir; + } } if (!$this->middlewareDir) { diff --git a/src/Console/Command/ModuleGenerator.php b/src/Console/Command/ModuleGenerator.php index d0c2794..c01d96c 100644 --- a/src/Console/Command/ModuleGenerator.php +++ b/src/Console/Command/ModuleGenerator.php @@ -7,7 +7,8 @@ use ArrayAccess\TrayDigita\Container\Interfaces\ContainerAllocatorInterface; use ArrayAccess\TrayDigita\Event\Interfaces\ManagerAllocatorInterface; use ArrayAccess\TrayDigita\Exceptions\InvalidArgument\InteractiveArgumentException; -use ArrayAccess\TrayDigita\Kernel\Decorator; +use ArrayAccess\TrayDigita\HttpKernel\BaseKernel; +use ArrayAccess\TrayDigita\Kernel\Interfaces\KernelInterface; use ArrayAccess\TrayDigita\Traits\Container\ContainerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Manager\ManagerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Service\TranslatorTrait; @@ -51,10 +52,16 @@ class ModuleGenerator extends Command implements ContainerAllocatorInterface, Ma private ?string $moduleDir = null; private string $moduleNamespace; - public function __construct(string $name = null) + protected function configure() : void { - $moduleNamespace = Decorator::kernel()?->getModuleNamespace(); - if (!$moduleNamespace) { + $kernel = ContainerHelper::use( + KernelInterface::class, + $this->getContainer() + ); + if ($kernel instanceof BaseKernel) { + $this->moduleNamespace = $kernel->getControllerNameSpace(); + $this->moduleDir = $kernel->getRegisteredDirectories()[$this->moduleNamespace]??null; + } else { $namespace = dirname( str_replace( '\\', @@ -63,14 +70,8 @@ public function __construct(string $name = null) ) ); $appNameSpace = str_replace('/', '\\', dirname($namespace)) . '\\App'; - $moduleNamespace = "$appNameSpace\\Modules\\"; + $this->moduleNamespace = "$appNameSpace\\Modules\\"; } - $this->moduleNamespace = $moduleNamespace; - parent::__construct($name); - } - - protected function configure() : void - { $namespace = rtrim($this->moduleNamespace, '\\'); $this ->setName('app:generate:module') @@ -239,12 +240,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int $input->setInteractive(true); $container = $this->getContainer(); - $config = ContainerHelper::use(Config::class, $container)??new Config(); - $path = $config->get('path'); - $path = $path instanceof Config ? $path : null; - $moduleDir = $path?->get('module'); - if (is_string($moduleDir) && is_dir($moduleDir)) { - $this->moduleDir = realpath($moduleDir)??$moduleDir; + if (!$this->moduleDir) { + $config = ContainerHelper::use(Config::class, $container) ?? new Config(); + $path = $config->get('path'); + $path = $path instanceof Config ? $path : null; + $moduleDir = $path?->get('module'); + if (is_string($moduleDir) && is_dir($moduleDir)) { + $this->moduleDir = realpath($moduleDir) ?? $moduleDir; + } } if (!$this->moduleDir) { diff --git a/src/Console/Command/SchedulerGenerator.php b/src/Console/Command/SchedulerGenerator.php index 85e0073..dc28432 100644 --- a/src/Console/Command/SchedulerGenerator.php +++ b/src/Console/Command/SchedulerGenerator.php @@ -7,7 +7,9 @@ use ArrayAccess\TrayDigita\Container\Interfaces\ContainerAllocatorInterface; use ArrayAccess\TrayDigita\Event\Interfaces\ManagerAllocatorInterface; use ArrayAccess\TrayDigita\Exceptions\InvalidArgument\InteractiveArgumentException; +use ArrayAccess\TrayDigita\HttpKernel\BaseKernel; use ArrayAccess\TrayDigita\Kernel\Decorator; +use ArrayAccess\TrayDigita\Kernel\Interfaces\KernelInterface; use ArrayAccess\TrayDigita\Traits\Container\ContainerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Manager\ManagerAllocatorTrait; use ArrayAccess\TrayDigita\Traits\Service\TranslatorTrait; @@ -49,12 +51,19 @@ class SchedulerGenerator extends Command implements ContainerAllocatorInterface, TranslatorTrait; private ?string $schedulerDir = null; + private string $schedulerNamespace; - public function __construct(string $name = null) + protected function configure() : void { - $schedulerNamespace = Decorator::kernel()?->getSchedulerNamespace(); - if (!$schedulerNamespace) { + $kernel = ContainerHelper::use( + KernelInterface::class, + $this->getContainer() + ); + if ($kernel instanceof BaseKernel) { + $this->schedulerNamespace = $kernel->getSchedulerNamespace(); + $this->schedulerDir = $kernel->getRegisteredDirectories()[$this->schedulerNamespace]??null; + } else { $namespace = dirname( str_replace( '\\', @@ -63,14 +72,9 @@ public function __construct(string $name = null) ) ); $appNameSpace = str_replace('/', '\\', dirname($namespace)) . '\\App'; - $schedulerNamespace = "$appNameSpace\\Schedulers\\"; + $this->schedulerNamespace = "$appNameSpace\\Schedulers\\"; } - $this->schedulerNamespace = $schedulerNamespace; - parent::__construct($name); - } - protected function configure() : void - { $namespace = rtrim($this->schedulerNamespace, '\\'); $this ->setName('app:generate:scheduler') @@ -242,13 +246,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int $input->setInteractive(true); $container = $this->getContainer(); - $config = ContainerHelper::use(Config::class, $container) - ??new Config(); - $path = $config->get('path'); - $path = $path instanceof Config ? $path : null; - $schedulerDir = $path?->get('scheduler'); - if (is_string($schedulerDir) && is_dir($schedulerDir)) { - $this->schedulerDir = realpath($schedulerDir)??$schedulerDir; + if (!$this->schedulerDir) { + $config = ContainerHelper::use(Config::class, $container) + ?? new Config(); + $path = $config->get('path'); + $path = $path instanceof Config ? $path : null; + $schedulerDir = $path?->get('scheduler'); + if (is_string($schedulerDir) && is_dir($schedulerDir)) { + $this->schedulerDir = realpath($schedulerDir) ?? $schedulerDir; + } } if (!$this->schedulerDir) { diff --git a/src/HttpKernel/BaseKernel.php b/src/HttpKernel/BaseKernel.php index 87c4d74..f065b06 100644 --- a/src/HttpKernel/BaseKernel.php +++ b/src/HttpKernel/BaseKernel.php @@ -97,7 +97,7 @@ abstract class BaseKernel implements /** * @var array */ - private array $registeredDirectories = []; + protected array $registeredDirectories = []; /** * @var array|string[] @@ -324,24 +324,19 @@ public function __call(string $name, array $arguments) private bool $ready = false; /*! NAMESPACE */ - private ?string $appNameSpace = null; - private ?string $controllerNameSpace = null; - private ?string $entityNamespace = null; - private ?string $middlewareNamespace = null; - private ?string $migrationNameSpace = null; - private ?string $moduleNameSpace = null; - private ?string $databaseEventNameSpace = null; - private ?string $commandNameSpace = null; - private ?string $schedulerNamespace = null; + protected ?string $appNameSpace = null; + protected ?string $controllerNameSpace = null; + protected ?string $entityNamespace = null; + protected ?string $middlewareNamespace = null; + protected ?string $migrationNameSpace = null; + protected ?string $moduleNameSpace = null; + protected ?string $databaseEventNameSpace = null; + protected ?string $commandNameSpace = null; + protected ?string $schedulerNamespace = null; /*! STATUS */ private bool $providerRegistered = false; - private bool $moduleRegistered = false; - private bool $schedulerRegistered = false; - - private bool $commandRegistered = false; - private bool $serviceRegistered = false; private ?string $rootDirectory = null; @@ -822,6 +817,7 @@ final public function init() : static // do register schedulers KernelSchedulerLoader::register($this); + /*! APPS */ // do register middlewares KernelMiddlewareLoader::register($this); // do register controllers diff --git a/src/HttpKernel/Helper/AbstractHelper.php b/src/HttpKernel/Helper/AbstractHelper.php index 89c08b1..8406fd1 100644 --- a/src/HttpKernel/Helper/AbstractHelper.php +++ b/src/HttpKernel/Helper/AbstractHelper.php @@ -321,7 +321,19 @@ final protected function saveCacheItem( } } - private static array $registeredKernel = []; + /** + * @var array> + */ + private static array $registeredKernelServices = []; + + /** + * @return array> + * @noinspection PhpUnused + */ + public static function getRegisteredKernelServices(): array + { + return self::$registeredKernelServices; + } /** * @param BaseKernel $kernel @@ -330,13 +342,10 @@ final protected function saveCacheItem( final public static function register(BaseKernel $kernel) : bool { $helper = new static($kernel); - $id = $helper::class ."::" .spl_object_hash($kernel); - // prevent duplicate registration - if (isset(self::$registeredKernel[$id])) { - return false; - } - self::$registeredKernel[$id] = true; - $helper->doRegister(); + $kernelId = spl_object_hash($kernel); + $id = $helper::class; + self::$registeredKernelServices[$id][$kernelId] ??= 0; + self::$registeredKernelServices[$id][$kernelId] += $helper->doRegister() ? 1 : 0; return true; } @@ -444,7 +453,7 @@ abstract protected function isProcessable() : bool; /** * Doing register */ - abstract protected function doRegister(); + abstract protected function doRegister() : bool; abstract protected function loadService(SplFileInfo $splFileInfo); } diff --git a/src/HttpKernel/Helper/AbstractLoaderNameBased.php b/src/HttpKernel/Helper/AbstractLoaderNameBased.php index fc1a157..00579f9 100644 --- a/src/HttpKernel/Helper/AbstractLoaderNameBased.php +++ b/src/HttpKernel/Helper/AbstractLoaderNameBased.php @@ -9,18 +9,22 @@ abstract class AbstractLoaderNameBased extends AbstractHelper { /** - * @return Finder + * @return ?Finder */ - abstract protected function getFileLists() : Finder; + abstract protected function getFileLists() : ?Finder; - protected function doRegister(): void + protected function doRegister(): bool { if (!$this->isProcessable()) { - return; + return false; } // preprocess $this->preProcess(); + $files = $this->getFileLists(); + if (!$files) { + return false; + } $mode = ucwords(trim($this->getMode())); $manager = $this->getManager(); @@ -29,7 +33,7 @@ protected function doRegister(): void $this->kernel ); try { - foreach ($this->getFileLists() as $list) { + foreach ($files as $list) { $this->loadService($list); } @@ -46,5 +50,6 @@ protected function doRegister(): void // postprocess $this->postProcess(); } + return true; } } diff --git a/src/HttpKernel/Helper/KernelCommandLoader.php b/src/HttpKernel/Helper/KernelCommandLoader.php index 0e69595..7b85d8a 100644 --- a/src/HttpKernel/Helper/KernelCommandLoader.php +++ b/src/HttpKernel/Helper/KernelCommandLoader.php @@ -13,8 +13,10 @@ use Symfony\Component\Finder\Finder; use Throwable; use function class_exists; +use function is_bool; +use function is_dir; -final class KernelCommandLoader extends AbstractLoaderNameBased +class KernelCommandLoader extends AbstractLoaderNameBased { private ?Application $scheduler = null; @@ -24,16 +26,19 @@ protected function getNameSpace(): ?string } /** - * @return Finder + * @return ?Finder */ - protected function getFileLists(): Finder + protected function getFileLists(): ?Finder { - return $this + $directory = $this->getDirectory(); + return !$directory || ! is_dir($directory) + ? null + : $this ->createFinder($this->getDirectory(), 0, '/^[_A-za-z]([a-zA-Z0-9]+)?\.php$/') ->files(); } - protected function getScheduler() : ?Application + protected function getApplication() : ?Application { return $this->scheduler ??= ContainerHelper::service( Application::class, @@ -43,22 +48,23 @@ protected function getScheduler() : ?Application protected function getManager(): ?ManagerInterface { - return $this->getScheduler() + return $this->getApplication() ?->getManager()??parent::getManager(); } protected function getContainer(): ?ContainerInterface { - return $this->getScheduler() + return $this->getApplication() ?->getContainer()??parent::getContainer(); } protected function getDirectory(): ?string { $namespace = $this->getNameSpace(); - return $namespace + $directory = $namespace ? $this->kernel->getRegisteredDirectories()[$namespace]??null : null; + return $directory && is_dir($directory) ? $directory : null; } protected function getMode(): string @@ -68,9 +74,16 @@ protected function getMode(): string protected function isProcessable(): bool { - return $this->getNameSpace() + $processable = $this->getNameSpace() && $this->getDirectory() - && $this->getScheduler(); + && $this->getApplication(); + if ($processable) { + $canBeProcess = $this + ->getManager() + ->dispatch('kernel.commandLoader', true); + $processable = is_bool($canBeProcess) ? $canBeProcess : true; + } + return $processable; } /** @@ -81,7 +94,7 @@ protected function loadService( SplFileInfo $splFileInfo ): void { if (!$splFileInfo->isFile() - || ! ($application = $this->getScheduler()) + || ! ($application = $this->getApplication()) ) { return; } diff --git a/src/HttpKernel/Helper/KernelControllerLoader.php b/src/HttpKernel/Helper/KernelControllerLoader.php index 45a25f5..9a4258f 100644 --- a/src/HttpKernel/Helper/KernelControllerLoader.php +++ b/src/HttpKernel/Helper/KernelControllerLoader.php @@ -12,8 +12,10 @@ use Symfony\Component\Finder\Finder; use Throwable; use function class_exists; +use function is_bool; +use function is_dir; -final class KernelControllerLoader extends AbstractLoaderNameBased +class KernelControllerLoader extends AbstractLoaderNameBased { protected function getNameSpace(): ?string { @@ -21,13 +23,15 @@ protected function getNameSpace(): ?string } /** - * @return Finder + * @return ?Finder */ - protected function getFileLists(): Finder + protected function getFileLists(): ?Finder { - // override $maxDepth = 20; - return $this + $directory = $this->getDirectory(); + return !$directory || ! is_dir($directory) + ? null + : $this ->createFinder($this->getDirectory(), "<= $maxDepth", '/^[_A-za-z]([a-zA-Z0-9]+)?\.php$/') ->files(); } @@ -43,9 +47,10 @@ public function getRouter() : RouterInterface protected function getDirectory(): ?string { $namespace = $this->getNameSpace(); - return $namespace + $directory = $namespace ? $this->kernel->getRegisteredDirectories()[$namespace]??null : null; + return $directory && is_dir($directory) ? $directory : null; } protected function getContainer(): ContainerInterface @@ -60,9 +65,16 @@ protected function getMode(): string protected function isProcessable(): bool { - return ! $this->kernel->getConfigError() - && $this->getNameSpace() - && $this->getDirectory(); + $processable = $this->getNameSpace() + && $this->getDirectory() + && !$this->kernel->getConfigError(); + if ($processable) { + $canBeProcess = $this + ->getManager() + ->dispatch('kernel.controllerLoader', true); + $processable = is_bool($canBeProcess) ? $canBeProcess : true; + } + return $processable; } /** diff --git a/src/HttpKernel/Helper/KernelDatabaseEventLoader.php b/src/HttpKernel/Helper/KernelDatabaseEventLoader.php index cb164ad..79dbdab 100644 --- a/src/HttpKernel/Helper/KernelDatabaseEventLoader.php +++ b/src/HttpKernel/Helper/KernelDatabaseEventLoader.php @@ -11,8 +11,10 @@ use Symfony\Component\Finder\Finder; use Throwable; use function class_exists; +use function is_bool; +use function is_dir; -final class KernelDatabaseEventLoader extends AbstractLoaderNameBased +class KernelDatabaseEventLoader extends AbstractLoaderNameBased { private ?DatabaseEventsCollector $databaseEventsCollector = null; @@ -22,11 +24,14 @@ protected function getNameSpace(): ?string } /** - * @return Finder + * @return ?Finder */ - protected function getFileLists(): Finder + protected function getFileLists(): ?Finder { - return $this + $directory = $this->getDirectory(); + return !$directory || ! is_dir($directory) + ? null + : $this ->createFinder($this->getDirectory(), 0, '/^[_A-za-z]([a-zA-Z0-9]+)?\.php$/') ->files(); } @@ -42,9 +47,10 @@ protected function getDatabaseEventsCollector() : ?DatabaseEventsCollector protected function getDirectory(): ?string { $namespace = $this->getNameSpace(); - return $namespace + $directory = $namespace ? $this->kernel->getRegisteredDirectories()[$namespace]??null : null; + return $directory && is_dir($directory) ? $directory : null; } protected function getMode(): string @@ -54,10 +60,17 @@ protected function getMode(): string protected function isProcessable(): bool { - return ! $this->kernel->getConfigError() + $processable = ! $this->kernel->getConfigError() && $this->getNameSpace() && $this->getDirectory() && $this->getDatabaseEventsCollector(); + if ($processable) { + $canBeProcess = $this + ->getManager() + ->dispatch('kernel.databaseEventLoader', true); + $processable = is_bool($canBeProcess) ? $canBeProcess : true; + } + return $processable; } /** diff --git a/src/HttpKernel/Helper/KernelMiddlewareLoader.php b/src/HttpKernel/Helper/KernelMiddlewareLoader.php index 62e8676..955efb1 100644 --- a/src/HttpKernel/Helper/KernelMiddlewareLoader.php +++ b/src/HttpKernel/Helper/KernelMiddlewareLoader.php @@ -12,8 +12,10 @@ use Symfony\Component\Finder\Finder; use Throwable; use function class_exists; +use function is_bool; +use function is_dir; -final class KernelMiddlewareLoader extends AbstractLoaderNameBased +class KernelMiddlewareLoader extends AbstractLoaderNameBased { protected function getNameSpace(): ?string { @@ -21,11 +23,14 @@ protected function getNameSpace(): ?string } /** - * @return Finder + * @return ?Finder */ - protected function getFileLists(): Finder + protected function getFileLists(): ?Finder { - return $this + $directory = $this->getDirectory(); + return !$directory || ! is_dir($directory) + ? null + : $this ->createFinder($this->getDirectory(), 0, '/^[_A-za-z]([a-zA-Z0-9]+)?\.php$/') ->files(); } @@ -33,9 +38,10 @@ protected function getFileLists(): Finder protected function getDirectory(): ?string { $namespace = $this->getNameSpace(); - return $namespace + $directory = $namespace ? $this->kernel->getRegisteredDirectories()[$namespace]??null : null; + return $directory && is_dir($directory) ? $directory : null; } protected function getContainer(): ContainerInterface @@ -50,8 +56,15 @@ protected function getMode(): string protected function isProcessable(): bool { - return $this->getNameSpace() + $processable = $this->getNameSpace() && $this->getDirectory(); + if ($processable) { + $canBeProcess = $this + ->getManager() + ->dispatch('kernel.middlewareLoader', true); + $processable = is_bool($canBeProcess) ? $canBeProcess : true; + } + return $processable; } /** diff --git a/src/HttpKernel/Helper/KernelModuleLoader.php b/src/HttpKernel/Helper/KernelModuleLoader.php index 959ea2d..a251d77 100644 --- a/src/HttpKernel/Helper/KernelModuleLoader.php +++ b/src/HttpKernel/Helper/KernelModuleLoader.php @@ -13,8 +13,10 @@ use Symfony\Component\Finder\Finder; use Throwable; use function class_exists; +use function is_bool; +use function is_dir; -final class KernelModuleLoader extends AbstractLoaderNameBased +class KernelModuleLoader extends AbstractLoaderNameBased { private ?Modules $modules = null; @@ -24,11 +26,14 @@ protected function getNameSpace(): ?string } /** - * @return Finder + * @return ?Finder */ - protected function getFileLists(): Finder + protected function getFileLists(): ?Finder { - return $this + $directory = $this->getDirectory(); + return !$directory || ! is_dir($directory) + ? null + : $this ->createFinder($this->getDirectory(), 0, '/^[_A-za-z]([a-zA-Z0-9]+)?$/') ->directories(); } @@ -44,9 +49,10 @@ protected function getModules() : ?Modules protected function getDirectory(): ?string { $namespace = $this->getNameSpace(); - return $namespace + $directory = $namespace ? $this->kernel->getRegisteredDirectories()[$namespace]??null : null; + return $directory && is_dir($directory) ? $directory : null; } protected function getMode(): string @@ -69,9 +75,16 @@ protected function getContainer(): ?ContainerInterface protected function isProcessable(): bool { - return $this->getNameSpace() + $processable = $this->getNameSpace() && $this->getDirectory() && $this->getModules(); + if ($processable) { + $canBeProcess = $this + ->getManager() + ->dispatch('kernel.moduleLoader', true); + $processable = is_bool($canBeProcess) ? $canBeProcess : true; + } + return $processable; } /** diff --git a/src/HttpKernel/Helper/KernelSchedulerLoader.php b/src/HttpKernel/Helper/KernelSchedulerLoader.php index d3b1e2c..c561df1 100644 --- a/src/HttpKernel/Helper/KernelSchedulerLoader.php +++ b/src/HttpKernel/Helper/KernelSchedulerLoader.php @@ -13,8 +13,10 @@ use Symfony\Component\Finder\Finder; use Throwable; use function class_exists; +use function is_bool; +use function is_dir; -final class KernelSchedulerLoader extends AbstractLoaderNameBased +class KernelSchedulerLoader extends AbstractLoaderNameBased { private ?Scheduler $scheduler = null; @@ -56,9 +58,10 @@ protected function getContainer(): ?ContainerInterface protected function getDirectory(): ?string { $namespace = $this->getNameSpace(); - return $namespace + $directory = $namespace ? $this->kernel->getRegisteredDirectories()[$namespace]??null : null; + return $directory && is_dir($directory) ? $directory : null; } protected function getMode(): string @@ -68,10 +71,17 @@ protected function getMode(): string protected function isProcessable(): bool { - return ! $this->kernel->getConfigError() + $processable = ! $this->kernel->getConfigError() && $this->getNameSpace() && $this->getDirectory() && $this->getScheduler(); + if ($processable) { + $canBeProcess = $this + ->getManager() + ->dispatch('kernel.schedulerLoader', true); + $processable = is_bool($canBeProcess) ? $canBeProcess : true; + } + return $processable; } /** diff --git a/src/Routing/AbstractController.php b/src/Routing/AbstractController.php index 82c028d..780288f 100644 --- a/src/Routing/AbstractController.php +++ b/src/Routing/AbstractController.php @@ -18,6 +18,7 @@ use ArrayAccess\TrayDigita\Traits\Responder\JsonResponderFactoryTrait; use ArrayAccess\TrayDigita\Traits\View\ViewTrait; use ArrayAccess\TrayDigita\Util\Filter\ContainerHelper; +use ArrayAccess\TrayDigita\Util\Filter\DataType; use JsonSerializable; use Psr\Container\ContainerInterface; use Psr\Http\Message\ResponseInterface; @@ -183,16 +184,10 @@ public function redirect( ) : ResponseInterface { $code = $code === 301 ? 301 : 302; $response ??= $this->getResponseFactory()->createResponse($code); - return $response + return DataType::appendNoCache($response) ->withHeader( 'Location', (string) $uri - )->withHeader( - 'Pragma', - 'no-cache' - )->withHeader( - 'Cache-control', - 'no-store, no-cache, must-revalidate, max-age=0' ); } diff --git a/src/Util/Filter/Consolidation.php b/src/Util/Filter/Consolidation.php index 4906656..65b9c78 100644 --- a/src/Util/Filter/Consolidation.php +++ b/src/Util/Filter/Consolidation.php @@ -27,6 +27,7 @@ use function ini_get; use function intval; use function is_array; +use function is_callable; use function is_dir; use function is_file; use function is_int; @@ -46,6 +47,7 @@ use function rtrim; use function set_error_handler; use function spl_autoload_register; +use function spl_autoload_unregister; use function spl_object_hash; use function sprintf; use function str_contains; @@ -916,12 +918,37 @@ public function __debugInfo(): ?array /*! AUTOLOADER */ /** - * @var array> + * @var array> */ private static array $registeredLoaderAutoloader = []; private static array $registeredDirectoriesAutoloader = []; + /** + * Register autoloader with namespace + * + * @param string $namespace + * @param string $directory + * @return bool + */ + public static function deRegisterAutoloader( + string $namespace, + string $directory + ): bool { + $namespace = trim($namespace, '\\'); + $namespace = $namespace . '\\'; + $directory = realpath($directory)?:$directory; + if (!isset(self::$registeredLoaderAutoloader[$namespace][$directory])) { + return false; + } + $callback = self::$registeredLoaderAutoloader[$namespace][$directory]; + unset(self::$registeredLoaderAutoloader[$namespace][$directory]); + if (!is_callable($callback)) { + return false; + } + return spl_autoload_unregister($callback); + } + /** * Register autoloader with namespace * @@ -950,26 +977,39 @@ public static function registerAutoloader( $namespace = $namespace . '\\'; $directory = realpath($directory)?:$directory; if (!empty(self::$registeredLoaderAutoloader[$namespace][$directory])) { - return self::$registeredLoaderAutoloader[$namespace][$directory]; + return false; } - return self::$registeredLoaderAutoloader[$namespace][$directory] = spl_autoload_register( - static function ($className) use ($namespace, $directory, $include) { - if (!str_starts_with($className, $namespace)) { - return; - } - $file = substr($className, strlen($namespace)); - $file = str_replace('\\', DIRECTORY_SEPARATOR, $file); - $fileName = $directory . DIRECTORY_SEPARATOR . $file. ".php"; - if (isset(self::$registeredDirectoriesAutoloader[$fileName])) { - return; - } - self::$registeredDirectoriesAutoloader[$fileName] = true; - if (file_exists($fileName)) { - $include($fileName); - } - }, + + self::$registeredLoaderAutoloader[$namespace][$directory] = static function ( + $className + ) use ( + $namespace, + $directory, + $include + ) { + if (!str_starts_with($className, $namespace)) { + return; + } + $file = substr($className, strlen($namespace)); + $file = str_replace('\\', DIRECTORY_SEPARATOR, $file); + $fileName = $directory . DIRECTORY_SEPARATOR . $file. ".php"; + if (isset(self::$registeredDirectoriesAutoloader[$fileName])) { + return; + } + self::$registeredDirectoriesAutoloader[$fileName] = true; + if (file_exists($fileName)) { + $include($fileName); + } + }; + + if (!spl_autoload_register( + self::$registeredLoaderAutoloader[$namespace][$directory], true, $prepend - ); + )) { + unset(self::$registeredLoaderAutoloader[$namespace][$directory]); + } + + return is_string(self::$registeredLoaderAutoloader[$namespace][$directory]); } } diff --git a/src/Util/Filter/DataType.php b/src/Util/Filter/DataType.php index 147bd5c..8a3fc46 100644 --- a/src/Util/Filter/DataType.php +++ b/src/Util/Filter/DataType.php @@ -289,4 +289,36 @@ public static function shouldSerialize(mixed $data, bool $doubleSerialize = true return $data; } + + /** + * Append no cache response + * @param ResponseInterface $response + * @return ResponseInterface + */ + public static function appendNoIndex(ResponseInterface $response): ResponseInterface + { + return $response + ->withHeader( + 'X-Robots-Tag', + 'noindex, nofollow, noodp, noydir, noarchive' + ); + } + + /** + * Add no cache response + * + * @param ResponseInterface $response + * @return ResponseInterface + */ + public static function appendNoCache(ResponseInterface $response) : ResponseInterface + { + return $response + ->withHeader( + 'Pragma', + 'no-cache' + )->withHeader( + 'Cache-control', + 'no-store, no-cache, must-revalidate, max-age=0' + ); + } }