From 3fb9872fa6fb84b0cfc1fdb6900f4d7008b7389c Mon Sep 17 00:00:00 2001 From: shalvah Date: Mon, 21 Feb 2022 13:14:24 +0100 Subject: [PATCH] Add `instantiateFormRequestUsing` hook --- phpstan.neon | 6 +++-- .../Strategies/GetFromFormRequestBase.php | 8 ++++++- .../Strategies/Responses/ResponseCalls.php | 4 ++-- src/Scribe.php | 16 ++++++++++++-- src/Tools/Globals.php | 6 +++-- src/Writing/OpenAPISpecWriter.php | 2 +- src/Writing/Writer.php | 4 ++-- tests/Strategies/GetFromFormRequestTest.php | 22 +++++++++++++++++++ .../UrlParameters/GetFromLaravelAPITest.php | 2 +- 9 files changed, 57 insertions(+), 13 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 7652dff6..89bb3650 100644 --- a/phpstan.neon +++ b/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/' diff --git a/src/Extracting/Strategies/GetFromFormRequestBase.php b/src/Extracting/Strategies/GetFromFormRequestBase.php index 462b74ef..204aff10 100644 --- a/src/Extracting/Strategies/GetFromFormRequestBase.php +++ b/src/Extracting/Strategies/GetFromFormRequestBase.php @@ -8,6 +8,7 @@ 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 @@ public function getParametersFromFormRequest(ReflectionFunctionAbstract $method, } $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 diff --git a/src/Extracting/Strategies/Responses/ResponseCalls.php b/src/Extracting/Strategies/Responses/ResponseCalls.php index 8274f96d..7fd07b62 100644 --- a/src/Extracting/Strategies/Responses/ResponseCalls.php +++ b/src/Extracting/Strategies/Responses/ResponseCalls.php @@ -158,8 +158,8 @@ protected function prepareRequest(Route $route, array $rulesToApply, array $urlP 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; diff --git a/src/Scribe.php b/src/Scribe.php index ce7fa6a2..367f92b6 100644 --- a/src/Scribe.php +++ b/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 @@ public static function beforeResponseCall(callable $callable) */ 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; } } \ No newline at end of file diff --git a/src/Tools/Globals.php b/src/Tools/Globals.php index 3db36570..e796f98a 100644 --- a/src/Tools/Globals.php +++ b/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; } diff --git a/src/Writing/OpenAPISpecWriter.php b/src/Writing/OpenAPISpecWriter.php index e846c05d..95768cff 100644 --- a/src/Writing/OpenAPISpecWriter.php +++ b/src/Writing/OpenAPISpecWriter.php @@ -147,7 +147,7 @@ protected function generatePathsSpec(array $groupedEndpoints) } $parameters[] = $parameterData; } - $pathItem['parameters'] = $parameters; + $pathItem['parameters'] = $parameters; // @phpstan-ignore-line } return [$path => $pathItem]; diff --git a/src/Writing/Writer.php b/src/Writing/Writer.php index da015665..1d7eab95 100644 --- a/src/Writing/Writer.php +++ b/src/Writing/Writer.php @@ -201,9 +201,9 @@ public function writeHtmlDocs(array $groupedEndpoints): void 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]); } } diff --git a/tests/Strategies/GetFromFormRequestTest.php b/tests/Strategies/GetFromFormRequestTest.php index dd15c43a..55abb450 100644 --- a/tests/Strategies/GetFromFormRequestTest.php +++ b/tests/Strategies/GetFromFormRequestTest.php @@ -6,8 +6,12 @@ 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 @@ public function will_ignore_not_relevant_form_request() $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; + } } diff --git a/tests/Strategies/UrlParameters/GetFromLaravelAPITest.php b/tests/Strategies/UrlParameters/GetFromLaravelAPITest.php index 2ddb45ad..88062afd 100644 --- a/tests/Strategies/UrlParameters/GetFromLaravelAPITest.php +++ b/tests/Strategies/UrlParameters/GetFromLaravelAPITest.php @@ -81,7 +81,7 @@ public function __construct(array $parameters = []) { $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;