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

orchestral / testbench-core / 17421407024

03 Sep 2025 02:38AM UTC coverage: 92.029% (+0.1%) from 91.914%
17421407024

push

github

crynobone
wip

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

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

8 existing lines in 1 file now uncovered.

1547 of 1681 relevant lines covered (92.03%)

77.07 hits per line

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

89.89
/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

230
        if (class_exists(EncodedHtmlString::class)) {
193✔
231
            EncodedHtmlString::flushState();
193✔
232
        }
233

234
        Factory::flushState();
193✔
235

236
        if (! $instance instanceof Commander) {
193✔
237
            if (laravel_version_compare('12.24.0', '<')) {
193✔
UNCOV
238
                HandleExceptions::flushState();
×
239
            } else {
240
                HandleExceptions::flushState($instance);
193✔
241
            }
242
        }
243

244
        JsonResource::wrap('data');
193✔
245

246
        if (method_exists(Markdown::class, 'flushState')) {
193✔
247
            Markdown::flushState();
193✔
248
        }
249

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

273
        if (method_exists(Validator::class, 'flushState')) {
193✔
NEW
274
            Validator::flushState();
×
275
        }
276

277
        ValidateCsrfToken::flushState();
193✔
278
        WorkCommand::flushState();
193✔
279
    }
280

281
    /**
282
     * Configure the application options.
283
     *
284
     * @param  array<string, mixed>  $options
285
     *
286
     * @phpstan-param TConfig  $options
287
     *
288
     * @return $this
289
     */
290
    public function configure(array $options)
291
    {
292
        if (isset($options['load_environment_variables']) && \is_bool($options['load_environment_variables'])) {
14✔
293
            $this->loadEnvironmentVariables = $options['load_environment_variables'];
1✔
294
        }
295

296
        if (isset($options['enables_package_discoveries']) && \is_bool($options['enables_package_discoveries'])) {
14✔
UNCOV
297
            Arr::set($options, 'extra.dont-discover', []);
×
298
        }
299

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

303
        $this->config = $config;
14✔
304

305
        return $this;
14✔
306
    }
307

308
    /**
309
     * Ignore package discovery from.
310
     *
311
     * @api
312
     *
313
     * @return array<int, string>
314
     */
315
    public function ignorePackageDiscoveriesFrom()
316
    {
317
        return $this->config['dont-discover'] ?? [];
15✔
318
    }
319

320
    /**
321
     * Get package providers.
322
     *
323
     * @api
324
     *
325
     * @param  \Illuminate\Foundation\Application  $app
326
     * @return array<int, class-string>
327
     */
328
    protected function getPackageProviders($app)
329
    {
330
        return $this->config['providers'] ?? [];
15✔
331
    }
332

333
    /**
334
     * Get package bootstrapper.
335
     *
336
     * @api
337
     *
338
     * @param  \Illuminate\Foundation\Application  $app
339
     * @return array<int, class-string>
340
     */
341
    protected function getPackageBootstrappers($app)
342
    {
343
        if (\is_null($bootstrappers = ($this->config['bootstrappers'] ?? null))) {
15✔
344
            return [];
13✔
345
        }
346

347
        return Arr::wrap($bootstrappers);
2✔
348
    }
349

350
    /**
351
     * Resolve application resolving callback.
352
     *
353
     * @internal
354
     *
355
     * @param  \Illuminate\Foundation\Application  $app
356
     * @return void
357
     */
358
    protected function resolveApplicationResolvingCallback($app): void
359
    {
360
        $this->resolveApplicationResolvingCallbackFromTrait($app);
15✔
361

362
        if (\is_callable($this->resolvingCallback)) {
15✔
UNCOV
363
            \call_user_func($this->resolvingCallback, $app);
×
364
        }
365
    }
366

367
    /**
368
     * Resolve the application's base path.
369
     *
370
     * @api
371
     *
372
     * @return string
373
     */
374
    protected function getApplicationBasePath()
375
    {
376
        return $this->basePath ?? static::applicationBasePath();
15✔
377
    }
378

379
    /**
380
     * Resolve application core environment variables implementation.
381
     *
382
     * @internal
383
     *
384
     * @param  \Illuminate\Foundation\Application  $app
385
     * @return void
386
     */
387
    protected function resolveApplicationEnvironmentVariables($app)
388
    {
389
        Env::disablePutenv();
15✔
390

391
        $app->terminating(static function () {
15✔
392
            Env::enablePutenv();
1✔
393
        });
15✔
394

395
        if ($this->loadEnvironmentVariables === true) {
15✔
UNCOV
396
            $app->make(LoadEnvironmentVariables::class)->bootstrap($app);
×
397
        }
398

399
        (new Bootstrap\LoadEnvironmentVariablesFromArray($this->config['env'] ?? []))->bootstrap($app);
15✔
400
    }
401

402
    /**
403
     * Resolve application core configuration implementation.
404
     *
405
     * @internal
406
     *
407
     * @param  \Illuminate\Foundation\Application  $app
408
     * @return void
409
     */
410
    protected function resolveApplicationConfiguration($app)
411
    {
412
        $this->resolveApplicationConfigurationFromTrait($app);
15✔
413

414
        (new Bootstrap\EnsuresDefaultConfiguration)->bootstrap($app);
15✔
415
    }
416

417
    /**
418
     * Resolve application Console Kernel implementation.
419
     *
420
     * @api
421
     *
422
     * @param  \Illuminate\Foundation\Application  $app
423
     * @return void
424
     */
425
    protected function resolveApplicationConsoleKernel($app)
426
    {
427
        if ($this->hasCustomApplicationKernels() === true) {
15✔
UNCOV
428
            return;
×
429
        }
430

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

433
        if (is_file($app->basePath(join_paths('app', 'Console', 'Kernel.php'))) && class_exists('App\Console\Kernel')) {
15✔
UNCOV
434
            $kernel = 'App\Console\Kernel';
×
435
        }
436

437
        $app->singleton('Illuminate\Contracts\Console\Kernel', $kernel);
15✔
438
    }
439

440
    /**
441
     * Resolve application HTTP Kernel implementation.
442
     *
443
     * @api
444
     *
445
     * @param  \Illuminate\Foundation\Application  $app
446
     * @return void
447
     */
448
    protected function resolveApplicationHttpKernel($app)
449
    {
450
        if ($this->hasCustomApplicationKernels() === true) {
15✔
UNCOV
451
            return;
×
452
        }
453

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

456
        if (is_file($app->basePath(join_paths('app', 'Http', 'Kernel.php'))) && class_exists('App\Http\Kernel')) {
15✔
UNCOV
457
            $kernel = 'App\Http\Kernel';
×
458
        }
459

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