Kaynağa Gözat

Add `instantiateFormRequestUsing` hook

shalvah 3 yıl önce
ebeveyn
işleme
3fb9872fa6

+ 4 - 2
phpstan.neon

@@ -1,6 +1,6 @@
 parameters:
     level: 5
-    reportUnmatchedIgnoredErrors: false
+    reportUnmatchedIgnoredErrors: true
     inferPrivatePropertyTypeFromConstructor: true
     ignoreErrors:
         - '#Call to an undefined static method Illuminate\\Support\\Facades\\URL::forceRootUrl\(\)#'
@@ -14,6 +14,8 @@ parameters:
         - '#Access to an undefined property Illuminate\\Contracts\\Foundation\\Application::\$view#'
         - '#Unsafe usage of new static#'
         - '#Dead catch#'
+        - '/Call to an undefined static method Illuminate\\Database\\Eloquent\\Model::first\(\)/'
         - '/Call to an undefined method League\\Flysystem\\Filesystem::deleteDir\(\)./'
         - '/Instantiated class League\\Flysystem\\Adapter\\Local not found./'
-        - '/Parameter #1 \$adapter of class League\\Flysystem\\Filesystem constructor expects League\\Flysystem\\AdapterInterface, League\\Flysystem\\Adapter\\Local given./'
+        - '/Parameter #1 \$adapter of class League\\Flysystem\\Filesystem constructor expects League\\Flysystem\\FilesystemAdapter, League\\Flysystem\\Adapter\\Local given./'
+        - '/Call to method getPathPrefix\(\) on an unknown class League\\Flysystem\\Adapter\\Local/'

+ 7 - 1
src/Extracting/Strategies/GetFromFormRequestBase.php

@@ -8,6 +8,7 @@ use Illuminate\Foundation\Http\FormRequest as LaravelFormRequest;
 use Knuckles\Scribe\Extracting\FindsFormRequestForMethod;
 use Knuckles\Scribe\Extracting\ParsesValidationRules;
 use Knuckles\Scribe\Tools\ConsoleOutputUtils as c;
+use Knuckles\Scribe\Tools\Globals;
 use ReflectionClass;
 use ReflectionFunctionAbstract;
 use Illuminate\Contracts\Validation\Factory as ValidationFactory;
@@ -34,8 +35,13 @@ class GetFromFormRequestBase extends Strategy
         }
 
         $className = $formRequestReflectionClass->getName();
+
+        if (Globals::$__instantiateFormRequestUsing) {
+            $formRequest = call_user_func_array(Globals::$__instantiateFormRequestUsing, [$className, $route, $method]);
+        } else {
+            $formRequest = new $className;
+        }
         /** @var LaravelFormRequest|DingoFormRequest $formRequest */
-        $formRequest = new $className;
         // Set the route properly so it works for users who have code that checks for the route.
         $formRequest->setRouteResolver(function () use ($formRequest, $route) {
             // Also need to bind the request to the route in case their code tries to inspect current request

+ 2 - 2
src/Extracting/Strategies/Responses/ResponseCalls.php

@@ -158,8 +158,8 @@ class ResponseCalls extends Strategy
 
     protected function runPreRequestHook(Request $request, ExtractedEndpointData $endpointData): Request
     {
-        if (is_callable(Globals::$beforeResponseCall)) {
-            call_user_func_array(Globals::$beforeResponseCall, [$request, $endpointData]);
+        if (is_callable(Globals::$__beforeResponseCall)) {
+            call_user_func_array(Globals::$__beforeResponseCall, [$request, $endpointData]);
         }
 
         return $request;

+ 14 - 2
src/Scribe.php

@@ -16,7 +16,7 @@ class Scribe
      */
     public static function beforeResponseCall(callable $callable)
     {
-        Globals::$beforeResponseCall = $callable;
+        Globals::$__beforeResponseCall = $callable;
     }
 
     /**
@@ -42,6 +42,18 @@ class Scribe
      */
     public static function afterGenerating(callable $callable)
     {
-        Globals::$afterGenerating = $callable;
+        Globals::$__afterGenerating = $callable;
+    }
+
+    /**
+     * Specify a callback that will be used by all FormRequest strategies
+     * to instantiate Form Requests. his callback takes the name of the form request class,
+     * the current Laravel route being processed, and the controller method.
+     *
+     * @param callable(string,\Illuminate\Routing\Route,\ReflectionFunctionAbstract): mixed $callable
+     */
+    public static function instantiateFormRequestUsing(callable $callable)
+    {
+        Globals::$__instantiateFormRequestUsing = $callable;
     }
 }

+ 4 - 2
src/Tools/Globals.php

@@ -8,7 +8,9 @@ class Globals
 
     public static bool $shouldBeVerbose = false;
 
-    public static $beforeResponseCall;
+    public static $__beforeResponseCall;
 
-    public static $afterGenerating;
+    public static $__afterGenerating;
+
+    public static $__instantiateFormRequestUsing;
 }

+ 1 - 1
src/Writing/OpenAPISpecWriter.php

@@ -147,7 +147,7 @@ class OpenAPISpecWriter
                     }
                     $parameters[] = $parameterData;
                 }
-                $pathItem['parameters'] = $parameters;
+                $pathItem['parameters'] = $parameters; // @phpstan-ignore-line
             }
 
             return [$path => $pathItem];

+ 2 - 2
src/Writing/Writer.php

@@ -201,9 +201,9 @@ class Writer
 
     protected function runAfterGeneratingHook()
     {
-        if (is_callable(Globals::$afterGenerating)) {
+        if (is_callable(Globals::$__afterGenerating)) {
             c::info("Running `afterGenerating()` hook...");
-            call_user_func_array(Globals::$afterGenerating, [$this->generatedFiles]);
+            call_user_func_array(Globals::$__afterGenerating, [$this->generatedFiles]);
         }
     }
 

+ 22 - 0
tests/Strategies/GetFromFormRequestTest.php

@@ -6,8 +6,12 @@ use Knuckles\Scribe\Extracting\Strategies\BodyParameters;
 use Knuckles\Scribe\Extracting\Strategies\QueryParameters;
 use Knuckles\Scribe\Tests\BaseLaravelTest;
 use Knuckles\Scribe\Tests\Fixtures\TestController;
+use Knuckles\Scribe\Tests\Fixtures\TestRequest;
+use Knuckles\Scribe\Tests\Fixtures\TestRequestQueryParams;
 use Knuckles\Scribe\Tools\DocumentationConfig;
 use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
+use Knuckles\Scribe\Tools\Globals;
+use PHPUnit\Framework\Assert;
 
 class GetFromFormRequestTest extends BaseLaravelTest
 {
@@ -142,4 +146,22 @@ class GetFromFormRequestTest extends BaseLaravelTest
         $results = $bodyParamsStrategy->getParametersFromFormRequest($method);
         $this->assertEquals([], $results);
     }
+
+    /** @test */
+    public function allows_customisation_of_form_request_instantiation()
+    {
+        $controllerMethod = new \ReflectionMethod(TestController::class, 'withFormRequestParameter');
+
+        Globals::$__instantiateFormRequestUsing = function ($className, $route, $method) use (&$controllerMethod) {
+            Assert::assertEquals(TestRequest::class, $className);
+            Assert::assertEquals(null, $route);
+            Assert::assertEquals($controllerMethod, $method);
+            return new TestRequestQueryParams;
+        };
+
+        $strategy = new BodyParameters\GetFromFormRequest(new DocumentationConfig([]));
+        $strategy->getParametersFromFormRequest($controllerMethod);
+
+        Globals::$__instantiateFormRequestUsing = null;
+    }
 }

+ 1 - 1
tests/Strategies/UrlParameters/GetFromLaravelAPITest.php

@@ -81,7 +81,7 @@ class GetFromLaravelAPITest extends BaseLaravelTest
             {
                 $this->method = new \ReflectionMethod(TestController::class, 'dummy');
 
-                $route =  app(Router::class)->addRoute(['GET'], "everything/{cat_id}", ['uses' => [TestController::class, 'dummy']]);
+                $route = app(Router::class)->addRoute(['GET'], "everything/{cat_id}", ['uses' => [TestController::class, 'dummy']]);
                 $this->regex = '/catz\d+-\d/';
                 $this->route = $route->where('cat_id', $this->regex);
                 $this->uri = $this->route->uri;