Repository: knuckleswtf/scribe (php)

Issue:
Laravel Enum validation
scribe can not auto generate suitable doc for request validation enum:

my validation:
'bannerDetail.type' => [
                'required',
                new Enum(BannerDetailType::class),
            ],

generated doc:

bannerDetail.type   string   
Example: quidem

And it force me to write @bodyParam manualy or using in valiadator.

Pull request description:
Parse Enum Rule
Adds description, example and type for Laravel's Enum Rule.

Fixes #579

Patch:
diff --git a/src/Extracting/ParsesValidationRules.php b/src/Extracting/ParsesValidationRules.php
index 3799d3c9..9c4eb754 100644
--- a/src/Extracting/ParsesValidationRules.php
+++ b/src/Extracting/ParsesValidationRules.php
@@ -191,6 +191,22 @@ trait ParsesValidationRules
             return true;
         }
 
+        if (function_exists('enum_exists') && $rule instanceof \Illuminate\Validation\Rules\Enum) {
+            $reflection = new \ReflectionClass($rule);
+            $property = $reflection->getProperty('type');
+            $property->setAccessible(true);
+            $type = $property->getValue($rule);
+
+            if (enum_exists($type) && method_exists($type, 'tryFrom')) {
+                $cases = array_map(fn ($case) => $case->value, $type::cases());
+                $parameterData['type'] = gettype($cases[0]);
+                $parameterData['description'] = ' Must be one of ' . w::getListOfValuesAsFriendlyHtmlString($cases) . ' ';
+                $parameterData['setter'] = fn () => Arr::random($cases);
+            }
+
+            return true;
+        }
+
         if ($rule instanceof Rule || $rule instanceof InvokableRule) {
             if (method_exists($rule, 'docs')) {
                 $customData = call_user_func_array([$rule, 'docs'], []) ?: [];


Test patch:
diff --git a/tests/Fixtures/TestIntegerBackedEnum.php b/tests/Fixtures/TestIntegerBackedEnum.php
new file mode 100644
index 00000000..052bfdde
--- /dev/null
+++ b/tests/Fixtures/TestIntegerBackedEnum.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Knuckles\Scribe\Tests\Fixtures;
+
+enum TestIntegerBackedEnum: int
+{
+    case One = 1;
+    case Two = 2;
+    case Three = 3;
+}
diff --git a/tests/Fixtures/TestStringBackedEnum.php b/tests/Fixtures/TestStringBackedEnum.php
new file mode 100644
index 00000000..905720a6
--- /dev/null
+++ b/tests/Fixtures/TestStringBackedEnum.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Knuckles\Scribe\Tests\Fixtures;
+
+enum TestStringBackedEnum: string
+{
+    case Red = 'red';
+    case Green = 'green';
+    case Blue = 'blue';
+}
diff --git a/tests/Unit/ValidationRuleParsingTest.php b/tests/Unit/ValidationRuleParsingTest.php
index 2a29fd3a..a2f5e269 100644
--- a/tests/Unit/ValidationRuleParsingTest.php
+++ b/tests/Unit/ValidationRuleParsingTest.php
@@ -9,6 +9,7 @@ use Illuminate\Validation\ValidationException;
 use Knuckles\Scribe\Extracting\ParsesValidationRules;
 use Knuckles\Scribe\Tests\BaseLaravelTest;
 use Knuckles\Scribe\Tools\DocumentationConfig;
+use Knuckles\Scribe\Tests\Fixtures;
 
 class ValidationRuleParsingTest extends BaseLaravelTest
 {
@@ -506,6 +507,41 @@ class ValidationRuleParsingTest extends BaseLaravelTest
         $this->assertEquals(true, $results['custom_rule']['required']);
         $this->assertEquals('This is a dummy test rule.', $results['custom_rule']['description']);
     }
+
+    /** @test */
+    public function can_parse_enum_rules()
+    {
+        if (phpversion() < 8.1) {
+            $this->markTestSkipped('Enums are only supported in PHP 8.1 or later');
+        }
+
+        $results = $this->strategy->parse([
+            'enum' => ['required', Rule::enum(Fixtures\TestStringBackedEnum::class)],
+        ]);
+        $this->assertEquals('string', $results['enum']['type']);
+        $this->assertEquals(
+            'Must be one of <code>red</code>, <code>green</code>, or <code>blue</code>.',
+            $results['enum']['description']
+        );
+        $this->assertTrue(in_array(
+            $results['enum']['example'],
+            array_map(fn ($case) => $case->value, Fixtures\TestStringBackedEnum::cases())
+        ));
+
+
+        $results = $this->strategy->parse([
+            'enum' => ['required', Rule::enum(Fixtures\TestIntegerBackedEnum::class)],
+        ]);
+        $this->assertEquals('integer', $results['enum']['type']);
+        $this->assertEquals(
+            'Must be one of <code>1</code>, <code>2</code>, or <code>3</code>.',
+            $results['enum']['description']
+        );
+        $this->assertTrue(in_array(
+            $results['enum']['example'],
+            array_map(fn ($case) => $case->value, Fixtures\TestIntegerBackedEnum::cases())
+        ));
+    }
 }
 
 class DummyValidationRule implements \Illuminate\Contracts\Validation\Rule