diff --git a/Application.php b/Application.php index b458dee..41bcbdd 100644 --- a/Application.php +++ b/Application.php @@ -4,6 +4,7 @@ namespace Codefy\Framework; +use Codefy\Framework\Configuration\ApplicationBuilder; use Codefy\Framework\Factory\FileLoggerFactory; use Codefy\Framework\Factory\FileLoggerSmtpFactory; use Codefy\Framework\Pipeline\PipelineBuilder; @@ -68,7 +69,7 @@ final class Application extends Container { use InvokerAware; - public const APP_VERSION = '2.1.2'; + public const APP_VERSION = '2.1.3'; public const MIN_PHP_VERSION = '8.2'; @@ -107,6 +108,8 @@ final class Application extends Container protected array $bootedCallbacks = []; + protected array $registeredCallbacks = []; + private array $param = []; /** @@ -349,7 +352,7 @@ public function forceRegisterServiceProvider(string|Serviceable|Bootable $provid } /** - * Register all configured service providers via config/app.php. + * Register all configured providers. * * @return void * @throws TypeException @@ -365,6 +368,8 @@ public function registerConfiguredServiceProviders(): void foreach ($providers as $serviceProvider) { $this->registerServiceProvider(serviceProvider: $serviceProvider); } + + $this->fireAppCallbacks($this->registeredCallbacks); } /** @@ -750,6 +755,17 @@ public function hasDebugModeEnabled(): bool return false; } + /** + * Register a new callable function. + * + * @param callable $callback + * @return void + */ + public function registered(callable $callback): void + { + $this->registeredCallbacks[] = $callback; + } + protected function coreAliases(): array { return [ @@ -862,6 +878,17 @@ public function isDevelopment(): bool return env(key: 'APP_ENV') === 'development'; } + /** + * Configure a new CodefyPHP application instance. + * + * @throws TypeException + */ + public static function configure(array $config): ApplicationBuilder + { + return (new ApplicationBuilder(new self($config))) + ->withKernels(); + } + /** * Get the globally available instance of the container. * diff --git a/Bootstrap/RegisterProviders.php b/Bootstrap/RegisterProviders.php index 0d49e17..c73d7ca 100644 --- a/Bootstrap/RegisterProviders.php +++ b/Bootstrap/RegisterProviders.php @@ -5,17 +5,70 @@ namespace Codefy\Framework\Bootstrap; use Codefy\Framework\Application; +use Qubus\Config\ConfigContainer; use Qubus\Exception\Data\TypeException; use Qubus\Exception\Exception; -class RegisterProviders +use function array_filter; +use function array_merge; +use function array_unique; +use function array_values; + +final class RegisterProviders { + protected static array $merge = []; + /** * @throws TypeException * @throws Exception */ public function bootstrap(Application $app): void { + $this->mergeAdditionalProviders($app); $app->registerConfiguredServiceProviders(); } + + /** + * Merge additional configured providers into the configuration. + * + * @param Application $app + * @return void + * @throws Exception + */ + protected function mergeAdditionalProviders(Application $app): void + { + /** @var ConfigContainer $config */ + $config = $app->make(name: 'codefy.config'); + + $config->setConfigKey( + 'app.providers', + array_merge( + $config->getConfigKey('app.providers'), + self::$merge + ) + ); + } + + /** + * Merge the given providers into the provider configuration + * before registration. + * + * @param array $providers + * @return void + */ + public static function merge(array $providers): void + { + self::$merge = array_values( + array_filter( + array_unique( + array_merge(self::$merge, $providers) + ) + ) + ); + } + + public static function flushState(): void + { + self::$merge = []; + } } diff --git a/Configuration/ApplicationBuilder.php b/Configuration/ApplicationBuilder.php new file mode 100644 index 0000000..4b5c554 --- /dev/null +++ b/Configuration/ApplicationBuilder.php @@ -0,0 +1,90 @@ +app->singleton( + \Codefy\Framework\Contracts\Kernel::class, + fn() => $this->app->make(name: \Codefy\Framework\Http\Kernel::class) + ); + + $this->app->singleton( + key: \Codefy\Framework\Console\Kernel::class, + value: fn() => $this->app->make(name: \Codefy\Framework\Console\ConsoleKernel::class) + ); + + return $this; + } + + /** + * Register additional service providers. + * + * @param array $providers + * @return $this + */ + public function withProviders(array $providers = []): self + { + RegisterProviders::merge($providers); + + return $this; + } + + /** + * Register an array of singletons that are resource intensive + * or are not called often. + * + * @param array $singletons + * @return $this + */ + public function withSingletons(array $singletons): self + { + $this->registered(function ($app) use ($singletons) { + foreach ($singletons as $key => $callable) { + $app->singleton($key, $callable); + } + }); + + return $this; + } + + /** + * Register a callback to be invoked when the application's + * service providers are registered. + * + * @param callable $callback + * @return $this + */ + public function registered(callable $callback): self + { + $this->app->registered(callback: $callback); + + return $this; + } + + /** + * Return the application instance. + * + * @return Application + */ + public function return(): Application + { + return $this->app; + } +} diff --git a/Console/ConsoleKernel.php b/Console/ConsoleKernel.php index 62b932c..57b1c7a 100644 --- a/Console/ConsoleKernel.php +++ b/Console/ConsoleKernel.php @@ -19,7 +19,7 @@ use function Qubus\Inheritance\Helpers\tap; -class ConsoleKernel +class ConsoleKernel implements Kernel { protected ?Codex $codex = null; @@ -61,6 +61,7 @@ protected function defineConsoleSchedule(): void } /** + * {@inheritDoc} * @throws Exception */ public function handle(InputInterface $input, ?OutputInterface $output = null): int @@ -97,9 +98,7 @@ public function registerCommand(Command $command): void } /** - * Gets all the commands registered. - * - * @return array + * {@inheritDoc} */ public function all(): array { @@ -109,9 +108,7 @@ public function all(): array } /** - * Get the output for the last run command. - * - * @return string + * {@inheritDoc} */ public function output(): string { @@ -121,9 +118,7 @@ public function output(): string } /** - * Bootstrap the console kernel. - * - * @return void + * {@inheritDoc} */ public function bootstrap(): void { @@ -153,12 +148,7 @@ protected function getCodex(): Codex } /** - * Run a Codex console command by name. - * - * @param string $command - * @param array $parameters - * @param bool|OutputInterface|null $outputBuffer - * @return int + * {@inheritDoc} * * @throws CommandNotFoundException * @throws Exception diff --git a/Console/Kernel.php b/Console/Kernel.php new file mode 100644 index 0000000..2abad8d --- /dev/null +++ b/Console/Kernel.php @@ -0,0 +1,51 @@ +return()); it('has exception handled by onFailure method.', function () use ($pipeline) { $result = $pipeline diff --git a/tests/vendor/bootstrap.php b/tests/vendor/bootstrap.php index 2ba7675..f98e8d4 100644 --- a/tests/vendor/bootstrap.php +++ b/tests/vendor/bootstrap.php @@ -4,7 +4,7 @@ use Qubus\Exception\Data\TypeException; try { - return Application::getInstance(dirname(__DIR__, 2)); + return Application::configure(['basePath' => dirname(path: __DIR__, levels: 2)]); } catch (TypeException $e) { return $e->getMessage(); }