Skip to content

Commit 1959c2a

Browse files
committed
Merge 3.4 into 4.0
2 parents a0409fc + 77d3ff3 commit 1959c2a

File tree

17 files changed

+569
-12
lines changed

17 files changed

+569
-12
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,17 @@ Notes:
143143

144144
* [0d5f35683](https://github.com/api-platform/core/commit/0d5f356839eb6aa9f536044abe4affa736553e76) feat(laravel): laravel component (#5882)
145145

146+
## v3.4.4
147+
148+
### Bug fixes
149+
150+
* [550347867](https://github.com/api-platform/core/commit/550347867f30611b673d8df99f65186d013919dd) fix(graphql): register query parameter arguments with filters (#6727)
151+
* [99262dce7](https://github.com/api-platform/core/commit/99262dce739800bd841c95e026848b587ba25801) fix(jsonschema): handle @id when genId is false (#6716)
152+
* [ad5efa535](https://github.com/api-platform/core/commit/ad5efa535a4dcbaad64ecff89514eaa6e07f5b7c) fix: multiple parameter provider #6673 (#6732)
153+
* [d34cd7be8](https://github.com/api-platform/core/commit/d34cd7be8e7a12fd08a8b10270a614c06c10aa89) fix: use stateOptions when retrieving a Parameter filter (#6728)
154+
* [e7fb04fab](https://github.com/api-platform/core/commit/e7fb04fab05bc077e2dbeb0fa0fc2c1d28c96105) fix(symfony): fetch api-platform/symfony version debug bar (#6722)
155+
* [e96623ebf](https://github.com/api-platform/core/commit/e96623ebfd8691ba943bdb56a4d91e160497a311) fix(jsonld): prefix error @type with hydra: (#6721)
156+
146157
## v3.4.3
147158

148159
### Bug fixes

features/main/relation.feature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ Feature: Relations support
493493
"properties": {
494494
"@type": {
495495
"type": "string",
496-
"pattern": "^Error$"
496+
"pattern": "^hydra:Error$"
497497
},
498498
"title": {
499499
"type": "string",

features/serializer/vo_relations.feature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ Feature: Value object as ApiResource
148148
"properties": {
149149
"@type": {
150150
"type": "string",
151-
"pattern": "^Error$"
151+
"pattern": "^hydra:Error$"
152152
},
153153
"title": {
154154
"type": "string",

src/JsonLd/Serializer/ErrorNormalizer.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,17 @@ public function __construct(private readonly NormalizerInterface $inner, private
2727

2828
public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
2929
{
30+
$context += $this->defaultContext;
3031
$normalized = $this->inner->normalize($object, $format, $context);
31-
$hydraPrefix = $this->getHydraPrefix($context + $this->defaultContext);
32+
$hydraPrefix = $this->getHydraPrefix($context);
3233
if (!$hydraPrefix) {
3334
return $normalized;
3435
}
3536

37+
if ('Error' === $normalized['@type']) {
38+
$normalized['@type'] = 'hydra:Error';
39+
}
40+
3641
if (isset($normalized['description'])) {
3742
$normalized['hydra:description'] = $normalized['description'];
3843
}

src/JsonSchema/SchemaFactory.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,14 @@ private function buildPropertySchema(Schema $schema, string $definitionName, str
222222
continue;
223223
}
224224

225+
if (false === $propertyMetadata->getGenId()) {
226+
$subDefinitionName = $this->definitionNameFactory->create($className, $format, $className, null, $serializerContext);
227+
228+
if (isset($subSchema->getDefinitions()[$subDefinitionName])) {
229+
unset($subSchema->getDefinitions()[$subDefinitionName]['properties']['@id']);
230+
}
231+
}
232+
225233
if ($isCollection) {
226234
$propertySchema['items']['$ref'] = $subSchema['$ref'];
227235
unset($propertySchema['items']['type']);

src/Metadata/Resource/Factory/ParameterResourceMetadataCollectionFactory.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ private function getDefaultParameters(Operation $operation, string $resourceClas
113113
if (':property' === $key) {
114114
foreach ($propertyNames as $property) {
115115
$converted = $this->nameConverter?->denormalize($property) ?? $property;
116-
$propertyParameter = $this->setDefaults($converted, $parameter, $resourceClass, $properties);
116+
$propertyParameter = $this->setDefaults($converted, $parameter, $resourceClass, $properties, $operation);
117117
$priority = $propertyParameter->getPriority() ?? $internalPriority--;
118118
$parameters->add($converted, $propertyParameter->withPriority($priority)->withKey($converted));
119119
}
@@ -133,7 +133,7 @@ private function getDefaultParameters(Operation $operation, string $resourceClas
133133
$parameter = $parameter->withExtraProperties($parameter->getExtraProperties() + ['_properties' => $p]);
134134
}
135135

136-
$parameter = $this->setDefaults($key, $parameter, $resourceClass, $properties);
136+
$parameter = $this->setDefaults($key, $parameter, $resourceClass, $properties, $operation);
137137
$priority = $parameter->getPriority() ?? $internalPriority--;
138138
$parameters->add($key, $parameter->withPriority($priority));
139139
}
@@ -171,7 +171,7 @@ private function addFilterMetadata(Parameter $parameter): Parameter
171171
/**
172172
* @param array<string, ApiProperty> $properties
173173
*/
174-
private function setDefaults(string $key, Parameter $parameter, string $resourceClass, array $properties): Parameter
174+
private function setDefaults(string $key, Parameter $parameter, string $resourceClass, array $properties, Operation $operation): Parameter
175175
{
176176
if (null === $parameter->getKey()) {
177177
$parameter = $parameter->withKey($key);
@@ -187,7 +187,7 @@ private function setDefaults(string $key, Parameter $parameter, string $resource
187187
}
188188

189189
// Read filter description to populate the Parameter
190-
$description = $filter instanceof FilterInterface ? $filter->getDescription($resourceClass) : [];
190+
$description = $filter instanceof FilterInterface ? $filter->getDescription($this->getFilterClass($operation)) : [];
191191
if (($schema = $description[$key]['schema'] ?? null) && null === $parameter->getSchema()) {
192192
$parameter = $parameter->withSchema($schema);
193193
}
@@ -220,4 +220,17 @@ private function setDefaults(string $key, Parameter $parameter, string $resource
220220

221221
return $this->addFilterMetadata($parameter);
222222
}
223+
224+
private function getFilterClass(Operation $operation): ?string
225+
{
226+
$stateOptions = $operation->getStateOptions();
227+
if ($stateOptions instanceof DoctrineOrmOptions) {
228+
return $stateOptions->getEntityClass();
229+
}
230+
if ($stateOptions instanceof DoctrineOdmOptions) {
231+
return $stateOptions->getDocumentClass();
232+
}
233+
return $operation->getClass();
234+
}
223235
}
236+

src/State/Provider/ParameterProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
4949
$request->attributes->set('_api_header_parameters', $request->headers->all());
5050
}
5151

52-
$context = ['operation' => $operation] + $context;
5352
$parameters = $operation->getParameters();
5453
foreach ($parameters ?? [] as $parameter) {
5554
$extraProperties = $parameter->getExtraProperties();
5655
unset($extraProperties['_api_values']);
5756
$parameters->add($parameter->getKey(), $parameter = $parameter->withExtraProperties($extraProperties));
5857

58+
$context = ['operation' => $operation] + $context;
5959
$values = $this->getParameterValues($parameter, $request, $context);
6060
$value = $this->extractParameterValues($parameter, $values);
6161

src/Symfony/Bundle/DataCollector/RequestDataCollector.php

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use ApiPlatform\Metadata\ApiResource;
1717
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
1818
use ApiPlatform\State\Util\RequestAttributesExtractor;
19+
use Composer\InstalledVersions;
1920
use PackageVersions\Versions;
2021
use Psr\Container\ContainerInterface;
2122
use Symfony\Component\HttpFoundation\Request;
@@ -67,16 +68,38 @@ private function setFilters(ApiResource $resourceMetadata, int $index, array &$f
6768
}
6869
}
6970

71+
// TODO: 4.1 remove Versions as its deprecated
7072
public function getVersion(): ?string
7173
{
74+
if (class_exists(InstalledVersions::class)) {
75+
return InstalledVersions::getPrettyVersion('api-platform/symfony') ?? InstalledVersions::getPrettyVersion('api-platform/core');
76+
}
77+
7278
if (!class_exists(Versions::class)) {
7379
return null;
7480
}
7581

76-
$version = Versions::getVersion('api-platform/core');
77-
preg_match('/^v(.*?)@/', (string) $version, $output);
82+
try {
83+
$version = strtok(Versions::getVersion('api-platform/symfony'), '@');
84+
} catch (\OutOfBoundsException) {
85+
$version = false;
86+
}
87+
88+
if (false === $version) {
89+
try {
90+
$version = strtok(Versions::getVersion('api-platform/core'), '@');
91+
} catch (\OutOfBoundsException) {
92+
$version = false;
93+
}
94+
}
95+
96+
if (false === $version) {
97+
return null;
98+
}
99+
100+
preg_match('/^v(.*?)$/', $version, $output);
78101

79-
return $output[1] ?? strtok($version, '@');
102+
return $output[1] ?? $version;
80103
}
81104

82105
/**
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource;
15+
16+
use ApiPlatform\Doctrine\Odm\Filter\DateFilter as OdmDateFilter;
17+
use ApiPlatform\Doctrine\Odm\State\Options as OdmOptions;
18+
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
19+
use ApiPlatform\Doctrine\Orm\State\Options;
20+
use ApiPlatform\Metadata\ApiFilter;
21+
use ApiPlatform\Metadata\ApiResource;
22+
use ApiPlatform\Metadata\GetCollection;
23+
use ApiPlatform\Metadata\QueryParameter;
24+
use ApiPlatform\Tests\Fixtures\TestBundle\Document\AgentDocument;
25+
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Agent;
26+
27+
#[ApiFilter(DateFilter::class, properties: ['birthday'], alias: 'app_filter_date')]
28+
#[ApiResource(
29+
shortName: 'Agent',
30+
operations: [
31+
new GetCollection(parameters: [
32+
'birthday' => new QueryParameter(filter: 'app_filter_date'),
33+
]),
34+
],
35+
stateOptions: new Options(entityClass: Agent::class)
36+
)]
37+
#[ApiFilter(OdmDateFilter::class, properties: ['birthday'], alias: 'app_filter_date_odm')]
38+
#[ApiResource(
39+
shortName: 'AgentDocument',
40+
operations: [
41+
new GetCollection(parameters: [
42+
'birthday' => new QueryParameter(filter: 'app_filter_date_odm'),
43+
]),
44+
],
45+
stateOptions: new OdmOptions(documentClass: AgentDocument::class)
46+
)]
47+
class AgentApi
48+
{
49+
private ?int $id = null;
50+
51+
private ?string $name = null;
52+
53+
private ?\DateTimeInterface $birthday = null;
54+
55+
public function getId(): ?int
56+
{
57+
return $this->id;
58+
}
59+
60+
public function setId(?int $id): self
61+
{
62+
$this->id = $id;
63+
64+
return $this;
65+
}
66+
67+
public function getName(): ?string
68+
{
69+
return $this->name;
70+
}
71+
72+
public function setName(?string $name): self
73+
{
74+
$this->name = $name;
75+
76+
return $this;
77+
}
78+
79+
public function getBirthday(): ?\DateTimeInterface
80+
{
81+
return $this->birthday;
82+
}
83+
84+
public function setBirthday(?\DateTimeInterface $birthday): self
85+
{
86+
$this->birthday = $birthday;
87+
88+
return $this;
89+
}
90+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6673;
15+
16+
use ApiPlatform\Metadata\GetCollection;
17+
use ApiPlatform\Metadata\Operation;
18+
use ApiPlatform\Metadata\Parameter;
19+
use ApiPlatform\Metadata\QueryParameter;
20+
21+
#[GetCollection(
22+
uriTemplate: 'issue6673_multiple_parameter_provider',
23+
shortName: 'multiple_parameter_provider',
24+
outputFormats: ['json'],
25+
parameters: [
26+
'a' => new QueryParameter(
27+
provider: [self::class, 'parameterOneProvider'],
28+
),
29+
'b' => new QueryParameter(
30+
provider: [self::class, 'parameterTwoProvider'],
31+
),
32+
],
33+
provider: [self::class, 'provide']
34+
)]
35+
final class MutlipleParameterProvider
36+
{
37+
public function __construct(public readonly string $id)
38+
{
39+
}
40+
41+
public static function provide(Operation $operation): ?array
42+
{
43+
return $operation->getNormalizationContext();
44+
}
45+
46+
public static function parameterOneProvider(Parameter $parameter, array $parameters = [], array $context = []): ?Operation
47+
{
48+
$operation = $context['operation'];
49+
$context = $operation->getNormalizationContext() ?? [];
50+
$context['a'] = $parameter->getValue();
51+
52+
return $operation->withNormalizationContext($context);
53+
}
54+
55+
public static function parameterTwoProvider(Parameter $parameter, array $parameters = [], array $context = []): ?Operation
56+
{
57+
$operation = $context['operation'];
58+
$context = $operation->getNormalizationContext() ?? [];
59+
$context['b'] = $parameter->getValue();
60+
61+
return $operation->withNormalizationContext($context);
62+
}
63+
}

0 commit comments

Comments
 (0)