diff --git a/CHANGELOG.md b/CHANGELOG.md index ea079941e4..3c041f35c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ a release. --- ## [Unreleased] +### Added +- AttributeReader reads attributes from class traits ## [3.16.1] ### Fixed diff --git a/src/Mapping/Driver/AttributeReader.php b/src/Mapping/Driver/AttributeReader.php index 7e57396498..d67370494b 100644 --- a/src/Mapping/Driver/AttributeReader.php +++ b/src/Mapping/Driver/AttributeReader.php @@ -26,7 +26,7 @@ final class AttributeReader */ public function getClassAnnotations(\ReflectionClass $class): array { - return $this->convertToAttributeInstances($class->getAttributes()); + return $this->convertToAttributeInstances($this->getClassAndTraitsAttributes($class)); } /** @@ -94,6 +94,24 @@ private function convertToAttributeInstances(iterable $attributes): array return $instances; } + /** + * Get attributes from a class including those from traits. + * + * @phpstan-param \ReflectionClass $class + * + * @return \ReflectionAttribute[] + */ + private function getClassAndTraitsAttributes(\ReflectionClass $class): array + { + $traitAttributes = array_reduce( + $class->getTraits(), + static fn (array $carry, \ReflectionClass $trait) => array_merge($trait->getAttributes(), $carry), + [] + ); + + return array_merge($class->getAttributes(), $traitAttributes); + } + private function isRepeatable(string $attributeClassName): bool { if (isset($this->isRepeatableAttribute[$attributeClassName])) {