Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat, refactor: application with bootstrapper #327

Merged
merged 5 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 95 additions & 8 deletions src/System/Integrate/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,32 @@ final class Application extends Container
*/
private $isBooted = false;

/**
* Detect application has been bootstrapped.
*/
private bool $isBootstrapped = false;

/**
* Terminate callback register.
*
* @var callable[]
*/
private $terminateCallback = [];

/**
* Registered booting callback.
*
* @var callable[]
*/
protected array $booting_callbacks = [];

/**
* Registered booted callback.
*
* @var callable[]
*/
protected array $booted_callbacks = [];

/**
* Contructor.
*
Expand All @@ -198,10 +217,6 @@ public function __construct(string $base_path)
// register base provider
$this->register(IntegrateServiceProvider::class);

// boot provider
$this->registerProvider();
$this->bootProvider();

// register container alias
$this->registerAlias();
}
Expand Down Expand Up @@ -829,8 +844,38 @@ public function isDev()
return $this->environment() === 'dev';
}

/**
* Detect appliaction has been booted.
*/
public function isBooted(): bool
{
return $this->isBooted;
}

/**
* Detect application has been bootstrapped.
*/
public function isBootstrapped(): bool
{
return $this->isBootstrapped;
}

// core region

/**
* Bootstrapper.
*
* @param array<int, class-string> $bootstrappers
*/
public function bootstrapWith($bootstrappers): void
{
$this->isBootstrapped = true;

foreach ($bootstrappers as $bootstrapper) {
$this->make($bootstrapper)->bootstrap($this);
}
}

/**
* Boot service provider.
*
Expand All @@ -842,6 +887,8 @@ public function bootProvider()
return;
}

$this->callBootCallbacks($this->booting_callbacks);

foreach ($this->providers as $provider) {
if (in_array($provider, $this->booted_providers)) {
continue;
Expand All @@ -851,6 +898,8 @@ public function bootProvider()
$this->booted_providers[] = $provider;
}

$this->callBootCallbacks($this->booted_callbacks);

$this->isBooted = true;
}

Expand All @@ -861,10 +910,6 @@ public function bootProvider()
*/
public function registerProvider()
{
if (!$this->isBooted) {
return;
}

foreach ($this->providers as $provider) {
if (in_array($provider, $this->looded_providers)) {
continue;
Expand All @@ -876,6 +921,46 @@ public function registerProvider()
}
}

/**
* Call the registered booting callbacks.
*
* @param callable[] $bootCallBacks
*/
public function callBootCallbacks($bootCallBacks): void
{
$index = 0;

while ($index < count($bootCallBacks)) {
$this->call($bootCallBacks[$index]);

$index++;
}
}

/**
* Add booting call back, call before boot is calling.
*
* @param callable[] $callback
*/
public function bootingCallback($callback): void
{
$this->booting_callbacks[] = $callback;
}

/**
* Add booted call back, call after boot is called.
*
* @param callable[] $callback
*/
public function bootedCallback($callback): void
{
$this->booted_callbacks[] = $callback;

if ($this->isBooted()) {
$this->call($callback);
}
}

/**
* Flush or reset application (static).
*/
Expand All @@ -887,6 +972,8 @@ public function flush(): void
$this->looded_providers = [];
$this->booted_providers = [];
$this->terminateCallback = [];
$this->booting_callbacks = [];
$this->booted_callbacks = [];

parent::flush();
}
Expand Down
15 changes: 15 additions & 0 deletions src/System/Integrate/Bootstrap/BootProviders.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace System\Integrate\Bootstrap;

use System\Integrate\Application;

class BootProviders
{
public function bootstrap(Application $app): void
{
$app->bootProvider();
}
}
15 changes: 15 additions & 0 deletions src/System/Integrate/Bootstrap/RegisterProviders.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace System\Integrate\Bootstrap;

use System\Integrate\Application;

class RegisterProviders
{
public function bootstrap(Application $app): void
{
$app->registerProvider();
}
}
22 changes: 22 additions & 0 deletions src/System/Integrate/Console/Karnel.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,25 @@

use System\Console\Style\Style;
use System\Integrate\Application;
use System\Integrate\Bootstrap\BootProviders;
use System\Integrate\Bootstrap\RegisterProviders;

class Karnel
{
/**
* Application Container.
*/
protected Application $app;

/** @var int concole exit status */
protected $exit_code;

/** @var array<int, class-string> Apllication bootstrap register. */
protected array $bootstrappers = [
RegisterProviders::class,
BootProviders::class,
];

/**
* Set instance.
*/
Expand All @@ -34,6 +46,8 @@ public function handle($arguments)
$baseArgs = $arguments[1] ?? '--help';
$commands = [];

$this->bootstrap();

foreach ($this->commands() as $cmd) {
$commands = array_merge($commands, $cmd->patterns(), $cmd->cmd());

Expand Down Expand Up @@ -78,6 +92,14 @@ public function handle($arguments)
return $this->exit_code = 1;
}

/**
* Register bootstraper application.
*/
public function bootstrap(): void
{
$this->app->bootstrapWith($this->bootstrappers);
}

/**
* Return similar from given array, compare with key.
*
Expand Down
21 changes: 21 additions & 0 deletions src/System/Integrate/Http/Karnel.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@
use System\Http\Request;
use System\Http\Response;
use System\Integrate\Application;
use System\Integrate\Bootstrap\BootProviders;
use System\Integrate\Bootstrap\RegisterProviders;
use System\Integrate\Exceptions\Handler;
use System\Integrate\Http\Middleware\MaintenanceMiddleware;
use System\Router\Router;

class Karnel
{
/**
* Application Container.
*/
protected Application $app;

/** @var array<int, class-string> Global middleware */
Expand All @@ -23,6 +28,12 @@ class Karnel
/** @var array<int, class-string> Middleware has register */
protected $middleware_used = [];

/** @var array<int, class-string> Apllication bootstrap register. */
protected array $bootstrappers = [
RegisterProviders::class,
BootProviders::class,
];

/**
* Set instance.
*/
Expand All @@ -43,6 +54,8 @@ public function handle(Request $request)
$this->app->set(Request::class, $request);

try {
$this->bootstrap();

$dispatcher = $this->dispatcher($request);

$pipeline = array_reduce(
Expand All @@ -62,6 +75,14 @@ public function handle(Request $request)
return $response;
}

/**
* Register bootstraper application.
*/
public function bootstrap(): void
{
$this->app->bootstrapWith($this->bootstrappers);
}

/**
* Terminate Requesr and Response.
*/
Expand Down
65 changes: 65 additions & 0 deletions tests/Integrate/ApplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,63 @@ public function itCanAbortApplication()
(new Application(__DIR__))->abort(500);
}

/** @test */
public function itCanBootstrapWith()
{
$app = new Application(__DIR__);

ob_start();
$app->bootstrapWith([
TestBootstrapProvider::class,
]);
$out = ob_get_clean();

$this->assertEquals($out, 'TestBootstrapProvider::bootstrap');
$this->assertTrue($app->isBootstrapped());
}

/** @test */
public function itCanAddCallBacksBeforeAndAfterBoot()
{
$app = new Application(__DIR__);

$app->bootedCallback(static function () {
echo 'booted01';
});
$app->bootedCallback(static function () {
echo 'booted02';
});
$app->bootingCallback(static function () {
echo 'booting01';
});
$app->bootingCallback(static function () {
echo 'booting02';
});

ob_start();
$app->bootProvider();
$out = ob_get_clean();

$this->assertEquals($out, 'booting01booting02booted01booted02');
$this->assertTrue($app->isBooted());
}

public function itCanAddCallImediatllyIfApplicationAlredyBooted()
{
$app = new Application(__DIR__);

$app->bootProvider();

ob_start();
$app->bootedCallback(static function () {
echo 'imediatly call';
});
$out = ob_get_clean();

$this->assertTrue($app->isBooted());
$this->assertEquals($out, 'imediatly call');
}

/** @test */
public function itCanCallDeprecatedMethod()
{
Expand Down Expand Up @@ -238,3 +295,11 @@ private function defaultConfigs()
];
}
}

class TestBootstrapProvider
{
public function bootstrap(Application $app): void
{
echo __CLASS__ . '::' . __FUNCTION__;
}
}
Loading
Loading