Skip to content

Commit e5cbede

Browse files
committed
Merge 3.4
2 parents 898ce52 + e03e9a1 commit e5cbede

File tree

10 files changed

+106
-14
lines changed

10 files changed

+106
-14
lines changed

CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ You should now install `api-platform/symfony` instead of `api-platform/core`.
163163
* [41deeb4e4](https://github.com/api-platform/core/commit/41deeb4e49c35d27cd902ea41ddaa3c8c492d8e4) fix(symfony): fix debug:api-resource command for class with multiple resources with same uriTemplate (#6505)
164164
* [52fd9818b](https://github.com/api-platform/core/commit/52fd9818b1d02dd89cac578e0762530079b5b42d) fix(elasticsearch): change normalize return type to compatible with other normalizers (#6493)
165165
* [b3d7c0768](https://github.com/api-platform/core/commit/b3d7c07682366cc387ceee904cadbdd85bad0c09) fix(openapi): allow null return type parameter
166-
>>>>>>> upstream/3.3
167166

168167
## v3.3.11
169168

src/Doctrine/Common/ParameterValueExtractorTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ trait ParameterValueExtractorTrait
2222
*/
2323
private function extractParameterValue(Parameter $parameter, mixed $value): array
2424
{
25-
$key = $parameter->getKey();
25+
$key = $parameter->getProperty() ?? $parameter->getKey();
2626
if (!str_contains($key, ':property')) {
2727
return [$key => $value];
2828
}

src/GraphQl/Serializer/SerializerContextBuilder.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface;
2121
use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;
2222
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
23+
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
2324

2425
/**
2526
* Builds the context used by the Symfony Serializer.
@@ -53,6 +54,15 @@ public function create(?string $resourceClass, Operation $operation, array $reso
5354
$context['attributes'] = $this->fieldsToAttributes($resourceClass, $operation, $resolverContext, $context);
5455
}
5556

57+
// to keep the cache computation smaller, we have "operation_name" and "iri" anyways
58+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'root_operation';
59+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'operation';
60+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'object';
61+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'data';
62+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'property_metadata';
63+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'circular_reference_limit_counters';
64+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'debug_trace_id';
65+
5666
return $context;
5767
}
5868

src/GraphQl/Tests/Serializer/SerializerContextBuilderTest.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,15 @@ public static function createNormalizationContextProvider(): iterable
139139
'id' => 3,
140140
'field' => 'foo',
141141
],
142+
'exclude_from_cache_key' => [
143+
'root_operation',
144+
'operation',
145+
'object',
146+
'data',
147+
'property_metadata',
148+
'circular_reference_limit_counters',
149+
'debug_trace_id',
150+
],
142151
],
143152
];
144153
yield 'nominal with advanced name converter' => [
@@ -159,6 +168,15 @@ public static function createNormalizationContextProvider(): iterable
159168
'id' => 3,
160169
'denormalizedField' => 'foo',
161170
],
171+
'exclude_from_cache_key' => [
172+
'root_operation',
173+
'operation',
174+
'object',
175+
'data',
176+
'property_metadata',
177+
'circular_reference_limit_counters',
178+
'debug_trace_id',
179+
],
162180
],
163181
$advancedNameConverterFactory,
164182
];
@@ -179,6 +197,15 @@ public static function createNormalizationContextProvider(): iterable
179197
'attributes' => [
180198
'nodeField' => 'baz',
181199
],
200+
'exclude_from_cache_key' => [
201+
'root_operation',
202+
'operation',
203+
'object',
204+
'data',
205+
'property_metadata',
206+
'circular_reference_limit_counters',
207+
'debug_trace_id',
208+
],
182209
],
183210
];
184211
yield 'no resource class' => [
@@ -195,6 +222,15 @@ public static function createNormalizationContextProvider(): iterable
195222
'attributes' => [
196223
'related' => ['id' => 9],
197224
],
225+
'exclude_from_cache_key' => [
226+
'root_operation',
227+
'operation',
228+
'object',
229+
'data',
230+
'property_metadata',
231+
'circular_reference_limit_counters',
232+
'debug_trace_id',
233+
],
198234
],
199235
];
200236
yield 'mutation' => [
@@ -215,6 +251,15 @@ public static function createNormalizationContextProvider(): iterable
215251
'id' => 7,
216252
'related' => ['field' => 'bar'],
217253
],
254+
'exclude_from_cache_key' => [
255+
'root_operation',
256+
'operation',
257+
'object',
258+
'data',
259+
'property_metadata',
260+
'circular_reference_limit_counters',
261+
'debug_trace_id',
262+
],
218263
],
219264
];
220265
yield 'subscription (using fields in context)' => [
@@ -236,6 +281,15 @@ public static function createNormalizationContextProvider(): iterable
236281
'id' => 7,
237282
'related' => ['field' => 'bar'],
238283
],
284+
'exclude_from_cache_key' => [
285+
'root_operation',
286+
'operation',
287+
'object',
288+
'data',
289+
'property_metadata',
290+
'circular_reference_limit_counters',
291+
'debug_trace_id',
292+
],
239293
],
240294
];
241295
}
@@ -264,6 +318,15 @@ public static function createDenormalizationContextProvider(): array
264318
'graphql_operation_name' => $operationName,
265319
'input' => ['class' => 'inputClass'],
266320
'output' => ['class' => 'outputClass'],
321+
'exclude_from_cache_key' => [
322+
'root_operation',
323+
'operation',
324+
'object',
325+
'data',
326+
'property_metadata',
327+
'circular_reference_limit_counters',
328+
'debug_trace_id',
329+
],
267330
],
268331
],
269332
'no resource class' => [
@@ -273,6 +336,15 @@ public static function createDenormalizationContextProvider(): array
273336
'resource_class' => $resourceClass,
274337
'operation_name' => $operationName,
275338
'graphql_operation_name' => $operationName,
339+
'exclude_from_cache_key' => [
340+
'root_operation',
341+
'operation',
342+
'object',
343+
'data',
344+
'property_metadata',
345+
'circular_reference_limit_counters',
346+
'debug_trace_id',
347+
],
276348
],
277349
],
278350
];

src/Metadata/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"phpspec/prophecy-phpunit": "^2.0",
4343
"phpstan/phpdoc-parser": "^1.16",
4444
"phpunit/phpunit": "^11.2",
45-
"symfony/config": "^6.4 || 7.1",
45+
"symfony/config": "^6.4 || ^7.1",
4646
"symfony/routing": "^6.4 || ^7.1",
4747
"symfony/var-dumper": "^6.4 || ^7.0",
4848
"symfony/web-link": "^6.4 || ^7.0",

src/Serializer/SerializerContextBuilder.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ public function createFromRequest(Request $request, bool $normalization, ?array
113113
// to keep the cache computation smaller, we have "operation_name" and "iri" anyways
114114
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'root_operation';
115115
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'operation';
116+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'object';
117+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'data';
118+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'property_metadata';
119+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'circular_reference_limit_counters';
120+
$context[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY][] = 'debug_trace_id';
116121

117122
// JSON API see JsonApiProvider
118123
if ($included = $request->attributes->get('_api_included')) {

src/Serializer/Tests/SerializerContextBuilderTest.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,42 +67,42 @@ public function testCreateFromRequest(): void
6767
{
6868
$request = Request::create('/foos/1');
6969
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
70-
$expected = ['foo' => 'bar', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation']];
70+
$expected = ['foo' => 'bar', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
7171
$this->assertEquals($expected, $this->builder->createFromRequest($request, true));
7272

7373
$request = Request::create('/foos');
7474
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get_collection', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
75-
$expected = ['foo' => 'bar', 'operation_name' => 'get_collection', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('get_collection'), 'exclude_from_cache_key' => ['root_operation', 'operation']];
75+
$expected = ['foo' => 'bar', 'operation_name' => 'get_collection', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('get_collection'), 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
7676
$this->assertEquals($expected, $this->builder->createFromRequest($request, true));
7777

7878
$request = Request::create('/foos/1');
7979
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
80-
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation']];
80+
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
8181
$this->assertEquals($expected, $this->builder->createFromRequest($request, false));
8282

8383
$request = Request::create('/foos', 'POST');
8484
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'post', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
85-
$expected = ['bar' => 'baz', 'operation_name' => 'post', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('post'), 'exclude_from_cache_key' => ['root_operation', 'operation']];
85+
$expected = ['bar' => 'baz', 'operation_name' => 'post', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation->withName('post'), 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
8686
$this->assertEquals($expected, $this->builder->createFromRequest($request, false));
8787

8888
$request = Request::create('/foos', 'PUT');
8989
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'put', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
90-
$expected = ['bar' => 'baz', 'operation_name' => 'put', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => true, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => (new Put(name: 'put'))->withOperation($this->operation), 'exclude_from_cache_key' => ['root_operation', 'operation']];
90+
$expected = ['bar' => 'baz', 'operation_name' => 'put', 'resource_class' => 'Foo', 'request_uri' => '/foos', 'api_allow_update' => true, 'uri' => 'http://localhost/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => (new Put(name: 'put'))->withOperation($this->operation), 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
9191
$this->assertEquals($expected, $this->builder->createFromRequest($request, false));
9292

9393
$request = Request::create('/bars/1/foos');
9494
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml']);
95-
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation']];
95+
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
9696
$this->assertEquals($expected, $this->builder->createFromRequest($request, false));
9797

9898
$request = Request::create('/foowithpatch/1', 'PATCH');
9999
$request->attributes->replace(['_api_resource_class' => 'FooWithPatch', '_api_operation_name' => 'patch', '_api_format' => 'json', '_api_mime_type' => 'application/json']);
100-
$expected = ['operation_name' => 'patch', 'resource_class' => 'FooWithPatch', 'request_uri' => '/foowithpatch/1', 'api_allow_update' => true, 'uri' => 'http://localhost/foowithpatch/1', 'output' => null, 'input' => null, 'deep_object_to_populate' => true, 'skip_null_values' => true, 'iri_only' => false, 'operation' => $this->patchOperation, 'exclude_from_cache_key' => ['root_operation', 'operation']];
100+
$expected = ['operation_name' => 'patch', 'resource_class' => 'FooWithPatch', 'request_uri' => '/foowithpatch/1', 'api_allow_update' => true, 'uri' => 'http://localhost/foowithpatch/1', 'output' => null, 'input' => null, 'deep_object_to_populate' => true, 'skip_null_values' => true, 'iri_only' => false, 'operation' => $this->patchOperation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
101101
$this->assertEquals($expected, $this->builder->createFromRequest($request, false));
102102

103103
$request = Request::create('/bars/1/foos');
104104
$request->attributes->replace(['_api_resource_class' => 'Foo', '_api_operation_name' => 'get', '_api_format' => 'xml', '_api_mime_type' => 'text/xml', 'id' => '1']);
105-
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'operation' => $this->operation, 'skip_null_values' => true, 'exclude_from_cache_key' => ['root_operation', 'operation']];
105+
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/bars/1/foos', 'api_allow_update' => false, 'uri' => 'http://localhost/bars/1/foos', 'output' => null, 'input' => null, 'iri_only' => false, 'operation' => $this->operation, 'skip_null_values' => true, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
106106
$this->assertEquals($expected, $this->builder->createFromRequest($request, false));
107107
}
108108

@@ -115,7 +115,7 @@ public function testThrowExceptionOnInvalidRequest(): void
115115

116116
public function testReuseExistingAttributes(): void
117117
{
118-
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation']];
118+
$expected = ['bar' => 'baz', 'operation_name' => 'get', 'resource_class' => 'Foo', 'request_uri' => '/foos/1', 'api_allow_update' => false, 'uri' => 'http://localhost/foos/1', 'output' => null, 'input' => null, 'iri_only' => false, 'skip_null_values' => true, 'operation' => $this->operation, 'exclude_from_cache_key' => ['root_operation', 'operation', 'object', 'data', 'property_metadata', 'circular_reference_limit_counters', 'debug_trace_id']];
119119
$this->assertEquals($expected, $this->builder->createFromRequest(Request::create('/foos/1'), false, ['resource_class' => 'Foo', 'operation_name' => 'get']));
120120
}
121121

src/State/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"require-dev": {
3636
"phpunit/phpunit": "^11.2",
3737
"symfony/web-link": "^6.4 || ^7.0",
38-
"symfony/http-foundation": "^6.4 || 7.0",
38+
"symfony/http-foundation": "^6.4 || ^7.0",
3939
"willdurand/negotiation": "^3.1",
4040
"api-platform/validator": "^3.4 || ^4.0",
4141
"api-platform/serializer": "^3.4 || ^4.0"

tests/Fixtures/TestBundle/Entity/SearchFilterParameter.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
uriTemplate: 'search_filter_parameter{._format}',
2727
parameters: [
2828
'foo' => new QueryParameter(filter: 'app_search_filter_via_parameter'),
29+
'fooAlias' => new QueryParameter(filter: 'app_search_filter_via_parameter', property: 'foo'),
2930
'order[:property]' => new QueryParameter(filter: 'app_search_filter_via_parameter.order_filter'),
3031

3132
'searchPartial[:property]' => new QueryParameter(filter: 'app_search_filter_partial'),

0 commit comments

Comments
 (0)