From d159c8ef2a7a7a5572e02b1e773a3fed9bbaf9cd Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Sun, 29 Jan 2023 18:15:18 -0500 Subject: [PATCH 1/2] Rename the existing annotation driver as a base class for annotations and attributes --- ...er.php => AnnotationOrAttributeDriver.php} | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) rename src/Metadata/Driver/{AnnotationDriver.php => AnnotationOrAttributeDriver.php} (93%) diff --git a/src/Metadata/Driver/AnnotationDriver.php b/src/Metadata/Driver/AnnotationOrAttributeDriver.php similarity index 93% rename from src/Metadata/Driver/AnnotationDriver.php rename to src/Metadata/Driver/AnnotationOrAttributeDriver.php index 8cda61bc3..461d831c1 100644 --- a/src/Metadata/Driver/AnnotationDriver.php +++ b/src/Metadata/Driver/AnnotationOrAttributeDriver.php @@ -4,7 +4,6 @@ namespace JMS\Serializer\Metadata\Driver; -use Doctrine\Common\Annotations\Reader; use JMS\Serializer\Annotation\Accessor; use JMS\Serializer\Annotation\AccessorOrder; use JMS\Serializer\Annotation\AccessType; @@ -48,27 +47,22 @@ use Metadata\Driver\DriverInterface; use Metadata\MethodMetadata; -class AnnotationDriver implements DriverInterface +abstract class AnnotationOrAttributeDriver implements DriverInterface { use ExpressionMetadataTrait; - /** - * @var Reader - */ - private $reader; - /** * @var ParserInterface */ private $typeParser; + /** * @var PropertyNamingStrategyInterface */ private $namingStrategy; - public function __construct(Reader $reader, PropertyNamingStrategyInterface $namingStrategy, ?ParserInterface $typeParser = null, ?CompilableExpressionEvaluatorInterface $expressionEvaluator = null) + public function __construct(PropertyNamingStrategyInterface $namingStrategy, ?ParserInterface $typeParser = null, ?CompilableExpressionEvaluatorInterface $expressionEvaluator = null) { - $this->reader = $reader; $this->typeParser = $typeParser ?: new Parser(); $this->namingStrategy = $namingStrategy; $this->expressionEvaluator = $expressionEvaluator; @@ -78,6 +72,7 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat { $classMetadata = new ClassMetadata($name = $class->name); $fileResource = $class->getFilename(); + if (false !== $fileResource) { $classMetadata->fileResources[] = $fileResource; } @@ -89,7 +84,8 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat $excludeAll = false; $classAccessType = PropertyMetadata::ACCESS_TYPE_PROPERTY; $readOnlyClass = false; - foreach ($this->reader->getClassAnnotations($class) as $annot) { + + foreach ($this->getClassAnnotations($class) as $annot) { if ($annot instanceof ExclusionPolicy) { $exclusionPolicy = $annot->policy; } elseif ($annot instanceof XmlRoot) { @@ -136,7 +132,7 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat continue; } - $methodAnnotations = $this->reader->getMethodAnnotations($method); + $methodAnnotations = $this->getMethodAnnotations($method); foreach ($methodAnnotations as $annot) { if ($annot instanceof PreSerialize) { @@ -164,7 +160,7 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat } $propertiesMetadata[] = new PropertyMetadata($name, $property->getName()); - $propertiesAnnotations[] = $this->reader->getPropertyAnnotations($property); + $propertiesAnnotations[] = $this->getPropertyAnnotations($property); } foreach ($propertiesMetadata as $propertyKey => $propertyMetadata) { @@ -280,4 +276,19 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat return $classMetadata; } + + /** + * @return list + */ + abstract protected function getClassAnnotations(\ReflectionClass $class): array; + + /** + * @return list + */ + abstract protected function getMethodAnnotations(\ReflectionMethod $method): array; + + /** + * @return list + */ + abstract protected function getPropertyAnnotations(\ReflectionProperty $property): array; } From e501fec3a3aca502a9a199111bb6e8a3da29d332 Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Sun, 29 Jan 2023 18:16:53 -0500 Subject: [PATCH 2/2] Create an attribute driver decoupled from the annotations driver, deprecate the annotation based attribute reader --- src/Metadata/Driver/AnnotationDriver.php | 49 +++++++++++++++++++ src/Metadata/Driver/AttributeDriver.php | 47 ++++++++++++++++++ .../AttributeDriver/AttributeReader.php | 3 ++ .../Metadata/Driver/AnnotationDriverTest.php | 22 +-------- tests/Metadata/Driver/AttributeDriverTest.php | 8 +-- .../BaseAnnotationOrAttributeDriverTest.php | 32 ++++++++++++ 6 files changed, 134 insertions(+), 27 deletions(-) create mode 100644 src/Metadata/Driver/AnnotationDriver.php create mode 100644 src/Metadata/Driver/AttributeDriver.php create mode 100644 tests/Metadata/Driver/BaseAnnotationOrAttributeDriverTest.php diff --git a/src/Metadata/Driver/AnnotationDriver.php b/src/Metadata/Driver/AnnotationDriver.php new file mode 100644 index 000000000..86f5a5bf4 --- /dev/null +++ b/src/Metadata/Driver/AnnotationDriver.php @@ -0,0 +1,49 @@ +reader = $reader; + } + + /** + * @return list + */ + protected function getClassAnnotations(\ReflectionClass $class): array + { + return $this->reader->getClassAnnotations($class); + } + + /** + * @return list + */ + protected function getMethodAnnotations(\ReflectionMethod $method): array + { + return $this->reader->getMethodAnnotations($method); + } + + /** + * @return list + */ + protected function getPropertyAnnotations(\ReflectionProperty $property): array + { + return $this->reader->getPropertyAnnotations($property); + } +} diff --git a/src/Metadata/Driver/AttributeDriver.php b/src/Metadata/Driver/AttributeDriver.php new file mode 100644 index 000000000..8d794c64b --- /dev/null +++ b/src/Metadata/Driver/AttributeDriver.php @@ -0,0 +1,47 @@ + + */ + protected function getClassAnnotations(\ReflectionClass $class): array + { + return array_map( + static function (\ReflectionAttribute $attribute): object { + return $attribute->newInstance(); + }, + $class->getAttributes() + ); + } + + /** + * @return list + */ + protected function getMethodAnnotations(\ReflectionMethod $method): array + { + return array_map( + static function (\ReflectionAttribute $attribute): object { + return $attribute->newInstance(); + }, + $method->getAttributes() + ); + } + + /** + * @return list + */ + protected function getPropertyAnnotations(\ReflectionProperty $property): array + { + return array_map( + static function (\ReflectionAttribute $attribute): object { + return $attribute->newInstance(); + }, + $property->getAttributes() + ); + } +} diff --git a/src/Metadata/Driver/AttributeDriver/AttributeReader.php b/src/Metadata/Driver/AttributeDriver/AttributeReader.php index 0b5156b22..454019039 100644 --- a/src/Metadata/Driver/AttributeDriver/AttributeReader.php +++ b/src/Metadata/Driver/AttributeDriver/AttributeReader.php @@ -9,6 +9,9 @@ use ReflectionMethod; use ReflectionProperty; +/** + * @deprecated use {@see \JMS\Serializer\Metadata\Driver\AttributeDriver} instead + */ class AttributeReader implements Reader { /** diff --git a/tests/Metadata/Driver/AnnotationDriverTest.php b/tests/Metadata/Driver/AnnotationDriverTest.php index 4afb55bc5..6a76d17a6 100644 --- a/tests/Metadata/Driver/AnnotationDriverTest.php +++ b/tests/Metadata/Driver/AnnotationDriverTest.php @@ -7,32 +7,12 @@ use Doctrine\Common\Annotations\AnnotationReader; use JMS\Serializer\Metadata\Driver\AnnotationDriver; use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; -use JMS\Serializer\Tests\Fixtures\AllExcludedObject; use Metadata\Driver\DriverInterface; -class AnnotationDriverTest extends BaseDriverTest +class AnnotationDriverTest extends BaseAnnotationOrAttributeDriverTest { - public function testAllExcluded() - { - $a = new AllExcludedObject(); - $m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass($a)); - - self::assertArrayNotHasKey('foo', $m->propertyMetadata); - self::assertArrayHasKey('bar', $m->propertyMetadata); - } - protected function getDriver(?string $subDir = null, bool $addUnderscoreDir = true): DriverInterface { return new AnnotationDriver(new AnnotationReader(), new IdenticalPropertyNamingStrategy(), null, $this->getExpressionEvaluator()); } - - public function testCanDefineMetadataForInternalClass() - { - $this->markTestSkipped('Can not define annotation metadata for internal classes'); - } - - public function testShortExposeSyntax(): void - { - $this->markTestSkipped('Short expose syntax not supported on annotations'); - } } diff --git a/tests/Metadata/Driver/AttributeDriverTest.php b/tests/Metadata/Driver/AttributeDriverTest.php index 1ab427c7a..3ba964838 100644 --- a/tests/Metadata/Driver/AttributeDriverTest.php +++ b/tests/Metadata/Driver/AttributeDriverTest.php @@ -4,13 +4,11 @@ namespace JMS\Serializer\Tests\Metadata\Driver; -use Doctrine\Common\Annotations\AnnotationReader; -use JMS\Serializer\Metadata\Driver\AnnotationDriver; use JMS\Serializer\Metadata\Driver\AttributeDriver; use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; use Metadata\Driver\DriverInterface; -class AttributeDriverTest extends AnnotationDriverTest +class AttributeDriverTest extends BaseAnnotationOrAttributeDriverTest { protected function setUp(): void { @@ -23,8 +21,6 @@ protected function setUp(): void protected function getDriver(?string $subDir = null, bool $addUnderscoreDir = true): DriverInterface { - $annotationsReader = new AttributeDriver\AttributeReader(new AnnotationReader()); - - return new AnnotationDriver($annotationsReader, new IdenticalPropertyNamingStrategy(), null, $this->getExpressionEvaluator()); + return new AttributeDriver(new IdenticalPropertyNamingStrategy(), null, $this->getExpressionEvaluator()); } } diff --git a/tests/Metadata/Driver/BaseAnnotationOrAttributeDriverTest.php b/tests/Metadata/Driver/BaseAnnotationOrAttributeDriverTest.php new file mode 100644 index 000000000..0f79f401e --- /dev/null +++ b/tests/Metadata/Driver/BaseAnnotationOrAttributeDriverTest.php @@ -0,0 +1,32 @@ +getDriver()->loadMetadataForClass(new \ReflectionClass($a)); + + self::assertArrayNotHasKey('foo', $m->propertyMetadata); + self::assertArrayHasKey('bar', $m->propertyMetadata); + } + + public function testCanDefineMetadataForInternalClass(): void + { + $this->markTestSkipped('Can not define annotation or attribute metadata for internal classes'); + } + + public function testShortExposeSyntax(): void + { + $this->markTestSkipped('Short expose syntax not supported on annotations or attribute'); + } +}