From 6d94b16fd5f4f72bb741f9b900b83179c8ab46c9 Mon Sep 17 00:00:00 2001 From: Ahmed Alaa <92916738+AhmedAlaa4611@users.noreply.github.com> Date: Fri, 8 Aug 2025 00:04:11 +0300 Subject: [PATCH 01/10] Improved assertion message (#56579) --- src/Illuminate/Support/Testing/Fakes/NotificationFake.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Support/Testing/Fakes/NotificationFake.php b/src/Illuminate/Support/Testing/Fakes/NotificationFake.php index ecc4d63b1090..b7ed694a91c0 100644 --- a/src/Illuminate/Support/Testing/Fakes/NotificationFake.php +++ b/src/Illuminate/Support/Testing/Fakes/NotificationFake.php @@ -215,7 +215,11 @@ public function assertSentTimes($notification, $expectedCount) PHPUnit::assertSame( $expectedCount, $actualCount, - "Expected [{$notification}] to be sent {$expectedCount} times, but was sent {$actualCount} times." + sprintf( + "Expected [{$notification}] to be sent {$expectedCount} %s, but was sent {$actualCount} %s.", + Str::plural('time', $expectedCount), + Str::plural('time', $actualCount) + ) ); } From c119641da248211d39b69196896bd35e8ef89bc2 Mon Sep 17 00:00:00 2001 From: Daniel Iancu Date: Fri, 8 Aug 2025 16:53:05 +0300 Subject: [PATCH 02/10] Fixed version increment (#56588) --- src/Illuminate/Foundation/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index 64b04d909bdd..0aacb8062c01 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -45,7 +45,7 @@ class Application extends Container implements ApplicationContract, CachesConfig * * @var string */ - const VERSION = '12.21.0'; + const VERSION = '12.22.0'; /** * The base path for the Laravel installation. From b735473bd98aa76483f3d7f6484131ca1d87f4e9 Mon Sep 17 00:00:00 2001 From: Amir Hossein Shokri Date: Fri, 8 Aug 2025 17:23:28 +0330 Subject: [PATCH 03/10] improve make:migration command output (#56591) --- .../Database/Console/Migrations/MigrateMakeCommand.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Illuminate/Database/Console/Migrations/MigrateMakeCommand.php b/src/Illuminate/Database/Console/Migrations/MigrateMakeCommand.php index c9494c5d5c44..ac5077f58d79 100644 --- a/src/Illuminate/Database/Console/Migrations/MigrateMakeCommand.php +++ b/src/Illuminate/Database/Console/Migrations/MigrateMakeCommand.php @@ -112,6 +112,10 @@ protected function writeMigration($name, $table, $create) $name, $this->getMigrationPath(), $table, $create ); + if (windows_os()) { + $file = str_replace('/', '\\', $file); + } + $this->components->info(sprintf('Migration [%s] created successfully.', $file)); } From c3bc7b18325715ff2bb196b5d592bfb092bdf97d Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 8 Aug 2025 08:56:14 -0500 Subject: [PATCH 04/10] Revert "[12.x] Improve PHPDoc blocks for array of arguments in Gate (#56426)" (#56593) This reverts commit b39a756d8ed310c1bf00c1eb2ff528d6a810c4aa. --- src/Illuminate/Auth/Access/Gate.php | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/Illuminate/Auth/Access/Gate.php b/src/Illuminate/Auth/Access/Gate.php index 775c43f91914..0bae564924b2 100644 --- a/src/Illuminate/Auth/Access/Gate.php +++ b/src/Illuminate/Auth/Access/Gate.php @@ -18,9 +18,6 @@ use function Illuminate\Support\enum_value; -/** - * @template TClass of object - */ class Gate implements GateContract { use HandlesAuthorization; @@ -329,7 +326,7 @@ public function after(callable $callback) * Determine if all of the given abilities should be granted for the current user. * * @param iterable|\UnitEnum|string $ability - * @param array{class-string|TClass, ...} $arguments + * @param mixed $arguments * @return bool */ public function allows($ability, $arguments = []) @@ -341,7 +338,7 @@ public function allows($ability, $arguments = []) * Determine if any of the given abilities should be denied for the current user. * * @param iterable|\UnitEnum|string $ability - * @param array{class-string|TClass, ...} $arguments + * @param mixed $arguments * @return bool */ public function denies($ability, $arguments = []) @@ -353,7 +350,7 @@ public function denies($ability, $arguments = []) * Determine if all of the given abilities should be granted for the current user. * * @param iterable|\UnitEnum|string $abilities - * @param array{class-string|TClass, ...} $arguments + * @param mixed $arguments * @return bool */ public function check($abilities, $arguments = []) @@ -367,7 +364,7 @@ public function check($abilities, $arguments = []) * Determine if any one of the given abilities should be granted for the current user. * * @param iterable|\UnitEnum|string $abilities - * @param array{class-string|TClass, ...} $arguments + * @param mixed $arguments * @return bool */ public function any($abilities, $arguments = []) @@ -379,7 +376,7 @@ public function any($abilities, $arguments = []) * Determine if all of the given abilities should be denied for the current user. * * @param iterable|\UnitEnum|string $abilities - * @param array{class-string|TClass, ...} $arguments + * @param mixed $arguments * @return bool */ public function none($abilities, $arguments = []) @@ -391,7 +388,7 @@ public function none($abilities, $arguments = []) * Determine if the given ability should be granted for the current user. * * @param \UnitEnum|string $ability - * @param array{class-string|TClass, ...} $arguments + * @param mixed $arguments * @return \Illuminate\Auth\Access\Response * * @throws \Illuminate\Auth\Access\AuthorizationException @@ -405,7 +402,7 @@ public function authorize($ability, $arguments = []) * Inspect the user for the given ability. * * @param \UnitEnum|string $ability - * @param array{class-string|TClass, ...} $arguments + * @param array|mixed $arguments * @return \Illuminate\Auth\Access\Response */ public function inspect($ability, $arguments = []) @@ -429,7 +426,7 @@ public function inspect($ability, $arguments = []) * Get the raw result from the authorization callback. * * @param string $ability - * @param array{class-string|TClass, ...} $arguments + * @param array|mixed $arguments * @return mixed * * @throws \Illuminate\Auth\Access\AuthorizationException From ed938de2fbfebee225ba51b2a54154f7614110ab Mon Sep 17 00:00:00 2001 From: taylorotwell <463230+taylorotwell@users.noreply.github.com> Date: Fri, 8 Aug 2025 13:56:41 +0000 Subject: [PATCH 05/10] Update facade docblocks --- src/Illuminate/Support/Facades/Gate.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Illuminate/Support/Facades/Gate.php b/src/Illuminate/Support/Facades/Gate.php index fc8c547808fe..16b867e76095 100644 --- a/src/Illuminate/Support/Facades/Gate.php +++ b/src/Illuminate/Support/Facades/Gate.php @@ -13,14 +13,14 @@ * @method static \Illuminate\Auth\Access\Gate policy(string $class, string $policy) * @method static \Illuminate\Auth\Access\Gate before(callable $callback) * @method static \Illuminate\Auth\Access\Gate after(callable $callback) - * @method static bool allows(iterable|\UnitEnum|string $ability, array $arguments = []) - * @method static bool denies(iterable|\UnitEnum|string $ability, array $arguments = []) - * @method static bool check(iterable|\UnitEnum|string $abilities, array $arguments = []) - * @method static bool any(iterable|\UnitEnum|string $abilities, array $arguments = []) - * @method static bool none(iterable|\UnitEnum|string $abilities, array $arguments = []) - * @method static \Illuminate\Auth\Access\Response authorize(\UnitEnum|string $ability, array $arguments = []) - * @method static \Illuminate\Auth\Access\Response inspect(\UnitEnum|string $ability, array $arguments = []) - * @method static mixed raw(string $ability, array $arguments = []) + * @method static bool allows(iterable|\UnitEnum|string $ability, mixed $arguments = []) + * @method static bool denies(iterable|\UnitEnum|string $ability, mixed $arguments = []) + * @method static bool check(iterable|\UnitEnum|string $abilities, mixed $arguments = []) + * @method static bool any(iterable|\UnitEnum|string $abilities, mixed $arguments = []) + * @method static bool none(iterable|\UnitEnum|string $abilities, mixed $arguments = []) + * @method static \Illuminate\Auth\Access\Response authorize(\UnitEnum|string $ability, mixed $arguments = []) + * @method static \Illuminate\Auth\Access\Response inspect(\UnitEnum|string $ability, array|mixed $arguments = []) + * @method static mixed raw(string $ability, array|mixed $arguments = []) * @method static mixed getPolicyFor(object|string $class) * @method static \Illuminate\Auth\Access\Gate guessPolicyNamesUsing(callable $callback) * @method static mixed resolvePolicy(object|string $class) From d33ee45184126f32f593d4b809a846ed88a1dc43 Mon Sep 17 00:00:00 2001 From: taylorotwell <463230+taylorotwell@users.noreply.github.com> Date: Fri, 8 Aug 2025 13:58:03 +0000 Subject: [PATCH 06/10] Update version to v12.22.1 --- src/Illuminate/Foundation/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index 0aacb8062c01..63da4578cfce 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -45,7 +45,7 @@ class Application extends Container implements ApplicationContract, CachesConfig * * @var string */ - const VERSION = '12.22.0'; + const VERSION = '12.22.1'; /** * The base path for the Laravel installation. From b10312f29675fb9c8ab818fed09cc4de45637526 Mon Sep 17 00:00:00 2001 From: taylorotwell <463230+taylorotwell@users.noreply.github.com> Date: Fri, 8 Aug 2025 13:59:54 +0000 Subject: [PATCH 07/10] Update CHANGELOG --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b65a09089f0..8803e41bed60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Release Notes for 12.x -## [Unreleased](https://github.com/laravel/framework/compare/v12.21.0...12.x) +## [Unreleased](https://github.com/laravel/framework/compare/v12.22.1...12.x) + +## [v12.22.1](https://github.com/laravel/framework/compare/v12.21.0...v12.22.1) - 2025-08-08 + +* [12.x] Improved assertion message by [@AhmedAlaa4611](https://github.com/AhmedAlaa4611) in https://github.com/laravel/framework/pull/56579 +* [12.x] Fixed version increment by [@dciancu](https://github.com/dciancu) in https://github.com/laravel/framework/pull/56588 +* [12.x] Normalize file path separators in `make:migration` command on Windows by [@amirhshokri](https://github.com/amirhshokri) in https://github.com/laravel/framework/pull/56591 +* Revert "[12.x] Improve PHPDoc blocks for array of arguments in Gate" by [@taylorotwell](https://github.com/taylorotwell) in https://github.com/laravel/framework/pull/56593 ## [v12.21.0](https://github.com/laravel/framework/compare/v12.20.0...v12.21.0) - 2025-07-22 From fe5e22c56ad03f230dc7b84b85e7ff81d0f93bbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Magyar?= Date: Fri, 8 Aug 2025 16:27:13 +0200 Subject: [PATCH 08/10] Prevent unintended sleep on early failure of assertSequence (#56583) --- src/Illuminate/Support/Sleep.php | 52 ++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/Illuminate/Support/Sleep.php b/src/Illuminate/Support/Sleep.php index 9b761811cfb9..b6b6ab32bca2 100644 --- a/src/Illuminate/Support/Sleep.php +++ b/src/Illuminate/Support/Sleep.php @@ -428,29 +428,37 @@ public static function assertSleptTimes($expected) */ public static function assertSequence($sequence) { - static::assertSleptTimes(count($sequence)); - - (new Collection($sequence)) - ->zip(static::$sequence) - ->eachSpread(function (?Sleep $expected, CarbonInterval $actual) { - if ($expected === null) { - return; + try { + static::assertSleptTimes(count($sequence)); + + (new Collection($sequence)) + ->zip(static::$sequence) + ->eachSpread(function (?Sleep $expected, CarbonInterval $actual) { + if ($expected === null) { + return; + } + + PHPUnit::assertTrue( + $expected->shouldNotSleep()->duration->equalTo($actual), + vsprintf('Expected sleep duration of [%s] but actually slept for [%s].', [ + $expected->duration->cascade()->forHumans([ + 'options' => 0, + 'minimumUnit' => 'microsecond', + ]), + $actual->cascade()->forHumans([ + 'options' => 0, + 'minimumUnit' => 'microsecond', + ]), + ]) + ); + }); + } finally { + foreach ($sequence as $expected) { + if ($expected instanceof self) { + $expected->shouldNotSleep(); } - - PHPUnit::assertTrue( - $expected->shouldNotSleep()->duration->equalTo($actual), - vsprintf('Expected sleep duration of [%s] but actually slept for [%s].', [ - $expected->duration->cascade()->forHumans([ - 'options' => 0, - 'minimumUnit' => 'microsecond', - ]), - $actual->cascade()->forHumans([ - 'options' => 0, - 'minimumUnit' => 'microsecond', - ]), - ]) - ); - }); + } + } } /** From 9bb82f7c10094097f2bc842a967fc17accf0933d Mon Sep 17 00:00:00 2001 From: Vadim Dvorovenko Date: Fri, 8 Aug 2025 21:46:15 +0700 Subject: [PATCH 09/10] [12.x] Redis cluster broadcaster (#56581) * [12.x] RedisBroadcaster for RedisCuster * formatting --------- Co-authored-by: Taylor Otwell --- .../Broadcasters/RedisBroadcaster.php | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Broadcasting/Broadcasters/RedisBroadcaster.php b/src/Illuminate/Broadcasting/Broadcasters/RedisBroadcaster.php index 9cb81c85af1d..15878575dec0 100644 --- a/src/Illuminate/Broadcasting/Broadcasters/RedisBroadcaster.php +++ b/src/Illuminate/Broadcasting/Broadcasters/RedisBroadcaster.php @@ -4,7 +4,11 @@ use Illuminate\Broadcasting\BroadcastException; use Illuminate\Contracts\Redis\Factory as Redis; +use Illuminate\Redis\Connections\PhpRedisClusterConnection; +use Illuminate\Redis\Connections\PredisClusterConnection; +use Illuminate\Redis\Connections\PredisConnection; use Illuminate\Support\Arr; +use Predis\Connection\Cluster\RedisCluster; use Predis\Connection\ConnectionException; use RedisException; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -125,10 +129,30 @@ public function broadcast(array $channels, $event, array $payload = []) ]); try { - $connection->eval( - $this->broadcastMultipleChannelsScript(), - 0, $payload, ...$this->formatChannels($channels) - ); + if ($connection instanceof PhpRedisClusterConnection) { + foreach ($channels as $channel) { + $connection->publish($channel, $payload); + } + } elseif ($connection instanceof PredisClusterConnection && + $connection->client()->getConnection() instanceof RedisCluster) { + $randomClusterNodeConnection = new PredisConnection( + $connection->client()->getClientBy('slot', mt_rand(0, 16383)) + ); + + if ($events = $connection->getEventDispatcher()) { + $randomClusterNodeConnection->setEventDispatcher($events); + } + + $randomClusterNodeConnection->eval( + $this->broadcastMultipleChannelsScript(), + 0, $payload, ...$this->formatChannels($channels) + ); + } else { + $connection->eval( + $this->broadcastMultipleChannelsScript(), + 0, $payload, ...$this->formatChannels($channels) + ); + } } catch (ConnectionException|RedisException $e) { throw new BroadcastException( sprintf('Redis error: %s.', $e->getMessage()) From ac498ff3adb6c434cd699f9085bb8bec66754316 Mon Sep 17 00:00:00 2001 From: Jack Bayliss Date: Fri, 8 Aug 2025 15:47:00 +0100 Subject: [PATCH 10/10] Update Facade.php (#56594) --- src/Illuminate/Support/Facades/Facade.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Illuminate/Support/Facades/Facade.php b/src/Illuminate/Support/Facades/Facade.php index 8874954a919b..1e643a3f9101 100755 --- a/src/Illuminate/Support/Facades/Facade.php +++ b/src/Illuminate/Support/Facades/Facade.php @@ -5,6 +5,7 @@ use Closure; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; +use Illuminate\Support\Benchmark; use Illuminate\Support\Collection; use Illuminate\Support\Js; use Illuminate\Support\Number; @@ -276,6 +277,7 @@ public static function defaultAliases() 'Arr' => Arr::class, 'Artisan' => Artisan::class, 'Auth' => Auth::class, + 'Benchmark' => Benchmark::class, 'Blade' => Blade::class, 'Broadcast' => Broadcast::class, 'Bus' => Bus::class,