From 317831c27a0bcb90a97860c9ec90b3ca05d0d6f0 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 27 Nov 2024 11:04:16 +0100 Subject: [PATCH 1/3] ensure that tests are run with lowest supported Serializer versions --- Tests/Extractor/SerializerExtractorTest.php | 8 +++++++- Tests/Fixtures/Dummy.php | 2 ++ Tests/Fixtures/IgnorePropertyDummy.php | 9 +++++++++ composer.json | 7 +++++-- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Tests/Extractor/SerializerExtractorTest.php b/Tests/Extractor/SerializerExtractorTest.php index ec3f949..53d3396 100644 --- a/Tests/Extractor/SerializerExtractorTest.php +++ b/Tests/Extractor/SerializerExtractorTest.php @@ -11,12 +11,14 @@ namespace Symfony\Component\PropertyInfo\Tests\Extractor; +use Doctrine\Common\Annotations\AnnotationReader; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Extractor\SerializerExtractor; use Symfony\Component\PropertyInfo\Tests\Fixtures\AdderRemoverDummy; use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy; use Symfony\Component\PropertyInfo\Tests\Fixtures\IgnorePropertyDummy; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; +use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader; /** @@ -28,7 +30,11 @@ class SerializerExtractorTest extends TestCase protected function setUp(): void { - $classMetadataFactory = new ClassMetadataFactory(new AttributeLoader()); + if (class_exists(AttributeLoader::class)) { + $classMetadataFactory = new ClassMetadataFactory(new AttributeLoader()); + } else { + $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); + } $this->extractor = new SerializerExtractor($classMetadataFactory); } diff --git a/Tests/Fixtures/Dummy.php b/Tests/Fixtures/Dummy.php index 6c2ea07..97f4c04 100644 --- a/Tests/Fixtures/Dummy.php +++ b/Tests/Fixtures/Dummy.php @@ -11,6 +11,7 @@ namespace Symfony\Component\PropertyInfo\Tests\Fixtures; +use Symfony\Component\Serializer\Annotation\Groups as GroupsAnnotation; use Symfony\Component\Serializer\Attribute\Groups; /** @@ -42,6 +43,7 @@ class Dummy extends ParentDummy /** * @var \DateTimeImmutable[] + * @GroupsAnnotation({"a", "b"}) */ #[Groups(['a', 'b'])] public $collection; diff --git a/Tests/Fixtures/IgnorePropertyDummy.php b/Tests/Fixtures/IgnorePropertyDummy.php index 9216ff8..2ff38cb 100644 --- a/Tests/Fixtures/IgnorePropertyDummy.php +++ b/Tests/Fixtures/IgnorePropertyDummy.php @@ -11,6 +11,8 @@ namespace Symfony\Component\PropertyInfo\Tests\Fixtures; +use Symfony\Component\Serializer\Annotation\Groups as GroupsAnnotation; +use Symfony\Component\Serializer\Annotation\Ignore as IgnoreAnnotation; use Symfony\Component\Serializer\Attribute\Groups; use Symfony\Component\Serializer\Attribute\Ignore; @@ -19,9 +21,16 @@ */ class IgnorePropertyDummy { + /** + * @GroupsAnnotation({"a"}) + */ #[Groups(['a'])] public $visibleProperty; + /** + * @GroupsAnnotation({"a"}) + * @IgnoreAnnotation + */ #[Groups(['a']), Ignore] private $ignoredProperty; } diff --git a/composer.json b/composer.json index 26e754d..0b880b7 100644 --- a/composer.json +++ b/composer.json @@ -27,16 +27,19 @@ "symfony/string": "^5.4|^6.0|^7.0" }, "require-dev": { - "symfony/serializer": "^6.4|^7.0", + "doctrine/annotations": "^1.12|^2", + "symfony/serializer": "^5.4|^6.4|^7.0", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/dependency-injection": "^5.4|^6.0|^7.0", "phpdocumentor/reflection-docblock": "^5.2", "phpstan/phpdoc-parser": "^1.0|^2.0" }, "conflict": { + "doctrine/annotations": "<1.12", "phpdocumentor/reflection-docblock": "<5.2", "phpdocumentor/type-resolver": "<1.5.1", - "symfony/dependency-injection": "<5.4" + "symfony/dependency-injection": "<5.4", + "symfony/dependency-injection": "<5.4|>=6.0,<6.4" }, "autoload": { "psr-4": { "Symfony\\Component\\PropertyInfo\\": "" }, From 07bff618858b7997c455b6c9194d9f93a118c085 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 2 Dec 2024 15:13:07 +0100 Subject: [PATCH 2/3] evaluate access flags for properties with asymmetric visibility --- Extractor/ReflectionExtractor.php | 8 +++- Tests/Extractor/ReflectionExtractorTest.php | 45 +++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/Extractor/ReflectionExtractor.php b/Extractor/ReflectionExtractor.php index 8e00e64..89239a5 100644 --- a/Extractor/ReflectionExtractor.php +++ b/Extractor/ReflectionExtractor.php @@ -581,8 +581,12 @@ private function isAllowedProperty(string $class, string $property, bool $writeA return false; } - if (\PHP_VERSION_ID >= 80400 && ($reflectionProperty->isProtectedSet() || $reflectionProperty->isPrivateSet())) { - return false; + if (\PHP_VERSION_ID >= 80400 && $reflectionProperty->isProtectedSet()) { + return (bool) ($this->propertyReflectionFlags & \ReflectionProperty::IS_PROTECTED); + } + + if (\PHP_VERSION_ID >= 80400 && $reflectionProperty->isPrivateSet()) { + return (bool) ($this->propertyReflectionFlags & \ReflectionProperty::IS_PRIVATE); } if (\PHP_VERSION_ID >= 80400 &&$reflectionProperty->isVirtual() && !$reflectionProperty->hasHook(\PropertyHookType::Set)) { diff --git a/Tests/Extractor/ReflectionExtractorTest.php b/Tests/Extractor/ReflectionExtractorTest.php index a631510..4556509 100644 --- a/Tests/Extractor/ReflectionExtractorTest.php +++ b/Tests/Extractor/ReflectionExtractorTest.php @@ -672,6 +672,51 @@ public function testAsymmetricVisibility() $this->assertFalse($this->extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate')); } + /** + * @requires PHP 8.4 + */ + public function testAsymmetricVisibilityAllowPublicOnly() + { + $extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PUBLIC); + + $this->assertTrue($extractor->isReadable(AsymmetricVisibility::class, 'publicPrivate')); + $this->assertTrue($extractor->isReadable(AsymmetricVisibility::class, 'publicProtected')); + $this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'protectedPrivate')); + $this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'publicPrivate')); + $this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'publicProtected')); + $this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate')); + } + + /** + * @requires PHP 8.4 + */ + public function testAsymmetricVisibilityAllowProtectedOnly() + { + $extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PROTECTED); + + $this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'publicPrivate')); + $this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'publicProtected')); + $this->assertTrue($extractor->isReadable(AsymmetricVisibility::class, 'protectedPrivate')); + $this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'publicPrivate')); + $this->assertTrue($extractor->isWritable(AsymmetricVisibility::class, 'publicProtected')); + $this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate')); + } + + /** + * @requires PHP 8.4 + */ + public function testAsymmetricVisibilityAllowPrivateOnly() + { + $extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PRIVATE); + + $this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'publicPrivate')); + $this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'publicProtected')); + $this->assertFalse($extractor->isReadable(AsymmetricVisibility::class, 'protectedPrivate')); + $this->assertTrue($extractor->isWritable(AsymmetricVisibility::class, 'publicPrivate')); + $this->assertFalse($extractor->isWritable(AsymmetricVisibility::class, 'publicProtected')); + $this->assertTrue($extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate')); + } + /** * @requires PHP 8.4 */ From 334d1c34113caba7485ee62cdc9a6af81c37663c Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Thu, 5 Dec 2024 00:17:16 +0100 Subject: [PATCH 3/3] chore: fix CS --- Tests/Extractor/ReflectionExtractorTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/Extractor/ReflectionExtractorTest.php b/Tests/Extractor/ReflectionExtractorTest.php index 13e9db7..614e7d8 100644 --- a/Tests/Extractor/ReflectionExtractorTest.php +++ b/Tests/Extractor/ReflectionExtractorTest.php @@ -718,6 +718,7 @@ public function testVirtualProperties() /** * @dataProvider provideAsymmetricVisibilityMutator + * * @requires PHP 8.4 */ public function testAsymmetricVisibilityMutator(string $property, string $readVisibility, string $writeVisibility) @@ -743,6 +744,7 @@ public static function provideAsymmetricVisibilityMutator(): iterable /** * @dataProvider provideVirtualPropertiesMutator + * * @requires PHP 8.4 */ public function testVirtualPropertiesMutator(string $property, string $readVisibility, string $writeVisibility)