From 0bf31e9ad3d8c85eca2f8c0a66b36f878f273feb Mon Sep 17 00:00:00 2001 From: Rodolfo Berrios <20590102+rodber@users.noreply.github.com> Date: Sat, 18 Jan 2025 17:00:56 -0300 Subject: [PATCH] close #11 --- src/functions.php | 27 ++++++++++++++++++++++++++- tests/FunctionsTest.php | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/functions.php b/src/functions.php index 2f82228..8d41dc4 100644 --- a/src/functions.php +++ b/src/functions.php @@ -14,6 +14,7 @@ namespace Chevere\Parameter; use ArrayAccess; +use BadMethodCallException; use Chevere\Parameter\Attributes\ReturnAttr; use Chevere\Parameter\Exceptions\AttributeNotFoundException; use Chevere\Parameter\Exceptions\ParameterException; @@ -41,8 +42,32 @@ use Throwable; use function Chevere\Message\message; -function cast(mixed $argument): CastInterface +function cast(mixed $argument, string|int ...$key): CastInterface { + if ($key !== []) { + if (! ($argument instanceof ArrayAccess || is_array($argument))) { + throw new BadMethodCallException( + (string) message( + 'Argument must be array-accessible, %type% provided', + type: gettype($argument) + ) + ); + } + $fn = function ($carry, $item) { + if (array_key_exists($item, $carry)) { + return $carry[$item]; + } + + throw new InvalidArgumentException( + (string) message( + 'Key `%key%` not found in array', + key: $item + ) + ); + }; + $argument = array_reduce($key, $fn, $argument); + } + return new Cast($argument); } diff --git a/tests/FunctionsTest.php b/tests/FunctionsTest.php index 6448dc8..361a297 100644 --- a/tests/FunctionsTest.php +++ b/tests/FunctionsTest.php @@ -13,6 +13,7 @@ namespace Chevere\Tests; +use BadMethodCallException; use Chevere\Parameter\Exceptions\ParameterException; use Chevere\Parameter\Exceptions\ReturnException; use InvalidArgumentException; @@ -370,6 +371,44 @@ public function testCast(): void $this->assertSame($value, $cast->string()); } + public function testCastNested(): void + { + $value = [ + 'super' => [ + 'taldo' => null, + ], + 3 => 'co', + 'agac', + ]; + $cast = cast($value); + $this->assertSame($value, $cast->array()); + $cast = cast($value, 'super'); + $this->assertSame($value['super'], $cast->array()); + $cast = cast($value, 'super', 'taldo'); + $this->assertSame($value['super']['taldo'], $cast->mixed()); + $cast = cast($value, 3); + $this->assertSame($value[3], $cast->string()); + $cast = cast($value, 4); + $this->assertSame($value[4], $cast->string()); + } + + public static function dataProviderCastNestedError(): array + { + return [ + [1, BadMethodCallException::class], + [[], InvalidArgumentException::class], + ]; + } + + /** + * @dataProvider dataProviderCastNestedError + */ + public function testCastNestedError(mixed $value, string $exception): void + { + $this->expectException($exception); + $cast = cast($value, 'foo'); + } + public function testParameterAttr(): void { $caller = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0];