diff --git a/src/Extracting/Shared/ValidationRulesFinders/RequestValidateFacade.php b/src/Extracting/Shared/ValidationRulesFinders/RequestValidateFacade.php new file mode 100644 index 00000000..07aaeb7e --- /dev/null +++ b/src/Extracting/Shared/ValidationRulesFinders/RequestValidateFacade.php @@ -0,0 +1,39 @@ +validateWithBag('', ...)` + */ +class RequestValidateFacade +{ + public static function find(Node $node) + { + if (!($node instanceof Node\Stmt\Expression)) return; + + $expr = $node->expr; + if ($expr instanceof Node\Expr\Assign) { + $expr = $expr->expr; // If it's an assignment, get the expression on the RHS + } + + if ( + $expr instanceof Node\Expr\StaticCall + && in_array((string) $expr->class, ['Request', \Illuminate\Support\Facades\Request::class]) + ) { + if ($expr->name->name == "validate") { + return $expr->args[0]->value; + } + + if ($expr->name->name == "validateWithBag") { + return $expr->args[1]->value; + } + } + } +} diff --git a/src/Extracting/Strategies/GetFromInlineValidatorBase.php b/src/Extracting/Strategies/GetFromInlineValidatorBase.php index e52640f5..6995a15c 100644 --- a/src/Extracting/Strategies/GetFromInlineValidatorBase.php +++ b/src/Extracting/Strategies/GetFromInlineValidatorBase.php @@ -6,6 +6,7 @@ use Knuckles\Scribe\Extracting\MethodAstParser; use Knuckles\Scribe\Extracting\ParsesValidationRules; use Knuckles\Scribe\Extracting\Shared\ValidationRulesFinders\RequestValidate; +use Knuckles\Scribe\Extracting\Shared\ValidationRulesFinders\RequestValidateFacade; use Knuckles\Scribe\Extracting\Shared\ValidationRulesFinders\ThisValidate; use Knuckles\Scribe\Extracting\Shared\ValidationRulesFinders\ValidatorMake; use PhpParser\Node; @@ -175,6 +176,7 @@ protected function findValidationExpression($statements): ?array { $strategies = [ RequestValidate::class, // $request->validate(...); + RequestValidateFacade::class, // Request::validate(...); ValidatorMake::class, // Validator::make($request, ...) ThisValidate::class, // $this->validate(...); ]; diff --git a/tests/Fixtures/TestController.php b/tests/Fixtures/TestController.php index 43b0992e..8ed6a69b 100644 --- a/tests/Fixtures/TestController.php +++ b/tests/Fixtures/TestController.php @@ -502,6 +502,109 @@ public function withInlineRequestValidateQueryParams(Request $request) // Do stuff } + public function withInlineRequestValidateFacade() + { + // Some stuff + $validated = Request::validate([ + // The id of the user. Example: 9 + 'user_id' => 'int|required', + // The id of the room. + 'room_id' => ['string', 'in:3,5,6'], + // Whether to ban the user forever. Example: false + 'forever' => 'boolean', + // Just need something here. No-example + 'another_one' => 'numeric', + 'even_more_param' => 'array', + 'book.name' => 'string', + 'book.author_id' => 'integer', + 'book.pages_count' => 'integer', + 'ids.*' => 'integer', + // The first name of the user. Example: John + 'users.*.first_name' => ['string'], + // The last name of the user. Example: Doe + 'users.*.last_name' => 'string', + ]); + + // Do stuff + } + + public function withInlineRequestValidateFacadeNoAssignment() + { + Request::validate([ + // The id of the user. Example: 9 + 'user_id' => 'int|required', + // The id of the room. + 'room_id' => ['string', 'in:3,5,6'], + // Whether to ban the user forever. Example: false + 'forever' => 'boolean', + // Just need something here. No-example + 'another_one' => 'numeric', + 'even_more_param' => 'array', + 'book.name' => 'string', + 'book.author_id' => 'integer', + 'book.pages_count' => 'integer', + 'ids.*' => 'integer', + // The first name of the user. Example: John + 'users.*.first_name' => ['string'], + // The last name of the user. Example: Doe + 'users.*.last_name' => 'string', + ]); + + // Do stuff + } + + public function withInlineRequestValidateFacadeWithFullImport() + { + // Some stuff + $validated = \Illuminate\Support\Facades\Request::validate([ + // The id of the user. Example: 9 + 'user_id' => 'int|required', + // The id of the room. + 'room_id' => ['string', 'in:3,5,6'], + // Whether to ban the user forever. Example: false + 'forever' => 'boolean', + // Just need something here. No-example + 'another_one' => 'numeric', + 'even_more_param' => 'array', + 'book.name' => 'string', + 'book.author_id' => 'integer', + 'book.pages_count' => 'integer', + 'ids.*' => 'integer', + // The first name of the user. Example: John + 'users.*.first_name' => ['string'], + // The last name of the user. Example: Doe + 'users.*.last_name' => 'string', + ]); + + // Do stuff + } + + public function withInlineRequestValidateWithBagFacade() + { + // Some stuff + $validated = Request::validateWithBag('stuff', [ + // The id of the user. Example: 9 + 'user_id' => 'int|required', + // The id of the room. + 'room_id' => ['string', 'in:3,5,6'], + // Whether to ban the user forever. Example: false + 'forever' => 'boolean', + // Just need something here. No-example + 'another_one' => 'numeric', + 'even_more_param' => 'array', + 'book.name' => 'string', + 'book.author_id' => 'integer', + 'book.pages_count' => 'integer', + 'ids.*' => 'integer', + // The first name of the user. Example: John + 'users.*.first_name' => ['string'], + // The last name of the user. Example: Doe + 'users.*.last_name' => 'string', + ]); + + // Do stuff + } + public function withInlineValidatorMake(Request $request) { // Some stuff @@ -585,7 +688,7 @@ public function withInjectedModel(TestUser $user) { return null; } - + public function withInjectedModelFullParamName(TestPost $testPost) { return null; diff --git a/tests/Strategies/GetFromInlineValidatorTest.php b/tests/Strategies/GetFromInlineValidatorTest.php index 4235b598..5bc8bd51 100644 --- a/tests/Strategies/GetFromInlineValidatorTest.php +++ b/tests/Strategies/GetFromInlineValidatorTest.php @@ -130,6 +130,58 @@ public function can_fetch_from_request_validatewithbag() $this->assertIsArray($results['ids']['example']); } + /** @test */ + public function can_fetch_from_request_validate_facade_assignment() + { + $endpoint = $this->endpoint(function (ExtractedEndpointData $e) { + $e->method = new \ReflectionMethod(TestController::class, 'withInlineRequestValidateFacade'); + }); + + $results = $this->fetchViaBodyParams($endpoint); + + $this->assertArraySubset(self::$expected, $results); + $this->assertIsArray($results['ids']['example']); + } + + /** @test */ + public function can_fetch_from_request_validate_facade_expression() + { + $endpoint = $this->endpoint(function (ExtractedEndpointData $e) { + $e->method = new \ReflectionMethod(TestController::class, 'withInlineRequestValidateFacadeNoAssignment'); + }); + + $results = $this->fetchViaBodyParams($endpoint); + + $this->assertArraySubset(self::$expected, $results); + $this->assertIsArray($results['ids']['example']); + } + + /** @test */ + public function can_fetch_from_request_validate_facade_with_full_import() + { + $endpoint = $this->endpoint(function (ExtractedEndpointData $e) { + $e->method = new \ReflectionMethod(TestController::class, 'withInlineRequestValidateFacadeWithFullImport'); + }); + + $results = $this->fetchViaBodyParams($endpoint); + + $this->assertArraySubset(self::$expected, $results); + $this->assertIsArray($results['ids']['example']); + } + + /** @test */ + public function can_fetch_from_request_validatewithbag_facade() + { + $endpoint = $this->endpoint(function (ExtractedEndpointData $e) { + $e->method = new \ReflectionMethod(TestController::class, 'withInlineRequestValidateWithBagFacade'); + }); + + $results = $this->fetchViaBodyParams($endpoint); + + $this->assertArraySubset(self::$expected, $results); + $this->assertIsArray($results['ids']['example']); + } + /** @test */ public function can_fetch_from_this_validate() {