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

orchestral / testbench-core / 17602063150

10 Sep 2025 03:15AM UTC coverage: 92.124% (+0.04%) from 92.088%
17602063150

Pull #359

github

web-flow
Merge 9e58435b3 into 0c61023ad
Pull Request #359: Bump minimum `laravel/framework` to 12.28.0+

4 of 4 new or added lines in 1 file covered. (100.0%)

7 existing lines in 1 file now uncovered.

1544 of 1676 relevant lines covered (92.12%)

76.95 hits per line

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

91.67
/src/Foundation/Application.php
1
<?php
2

3
namespace Orchestra\Testbench\Foundation;
4

5
use Illuminate\Console\Application as Artisan;
6
use Illuminate\Console\Scheduling\ScheduleListCommand;
7
use Illuminate\Console\Signals;
8
use Illuminate\Database\Eloquent\Factories\Factory;
9
use Illuminate\Database\Eloquent\Model;
10
use Illuminate\Database\Migrations\Migrator;
11
use Illuminate\Database\Schema\Builder as SchemaBuilder;
12
use Illuminate\Foundation\Bootstrap\HandleExceptions;
13
use Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables;
14
use Illuminate\Foundation\Bootstrap\RegisterProviders;
15
use Illuminate\Foundation\Console\AboutCommand;
16
use Illuminate\Foundation\Console\ChannelListCommand;
17
use Illuminate\Foundation\Console\RouteListCommand;
18
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
19
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance;
20
use Illuminate\Foundation\Http\Middleware\TrimStrings;
21
use Illuminate\Foundation\Http\Middleware\ValidateCsrfToken;
22
use Illuminate\Http\Middleware\TrustHosts;
23
use Illuminate\Http\Middleware\TrustProxies;
24
use Illuminate\Http\Resources\Json\JsonResource;
25
use Illuminate\Mail\Markdown;
26
use Illuminate\Queue\Console\WorkCommand;
27
use Illuminate\Queue\Queue;
28
use Illuminate\Routing\Middleware\ThrottleRequests;
29
use Illuminate\Support\Arr;
30
use Illuminate\Support\EncodedHtmlString;
31
use Illuminate\Support\Once;
32
use Illuminate\Support\Sleep;
33
use Illuminate\Validation\Validator;
34
use Illuminate\View\Component;
35
use Orchestra\Testbench\Concerns\CreatesApplication;
36
use Orchestra\Testbench\Console\Commander;
37
use Orchestra\Testbench\Contracts\Config as ConfigContract;
38
use Orchestra\Testbench\Workbench\Workbench;
39

40
use function Orchestra\Sidekick\join_paths;
41
use function Orchestra\Sidekick\laravel_version_compare;
42

43
/**
44
 * @api
45
 *
46
 * @phpstan-import-type TExtraConfig from \Orchestra\Testbench\Foundation\Config
47
 * @phpstan-import-type TOptionalExtraConfig from \Orchestra\Testbench\Foundation\Config
48
 *
49
 * @phpstan-type TConfig array{
50
 *   extra?: TOptionalExtraConfig,
51
 *   load_environment_variables?: bool,
52
 *   enabled_package_discoveries?: bool
53
 * }
54
 */
55
class Application
56
{
57
    use CreatesApplication {
58
        resolveApplicationResolvingCallback as protected resolveApplicationResolvingCallbackFromTrait;
59
        resolveApplicationConfiguration as protected resolveApplicationConfigurationFromTrait;
60
    }
61

62
    /**
63
     * The Illuminate application instance.
64
     *
65
     * @var \Illuminate\Foundation\Application|null
66
     */
67
    protected $app;
68

69
    /**
70
     * List of configurations.
71
     *
72
     * @var array<string, mixed>
73
     *
74
     * @phpstan-var TExtraConfig
75
     */
76
    protected array $config = [
77
        'env' => [],
78
        'providers' => [],
79
        'dont-discover' => [],
80
        'bootstrappers' => [],
81
    ];
82

83
    /**
84
     * The application resolving callback.
85
     *
86
     * @var (callable(\Illuminate\Foundation\Application):(void))|null
87
     */
88
    protected $resolvingCallback;
89

90
    /**
91
     * Load Environment variables.
92
     *
93
     * @var bool
94
     */
95
    protected bool $loadEnvironmentVariables = false;
96

97
    /**
98
     * Create new application resolver.
99
     *
100
     * @param  string|null  $basePath
101
     * @param  (callable(\Illuminate\Foundation\Application):(void))|null  $resolvingCallback
102
     */
103
    public function __construct(
104
        protected readonly ?string $basePath = null,
105
        ?callable $resolvingCallback = null
106
    ) {
107
        $this->resolvingCallback = $resolvingCallback;
15✔
108
    }
109

110
    /**
111
     * Create new application resolver.
112
     *
113
     * @param  string|null  $basePath
114
     * @param  (callable(\Illuminate\Foundation\Application):(void))|null  $resolvingCallback
115
     * @param  array<string, mixed>  $options
116
     *
117
     * @phpstan-param TConfig  $options
118
     *
119
     * @return static
120
     */
121
    public static function make(?string $basePath = null, ?callable $resolvingCallback = null, array $options = [])
122
    {
123
        return (new static($basePath, $resolvingCallback))->configure($options);
13✔
124
    }
125

126
    /**
127
     * Create new application resolver from configuration file.
128
     *
129
     * @param  \Orchestra\Testbench\Contracts\Config  $config
130
     * @param  (callable(\Illuminate\Foundation\Application):(void))|null  $resolvingCallback
131
     * @param  array<string, mixed>  $options
132
     *
133
     * @phpstan-param TConfig  $options
134
     *
135
     * @return static
136
     */
137
    public static function makeFromConfig(ConfigContract $config, ?callable $resolvingCallback = null, array $options = [])
138
    {
139
        $basePath = $config['laravel'] ?? static::applicationBasePath();
1✔
140

141
        return (new static($config['laravel'], $resolvingCallback))->configure(array_merge($options, [
1✔
142
            'load_environment_variables' => is_file("{$basePath}/.env"),
1✔
143
            'extra' => $config->getExtraAttributes(),
1✔
144
        ]));
1✔
145
    }
146

147
    /**
148
     * Create symlink to vendor path via new application instance.
149
     *
150
     * @param  string|null  $basePath
151
     * @param  string  $workingVendorPath
152
     * @return \Illuminate\Foundation\Application
153
     *
154
     * @codeCoverageIgnore
155
     */
156
    public static function createVendorSymlink(?string $basePath, string $workingVendorPath)
157
    {
158
        $app = static::create(basePath: $basePath, options: ['extra' => ['dont-discover' => ['*']]]);
159

160
        (new Actions\CreateVendorSymlink($workingVendorPath))->handle($app);
161

162
        return $app;
163
    }
164

165
    /**
166
     * Delete symlink to vendor path via new application instance.
167
     *
168
     * @param  string|null  $basePath
169
     * @return \Illuminate\Foundation\Application
170
     *
171
     * @codeCoverageIgnore
172
     */
173
    public static function deleteVendorSymlink(?string $basePath)
174
    {
175
        $app = static::create(basePath: $basePath, options: ['extra' => ['dont-discover' => ['*']]]);
176

177
        (new Actions\DeleteVendorSymlink)->handle($app);
178

179
        return $app;
180
    }
181

182
    /**
183
     * Create new application instance.
184
     *
185
     * @param  string|null  $basePath
186
     * @param  (callable(\Illuminate\Foundation\Application):(void))|null  $resolvingCallback
187
     * @param  array<string, mixed>  $options
188
     *
189
     * @phpstan-param TConfig  $options
190
     *
191
     * @return \Illuminate\Foundation\Application
192
     */
193
    public static function create(?string $basePath = null, ?callable $resolvingCallback = null, array $options = [])
194
    {
195
        return static::make($basePath, $resolvingCallback, $options)->createApplication();
10✔
196
    }
197

198
    /**
199
     * Create new application instance from configuration file.
200
     *
201
     * @param  \Orchestra\Testbench\Contracts\Config  $config
202
     * @param  (callable(\Illuminate\Foundation\Application):(void))|null  $resolvingCallback
203
     * @param  array<string, mixed>  $options
204
     *
205
     * @phpstan-param TConfig  $options
206
     *
207
     * @return \Illuminate\Foundation\Application
208
     */
209
    public static function createFromConfig(ConfigContract $config, ?callable $resolvingCallback = null, array $options = [])
210
    {
211
        return static::makeFromConfig($config, $resolvingCallback, $options)->createApplication();
1✔
212
    }
213

214
    /**
215
     * Flush the application states.
216
     *
217
     * @param  \Orchestra\Testbench\Console\Commander|\Orchestra\Testbench\PHPUnit\TestCase  $instance
218
     * @return void
219
     */
220
    public static function flushState(object $instance): void
221
    {
222
        AboutCommand::flushState();
193✔
223
        Artisan::forgetBootstrappers();
193✔
224
        ChannelListCommand::resolveTerminalWidthUsing(null);
193✔
225
        Component::flushCache();
193✔
226
        Component::forgetComponentsResolver();
193✔
227
        Component::forgetFactory();
193✔
228
        ConvertEmptyStringsToNull::flushState();
193✔
229
        EncodedHtmlString::flushState();
193✔
230
        Factory::flushState();
193✔
231

232
        if (! $instance instanceof Commander) {
193✔
233
            HandleExceptions::flushState($instance);
193✔
234
        }
235

236
        JsonResource::wrap('data');
193✔
237
        Markdown::flushState();
193✔
238
        Migrator::withoutMigrations([]);
193✔
239
        Model::handleDiscardedAttributeViolationUsing(null);
193✔
240
        Model::handleLazyLoadingViolationUsing(null);
193✔
241
        Model::handleMissingAttributeViolationUsing(null);
193✔
242
        Model::automaticallyEagerLoadRelationships(false);
193✔
243
        Model::preventAccessingMissingAttributes(false);
193✔
244
        Model::preventLazyLoading(false);
193✔
245
        Model::preventSilentlyDiscardingAttributes(false);
193✔
246
        Once::flush();
193✔
247
        PreventRequestsDuringMaintenance::flushState();
193✔
248
        Queue::createPayloadUsing(null);
193✔
249
        RegisterProviders::flushState();
193✔
250
        RouteListCommand::resolveTerminalWidthUsing(null);
193✔
251
        ScheduleListCommand::resolveTerminalWidthUsing(null);
193✔
252
        SchemaBuilder::$defaultStringLength = 255;
193✔
253
        SchemaBuilder::$defaultMorphKeyType = 'int';
193✔
254
        Signals::resolveAvailabilityUsing(null); // @phpstan-ignore argument.type
193✔
255
        Sleep::fake(false);
193✔
256
        ThrottleRequests::shouldHashKeys();
193✔
257
        TrimStrings::flushState();
193✔
258
        TrustProxies::flushState();
193✔
259
        TrustHosts::flushState();
193✔
260
        Validator::flushState();
193✔
261
        ValidateCsrfToken::flushState();
193✔
262
        WorkCommand::flushState();
193✔
263
    }
264

265
    /**
266
     * Configure the application options.
267
     *
268
     * @param  array<string, mixed>  $options
269
     *
270
     * @phpstan-param TConfig  $options
271
     *
272
     * @return $this
273
     */
274
    public function configure(array $options)
275
    {
276
        if (isset($options['load_environment_variables']) && \is_bool($options['load_environment_variables'])) {
14✔
277
            $this->loadEnvironmentVariables = $options['load_environment_variables'];
1✔
278
        }
279

280
        if (isset($options['enables_package_discoveries']) && \is_bool($options['enables_package_discoveries'])) {
14✔
UNCOV
281
            Arr::set($options, 'extra.dont-discover', []);
×
282
        }
283

284
        /** @var TExtraConfig $config */
285
        $config = Arr::only($options['extra'] ?? [], array_keys($this->config));
14✔
286

287
        $this->config = $config;
14✔
288

289
        return $this;
14✔
290
    }
291

292
    /**
293
     * Ignore package discovery from.
294
     *
295
     * @api
296
     *
297
     * @return array<int, string>
298
     */
299
    public function ignorePackageDiscoveriesFrom()
300
    {
301
        return $this->config['dont-discover'] ?? [];
15✔
302
    }
303

304
    /**
305
     * Get package providers.
306
     *
307
     * @api
308
     *
309
     * @param  \Illuminate\Foundation\Application  $app
310
     * @return array<int, class-string>
311
     */
312
    protected function getPackageProviders($app)
313
    {
314
        return $this->config['providers'] ?? [];
15✔
315
    }
316

317
    /**
318
     * Get package bootstrapper.
319
     *
320
     * @api
321
     *
322
     * @param  \Illuminate\Foundation\Application  $app
323
     * @return array<int, class-string>
324
     */
325
    protected function getPackageBootstrappers($app)
326
    {
327
        if (\is_null($bootstrappers = ($this->config['bootstrappers'] ?? null))) {
15✔
328
            return [];
13✔
329
        }
330

331
        return Arr::wrap($bootstrappers);
2✔
332
    }
333

334
    /**
335
     * Resolve application resolving callback.
336
     *
337
     * @internal
338
     *
339
     * @param  \Illuminate\Foundation\Application  $app
340
     * @return void
341
     */
342
    protected function resolveApplicationResolvingCallback($app): void
343
    {
344
        $this->resolveApplicationResolvingCallbackFromTrait($app);
15✔
345

346
        if (\is_callable($this->resolvingCallback)) {
15✔
UNCOV
347
            \call_user_func($this->resolvingCallback, $app);
×
348
        }
349
    }
350

351
    /**
352
     * Resolve the application's base path.
353
     *
354
     * @api
355
     *
356
     * @return string
357
     */
358
    protected function getApplicationBasePath()
359
    {
360
        return $this->basePath ?? static::applicationBasePath();
15✔
361
    }
362

363
    /**
364
     * Resolve application core environment variables implementation.
365
     *
366
     * @internal
367
     *
368
     * @param  \Illuminate\Foundation\Application  $app
369
     * @return void
370
     */
371
    protected function resolveApplicationEnvironmentVariables($app)
372
    {
373
        Env::disablePutenv();
15✔
374

375
        $app->terminating(static function () {
15✔
376
            Env::enablePutenv();
1✔
377
        });
15✔
378

379
        if ($this->loadEnvironmentVariables === true) {
15✔
UNCOV
380
            $app->make(LoadEnvironmentVariables::class)->bootstrap($app);
×
381
        }
382

383
        (new Bootstrap\LoadEnvironmentVariablesFromArray($this->config['env'] ?? []))->bootstrap($app);
15✔
384
    }
385

386
    /**
387
     * Resolve application core configuration implementation.
388
     *
389
     * @internal
390
     *
391
     * @param  \Illuminate\Foundation\Application  $app
392
     * @return void
393
     */
394
    protected function resolveApplicationConfiguration($app)
395
    {
396
        $this->resolveApplicationConfigurationFromTrait($app);
15✔
397

398
        (new Bootstrap\EnsuresDefaultConfiguration)->bootstrap($app);
15✔
399
    }
400

401
    /**
402
     * Resolve application Console Kernel implementation.
403
     *
404
     * @api
405
     *
406
     * @param  \Illuminate\Foundation\Application  $app
407
     * @return void
408
     */
409
    protected function resolveApplicationConsoleKernel($app)
410
    {
411
        if ($this->hasCustomApplicationKernels() === true) {
15✔
UNCOV
412
            return;
×
413
        }
414

415
        $kernel = Workbench::applicationConsoleKernel() ?? 'Orchestra\Testbench\Console\Kernel';
15✔
416

417
        if (is_file($app->basePath(join_paths('app', 'Console', 'Kernel.php'))) && class_exists('App\Console\Kernel')) {
15✔
UNCOV
418
            $kernel = 'App\Console\Kernel';
×
419
        }
420

421
        $app->singleton('Illuminate\Contracts\Console\Kernel', $kernel);
15✔
422
    }
423

424
    /**
425
     * Resolve application HTTP Kernel implementation.
426
     *
427
     * @api
428
     *
429
     * @param  \Illuminate\Foundation\Application  $app
430
     * @return void
431
     */
432
    protected function resolveApplicationHttpKernel($app)
433
    {
434
        if ($this->hasCustomApplicationKernels() === true) {
15✔
UNCOV
435
            return;
×
436
        }
437

438
        $kernel = Workbench::applicationHttpKernel() ?? 'Orchestra\Testbench\Http\Kernel';
15✔
439

440
        if (is_file($app->basePath(join_paths('app', 'Http', 'Kernel.php'))) && class_exists('App\Http\Kernel')) {
15✔
UNCOV
441
            $kernel = 'App\Http\Kernel';
×
442
        }
443

444
        $app->singleton('Illuminate\Contracts\Http\Kernel', $kernel);
15✔
445
    }
446
}
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