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

orchestral / testbench-core / 21468268332

29 Jan 2026 06:30AM UTC coverage: 91.463% (+0.07%) from 91.398%
21468268332

push

github

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

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

1 existing line in 1 file now uncovered.

1532 of 1675 relevant lines covered (91.46%)

76.84 hits per line

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

90.91
/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\Http\Resources\JsonApi\JsonApiResource;
26
use Illuminate\Mail\Markdown;
27
use Illuminate\Queue\Console\WorkCommand;
28
use Illuminate\Queue\Queue;
29
use Illuminate\Routing\Middleware\ThrottleRequests;
30
use Illuminate\Support\Arr;
31
use Illuminate\Support\EncodedHtmlString;
32
use Illuminate\Support\Once;
33
use Illuminate\Support\Sleep;
34
use Illuminate\Support\Str;
35
use Illuminate\Validation\Validator;
36
use Illuminate\View\Component;
37
use Orchestra\Testbench\Concerns\CreatesApplication;
38
use Orchestra\Testbench\Console\Commander;
39
use Orchestra\Testbench\Contracts\Config as ConfigContract;
40
use Orchestra\Testbench\Workbench\Workbench;
41

42
use function Orchestra\Sidekick\Filesystem\join_paths;
43

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

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

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

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

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

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

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

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

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

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

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

163
        return $app;
164
    }
165

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

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

180
        return $app;
181
    }
182

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

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

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

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

237
        if (class_exists(JsonApiResource::class)) {
196✔
238
            JsonResource::flushState();
196✔
239
            JsonApiResource::flushState();
196✔
240
        } else {
UNCOV
241
            JsonResource::wrap('data');
×
242
        }
243

244
        Markdown::flushState();
196✔
245
        Migrator::withoutMigrations([]);
196✔
246
        Model::handleDiscardedAttributeViolationUsing(null);
196✔
247
        Model::handleLazyLoadingViolationUsing(null);
196✔
248
        Model::handleMissingAttributeViolationUsing(null);
196✔
249
        Model::automaticallyEagerLoadRelationships(false);
196✔
250
        Model::preventAccessingMissingAttributes(false);
196✔
251
        Model::preventLazyLoading(false);
196✔
252
        Model::preventSilentlyDiscardingAttributes(false);
196✔
253
        Once::flush();
196✔
254
        PreventRequestsDuringMaintenance::flushState();
196✔
255
        Queue::createPayloadUsing(null);
196✔
256
        RegisterProviders::flushState();
196✔
257
        RouteListCommand::resolveTerminalWidthUsing(null);
196✔
258
        ScheduleListCommand::resolveTerminalWidthUsing(null);
196✔
259
        SchemaBuilder::$defaultStringLength = 255;
196✔
260
        SchemaBuilder::$defaultMorphKeyType = 'int';
196✔
261
        Signals::resolveAvailabilityUsing(null); // @phpstan-ignore argument.type
196✔
262
        Sleep::fake(false);
196✔
263
        Str::resetFactoryState();
196✔
264
        ThrottleRequests::shouldHashKeys();
196✔
265
        TrimStrings::flushState();
196✔
266
        TrustProxies::flushState();
196✔
267
        TrustHosts::flushState();
196✔
268
        Validator::flushState();
196✔
269
        ValidateCsrfToken::flushState();
196✔
270
        WorkCommand::flushState();
196✔
271
    }
272

273
    /**
274
     * Configure the application options.
275
     *
276
     * @param  array<string, mixed>  $options
277
     *
278
     * @phpstan-param TConfig  $options
279
     *
280
     * @return $this
281
     */
282
    public function configure(array $options)
283
    {
284
        if (isset($options['load_environment_variables']) && \is_bool($options['load_environment_variables'])) {
15✔
285
            $this->loadEnvironmentVariables = $options['load_environment_variables'];
1✔
286
        }
287

288
        if (isset($options['enables_package_discoveries']) && \is_bool($options['enables_package_discoveries'])) {
15✔
289
            Arr::set($options, 'extra.dont-discover', []);
×
290
        }
291

292
        /** @var TExtraConfig $config */
293
        $config = Arr::only($options['extra'] ?? [], array_keys($this->config));
15✔
294

295
        $this->config = $config;
15✔
296

297
        return $this;
15✔
298
    }
299

300
    /**
301
     * Ignore package discovery from.
302
     *
303
     * @api
304
     *
305
     * @return array<int, string>
306
     */
307
    public function ignorePackageDiscoveriesFrom()
308
    {
309
        return $this->config['dont-discover'] ?? [];
16✔
310
    }
311

312
    /**
313
     * Get package providers.
314
     *
315
     * @api
316
     *
317
     * @param  \Illuminate\Foundation\Application  $app
318
     * @return array<int, class-string>
319
     */
320
    protected function getPackageProviders($app)
321
    {
322
        return $this->config['providers'] ?? [];
16✔
323
    }
324

325
    /**
326
     * Get package bootstrapper.
327
     *
328
     * @api
329
     *
330
     * @param  \Illuminate\Foundation\Application  $app
331
     * @return array<int, class-string>
332
     */
333
    protected function getPackageBootstrappers($app)
334
    {
335
        if (\is_null($bootstrappers = ($this->config['bootstrappers'] ?? null))) {
16✔
336
            return [];
14✔
337
        }
338

339
        return Arr::wrap($bootstrappers);
2✔
340
    }
341

342
    /**
343
     * Resolve application resolving callback.
344
     *
345
     * @internal
346
     *
347
     * @param  \Illuminate\Foundation\Application  $app
348
     * @return void
349
     */
350
    protected function resolveApplicationResolvingCallback($app): void
351
    {
352
        $this->resolveApplicationResolvingCallbackFromTrait($app);
16✔
353

354
        if (\is_callable($this->resolvingCallback)) {
16✔
355
            \call_user_func($this->resolvingCallback, $app);
×
356
        }
357
    }
358

359
    /**
360
     * Resolve the application's base path.
361
     *
362
     * @api
363
     *
364
     * @return string
365
     */
366
    protected function getApplicationBasePath()
367
    {
368
        return $this->basePath ?? static::applicationBasePath();
16✔
369
    }
370

371
    /**
372
     * Resolve application core environment variables implementation.
373
     *
374
     * @internal
375
     *
376
     * @param  \Illuminate\Foundation\Application  $app
377
     * @return void
378
     */
379
    protected function resolveApplicationEnvironmentVariables($app)
380
    {
381
        Env::disablePutenv();
16✔
382

383
        $app->terminating(static function () {
16✔
384
            Env::enablePutenv();
1✔
385
        });
16✔
386

387
        if ($this->loadEnvironmentVariables === true) {
16✔
388
            $app->make(LoadEnvironmentVariables::class)->bootstrap($app);
×
389
        }
390

391
        (new Bootstrap\LoadEnvironmentVariablesFromArray($this->config['env'] ?? []))->bootstrap($app);
16✔
392
    }
393

394
    /**
395
     * Resolve application core configuration implementation.
396
     *
397
     * @internal
398
     *
399
     * @param  \Illuminate\Foundation\Application  $app
400
     * @return void
401
     */
402
    protected function resolveApplicationConfiguration($app)
403
    {
404
        $this->resolveApplicationConfigurationFromTrait($app);
16✔
405

406
        (new Bootstrap\EnsuresDefaultConfiguration)->bootstrap($app);
16✔
407
    }
408

409
    /**
410
     * Resolve application Console Kernel implementation.
411
     *
412
     * @api
413
     *
414
     * @param  \Illuminate\Foundation\Application  $app
415
     * @return void
416
     */
417
    protected function resolveApplicationConsoleKernel($app)
418
    {
419
        if ($this->hasCustomApplicationKernels() === true) {
16✔
420
            return;
×
421
        }
422

423
        $kernel = Workbench::applicationConsoleKernel() ?? 'Orchestra\Testbench\Console\Kernel';
16✔
424

425
        if (is_file($app->basePath(join_paths('app', 'Console', 'Kernel.php'))) && class_exists('App\Console\Kernel')) {
16✔
426
            $kernel = 'App\Console\Kernel';
×
427
        }
428

429
        $app->singleton('Illuminate\Contracts\Console\Kernel', $kernel);
16✔
430
    }
431

432
    /**
433
     * Resolve application HTTP Kernel implementation.
434
     *
435
     * @api
436
     *
437
     * @param  \Illuminate\Foundation\Application  $app
438
     * @return void
439
     */
440
    protected function resolveApplicationHttpKernel($app)
441
    {
442
        if ($this->hasCustomApplicationKernels() === true) {
16✔
443
            return;
×
444
        }
445

446
        $kernel = Workbench::applicationHttpKernel() ?? 'Orchestra\Testbench\Http\Kernel';
16✔
447

448
        if (is_file($app->basePath(join_paths('app', 'Http', 'Kernel.php'))) && class_exists('App\Http\Kernel')) {
16✔
449
            $kernel = 'App\Http\Kernel';
×
450
        }
451

452
        $app->singleton('Illuminate\Contracts\Http\Kernel', $kernel);
16✔
453
    }
454
}
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