Skip to content

Commit

Permalink
fix(laravel): jsonapi query parameters (page, sort, fields and includ…
Browse files Browse the repository at this point in the history
…e) (#6876)
  • Loading branch information
soyuka authored Dec 20, 2024
1 parent 1977783 commit 809e698
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
52 changes: 52 additions & 0 deletions Filter/SparseFieldset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\JsonApi\Filter;

use ApiPlatform\Metadata\JsonSchemaFilterInterface;
use ApiPlatform\Metadata\OpenApiParameterFilterInterface;
use ApiPlatform\Metadata\Parameter as MetadataParameter;
use ApiPlatform\Metadata\ParameterProviderFilterInterface;
use ApiPlatform\Metadata\PropertiesAwareInterface;
use ApiPlatform\Metadata\QueryParameter;
use ApiPlatform\OpenApi\Model\Parameter;

final class SparseFieldset implements OpenApiParameterFilterInterface, JsonSchemaFilterInterface, ParameterProviderFilterInterface, PropertiesAwareInterface
{
public function getSchema(MetadataParameter $parameter): array
{
return [
'type' => 'array',
'items' => [
'type' => 'string',
],
];
}

public function getOpenApiParameters(MetadataParameter $parameter): Parameter|array|null
{
return new Parameter(
name: ($k = $parameter->getKey()).'[]',
in: $parameter instanceof QueryParameter ? 'query' : 'header',
description: 'Allows you to reduce the response to contain only the properties you need. If your desired property is nested, you can address it using nested arrays. Example: '.\sprintf(
'%1$s[]={propertyName}&%1$s[]={anotherPropertyName}',
$k
)
);
}

public static function getParameterProvider(): string
{
return SparseFieldsetParameterProvider::class;
}
}
62 changes: 62 additions & 0 deletions Filter/SparseFieldsetParameterProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\JsonApi\Filter;

use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Parameter;
use ApiPlatform\State\ParameterProviderInterface;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;

final readonly class SparseFieldsetParameterProvider implements ParameterProviderInterface
{
public function provide(Parameter $parameter, array $parameters = [], array $context = []): ?Operation
{
if (!($operation = $context['operation'] ?? null)) {
return null;
}

$allowedProperties = $parameter->getExtraProperties()['_properties'] ?? [];
$value = $parameter->getValue();
$normalizationContext = $operation->getNormalizationContext();

if (!\is_array($value)) {
return null;
}

$properties = [];
$shortName = strtolower($operation->getShortName());
foreach ($value as $resource => $fields) {
if (strtolower($resource) === $shortName) {
$p = &$properties;
} else {
$properties[$resource] = [];
$p = &$properties[$resource];
}

foreach (explode(',', $fields) as $f) {
if (\array_key_exists($f, $allowedProperties)) {
$p[] = $f;
}
}
}

if (isset($normalizationContext[AbstractNormalizer::ATTRIBUTES])) {
$properties = array_merge_recursive((array) $normalizationContext[AbstractNormalizer::ATTRIBUTES], $properties);
}

$normalizationContext[AbstractNormalizer::ATTRIBUTES] = $properties;

return $operation->withNormalizationContext($normalizationContext);
}
}

0 comments on commit 809e698

Please sign in to comment.