diff --git a/src/Traits/EnumFrom.php b/src/Traits/EnumFrom.php index 436b7cb..51b75a5 100644 --- a/src/Traits/EnumFrom.php +++ b/src/Traits/EnumFrom.php @@ -11,9 +11,16 @@ trait EnumFrom use EnumEquality; /** - * Gets the Enum by name, value or another enum. - */ - public static function wrap(self|string|int|null $value): ?self + * Gets the Enum by name, value or another enum. + * + * @param self|string|int|null $value The value to wrap as the enum. If an instance of the enum is passed it is returned unchanged. + * Strings are treated as either backing values (for int-backed enums) or names. + * @param bool $strict When true, the method throws a {@see ValueError} if the given value cannot be converted to a valid enum. + * When false (default), the method returns null on failure. + * @return ?self The matched enum instance, or null if no match is found and `$strict` is false. + * @throws \ValueError If `$strict` is true and the value is not a valid enum name or backing value. + */ + public static function wrap(self|string|int|null $value, bool $strict = false): ?self { if ($value instanceof self || is_null($value)) { return $value; @@ -21,7 +28,7 @@ public static function wrap(self|string|int|null $value): ?self $enum = null; if (is_string($value) && self::isIntBacked()) { - if(is_numeric($value)){ + if (is_numeric($value)) { $enum = self::tryFrom(intval($value)); } } else { @@ -32,6 +39,10 @@ public static function wrap(self|string|int|null $value): ?self $enum = self::tryFromName($value); } + if (is_null($enum) and $strict) { + throw new ValueError('"'.$value.'" is not a valid backing value for enum "'.self::class.'"'); + } + return $enum; } diff --git a/src/Traits/EnumInvokable.php b/src/Traits/EnumInvokable.php index 7e28ce4..3727e30 100644 --- a/src/Traits/EnumInvokable.php +++ b/src/Traits/EnumInvokable.php @@ -26,7 +26,7 @@ public static function __callStatic(string $enumName, array $args): string|int { foreach (self::cases() as $case) { $check1 = strtolower($case->name); - $check2 = str_replace('_', '',strtolower($case->name)); + $check2 = str_replace('_', '', strtolower($case->name)); if ( $check1 === strtolower($enumName) || $check1 === strtolower(self::snake($enumName)) diff --git a/tests/EnumFromTest.php b/tests/EnumFromTest.php index fd1344b..f278282 100644 --- a/tests/EnumFromTest.php +++ b/tests/EnumFromTest.php @@ -46,6 +46,16 @@ 'String Backed Enum' => [StringBackedEnum::class, 'M'], ]); +it('throws ValueError for invalid backing value in strict mode', function () { + expect(fn () => StringBackedEnum::wrap('non-existent-value', true)) + ->toThrow(ValueError::class); +}); + +it('returns null for invalid backing value when not in strict mode', function () { + expect(StringBackedEnum::wrap('non-existent-value')) + ->toBeNull(); +}); + it('does work with tryFrom method', function ($enumCass, $value, $result) { expect($enumCass::tryFrom($value))->toBe($result)->not->toThrow(ValueError::class); })->with([