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

orchestral / testbench-core / 26936896244

04 Jun 2026 07:15AM UTC coverage: 91.413% (+0.02%) from 91.393%
26936896244

push

github

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

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

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

14 existing lines in 4 files now uncovered.

1533 of 1677 relevant lines covered (91.41%)

78.11 hits per line

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

91.95
/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\FormRequest;
19
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
20
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance;
21
use Illuminate\Foundation\Http\Middleware\TrimStrings;
22
use Illuminate\Foundation\Http\Middleware\ValidateCsrfToken;
23
use Illuminate\Http\Middleware\TrustHosts;
24
use Illuminate\Http\Middleware\TrustProxies;
25
use Illuminate\Http\Resources\Json\JsonResource;
26
use Illuminate\Http\Resources\JsonApi\JsonApiResource;
27
use Illuminate\Mail\Markdown;
28
use Illuminate\Queue\Console\WorkCommand;
29
use Illuminate\Queue\Queue;
30
use Illuminate\Routing\Middleware\ThrottleRequests;
31
use Illuminate\Support\Arr;
32
use Illuminate\Support\EncodedHtmlString;
33
use Illuminate\Support\Once;
34
use Illuminate\Support\Sleep;
35
use Illuminate\Support\Str;
36
use Illuminate\Validation\Validator;
37
use Illuminate\View\Component;
38
use Orchestra\Sidekick\Env;
39
use Orchestra\Testbench\Concerns\CreatesApplication;
40
use Orchestra\Testbench\Console\Commander;
41
use Orchestra\Testbench\Contracts\Config as ConfigContract;
42
use Orchestra\Testbench\Workbench\Workbench;
43

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

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

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

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

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

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

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

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

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

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

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

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

165
        return $app;
166
    }
167

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

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

182
        return $app;
183
    }
184

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

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

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

236
        if (! $instance instanceof Commander) {
199✔
237
            HandleExceptions::flushState($instance);
199✔
238
        }
239

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

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

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

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

293
        $this->config = $config;
5✔
294

295
        return $this;
5✔
296
    }
297

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

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

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

337
        return Arr::wrap($bootstrappers);
2✔
338
    }
339

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

352
        if (\is_callable($this->resolvingCallback)) {
6✔
UNCOV
353
            \call_user_func($this->resolvingCallback, $app);
×
354
        }
355
    }
356

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

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

381
        $app->terminating(static function () {
6✔
382
            Env::enablePutenv();
1✔
383
        });
6✔
384

385
        if ($this->loadEnvironmentVariables === true) {
6✔
UNCOV
386
            $app->make(LoadEnvironmentVariables::class)->bootstrap($app);
×
387
        }
388

389
        (new Bootstrap\LoadEnvironmentVariablesFromArray($this->config['env'] ?? []))->bootstrap($app);
6✔
390
    }
391

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

404
        (new Bootstrap\EnsuresDefaultConfiguration)->bootstrap($app);
6✔
405
    }
406

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

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

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

427
        $app->singleton('Illuminate\Contracts\Console\Kernel', $kernel);
6✔
428
    }
429

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

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

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

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