From 076e2262b8839365f440a406ccf8212bcf546c73 Mon Sep 17 00:00:00 2001 From: david <61474950+zero-to-prod@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:48:42 -0500 Subject: [PATCH] Add support for `when`; (#22) Co-authored-by: david_smith --- README.md | 22 ++++++++++++++ src/DataModelHelper.php | 36 +++++++++++++++++++++++ tests/Unit/When/Eval/EvalTest.php | 27 +++++++++++++++++ tests/Unit/When/Eval/User.php | 32 ++++++++++++++++++++ tests/Unit/When/Nullable/NullTest.php | 18 ++++++++++++ tests/Unit/When/Nullable/User.php | 25 ++++++++++++++++ tests/Unit/When/Required/RequiredTest.php | 17 +++++++++++ tests/Unit/When/Required/User.php | 21 +++++++++++++ tests/Unit/When/Value/User.php | 31 +++++++++++++++++++ tests/Unit/When/Value/ValueTest.php | 18 ++++++++++++ 10 files changed, 247 insertions(+) create mode 100644 tests/Unit/When/Eval/EvalTest.php create mode 100644 tests/Unit/When/Eval/User.php create mode 100644 tests/Unit/When/Nullable/NullTest.php create mode 100644 tests/Unit/When/Nullable/User.php create mode 100644 tests/Unit/When/Required/RequiredTest.php create mode 100644 tests/Unit/When/Required/User.php create mode 100644 tests/Unit/When/Value/User.php create mode 100644 tests/Unit/When/Value/ValueTest.php diff --git a/README.md b/README.md index f5717e5..21a2c1d 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ class DataModelHelper ## Helper Methods +- [when](#when): Create a map of any type by using - [mapOf](#mapof): Create a map of any type by using - [pregReplace](#pregreplace): Perform a regular expression search and replace. - [pregMatch](#pregmatch): Perform a regular expression match. @@ -41,6 +42,27 @@ class DataModelHelper - [isEmail](#isemail): Validates an email. - [isMultiple](#ismultiple): Validate a value is a multiple of another. +### `when` + +Use `when` to call a function based on a condition. + +```php +class User +{ + use \Zerotoprod\DataModel\DataModel; + use \Zerotoprod\DataModelHelper\DataModelHelper; + + #[Describe([ + 'cast' => [self::class, 'when'], + 'eval' => '$value >= $context["value_2"]' // The expression to evaluate. + 'true' => [MyAction::class, 'passed'], // Optional. Invoked when condition is true. + 'false' => [MyAction::class, 'failed'], // Optional. Invoked when condition is true. + 'required', // Throws PropertyRequiredException when value not present. + ])] + public string $value; +} +``` + ### `mapOf` Create a map of any type by using the `DataModelHelper::mapOf()` method. diff --git a/src/DataModelHelper.php b/src/DataModelHelper.php index 04bfb3f..992f701 100644 --- a/src/DataModelHelper.php +++ b/src/DataModelHelper.php @@ -314,4 +314,40 @@ public static function isMultiple(mixed $value, array $context, ?ReflectionAttri return $value; } + + /** + * Determine if a given value is a valid URL. + * ``` + * #[Describe([ + * 'cast' => [self::class, 'when'], + * 'eval' => '$value >= $context["value_2"]' // The expression to evaluate. + * 'true' => [MyAction::class, 'passed'], // Optional. Invoked when condition is true. + * 'false' => [MyAction::class, 'failed'], // Optional. Invoked when condition is true. + * 'required', // Throws PropertyRequiredException when value not present. + * ])] + * ``` + */ + public static function when(mixed $value, array $context, ?ReflectionAttribute $Attribute, ReflectionProperty $Property): ?string + { + $args = $Attribute?->getArguments()[0]; + if ((!empty($args['required']) || in_array('required', $args, true)) + && !isset($context[$Property->getName()]) + ) { + throw new PropertyRequiredException("Property `\${$Property->getName()}` is required."); + } + + if (!$value && $Property->getType()?->allowsNull()) { + return null; + } + + if (eval("return {$args['eval']};")) { + if (isset($args['true'])) { + return call_user_func($args['true'], $value, $context, $Attribute, $Property); + } + } elseif (isset($args['false'])) { + return call_user_func($args['false'], $value, $context, $Attribute, $Property); + } + + return $value; + } } \ No newline at end of file diff --git a/tests/Unit/When/Eval/EvalTest.php b/tests/Unit/When/Eval/EvalTest.php new file mode 100644 index 0000000..53be48c --- /dev/null +++ b/tests/Unit/When/Eval/EvalTest.php @@ -0,0 +1,27 @@ + 100, + ]); + + self::assertEquals(1, $User->value); + } + + #[Test] public function false(): void + { + $User = User::from([ + User::value => 2, + ]); + + self::assertEquals(0, $User->value); + } +} \ No newline at end of file diff --git a/tests/Unit/When/Eval/User.php b/tests/Unit/When/Eval/User.php new file mode 100644 index 0000000..512d8c3 --- /dev/null +++ b/tests/Unit/When/Eval/User.php @@ -0,0 +1,32 @@ + [self::class, 'when'], + 'eval' => '$value >= 10', + 'true' => [self::class, 'true'], + 'false' => [self::class, 'false'], + ])] + public int $value; + + public static function true(): int + { + return 1; + } + public static function false(): int + { + return 0; + } +} \ No newline at end of file diff --git a/tests/Unit/When/Nullable/NullTest.php b/tests/Unit/When/Nullable/NullTest.php new file mode 100644 index 0000000..842888d --- /dev/null +++ b/tests/Unit/When/Nullable/NullTest.php @@ -0,0 +1,18 @@ + null, + ]); + + self::assertNull($User->value); + } +} \ No newline at end of file diff --git a/tests/Unit/When/Nullable/User.php b/tests/Unit/When/Nullable/User.php new file mode 100644 index 0000000..96b887f --- /dev/null +++ b/tests/Unit/When/Nullable/User.php @@ -0,0 +1,25 @@ + [self::class, 'when'], + ])] + public ?int $value; + + public static function false(): int + { + return 0; + } +} \ No newline at end of file diff --git a/tests/Unit/When/Required/RequiredTest.php b/tests/Unit/When/Required/RequiredTest.php new file mode 100644 index 0000000..8edee64 --- /dev/null +++ b/tests/Unit/When/Required/RequiredTest.php @@ -0,0 +1,17 @@ +expectException(PropertyRequiredException::class); + $this->expectExceptionMessage('Property `$value` is required.'); + User::from(); + } +} \ No newline at end of file diff --git a/tests/Unit/When/Required/User.php b/tests/Unit/When/Required/User.php new file mode 100644 index 0000000..09edb1c --- /dev/null +++ b/tests/Unit/When/Required/User.php @@ -0,0 +1,21 @@ + [self::class, 'when'], + 'required' + ])] + public string $value; +} \ No newline at end of file diff --git a/tests/Unit/When/Value/User.php b/tests/Unit/When/Value/User.php new file mode 100644 index 0000000..3e6bddd --- /dev/null +++ b/tests/Unit/When/Value/User.php @@ -0,0 +1,31 @@ + [self::class, 'when'], + 'eval' => '$value >= 10', + 'false' => [self::class, 'false'], + ])] + public int $value; + + public static function true(): int + { + return 1; + } + public static function false(): int + { + return 0; + } +} \ No newline at end of file diff --git a/tests/Unit/When/Value/ValueTest.php b/tests/Unit/When/Value/ValueTest.php new file mode 100644 index 0000000..2524579 --- /dev/null +++ b/tests/Unit/When/Value/ValueTest.php @@ -0,0 +1,18 @@ + 100, + ]); + + self::assertEquals(100, $User->value); + } +} \ No newline at end of file