Skip to content

Commit 9f4c4a5

Browse files
committed
Merge 4.0
2 parents c97db6b + 268519a commit 9f4c4a5

File tree

7 files changed

+104
-33
lines changed

7 files changed

+104
-33
lines changed

CHANGELOG.md

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,27 @@
1717
* [d0a442786](https://github.com/api-platform/core/commit/d0a44278630d201b91cbba0774a09f4eeaac88f7) feat(doctrine): enhance getLinksHandler with method validation and typo suggestions (#6874)
1818
* [f67f6f1ac](https://github.com/api-platform/core/commit/f67f6f1acb6476182c18a3503f2a8bc80ae89a0b) feat(doctrine): doctrine filters like laravel eloquent filters (#6775)
1919

20+
## v4.0.15
21+
22+
### Bug fixes
23+
24+
* [36cee399c](https://github.com/api-platform/core/commit/36cee399cfd519355b03d0406921066a22ab474c) fix(state): skip Content-Location header for GET requests (#6901)
25+
* [dba9de197](https://github.com/api-platform/core/commit/dba9de197001e91094e594f0e4dc638007cce7a6) fix(symfony): fix property restrictions for root resource with dynamic validation groups (#6908)
26+
27+
### Features
28+
29+
* [421d97ecf](https://github.com/api-platform/core/commit/421d97ecfdbc7d699a3d017d1e3ae3827a38b216) feat(laravel): add support for backed enum normalizers (#6911)
30+
31+
Also contains [v3.4.15 changes](#v3415).
32+
2033
## v4.0.14
2134

2235
### Bug fixes
2336

2437
* [97cdb6b3f](https://github.com/api-platform/core/commit/97cdb6b3f43471789e096c9dc3a0c3c7b6d4e43c) fix(state): remove ProcessorInterface laravel specific type
2538
* [b12a0d005](https://github.com/api-platform/core/commit/b12a0d005fda58a162b82a3574e6ee877838a55b) fix(graphql): register types for parameter args (#6895)
2639

27-
### Features
40+
Also contains [v3.4.14 changes](#v3414).
2841

2942
## v4.0.13
3043

@@ -36,8 +49,6 @@
3649

3750
Also contains [v3.4.10 changes](#v3410).
3851

39-
### Features
40-
4152
## v4.0.12
4253

4354
### Bug fixes
@@ -49,16 +60,12 @@ Also contains [v3.4.10 changes](#v3410).
4960

5061
Also contains [v3.4.9 changes](#v349).
5162

52-
### Features
53-
5463
## v4.0.11
5564

5665
### Bug fixes
5766

5867
* [af66075fd](https://github.com/api-platform/core/commit/af66075fdd6b83bdebc1c4ca33cc0ab7e1a7f8af) fix(laravel): fix foregin keys (relations) beeing in attributes (#6843)
5968

60-
### Features
61-
6269
* [2d59c6369](https://github.com/api-platform/core/commit/2d59c63699b4602cfe4d62504896c6d4121c1be4) feat(laravel): belongs to many relations (#6818)
6370

6471
Also contains [v3.4.8 changes](#v348).
@@ -73,8 +80,6 @@ Also contains [v3.4.8 changes](#v348).
7380

7481
Also contains [v3.4.7 changes](#v347).
7582

76-
### Features
77-
7883
## v4.0.9
7984

8085
### Bug fixes
@@ -85,16 +90,12 @@ Also contains [v3.4.7 changes](#v347).
8590

8691
Also contains [v3.4.6 changes](#v346).
8792

88-
### Features
89-
9093
## v4.0.8
9194

9295
### Bug fixes
9396

9497
* [dddb97075](https://github.com/api-platform/core/commit/dddb97075af9c6e2517e1881b803c9d31a1913cf) fix(symfony): default formats order (#6780)
9598

96-
### Features
97-
9899
## v4.0.7
99100

100101
### Bug fixes
@@ -106,8 +107,6 @@ Also contains [v3.4.6 changes](#v346).
106107
* [736ca045e](https://github.com/api-platform/core/commit/736ca045e6832f04aaa002ddd7b85c55df4696bb) fix(validator): allow to pass both a ConstraintViolationList and a previous exception (#6762)
107108
* [9ac3661b6](https://github.com/api-platform/core/commit/9ac3661b6a75255832203b87a9ba7994add64061) fix(hydra): store and use hydra context in a local variable (#6765)
108109

109-
### Features
110-
111110
## v4.0.6
112111

113112
### Bug fixes
@@ -118,8 +117,6 @@ Also contains [v3.4.6 changes](#v346).
118117
* [67c5a2a24](https://github.com/api-platform/core/commit/67c5a2a2463bca94f0997b4fab1248a08994465b) fix(laravel): jsonapi error serialization (#6755)
119118
* [ac6f667f3](https://github.com/api-platform/core/commit/ac6f667f301f6c4c399a707faf00567239bd98d8) fix(laravel): collection relations other than HasMany (#6737)
120119

121-
### Features
122-
123120
* [cecd77149](https://github.com/api-platform/core/commit/cecd77149795c1a455ac72bc3ed0606413e69900) feat(laravel): use laravel cache setting (#6751)
124121

125122
## v4.0.5
@@ -129,8 +126,6 @@ Also contains [v3.4.6 changes](#v346).
129126
* [4171d5f9c](https://github.com/api-platform/core/commit/4171d5f9cd41731b857c53a186270ba0626baedf) fix(graphql): register query parameter arguments with filters (#6726)
130127
* [48ab53816](https://github.com/api-platform/core/commit/48ab53816c55e6116aa64ac81f522f4b7b9bb9f6) fix(laravel): make command writes to app instead of src (#6723)
131128

132-
### Features
133-
134129
## v4.0.4
135130

136131
### Bug fixes
@@ -175,7 +170,7 @@ Also contains [v3.4.6 changes](#v346).
175170
* [c47e2996e](https://github.com/api-platform/core/commit/c47e2996e51c587c998fde88903703bd6ac9a43c) fix: default format and standard_put values
176171
* [e327f5f69](https://github.com/api-platform/core/commit/e327f5f69c823c1ed674eefc0eb2551e30fb36bd) fix(symfony): namespace of path segment name generator services (#6642)
177172

178-
Notes:
173+
Notes:
179174

180175
`standard_put=true` is now the default, you can set it to `false` using `extra_properties.defaults`
181176

@@ -274,6 +269,12 @@ Notes:
274269

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

272+
## v3.4.15
273+
274+
### Bug fixes
275+
276+
* [ab03b5544](https://github.com/api-platform/core/commit/ab03b5544f742b98a39cc23fc157f1be7a2e0c63) fix(openapi): typing issue with `openapiContext` in `#[ApiProperty]` (#6910)
277+
277278
## v3.4.14
278279

279280
### Bug fixes

src/JsonSchema/Metadata/Property/Factory/SchemaPropertyMetadataFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public function create(string $resourceClass, string $property, array $options =
106106
// never override the following keys if at least one is already set or if there's a custom openapi context
107107
if ([] === $types
108108
|| ($propertySchema['type'] ?? $propertySchema['$ref'] ?? $propertySchema['anyOf'] ?? $propertySchema['allOf'] ?? $propertySchema['oneOf'] ?? false)
109-
|| ($propertyMetadata->getOpenapiContext() ?? false)
109+
|| \array_key_exists('type', $propertyMetadata->getOpenapiContext() ?? [])
110110
) {
111111
return $propertyMetadata->withSchema($propertySchema);
112112
}

src/JsonSchema/Tests/Fixtures/DummyWithCustomOpenApiContext.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,10 @@ class DummyWithCustomOpenApiContext
3030
{
3131
#[ApiProperty(openapiContext: ['type' => 'object', 'properties' => ['alpha' => ['type' => 'integer']]])]
3232
public $acme;
33+
34+
#[ApiProperty(openapiContext: ['description' => 'My description'])]
35+
public bool $foo;
36+
37+
#[ApiProperty(openapiContext: ['iris' => 'https://schema.org/Date'])]
38+
public \DateTimeImmutable $bar;
3339
}

src/JsonSchema/Tests/Metadata/Property/Factory/SchemaPropertyMetadataFactoryTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,33 @@ public function testWithCustomOpenApiContext(): void
4949
$apiProperty = $schemaPropertyMetadataFactory->create(DummyWithCustomOpenApiContext::class, 'acme');
5050
$this->assertEquals([], $apiProperty->getSchema());
5151
}
52+
53+
public function testWithCustomOpenApiContextWithoutTypeDefinition(): void
54+
{
55+
$resourceClassResolver = $this->createMock(ResourceClassResolverInterface::class);
56+
$apiProperty = new ApiProperty(
57+
openapiContext: ['description' => 'My description'],
58+
builtinTypes: [new Type(builtinType: 'bool')],
59+
);
60+
$decorated = $this->createMock(PropertyMetadataFactoryInterface::class);
61+
$decorated->expects($this->once())->method('create')->with(DummyWithCustomOpenApiContext::class, 'foo')->willReturn($apiProperty);
62+
$schemaPropertyMetadataFactory = new SchemaPropertyMetadataFactory($resourceClassResolver, $decorated);
63+
$apiProperty = $schemaPropertyMetadataFactory->create(DummyWithCustomOpenApiContext::class, 'foo');
64+
$this->assertEquals([
65+
'type' => 'boolean',
66+
], $apiProperty->getSchema());
67+
68+
$apiProperty = new ApiProperty(
69+
openapiContext: ['iris' => 'https://schema.org/Date'],
70+
builtinTypes: [new Type(builtinType: 'object', class: \DateTimeImmutable::class)],
71+
);
72+
$decorated = $this->createMock(PropertyMetadataFactoryInterface::class);
73+
$decorated->expects($this->once())->method('create')->with(DummyWithCustomOpenApiContext::class, 'bar')->willReturn($apiProperty);
74+
$schemaPropertyMetadataFactory = new SchemaPropertyMetadataFactory($resourceClassResolver, $decorated);
75+
$apiProperty = $schemaPropertyMetadataFactory->create(DummyWithCustomOpenApiContext::class, 'bar');
76+
$this->assertEquals([
77+
'type' => 'string',
78+
'format' => 'date-time',
79+
], $apiProperty->getSchema());
80+
}
5281
}

src/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,10 @@ public function create(string $resourceClass, string $property, array $options =
151151
*/
152152
private function getValidationGroups(ValidatorClassMetadataInterface $classMetadata, array $options): array
153153
{
154-
if (isset($options['validation_groups'])) {
154+
if (
155+
isset($options['validation_groups'])
156+
&& !\is_callable($options['validation_groups'])
157+
) {
155158
return $options['validation_groups'];
156159
}
157160

tests/Fixtures/DummyValidatedEntity.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,12 @@ class DummyValidatedEntity
7777
*/
7878
#[Assert\Url]
7979
public $dummyUrl;
80+
81+
/**
82+
* @return string[]
83+
*/
84+
public static function getValidationGroups(): array
85+
{
86+
return ['dummy'];
87+
}
8088
}

tests/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,8 @@ public function testCreateWithPropertyLengthRestriction(): void
272272

273273
$validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class);
274274
$validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)
275-
->willReturn($validatorClassMetadata)
276-
->shouldBeCalled();
275+
->willReturn($validatorClassMetadata)
276+
->shouldBeCalled();
277277

278278
$decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class);
279279
$property = 'dummy';
@@ -283,7 +283,9 @@ public function testCreateWithPropertyLengthRestriction(): void
283283

284284
$lengthRestrictions = new PropertySchemaLengthRestriction();
285285
$validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory(
286-
$validatorMetadataFactory->reveal(), $decoratedPropertyMetadataFactory->reveal(), [$lengthRestrictions]
286+
$validatorMetadataFactory->reveal(),
287+
$decoratedPropertyMetadataFactory->reveal(),
288+
[$lengthRestrictions]
287289
);
288290

289291
$schema = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, $property)->getSchema();
@@ -299,16 +301,17 @@ public function testCreateWithPropertyRegexRestriction(): void
299301

300302
$validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class);
301303
$validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)
302-
->willReturn($validatorClassMetadata)
303-
->shouldBeCalled();
304+
->willReturn($validatorClassMetadata)
305+
->shouldBeCalled();
304306

305307
$decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class);
306308
$decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummy', [])->willReturn(
307309
new ApiProperty()
308310
)->shouldBeCalled();
309311

310312
$validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory(
311-
$validatorMetadataFactory->reveal(), $decoratedPropertyMetadataFactory->reveal(),
313+
$validatorMetadataFactory->reveal(),
314+
$decoratedPropertyMetadataFactory->reveal(),
312315
[new PropertySchemaRegexRestriction()]
313316
);
314317

@@ -326,8 +329,8 @@ public function testCreateWithPropertyFormatRestriction(string $property, string
326329

327330
$validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class);
328331
$validatorMetadataFactory->getMetadataFor($class)
329-
->willReturn($validatorClassMetadata)
330-
->shouldBeCalled();
332+
->willReturn($validatorClassMetadata)
333+
->shouldBeCalled();
331334

332335
$decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class);
333336
$decoratedPropertyMetadataFactory->create($class, $property, [])->willReturn(
@@ -521,7 +524,8 @@ public function testCreateWithPropertyChoiceRestriction(ApiProperty $propertyMet
521524
)->shouldBeCalled();
522525

523526
$validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory(
524-
$validatorMetadataFactory->reveal(), $decoratedPropertyMetadataFactory->reveal(),
527+
$validatorMetadataFactory->reveal(),
528+
$decoratedPropertyMetadataFactory->reveal(),
525529
[new PropertySchemaChoiceRestriction()]
526530
);
527531

@@ -558,7 +562,8 @@ public function testCreateWithPropertyCountRestriction(string $property, array $
558562
)->shouldBeCalled();
559563

560564
$validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory(
561-
$validatorMetadataFactory->reveal(), $decoratedPropertyMetadataFactory->reveal(),
565+
$validatorMetadataFactory->reveal(),
566+
$decoratedPropertyMetadataFactory->reveal(),
562567
[new PropertySchemaCountRestriction()]
563568
);
564569

@@ -660,7 +665,8 @@ public function testCreateWithPropertyNumericRestriction(ApiProperty $propertyMe
660665
)->shouldBeCalled();
661666

662667
$validationPropertyMetadataFactory = new ValidatorPropertyMetadataFactory(
663-
$validatorMetadataFactory->reveal(), $decoratedPropertyMetadataFactory->reveal(),
668+
$validatorMetadataFactory->reveal(),
669+
$decoratedPropertyMetadataFactory->reveal(),
664670
[
665671
new PropertySchemaGreaterThanOrEqualRestriction(),
666672
new PropertySchemaGreaterThanRestriction(),
@@ -724,4 +730,22 @@ public static function provideNumericConstraintCases(): \Generator
724730
'expectedSchema' => ['maximum' => 0],
725731
];
726732
}
733+
734+
public function testCallableGroup(): void
735+
{
736+
$propertyMetadata = (new ApiProperty())->withDescription('A dummy group')->withReadable(true)->withWritable(true);
737+
738+
$decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class);
739+
$decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => [DummyValidatedEntity::class, 'getValidationGroups']])->willReturn($propertyMetadata)->shouldBeCalled();
740+
741+
$validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class);
742+
$validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled();
743+
744+
$validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory(
745+
$validatorMetadataFactory->reveal(),
746+
$decoratedPropertyMetadataFactory->reveal(),
747+
[]
748+
);
749+
$validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => [DummyValidatedEntity::class, 'getValidationGroups']]);
750+
}
727751
}

0 commit comments

Comments
 (0)