Skip to content
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
33 changes: 30 additions & 3 deletions src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Illuminate\Foundation\Bootstrap;

use Closure;
use Illuminate\Config\Repository;
use Illuminate\Contracts\Config\Repository as RepositoryContract;
use Illuminate\Contracts\Foundation\Application;
Expand All @@ -11,6 +12,13 @@

class LoadConfiguration
{
/**
* The closure that resolves the permanent, static configuration if applicable.
*
* @var (Closure(Application): array<array-key, mixed>)|null
*/
protected static ?Closure $alwaysUseConfig = null;

/**
* Bootstrap the given application.
*
Expand All @@ -24,18 +32,26 @@ public function bootstrap(Application $app)
// First we will see if we have a cache configuration file. If we do, we'll load
// the configuration items from that file so that it is very quick. Otherwise
// we will need to spin through every configuration file and load them all.
if (file_exists($cached = $app->getCachedConfigPath())) {
$loadedFromCache = false;

if (self::$alwaysUseConfig !== null) {
$items = $app->call(self::$alwaysUseConfig);

$loadedFromCache = true;
} elseif (file_exists($cached = $app->getCachedConfigPath())) {
$items = require $cached;

$app->instance('config_loaded_from_cache', $loadedFromCache = true);
$loadedFromCache = true;
}

$app->instance('config_loaded_from_cache', $loadedFromCache);

// Next we will spin through all of the configuration files in the configuration
// directory and load each one into the repository. This will make all of the
// options available to the developer for use in various parts of this app.
$app->instance('config', $config = new Repository($items));

if (! isset($loadedFromCache)) {
if (! $loadedFromCache) {
$this->loadConfigurationFiles($app, $config);
}

Expand Down Expand Up @@ -195,4 +211,15 @@ protected function getBaseConfiguration()

return $config;
}

/**
* Set a callback to return the permanent, static configuration values.
*
* @param (Closure(Application): array<array-key, mixed>)|null $alwaysUseConfig
* @return void
*/
public static function alwaysUse(?Closure $alwaysUseConfig): void
{
static::$alwaysUseConfig = $alwaysUseConfig;
}
}
1 change: 1 addition & 0 deletions src/Illuminate/Foundation/Testing/CachedState.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
class CachedState
{
public static array $cachedRoutes;
public static array $cachedConfig;
}
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ protected function tearDownTheTestEnvironment(): void
*/
protected function setUpTraits()
{
$uses = array_flip(class_uses_recursive(static::class));
$uses = $this->traitsUsedByTest ?? array_flip(class_uses_recursive(static::class));

if (isset($uses[RefreshDatabase::class])) {
$this->refreshDatabase();
Expand Down
16 changes: 15 additions & 1 deletion src/Illuminate/Foundation/Testing/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ abstract class TestCase extends BaseTestCase
Concerns\InteractsWithTestCaseLifecycle,
Concerns\InteractsWithViews;

/**
* The list of trait that this test uses, fetched recursively.
*
* @var array<class-string, int>
*/
protected array $traitsUsedByTest;

/**
* Creates the application.
*
Expand All @@ -29,8 +36,15 @@ public function createApplication()
{
$app = require Application::inferBasePath().'/bootstrap/app.php';

$this->traitsUsedByTest = array_flip(class_uses_recursive(static::class));

if (isset(CachedState::$cachedConfig) &&
isset($this->traitsUsedByTest[WithCachedConfig::class])) {
$this->markConfigCached($app);
}

if (isset(CachedState::$cachedRoutes) &&
in_array(WithCachedRoutes::class, class_uses_recursive(static::class))) {
isset($this->traitsUsedByTest[WithCachedRoutes::class])) {
$app->booting(fn () => $this->markRoutesCached($app));
}

Expand Down
41 changes: 41 additions & 0 deletions src/Illuminate/Foundation/Testing/WithCachedConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Illuminate\Foundation\Testing;

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Bootstrap\LoadConfiguration;

trait WithCachedConfig
{
/**
* After resolving the configuration once, we can cache it for the remaining tests.
*/
protected function setUpWithCachedConfig(): void
{
if ((CachedState::$cachedConfig ?? null) === null) {
CachedState::$cachedConfig = $this->app->make('config')->all();
}

$this->markConfigCached($this->app);
}

/**
* Reset the cached configuration.
*
* This is helpful if some of the tests in the suite apply this trait while others do not.
*/
protected function tearDownWithCachedConfig(): void
{
LoadConfiguration::setAlwaysUseConfig(null);
}

/**
* Inform the container that the configuration is cached.
*/
protected function markConfigCached(Application $app): void
{
$app->instance('config_loaded_from_cache', true); // I'm not sure this is actually needed

LoadConfiguration::alwaysUse(static fn () => CachedState::$cachedConfig);
}
}