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

orchestral / testbench-core / 14605732421

22 Apr 2025 10:22PM UTC coverage: 92.431% (+0.08%) from 92.35%
14605732421

push

github

crynobone
wip

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

1502 of 1625 relevant lines covered (92.43%)

73.54 hits per line

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

88.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\Schema\Builder as SchemaBuilder;
9
use Illuminate\Foundation\Bootstrap\HandleExceptions;
10
use Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables;
11
use Illuminate\Foundation\Bootstrap\RegisterProviders;
12
use Illuminate\Foundation\Console\AboutCommand;
13
use Illuminate\Foundation\Console\ChannelListCommand;
14
use Illuminate\Foundation\Console\RouteListCommand;
15
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
16
use Illuminate\Foundation\Http\Middleware\TrimStrings;
17
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
18
use Illuminate\Http\Middleware\TrustProxies;
19
use Illuminate\Http\Resources\Json\JsonResource;
20
use Illuminate\Queue\Console\WorkCommand;
21
use Illuminate\Queue\Queue;
22
use Illuminate\Routing\Middleware\ThrottleRequests;
23
use Illuminate\Support\Arr;
24
use Illuminate\Support\EncodedHtmlString;
25
use Illuminate\Support\Once;
26
use Illuminate\Support\Sleep;
27
use Illuminate\View\Component;
28
use Orchestra\Testbench\Concerns\CreatesApplication;
29
use Orchestra\Testbench\Console\Commander;
30
use Orchestra\Testbench\Contracts\Config as ConfigContract;
31
use Orchestra\Testbench\Workbench\Workbench;
32

33
use function Orchestra\Sidekick\join_paths;
34

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

54
    /**
55
     * The Illuminate application instance.
56
     *
57
     * @var \Illuminate\Foundation\Application|null
58
     */
59
    protected $app;
60

61
    /**
62
     * List of configurations.
63
     *
64
     * @var array<string, mixed>
65
     *
66
     * @phpstan-var TExtraConfig
67
     */
68
    protected array $config = [
69
        'env' => [],
70
        'providers' => [],
71
        'dont-discover' => [],
72
        'bootstrappers' => [],
73
    ];
74

75
    /**
76
     * The application resolving callback.
77
     *
78
     * @var (callable(\Illuminate\Foundation\Application):(void))|null
79
     */
80
    protected $resolvingCallback;
81

82
    /**
83
     * Load Environment variables.
84
     *
85
     * @var bool
86
     */
87
    protected bool $loadEnvironmentVariables = false;
88

89
    /**
90
     * Create new application resolver.
91
     *
92
     * @param  string|null  $basePath
93
     * @param  (callable(\Illuminate\Foundation\Application):(void))|null  $resolvingCallback
94
     */
95
    public function __construct(
96
        protected readonly ?string $basePath = null,
97
        ?callable $resolvingCallback = null
98
    ) {
99
        $this->resolvingCallback = $resolvingCallback;
15✔
100
    }
101

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

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

131
        return (new static($config['laravel'], $resolvingCallback))->configure(array_merge($options, [
1✔
132
            'load_environment_variables' => is_file("{$basePath}/.env"),
1✔
133
            'extra' => $config->getExtraAttributes(),
1✔
134
        ]));
1✔
135
    }
136

137
    /**
138
     * Create symlink to vendor path via new application instance.
139
     *
140
     * @param  string|null  $basePath
141
     * @param  string  $workingVendorPath
142
     * @return \Illuminate\Foundation\Application
143
     *
144
     * @codeCoverageIgnore
145
     */
146
    public static function createVendorSymlink(?string $basePath, string $workingVendorPath)
147
    {
148
        $app = static::create(basePath: $basePath, options: ['extra' => ['dont-discover' => ['*']]]);
149

150
        (new Actions\CreateVendorSymlink($workingVendorPath))->handle($app);
151

152
        return $app;
153
    }
154

155
    /**
156
     * Delete symlink to vendor path via new application instance.
157
     *
158
     * @param  string|null  $basePath
159
     * @return \Illuminate\Foundation\Application
160
     *
161
     * @codeCoverageIgnore
162
     */
163
    public static function deleteVendorSymlink(?string $basePath)
164
    {
165
        $app = static::create(basePath: $basePath, options: ['extra' => ['dont-discover' => ['*']]]);
166

167
        (new Actions\DeleteVendorSymlink)->handle($app);
168

169
        return $app;
170
    }
171

172
    /**
173
     * Create new application instance.
174
     *
175
     * @param  string|null  $basePath
176
     * @param  (callable(\Illuminate\Foundation\Application):(void))|null  $resolvingCallback
177
     * @param  array<string, mixed>  $options
178
     * @return \Illuminate\Foundation\Application
179
     *
180
     * @phpstan-param TConfig  $options
181
     */
182
    public static function create(?string $basePath = null, ?callable $resolvingCallback = null, array $options = [])
183
    {
184
        return static::make($basePath, $resolvingCallback, $options)->createApplication();
10✔
185
    }
186

187
    /**
188
     * Create new application instance from configuration file.
189
     *
190
     * @param  \Orchestra\Testbench\Contracts\Config  $config
191
     * @param  (callable(\Illuminate\Foundation\Application):(void))|null  $resolvingCallback
192
     * @param  array<string, mixed>  $options
193
     * @return \Illuminate\Foundation\Application
194
     *
195
     * @phpstan-param TConfig  $options
196
     */
197
    public static function createFromConfig(ConfigContract $config, ?callable $resolvingCallback = null, array $options = [])
198
    {
199
        return static::makeFromConfig($config, $resolvingCallback, $options)->createApplication();
1✔
200
    }
201

202
    /**
203
     * Flush the application states.
204
     *
205
     * @param  \Orchestra\Testbench\Console\Commander|\Orchestra\Testbench\PHPUnit\TestCase  $instance
206
     * @return void
207
     */
208
    public static function flushState(object $instance): void
209
    {
210
        AboutCommand::flushState();
193✔
211
        Artisan::forgetBootstrappers();
193✔
212
        ChannelListCommand::resolveTerminalWidthUsing(null);
193✔
213
        Component::flushCache();
193✔
214
        Component::forgetComponentsResolver();
193✔
215
        Component::forgetFactory();
193✔
216
        ConvertEmptyStringsToNull::flushState();
193✔
217

218
        if (class_exists(EncodedHtmlString::class)) {
193✔
219
            EncodedHtmlString::flushState();
×
220
        }
221

222
        if (! $instance instanceof Commander) {
193✔
223
            HandleExceptions::flushState();
193✔
224
        }
225

226
        JsonResource::wrap('data');
193✔
227
        Once::flush();
193✔
228
        Queue::createPayloadUsing(null);
193✔
229
        RegisterProviders::flushState();
193✔
230
        RouteListCommand::resolveTerminalWidthUsing(null);
193✔
231
        ScheduleListCommand::resolveTerminalWidthUsing(null);
193✔
232
        SchemaBuilder::$defaultStringLength = 255;
193✔
233
        SchemaBuilder::$defaultMorphKeyType = 'int';
193✔
234
        Signals::resolveAvailabilityUsing(null); // @phpstan-ignore argument.type
193✔
235
        Sleep::fake(false);
193✔
236
        ThrottleRequests::shouldHashKeys();
193✔
237
        TrimStrings::flushState();
193✔
238
        TrustProxies::flushState();
193✔
239
        VerifyCsrfToken::flushState();
193✔
240
        WorkCommand::flushState();
193✔
241
    }
242

243
    /**
244
     * Configure the application options.
245
     *
246
     * @param  array<string, mixed>  $options
247
     * @return $this
248
     *
249
     * @phpstan-param TConfig  $options
250
     */
251
    public function configure(array $options)
252
    {
253
        if (isset($options['load_environment_variables']) && \is_bool($options['load_environment_variables'])) {
14✔
254
            $this->loadEnvironmentVariables = $options['load_environment_variables'];
1✔
255
        }
256

257
        if (isset($options['enables_package_discoveries']) && \is_bool($options['enables_package_discoveries'])) {
14✔
258
            Arr::set($options, 'extra.dont-discover', []);
×
259
        }
260

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

264
        $this->config = $config;
14✔
265

266
        return $this;
14✔
267
    }
268

269
    /**
270
     * Ignore package discovery from.
271
     *
272
     * @api
273
     *
274
     * @return array<int, string>
275
     */
276
    public function ignorePackageDiscoveriesFrom()
277
    {
278
        return $this->config['dont-discover'] ?? [];
15✔
279
    }
280

281
    /**
282
     * Get package providers.
283
     *
284
     * @api
285
     *
286
     * @param  \Illuminate\Foundation\Application  $app
287
     * @return array<int, class-string>
288
     */
289
    protected function getPackageProviders($app)
290
    {
291
        return $this->config['providers'] ?? [];
15✔
292
    }
293

294
    /**
295
     * Get package bootstrapper.
296
     *
297
     * @api
298
     *
299
     * @param  \Illuminate\Foundation\Application  $app
300
     * @return array<int, class-string>
301
     */
302
    protected function getPackageBootstrappers($app)
303
    {
304
        if (\is_null($bootstrappers = ($this->config['bootstrappers'] ?? null))) {
15✔
305
            return [];
13✔
306
        }
307

308
        return Arr::wrap($bootstrappers);
2✔
309
    }
310

311
    /**
312
     * Resolve application resolving callback.
313
     *
314
     * @internal
315
     *
316
     * @param  \Illuminate\Foundation\Application  $app
317
     * @return void
318
     */
319
    protected function resolveApplicationResolvingCallback($app): void
320
    {
321
        $this->resolveApplicationResolvingCallbackFromTrait($app);
15✔
322

323
        if (\is_callable($this->resolvingCallback)) {
15✔
324
            \call_user_func($this->resolvingCallback, $app);
×
325
        }
326
    }
327

328
    /**
329
     * Resolve the application's base path.
330
     *
331
     * @api
332
     *
333
     * @return string
334
     */
335
    protected function getApplicationBasePath()
336
    {
337
        return $this->basePath ?? static::applicationBasePath();
15✔
338
    }
339

340
    /**
341
     * Resolve application core environment variables implementation.
342
     *
343
     * @internal
344
     *
345
     * @param  \Illuminate\Foundation\Application  $app
346
     * @return void
347
     */
348
    protected function resolveApplicationEnvironmentVariables($app)
349
    {
350
        Env::disablePutenv();
15✔
351

352
        $app->terminating(static function () {
15✔
353
            Env::enablePutenv();
1✔
354
        });
15✔
355

356
        if ($this->loadEnvironmentVariables === true) {
15✔
357
            $app->make(LoadEnvironmentVariables::class)->bootstrap($app);
×
358
        }
359

360
        (new Bootstrap\LoadEnvironmentVariablesFromArray($this->config['env'] ?? []))->bootstrap($app);
15✔
361
    }
362

363
    /**
364
     * Resolve application core configuration implementation.
365
     *
366
     * @internal
367
     *
368
     * @param  \Illuminate\Foundation\Application  $app
369
     * @return void
370
     */
371
    protected function resolveApplicationConfiguration($app)
372
    {
373
        $this->resolveApplicationConfigurationFromTrait($app);
15✔
374

375
        (new Bootstrap\EnsuresDefaultConfiguration)->bootstrap($app);
15✔
376
    }
377

378
    /**
379
     * Resolve application Console Kernel implementation.
380
     *
381
     * @api
382
     *
383
     * @param  \Illuminate\Foundation\Application  $app
384
     * @return void
385
     */
386
    protected function resolveApplicationConsoleKernel($app)
387
    {
388
        if ($this->hasCustomApplicationKernels() === true) {
15✔
389
            return;
×
390
        }
391

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

394
        if (is_file($app->basePath(join_paths('app', 'Console', 'Kernel.php'))) && class_exists('App\Console\Kernel')) {
15✔
395
            $kernel = 'App\Console\Kernel';
×
396
        }
397

398
        $app->singleton('Illuminate\Contracts\Console\Kernel', $kernel);
15✔
399
    }
400

401
    /**
402
     * Resolve application HTTP Kernel implementation.
403
     *
404
     * @api
405
     *
406
     * @param  \Illuminate\Foundation\Application  $app
407
     * @return void
408
     */
409
    protected function resolveApplicationHttpKernel($app)
410
    {
411
        if ($this->hasCustomApplicationKernels() === true) {
15✔
412
            return;
×
413
        }
414

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

417
        if (is_file($app->basePath(join_paths('app', 'Http', 'Kernel.php'))) && class_exists('App\Http\Kernel')) {
15✔
418
            $kernel = 'App\Http\Kernel';
×
419
        }
420

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