Skip to content

Commit

Permalink
fix(laravel): parameter fixes and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
soyuka committed Sep 10, 2024
1 parent 941bf4f commit 09faa7e
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/Laravel/ApiPlatformMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public function __construct(
*/
public function handle(Request $request, \Closure $next, ?string $operationName = null): Response
{
$operation = null;
if ($operationName) {
$request->attributes->set('_api_operation', $operation = $this->operationMetadataFactory->create($operationName));
}
Expand Down
1 change: 1 addition & 0 deletions src/Laravel/Eloquent/Metadata/ModelMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ public function getRelations(Model $model): Collection
'name' => $method->getName(),
'type' => $relation::class,
'related' => \get_class($relation->getRelated()),
'foreign_key' => method_exists($relation, 'getForeignKeyName') ? $relation->getForeignKeyName() : null,
];
})
->filter()
Expand Down
8 changes: 6 additions & 2 deletions src/Laravel/State/ParameterValidatorProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,12 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
$value = null;
}

foreach ($constraints as $c) {
$allConstraints[] = $c;
foreach ((array) $constraints as $k => $c) {
if (!\is_string($k)) {
$k = $key;
}

$allConstraints[$k] = $c;
}
}

Expand Down
12 changes: 12 additions & 0 deletions src/Laravel/Tests/EloquentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ public function testSearchFilter(): void
$this->assertSame($response->json()['member'][0], $book);
}

public function testValidateSearchFilter(): void
{
$response = $this->get('/api/books?isbn=a', ['accept' => ['application/ld+json']]);
$this->assertSame($response->json()['detail'], 'The isbn field must be at least 2 characters.');
}

public function testSearchFilterRelation(): void
{
$response = $this->get('/api/books?author=1', ['accept' => ['application/ld+json']]);
$this->assertSame($response->json()['member'][0]['author'], '/api/authors/1');
}

public function testPropertyFilter(): void
{
$response = $this->get('/api/books', ['accept' => ['application/ld+json']]);
Expand Down
3 changes: 2 additions & 1 deletion src/Laravel/workbench/app/Models/Book.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@
new GetCollection(),
]
)]
#[QueryParameter(key: 'isbn', filter: PartialSearchFilter::class)]
#[QueryParameter(key: 'isbn', filter: PartialSearchFilter::class, constraints: 'min:2')]
#[QueryParameter(key: 'name', filter: PartialSearchFilter::class)]
#[QueryParameter(key: 'author', filter: EqualsFilter::class)]
#[QueryParameter(key: 'publicationDate', filter: DateFilter::class)]
#[QueryParameter(
key: 'name2',
Expand Down
13 changes: 8 additions & 5 deletions src/Metadata/Parameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ abstract class Parameter
* @param array<string, mixed> $extraProperties
* @param ParameterProviderInterface|callable|string|null $provider
* @param FilterInterface|string|null $filter
* @param Constraint|Constraint[]|null $constraints
* @param Constraint|array<string, string>|string|Constraint[]|null $constraints
*/
public function __construct(
protected ?string $key = null,
Expand All @@ -41,7 +41,7 @@ public function __construct(
protected ?bool $required = null,
protected ?int $priority = null,
protected ?false $hydra = null,
protected Constraint|array|null $constraints = null,
protected Constraint|array|string|null $constraints = null,
protected string|\Stringable|null $security = null,
protected ?string $securityMessage = null,
protected ?array $extraProperties = [],
Expand Down Expand Up @@ -103,9 +103,9 @@ public function getHydra(): ?bool
}

/**
* @return Constraint|Constraint[]|null
* @return Constraint|string|array<string, string>|Constraint[]|null
*/
public function getConstraints(): Constraint|array|null
public function getConstraints(): Constraint|string|array|null
{
return $this->constraints;
}
Expand Down Expand Up @@ -232,7 +232,10 @@ public function withHydra(false $hydra): static
return $self;
}

public function withConstraints(array|Constraint $constraints): static
/**
* @param string|array<string, string>|Constraint[]|Constraint
*/
public function withConstraints(string|array|Constraint $constraints): static

Check failure on line 238 in src/Metadata/Parameter.php

View workflow job for this annotation

GitHub Actions / PHPStan (PHP 8.3)

PHPDoc tag @param has invalid value (string|array<string, string>|Constraint[]|Constraint): Unexpected token "\n ", expected variable at offset 70
{
$self = clone $this;
$self->constraints = $constraints;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace ApiPlatform\Metadata\Resource\Factory;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\FilterInterface;
use ApiPlatform\Metadata\HasOpenApiParameterFilterInterface;
use ApiPlatform\Metadata\HasSchemaFilterInterface;
Expand Down Expand Up @@ -63,14 +64,17 @@ public function create(string $resourceClass): ResourceMetadataCollection
$resourceMetadataCollection = $this->decorated?->create($resourceClass) ?? new ResourceMetadataCollection($resourceClass);

$propertyNames = [];
$properties = [];
foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $i => $property) {
$propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $property);
if ('author' === $property) {
}
if ($propertyMetadata->isReadable()) {
$propertyNames[] = $property;
$properties[$property] = $propertyMetadata;
}
}

$properties = array_flip($propertyNames);
foreach ($resourceMetadataCollection as $i => $resource) {
$operations = $resource->getOperations();

Expand Down Expand Up @@ -169,7 +173,7 @@ private function addFilterMetadata(Parameter $parameter): Parameter
}

/**
* @param array<string, int> $properties
* @param array<string, ApiProperty> $properties
*/
private function setDefaults(string $key, Parameter $parameter, string $resourceClass, array $properties): Parameter
{
Expand All @@ -196,12 +200,18 @@ private function setDefaults(string $key, Parameter $parameter, string $resource
$parameter = $parameter->withProperty($property);
}

$currentKey = $key;
if (null === $parameter->getProperty() && isset($properties[$key])) {
$parameter = $parameter->withProperty($key);
}

if (null === $parameter->getProperty() && $this->nameConverter && ($nameConvertedKey = $this->nameConverter->normalize($key)) && isset($properties[$nameConvertedKey])) {
$parameter = $parameter->withProperty($key)->withExtraProperties(['_query_property' => $nameConvertedKey] + $parameter->getExtraProperties());
$currentKey = $nameConvertedKey;
}

if (isset($properties[$currentKey]) && ($eloquentRelation = ($properties[$currentKey]->getExtraProperties()['eloquent_relation'] ?? null)) && isset($eloquentRelation['foreign_key'])) {
$parameter = $parameter->withExtraProperties(['_query_property' => $eloquentRelation['foreign_key']] + $parameter->getExtraProperties());
}

if (null === $parameter->getRequired() && ($required = $description[$key]['required'] ?? null)) {
Expand Down
3 changes: 2 additions & 1 deletion src/State/SerializerContextBuilderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ interface SerializerContextBuilderInterface
* deep_object_to_populate?: bool,
* collect_denormalization_errors?: bool,
* exclude_from_cache_key?: string[],
* api_included?: bool
* api_included?: bool,
* attributes?: string[],
* }
*/
public function createFromRequest(Request $request, bool $normalization, ?array $extractedAttributes = null): array;
Expand Down

0 comments on commit 09faa7e

Please sign in to comment.