• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

orchestral / testbench-core / 17538372481

08 Sep 2025 03:03AM UTC coverage: 92.096% (-0.4%) from 92.525%
17538372481

push

github

crynobone
Merge branch '10.x' into 11.x

37 of 45 new or added lines in 5 files covered. (82.22%)

2 existing lines in 2 files now uncovered.

1538 of 1670 relevant lines covered (92.1%)

75.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.33
/src/Bootstrap/LoadConfiguration.php
1
<?php
2

3
namespace Orchestra\Testbench\Bootstrap;
4

5
use Generator;
6
use Illuminate\Config\Repository;
7
use Illuminate\Contracts\Config\Repository as RepositoryContract;
8
use Illuminate\Contracts\Foundation\Application;
9
use Illuminate\Support\Collection;
10
use Illuminate\Support\LazyCollection;
11
use Orchestra\Sidekick\Env;
12
use RuntimeException;
13
use SplFileInfo;
14
use Symfony\Component\Finder\Finder;
15

16
use function Orchestra\Testbench\default_skeleton_path;
17
use function Orchestra\Testbench\package_path;
18
use function Orchestra\Testbench\uses_default_skeleton;
19

20
/**
21
 * @internal
22
 *
23
 * @phpstan-type TLaravel \Illuminate\Contracts\Foundation\Application
24
 */
25
class LoadConfiguration
26
{
27
    /**
28
     * Cached Laravel Framework default configuration.
29
     *
30
     * @var \Illuminate\Contracts\Config\Repository|null
31
     */
32
    protected static ?RepositoryContract $cachedFrameworkConfigurations = null;
33

34
    /**
35
     * Bootstrap the given application.
36
     *
37
     * @param  TLaravel  $app
38
     * @return void
39
     */
40
    public function bootstrap(Application $app): void
41
    {
42
        $app->instance('config', $config = new Repository([]));
189✔
43

44
        $this->loadConfigurationFiles($app, $config);
189✔
45

46
        if (\is_null($config->get('database.connections.testing'))) {
189✔
47
            $config->set('database.connections.testing', [
189✔
48
                'driver' => 'sqlite',
189✔
49
                'database' => ':memory:',
189✔
50
                'foreign_key_constraints' => Env::get('DB_FOREIGN_KEYS', false),
189✔
51
            ]);
189✔
52
        }
53

54
        $this->configureDefaultDatabaseConnection($config);
189✔
55

56
        mb_internal_encoding('UTF-8');
189✔
57
    }
58

59
    /**
60
     * Load the configuration items from all of the files.
61
     *
62
     * @param  TLaravel  $app
63
     * @param  \Illuminate\Contracts\Config\Repository  $config
64
     * @return void
65
     */
66
    private function loadConfigurationFiles(Application $app, RepositoryContract $config): void
67
    {
68
        $shouldMerge = method_exists($app, 'shouldMergeFrameworkConfiguration')
189✔
69
            ? $app->shouldMergeFrameworkConfiguration()
189✔
NEW
70
            : true;
×
71

72
        static::$cachedFrameworkConfigurations ??= new Repository(
189✔
73
            (new Collection(uses_default_skeleton($app->basePath()) ? [] : $this->getFrameworkDefaultConfigurations()))
189✔
74
                ->transform(fn ($path, $key) => require $path)
189✔
75
                ->all()
189✔
76
        );
189✔
77

78
        $this->extendsLoadedConfiguration(
189✔
79
            (new LazyCollection(function () use ($app) {
189✔
80
                $path = $this->getConfigurationPath($app);
189✔
81

82
                if (\is_string($path)) {
189✔
83
                    yield from $this->getConfigurationsFromPath($path);
189✔
84
                }
85
            }))
189✔
86
                ->collect()
189✔
87
                ->transform(fn ($path, $key) => $this->resolveConfigurationFile($path, $key))
189✔
88
        )->each(static function ($path, $key) use ($config) {
189✔
89
            $config->set($key, require $path);
189✔
90
        })->when($shouldMerge === true, static function ($configurations) use ($config) {
189✔
91
            /** @var \Illuminate\Contracts\Config\Repository $baseConfigurations */
92
            $baseConfigurations = static::$cachedFrameworkConfigurations;
189✔
93

94
            /** @var array<int, string> $excludes */
95
            $excludes = $configurations->keys()->all();
189✔
96

97
            (new Collection($baseConfigurations->all()))->reject(
189✔
98
                fn ($data, $key) => \in_array($key, $excludes)
189✔
99
            )->each(function ($data, $key) use ($config) {
189✔
NEW
100
                $config->set($key, $data);
×
101
            });
189✔
102

103
            return $configurations->each(static function ($data, $key) use ($config, $baseConfigurations) {
189✔
104
                foreach (static::mergeableOptions($key) as $option) {
189✔
105
                    $name = "{$key}.{$option}";
189✔
106

107
                    $config->set($name, array_merge(($baseConfigurations->get($name) ?? []), ($config->get($name) ?? [])));
189✔
108
                }
109
            });
189✔
110
        });
189✔
111
    }
112

113
    /**
114
     * Get the configuration file nesting path.
115
     *
116
     * @param  \SplFileInfo  $file
117
     * @param  string  $configPath
118
     * @return string
119
     */
120
    protected function getNestedDirectory(SplFileInfo $file, string $configPath): string
121
    {
122
        $directory = $file->getPath();
189✔
123

124
        if ($nested = trim(str_replace($configPath, '', $directory), DIRECTORY_SEPARATOR)) {
189✔
125
            $nested = str_replace(DIRECTORY_SEPARATOR, '.', $nested).'.';
61✔
126
        }
127

128
        return $nested;
189✔
129
    }
130

131
    /**
132
     * Resolve the configuration file.
133
     *
134
     * @param  string  $path
135
     * @param  string  $key
136
     * @return string
137
     */
138
    protected function resolveConfigurationFile(string $path, string $key): string
139
    {
140
        return $path;
139✔
141
    }
142

143
    /**
144
     * Extend the loaded configuration.
145
     *
146
     * @param  \Illuminate\Support\Collection  $configurations
147
     * @return \Illuminate\Support\Collection
148
     */
149
    protected function extendsLoadedConfiguration(Collection $configurations): Collection
150
    {
151
        return $configurations;
139✔
152
    }
153

154
    /**
155
     * Configure the default database connection.
156
     *
157
     * @param  \Illuminate\Contracts\Config\Repository  $config
158
     * @return void
159
     */
160
    protected function configureDefaultDatabaseConnection(RepositoryContract $config): void
161
    {
162
        if ($config->get('database.default') === 'sqlite' && ! is_file($config->get('database.connections.sqlite.database'))) {
189✔
163
            $config->set('database.default', 'testing');
90✔
164
        }
165
    }
166

167
    /**
168
     * Get the application configuration path.
169
     *
170
     * @param  TLaravel  $app
171
     * @return string
172
     *
173
     * @throws \RuntimeException
174
     */
175
    protected function getConfigurationPath(Application $app): string
176
    {
177
        $configurationPath = is_dir($app->basePath('config'))
189✔
178
            ? $app->basePath('config')
189✔
UNCOV
179
            : default_skeleton_path('config');
×
180

181
        if ($configurationPath === false) {
189✔
NEW
182
            throw new RuntimeException('Unable to locate configuration path');
×
183
        }
184

185
        return $configurationPath;
189✔
186
    }
187

188
    /**
189
     * Get the framework default configurations.
190
     *
191
     * @return array<string, string>
192
     *
193
     * @codeCoverageIgnore
194
     */
195
    protected function getFrameworkDefaultConfigurations(): array
196
    {
197
        return (new LazyCollection(function () {
198
            yield from $this->getConfigurationsFromPath(package_path(['vendor', 'laravel', 'framework', 'config']));
199
        }))->all();
200
    }
201

202
    /**
203
     * Get the configurations from path.
204
     *
205
     * @param  string  $path
206
     * @return \Generator
207
     */
208
    protected function getConfigurationsFromPath(string $path): Generator
209
    {
210
        foreach (Finder::create()->files()->name('*.php')->in($path) as $file) {
189✔
211
            $directory = $this->getNestedDirectory($file, $path);
189✔
212

213
            yield $directory.basename($file->getRealPath(), '.php') => $file->getRealPath();
189✔
214
        }
215
    }
216

217
    /**
218
     * Get the options within the configuration file that should be merged again.
219
     *
220
     * @param  string  $name
221
     * @return array<int, string>
222
     */
223
    public static function mergeableOptions(string $name): array
224
    {
225
        return [
226
            'auth' => ['guards', 'providers', 'passwords'],
227
            'broadcasting' => ['connections'],
228
            'cache' => ['stores'],
229
            'database' => ['connections'],
230
            'filesystems' => ['disks'],
231
            'logging' => ['channels'],
232
            'mail' => ['mailers'],
233
            'queue' => ['connections'],
234
        ][$name] ?? [];
189✔
235
    }
236
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc