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

Refactor console kernel bootstrapper loading #1772

Merged
merged 10 commits into from
Jul 1, 2024
27 changes: 12 additions & 15 deletions packages/framework/src/Foundation/ConsoleKernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@
namespace Hyde\Foundation;

use LaravelZero\Framework\Kernel;
use Hyde\Foundation\Internal\LoadYamlConfiguration;

use function array_combine;
use function array_splice;
use function array_values;
use function tap;

class ConsoleKernel extends Kernel
{
Expand All @@ -19,17 +13,20 @@ class ConsoleKernel extends Kernel
*/
protected function bootstrappers(): array
{
$bootstrappers = $this->bootstrappers;

// Insert our bootstrapper between load configuration and register provider bootstrappers.
array_splice($bootstrappers, 5, 0, LoadYamlConfiguration::class);

// Since we store our application config in `app/config.php`, we need to replace
// the default LoadConfiguration bootstrapper class with our implementation.
// We do this by swapping out the LoadConfiguration class with our own.

return array_values((array) tap(array_combine($bootstrappers, $bootstrappers), function (array &$array): void {
$array[\LaravelZero\Framework\Bootstrap\LoadConfiguration::class] = \Hyde\Foundation\Internal\LoadConfiguration::class;
}));
// We also inject our Yaml configuration loading bootstrapper.

return [
\LaravelZero\Framework\Bootstrap\CoreBindings::class,
\LaravelZero\Framework\Bootstrap\LoadEnvironmentVariables::class,
\Hyde\Foundation\Internal\LoadConfiguration::class,
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
\LaravelZero\Framework\Bootstrap\RegisterFacades::class,
\Hyde\Foundation\Internal\LoadYamlConfiguration::class,
\LaravelZero\Framework\Bootstrap\RegisterProviders::class,
\Illuminate\Foundation\Bootstrap\BootProviders::class,
];
}
}
49 changes: 34 additions & 15 deletions packages/framework/tests/Feature/ConsoleKernelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@

namespace Hyde\Framework\Testing\Feature;

use LaravelZero\Framework\Kernel as LaravelZeroKernel;
use Hyde\Foundation\Internal\LoadYamlConfiguration;
use Illuminate\Contracts\Console\Kernel;
use Hyde\Foundation\ConsoleKernel;
use Hyde\Testing\TestCase;
use ReflectionMethod;

/**
* This test covers our custom console kernel, which is responsible for registering our custom bootstrappers.
*
* @covers \Hyde\Foundation\ConsoleKernel
*
* Our custom bootstrapping system depends on code from Laravel Zero which is marked as internal.
* Sadly, there is no way around working with this private API. Since they may change the API
* at any time, we have tests here to detect if their code changes, so we can catch it early.
*/
class ConsoleKernelTest extends TestCase
{
Expand All @@ -25,28 +32,40 @@ public function testClassImplementsKernelInterface()
$this->assertInstanceOf(Kernel::class, app(ConsoleKernel::class));
}

public function testBootstrappers()
public function testLaravelZeroBootstrappersHaveNotChanged()
{
$kernel = app(ConsoleKernel::class);
$this->assertSame([
\LaravelZero\Framework\Bootstrap\CoreBindings::class,
\LaravelZero\Framework\Bootstrap\LoadEnvironmentVariables::class,
\LaravelZero\Framework\Bootstrap\LoadConfiguration::class,
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
\LaravelZero\Framework\Bootstrap\RegisterFacades::class,
\LaravelZero\Framework\Bootstrap\RegisterProviders::class,
\Illuminate\Foundation\Bootstrap\BootProviders::class,
], $this->getBootstrappersFromKernel(app(LaravelZeroKernel::class)));
}

// Normally, protected code does not need to be unit tested, but since this array is so vital, we want to inspect it.
$bootstrappers = (new ReflectionMethod($kernel, 'bootstrappers'))->invoke($kernel);
public function testHydeBootstrapperInjections()
{
$bootstrappers = $this->getBootstrappersFromKernel(app(ConsoleKernel::class));

$this->assertIsArray($bootstrappers);
$this->assertContains(LoadYamlConfiguration::class, $bootstrappers);

// Another assertion that is usually a no-no, testing vendor code, especially those which are marked as internal.
// We do this here however, so we get a heads-up if the vendor code changes as that could break our code.

$this->assertSame([
0 => 'LaravelZero\Framework\Bootstrap\CoreBindings',
1 => 'LaravelZero\Framework\Bootstrap\LoadEnvironmentVariables',
2 => 'Hyde\Foundation\Internal\LoadConfiguration',
3 => 'Illuminate\Foundation\Bootstrap\HandleExceptions',
4 => 'LaravelZero\Framework\Bootstrap\RegisterFacades',
5 => 'Hyde\Foundation\Internal\LoadYamlConfiguration',
6 => 'LaravelZero\Framework\Bootstrap\RegisterProviders',
7 => 'Illuminate\Foundation\Bootstrap\BootProviders',
\LaravelZero\Framework\Bootstrap\CoreBindings::class,
\LaravelZero\Framework\Bootstrap\LoadEnvironmentVariables::class,
\Hyde\Foundation\Internal\LoadConfiguration::class,
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
\LaravelZero\Framework\Bootstrap\RegisterFacades::class,
\Hyde\Foundation\Internal\LoadYamlConfiguration::class,
\LaravelZero\Framework\Bootstrap\RegisterProviders::class,
\Illuminate\Foundation\Bootstrap\BootProviders::class,
], $bootstrappers);
}

protected function getBootstrappersFromKernel(\Illuminate\Foundation\Console\Kernel $kernel): array
{
return (new ReflectionMethod($kernel, 'bootstrappers'))->invoke($kernel);
}
}
Loading