10000 feature #50983 [Serializer] Deprecate annotations in favor of attribu… · symfony/symfony@f6c7a74 · GitHub
[go: up one dir, main page]

Skip to content

Commit f6c7a74

Browse files
feature #50983 [Serializer] Deprecate annotations in favor of attributes (derrabus)
This PR was merged into the 6.4 branch. Discussion ---------- [Serializer] Deprecate annotations in favor of attributes | Q | A | ------------- | --- | Branch? | 6.4 | Bug fix? | no | New feature? | yes | Deprecations? | yes | Tickets | Follows #50888 | License | MIT | Doc PR | TODO, see symfony/symfony-docs#18589 This PR deprecates using Doctrine annotations to configure serialization. Attributes shall be used instead. Existing applications can be migrated easily using [Rector](https://getrector.com/blog/how-to-upgrade-annotations-to-attributes). Deprecation errors triggered by the bundles' functional tests will be resolved once #50888 is merged. Commits ------- 9b7b397 [Serializer] Deprecate annotations in favor of attributes
2 parents 1698d1e + 9b7b397 commit f6c7a74

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+482
-358
lines changed

UPGRADE-6.4.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,9 @@ Security
7171
* `UserValueResolver` no longer implements `ArgumentValueResolverInterface`
7272
* Make `PersistentToken` immutable
7373
* Deprecate accepting only `DateTime` for `TokenProviderInterface::updateToken()`, use `DateTimeInterface` instead
74+
75+
Serializer
76+
----------
77+
78+
* Deprecate Doctrine annotations support in favor of native attributes
79+
* Deprecate passing an annotation reader to the constructor of `AnnotationLoader`

src/Symfony/Bridge/Twig/Tests/Extension/Fixtures/SerializerModelFixture.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@
99
*/
1010
class SerializerModelFixture
1111
{
12-
/**
13-
* @Groups({"read"})
14-
*/
12+
#[Groups(['read'])]
1513
public $name = 'howdy';
1614

1715
public $title = 'fixture';

src/Symfony/Bridge/Twig/Tests/Extension/SerializerExtensionTest.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
namespace Symfony\Bridge\Twig\Tests\Extension;
1313

14-
use Doctrine\Common\Annotations\AnnotationReader;
1514
use PHPUnit\Framework\TestCase;
1615
use Symfony\Bridge\Twig\Extension\SerializerExtension;
1716
use Symfony\Bridge\Twig\Extension\SerializerRuntime;
@@ -50,7 +49,7 @@ public static function serializerDataProvider(): \Generator
5049

5150
private function getTwig(string $template): Environment
5251
{
53-
$meta = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
52+
$meta = new ClassMetadataFactory(new AnnotationLoader());
5453
$runtime = new SerializerRuntime(new Serializer([new ObjectNormalizer($meta)], [new JsonEncoder(), new YamlEncoder()]));
5554

5655
$mockRuntimeLoader = $this->createMock(RuntimeLoaderInterface::class);

src/Symfony/Bridge/Twig/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
"twig/twig": "^2.13|^3.0.4"
2222
},
2323
"require-dev": {
24-
"doctrine/annotations": "^1.12|^2",
2524
"egulias/email-validator": "^2.1.10|^3|^4",
2625
"league/html-to-markdown": "^5.0",
2726
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
@@ -62,6 +61,7 @@
6261
"symfony/http-foundation": "<5.4",
6362
"symfony/http-kernel": "<6.2",
6463
"symfony/mime": "<6.2",
64+
"symfony/serializer": "<6.2",
6565
"symfony/translation": "<5.4",
6666
"symfony/workflow": "<5.4"
6767
},

src/Symfony/Component/PropertyInfo/Tests/Extractor/SerializerExtractorTest.php

Lines changed: 4 additions & 7 deletions
38
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111

1212
namespace Symfony\Component\PropertyInfo\Tests\Extractor;
1313

14-
use Doctrine\Common\Annotations\AnnotationReader;
1514
use PHPUnit\Framework\TestCase;
1615
use Symfony\Component\PropertyInfo\Extractor\SerializerExtractor;
1716
use Symfony\Component\PropertyInfo\Tests\Fixtures\AdderRemoverDummy;
17+
use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy;
1818
use Symfony\Component\PropertyInfo\Tests\Fixtures\IgnorePropertyDummy;
1919
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
2020
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
@@ -24,22 +24,19 @@
2424
*/
2525
class SerializerExtractorTest extends TestCase
2626
{
27-
/**
28-
* @var SerializerExtractor
29-
*/
30-
private $extractor;
27+
private SerializerExtractor $extractor;
3128

3229
protected function setUp(): void
3330
{
34-
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
31+
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader());
3532
$this->extractor = new SerializerExtractor($classMetadataFactory);
3633
}
3734

3835
public function testGetProperties()
3936
{
4037
$this->assertEquals(
41
['collection'],
42-
$this->extractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', ['serializer_groups' => ['a']])
39+
$this->extractor->getProperties(Dummy::class, ['serializer_groups' => ['a']])
4340
);
4441
}
4542

src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ class Dummy extends ParentDummy
4242

4343
/**
4444
* @var \DateTimeImmutable[]
45-
* @Groups({"a", "b"})
4645
*/
46+
#[Groups(['a', 'b'])]
4747
public $collection;
4848

4949
/**

src/Symfony/Component/PropertyInfo/Tests/Fixtures/IgnorePropertyDummy.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,9 @@
1919
*/
2020
class IgnorePropertyDummy
2121
{
22-
/**
23-
* @Groups({"a"})
24-
*/
22+
#[Groups(['a'])]
2523
public $visibleProperty;
2624

27-
/**
28-
* @Groups({"a"})
29-
* @Ignore
30-
*/
25+
#[Groups(['a']), Ignore]
3126
private $ignoredProperty;
3227
}

src/Symfony/Component/PropertyInfo/composer.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@
3131
"symfony/cache": "^5.4|^6.0|^7.0",
3232
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
3333
"phpdocumentor/reflection-docblock": "^5.2",
34-
"phpstan/phpdoc-parser": "^1.0",
35-
"doctrine/annotations": "^1.10.4|^2"
34+
"phpstan/phpdoc-parser": "^1.0"
3635
},
3736
"conflict": {
3837
"phpdocumentor/reflection-docblock": "<5.2",
3938
"phpdocumentor/type-resolver": "<1.5.1",
40-
"symfony/dependency-injection": "<5.4"
39+
"symfony/dependency-injection": "<5.4",
40+
"symfony/serializer": "<5.4"
4141
},
4242
"autoload": {
4343
"psr-4": { "Symfony\\Component\\PropertyInfo\\": "" },

src/Symfony/Component/Serializer/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
CHANGELOG
22
=========
33

4+
6.4
5+
---
6+
7+
* Deprecate Doctrine annotations support in favor of native attributes
8+
* Deprecate passing an annotation reader to the constructor of `AnnotationLoader`
9+
410
6.3
511
---
612

src/Symfony/Component/Serializer/Mapping/Loader/AnnotationLoader.php

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ class AnnotationLoader implements LoaderInterface
4646
public function __construct(
4747
private readonly ?Reader $reader = null,
4848
) {
49+
if ($reader) {
50+
trigger_deprecation('symfony/validator', '6.4', 'Passing a "%s" instance as argument 1 to "%s()" is deprecated, pass null or omit the parameter instead.', get_debug_type($reader), __METHOD__);
51+
}
4952
}
5053

5154
public function loadClassMetadata(ClassMetadataInterface $classMetadata): bool
@@ -163,10 +166,7 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata): bool
163166
return $loaded;
164167
}
165168

166-
/**
167-
* @param \ReflectionClass|\ReflectionMethod|\ReflectionProperty $reflector
168-
*/
169-
public function loadAnnotations(object $reflector): iterable
169+
public function loadAnnotations(\ReflectionMethod|\ReflectionClass|\ReflectionProperty $reflector): iterable
170170
{
171171
foreach ($reflector->getAttributes() as $attribute) {
172172
if ($this->isKnownAttribute($attribute->getName())) {
@@ -193,13 +193,13 @@ public function loadAnnotations(object $reflector): iterable
193193
}
194194

195195
if ($reflector instanceof \ReflectionClass) {
196-
yield from $this->reader->getClassAnnotations($reflector);
196+
yield from $this->getClassAnnotations($reflector);
197197
}
198198
if ($reflector instanceof \ReflectionMethod) {
199-
yield from $this->reader->getMethodAnnotations($reflector);
199+
yield from $this->getMethodAnnotations($reflector);
200200
}
201201
if ($reflector instanceof \ReflectionProperty) {
202-
yield from $this->reader->getPropertyAnnotations($reflector);
202+
yield from $this->getPropertyAnnotations($reflector);
203203
}
204204
}
205205

@@ -229,4 +229,49 @@ private function isKnownAttribute(string $attributeName): bool
229229

230230
return false;
231231
}
232+
233+
/**
234+
* @return object[]
235+
*/
236+
private function getClassAnnotations(\ReflectionClass $reflector): array
237+
{
238+
if ($annotations = array_filter(
239+
$this->reader->getClassAnnotations($reflector),
240+
fn (object $annotation): bool => $this->isKnownAttribute($annotation::class),
241+
)) {
242+
trigger_deprecation('symfony/serializer', '6.4', 'Class "%s" uses Doctrine Annotations to configure serialization, which is deprecated. Use PHP attributes instead.', $reflector->getName());
243+
}
244+
245+
return $annotations;
246+
}
247+
248+
/**
249+
* @return object[]
250+
*/
251+
private function getMethodAnnotations(\ReflectionMethod $reflector): array
252+
{
253+
if ($annotations = array_filter(
254+
$this->reader->getMethodAnnotations($reflector),
255+
fn (object $annotation): bool => $this->isKnownAttribute($annotation::class),
256+
)) {
257+
trigger_deprecation('symfony/serializer', '6.4', 'Method "%s::%s()" uses Doctrine Annotations to configure serialization, which is deprecated. Use PHP attributes instead.', $reflector->getDeclaringClass()->getName(), $reflector->getName());
258+
}
259+
260+
return $annotations;
261+
}
262+
263+
/**
264+
* @return object[]
265+
*/
266+
private function getPropertyAnnotations(\ReflectionProperty $reflector): array
267+
{
268+
if ($annotations = array_filter(
269+
$this->reader->getPropertyAnnotations($reflector),
270+
fn (object $annotation): bool => $this->isKnownAttribute($annotation::class),
271+
)) {
272+
trigger_deprecation('symfony/serializer', '6.4', 'Property "%s::$%s" uses Doctrine Annotations to configure serialization, which is deprecated. Use PHP attributes instead.', $reflector->getDeclaringClass()->getName(), $reflector->getName());
273+
}
274+
275+
return $annotations;
276+
}
232277
}

src/Symfony/Component/Serializer/Tests/Fixtures/Annotations/GroupDummy.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
use Symfony\Component\Serializer\Annotation\Groups;
1515
use Symfony\Component\Serializer\Tests\Fixtures\ChildOfGroupsAnnotationDummy;
16-
use Symfony\Component\Serializer\Tests\Fixtures\GroupDummyInterface;
16+
use Symfony\Component\Serializer\Tests\Fixtures\Annotations\GroupDummyInterface;
1717

1818
/**
1919
* @author Kévin Dunglas <dunglas@gmail.com>

src/Symfony/Component/Serializer/Tests/Fixtures/GroupDummyInterface.php renamed to src/Symfony/Component/Serializer/Tests/Fixtures/Annotations/GroupDummyInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* file that was distributed with this source code.
1010
*/
1111

12-
namespace Symfony\Component\Serializer\Tests\Fixtures;
12+
namespace Symfony\Component\Serializer\Tests\Fixtures\Annotations;
1313

1414
use Symfony\Component\Serializer\Annotation\Groups;
1515

src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/GroupDummy.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
use Symfony\Component\Serializer\Annotation\Groups;
1515
use Symfony\Component\Serializer\Tests\Fixtures\ChildOfGroupsAnnotationDummy;
16-
use Symfony\Component\Serializer\Tests\Fixtures\GroupDummyInterface;
1716

1817
/**
1918
* @author Kévin Dunglas <dunglas@gmail.com>

src/Symfony/Component/Serializer/Tests/Fixtures/Annotations/GroupDummyChild.php renamed to src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/GroupDummyChild.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* file that was distributed with this source code.
1010
*/
1111

12-
namespace Symfony\Component\Serializer\Tests\Fixtures\Annotations;
12+
namespace Symfony\Component\Serializer\Tests\Fixtures\Attributes;
1313

1414
class GroupDummyChild extends GroupDummy
1515
{
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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+
namespace Symfony\Component\Serializer\Tests\Fixtures\Attributes;
13+
14+
use Symfony\Component\Serializer\Annotation\Groups;
15+
16+
/**
17+
* @author Kévin Dunglas <dunglas@gmail.com>
18+
*/
19+
interface GroupDummyInterface
20+
{
21+
#[Groups(['a', 'name_converter'])]
22+
public function getSymfony();
23+
}

src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageInterface.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,12 @@
1414
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
1515

1616
/**
17-
* @DiscriminatorMap(typeProperty="type", mapping={
18-
* "one"="Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberOne",
19-
* "two"="Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo"
20-
* })
21-
*
2217
* @author Samuel Roze <samuel.roze@gmail.com>
2318
*/
19+
#[DiscriminatorMap(typeProperty: 'type', mapping: [
20+
'one' => DummyMessageNumberOne::class,
21+
'two' => DummyMessageNumberTwo::class,
22+
])]
2423
interface DummyMessageInterface
2524
{
2625
}

src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberOne.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ class DummyMessageNumberOne implements DummyMessageInterface
2020
{
2121
public $one;
2222

23-
/**
24-
* @Groups({"two"})
25-
*/
23+
#[Groups(['two'])]
2624
public $two;
2725
}

src/Symfony/Component/Serializer/Tests/Fixtures/OtherSerializedNameDummy.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@
1919
*/
2020
class OtherSerializedNameDummy
2121
{
22-
/**
23-
* @Groups({"a"})
24-
*/
22+
#[Groups(['a'])]
2523
private $buz;
2624

2725
public function setBuz($buz)
@@ -34,10 +32,7 @@ public function getBuz()
3432
return $this->buz;
3533
}
3634

37-
/**
38-
* @Groups({"b"})
39-
* @SerializedName("buz")
40-
*/
35+
#[Groups(['b']), SerializedName('buz')]
4136
public function getBuzForExport()
4237
{
4338
return $this->buz.' Rocks';
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
'Symfony\Component\Serializer\Tests\Fixtures\Annotations\IgnoreDummy':
1+
'Symfony\Component\Serializer\Tests\Fixtures\Attributes\IgnoreDummy':
22
attributes:
33
ignored1:
44
ignore: foo

0 commit comments

Comments
 (0)
0