Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow parse expressions with Request::validate facade usage #895

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Knuckles\Scribe\Extracting\Shared\ValidationRulesFinders;

use PhpParser\Node;

/**
* This class looks for
* $anyVariable = Request::validate(...);
* or just
* Request::validate(...);
*
* Also supports `->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;
}
}
}
}
2 changes: 2 additions & 0 deletions src/Extracting/Strategies/GetFromInlineValidatorBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(...);
];
Expand Down
105 changes: 104 additions & 1 deletion tests/Fixtures/TestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -585,7 +688,7 @@ public function withInjectedModel(TestUser $user)
{
return null;
}

public function withInjectedModelFullParamName(TestPost $testPost)
{
return null;
Expand Down
52 changes: 52 additions & 0 deletions tests/Strategies/GetFromInlineValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down
Loading