-
+

@yield('code') -

+ -
+
@yield('message')
diff --git a/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php b/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php index 1c20d22051b1..c3944d6c72f7 100644 --- a/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php +++ b/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php @@ -127,14 +127,14 @@ protected function hasValidBypassCookie($request, array $data) } /** - * Redirect the user back to the root of the application with a maintenance mode bypass cookie. + * Redirect the user to their intended destination with a maintenance mode bypass cookie. * * @param string $secret * @return \Illuminate\Http\RedirectResponse */ protected function bypassResponse(string $secret) { - return redirect('/')->withCookie( + return redirect()->intended('/')->withCookie( MaintenanceModeBypassCookie::create($secret) ); } diff --git a/src/Illuminate/Foundation/Inspiring.php b/src/Illuminate/Foundation/Inspiring.php index 59891493d9b5..3d4c6d83ef25 100644 --- a/src/Illuminate/Foundation/Inspiring.php +++ b/src/Illuminate/Foundation/Inspiring.php @@ -106,6 +106,7 @@ public static function quotes() 'The biggest battle is the war against ignorance. - Mustafa Kemal Atatürk', 'Always remember that you are absolutely unique. Just like everyone else. - Margaret Mead', 'You must be the change you wish to see in the world. - Mahatma Gandhi', + 'It always seems impossible until it is done. - Nelson Mandela', 'We must ship. - Taylor Otwell', ]); } diff --git a/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php b/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php index ae5fdc9c9c4e..0ac742bb9935 100755 --- a/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php @@ -39,6 +39,7 @@ use Illuminate\Foundation\Console\ComponentMakeCommand; use Illuminate\Foundation\Console\ConfigCacheCommand; use Illuminate\Foundation\Console\ConfigClearCommand; +use Illuminate\Foundation\Console\ConfigMakeCommand; use Illuminate\Foundation\Console\ConfigPublishCommand; use Illuminate\Foundation\Console\ConfigShowCommand; use Illuminate\Foundation\Console\ConsoleMakeCommand; @@ -69,6 +70,7 @@ use Illuminate\Foundation\Console\PackageDiscoverCommand; use Illuminate\Foundation\Console\PolicyMakeCommand; use Illuminate\Foundation\Console\ProviderMakeCommand; +use Illuminate\Foundation\Console\ReloadCommand; use Illuminate\Foundation\Console\RequestMakeCommand; use Illuminate\Foundation\Console\ResourceMakeCommand; use Illuminate\Foundation\Console\RouteCacheCommand; @@ -96,9 +98,11 @@ use Illuminate\Queue\Console\ListenCommand as QueueListenCommand; use Illuminate\Queue\Console\ListFailedCommand as ListFailedQueueCommand; use Illuminate\Queue\Console\MonitorCommand as QueueMonitorCommand; +use Illuminate\Queue\Console\PauseCommand as QueuePauseCommand; use Illuminate\Queue\Console\PruneBatchesCommand as QueuePruneBatchesCommand; use Illuminate\Queue\Console\PruneFailedJobsCommand as QueuePruneFailedJobsCommand; use Illuminate\Queue\Console\RestartCommand as QueueRestartCommand; +use Illuminate\Queue\Console\ResumeCommand as QueueResumeCommand; use Illuminate\Queue\Console\RetryBatchCommand as QueueRetryBatchCommand; use Illuminate\Queue\Console\RetryCommand as QueueRetryCommand; use Illuminate\Queue\Console\TableCommand; @@ -149,12 +153,15 @@ class ArtisanServiceProvider extends ServiceProvider implements DeferrableProvid 'QueueForget' => ForgetFailedQueueCommand::class, 'QueueListen' => QueueListenCommand::class, 'QueueMonitor' => QueueMonitorCommand::class, + 'QueuePause' => QueuePauseCommand::class, 'QueuePruneBatches' => QueuePruneBatchesCommand::class, 'QueuePruneFailedJobs' => QueuePruneFailedJobsCommand::class, 'QueueRestart' => QueueRestartCommand::class, + 'QueueResume' => QueueResumeCommand::class, 'QueueRetry' => QueueRetryCommand::class, 'QueueRetryBatch' => QueueRetryBatchCommand::class, 'QueueWork' => QueueWorkCommand::class, + 'Reload' => ReloadCommand::class, 'RouteCache' => RouteCacheCommand::class, 'RouteClear' => RouteClearCommand::class, 'RouteList' => RouteListCommand::class, @@ -189,6 +196,7 @@ class ArtisanServiceProvider extends ServiceProvider implements DeferrableProvid 'ChannelMake' => ChannelMakeCommand::class, 'ClassMake' => ClassMakeCommand::class, 'ComponentMake' => ComponentMakeCommand::class, + 'ConfigMake' => ConfigMakeCommand::class, 'ConfigPublish' => ConfigPublishCommand::class, 'ConsoleMake' => ConsoleMakeCommand::class, 'ControllerMake' => ControllerMakeCommand::class, @@ -250,7 +258,6 @@ public function register() /** * Register the given commands. * - * @param array $commands * @return void */ protected function registerCommands(array $commands) @@ -388,6 +395,18 @@ protected function registerConfigClearCommand() }); } + /** + * Register the command. + * + * @return void + */ + protected function registerConfigMakeCommand() + { + $this->app->singleton(ConfigMakeCommand::class, function ($app) { + return new ConfigMakeCommand($app['files']); + }); + } + /** * Register the command. * @@ -395,7 +414,7 @@ protected function registerConfigClearCommand() */ protected function registerConfigPublishCommand() { - $this->app->singleton(ConfigPublishCommand::class, function ($app) { + $this->app->singleton(ConfigPublishCommand::class, function () { return new ConfigPublishCommand; }); } diff --git a/src/Illuminate/Foundation/Providers/FoundationServiceProvider.php b/src/Illuminate/Foundation/Providers/FoundationServiceProvider.php index fca2cc61057f..625e3f608bf3 100644 --- a/src/Illuminate/Foundation/Providers/FoundationServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/FoundationServiceProvider.php @@ -8,6 +8,7 @@ use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Contracts\Foundation\Application; +use Illuminate\Contracts\Foundation\ExceptionRenderer; use Illuminate\Contracts\Foundation\MaintenanceMode as MaintenanceModeContract; use Illuminate\Contracts\View\Factory; use Illuminate\Database\ConnectionInterface; @@ -70,7 +71,7 @@ public function boot() ], 'laravel-errors'); } - if ($this->app->hasDebugModeEnabled()) { + if ($this->app->hasDebugModeEnabled() && ! $this->app->has(ExceptionRenderer::class)) { $this->app->make(Listener::class)->registerListeners( $this->app->make(Dispatcher::class) ); @@ -210,13 +211,11 @@ protected function registerDeferHandler() $this->app->scoped(DeferredCallbackCollection::class); $this->app['events']->listen(function (CommandFinished $event) { - app(DeferredCallbackCollection::class)->invokeWhen(fn ($callback) => app()->runningInConsole() && ($event->exitCode === 0 || $callback->always) - ); + app(DeferredCallbackCollection::class)->invokeWhen(fn ($callback) => app()->runningInConsole() && ($event->exitCode === 0 || $callback->always)); }); $this->app['events']->listen(function (JobAttempted $event) { - app(DeferredCallbackCollection::class)->invokeWhen(fn ($callback) => $event->connectionName !== 'sync' && ($event->successful() || $callback->always) - ); + app(DeferredCallbackCollection::class)->invokeWhen(fn ($callback) => $event->connectionName !== 'sync' && ($event->successful() || $callback->always)); }); } diff --git a/src/Illuminate/Foundation/Support/Providers/EventServiceProvider.php b/src/Illuminate/Foundation/Support/Providers/EventServiceProvider.php index d5074505302d..ac7b3ec7838b 100644 --- a/src/Illuminate/Foundation/Support/Providers/EventServiceProvider.php +++ b/src/Illuminate/Foundation/Support/Providers/EventServiceProvider.php @@ -6,8 +6,8 @@ use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Events\DiscoverEvents; use Illuminate\Support\Arr; -use Illuminate\Support\Collection; use Illuminate\Support\Facades\Event; +use Illuminate\Support\LazyCollection; use Illuminate\Support\ServiceProvider; class EventServiceProvider extends ServiceProvider @@ -43,7 +43,7 @@ class EventServiceProvider extends ServiceProvider /** * The configured event discovery paths. * - * @var array|null + * @var iterable|null */ protected static $eventDiscoveryPaths; @@ -145,25 +145,23 @@ public function shouldDiscoverEvents() */ public function discoverEvents() { - return (new Collection($this->discoverEventsWithin())) + return (new LazyCollection($this->discoverEventsWithin())) ->flatMap(function ($directory) { return glob($directory, GLOB_ONLYDIR); }) ->reject(function ($directory) { return ! is_dir($directory); }) - ->reduce(function ($discovered, $directory) { - return array_merge_recursive( - $discovered, - DiscoverEvents::within($directory, $this->eventDiscoveryBasePath()) - ); - }, []); + ->pipe(fn ($directories) => DiscoverEvents::within( + $directories->all(), + $this->eventDiscoveryBasePath(), + )); } /** * Get the listener directories that should be used to discover events. * - * @return array + * @return iterable */ protected function discoverEventsWithin() { @@ -175,23 +173,24 @@ protected function discoverEventsWithin() /** * Add the given event discovery paths to the application's event discovery paths. * - * @param string|array $paths + * @param string|iterable $paths * @return void */ - public static function addEventDiscoveryPaths(array|string $paths) + public static function addEventDiscoveryPaths(iterable|string $paths) { - static::$eventDiscoveryPaths = array_values(array_unique( - array_merge(static::$eventDiscoveryPaths, Arr::wrap($paths)) - )); + static::$eventDiscoveryPaths = (new LazyCollection(static::$eventDiscoveryPaths)) + ->merge(is_string($paths) ? [$paths] : $paths) + ->unique() + ->values(); } /** * Set the globally configured event discovery paths. * - * @param array $paths + * @param iterable $paths * @return void */ - public static function setEventDiscoveryPaths(array $paths) + public static function setEventDiscoveryPaths(iterable $paths) { static::$eventDiscoveryPaths = $paths; } diff --git a/src/Illuminate/Foundation/Testing/CachedState.php b/src/Illuminate/Foundation/Testing/CachedState.php new file mode 100644 index 000000000000..79d333c0d3ef --- /dev/null +++ b/src/Illuminate/Foundation/Testing/CachedState.php @@ -0,0 +1,9 @@ +be($user, $guard); } + /** + * Clear the currently logged in user for the application. + * + * @param string|null $guard + * @return $this + */ + public function actingAsGuest($guard = null) + { + $this->app['auth']->guard($guard)->forgetUser(); + + $this->app['auth']->shouldUse($guard); + + return $this; + } + /** * Set the currently logged in user for the application. * diff --git a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithContainer.php b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithContainer.php index c63a33164c25..ecaa4fdd38f4 100644 --- a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithContainer.php +++ b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithContainer.php @@ -36,9 +36,11 @@ trait InteractsWithContainer /** * Register an instance of an object in the container. * + * @template TSwap of object + * * @param string $abstract - * @param object $instance - * @return object + * @param TSwap $instance + * @return TSwap */ protected function swap($abstract, $instance) { @@ -48,9 +50,11 @@ protected function swap($abstract, $instance) /** * Register an instance of an object in the container. * + * @template TInstance of object + * * @param string $abstract - * @param object $instance - * @return object + * @param TInstance $instance + * @return TInstance */ protected function instance($abstract, $instance) { diff --git a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.php b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.php index 89a0c3ac9797..73d5f9771b5b 100644 --- a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.php +++ b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.php @@ -4,7 +4,6 @@ use Illuminate\Contracts\Support\Jsonable; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Events\QueryExecuted; use Illuminate\Support\Arr; use Illuminate\Support\Facades\DB; @@ -19,13 +18,21 @@ trait InteractsWithDatabase /** * Assert that a given where condition exists in the database. * - * @param \Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string $table + * @param iterable<\Illuminate\Database\Eloquent\Model>|\Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string $table * @param array $data * @param string|null $connection * @return $this */ protected function assertDatabaseHas($table, array $data = [], $connection = null) { + if (is_iterable($table)) { + foreach ($table as $item) { + $this->assertDatabaseHas($item, $data, $connection); + } + + return $this; + } + if ($table instanceof Model) { $data = [ $table->getKeyName() => $table->getKey(), @@ -43,13 +50,21 @@ protected function assertDatabaseHas($table, array $data = [], $connection = nul /** * Assert that a given where condition does not exist in the database. * - * @param \Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string $table + * @param iterable<\Illuminate\Database\Eloquent\Model>|\Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string $table * @param array $data * @param string|null $connection * @return $this */ protected function assertDatabaseMissing($table, array $data = [], $connection = null) { + if (is_iterable($table)) { + foreach ($table as $item) { + $this->assertDatabaseMissing($item, $data, $connection); + } + + return $this; + } + if ($table instanceof Model) { $data = [ $table->getKeyName() => $table->getKey(), @@ -102,7 +117,7 @@ protected function assertDatabaseEmpty($table, $connection = null) /** * Assert the given record has been "soft deleted". * - * @param \Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string $table + * @param iterable<\Illuminate\Database\Eloquent\Model>|\Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string $table * @param array $data * @param string|null $connection * @param string|null $deletedAtColumn @@ -110,6 +125,14 @@ protected function assertDatabaseEmpty($table, $connection = null) */ protected function assertSoftDeleted($table, array $data = [], $connection = null, $deletedAtColumn = 'deleted_at') { + if (is_iterable($table)) { + foreach ($table as $item) { + $this->assertSoftDeleted($item, $data, $connection); + } + + return $this; + } + if ($this->isSoftDeletableModel($table)) { return $this->assertSoftDeleted( $table->getTable(), @@ -134,7 +157,7 @@ protected function assertSoftDeleted($table, array $data = [], $connection = nul /** * Assert the given record has not been "soft deleted". * - * @param \Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string $table + * @param iterable<\Illuminate\Database\Eloquent\Model>|\Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string $table * @param array $data * @param string|null $connection * @param string|null $deletedAtColumn @@ -142,6 +165,14 @@ protected function assertSoftDeleted($table, array $data = [], $connection = nul */ protected function assertNotSoftDeleted($table, array $data = [], $connection = null, $deletedAtColumn = 'deleted_at') { + if (is_iterable($table)) { + foreach ($table as $item) { + $this->assertNotSoftDeleted($item, $data, $connection); + } + + return $this; + } + if ($this->isSoftDeletableModel($table)) { return $this->assertNotSoftDeleted( $table->getTable(), @@ -166,7 +197,7 @@ protected function assertNotSoftDeleted($table, array $data = [], $connection = /** * Assert the given model exists in the database. * - * @param \Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string $model + * @param iterable<\Illuminate\Database\Eloquent\Model>|\Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string $model * @return $this */ protected function assertModelExists($model) @@ -177,7 +208,7 @@ protected function assertModelExists($model) /** * Assert the given model does not exist in the database. * - * @param \Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string $model + * @param iterable<\Illuminate\Database\Eloquent\Model>|\Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string $model * @return $this */ protected function assertModelMissing($model) @@ -194,22 +225,22 @@ protected function assertModelMissing($model) */ public function expectsDatabaseQueryCount($expected, $connection = null) { - with($this->getConnection($connection), function ($connectionInstance) use ($expected, $connection) { - $actual = 0; - - $connectionInstance->listen(function (QueryExecuted $event) use (&$actual, $connectionInstance, $connection) { - if (is_null($connection) || $connectionInstance === $event->connection) { - $actual++; - } - }); - - $this->beforeApplicationDestroyed(function () use (&$actual, $expected, $connectionInstance) { - $this->assertSame( - $expected, - $actual, - "Expected {$expected} database queries on the [{$connectionInstance->getName()}] connection. {$actual} occurred." - ); - }); + $connectionInstance = $this->getConnection($connection); + + $actual = 0; + + $connectionInstance->listen(function (QueryExecuted $event) use (&$actual, $connectionInstance, $connection) { + if (is_null($connection) || $connectionInstance === $event->connection) { + $actual++; + } + }); + + $this->beforeApplicationDestroyed(function () use (&$actual, $expected, $connectionInstance) { + $this->assertSame( + $expected, + $actual, + "Expected {$expected} database queries on the [{$connectionInstance->getName()}] connection. {$actual} occurred." + ); }); return $this; @@ -223,8 +254,7 @@ public function expectsDatabaseQueryCount($expected, $connection = null) */ protected function isSoftDeletableModel($model) { - return $model instanceof Model - && in_array(SoftDeletes::class, class_uses_recursive($model)); + return $model instanceof Model && $model::isSoftDeletable(); } /** @@ -255,7 +285,7 @@ public function castAsJson($value, $connection = null) * Get the database connection. * * @param string|null $connection - * @param \Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string $table + * @param \Illuminate\Database\Eloquent\Model|class-string<\Illuminate\Database\Eloquent\Model>|string|null $table * @return \Illuminate\Database\Connection */ protected function getConnection($connection = null, $table = null) diff --git a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithRedis.php b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithRedis.php index f15814f1ea78..77b63302b653 100644 --- a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithRedis.php +++ b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithRedis.php @@ -105,6 +105,10 @@ public function setUpRedis() */ public function tearDownRedis() { + if (static::$connectionFailedOnceWithDefaultsSkip === true) { + return; + } + if (isset($this->redis['phpredis'])) { $this->redis['phpredis']->connection()->flushdb(); } diff --git a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithTestCaseLifecycle.php b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithTestCaseLifecycle.php index 4be085daa39c..860c7a4b47f5 100644 --- a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithTestCaseLifecycle.php +++ b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithTestCaseLifecycle.php @@ -23,14 +23,17 @@ use Illuminate\Foundation\Testing\WithoutMiddleware; use Illuminate\Http\Middleware\TrustHosts; use Illuminate\Http\Middleware\TrustProxies; +use Illuminate\Mail\Markdown; use Illuminate\Queue\Console\WorkCommand; use Illuminate\Queue\Queue; use Illuminate\Support\Carbon; +use Illuminate\Support\EncodedHtmlString; use Illuminate\Support\Facades\Facade; use Illuminate\Support\Facades\ParallelTesting; use Illuminate\Support\Once; use Illuminate\Support\Sleep; use Illuminate\Support\Str; +use Illuminate\Validation\Validator; use Illuminate\View\Component; use Mockery; use Mockery\Exception\InvalidCountException; @@ -171,8 +174,10 @@ protected function tearDownTheTestEnvironment(): void Component::forgetFactory(); ConvertEmptyStringsToNull::flushState(); Factory::flushState(); + EncodedHtmlString::flushState(); EncryptCookies::flushState(); - HandleExceptions::flushState(); + HandleExceptions::flushState($this); + Markdown::flushState(); Migrator::withoutMigrations([]); Once::flush(); PreventRequestsDuringMaintenance::flushState(); @@ -183,6 +188,7 @@ protected function tearDownTheTestEnvironment(): void TrustProxies::flushState(); TrustHosts::flushState(); ValidateCsrfToken::flushState(); + Validator::flushState(); WorkCommand::flushState(); if ($this->callbackException) { @@ -197,7 +203,7 @@ protected function tearDownTheTestEnvironment(): void */ protected function setUpTraits() { - $uses = array_flip(class_uses_recursive(static::class)); + $uses = $this->traitsUsedByTest ?? array_flip(class_uses_recursive(static::class)); if (isset($uses[RefreshDatabase::class])) { $this->refreshDatabase(); diff --git a/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php b/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php index 3c37c95e4e00..1ace8556feef 100644 --- a/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php +++ b/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php @@ -702,9 +702,10 @@ protected function prepareCookiesForRequest() return array_merge($this->defaultCookies, $this->unencryptedCookies); } - return (new Collection($this->defaultCookies))->map(function ($value, $key) { - return encrypt(CookieValuePrefix::create($key, app('encrypter')->getKey()).$value, false); - })->merge($this->unencryptedCookies)->all(); + return (new Collection($this->defaultCookies)) + ->map(fn ($value, $key) => encrypt(CookieValuePrefix::create($key, app('encrypter')->getKey()).$value, false)) + ->merge($this->unencryptedCookies) + ->all(); } /** diff --git a/src/Illuminate/Foundation/Testing/DatabaseTruncation.php b/src/Illuminate/Foundation/Testing/DatabaseTruncation.php index 9ed063241a8f..a84c082343b7 100644 --- a/src/Illuminate/Foundation/Testing/DatabaseTruncation.php +++ b/src/Illuminate/Foundation/Testing/DatabaseTruncation.php @@ -5,6 +5,7 @@ use Illuminate\Contracts\Console\Kernel; use Illuminate\Database\ConnectionInterface; use Illuminate\Foundation\Testing\Traits\CanConfigureMigrationCommands; +use Illuminate\Support\Arr; use Illuminate\Support\Collection; trait DatabaseTruncation @@ -120,7 +121,7 @@ protected function getAllTablesForConnection(ConnectionInterface $connection, ?s $schema = $connection->getSchemaBuilder(); - return static::$allTables[$name] = (new Collection($schema->getTables($schema->getCurrentSchemaListing())))->all(); + return static::$allTables[$name] = Arr::from($schema->getTables($schema->getCurrentSchemaListing())); } /** diff --git a/src/Illuminate/Foundation/Testing/RefreshDatabase.php b/src/Illuminate/Foundation/Testing/RefreshDatabase.php index f039c510f8c2..28626ec5e706 100644 --- a/src/Illuminate/Foundation/Testing/RefreshDatabase.php +++ b/src/Illuminate/Foundation/Testing/RefreshDatabase.php @@ -85,12 +85,30 @@ protected function refreshTestDatabase() $this->app[Kernel::class]->setArtisan(null); + $this->updateLocalCacheOfInMemoryDatabases(); + RefreshDatabaseState::$migrated = true; } $this->beginDatabaseTransaction(); } + /** + * Update locally cached in-memory PDO connections after migration. + * + * @return void + */ + protected function updateLocalCacheOfInMemoryDatabases() + { + $database = $this->app->make('db'); + + foreach ($this->connectionsToTransact() as $name) { + if ($this->usingInMemoryDatabase($name)) { + RefreshDatabaseState::$inMemoryConnections[$name] = $database->connection($name)->getPdo(); + } + } + } + /** * Migrate the database. * diff --git a/src/Illuminate/Foundation/Testing/TestCase.php b/src/Illuminate/Foundation/Testing/TestCase.php index 1d7a17df84ce..0b5acfd37662 100644 --- a/src/Illuminate/Foundation/Testing/TestCase.php +++ b/src/Illuminate/Foundation/Testing/TestCase.php @@ -20,6 +20,13 @@ abstract class TestCase extends BaseTestCase Concerns\InteractsWithTestCaseLifecycle, Concerns\InteractsWithViews; + /** + * The list of trait that this test uses, fetched recursively. + * + * @var array + */ + protected array $traitsUsedByTest; + /** * Creates the application. * @@ -29,6 +36,18 @@ public function createApplication() { $app = require Application::inferBasePath().'/bootstrap/app.php'; + $this->traitsUsedByTest = array_flip(class_uses_recursive(static::class)); + + if (isset(CachedState::$cachedConfig) && + isset($this->traitsUsedByTest[WithCachedConfig::class])) { + $this->markConfigCached($app); + } + + if (isset(CachedState::$cachedRoutes) && + isset($this->traitsUsedByTest[WithCachedRoutes::class])) { + $app->booting(fn () => $this->markRoutesCached($app)); + } + $app->make(Kernel::class)->bootstrap(); return $app; diff --git a/src/Illuminate/Foundation/Testing/WithCachedConfig.php b/src/Illuminate/Foundation/Testing/WithCachedConfig.php new file mode 100644 index 000000000000..e1ed65a8da7d --- /dev/null +++ b/src/Illuminate/Foundation/Testing/WithCachedConfig.php @@ -0,0 +1,41 @@ +app->make('config')->all(); + } + + $this->markConfigCached($this->app); + } + + /** + * Reset the cached configuration. + * + * This is helpful if some of the tests in the suite apply this trait while others do not. + */ + protected function tearDownWithCachedConfig(): void + { + LoadConfiguration::alwaysUse(null); + } + + /** + * Inform the container that the configuration is cached. + */ + protected function markConfigCached(Application $app): void + { + $app->instance('config_loaded_from_cache', true); + + LoadConfiguration::alwaysUse(static fn () => CachedState::$cachedConfig); + } +} diff --git a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php new file mode 100644 index 000000000000..1a02a370b7a2 --- /dev/null +++ b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php @@ -0,0 +1,52 @@ +app['router']->getRoutes(); + + $routes->refreshNameLookups(); + $routes->refreshActionLookups(); + + CachedState::$cachedRoutes = $routes->compile(); + } + + $this->markRoutesCached($this->app); + } + + /** + * Reset the route service provider so it's not defaulting to loading cached routes. + * + * This is helpful if some of the tests in the suite apply this trait while others do not. + * + * @return void + */ + protected function tearDownWithCachedRoutes(): void + { + RouteServiceProvider::loadCachedRoutesUsing(null); + } + + /** + * Inform the container to treat routes as cached. + */ + protected function markRoutesCached(Application $app): void + { + $app->instance('routes.cached', true); + + RouteServiceProvider::loadCachedRoutesUsing( + static fn () => app('router')->setCompiledRoutes(CachedState::$cachedRoutes) + ); + } +} diff --git a/src/Illuminate/Foundation/Vite.php b/src/Illuminate/Foundation/Vite.php index 7b7de434c27a..b348992c20f2 100644 --- a/src/Illuminate/Foundation/Vite.php +++ b/src/Illuminate/Foundation/Vite.php @@ -693,6 +693,7 @@ protected function resolvePreloadTagAttributes($src, $url, $chunk, $manifest) 'crossorigin' => $this->resolveStylesheetTagAttributes($src, $url, $chunk, $manifest)['crossorigin'] ?? false, ] : [ 'rel' => 'modulepreload', + 'as' => 'script', 'href' => $url, 'nonce' => $this->nonce ?? false, 'crossorigin' => $this->resolveScriptTagAttributes($src, $url, $chunk, $manifest)['crossorigin'] ?? false, @@ -896,7 +897,7 @@ public function content($asset, $buildDirectory = null) $chunk = $this->chunk($this->manifest($buildDirectory), $asset); - $path = public_path($buildDirectory.'/'.$chunk['file']); + $path = $this->publicPath($buildDirectory.'/'.$chunk['file']); if (! is_file($path) || ! file_exists($path)) { throw new ViteException("Unable to locate file from Vite manifest: {$path}."); @@ -917,6 +918,17 @@ protected function assetPath($path, $secure = null) return ($this->assetPathResolver ?? asset(...))($path, $secure); } + /** + * Generate a public path for an asset. + * + * @param string $path + * @return string + */ + protected function publicPath($path) + { + return public_path($path); + } + /** * Get the manifest file for the given build directory. * diff --git a/src/Illuminate/Foundation/helpers.php b/src/Illuminate/Foundation/helpers.php index 8f0523dce09f..94ca5f84924b 100644 --- a/src/Illuminate/Foundation/helpers.php +++ b/src/Illuminate/Foundation/helpers.php @@ -1,8 +1,12 @@ action($name, $parameters, $absolute); } @@ -115,7 +127,6 @@ function action($name, $parameters = [], $absolute = true) * @template TClass of object * * @param string|class-string|null $abstract - * @param array $parameters * @return ($abstract is class-string ? TClass : ($abstract is null ? \Illuminate\Foundation\Application : mixed)) */ function app($abstract = null, array $parameters = []) @@ -133,9 +144,8 @@ function app($abstract = null, array $parameters = []) * Get the path to the application folder. * * @param string $path - * @return string */ - function app_path($path = '') + function app_path($path = ''): string { return app()->path($path); } @@ -147,9 +157,8 @@ function app_path($path = '') * * @param string $path * @param bool|null $secure - * @return string */ - function asset($path, $secure = null) + function asset($path, $secure = null): string { return app('url')->asset($path, $secure); } @@ -160,9 +169,9 @@ function asset($path, $secure = null) * Get the available auth instance. * * @param string|null $guard - * @return ($guard is null ? \Illuminate\Contracts\Auth\Factory : \Illuminate\Contracts\Auth\StatefulGuard) + * @return ($guard is null ? \Illuminate\Contracts\Auth\Factory : \Illuminate\Contracts\Auth\Guard) */ - function auth($guard = null) + function auth($guard = null): AuthFactory|Guard { if (is_null($guard)) { return app(AuthFactory::class); @@ -179,9 +188,8 @@ function auth($guard = null) * @param int $status * @param array $headers * @param mixed $fallback - * @return \Illuminate\Http\RedirectResponse */ - function back($status = 302, $headers = [], $fallback = false) + function back($status = 302, $headers = [], $fallback = false): RedirectResponse { return app('redirect')->back($status, $headers, $fallback); } @@ -192,9 +200,8 @@ function back($status = 302, $headers = [], $fallback = false) * Get the path to the base of the install. * * @param string $path - * @return string */ - function base_path($path = '') + function base_path($path = ''): string { return app()->basePath($path); } @@ -206,9 +213,8 @@ function base_path($path = '') * * @param string $value * @param array $options - * @return string */ - function bcrypt($value, $options = []) + function bcrypt($value, $options = []): string { return app('hash')->driver('bcrypt')->make($value, $options); } @@ -218,15 +224,48 @@ function bcrypt($value, $options = []) /** * Begin broadcasting an event. * - * @param mixed|null $event - * @return \Illuminate\Broadcasting\PendingBroadcast + * @param mixed $event */ - function broadcast($event = null) + function broadcast($event = null): PendingBroadcast { return app(BroadcastFactory::class)->event($event); } } +if (! function_exists('broadcast_if')) { + /** + * Begin broadcasting an event if the given condition is true. + * + * @param bool $boolean + * @param mixed $event + */ + function broadcast_if($boolean, $event = null): PendingBroadcast + { + if ($boolean) { + return app(BroadcastFactory::class)->event(value($event)); + } else { + return new FakePendingBroadcast; + } + } +} + +if (! function_exists('broadcast_unless')) { + /** + * Begin broadcasting an event unless the given condition is true. + * + * @param bool $boolean + * @param mixed $event + */ + function broadcast_unless($boolean, $event = null): PendingBroadcast + { + if (! $boolean) { + return app(BroadcastFactory::class)->event(value($event)); + } else { + return new FakePendingBroadcast; + } + } +} + if (! function_exists('cache')) { /** * Get / set the specified cache value. @@ -255,7 +294,7 @@ function cache($key = null, $default = null) ); } - return app('cache')->put(key($key), reset($key), ttl: $default); + return app('cache')->put(key($key), array_first($key), ttl: $default); } } @@ -288,9 +327,8 @@ function config($key = null, $default = null) * Get the configuration path. * * @param string $path - * @return string */ - function config_path($path = '') + function config_path($path = ''): string { return app()->configPath($path); } @@ -331,7 +369,7 @@ function context($key = null, $default = null) * @param string|null $sameSite * @return ($name is null ? \Illuminate\Cookie\CookieJar : \Symfony\Component\HttpFoundation\Cookie) */ - function cookie($name = null, $value = null, $minutes = 0, $path = null, $domain = null, $secure = null, $httpOnly = true, $raw = false, $sameSite = null) + function cookie($name = null, $value = null, $minutes = 0, $path = null, $domain = null, $secure = null, $httpOnly = true, $raw = false, $sameSite = null): CookieJar|Cookie { $cookie = app(CookieFactory::class); @@ -346,10 +384,8 @@ function cookie($name = null, $value = null, $minutes = 0, $path = null, $domain if (! function_exists('csrf_field')) { /** * Generate a CSRF token form field. - * - * @return \Illuminate\Support\HtmlString */ - function csrf_field() + function csrf_field(): HtmlString { return new HtmlString(''); } @@ -359,11 +395,9 @@ function csrf_field() /** * Get the CSRF token value. * - * @return string - * * @throws \RuntimeException */ - function csrf_token() + function csrf_token(): ?string { $session = app('session'); @@ -380,9 +414,8 @@ function csrf_token() * Get the database path. * * @param string $path - * @return string */ - function database_path($path = '') + function database_path($path = ''): string { return app()->databasePath($path); } @@ -406,12 +439,9 @@ function decrypt($value, $unserialize = true) /** * Defer execution of the given callback. * - * @param callable|null $callback - * @param string|null $name - * @param bool $always - * @return \Illuminate\Support\Defer\DeferredCallback + * @return ($callback is null ? \Illuminate\Support\Defer\DeferredCallbackCollection : \Illuminate\Support\Defer\DeferredCallback) */ - function defer(?callable $callback = null, ?string $name = null, bool $always = false) + function defer(?callable $callback = null, ?string $name = null, bool $always = false): DeferredCallback|DeferredCallbackCollection { return \Illuminate\Support\defer($callback, $name, $always); } @@ -424,7 +454,7 @@ function defer(?callable $callback = null, ?string $name = null, bool $always = * @param mixed $job * @return ($job is \Closure ? \Illuminate\Foundation\Bus\PendingClosureDispatch : \Illuminate\Foundation\Bus\PendingDispatch) */ - function dispatch($job) + function dispatch($job): PendingDispatch|PendingClosureDispatch { return $job instanceof Closure ? new PendingClosureDispatch(CallQueuedClosure::create($job)) @@ -454,9 +484,8 @@ function dispatch_sync($job, $handler = null) * * @param mixed $value * @param bool $serialize - * @return string */ - function encrypt($value, $serialize = true) + function encrypt($value, $serialize = true): string { return app('encrypter')->encrypt($value, $serialize); } @@ -482,9 +511,8 @@ function event(...$args) * Get a faker instance. * * @param string|null $locale - * @return \Faker\Generator */ - function fake($locale = null) + function fake($locale = null): \Faker\Generator { if (app()->bound('config')) { $locale ??= app('config')->get('app.faker_locale'); @@ -508,23 +536,33 @@ function fake($locale = null) * * @param string $message * @param array $context - * @return void */ - function info($message, $context = []) + function info($message, $context = []): void { app('log')->info($message, $context); } } +if (! function_exists('lang_path')) { + /** + * Get the path to the language folder. + * + * @param string $path + */ + function lang_path($path = ''): string + { + return app()->langPath($path); + } +} + if (! function_exists('logger')) { /** * Log a debug message to the logs. * * @param string|null $message - * @param array $context - * @return ($message is null ? \Illuminate\Log\LogManager : null) + * @return ($message is null ? \Psr\Log\LoggerInterface : null) */ - function logger($message = null, array $context = []) + function logger($message = null, array $context = []): ?LoggerInterface { if (is_null($message)) { return app('log'); @@ -534,19 +572,6 @@ function logger($message = null, array $context = []) } } -if (! function_exists('lang_path')) { - /** - * Get the path to the language folder. - * - * @param string $path - * @return string - */ - function lang_path($path = '') - { - return app()->langPath($path); - } -} - if (! function_exists('logs')) { /** * Get a log driver instance. @@ -554,7 +579,7 @@ function lang_path($path = '') * @param string|null $driver * @return ($driver is null ? \Illuminate\Log\LogManager : \Psr\Log\LoggerInterface) */ - function logs($driver = null) + function logs($driver = null): LoggerInterface|LogManager { return $driver ? app('log')->driver($driver) : app('log'); } @@ -565,9 +590,8 @@ function logs($driver = null) * Generate a form field to spoof the HTTP verb used by forms. * * @param string $method - * @return \Illuminate\Support\HtmlString */ - function method_field($method) + function method_field($method): HtmlString { return new HtmlString(''); } @@ -579,11 +603,10 @@ function method_field($method) * * @param string $path * @param string $manifestDirectory - * @return \Illuminate\Support\HtmlString|string * * @throws \Exception */ - function mix($path, $manifestDirectory = '') + function mix($path, $manifestDirectory = ''): HtmlString|string { return app(Mix::class)(...func_get_args()); } @@ -593,12 +616,12 @@ function mix($path, $manifestDirectory = '') /** * Create a new Carbon instance for the current time. * - * @param \DateTimeZone|string|null $tz + * @param \DateTimeZone|\UnitEnum|string|null $tz * @return \Illuminate\Support\Carbon */ - function now($tz = null) + function now($tz = null): CarbonInterface { - return Date::now($tz); + return Date::now(enum_value($tz)); } } @@ -665,9 +688,8 @@ function precognitive($callable = null) * Get the path to the public folder. * * @param string $path - * @return string */ - function public_path($path = '') + function public_path($path = ''): string { return app()->publicPath($path); } @@ -683,7 +705,7 @@ function public_path($path = '') * @param bool|null $secure * @return ($to is null ? \Illuminate\Routing\Redirector : \Illuminate\Http\RedirectResponse) */ - function redirect($to = null, $status = 302, $headers = [], $secure = null) + function redirect($to = null, $status = 302, $headers = [], $secure = null): Redirector|RedirectResponse { if (is_null($to)) { return app('redirect'); @@ -698,9 +720,8 @@ function redirect($to = null, $status = 302, $headers = [], $secure = null) * Report an exception. * * @param \Throwable|string $exception - * @return void */ - function report($exception) + function report($exception): void { if (is_string($exception)) { $exception = new Exception($exception); @@ -716,9 +737,8 @@ function report($exception) * * @param bool $boolean * @param \Throwable|string $exception - * @return void */ - function report_if($boolean, $exception) + function report_if($boolean, $exception): void { if ($boolean) { report($exception); @@ -732,9 +752,8 @@ function report_if($boolean, $exception) * * @param bool $boolean * @param \Throwable|string $exception - * @return void */ - function report_unless($boolean, $exception) + function report_unless($boolean, $exception): void { if (! $boolean) { report($exception); @@ -799,7 +818,6 @@ function rescue(callable $callback, $rescue = null, $report = true) * @template TClass of object * * @param string|class-string $name - * @param array $parameters * @return ($name is class-string ? TClass : mixed) */ function resolve($name, array $parameters = []) @@ -813,9 +831,8 @@ function resolve($name, array $parameters = []) * Get the path to the resources folder. * * @param string $path - * @return string */ - function resource_path($path = '') + function resource_path($path = ''): string { return app()->resourcePath($path); } @@ -827,10 +844,9 @@ function resource_path($path = '') * * @param \Illuminate\Contracts\View\View|string|array|null $content * @param int $status - * @param array $headers * @return ($content is null ? \Illuminate\Contracts\Routing\ResponseFactory : \Illuminate\Http\Response) */ - function response($content = null, $status = 200, array $headers = []) + function response($content = null, $status = 200, array $headers = []): ResponseFactory|IlluminateResponse { $factory = app(ResponseFactory::class); @@ -849,9 +865,8 @@ function response($content = null, $status = 200, array $headers = []) * @param \BackedEnum|string $name * @param mixed $parameters * @param bool $absolute - * @return string */ - function route($name, $parameters = [], $absolute = true) + function route($name, $parameters = [], $absolute = true): string { return app('url')->route($name, $parameters, $absolute); } @@ -862,9 +877,8 @@ function route($name, $parameters = [], $absolute = true) * Generate an asset path for the application. * * @param string $path - * @return string */ - function secure_asset($path) + function secure_asset($path): string { return asset($path, true); } @@ -913,14 +927,29 @@ function session($key = null, $default = null) * Get the path to the storage folder. * * @param string $path - * @return string */ - function storage_path($path = '') + function storage_path($path = ''): string { return app()->storagePath($path); } } +if (! function_exists('to_action')) { + /** + * Create a new redirect response to a controller action. + * + * @param string|array $action + * @param mixed $parameters + * @param int $status + * @param array $headers + * @return \Illuminate\Http\RedirectResponse + */ + function to_action($action, $parameters = [], $status = 302, $headers = []) + { + return redirect()->action($action, $parameters, $status, $headers); + } +} + if (! function_exists('to_route')) { /** * Create a new redirect response to a named route. @@ -941,12 +970,12 @@ function to_route($route, $parameters = [], $status = 302, $headers = []) /** * Create a new Carbon instance for the current date. * - * @param \DateTimeZone|string|null $tz + * @param \DateTimeZone|\UnitEnum|string|null $tz * @return \Illuminate\Support\Carbon */ - function today($tz = null) + function today($tz = null): CarbonInterface { - return Date::today($tz); + return Date::today(enum_value($tz)); } } @@ -959,7 +988,7 @@ function today($tz = null) * @param string|null $locale * @return ($key is null ? \Illuminate\Contracts\Translation\Translator : array|string) */ - function trans($key = null, $replace = [], $locale = null) + function trans($key = null, $replace = [], $locale = null): Translator|array|string { if (is_null($key)) { return app('translator'); @@ -975,11 +1004,9 @@ function trans($key = null, $replace = [], $locale = null) * * @param string $key * @param \Countable|int|float|array $number - * @param array $replace * @param string|null $locale - * @return string */ - function trans_choice($key, $number, array $replace = [], $locale = null) + function trans_choice($key, $number, array $replace = [], $locale = null): string { return app('translator')->choice($key, $number, $replace, $locale); } @@ -992,9 +1019,8 @@ function trans_choice($key, $number, array $replace = [], $locale = null) * @param string|null $key * @param array $replace * @param string|null $locale - * @return string|array|null */ - function __($key = null, $replace = [], $locale = null) + function __($key = null, $replace = [], $locale = null): string|array|null { if (is_null($key)) { return $key; @@ -1027,7 +1053,7 @@ function uri(UriInterface|Stringable|array|string $uri, mixed $parameters = [], * @param bool|null $secure * @return ($path is null ? \Illuminate\Contracts\Routing\UrlGenerator : string) */ - function url($path = null, $parameters = [], $secure = null) + function url($path = null, $parameters = [], $secure = null): UrlGenerator|string { if (is_null($path)) { return app(UrlGenerator::class); @@ -1041,13 +1067,9 @@ function url($path = null, $parameters = [], $secure = null) /** * Create a new Validator instance. * - * @param array|null $data - * @param array $rules - * @param array $messages - * @param array $attributes * @return ($data is null ? \Illuminate\Contracts\Validation\Factory : \Illuminate\Contracts\Validation\Validator) */ - function validator(?array $data = null, array $rules = [], array $messages = [], array $attributes = []) + function validator(?array $data = null, array $rules = [], array $messages = [], array $attributes = []): ValidatorContract|ValidationFactory { $factory = app(ValidationFactory::class); @@ -1068,7 +1090,7 @@ function validator(?array $data = null, array $rules = [], array $messages = [], * @param array $mergeData * @return ($view is null ? \Illuminate\Contracts\View\Factory : \Illuminate\Contracts\View\View) */ - function view($view = null, $data = [], $mergeData = []) + function view($view = null, $data = [], $mergeData = []): ViewFactory|ViewContract { $factory = app(ViewFactory::class); diff --git a/src/Illuminate/Foundation/resources/exceptions/renderer/.gitignore b/src/Illuminate/Foundation/resources/exceptions/renderer/.gitignore new file mode 100644 index 000000000000..07e6e472cc75 --- /dev/null +++ b/src/Illuminate/Foundation/resources/exceptions/renderer/.gitignore @@ -0,0 +1 @@ +/node_modules diff --git a/src/Illuminate/Foundation/resources/exceptions/renderer/components/badge.blade.php b/src/Illuminate/Foundation/resources/exceptions/renderer/components/badge.blade.php new file mode 100644 index 000000000000..5fedfcf12535 --- /dev/null +++ b/src/Illuminate/Foundation/resources/exceptions/renderer/components/badge.blade.php @@ -0,0 +1,47 @@ +@props(['type' => 'default', 'variant' => 'soft']) + +@php +$baseClasses = 'inline-flex w-fit shrink-0 items-center justify-center gap-1 font-mono leading-3 uppercase transition-colors dark:border [&_svg]:size-2.5 h-6 min-w-5 rounded-md px-1.5 text-xs/none'; + +$types = [ + 'default' => [ + 'soft' => 'bg-black/8 text-neutral-900 dark:border-neutral-700 dark:bg-white/10 dark:text-neutral-100', + 'solid' => 'bg-neutral-600 text-neutral-100 dark:border-neutral-500 dark:bg-neutral-600', + ], + 'success' => [ + 'soft' => 'bg-emerald-200 text-emerald-900 dark:border-emerald-600 dark:bg-emerald-900/70 dark:text-emerald-400', + 'solid' => 'bg-emerald-600 dark:border-emerald-500 dark:bg-emerald-600', + ], + 'primary' => [ + 'soft' => 'bg-blue-100 text-blue-900 dark:border-blue-800 dark:bg-blue-950 dark:text-blue-300', + 'solid' => 'bg-blue-700 dark:border-blue-600 dark:bg-blue-700', + ], + 'error' => [ + 'soft' => 'bg-rose-200 text-rose-900 dark:border-rose-900 dark:bg-rose-950 dark:text-rose-100 dark:[&_svg]:!text-white', + 'solid' => 'bg-rose-600 dark:border-rose-500 dark:bg-rose-600', + ], + 'alert' => [ + 'soft' => 'bg-amber-200 text-amber-900 dark:border-amber-800 dark:bg-amber-950 dark:text-amber-300', + 'solid' => 'bg-amber-600 dark:border-amber-500 dark:bg-amber-600', + ], + 'white' => [ + 'soft' => 'bg-white text-neutral-900 dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-100', + 'solid' => 'bg-black/10 text-neutral-900 dark:text-neutral-900 dark:bg-white', + ], +]; + +$variants = [ + 'soft' => '', + 'solid' => 'text-white dark:text-white [&_svg]:!text-white', +]; + +$typeClasses = $types[$type][$variant] ?? $types['default']['soft']; +$variantClasses = $variants[$variant] ?? $variants['soft']; + +$classes = implode(' ', [$baseClasses, $typeClasses, $variantClasses]); + +@endphp + +
merge(['class' => $classes]) }}> + {{ $slot }} +
diff --git a/src/Illuminate/Foundation/resources/exceptions/renderer/components/card.blade.php b/src/Illuminate/Foundation/resources/exceptions/renderer/components/card.blade.php deleted file mode 100644 index 14dcd4f51426..000000000000 --- a/src/Illuminate/Foundation/resources/exceptions/renderer/components/card.blade.php +++ /dev/null @@ -1,5 +0,0 @@ -
merge(['class' => "@container flex flex-col p-6 sm:p-12 bg-white dark:bg-gray-900/80 text-gray-900 dark:text-gray-100 rounded-lg default:col-span-full default:lg:col-span-6 default:row-span-1 dark:ring-1 dark:ring-gray-800 shadow-xl"]) }} -> - {{ $slot }} -
diff --git a/src/Illuminate/Foundation/resources/exceptions/renderer/components/context.blade.php b/src/Illuminate/Foundation/resources/exceptions/renderer/components/context.blade.php deleted file mode 100644 index 13b922a865e6..000000000000 --- a/src/Illuminate/Foundation/resources/exceptions/renderer/components/context.blade.php +++ /dev/null @@ -1,148 +0,0 @@ -@use('Illuminate\Support\Str') - -
- Request -
- -
- {{ $exception->request()->method() }} - {{ Str::start($exception->request()->path(), '/') }} -
- -
- Headers -
- -
- @forelse ($exception->requestHeaders() as $key => $value) -
- - {{ $key }} - - -
{{ $value }}
-
-
- @empty - -
No headers data
-
- @endforelse -
- -
- Body -
- -
-
- -
{{ $exception->requestBody() ?: 'No body data' }}
-
-
-
- -
- - -
- Application -
- -
- Routing -
- -
- @forelse ($exception->applicationRouteContext() as $name => $value) -
- {{ $name }} - -
{{ $value }}
-
-
- @empty - -
No routing data
-
- @endforelse -
- - @if ($routeParametersContext = $exception->applicationRouteParametersContext()) -
- Routing Parameters -
- -
-
- -
{{ $routeParametersContext }}
-
-
-
- @endif - -
- Database Queries - - @if (count($exception->applicationQueries()) === 100) - only the first 100 queries are displayed - @endif - -
- -
- @forelse ($exception->applicationQueries() as ['connectionName' => $connectionName, 'sql' => $sql, 'time' => $time]) -
-
- {{ $connectionName }} - -
- -
{{ $sql }}
-
-
- @empty - -
No query data
-
- @endforelse -
-
diff --git a/src/Illuminate/Foundation/resources/exceptions/renderer/components/editor.blade.php b/src/Illuminate/Foundation/resources/exceptions/renderer/components/editor.blade.php deleted file mode 100644 index 4171fb8e3e2d..000000000000 --- a/src/Illuminate/Foundation/resources/exceptions/renderer/components/editor.blade.php +++ /dev/null @@ -1,32 +0,0 @@ -@foreach ($exception->frames() as $frame) -
-
-
-
- - @if (config('app.editor')) - - {{ $frame->file() }} - - @else - {{ $frame->file() }} - @endif - - :{{ $frame->line() }} -
-
-
-
-
-
-
-@endforeach diff --git a/src/Illuminate/Foundation/resources/exceptions/renderer/components/empty-state.blade.php b/src/Illuminate/Foundation/resources/exceptions/renderer/components/empty-state.blade.php new file mode 100644 index 000000000000..9a41f78a8f1b --- /dev/null +++ b/src/Illuminate/Foundation/resources/exceptions/renderer/components/empty-state.blade.php @@ -0,0 +1,5 @@ +@props(['message']) + +
+ // {{ $message }} +
diff --git a/src/Illuminate/Foundation/resources/exceptions/renderer/components/file-with-line.blade.php b/src/Illuminate/Foundation/resources/exceptions/renderer/components/file-with-line.blade.php new file mode 100644 index 000000000000..99dd9f4a493b --- /dev/null +++ b/src/Illuminate/Foundation/resources/exceptions/renderer/components/file-with-line.blade.php @@ -0,0 +1,21 @@ +@props(['frame', 'direction' => 'ltr']) + +@php + $file = $frame->file(); + $line = $frame->line(); +@endphp + +
merge(['class' => 'truncate font-mono text-xs text-neutral-500 dark:text-neutral-400']) }} + dir="{{ $direction }}" +> + + @if (config('app.editor')) + + {{ $file }}:{{ $line }} + + @else + {{ $file }}:{{ $line }} + @endif + +
diff --git a/src/Illuminate/Foundation/resources/exceptions/renderer/components/formatted-source.blade.php b/src/Illuminate/Foundation/resources/exceptions/renderer/components/formatted-source.blade.php new file mode 100644 index 000000000000..e6364fc9eb05 --- /dev/null +++ b/src/Illuminate/Foundation/resources/exceptions/renderer/components/formatted-source.blade.php @@ -0,0 +1,23 @@ +@props(['frame']) + +@php + if ($class = $frame->class()) { + $source = $class; + + if ($previous = $frame->previous()) { + $source .= $previous->operator(); + $source .= $previous->callable(); + $source .= '('.implode(', ', $previous->args()).')'; + } + } else { + $source = $frame->source(); + } +@endphp + + diff --git a/src/Illuminate/Foundation/resources/exceptions/renderer/components/frame-code.blade.php b/src/Illuminate/Foundation/resources/exceptions/renderer/components/frame-code.blade.php new file mode 100644 index 000000000000..23b022062825 --- /dev/null +++ b/src/Illuminate/Foundation/resources/exceptions/renderer/components/frame-code.blade.php @@ -0,0 +1,15 @@ +@props(['code', 'highlightedLine']) + +
+ +
diff --git a/src/Illuminate/Foundation/resources/exceptions/renderer/components/frame.blade.php b/src/Illuminate/Foundation/resources/exceptions/renderer/components/frame.blade.php new file mode 100644 index 000000000000..406c246aebdb --- /dev/null +++ b/src/Illuminate/Foundation/resources/exceptions/renderer/components/frame.blade.php @@ -0,0 +1,55 @@ +@props(['frame']) + +
+
+ {{-- Dot --}} +
+
+
+ +
+ + +
+ +
+ +
+
+ + @if($snippet = $frame->snippet()) + + @endif +
diff --git a/src/Illuminate/Foundation/resources/exceptions/renderer/components/header.blade.php b/src/Illuminate/Foundation/resources/exceptions/renderer/components/header.blade.php index 4da473e71d90..ffb0c9a9a212 100644 --- a/src/Illuminate/Foundation/resources/exceptions/renderer/components/header.blade.php +++ b/src/Illuminate/Foundation/resources/exceptions/renderer/components/header.blade.php @@ -1,28 +1,33 @@ - -
-
-
- - - {{ implode(' ', array_slice(explode('\\', $exception->class()), -1)) }} - -
-
- {{ $exception->message() }} -
-
+@props(['exception']) -