update after stop build
All checks were successful
All checks were successful
This commit is contained in:
136
vendor/knuckleswtf/scribe/src/Extracting/Shared/ApiResourceResponseTools.php
vendored
Normal file
136
vendor/knuckleswtf/scribe/src/Extracting/Shared/ApiResourceResponseTools.php
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace Knuckles\Scribe\Extracting\Shared;
|
||||
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
use Illuminate\Pagination\CursorPaginator;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Illuminate\Support\Arr;
|
||||
use Knuckles\Camel\Extraction\ExtractedEndpointData;
|
||||
use Knuckles\Scribe\Tools\ErrorHandlingUtils as e;
|
||||
use Knuckles\Scribe\Tools\Utils;
|
||||
use Mpociot\Reflection\DocBlock;
|
||||
use Mpociot\Reflection\DocBlock\Tag;
|
||||
|
||||
class ApiResourceResponseTools
|
||||
{
|
||||
public static function fetch(
|
||||
string $apiResourceClass,
|
||||
bool $isCollection,
|
||||
?callable $modelInstantiator,
|
||||
ExtractedEndpointData $endpointData,
|
||||
array $pagination,
|
||||
array $additionalData,
|
||||
) {
|
||||
$resource = static::getApiResourceOrCollectionInstance(
|
||||
$apiResourceClass,
|
||||
$isCollection,
|
||||
$modelInstantiator,
|
||||
$pagination,
|
||||
$additionalData
|
||||
);
|
||||
$response = static::callApiResourceAndGetResponse($resource, $endpointData);
|
||||
|
||||
return $response->getContent();
|
||||
}
|
||||
|
||||
public static function callApiResourceAndGetResponse(JsonResource $resource, ExtractedEndpointData $endpointData): JsonResponse
|
||||
{
|
||||
$uri = Utils::getUrlWithBoundParameters($endpointData->route->uri(), $endpointData->cleanUrlParameters);
|
||||
$method = $endpointData->route->methods()[0];
|
||||
$request = Request::create($uri, $method);
|
||||
$request->headers->add(['Accept' => 'application/json']);
|
||||
// Set the route properly, so it works for users who have code that checks for the route.
|
||||
$request->setRouteResolver(fn () => $endpointData->route);
|
||||
|
||||
$previousBoundRequest = app('request');
|
||||
app()->bind('request', fn () => $request);
|
||||
|
||||
$response = $resource->toResponse($request);
|
||||
|
||||
app()->bind('request', fn () => $previousBoundRequest);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public static function getApiResourceOrCollectionInstance(
|
||||
string $apiResourceClass,
|
||||
bool $isCollection,
|
||||
?callable $modelInstantiator,
|
||||
array $paginationStrategy = [],
|
||||
array $additionalData = [],
|
||||
): JsonResource {
|
||||
// If the API Resource uses an empty $resource (e.g. an empty array), the $modelInstantiator will be null
|
||||
// See https://github.com/knuckleswtf/scribe/issues/652
|
||||
$modelInstance = is_callable($modelInstantiator) ? $modelInstantiator() : [];
|
||||
|
||||
try {
|
||||
$resource = new $apiResourceClass($modelInstance);
|
||||
} catch (\Exception) {
|
||||
// If it is a ResourceCollection class, it might throw an error
|
||||
// when trying to instantiate with something other than a collection
|
||||
$resource = new $apiResourceClass(collect([$modelInstance]));
|
||||
}
|
||||
|
||||
if ($isCollection) {
|
||||
// Collections can either use the regular JsonResource class (via `::collection()`,
|
||||
// or a ResourceCollection (via `new`)
|
||||
// See https://laravel.com/docs/5.8/eloquent-resources
|
||||
$models = [$modelInstance, $modelInstantiator()];
|
||||
// Pagination can be in two forms:
|
||||
// [15] : means ::paginate(15)
|
||||
// [15, 'simple'] : means ::simplePaginate(15)
|
||||
if (count($paginationStrategy) === 1) {
|
||||
$perPage = $paginationStrategy[0];
|
||||
$paginator = new LengthAwarePaginator(
|
||||
// For some reason, the LengthAware paginator needs only first page items to work correctly
|
||||
collect($models)->slice(0, $perPage),
|
||||
count($models),
|
||||
$perPage
|
||||
);
|
||||
$list = $paginator;
|
||||
} elseif (count($paginationStrategy) === 2 && $paginationStrategy[1] === 'simple') {
|
||||
$perPage = $paginationStrategy[0];
|
||||
$paginator = new Paginator($models, $perPage);
|
||||
$list = $paginator;
|
||||
} elseif (count($paginationStrategy) === 2 && $paginationStrategy[1] === 'cursor') {
|
||||
$perPage = $paginationStrategy[0];
|
||||
$paginator = new CursorPaginator($models, $perPage);
|
||||
$list = $paginator;
|
||||
} else {
|
||||
$list = collect($models);
|
||||
}
|
||||
|
||||
/** @var JsonResource $resource */
|
||||
$resource = $resource instanceof ResourceCollection
|
||||
? new $apiResourceClass($list) : $apiResourceClass::collection($list);
|
||||
}
|
||||
|
||||
return $resource->additional($additionalData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the ApiResource class has an `@mixin` docblock, and fetch the model from there.
|
||||
*/
|
||||
public static function tryToInferApiResourceModel(string $apiResourceClass): ?string
|
||||
{
|
||||
$class = new \ReflectionClass($apiResourceClass);
|
||||
$docBlock = new DocBlock($class->getDocComment() ?: '');
|
||||
|
||||
/** @var null|Tag $mixinTag */
|
||||
$mixinTag = Arr::first(Utils::filterDocBlockTags($docBlock->getTags(), 'mixin'));
|
||||
if (empty($mixinTag) || empty($modelClass = mb_trim($mixinTag->getContent()))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (class_exists($modelClass)) {
|
||||
return $modelClass;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
38
vendor/knuckleswtf/scribe/src/Extracting/Shared/ResponseFieldTools.php
vendored
Normal file
38
vendor/knuckleswtf/scribe/src/Extracting/Shared/ResponseFieldTools.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Knuckles\Scribe\Extracting\Shared;
|
||||
|
||||
use Knuckles\Camel\Extraction\ExtractedEndpointData;
|
||||
use Knuckles\Camel\Extraction\Response;
|
||||
use Knuckles\Scribe\Extracting\ParamHelpers;
|
||||
|
||||
class ResponseFieldTools
|
||||
{
|
||||
use ParamHelpers;
|
||||
|
||||
public static function inferTypeOfResponseField(array $data, ExtractedEndpointData $endpointData): string
|
||||
{
|
||||
if (! empty($data['type'])) {
|
||||
return self::normalizeTypeName($data['type']);
|
||||
}
|
||||
|
||||
// Try to get a type from first 2xx response
|
||||
$validResponse = collect($endpointData->responses)->first(
|
||||
fn (Response $r) => $r->status >= 200 && $r->status < 300
|
||||
);
|
||||
if ($validResponse && ($validResponseContent = json_decode($validResponse->content, true))) {
|
||||
$nonexistent = new \stdClass;
|
||||
$value = $validResponseContent[$data['name']]
|
||||
?? $validResponseContent['data'][$data['name']] // Maybe it's a Laravel ApiResource
|
||||
?? $validResponseContent[0][$data['name']] // Maybe it's a list
|
||||
?? $validResponseContent['data'][0][$data['name']] // Maybe an Api Resource Collection?
|
||||
?? $nonexistent;
|
||||
|
||||
if ($value !== $nonexistent) {
|
||||
return self::normalizeTypeName(gettype($value), $value);
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
36
vendor/knuckleswtf/scribe/src/Extracting/Shared/ResponseFileTools.php
vendored
Normal file
36
vendor/knuckleswtf/scribe/src/Extracting/Shared/ResponseFileTools.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Knuckles\Scribe\Extracting\Shared;
|
||||
|
||||
class ResponseFileTools
|
||||
{
|
||||
public static function getResponseContents($filePath, array|string|null $merge): string
|
||||
{
|
||||
$content = self::getFileContents($filePath);
|
||||
if (empty($merge)) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
if (is_string($merge)) {
|
||||
$json = str_replace("'", '"', $merge);
|
||||
|
||||
return json_encode(array_merge(json_decode($content, true), json_decode($json, true)));
|
||||
}
|
||||
|
||||
return json_encode(array_merge(json_decode($content, true), $merge));
|
||||
}
|
||||
|
||||
protected static function getFileContents($filePath): string
|
||||
{
|
||||
if (! file_exists($filePath)) {
|
||||
// Try Laravel storage folder
|
||||
if (! file_exists(storage_path($filePath))) {
|
||||
throw new \InvalidArgumentException("@responseFile {$filePath} does not exist");
|
||||
}
|
||||
|
||||
$filePath = storage_path($filePath);
|
||||
}
|
||||
|
||||
return file_get_contents($filePath, true);
|
||||
}
|
||||
}
|
||||
40
vendor/knuckleswtf/scribe/src/Extracting/Shared/TransformerResponseTools.php
vendored
Normal file
40
vendor/knuckleswtf/scribe/src/Extracting/Shared/TransformerResponseTools.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Knuckles\Scribe\Extracting\Shared;
|
||||
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
class TransformerResponseTools
|
||||
{
|
||||
public static function fetch(string $transformerClass, bool $isCollection, $modelInstantiator, array $pagination = [], ?string $resourceKey = null, ?string $serializer = null)
|
||||
{
|
||||
$fractal = new Manager;
|
||||
|
||||
if (! is_null($serializer)) {
|
||||
$fractal->setSerializer(app($serializer));
|
||||
}
|
||||
|
||||
$modelInstance = $modelInstantiator();
|
||||
if ($isCollection) {
|
||||
$models = [$modelInstance, $modelInstantiator()];
|
||||
$resource = new Collection($models, new $transformerClass);
|
||||
|
||||
['adapter' => $paginatorAdapter, 'perPage' => $perPage] = $pagination;
|
||||
if ($paginatorAdapter) {
|
||||
$total = count($models);
|
||||
// Need to pass only the first page to both adapter and paginator, otherwise they will display ebverything
|
||||
$firstPage = collect($models)->slice(0, $perPage);
|
||||
$resource = new Collection($firstPage, new $transformerClass, $resourceKey);
|
||||
$paginator = new LengthAwarePaginator($firstPage, $total, $perPage);
|
||||
$resource->setPaginator(new $paginatorAdapter($paginator));
|
||||
}
|
||||
} else {
|
||||
$resource = (new Item($modelInstance, new $transformerClass, $resourceKey));
|
||||
}
|
||||
|
||||
return response($fractal->createData($resource)->toJson())->getContent();
|
||||
}
|
||||
}
|
||||
226
vendor/knuckleswtf/scribe/src/Extracting/Shared/UrlParamsNormalizer.php
vendored
Normal file
226
vendor/knuckleswtf/scribe/src/Extracting/Shared/UrlParamsNormalizer.php
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
|
||||
namespace Knuckles\Scribe\Extracting\Shared;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Routing\Route;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
// See https://laravel.com/docs/9.x/routing#route-model-binding
|
||||
class UrlParamsNormalizer
|
||||
{
|
||||
/**
|
||||
* Normalize a URL from Laravel-style to something that's clearer for a non-Laravel user.
|
||||
* For instance, `/posts/{post}` would be clearer as `/posts/{id}`,
|
||||
* and `/users/{user}/posts/{post}` would be clearer as `/users/{user_id}/posts/{id}`.
|
||||
*/
|
||||
public static function normalizeParameterNamesInRouteUri(Route $route, \ReflectionFunctionAbstract $method): string
|
||||
{
|
||||
$params = [];
|
||||
$uri = $route->uri;
|
||||
preg_match_all('#\{(\w+?)}#', $uri, $params);
|
||||
|
||||
$resourceRouteNames = ['.index', '.show', '.update', '.destroy', '.store'];
|
||||
|
||||
$typeHintedEloquentModels = self::getTypeHintedEloquentModels($method);
|
||||
$routeName = $route->action['as'] ?? '';
|
||||
if (Str::endsWith($routeName, $resourceRouteNames)) {
|
||||
// Note that resource routes can be nested eg users.posts.show
|
||||
$pluralResources = explode('.', $routeName);
|
||||
array_pop($pluralResources); // Remove the name of the action (eg `show`)
|
||||
|
||||
$alreadyFoundResourceParam = false;
|
||||
foreach (array_reverse($pluralResources) as $pluralResource) {
|
||||
$singularResource = Str::singular($pluralResource);
|
||||
|
||||
// Laravel turns hyphens in parameters to underscores
|
||||
// (`cool-things/{cool-thing}` to `cool-things/{cool_thing_id}`)
|
||||
// so we do the same
|
||||
$singularResourceParam = str_replace('-', '_', $singularResource);
|
||||
|
||||
$urlPatternsToSearchFor = [
|
||||
"{$pluralResource}/{{$singularResourceParam}}",
|
||||
"{$pluralResource}/{{$singularResource}}",
|
||||
"{$pluralResource}/{{$singularResourceParam}?}",
|
||||
"{$pluralResource}/{{$singularResource}?}",
|
||||
];
|
||||
|
||||
$binding = self::getRouteKeyForUrlParam(
|
||||
$route,
|
||||
$singularResource,
|
||||
$typeHintedEloquentModels,
|
||||
'id'
|
||||
);
|
||||
|
||||
if (! $alreadyFoundResourceParam) {
|
||||
// This is the first resource param (from the end).
|
||||
// We set it to `params/{id}` (or whatever field it's bound to)
|
||||
$replaceWith = [
|
||||
"{$pluralResource}/{{$binding}}",
|
||||
"{$pluralResource}/{{$binding}}",
|
||||
"{$pluralResource}/{{$binding}?}",
|
||||
"{$pluralResource}/{{$binding}?}",
|
||||
];
|
||||
$alreadyFoundResourceParam = true;
|
||||
} else {
|
||||
// Other resource parameters will be `params/{<param>_id}`
|
||||
$replaceWith = [
|
||||
"{$pluralResource}/{{$singularResourceParam}_{$binding}}",
|
||||
"{$pluralResource}/{{$singularResource}_{$binding}}",
|
||||
"{$pluralResource}/{{$singularResourceParam}_{$binding}?}",
|
||||
"{$pluralResource}/{{$singularResource}_{$binding}?}",
|
||||
];
|
||||
}
|
||||
$uri = str_replace($urlPatternsToSearchFor, $replaceWith, $uri);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($params[1] as $param) {
|
||||
// For non-resource parameters, if there's a field binding/type-hinted variable, replace that too:
|
||||
if ($binding = self::getRouteKeyForUrlParam($route, $param, $typeHintedEloquentModels)) {
|
||||
$urlPatternsToSearchFor = ["{{$param}}", "{{$param}?}"];
|
||||
$replaceWith = ["{{$param}_{$binding}}", "{{$param}_{$binding}?}"];
|
||||
$uri = str_replace($urlPatternsToSearchFor, $replaceWith, $uri);
|
||||
}
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type-hinted method arguments in the action that are Eloquent models,
|
||||
* The arguments will be returned as an array of the form: [<variable_name> => $instance].
|
||||
*/
|
||||
public static function getTypeHintedEloquentModels(\ReflectionFunctionAbstract $method): array
|
||||
{
|
||||
$arguments = [];
|
||||
foreach ($method->getParameters() as $argument) {
|
||||
if (($instance = self::instantiateMethodArgument($argument)) && $instance instanceof Model) {
|
||||
$arguments[$argument->getName()] = $instance;
|
||||
}
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type-hinted method arguments in the action that are enums,
|
||||
* The arguments will be returned as an array of the form: [<variable_name> => $instance].
|
||||
*/
|
||||
public static function getTypeHintedEnums(\ReflectionFunctionAbstract $method): array
|
||||
{
|
||||
$arguments = [];
|
||||
foreach ($method->getParameters() as $argument) {
|
||||
$argumentType = $argument->getType();
|
||||
if (! $argumentType instanceof \ReflectionNamedType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$reflectionEnum = new \ReflectionEnum($argumentType->getName());
|
||||
$arguments[$argument->getName()] = $reflectionEnum;
|
||||
} catch (\ReflectionException) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a URL that uses Eloquent model binding (for instance `/posts/{post}` -> `public function show(Post
|
||||
* $post)`), we need to figure out the field that Eloquent uses to retrieve the Post object. By default, this would
|
||||
* be `id`, but can be configured in a couple of ways:
|
||||
*
|
||||
* - Inline: `/posts/{post:slug}`
|
||||
* - `class Post { public function getRouteKeyName() { return 'slug'; } }`
|
||||
*
|
||||
* There are other ways, but they're dynamic and beyond our scope.
|
||||
*
|
||||
* @param string $paramName The name of the URL parameter
|
||||
* @param array<string, Model> $typeHintedEloquentModels
|
||||
* @param null|string $default Default field to use
|
||||
*/
|
||||
protected static function getRouteKeyForUrlParam(
|
||||
Route $route,
|
||||
string $paramName,
|
||||
array $typeHintedEloquentModels = [],
|
||||
?string $default = null,
|
||||
): ?string {
|
||||
if ($binding = self::getInlineRouteKey($route, $paramName)) {
|
||||
return $binding;
|
||||
}
|
||||
|
||||
return self::getRouteKeyFromModel($paramName, $typeHintedEloquentModels) ?: $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the `slug` in /posts/{post:slug}.
|
||||
*/
|
||||
protected static function getInlineRouteKey(Route $route, string $paramName): ?string
|
||||
{
|
||||
return $route->bindingFieldFor($paramName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there's a type-hinted argument on the controller method matching the URL param name:
|
||||
* eg /posts/{post} -> public function show(Post $post)
|
||||
* If there is, check if it's an Eloquent model.
|
||||
* If it is, return it's `getRouteKeyName()`.
|
||||
*
|
||||
* @param Model[] $typeHintedEloquentModels
|
||||
*/
|
||||
protected static function getRouteKeyFromModel(string $paramName, array $typeHintedEloquentModels): ?string
|
||||
{
|
||||
// Ensure param name is in camelCase so it matches the argument name (e.g. The '$userAddress' in `function show(BigThing $userAddress`)
|
||||
$paramName = Str::camel($paramName);
|
||||
|
||||
if (array_key_exists($paramName, $typeHintedEloquentModels)) {
|
||||
$argumentInstance = $typeHintedEloquentModels[$paramName];
|
||||
|
||||
return $argumentInstance->getRouteKeyName();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate an argument on a controller method via its typehint. For instance, $post in:
|
||||
*
|
||||
* public function show(Post $post)
|
||||
*
|
||||
* This method takes in a method argument and returns an instance, or null if it couldn't be instantiated safely.
|
||||
* Cases where instantiation may fail:
|
||||
* - the argument has no type (eg `public function show($postId)`)
|
||||
* - the argument has a primitive type (eg `public function show(string $postId)`)
|
||||
* - the argument is an injected dependency that itself needs other dependencies
|
||||
* (eg `public function show(PostsManager $manager)`)
|
||||
*/
|
||||
protected static function instantiateMethodArgument(\ReflectionParameter $argument): ?object
|
||||
{
|
||||
$argumentType = $argument->getType();
|
||||
// No type-hint, or primitive type
|
||||
if (! $argumentType instanceof \ReflectionNamedType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$argumentClassName = $argumentType->getName();
|
||||
if (class_exists($argumentClassName)) {
|
||||
try {
|
||||
return new $argumentClassName;
|
||||
} catch (\Throwable $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (interface_exists($argumentClassName)) {
|
||||
try {
|
||||
return app($argumentClassName);
|
||||
} catch (\Throwable $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
43
vendor/knuckleswtf/scribe/src/Extracting/Shared/ValidationRulesFinders/RequestValidate.php
vendored
Normal file
43
vendor/knuckleswtf/scribe/src/Extracting/Shared/ValidationRulesFinders/RequestValidate.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Knuckles\Scribe\Extracting\Shared\ValidationRulesFinders;
|
||||
|
||||
use PhpParser\Node;
|
||||
|
||||
/**
|
||||
* This class looks for
|
||||
* $anyVariable = $request->validate(...);
|
||||
* or just
|
||||
* $request->validate(...);.
|
||||
*
|
||||
* Also supports `$req` instead of `$request`
|
||||
* Also supports `->validateWithBag('', ...)`
|
||||
*/
|
||||
class RequestValidate
|
||||
{
|
||||
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\MethodCall
|
||||
&& $expr->var instanceof Node\Expr\Variable
|
||||
&& in_array($expr->var->name, ['request', 'req'])
|
||||
) {
|
||||
if ($expr->name->name === 'validate') {
|
||||
return $expr->args[0]->value;
|
||||
}
|
||||
|
||||
if ($expr->name->name === 'validateWithBag') {
|
||||
return $expr->args[1]->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
43
vendor/knuckleswtf/scribe/src/Extracting/Shared/ValidationRulesFinders/RequestValidateFacade.php
vendored
Normal file
43
vendor/knuckleswtf/scribe/src/Extracting/Shared/ValidationRulesFinders/RequestValidateFacade.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Knuckles\Scribe\Extracting\Shared\ValidationRulesFinders;
|
||||
|
||||
use Illuminate\Support\Facades\Request;
|
||||
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
|
||||
&& $expr->class instanceof Node\Name
|
||||
&& in_array($expr->class->name, ['Request', Request::class])
|
||||
) {
|
||||
if ($expr->name->name === 'validate') {
|
||||
return $expr->args[0]->value;
|
||||
}
|
||||
|
||||
if ($expr->name->name === 'validateWithBag') {
|
||||
return $expr->args[1]->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
vendor/knuckleswtf/scribe/src/Extracting/Shared/ValidationRulesFinders/ThisValidate.php
vendored
Normal file
38
vendor/knuckleswtf/scribe/src/Extracting/Shared/ValidationRulesFinders/ThisValidate.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Knuckles\Scribe\Extracting\Shared\ValidationRulesFinders;
|
||||
|
||||
use PhpParser\Node;
|
||||
|
||||
/**
|
||||
* This class looks for
|
||||
* $anyVariable = $this->validate($request, ...);
|
||||
* or just
|
||||
* $this->validate($request, ...);.
|
||||
*
|
||||
* Also supports `$req` instead of `$request`
|
||||
*/
|
||||
class ThisValidate
|
||||
{
|
||||
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\MethodCall
|
||||
&& $expr->var instanceof Node\Expr\Variable
|
||||
&& $expr->var->name === 'this'
|
||||
) {
|
||||
if ($expr->name->name === 'validate') {
|
||||
return $expr->args[1]->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
vendor/knuckleswtf/scribe/src/Extracting/Shared/ValidationRulesFinders/ValidatorMake.php
vendored
Normal file
35
vendor/knuckleswtf/scribe/src/Extracting/Shared/ValidationRulesFinders/ValidatorMake.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Knuckles\Scribe\Extracting\Shared\ValidationRulesFinders;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\NodeFinder;
|
||||
|
||||
/**
|
||||
* This class looks for
|
||||
* $validator = Validator::make($request, ...)
|
||||
* Validator::make($request, ...)->validate().
|
||||
*
|
||||
* The variable names (`$validator` and `$request`) don't matter.
|
||||
*/
|
||||
class ValidatorMake
|
||||
{
|
||||
public static function find(Node $node)
|
||||
{
|
||||
// Make sure it's an assignment
|
||||
if (! $node instanceof Node\Stmt\Expression) {
|
||||
return;
|
||||
}
|
||||
|
||||
$validatorNode = (new NodeFinder)->findFirst($node, function ($node): bool {
|
||||
return $node instanceof Node\Expr\StaticCall
|
||||
&& ! empty($node->class->name)
|
||||
&& str_ends_with($node->class->name, 'Validator')
|
||||
&& $node->name->name === 'make';
|
||||
});
|
||||
|
||||
if ($validatorNode instanceof Node\Expr\StaticCall) {
|
||||
return $validatorNode->args[1]->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user