From 9afc9fd29bb30f590a2b9ec6aa7347cf52875400 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 30 Apr 2025 16:59:02 +0800 Subject: [PATCH 01/10] Typed getters for Arr helper --- src/macros/output/Hyperf/Collection/Arr.php | 48 +++++++++ src/macros/src/ArrMixin.php | 89 +++++++++++++++++ tests/Macros/ArrTest.php | 105 ++++++++++++++++++++ 3 files changed, 242 insertions(+) diff --git a/src/macros/output/Hyperf/Collection/Arr.php b/src/macros/output/Hyperf/Collection/Arr.php index b1b4c8060..68b19631c 100644 --- a/src/macros/output/Hyperf/Collection/Arr.php +++ b/src/macros/output/Hyperf/Collection/Arr.php @@ -11,8 +11,56 @@ namespace Hyperf\Collection; +use ArrayAccess; +use InvalidArgumentException; + class Arr { + /** + * Get an array item from an array using "dot" notation. + * @return array + * @throws InvalidArgumentException + */ + public static function array(ArrayAccess|array $array, string|int|null $key, ?array $default = null) + { + } + + /** + * Get a boolean item from an array using "dot" notation. + * @return bool + * @throws InvalidArgumentException + */ + public static function boolean(ArrayAccess|array $array, string|int|null $key, ?bool $default = null) + { + } + + /** + * Get a float item from an array using "dot" notation. + * @return float + * @throws InvalidArgumentException + */ + public static function float(ArrayAccess|array $array, string|int|null $key, ?float $default = null) + { + } + + /** + * Get an integer item from an array using "dot" notation. + * @return int + * @throws InvalidArgumentException + */ + public static function integer(ArrayAccess|array $array, string|int|null $key, ?int $default = null) + { + } + + /** + * Get a string item from an array using "dot" notation. + * @return string + * @throws InvalidArgumentException + */ + public static function string(ArrayAccess|array $array, string|int|null $key, ?string $default = null) + { + } + /** * Sort given array by many properties. * diff --git a/src/macros/src/ArrMixin.php b/src/macros/src/ArrMixin.php index 2f48894a5..af17b4c25 100644 --- a/src/macros/src/ArrMixin.php +++ b/src/macros/src/ArrMixin.php @@ -11,13 +11,102 @@ namespace FriendsOfHyperf\Macros; +use ArrayAccess; use Hyperf\Collection\Arr; +use InvalidArgumentException; /** * @mixin Arr */ class ArrMixin { + public static function array() + { + return function (ArrayAccess|array $array, string|int|null $key, ?array $default = null) { + $value = Arr::get($array, $key, $default); + + if (! is_array($value)) { + throw new InvalidArgumentException( + sprintf('Array value for key [%s] must be an array, %s found.', $key, gettype($value)) + ); + } + + return $value; + }; + } + + /** + * Get a boolean item from an array using "dot" notation. + */ + public static function boolean() + { + return function (ArrayAccess|array $array, string|int|null $key, ?bool $default = null) { + $value = Arr::get($array, $key, $default); + + if (! is_bool($value)) { + throw new InvalidArgumentException( + sprintf('Array value for key [%s] must be a boolean, %s found.', $key, gettype($value)) + ); + } + + return $value; + }; + } + + /** + * Get a float item from an array using "dot" notation. + */ + public static function float() + { + return function (ArrayAccess|array $array, string|int|null $key, ?float $default = null) { + $value = Arr::get($array, $key, $default); + + if (! is_float($value)) { + throw new InvalidArgumentException( + sprintf('Array value for key [%s] must be a float, %s found.', $key, gettype($value)) + ); + } + + return $value; + }; + } + + /** + * Get an integer item from an array using "dot" notation. + */ + public static function integer() + { + return function (ArrayAccess|array $array, string|int|null $key, ?int $default = null) { + $value = Arr::get($array, $key, $default); + + if (! is_integer($value)) { + throw new InvalidArgumentException( + sprintf('Array value for key [%s] must be an integer, %s found.', $key, gettype($value)) + ); + } + + return $value; + }; + } + + /** + * Get a string item from an array using "dot" notation. + */ + public static function string() + { + return function (ArrayAccess|array $array, string|int|null $key, ?string $default = null) { + $value = Arr::get($array, $key, $default); + + if (! is_string($value)) { + throw new InvalidArgumentException( + sprintf('Array value for key [%s] must be a string, %s found.', $key, gettype($value)) + ); + } + + return $value; + }; + } + public function sortByMany() { return function ($array, $comparisons = []) { diff --git a/tests/Macros/ArrTest.php b/tests/Macros/ArrTest.php index e2badb707..040e89227 100644 --- a/tests/Macros/ArrTest.php +++ b/tests/Macros/ArrTest.php @@ -10,6 +10,111 @@ */ use Hyperf\Collection\Arr; +test('test getsAString', function () { + $test_array = ['string' => 'foo bar', 'integer' => 1234]; + + // Test string values are returned as strings + $this->assertSame( + 'foo bar', + Arr::string($test_array, 'string') + ); + + // Test that default string values are returned for missing keys + $this->assertSame( + 'default', + Arr::string($test_array, 'missing_key', 'default') + ); + + // Test that an exception is raised if the value is not a string + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessageMatches('#^Array value for key \[integer\] must be a string, (.*) found.#'); + Arr::string($test_array, 'integer'); +}); + +test('test getsAnInteger', function () { + $test_array = ['string' => 'foo bar', 'integer' => 1234]; + + // Test integer values are returned as integers + $this->assertSame( + 1234, + Arr::integer($test_array, 'integer') + ); + + // Test that default integer values are returned for missing keys + $this->assertSame( + 999, + Arr::integer($test_array, 'missing_key', 999) + ); + + // Test that an exception is raised if the value is not an integer + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessageMatches('#^Array value for key \[string\] must be an integer, (.*) found.#'); + Arr::integer($test_array, 'string'); +}); + +test('test getsAFloat', function () { + $test_array = ['string' => 'foo bar', 'float' => 12.34]; + + // Test float values are returned as floats + $this->assertSame( + 12.34, + Arr::float($test_array, 'float') + ); + + // Test that default float values are returned for missing keys + $this->assertSame( + 56.78, + Arr::float($test_array, 'missing_key', 56.78) + ); + + // Test that an exception is raised if the value is not a float + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessageMatches('#^Array value for key \[string\] must be a float, (.*) found.#'); + Arr::float($test_array, 'string'); +}); + +test('test getsABoolean', function () { + $test_array = ['string' => 'foo bar', 'boolean' => true]; + + // Test boolean values are returned as booleans + $this->assertSame( + true, + Arr::boolean($test_array, 'boolean') + ); + + // Test that default boolean values are returned for missing keys + $this->assertSame( + true, + Arr::boolean($test_array, 'missing_key', true) + ); + + // Test that an exception is raised if the value is not a boolean + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessageMatches('#^Array value for key \[string\] must be a boolean, (.*) found.#'); + Arr::boolean($test_array, 'string'); +}); + +test('test getsAnArray', function () { + $test_array = ['string' => 'foo bar', 'array' => ['foo', 'bar']]; + + // Test array values are returned as arrays + $this->assertSame( + ['foo', 'bar'], + Arr::array($test_array, 'array') + ); + + // Test that default array values are returned for missing keys + $this->assertSame( + [1, 'two'], + Arr::array($test_array, 'missing_key', [1, 'two']) + ); + + // Test that an exception is raised if the value is not an array + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessageMatches('#^Array value for key \[string\] must be an array, (.*) found.#'); + Arr::array($test_array, 'string'); +}); + test('test sortByMany', function () { $unsorted = [ ['name' => 'John', 'age' => 8, 'meta' => ['key' => 3]], From 098a110dfbe07588c7e8ee1f32494851e06fead9 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 30 Apr 2025 17:06:37 +0800 Subject: [PATCH 02/10] =?UTF-8?q?fix(tests):=20=E5=9C=A8=20PHP=208.3.20=20?= =?UTF-8?q?=E4=B8=8A=E8=B7=B3=E8=BF=87=E6=B5=8B=E8=AF=95=E4=BB=A5=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E5=B7=B2=E7=9F=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Support/SleepTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/Support/SleepTest.php b/tests/Support/SleepTest.php index b64394668..dee2161d0 100644 --- a/tests/Support/SleepTest.php +++ b/tests/Support/SleepTest.php @@ -28,6 +28,13 @@ #[\PHPUnit\Framework\Attributes\Group('support')] class SleepTest extends TestCase { + protected function setUp(): void + { + if (PHP_VERSION === '8.3.20') { + $this->markTestSkipped('Skipped on PHP 8.3.20 due to known issues.'); + } + } + protected function tearDown(): void { parent::tearDown(); From b554a900ad8d97fdcf6abb61652867d7f9d37a33 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 30 Apr 2025 17:15:03 +0800 Subject: [PATCH 03/10] =?UTF-8?q?fix(tests):=20=E6=9B=B4=E6=96=B0=20SleepT?= =?UTF-8?q?est=20=E4=BB=A5=E4=BD=BF=E7=94=A8=E5=B1=9E=E6=80=A7=E6=B3=A8?= =?UTF-8?q?=E8=A7=A3=E8=B7=B3=E8=BF=87=20PHP=208.3.20=20=E7=9A=84=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Support/SleepTest.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/Support/SleepTest.php b/tests/Support/SleepTest.php index dee2161d0..1a1092093 100644 --- a/tests/Support/SleepTest.php +++ b/tests/Support/SleepTest.php @@ -16,6 +16,7 @@ use Exception; use FriendsOfHyperf\Support\Sleep; use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; use RuntimeException; @@ -26,13 +27,15 @@ * @coversNothing */ #[\PHPUnit\Framework\Attributes\Group('support')] +#[RequiresPhp('!= 8.3.20')] class SleepTest extends TestCase { protected function setUp(): void { - if (PHP_VERSION === '8.3.20') { - $this->markTestSkipped('Skipped on PHP 8.3.20 due to known issues.'); - } + // if (PHP_VERSION === '8.3.20') { + // $this->markTestSkipped('Skipped on PHP 8.3.20 due to known issues.'); + // } + parent::setUp(); } protected function tearDown(): void From e39fce81c5764979f07744fbcc2002ad9db2cedf Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 30 Apr 2025 17:18:21 +0800 Subject: [PATCH 04/10] =?UTF-8?q?refactor(tests):=20=E7=A7=BB=E9=99=A4=20S?= =?UTF-8?q?leepTest=20=E4=B8=AD=E7=9A=84=20setUp=20=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E4=BB=A5=E7=AE=80=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Support/SleepTest.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/Support/SleepTest.php b/tests/Support/SleepTest.php index 1a1092093..8d300b283 100644 --- a/tests/Support/SleepTest.php +++ b/tests/Support/SleepTest.php @@ -30,14 +30,6 @@ #[RequiresPhp('!= 8.3.20')] class SleepTest extends TestCase { - protected function setUp(): void - { - // if (PHP_VERSION === '8.3.20') { - // $this->markTestSkipped('Skipped on PHP 8.3.20 due to known issues.'); - // } - parent::setUp(); - } - protected function tearDown(): void { parent::tearDown(); From 3cf31213acb10a88da54aceb9b320359b21f8433 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 30 Apr 2025 17:21:20 +0800 Subject: [PATCH 05/10] =?UTF-8?q?fix(tests):=20=E5=9C=A8=20CarbonCastTest?= =?UTF-8?q?=20=E4=B8=AD=E4=B8=BA=20'casts=20to=20carbon=20with=20timezone'?= =?UTF-8?q?=20=E6=B5=8B=E8=AF=95=E6=B7=BB=E5=8A=A0=20PHP=208.3.20=20?= =?UTF-8?q?=E8=B7=B3=E8=BF=87=E6=B3=A8=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/ValidatedDTO/Unit/CarbonCastTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ValidatedDTO/Unit/CarbonCastTest.php b/tests/ValidatedDTO/Unit/CarbonCastTest.php index ac24dcd29..e4520b985 100644 --- a/tests/ValidatedDTO/Unit/CarbonCastTest.php +++ b/tests/ValidatedDTO/Unit/CarbonCastTest.php @@ -65,7 +65,7 @@ $this->expectException(CastException::class); $castable->cast(test_property(), 'TEST'); -}); +})->skipOnPhp('8.3.20'); it('casts to carbon immutable', function () { $castable = new CarbonImmutableCast(); From 97b05de2e4ffd1f4638fc8a7d9c10f6c4f3b9828 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 30 Apr 2025 17:25:47 +0800 Subject: [PATCH 06/10] =?UTF-8?q?fix(tests):=20=E5=9C=A8=20CarbonCastTest?= =?UTF-8?q?=20=E4=B8=AD=E4=B8=BA=20'casts=20to=20carbon=20with=20timezone'?= =?UTF-8?q?=20=E6=B5=8B=E8=AF=95=E6=B7=BB=E5=8A=A0=20PHP=208.3.20=20?= =?UTF-8?q?=E8=B7=B3=E8=BF=87=E6=B3=A8=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/ValidatedDTO/Unit/CarbonCastTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/ValidatedDTO/Unit/CarbonCastTest.php b/tests/ValidatedDTO/Unit/CarbonCastTest.php index e4520b985..bec65f923 100644 --- a/tests/ValidatedDTO/Unit/CarbonCastTest.php +++ b/tests/ValidatedDTO/Unit/CarbonCastTest.php @@ -14,6 +14,8 @@ use FriendsOfHyperf\ValidatedDTO\Casting\CarbonImmutableCast; use FriendsOfHyperf\ValidatedDTO\Exception\CastException; +test()->skipOnPhp('8.3.20'); + it('casts to carbon', function () { $castable = new CarbonCast(); @@ -65,7 +67,7 @@ $this->expectException(CastException::class); $castable->cast(test_property(), 'TEST'); -})->skipOnPhp('8.3.20'); +}); it('casts to carbon immutable', function () { $castable = new CarbonImmutableCast(); From fb1698b5099baa0f6d6bf3776929b275286b79a6 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 30 Apr 2025 17:31:11 +0800 Subject: [PATCH 07/10] =?UTF-8?q?Revert=20"fix(tests):=20=E5=9C=A8=20Carbo?= =?UTF-8?q?nCastTest=20=E4=B8=AD=E4=B8=BA=20'casts=20to=20carbon=20with=20?= =?UTF-8?q?timezone'=20=E6=B5=8B=E8=AF=95=E6=B7=BB=E5=8A=A0=20PHP=208.3.20?= =?UTF-8?q?=20=E8=B7=B3=E8=BF=87=E6=B3=A8=E8=A7=A3"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 97b05de2e4ffd1f4638fc8a7d9c10f6c4f3b9828. --- tests/ValidatedDTO/Unit/CarbonCastTest.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/ValidatedDTO/Unit/CarbonCastTest.php b/tests/ValidatedDTO/Unit/CarbonCastTest.php index bec65f923..e4520b985 100644 --- a/tests/ValidatedDTO/Unit/CarbonCastTest.php +++ b/tests/ValidatedDTO/Unit/CarbonCastTest.php @@ -14,8 +14,6 @@ use FriendsOfHyperf\ValidatedDTO\Casting\CarbonImmutableCast; use FriendsOfHyperf\ValidatedDTO\Exception\CastException; -test()->skipOnPhp('8.3.20'); - it('casts to carbon', function () { $castable = new CarbonCast(); @@ -67,7 +65,7 @@ $this->expectException(CastException::class); $castable->cast(test_property(), 'TEST'); -}); +})->skipOnPhp('8.3.20'); it('casts to carbon immutable', function () { $castable = new CarbonImmutableCast(); From 8207101ffd87813d5843e6193eddd8355c60934d Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 30 Apr 2025 18:52:10 +0800 Subject: [PATCH 08/10] =?UTF-8?q?fix(tests):=20=E5=9C=A8=20CarbonCastTest?= =?UTF-8?q?=20=E4=B8=AD=E4=B8=BA=20'casts=20to=20carbon'=20=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E6=B7=BB=E5=8A=A0=20PHP=208.3.20=20=E8=B7=B3=E8=BF=87?= =?UTF-8?q?=E6=B3=A8=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/ValidatedDTO/Unit/CarbonCastTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/ValidatedDTO/Unit/CarbonCastTest.php b/tests/ValidatedDTO/Unit/CarbonCastTest.php index e4520b985..3ec49a19d 100644 --- a/tests/ValidatedDTO/Unit/CarbonCastTest.php +++ b/tests/ValidatedDTO/Unit/CarbonCastTest.php @@ -14,6 +14,9 @@ use FriendsOfHyperf\ValidatedDTO\Casting\CarbonImmutableCast; use FriendsOfHyperf\ValidatedDTO\Exception\CastException; +beforeEach(function () { +})->skipOnPhp('8.3.20'); + it('casts to carbon', function () { $castable = new CarbonCast(); From 9c9916b28c51cddc9f7ee4e20283bda636c365dd Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 30 Apr 2025 18:58:04 +0800 Subject: [PATCH 09/10] =?UTF-8?q?fix(tests):=20=E4=BF=AE=E5=A4=8D=20Carbon?= =?UTF-8?q?CastTest=20=E4=B8=AD=20beforeEach=20=E7=9A=84=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/ValidatedDTO/Unit/CarbonCastTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/ValidatedDTO/Unit/CarbonCastTest.php b/tests/ValidatedDTO/Unit/CarbonCastTest.php index 3ec49a19d..1da6f0dbd 100644 --- a/tests/ValidatedDTO/Unit/CarbonCastTest.php +++ b/tests/ValidatedDTO/Unit/CarbonCastTest.php @@ -14,8 +14,7 @@ use FriendsOfHyperf\ValidatedDTO\Casting\CarbonImmutableCast; use FriendsOfHyperf\ValidatedDTO\Exception\CastException; -beforeEach(function () { -})->skipOnPhp('8.3.20'); +beforeEach(function () {})->skipOnPhp('8.3.20'); it('casts to carbon', function () { $castable = new CarbonCast(); From 271b3b54236d02f723204c4e8455f1453006e9c7 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 30 Apr 2025 18:59:45 +0800 Subject: [PATCH 10/10] =?UTF-8?q?fix(tests):=20=E4=BF=AE=E5=A4=8D=20Carbon?= =?UTF-8?q?CastTest=20=E4=B8=AD=20'casts=20to=20carbon=20with=20timezone'?= =?UTF-8?q?=20=E6=B5=8B=E8=AF=95=E7=9A=84=20PHP=208.3.20=20=E8=B7=B3?= =?UTF-8?q?=E8=BF=87=E6=B3=A8=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/ValidatedDTO/Unit/CarbonCastTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ValidatedDTO/Unit/CarbonCastTest.php b/tests/ValidatedDTO/Unit/CarbonCastTest.php index 1da6f0dbd..207bcc179 100644 --- a/tests/ValidatedDTO/Unit/CarbonCastTest.php +++ b/tests/ValidatedDTO/Unit/CarbonCastTest.php @@ -67,7 +67,7 @@ $this->expectException(CastException::class); $castable->cast(test_property(), 'TEST'); -})->skipOnPhp('8.3.20'); +}); it('casts to carbon immutable', function () { $castable = new CarbonImmutableCast();