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

orchestral / testbench-core / 22745492076

06 Mar 2026 01:55AM UTC coverage: 91.393%. Remained the same
22745492076

push

github

crynobone
wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

1529 of 1673 relevant lines covered (91.39%)

77.14 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\Sidekick\Env;
38
use Orchestra\Testbench\Concerns\CreatesApplication;
39
use Orchestra\Testbench\Console\Commander;
40
use Orchestra\Testbench\Contracts\Config as ConfigContract;
41
use Orchestra\Testbench\Workbench\Workbench;
42

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

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

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

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

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

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

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

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

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

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

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

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

164
        return $app;
165
    }
166

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

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

181
        return $app;
182
    }
183

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

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

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

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

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

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

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

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

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

296
        $this->config = $config;
5✔
297

298
        return $this;
5✔
299
    }
300

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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