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

orchestral / testbench-core / 16924071631

13 Aug 2025 12:19AM UTC coverage: 92.505%. Remained the same
16924071631

push

github

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

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

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

7 existing lines in 1 file now uncovered.

1518 of 1641 relevant lines covered (92.5%)

75.93 hits per line

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

91.76
/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\View\Component;
34
use Orchestra\Testbench\Concerns\CreatesApplication;
35
use Orchestra\Testbench\Console\Commander;
36
use Orchestra\Testbench\Contracts\Config as ConfigContract;
37
use Orchestra\Testbench\Workbench\Workbench;
38

39
use function Orchestra\Sidekick\join_paths;
40

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

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

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

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

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

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

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

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

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

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

158
        (new Actions\CreateVendorSymlink($workingVendorPath))->handle($app);
159

160
        return $app;
161
    }
162

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

175
        (new Actions\DeleteVendorSymlink)->handle($app);
176

177
        return $app;
178
    }
179

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

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

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

228
        if (class_exists(EncodedHtmlString::class)) {
193✔
229
            EncodedHtmlString::flushState();
193✔
230
        }
231

232
        Factory::flushState();
193✔
233

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

238
        JsonResource::wrap('data');
193✔
239

240
        if (method_exists(Markdown::class, 'flushState')) {
193✔
241
            Markdown::flushState();
193✔
242
        }
243

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

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

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

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

292
        $this->config = $config;
14✔
293

294
        return $this;
14✔
295
    }
296

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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