Sfoglia il codice sorgente

Switch to new FormRequest implementation

shalvah 5 anni fa
parent
commit
384030d375

+ 0 - 54
src/Extracting/BodyParam.php

@@ -1,54 +0,0 @@
-<?php
-
-namespace Knuckles\Scribe\Extracting;
-
-
-class BodyParam
-{
-    /**
-     * @var string
-     */
-    private $description;
-
-    private $example;
-
-    /**
-     * @var array
-     */
-    private $validationRules = [];
-
-    public function __construct(string $description = '', $example = '')
-    {
-        $this->description = $description;
-        $this->example = $example;
-    }
-
-    public static function description(string $description = '')
-    {
-        return new self($description);
-    }
-
-    public function example($example = null)
-    {
-        $this->example = $example;
-        return $this;
-    }
-
-    public function rules($rules = [])
-    {
-        if (is_string($rules)) {
-            $rules = explode('|', $rules);
-        }
-
-        $rules[] = (new BodyParameterDefinition($this->description, $this->example))->__toString();
-        $this->validationRules = $rules;
-        return $rules;
-    }
-
-    public function __toString()
-    {
-        return implode('|', array_map(function ($rule) {
-            return (string) $rule; // Cast is important to handle rule objects
-        }, $this->validationRules));
-    }
-}

+ 0 - 47
src/Extracting/BodyParameterDefinition.php

@@ -1,47 +0,0 @@
-<?php
-
-
-namespace Knuckles\Scribe\Extracting;
-
-
-use Illuminate\Contracts\Validation\Rule;
-
-/**
- * BodyParameter validation rule
- * This is a dummy rule that always passes.
- * Used to pass properties of the body parameter to this package.
- */
-class BodyParameterDefinition implements Rule
-{
-    /**
-     * @var string
-     */
-    public $parameterDescription;
-
-    public $parameterExample;
-
-    public const RULENAME = "scribe_body_param";
-    public const DELIMITER = "/////";
-
-    public function __construct(string $description = '', $example = '')
-    {
-        $this->parameterDescription = $description;
-        $this->parameterExample = $example;
-    }
-
-    public function passes($attribute, $value)
-    {
-        return true;
-    }
-
-    public function message()
-    {
-        return '';
-    }
-
-    public function __toString()
-    {
-        // Can't use comma as delimiter since description may contain a comma
-        return self::RULENAME.":{$this->parameterDescription}".self::DELIMITER."$this->parameterExample";
-    }
-}

+ 36 - 35
src/Extracting/Strategies/BodyParameters/GetFromFormRequest.php

@@ -52,25 +52,27 @@ class GetFromFormRequest extends Strategy
             if (
                 (class_exists(LaravelFormRequest::class) && $parameterClass->isSubclassOf(LaravelFormRequest::class))
                 || (class_exists(DingoFormRequest::class) && $parameterClass->isSubclassOf(DingoFormRequest::class))) {
-                $bodyParametersFromDocBlock = $this->getBodyParametersFromValidationRules($this->getRouteValidationRules($parameterClassName));
-
-                return $bodyParametersFromDocBlock;
+                /** @var LaravelFormRequest|DingoFormRequest\ $formRequest */
+                $formRequest = new $parameterClassName;
+                $bodyParametersFromFormRequest = $this->getBodyParametersFromValidationRules(
+                    $this->getRouteValidationRules($formRequest),
+                    $this->getCustomParameterData($formRequest)
+                    );
+
+                return $bodyParametersFromFormRequest;
             }
         }
 
         return [];
     }
 
-    protected function getRouteValidationRules(string $formRequestClass)
+    /**
+     * @param LaravelFormRequest|DingoFormRequest $formRequest
+     *
+     * @return mixed
+     */
+    protected function getRouteValidationRules($formRequest)
     {
-        /** @var LaravelFormRequest|DingoFormRequest $formRequest */
-        $formRequest = new $formRequestClass;/*
-        // Add route parameter bindings
-        $formRequest->setContainer(app());
-        $formRequest->request->add($bindings);
-        $formRequest->query->add($bindings);
-        $formRequest->setMethod($routeMethods[0]);*/
-
         if (method_exists($formRequest, 'validator')) {
             $validationFactory = app(ValidationFactory::class);
 
@@ -81,38 +83,47 @@ class GetFromFormRequest extends Strategy
         }
     }
 
-    public function getBodyParametersFromValidationRules(array $validationRules)
+    /**
+     * @param LaravelFormRequest|DingoFormRequest $formRequest
+     */
+    protected function getCustomParameterData($formRequest)
+    {
+        if (method_exists($formRequest, 'bodyParameters')) {
+            return call_user_func_array([$formRequest, 'bodyParameters'], []);
+        }
+
+        clara('knuckleswtf/scribe')->warn("No bodyParameters() method found in ".get_class($formRequest)." Scribe will only be able to extract basic information from the rules() method.");
+        return [];
+    }
+
+    public function getBodyParametersFromValidationRules(array $validationRules, array $customParameterData = [])
     {
         self::$MISSING_VALUE = new \stdClass();
         $rules = $this->normaliseRules($validationRules);
 
         $parameters = [];
         foreach ($rules as $parameter => $ruleset) {
+            if (count($customParameterData) && !isset($customParameterData[$parameter])) {
+                clara('knuckleswtf/scribe')->warn("No data found for parameter '$parameter' from your bodyParameters() method. Add an entry for '$parameter' so you can add description and example.");
+            }
+            $parameterInfo = $customParameterData[$parameter] ?? [];
+
             $parameterData = [
                 'required' => false,
                 'type' => null,
                 'value' => self::$MISSING_VALUE,
-                'scribe_value' => self::$MISSING_VALUE,
                 'description' => '',
-                'visible_to_scribe' => false,
             ];
             foreach ($ruleset as $rule) {
                 $this->parseRule($rule, $parameterData);
             }
 
-            // Ignore parameters that didn't use our custom rule
-            if (!$parameterData['visible_to_scribe']) {
-                continue;
-            }
-            unset($parameterData['visible_to_scribe']);
-
             // Make sure the user-specified description comes first.
-            $businessDescription = $parameterData['scribe_description'] ?? '';
+            $businessDescription = $parameterInfo['description'] ?? '';
             $validationDescription = trim($parameterData['description'] ?: '');
             $fullDescription = trim($businessDescription . ' ' .trim($validationDescription));
             // Let's have our sentences end with full stops, like civilized people.🙂
             $parameterData['description'] = $fullDescription ? rtrim($fullDescription, '.').'.' : $fullDescription;
-            unset($parameterData['scribe_description']);
 
             // Set default values for type
             if (is_null($parameterData['type'])) {
@@ -124,10 +135,9 @@ class GetFromFormRequest extends Strategy
             }
 
             // Make sure the user-specified example overwrites others.
-            if ($parameterData['scribe_value'] !== self::$MISSING_VALUE) {
-                $parameterData['value'] = $parameterData['scribe_value'];
+            if (isset($parameterInfo['example'])) {
+                $parameterData['value'] = $parameterInfo['example'];
             }
-            unset($parameterData['scribe_value']);
 
             if (!is_null($parameterData['value']) && $parameterData['value'] !== self::$MISSING_VALUE) {
                 // Cast is important since values had been cast to string when serializing the validator
@@ -202,12 +212,6 @@ class GetFromFormRequest extends Strategy
         // For this reason, only deterministic rules are supported
         // 3. All rules supported must be rules that we can generate a valid dummy value for.
         switch ($rule) {
-            case BodyParameterDefinition::RULENAME:
-                $parameterData['scribe_description'] = $arguments[0];
-                $parameterData['scribe_value'] = $arguments[1] == ''  ? self::$MISSING_VALUE : $arguments[1];
-                $parameterData['visible_to_scribe'] = true;
-                break;
-
             case 'required':
                 $parameterData['required'] = true;
                 break;
@@ -353,9 +357,6 @@ class GetFromFormRequest extends Strategy
             // These rules can have ommas in their arguments, so we don't split on commas
             if (in_array(strtolower($rule), ['regex', 'date', 'date_format'])) {
                 $ruleArguments = [$argumentsString];
-                // For our custom rule, we're using a different delimiter, since descriptions may contain commas.
-            } elseif (strtolower($rule) === BodyParameterDefinition::RULENAME) {
-                $ruleArguments = explode(BodyParameterDefinition::DELIMITER, $argumentsString);
             } else {
                 $ruleArguments = str_getcsv($argumentsString);
             }

+ 0 - 5
src/ScribeServiceProvider.php

@@ -2,10 +2,8 @@
 
 namespace Knuckles\Scribe;
 
-use Illuminate\Support\Facades\Validator;
 use Illuminate\Support\ServiceProvider;
 use Knuckles\Scribe\Commands\GenerateDocumentation;
-use Knuckles\Scribe\Extracting\BodyParameterDefinition;
 use Knuckles\Scribe\Matching\RouteMatcher;
 use Knuckles\Scribe\Matching\RouteMatcherInterface;
 
@@ -18,9 +16,6 @@ class ScribeServiceProvider extends ServiceProvider
      */
     public function boot()
     {
-        // Ensure our dummy validation rule always passes
-        Validator::extend(BodyParameterDefinition::RULENAME, function () { return true; });
-
         $this->loadViewsFrom(__DIR__ . '/../resources/views/', 'scribe');
 
         $this->publishes([

+ 47 - 34
tests/Extracting/Strategies/BodyParameters/GetFromFormRequestTest.php

@@ -4,7 +4,6 @@ namespace Knuckles\Scribe\Tests\Extracting\Strategies\BodyParameters;
 
 use Illuminate\Support\Facades\Validator;
 use Illuminate\Validation\ValidationException;
-use Knuckles\Scribe\Extracting\BodyParam;
 use Knuckles\Scribe\Extracting\Strategies\BodyParameters\GetFromFormRequest;
 use Knuckles\Scribe\ScribeServiceProvider;
 use Knuckles\Scribe\Tests\Fixtures\TestController;
@@ -93,17 +92,16 @@ class GetFromFormRequestTest extends TestCase
                 'value' => 'Doe',
             ],
         ], $results);
-
-        $this->assertArrayNotHasKey('gets_ignored', $results);
     }
+
     /**
      * @test
      * @dataProvider supportedRules
      */
-    public function can_handle_specific_rules($ruleset, $expected)
+    public function can_handle_specific_rules($ruleset, $customInfo, $expected)
     {
         $strategy = new GetFromFormRequest(new DocumentationConfig([]));
-        $results = $strategy->getBodyParametersFromValidationRules($ruleset);
+        $results = $strategy->getBodyParametersFromValidationRules($ruleset, $customInfo);
 
         $parameterName = array_keys($ruleset)[0];
 
@@ -135,104 +133,119 @@ class GetFromFormRequestTest extends TestCase
         $description = 'A description';
         return [
             'required' => [
-                ['required' => BodyParam::description($description)->rules('required')],
+                ['required' => 'required'],
+                ['required' => ['description' => $description]],
                 [
                     'required' => true,
-                ]
+                ],
             ],
             'string' => [
-                ['string' => BodyParam::description($description)->rules('string|required')],
+                ['string' => 'string|required'],
+                ['string' => ['description' => $description]],
                 [
                     'type' => 'string',
-                ]
+                ],
             ],
             'boolean' => [
-                ['boolean' => BodyParam::description($description)->rules('boolean|required')],
+                ['boolean' => 'boolean|required'],
+                ['boolean' => ['description' => $description]],
                 [
                     'type' => 'boolean',
-                ]
+                ],
             ],
             'integer' => [
-                ['integer' => BodyParam::description($description)->rules('integer|required')],
+                ['integer' => 'integer|required'],
+                ['integer' => ['description' => $description]],
                 [
                     'type' => 'integer',
-                ]
+                ],
             ],
             'numeric' => [
-                ['numeric' => BodyParam::description($description)->rules('numeric|required')],
+                ['numeric' => 'numeric|required'],
+                ['numeric' => ['description' => $description]],
                 [
                     'type' => 'number',
-                ]
+                ],
             ],
             'array' => [
-                ['array' => BodyParam::description($description)->rules('array|required')],
+                ['array' => 'array|required'],
+                ['array' => ['description' => $description]],
                 [
                     'type' => 'array',
-                ]
+                ],
             ],
 
             /* Ignore file fo now until we figure out how to support it
             'file' => [
-                ['file' => BodyParam::description($description)->rules('file|required')],
+                ['file' => 'file|required'],
+['file' => ['description' => $description]],
                 [
                     'type' => 'file',
                 ]
             ],*/
             'timezone' => [
-                ['timezone' => BodyParam::description($description)->rules('timezone|required')],
+                ['timezone' => 'timezone|required'],
+                ['timezone' => ['description' => $description]],
                 [
                     'description' => 'The value must be a valid time zone, such as `Africa/Accra`.',
                     'type' => 'string',
-                ]
+                ],
             ],
             'email' => [
-                ['email' => BodyParam::description($description)->rules('email|required')],
+                ['email' => 'email|required'],
+                ['email' => ['description' => $description]],
                 [
                     'description' => 'The value must be a valid email address.',
                     'type' => 'string',
-                ]
+                ],
             ],
             'url' => [
-                ['url' => BodyParam::description($description)->rules('url|required')],
+                ['url' => 'url|required'],
+                ['url' => ['description' => $description]],
                 [
                     'description' => 'The value must be a valid URL.',
                     'type' => 'string',
-                ]
+                ],
             ],
             'ip' => [
-                ['ip' => BodyParam::description($description)->rules('ip|required')],
+                ['ip' => 'ip|required'],
+                ['ip' => ['description' => $description]],
                 [
                     'description' => 'The value must be a valid IP address.',
                     'type' => 'string',
-                ]
+                ],
             ],
             'json' => [
-                ['json' => BodyParam::description($description)->rules('json|required')],
+                ['json' => 'json|required'],
+                ['json' => ['description' => $description]],
                 [
                     'description' => 'The value must be a valid JSON string.',
                     'type' => 'string',
-                ]
+                ],
             ],
             'date' => [
-                ['date' => BodyParam::description($description)->rules('date|required')],
+                ['date' => 'date|required'],
+                ['date' => ['description' => $description]],
                 [
                     'description' => 'The value must be a valid date.',
                     'type' => 'string',
-                ]
+                ],
             ],
             'date_format' => [
-                ['date_format' => BodyParam::description($description)->rules('date_format:Y-m-d|required')],
+                ['date_format' => 'date_format:Y-m-d|required'],
+                ['date_format' => ['description' => $description]],
                 [
                     'description' => 'The value must be a valid date in the format Y-m-d.',
                     'type' => 'string',
-                ]
+                ],
             ],
             'in' => [
-                ['in' => BodyParam::description($description)->rules('in:3,5,6|required')],
+                ['in' => 'in:3,5,6|required'],
+                ['in' => ['description' => $description]],
                 [
                     'description' => 'The value must be one of `3`, `5`, or `6`.',
                     'type' => 'string',
-                ]
+                ],
             ],
         ];
     }

+ 45 - 15
tests/Fixtures/TestRequest.php

@@ -3,7 +3,6 @@
 namespace Knuckles\Scribe\Tests\Fixtures;
 
 use Illuminate\Foundation\Http\FormRequest;
-use Knuckles\Scribe\Extracting\BodyParam;
 
 /**
  * @queryParam location_id required The id of the location.
@@ -29,20 +28,51 @@ class TestRequest extends FormRequest
     public function rules()
     {
         return [
-            'user_id' => BodyParam::description('The id of the user.')
-                ->example(9)->rules('int|required'),
-            'room_id' => BodyParam::description('The id of the room.')->rules(['string']),
-            'forever' => BodyParam::description('Whether to ban the user forever.')
-                ->example(false)->rules('boolean'),
-            'another_one' => BodyParam::description('Just need something here.')->rules('numeric'),
-            'even_more_param' => BodyParam::description('')->rules('array'),
-            'book.name' => BodyParam::description('')->rules('string'),
-            'book.author_id' => BodyParam::description()->rules('integer'),
-            'book[pages_count]' => BodyParam::description()->rules('integer'),
-            'ids.*' => BodyParam::description()->rules('integer'),
-            'users.*.first_name' => BodyParam::description('The first name of the user.')->example('John')->rules(['string']),
-            'users.*.last_name' => BodyParam::description('The last name of the user.')->example('Doe')->rules('string'),
-            'gets_ignored' => 'string',
+            'user_id' => 'int|required',
+            'room_id' => ['string'],
+            'forever' => 'boolean',
+            'another_one' => 'numeric',
+            'even_more_param' => 'array',
+            'book.name' => 'string',
+            'book.author_id' => 'integer',
+            'book[pages_count]' => 'integer',
+            'ids.*' => 'integer',
+            'users.*.first_name' => ['string'],
+            'users.*.last_name' => 'string',
+        ];
+    }
+
+    public function bodyParameters()
+    {
+        return [
+            'user_id' => [
+                'description' => 'The id of the user.',
+                'example' => 9,
+            ],
+            'room_id' => [
+                'description' => 'The id of the room.',
+            ],
+            'forever' => [
+                'description' => 'Whether to ban the user forever.',
+                'example' => false,
+            ],
+            'another_one' => [
+                'description' => 'Just need something here.',
+            ],
+            'even_more_param' => [
+                'description' => '',
+            ],
+            'book.name' => [
+                'description' => '',
+            ],
+            'users.*.first_name' => [
+                'description' => 'The first name of the user.',
+                'example' => 'John',
+            ],
+            'users.*.last_name' => [
+                'description' => 'The last name of the user.',
+                'example' => 'Doe',
+            ],
         ];
     }
 }