From 14531d9504cf125aea0bf2240bf98f9e5c766ffe Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Mon, 12 Jun 2023 10:49:35 -0400 Subject: [PATCH 01/38] Don't return a metadata object unless there is explicit annotation or attribute configuration, add the NullDriver to the default driver chain to ensure a minimally configured metadata object is created --- src/Builder/DefaultDriverFactory.php | 14 ++-- src/Metadata/Driver/AnnotationDriver.php | 2 +- .../Driver/AnnotationOrAttributeDriver.php | 83 +++++++++++++++++-- src/Metadata/Driver/NullDriver.php | 26 ++++++ tests/Fixtures/AuthorDeprecatedReadOnly.php | 3 +- .../AuthorDeprecatedReadOnlyPerClass.php | 3 + tests/Fixtures/AuthorList.php | 12 +-- .../PersistendCollection/SmartPhone.php | 2 + .../Fixtures/ObjectWithLifecycleCallbacks.php | 3 + .../Metadata/Driver/AnnotationDriverTest.php | 9 +- tests/Metadata/Driver/AttributeDriverTest.php | 9 +- ...aseAnnotationOrAttributeDriverTestCase.php | 3 - tests/Metadata/Driver/DocBlockDriverTest.php | 15 +++- tests/Metadata/Driver/NullDriverTest.php | 3 +- .../Driver/UnionTypedPropertiesDriverTest.php | 12 ++- tests/Serializer/GraphNavigatorTest.php | 11 ++- 16 files changed, 175 insertions(+), 35 deletions(-) diff --git a/src/Builder/DefaultDriverFactory.php b/src/Builder/DefaultDriverFactory.php index e893a9355..5b53daf68 100644 --- a/src/Builder/DefaultDriverFactory.php +++ b/src/Builder/DefaultDriverFactory.php @@ -6,10 +6,10 @@ use Doctrine\Common\Annotations\Reader; use JMS\Serializer\Expression\CompilableExpressionEvaluatorInterface; -use JMS\Serializer\Metadata\Driver\AnnotationDriver; -use JMS\Serializer\Metadata\Driver\AttributeDriver; +use JMS\Serializer\Metadata\Driver\AnnotationOrAttributeDriver; use JMS\Serializer\Metadata\Driver\DefaultValuePropertyDriver; use JMS\Serializer\Metadata\Driver\EnumPropertiesDriver; +use JMS\Serializer\Metadata\Driver\NullDriver; use JMS\Serializer\Metadata\Driver\TypedPropertiesDriver; use JMS\Serializer\Metadata\Driver\XmlDriver; use JMS\Serializer\Metadata\Driver\YamlDriver; @@ -56,11 +56,9 @@ public function enableEnumSupport(bool $enableEnumSupport = true): void public function createDriver(array $metadataDirs, Reader $annotationReader): DriverInterface { - if (PHP_VERSION_ID >= 80000) { - $annotationReader = new AttributeDriver\AttributeReader($annotationReader); - } - - $driver = new AnnotationDriver($annotationReader, $this->propertyNamingStrategy, $this->typeParser); + $driver = new DriverChain([ + new AnnotationOrAttributeDriver($this->propertyNamingStrategy, $this->typeParser, $this->expressionEvaluator, $annotationReader), + ]); if (!empty($metadataDirs)) { $fileLocator = new FileLocator($metadataDirs); @@ -71,6 +69,8 @@ public function createDriver(array $metadataDirs, Reader $annotationReader): Dri ]); } + $driver->addDriver(new NullDriver($this->propertyNamingStrategy)); + if ($this->enableEnumSupport) { $driver = new EnumPropertiesDriver($driver); } diff --git a/src/Metadata/Driver/AnnotationDriver.php b/src/Metadata/Driver/AnnotationDriver.php index 86f5a5bf4..d2fbb9138 100644 --- a/src/Metadata/Driver/AnnotationDriver.php +++ b/src/Metadata/Driver/AnnotationDriver.php @@ -18,7 +18,7 @@ class AnnotationDriver extends AnnotationOrAttributeDriver public function __construct(Reader $reader, PropertyNamingStrategyInterface $namingStrategy, ?ParserInterface $typeParser = null, ?CompilableExpressionEvaluatorInterface $expressionEvaluator = null) { - parent::__construct($namingStrategy, $typeParser, $expressionEvaluator); + parent::__construct($namingStrategy, $typeParser, $expressionEvaluator, $reader); $this->reader = $reader; } diff --git a/src/Metadata/Driver/AnnotationOrAttributeDriver.php b/src/Metadata/Driver/AnnotationOrAttributeDriver.php index 461d831c1..8b506add4 100644 --- a/src/Metadata/Driver/AnnotationOrAttributeDriver.php +++ b/src/Metadata/Driver/AnnotationOrAttributeDriver.php @@ -4,6 +4,7 @@ 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; @@ -47,7 +48,7 @@ use Metadata\Driver\DriverInterface; use Metadata\MethodMetadata; -abstract class AnnotationOrAttributeDriver implements DriverInterface +class AnnotationOrAttributeDriver implements DriverInterface { use ExpressionMetadataTrait; @@ -61,15 +62,23 @@ abstract class AnnotationOrAttributeDriver implements DriverInterface */ private $namingStrategy; - public function __construct(PropertyNamingStrategyInterface $namingStrategy, ?ParserInterface $typeParser = null, ?CompilableExpressionEvaluatorInterface $expressionEvaluator = null) + /** + * @var Reader + */ + private $reader; + + public function __construct(PropertyNamingStrategyInterface $namingStrategy, ?ParserInterface $typeParser = null, ?CompilableExpressionEvaluatorInterface $expressionEvaluator = null, ?Reader $reader = null) { $this->typeParser = $typeParser ?: new Parser(); $this->namingStrategy = $namingStrategy; $this->expressionEvaluator = $expressionEvaluator; + $this->reader = $reader; } public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadata { + $configured = false; + $classMetadata = new ClassMetadata($name = $class->name); $fileResource = $class->getFilename(); @@ -86,6 +95,8 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat $readOnlyClass = false; foreach ($this->getClassAnnotations($class) as $annot) { + $configured = true; + if ($annot instanceof ExclusionPolicy) { $exclusionPolicy = $annot->policy; } elseif ($annot instanceof XmlRoot) { @@ -135,6 +146,8 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat $methodAnnotations = $this->getMethodAnnotations($method); foreach ($methodAnnotations as $annot) { + $configured = true; + if ($annot instanceof PreSerialize) { $classMetadata->addPreSerializeMethod(new MethodMetadata($name, $method->name)); continue 2; @@ -174,6 +187,8 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat $propertyAnnotations = $propertiesAnnotations[$propertyKey]; foreach ($propertyAnnotations as $annot) { + $configured = true; + if ($annot instanceof Since) { $propertyMetadata->sinceVersion = $annot->version; } elseif ($annot instanceof Until) { @@ -274,21 +289,79 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat } } + if (!$configured) { + return null; + } + return $classMetadata; } /** * @return list */ - abstract protected function getClassAnnotations(\ReflectionClass $class): array; + protected function getClassAnnotations(\ReflectionClass $class): array + { + $annotations = []; + + if (PHP_VERSION_ID >= 80000) { + $annotations = array_map( + static function (\ReflectionAttribute $attribute): object { + return $attribute->newInstance(); + }, + $class->getAttributes() + ); + } + + if (null !== $this->reader) { + $annotations = array_merge($annotations, $this->reader->getClassAnnotations($class)); + } + + return $annotations; + } /** * @return list */ - abstract protected function getMethodAnnotations(\ReflectionMethod $method): array; + protected function getMethodAnnotations(\ReflectionMethod $method): array + { + $annotations = []; + + if (PHP_VERSION_ID >= 80000) { + $annotations = array_map( + static function (\ReflectionAttribute $attribute): object { + return $attribute->newInstance(); + }, + $method->getAttributes() + ); + } + + if (null !== $this->reader) { + $annotations = array_merge($annotations, $this->reader->getMethodAnnotations($method)); + } + + return $annotations; + } /** * @return list */ - abstract protected function getPropertyAnnotations(\ReflectionProperty $property): array; + protected function getPropertyAnnotations(\ReflectionProperty $property): array + { + $annotations = []; + + if (PHP_VERSION_ID >= 80000) { + $annotations = array_map( + static function (\ReflectionAttribute $attribute): object { + return $attribute->newInstance(); + }, + $property->getAttributes() + ); + } + + if (null !== $this->reader) { + $annotations = array_merge($annotations, $this->reader->getPropertyAnnotations($property)); + } + + return $annotations; + } } diff --git a/src/Metadata/Driver/NullDriver.php b/src/Metadata/Driver/NullDriver.php index fbbf750f0..30bc387a4 100644 --- a/src/Metadata/Driver/NullDriver.php +++ b/src/Metadata/Driver/NullDriver.php @@ -5,11 +5,23 @@ namespace JMS\Serializer\Metadata\Driver; use JMS\Serializer\Metadata\ClassMetadata; +use JMS\Serializer\Metadata\PropertyMetadata; +use JMS\Serializer\Naming\PropertyNamingStrategyInterface; use Metadata\ClassMetadata as BaseClassMetadata; use Metadata\Driver\DriverInterface; class NullDriver implements DriverInterface { + /** + * @var PropertyNamingStrategyInterface + */ + private $namingStrategy; + + public function __construct(PropertyNamingStrategyInterface $namingStrategy) + { + $this->namingStrategy = $namingStrategy; + } + public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadata { $classMetadata = new ClassMetadata($name = $class->name); @@ -18,6 +30,20 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat $classMetadata->fileResources[] = $fileResource; } + foreach ($class->getProperties() as $property) { + if ($property->class !== $name || (isset($property->info) && $property->info['class'] !== $name)) { + continue; + } + + $propertyMetadata = new PropertyMetadata($name, $property->getName()); + + if (!$propertyMetadata->serializedName) { + $propertyMetadata->serializedName = $this->namingStrategy->translateName($propertyMetadata); + } + + $classMetadata->addPropertyMetadata($propertyMetadata); + } + return $classMetadata; } } diff --git a/tests/Fixtures/AuthorDeprecatedReadOnly.php b/tests/Fixtures/AuthorDeprecatedReadOnly.php index 3e31e1dc2..487c2de7a 100644 --- a/tests/Fixtures/AuthorDeprecatedReadOnly.php +++ b/tests/Fixtures/AuthorDeprecatedReadOnly.php @@ -19,9 +19,10 @@ class AuthorDeprecatedReadOnly { /** - * @JMS\Serializer\Annotation\ReadOnly + * @ReadOnly * @SerializedName("id") */ + #[\JMS\Serializer\Annotation\DeprecatedReadOnly] #[SerializedName(name: 'id')] private $id; diff --git a/tests/Fixtures/AuthorDeprecatedReadOnlyPerClass.php b/tests/Fixtures/AuthorDeprecatedReadOnlyPerClass.php index cff0e6e88..494929ed1 100644 --- a/tests/Fixtures/AuthorDeprecatedReadOnlyPerClass.php +++ b/tests/Fixtures/AuthorDeprecatedReadOnlyPerClass.php @@ -17,12 +17,14 @@ * @ReadOnly */ #[XmlRoot(name: 'author')] +#[\JMS\Serializer\Annotation\DeprecatedReadOnly] class AuthorDeprecatedReadOnlyPerClass { /** * @ReadOnly * @SerializedName("id") */ + #[\JMS\Serializer\Annotation\DeprecatedReadOnly] #[SerializedName(name: 'id')] private $id; @@ -41,6 +43,7 @@ public function __construct($id, $name) #[Type(name: 'string')] #[SerializedName(name: 'full_name')] #[Accessor(getter: 'getName')] + #[\JMS\Serializer\Annotation\DeprecatedReadOnly(readOnly: false)] private $name; public function getId() diff --git a/tests/Fixtures/AuthorList.php b/tests/Fixtures/AuthorList.php index 695beb569..23969b6ff 100644 --- a/tests/Fixtures/AuthorList.php +++ b/tests/Fixtures/AuthorList.php @@ -43,8 +43,7 @@ public function count(): int /** * @see ArrayAccess */ - #[\ReturnTypeWillChange] - public function offsetExists($offset) + public function offsetExists($offset): bool { return isset($this->authors[$offset]); } @@ -52,8 +51,7 @@ public function offsetExists($offset) /** * @see ArrayAccess */ - #[\ReturnTypeWillChange] - public function offsetGet($offset) + public function offsetGet($offset): ?Author { return $this->authors[$offset] ?? null; } @@ -61,8 +59,7 @@ public function offsetGet($offset) /** * @see ArrayAccess */ - #[\ReturnTypeWillChange] - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { if (null === $offset) { $this->authors[] = $value; @@ -74,8 +71,7 @@ public function offsetSet($offset, $value) /** * @see ArrayAccess */ - #[\ReturnTypeWillChange] - public function offsetUnset($offset) + public function offsetUnset($offset): void { unset($this->authors[$offset]); } diff --git a/tests/Fixtures/Doctrine/PersistendCollection/SmartPhone.php b/tests/Fixtures/Doctrine/PersistendCollection/SmartPhone.php index f6a5911a5..8622d5874 100644 --- a/tests/Fixtures/Doctrine/PersistendCollection/SmartPhone.php +++ b/tests/Fixtures/Doctrine/PersistendCollection/SmartPhone.php @@ -21,6 +21,7 @@ class SmartPhone * * @var string */ + #[Serializer\SerializedName(name: 'id')] #[Serializer\Type(name: 'string')] protected $id; @@ -40,6 +41,7 @@ class SmartPhone * * @var ArrayCollection */ + #[Serializer\SerializedName(name: 'applications')] #[Serializer\Type(name: 'ArrayCollection')] private $apps; diff --git a/tests/Fixtures/ObjectWithLifecycleCallbacks.php b/tests/Fixtures/ObjectWithLifecycleCallbacks.php index fb8359481..e991ae992 100644 --- a/tests/Fixtures/ObjectWithLifecycleCallbacks.php +++ b/tests/Fixtures/ObjectWithLifecycleCallbacks.php @@ -39,6 +39,7 @@ public function __construct($firstname = 'Foo', $lastname = 'Bar') /** * @PreSerialize */ + #[PreSerialize] private function prepareForSerialization() { $this->name = $this->firstname . ' ' . $this->lastname; @@ -47,6 +48,7 @@ private function prepareForSerialization() /** * @PostSerialize */ + #[PostSerialize] private function cleanUpAfterSerialization() { $this->name = null; @@ -55,6 +57,7 @@ private function cleanUpAfterSerialization() /** * @PostDeserialize */ + #[PostDeserialize] private function afterDeserialization() { [$this->firstname, $this->lastname] = explode(' ', $this->name); diff --git a/tests/Metadata/Driver/AnnotationDriverTest.php b/tests/Metadata/Driver/AnnotationDriverTest.php index 6ae989d90..b03b6ab57 100644 --- a/tests/Metadata/Driver/AnnotationDriverTest.php +++ b/tests/Metadata/Driver/AnnotationDriverTest.php @@ -6,13 +6,20 @@ use Doctrine\Common\Annotations\AnnotationReader; use JMS\Serializer\Metadata\Driver\AnnotationDriver; +use JMS\Serializer\Metadata\Driver\NullDriver; use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; +use Metadata\Driver\DriverChain; use Metadata\Driver\DriverInterface; class AnnotationDriverTest extends BaseAnnotationOrAttributeDriverTestCase { protected function getDriver(?string $subDir = null, bool $addUnderscoreDir = true): DriverInterface { - return new AnnotationDriver(new AnnotationReader(), new IdenticalPropertyNamingStrategy(), null, $this->getExpressionEvaluator()); + $namingStrategy = new IdenticalPropertyNamingStrategy(); + + return new DriverChain([ + new AnnotationDriver(new AnnotationReader(), $namingStrategy, null, $this->getExpressionEvaluator()), + new NullDriver($namingStrategy), + ]); } } diff --git a/tests/Metadata/Driver/AttributeDriverTest.php b/tests/Metadata/Driver/AttributeDriverTest.php index b2255b6da..5dcc3c4d8 100644 --- a/tests/Metadata/Driver/AttributeDriverTest.php +++ b/tests/Metadata/Driver/AttributeDriverTest.php @@ -5,7 +5,9 @@ namespace JMS\Serializer\Tests\Metadata\Driver; use JMS\Serializer\Metadata\Driver\AttributeDriver; +use JMS\Serializer\Metadata\Driver\NullDriver; use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; +use Metadata\Driver\DriverChain; use Metadata\Driver\DriverInterface; class AttributeDriverTest extends BaseAnnotationOrAttributeDriverTestCase @@ -21,6 +23,11 @@ protected function setUp(): void protected function getDriver(?string $subDir = null, bool $addUnderscoreDir = true): DriverInterface { - return new AttributeDriver(new IdenticalPropertyNamingStrategy(), null, $this->getExpressionEvaluator()); + $namingStrategy = new IdenticalPropertyNamingStrategy(); + + return new DriverChain([ + new AttributeDriver($namingStrategy, null, $this->getExpressionEvaluator()), + new NullDriver($namingStrategy), + ]); } } diff --git a/tests/Metadata/Driver/BaseAnnotationOrAttributeDriverTestCase.php b/tests/Metadata/Driver/BaseAnnotationOrAttributeDriverTestCase.php index 111da5737..686895727 100644 --- a/tests/Metadata/Driver/BaseAnnotationOrAttributeDriverTestCase.php +++ b/tests/Metadata/Driver/BaseAnnotationOrAttributeDriverTestCase.php @@ -5,12 +5,9 @@ namespace JMS\Serializer\Tests\Metadata\Driver; use JMS\Serializer\Tests\Fixtures\AllExcludedObject; -use Metadata\Driver\DriverInterface; abstract class BaseAnnotationOrAttributeDriverTestCase extends BaseDriverTestCase { - abstract protected function getDriver(?string $subDir = null, bool $addUnderscoreDir = true): DriverInterface; - public function testAllExcluded(): void { $a = new AllExcludedObject(); diff --git a/tests/Metadata/Driver/DocBlockDriverTest.php b/tests/Metadata/Driver/DocBlockDriverTest.php index e608e78a0..74ada8afa 100644 --- a/tests/Metadata/Driver/DocBlockDriverTest.php +++ b/tests/Metadata/Driver/DocBlockDriverTest.php @@ -8,6 +8,7 @@ use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\Driver\AnnotationDriver; use JMS\Serializer\Metadata\Driver\DocBlockDriver; +use JMS\Serializer\Metadata\Driver\NullDriver; use JMS\Serializer\Metadata\Driver\TypedPropertiesDriver; use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; use JMS\Serializer\Tests\Fixtures\DocBlockType\AlternativePHPDocsNames; @@ -47,19 +48,25 @@ use JMS\Serializer\Tests\Fixtures\DocBlockType\SingleClassFromGlobalNamespaceTypeHint; use JMS\Serializer\Tests\Fixtures\DocBlockType\UnionTypedDocBLockProperty; use JMS\Serializer\Tests\Fixtures\DocBlockType\VirtualPropertyGetter; +use Metadata\Driver\DriverChain; use PHPUnit\Framework\TestCase; class DocBlockDriverTest extends TestCase { private function resolve(string $classToResolve): ClassMetadata { + $namingStrategy = new IdenticalPropertyNamingStrategy(); + + $driver = new DriverChain([ + new AnnotationDriver(new AnnotationReader(), $namingStrategy), + new NullDriver($namingStrategy), + ]); + if (PHP_VERSION_ID > 70400) { - $baseDriver = new TypedPropertiesDriver(new AnnotationDriver(new AnnotationReader(), new IdenticalPropertyNamingStrategy())); - } else { - $baseDriver = new AnnotationDriver(new AnnotationReader(), new IdenticalPropertyNamingStrategy()); + $driver = new TypedPropertiesDriver($driver); } - $driver = new DocBlockDriver($baseDriver); + $driver = new DocBlockDriver($driver); $m = $driver->loadMetadataForClass(new \ReflectionClass($classToResolve)); self::assertNotNull($m); diff --git a/tests/Metadata/Driver/NullDriverTest.php b/tests/Metadata/Driver/NullDriverTest.php index 3a0c15f55..9c83dad17 100644 --- a/tests/Metadata/Driver/NullDriverTest.php +++ b/tests/Metadata/Driver/NullDriverTest.php @@ -6,13 +6,14 @@ use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\Driver\NullDriver; +use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; use PHPUnit\Framework\TestCase; class NullDriverTest extends TestCase { public function testReturnsValidMetadata() { - $driver = new NullDriver(); + $driver = new NullDriver(new IdenticalPropertyNamingStrategy()); $metadata = $driver->loadMetadataForClass(new \ReflectionClass('stdClass')); diff --git a/tests/Metadata/Driver/UnionTypedPropertiesDriverTest.php b/tests/Metadata/Driver/UnionTypedPropertiesDriverTest.php index f4d1363f6..c3a6357e3 100644 --- a/tests/Metadata/Driver/UnionTypedPropertiesDriverTest.php +++ b/tests/Metadata/Driver/UnionTypedPropertiesDriverTest.php @@ -7,9 +7,11 @@ use Doctrine\Common\Annotations\AnnotationReader; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\Driver\AnnotationDriver; +use JMS\Serializer\Metadata\Driver\NullDriver; use JMS\Serializer\Metadata\Driver\TypedPropertiesDriver; use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; use JMS\Serializer\Tests\Fixtures\TypedProperties\UnionTypedProperties; +use Metadata\Driver\DriverChain; use PHPUnit\Framework\TestCase; use ReflectionClass; @@ -34,8 +36,14 @@ public function testInferUnionTypesShouldResultInNoType() private function resolve(string $classToResolve): ClassMetadata { - $baseDriver = new AnnotationDriver(new AnnotationReader(), new IdenticalPropertyNamingStrategy()); - $driver = new TypedPropertiesDriver($baseDriver); + $namingStrategy = new IdenticalPropertyNamingStrategy(); + + $driver = new DriverChain([ + new AnnotationDriver(new AnnotationReader(), $namingStrategy), + new NullDriver($namingStrategy), + ]); + + $driver = new TypedPropertiesDriver($driver); $m = $driver->loadMetadataForClass(new ReflectionClass($classToResolve)); self::assertNotNull($m); diff --git a/tests/Serializer/GraphNavigatorTest.php b/tests/Serializer/GraphNavigatorTest.php index a06c07f94..8425be6d5 100644 --- a/tests/Serializer/GraphNavigatorTest.php +++ b/tests/Serializer/GraphNavigatorTest.php @@ -21,11 +21,13 @@ use JMS\Serializer\Handler\HandlerRegistry; use JMS\Serializer\Handler\SubscribingHandlerInterface; use JMS\Serializer\Metadata\Driver\AnnotationDriver; +use JMS\Serializer\Metadata\Driver\NullDriver; use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; use JMS\Serializer\SerializationContext; use JMS\Serializer\Visitor\DeserializationVisitorInterface; use JMS\Serializer\Visitor\SerializationVisitorInterface; use JMS\Serializer\VisitorInterface; +use Metadata\Driver\DriverChain; use Metadata\MetadataFactory; use PHPUnit\Framework\TestCase; @@ -243,7 +245,14 @@ protected function setUp(): void $this->handlerRegistry = new HandlerRegistry(); $this->objectConstructor = new UnserializeObjectConstructor(); - $this->metadataFactory = new MetadataFactory(new AnnotationDriver(new AnnotationReader(), new IdenticalPropertyNamingStrategy())); + $namingStrategy = new IdenticalPropertyNamingStrategy(); + + $driver = new DriverChain([ + new AnnotationDriver(new AnnotationReader(), $namingStrategy), + new NullDriver($namingStrategy), + ]); + + $this->metadataFactory = new MetadataFactory($driver); $this->serializationNavigator = new SerializationGraphNavigator($this->metadataFactory, $this->handlerRegistry, $this->accessor, $this->dispatcher); $this->serializationNavigator->initialize($this->serializationVisitor, $this->context); From 0a8d24187115a194d5ea10f0cf42cc03cceeba59 Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Sun, 30 Jul 2023 14:57:22 +0200 Subject: [PATCH 02/38] chore(composer): Update doctrine code standards to 12.x --- composer.json | 2 +- phpcs.xml.dist | 13 ++++++++++++- src/GraphNavigator/SerializationGraphNavigator.php | 1 + src/Handler/FormErrorHandler.php | 2 +- src/Handler/LazyHandlerRegistry.php | 2 ++ src/JsonDeserializationStrictVisitor.php | 1 + src/Metadata/ClassMetadata.php | 1 + .../Driver/DocBlockDriver/DocBlockTypeResolver.php | 1 + src/Metadata/Driver/XmlDriver.php | 1 + src/Twig/SerializerExtension.php | 1 + tests/Benchmark/Memory/JsonMultipleRunBench.php | 1 + tests/Benchmark/Memory/JsonSingleRunBench.php | 1 + tests/Benchmark/Memory/XmlMutlipleRunBench.php | 1 + tests/Benchmark/Memory/XmlSingleRunBench.php | 1 + tests/Fixtures/AuthorDeprecatedReadOnly.php | 1 - .../Discriminator/Serialization/ExtendedUser.php | 1 + tests/Fixtures/Discriminator/Serialization/User.php | 1 + .../CollectionOfInterfacesFromGlobalNamespace.php | 5 ++++- tests/Fixtures/Doctrine/Entity/Author.php | 3 ++- tests/Fixtures/Doctrine/Entity/AuthorExcludedId.php | 3 ++- tests/Fixtures/Doctrine/Entity/BlogPost.php | 4 +++- tests/Fixtures/Doctrine/Entity/Comment.php | 3 ++- .../Doctrine/SingleTableInheritance/Clazz.php | 6 +++++- .../SingleTableInheritance/Organization.php | 6 +++++- .../Doctrine/SingleTableInheritance/Person.php | 6 +++++- tests/Fixtures/GetSetObject.php | 5 ++++- tests/Fixtures/ObjectWithIntListAndIntMap.php | 10 ++++++++-- tests/Fixtures/ObjectWithNamespacesAndList.php | 1 - tests/Fixtures/SimpleInternalObject.php | 1 + 29 files changed, 69 insertions(+), 16 deletions(-) diff --git a/composer.json b/composer.json index beaa350cd..13dc0c866 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ }, "require-dev": { "ext-pdo_sqlite": "*", - "doctrine/coding-standard": "^9.0", + "doctrine/coding-standard": "^12.0", "doctrine/orm": "~2.1", "doctrine/persistence": "^1.3.3|^2.0|^3.0", "doctrine/phpcr-odm": "^1.3|^2.0", diff --git a/phpcs.xml.dist b/phpcs.xml.dist index bc27fa482..95a364845 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -37,7 +37,6 @@ - @@ -60,6 +59,18 @@ + + + + + + + + + + + + diff --git a/src/GraphNavigator/SerializationGraphNavigator.php b/src/GraphNavigator/SerializationGraphNavigator.php index 975788b73..1de6e3bb7 100644 --- a/src/GraphNavigator/SerializationGraphNavigator.php +++ b/src/GraphNavigator/SerializationGraphNavigator.php @@ -104,6 +104,7 @@ public function initialize(VisitorInterface $visitor, Context $context): void assert($context instanceof SerializationContext); parent::initialize($visitor, $context); + $this->shouldSerializeNull = $context->shouldSerializeNull(); } diff --git a/src/Handler/FormErrorHandler.php b/src/Handler/FormErrorHandler.php index dde738d0a..48a8d8a0a 100644 --- a/src/Handler/FormErrorHandler.php +++ b/src/Handler/FormErrorHandler.php @@ -141,7 +141,7 @@ private function getErrorMessage(FormError $error): ?string private function convertFormToArray(SerializationVisitorInterface $visitor, FormInterface $data): \ArrayObject { - /** @var \ArrayObject{errors?: string[], children?: array} $form */ + /** @var \ArrayObject{errors?:array,children?:array} $form */ $form = new \ArrayObject(); $errors = []; foreach ($data->getErrors() as $error) { diff --git a/src/Handler/LazyHandlerRegistry.php b/src/Handler/LazyHandlerRegistry.php index a569dca43..7914aeaf3 100644 --- a/src/Handler/LazyHandlerRegistry.php +++ b/src/Handler/LazyHandlerRegistry.php @@ -31,6 +31,7 @@ public function __construct($container, array $handlers = []) } parent::__construct($handlers); + $this->container = $container; } @@ -40,6 +41,7 @@ public function __construct($container, array $handlers = []) public function registerHandler(int $direction, string $typeName, string $format, $handler): void { parent::registerHandler($direction, $typeName, $format, $handler); + unset($this->initializedHandlers[$direction][$typeName][$format]); } diff --git a/src/JsonDeserializationStrictVisitor.php b/src/JsonDeserializationStrictVisitor.php index 83299e3c5..3c4e69a85 100644 --- a/src/JsonDeserializationStrictVisitor.php +++ b/src/JsonDeserializationStrictVisitor.php @@ -29,6 +29,7 @@ public function __construct( public function setNavigator(GraphNavigatorInterface $navigator): void { parent::setNavigator($navigator); + $this->wrappedDeserializationVisitor->setNavigator($navigator); } diff --git a/src/Metadata/ClassMetadata.php b/src/Metadata/ClassMetadata.php index c8e90b913..805ec294b 100644 --- a/src/Metadata/ClassMetadata.php +++ b/src/Metadata/ClassMetadata.php @@ -185,6 +185,7 @@ public function setAccessorOrder(string $order, array $customOrder = []): void public function addPropertyMetadata(BasePropertyMetadata $metadata): void { parent::addPropertyMetadata($metadata); + $this->sortProperties(); if ($metadata instanceof PropertyMetadata && $metadata->excludeIf) { $this->usingExpression = true; diff --git a/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php b/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php index 0a3d515e5..0b49017ac 100644 --- a/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php +++ b/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php @@ -26,6 +26,7 @@ final class DocBlockTypeResolver { /** resolve single use statements */ private const SINGLE_USE_STATEMENTS_REGEX = '/^[^\S\r\n]*use[\s]*([^;\n]*)[\s]*;$/m'; + /** resolve group use statements */ private const GROUP_USE_STATEMENTS_REGEX = '/^[^\S\r\n]*use[[\s]*([^;\n]*)[\s]*{([a-zA-Z0-9\s\n\r,]*)};$/m'; private const GLOBAL_NAMESPACE_PREFIX = '\\'; diff --git a/src/Metadata/Driver/XmlDriver.php b/src/Metadata/Driver/XmlDriver.php index 2d8cca3e3..dd5436709 100644 --- a/src/Metadata/Driver/XmlDriver.php +++ b/src/Metadata/Driver/XmlDriver.php @@ -39,6 +39,7 @@ class XmlDriver extends AbstractFileDriver public function __construct(FileLocatorInterface $locator, PropertyNamingStrategyInterface $namingStrategy, ?ParserInterface $typeParser = null, ?CompilableExpressionEvaluatorInterface $expressionEvaluator = null) { parent::__construct($locator); + $this->typeParser = $typeParser ?? new Parser(); $this->namingStrategy = $namingStrategy; $this->expressionEvaluator = $expressionEvaluator; diff --git a/src/Twig/SerializerExtension.php b/src/Twig/SerializerExtension.php index 9a45ca36c..d769517f8 100644 --- a/src/Twig/SerializerExtension.php +++ b/src/Twig/SerializerExtension.php @@ -24,6 +24,7 @@ class SerializerExtension extends SerializerBaseExtension public function __construct(SerializerInterface $serializer, string $serializationFunctionsPrefix = '') { $this->serializer = $serializer; + parent::__construct($serializationFunctionsPrefix); } diff --git a/tests/Benchmark/Memory/JsonMultipleRunBench.php b/tests/Benchmark/Memory/JsonMultipleRunBench.php index f6a3e713e..3a637adc4 100644 --- a/tests/Benchmark/Memory/JsonMultipleRunBench.php +++ b/tests/Benchmark/Memory/JsonMultipleRunBench.php @@ -9,6 +9,7 @@ class JsonMultipleRunBench extends JsonSingleRunBench public function __construct() { $this->iterations = 10000; + parent::__construct(); } } diff --git a/tests/Benchmark/Memory/JsonSingleRunBench.php b/tests/Benchmark/Memory/JsonSingleRunBench.php index 91b6f9207..72ac96f54 100644 --- a/tests/Benchmark/Memory/JsonSingleRunBench.php +++ b/tests/Benchmark/Memory/JsonSingleRunBench.php @@ -12,6 +12,7 @@ public function __construct() { $this->amountOfComments = 1; $this->amountOfPosts = 1; + parent::__construct(); } diff --git a/tests/Benchmark/Memory/XmlMutlipleRunBench.php b/tests/Benchmark/Memory/XmlMutlipleRunBench.php index 152f16068..816bd7405 100644 --- a/tests/Benchmark/Memory/XmlMutlipleRunBench.php +++ b/tests/Benchmark/Memory/XmlMutlipleRunBench.php @@ -9,6 +9,7 @@ class XmlMutlipleRunBench extends XmlSingleRunBench public function __construct() { $this->iterations = 10000; + parent::__construct(); } diff --git a/tests/Benchmark/Memory/XmlSingleRunBench.php b/tests/Benchmark/Memory/XmlSingleRunBench.php index 8de6c8f0e..4e1f5df59 100644 --- a/tests/Benchmark/Memory/XmlSingleRunBench.php +++ b/tests/Benchmark/Memory/XmlSingleRunBench.php @@ -12,6 +12,7 @@ public function __construct() { $this->amountOfComments = 1; $this->amountOfPosts = 1; + parent::__construct(); } diff --git a/tests/Fixtures/AuthorDeprecatedReadOnly.php b/tests/Fixtures/AuthorDeprecatedReadOnly.php index 3e31e1dc2..50d213580 100644 --- a/tests/Fixtures/AuthorDeprecatedReadOnly.php +++ b/tests/Fixtures/AuthorDeprecatedReadOnly.php @@ -5,7 +5,6 @@ namespace JMS\Serializer\Tests\Fixtures; use JMS\Serializer\Annotation\Accessor; -use JMS\Serializer\Annotation\ReadOnly; use JMS\Serializer\Annotation\SerializedName; use JMS\Serializer\Annotation\Type; use JMS\Serializer\Annotation\XmlRoot; diff --git a/tests/Fixtures/Discriminator/Serialization/ExtendedUser.php b/tests/Fixtures/Discriminator/Serialization/ExtendedUser.php index e7f4e2a75..bfdbc4ef8 100644 --- a/tests/Fixtures/Discriminator/Serialization/ExtendedUser.php +++ b/tests/Fixtures/Discriminator/Serialization/ExtendedUser.php @@ -20,6 +20,7 @@ class ExtendedUser extends User public function __construct($id, $name, $description, $extendAttribute) { parent::__construct($id, $name, $description); + $this->extendAttribute = $extendAttribute; } } diff --git a/tests/Fixtures/Discriminator/Serialization/User.php b/tests/Fixtures/Discriminator/Serialization/User.php index 89efb92da..9b74931b8 100644 --- a/tests/Fixtures/Discriminator/Serialization/User.php +++ b/tests/Fixtures/Discriminator/Serialization/User.php @@ -38,6 +38,7 @@ class User extends Entity public function __construct(int $id, string $name, string $description) { parent::__construct($id); + $this->name = $name; $this->description = $description; } diff --git a/tests/Fixtures/DocBlockType/Collection/CollectionOfInterfacesFromGlobalNamespace.php b/tests/Fixtures/DocBlockType/Collection/CollectionOfInterfacesFromGlobalNamespace.php index a166a623f..5736da14d 100644 --- a/tests/Fixtures/DocBlockType/Collection/CollectionOfInterfacesFromGlobalNamespace.php +++ b/tests/Fixtures/DocBlockType/Collection/CollectionOfInterfacesFromGlobalNamespace.php @@ -4,11 +4,14 @@ namespace JMS\Serializer\Tests\Fixtures\DocBlockType\Collection; +use JMS\Serializer\Tests\Fixtures\DocBlockType\Collection\Details\ProductColor; + class CollectionOfInterfacesFromGlobalNamespace { /** * phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName - * @var \JMS\Serializer\Tests\Fixtures\DocBlockType\Collection\Details\ProductColor[] + * + * @var ProductColor[] */ public array $productColors; } diff --git a/tests/Fixtures/Doctrine/Entity/Author.php b/tests/Fixtures/Doctrine/Entity/Author.php index 6d2c4ef78..5c04d19ee 100644 --- a/tests/Fixtures/Doctrine/Entity/Author.php +++ b/tests/Fixtures/Doctrine/Entity/Author.php @@ -12,7 +12,8 @@ class Author { /** - * @ORM\Id @ORM\Column(type="integer") + * @ORM\Id + * @ORM\Column(type="integer") * * @Groups({"id_group"}) */ diff --git a/tests/Fixtures/Doctrine/Entity/AuthorExcludedId.php b/tests/Fixtures/Doctrine/Entity/AuthorExcludedId.php index 8a87003b3..215160554 100644 --- a/tests/Fixtures/Doctrine/Entity/AuthorExcludedId.php +++ b/tests/Fixtures/Doctrine/Entity/AuthorExcludedId.php @@ -12,7 +12,8 @@ class AuthorExcludedId { /** - * @ORM\Id @ORM\Column(type="integer") + * @ORM\Id + * @ORM\Column(type="integer") * * @Exclude */ diff --git a/tests/Fixtures/Doctrine/Entity/BlogPost.php b/tests/Fixtures/Doctrine/Entity/BlogPost.php index 43ffcb5c6..d49b7e903 100644 --- a/tests/Fixtures/Doctrine/Entity/BlogPost.php +++ b/tests/Fixtures/Doctrine/Entity/BlogPost.php @@ -23,7 +23,9 @@ class BlogPost { /** - * @ORM\Id @ORM\Column(type="integer") @ORM\GeneratedValue(strategy="AUTO") + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; diff --git a/tests/Fixtures/Doctrine/Entity/Comment.php b/tests/Fixtures/Doctrine/Entity/Comment.php index a8fad7e41..402685f70 100644 --- a/tests/Fixtures/Doctrine/Entity/Comment.php +++ b/tests/Fixtures/Doctrine/Entity/Comment.php @@ -11,7 +11,8 @@ class Comment { /** - * @ORM\Id @ORM\Column(type="integer") + * @ORM\Id + * @ORM\Column(type="integer") */ protected $id; diff --git a/tests/Fixtures/Doctrine/SingleTableInheritance/Clazz.php b/tests/Fixtures/Doctrine/SingleTableInheritance/Clazz.php index 4a994d744..001f9223e 100644 --- a/tests/Fixtures/Doctrine/SingleTableInheritance/Clazz.php +++ b/tests/Fixtures/Doctrine/SingleTableInheritance/Clazz.php @@ -12,7 +12,11 @@ */ class Clazz extends AbstractModel { - /** @ORM\Id @ORM\GeneratedValue(strategy = "AUTO") @ORM\Column(type = "integer") */ + /** + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue(strategy="AUTO") + */ private $id; /** @ORM\ManyToOne(targetEntity = "JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Teacher") */ diff --git a/tests/Fixtures/Doctrine/SingleTableInheritance/Organization.php b/tests/Fixtures/Doctrine/SingleTableInheritance/Organization.php index 0309bead2..8c2edb809 100644 --- a/tests/Fixtures/Doctrine/SingleTableInheritance/Organization.php +++ b/tests/Fixtures/Doctrine/SingleTableInheritance/Organization.php @@ -16,6 +16,10 @@ */ abstract class Organization { - /** @ORM\Id @ORM\GeneratedValue(strategy = "AUTO") @ORM\Column(type = "integer") */ + /** + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue(strategy="AUTO") + */ private $id; } diff --git a/tests/Fixtures/Doctrine/SingleTableInheritance/Person.php b/tests/Fixtures/Doctrine/SingleTableInheritance/Person.php index 107ad52b5..b10e33ee1 100644 --- a/tests/Fixtures/Doctrine/SingleTableInheritance/Person.php +++ b/tests/Fixtures/Doctrine/SingleTableInheritance/Person.php @@ -17,6 +17,10 @@ */ abstract class Person extends AbstractModel { - /** @ORM\Id @ORM\GeneratedValue(strategy = "AUTO") @ORM\Column(type = "integer") */ + /** + * @ORM\Id + * @ORM\Column(type = "integer") + * @ORM\GeneratedValue(strategy = "AUTO") + */ private $id; } diff --git a/tests/Fixtures/GetSetObject.php b/tests/Fixtures/GetSetObject.php index ba4c48efa..088f9758e 100644 --- a/tests/Fixtures/GetSetObject.php +++ b/tests/Fixtures/GetSetObject.php @@ -13,7 +13,10 @@ #[AccessType(type: 'public_method')] class GetSetObject { - /** @AccessType("property") @Type("integer") */ + /** + * @AccessType("property") + * @AccessType("property") + @Type("integer") */ #[AccessType(type: 'property')] #[Type(name: 'integer')] private $id = 1; diff --git a/tests/Fixtures/ObjectWithIntListAndIntMap.php b/tests/Fixtures/ObjectWithIntListAndIntMap.php index 9cf6fe28a..9c0e804de 100644 --- a/tests/Fixtures/ObjectWithIntListAndIntMap.php +++ b/tests/Fixtures/ObjectWithIntListAndIntMap.php @@ -8,12 +8,18 @@ class ObjectWithIntListAndIntMap { - /** @Serializer\Type("array") @Serializer\XmlList */ + /** + * @Serializer\Type("array") + * @Serializer\Type("array") + @Serializer\XmlList */ #[Serializer\Type(name: 'array')] #[Serializer\XmlList] private $list; - /** @Serializer\Type("array") @Serializer\XmlMap */ + /** + * @Serializer\Type("array") + * @Serializer\Type("array") + @Serializer\XmlMap */ #[Serializer\Type(name: 'array')] #[Serializer\XmlMap] private $map; diff --git a/tests/Fixtures/ObjectWithNamespacesAndList.php b/tests/Fixtures/ObjectWithNamespacesAndList.php index ff069eed2..a936a7665 100644 --- a/tests/Fixtures/ObjectWithNamespacesAndList.php +++ b/tests/Fixtures/ObjectWithNamespacesAndList.php @@ -114,7 +114,6 @@ class ObjectWithNamespacesAndList #[Type(name: 'array')] #[SerializedName(name: 'phones')] #[XmlList(entry: 'phone', inline: false)] - public $phonesAlternativeD; /** * @Type("array") diff --git a/tests/Fixtures/SimpleInternalObject.php b/tests/Fixtures/SimpleInternalObject.php index 638a6a45b..01a847e1d 100644 --- a/tests/Fixtures/SimpleInternalObject.php +++ b/tests/Fixtures/SimpleInternalObject.php @@ -19,6 +19,7 @@ class SimpleInternalObject extends \Exception public function __construct($foo, $bar) { parent::__construct($foo); + $this->bar = $bar; } } From 7befd1d4d0475bf80da4f97491504a58084f8373 Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Tue, 27 Jun 2023 10:51:00 -0400 Subject: [PATCH 03/38] Only add the YamlDriver to the chain when symfony/yaml is installed --- src/Builder/DefaultDriverFactory.php | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Builder/DefaultDriverFactory.php b/src/Builder/DefaultDriverFactory.php index 5b53daf68..041ca4a71 100644 --- a/src/Builder/DefaultDriverFactory.php +++ b/src/Builder/DefaultDriverFactory.php @@ -19,6 +19,7 @@ use Metadata\Driver\DriverChain; use Metadata\Driver\DriverInterface; use Metadata\Driver\FileLocator; +use Symfony\Component\Yaml\Yaml; final class DefaultDriverFactory implements DriverFactoryInterface { @@ -56,19 +57,27 @@ public function enableEnumSupport(bool $enableEnumSupport = true): void public function createDriver(array $metadataDirs, Reader $annotationReader): DriverInterface { - $driver = new DriverChain([ - new AnnotationOrAttributeDriver($this->propertyNamingStrategy, $this->typeParser, $this->expressionEvaluator, $annotationReader), - ]); + /* + * Build the sorted list of metadata drivers based on the environment. The final order should be: + * + * - YAML Driver + * - XML Driver + * - Annotations/Attributes Driver + * - Null (Fallback) Driver + */ + $metadataDrivers = [new AnnotationOrAttributeDriver($this->propertyNamingStrategy, $this->typeParser, $this->expressionEvaluator, $annotationReader)]; if (!empty($metadataDirs)) { $fileLocator = new FileLocator($metadataDirs); - $driver = new DriverChain([ - new YamlDriver($fileLocator, $this->propertyNamingStrategy, $this->typeParser, $this->expressionEvaluator), - new XmlDriver($fileLocator, $this->propertyNamingStrategy, $this->typeParser, $this->expressionEvaluator), - $driver, - ]); + + array_unshift($metadataDrivers, new XmlDriver($fileLocator, $this->propertyNamingStrategy, $this->typeParser, $this->expressionEvaluator)); + + if (class_exists(Yaml::class)) { + array_unshift($metadataDrivers, new YamlDriver($fileLocator, $this->propertyNamingStrategy, $this->typeParser, $this->expressionEvaluator)); + } } + $driver = new DriverChain($metadataDrivers); $driver->addDriver(new NullDriver($this->propertyNamingStrategy)); if ($this->enableEnumSupport) { From e2609b02b3911059b6ee1ff07dd71fd521143a8c Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Thu, 3 Aug 2023 09:26:03 -0400 Subject: [PATCH 04/38] Fix CS issues --- tests/Fixtures/AuthorDeprecatedReadOnly.php | 5 +++-- tests/Fixtures/AuthorDeprecatedReadOnlyPerClass.php | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/Fixtures/AuthorDeprecatedReadOnly.php b/tests/Fixtures/AuthorDeprecatedReadOnly.php index 869e0e487..5bab54a6c 100644 --- a/tests/Fixtures/AuthorDeprecatedReadOnly.php +++ b/tests/Fixtures/AuthorDeprecatedReadOnly.php @@ -5,6 +5,7 @@ namespace JMS\Serializer\Tests\Fixtures; use JMS\Serializer\Annotation\Accessor; +use JMS\Serializer\Annotation\DeprecatedReadOnly; use JMS\Serializer\Annotation\SerializedName; use JMS\Serializer\Annotation\Type; use JMS\Serializer\Annotation\XmlRoot; @@ -18,10 +19,10 @@ class AuthorDeprecatedReadOnly { /** - * @ReadOnly + * @JMS\Serializer\Annotation\ReadOnly * @SerializedName("id") */ - #[\JMS\Serializer\Annotation\DeprecatedReadOnly] + #[DeprecatedReadOnly] #[SerializedName(name: 'id')] private $id; diff --git a/tests/Fixtures/AuthorDeprecatedReadOnlyPerClass.php b/tests/Fixtures/AuthorDeprecatedReadOnlyPerClass.php index 494929ed1..08de1e541 100644 --- a/tests/Fixtures/AuthorDeprecatedReadOnlyPerClass.php +++ b/tests/Fixtures/AuthorDeprecatedReadOnlyPerClass.php @@ -5,6 +5,7 @@ namespace JMS\Serializer\Tests\Fixtures; use JMS\Serializer\Annotation\Accessor; +use JMS\Serializer\Annotation\DeprecatedReadOnly; use JMS\Serializer\Annotation\ReadOnly; use JMS\Serializer\Annotation\SerializedName; use JMS\Serializer\Annotation\Type; @@ -17,14 +18,14 @@ * @ReadOnly */ #[XmlRoot(name: 'author')] -#[\JMS\Serializer\Annotation\DeprecatedReadOnly] +#[DeprecatedReadOnly] class AuthorDeprecatedReadOnlyPerClass { /** * @ReadOnly * @SerializedName("id") */ - #[\JMS\Serializer\Annotation\DeprecatedReadOnly] + #[DeprecatedReadOnly] #[SerializedName(name: 'id')] private $id; @@ -43,7 +44,7 @@ public function __construct($id, $name) #[Type(name: 'string')] #[SerializedName(name: 'full_name')] #[Accessor(getter: 'getName')] - #[\JMS\Serializer\Annotation\DeprecatedReadOnly(readOnly: false)] + #[DeprecatedReadOnly(readOnly: false)] private $name; public function getId() From 9570d11af9c8390929412617c2a20700a2d23731 Mon Sep 17 00:00:00 2001 From: Asmir Mustafic Date: Thu, 3 Aug 2023 16:22:48 +0200 Subject: [PATCH 05/38] do not return null when no annotations or attributes are found by the driver, this is to minimize possible bc breaks --- src/Metadata/Driver/AnnotationDriver.php | 3 +++ src/Metadata/Driver/AnnotationOrAttributeDriver.php | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Metadata/Driver/AnnotationDriver.php b/src/Metadata/Driver/AnnotationDriver.php index d2fbb9138..942b339ca 100644 --- a/src/Metadata/Driver/AnnotationDriver.php +++ b/src/Metadata/Driver/AnnotationDriver.php @@ -9,6 +9,9 @@ use JMS\Serializer\Naming\PropertyNamingStrategyInterface; use JMS\Serializer\Type\ParserInterface; +/** + * @deprecated + */ class AnnotationDriver extends AnnotationOrAttributeDriver { /** diff --git a/src/Metadata/Driver/AnnotationOrAttributeDriver.php b/src/Metadata/Driver/AnnotationOrAttributeDriver.php index 8b506add4..9f6f514c5 100644 --- a/src/Metadata/Driver/AnnotationOrAttributeDriver.php +++ b/src/Metadata/Driver/AnnotationOrAttributeDriver.php @@ -290,7 +290,8 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat } if (!$configured) { - return null; + // return null; + // uncomment the above line afetr a couple of months } return $classMetadata; From 7bee05379d3f34ba50a5a774d31f37a1aa43f1eb Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Thu, 3 Aug 2023 16:26:00 +0200 Subject: [PATCH 06/38] fix(test): Fix tests for doctrine 2.16 --- tests/Serializer/Doctrine/IntegrationTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Serializer/Doctrine/IntegrationTest.php b/tests/Serializer/Doctrine/IntegrationTest.php index 579e52b3b..c8f5ae5ae 100644 --- a/tests/Serializer/Doctrine/IntegrationTest.php +++ b/tests/Serializer/Doctrine/IntegrationTest.php @@ -67,9 +67,10 @@ public function testDiscriminatorIsInferredFromDoctrine() $teacher = new Teacher(); $class = new Clazz($teacher, [$student1, $student2]); + $em->persist($teacher); + $em->flush(); $em->persist($student1); $em->persist($student2); - $em->persist($teacher); $em->persist($class); $em->flush(); $em->clear(); From e349907330c7c5a8de81bac30a7f9cc730c11c16 Mon Sep 17 00:00:00 2001 From: Ross Riley Date: Wed, 13 Sep 2023 11:22:56 +0800 Subject: [PATCH 07/38] change the order of instantiation checks --- .../Driver/DocBlockDriver/DocBlockTypeResolver.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php b/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php index 0b49017ac..f3ff04645 100644 --- a/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php +++ b/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php @@ -249,10 +249,6 @@ private function resolveTypeFromTypeNode(TypeNode $typeNode, $reflector): string */ private function expandClassNameUsingUseStatements(string $typeHint, \ReflectionClass $declaringClass, $reflector): string { - if ($this->isClassOrInterface($typeHint)) { - return $typeHint; - } - $expandedClassName = $declaringClass->getNamespaceName() . '\\' . $typeHint; if ($this->isClassOrInterface($expandedClassName)) { return $expandedClassName; @@ -282,6 +278,10 @@ private function expandClassNameUsingUseStatements(string $typeHint, \Reflection } } + if ($this->isClassOrInterface($typeHint)) { + return $typeHint; + } + throw new \InvalidArgumentException(sprintf("Can't use incorrect type %s for collection in %s:%s", $typeHint, $declaringClass->getName(), $reflector->getName())); } From cc2bd94ef5180691401231e61433a6f10248fa6c Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Mon, 18 Sep 2023 10:07:12 -0400 Subject: [PATCH 08/38] Allow Symfony 7 in dev dependencies --- composer.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 13dc0c866..c25a1e4fc 100644 --- a/composer.json +++ b/composer.json @@ -41,14 +41,14 @@ "phpstan/phpstan": "^1.0.2", "phpunit/phpunit": "^8.5.21||^9.0||^10.0", "psr/container": "^1.0|^2.0", - "symfony/dependency-injection": "^3.0|^4.0|^5.0|^6.0", - "symfony/expression-language": "^3.2|^4.0|^5.0|^6.0", - "symfony/filesystem": "^3.0|^4.0|^5.0|^6.0", - "symfony/form": "^3.0|^4.0|^5.0|^6.0", - "symfony/translation": "^3.0|^4.0|^5.0|^6.0", - "symfony/uid": "^5.1|^6.0", - "symfony/validator": "^3.1.9|^4.0|^5.0|^6.0", - "symfony/yaml": "^3.3|^4.0|^5.0|^6.0", + "symfony/dependency-injection": "^3.0|^4.0|^5.0|^6.0|^7.0", + "symfony/expression-language": "^3.2|^4.0|^5.0|^6.0|^7.0", + "symfony/filesystem": "^3.0|^4.0|^5.0|^6.0|^7.0", + "symfony/form": "^3.0|^4.0|^5.0|^6.0|^7.0", + "symfony/translation": "^3.0|^4.0|^5.0|^6.0|^7.0", + "symfony/uid": "^5.1|^6.0|^7.0", + "symfony/validator": "^3.1.9|^4.0|^5.0|^6.0|^7.0", + "symfony/yaml": "^3.3|^4.0|^5.0|^6.0|^7.0", "twig/twig": "~1.34|~2.4|^3.0" }, "autoload": { From 211080b78a7edd33616f461feb7ed3761f2ca685 Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Thu, 28 Sep 2023 23:14:27 +0200 Subject: [PATCH 09/38] feat(ci): Run tests with dev dependencies --- .github/workflows/ci.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7156cfb67..dd6c11f95 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,6 +24,10 @@ jobs: dependencies: - "lowest" - "highest" + include: + - php-version: '8.3' + dependencies: 'highest' + composer-stability: 'dev' env: JMS_TESTS_SHOW_DEPRECATIONS: 1 @@ -37,6 +41,10 @@ jobs: with: php-version: ${{ matrix.php-version }} + - name: Composer config + if: ${{ matrix.composer-stability }} + run: composer config minimum-stability ${{ matrix.composer-stability }} + - name: "Install dependencies with Composer" uses: "ramsey/composer-install@v1" with: From e2e11af10dec2398022ed9a0828337fc7110b290 Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Wed, 11 Oct 2023 21:51:12 -0400 Subject: [PATCH 10/38] Run the ORM tests using an attribute driver when able --- .../Doctrine/Embeddable/BlogPostSeo.php | 3 +++ .../Embeddable/BlogPostWithEmbedded.php | 6 ++++++ tests/Fixtures/Doctrine/Entity/Author.php | 7 +++++++ .../Doctrine/Entity/AuthorExcludedId.php | 5 +++++ tests/Fixtures/Doctrine/Entity/BlogPost.php | 15 +++++++++++++- tests/Fixtures/Doctrine/Entity/Comment.php | 9 ++++++++- .../Doctrine/IdentityFields/Server.php | 7 +++++++ .../Doctrine/PersistendCollection/App.php | 8 ++++++++ .../PersistendCollection/SmartPhone.php | 6 ++++++ .../Doctrine/SingleTableInheritance/Clazz.php | 7 +++++++ .../SingleTableInheritance/Organization.php | 8 ++++++++ .../SingleTableInheritance/Person.php | 8 ++++++++ .../SingleTableInheritance/School.php | 1 + .../SingleTableInheritance/Student.php | 1 + .../SingleTableInheritance/Teacher.php | 1 + tests/Metadata/Driver/DoctrineDriverTest.php | 16 +++++++++++---- tests/Serializer/Doctrine/IntegrationTest.php | 15 +++++++++++--- .../Doctrine/ObjectConstructorTest.php | 20 ++++++++++++++----- 18 files changed, 129 insertions(+), 14 deletions(-) diff --git a/tests/Fixtures/Doctrine/Embeddable/BlogPostSeo.php b/tests/Fixtures/Doctrine/Embeddable/BlogPostSeo.php index ed24ab396..297c4c927 100644 --- a/tests/Fixtures/Doctrine/Embeddable/BlogPostSeo.php +++ b/tests/Fixtures/Doctrine/Embeddable/BlogPostSeo.php @@ -4,11 +4,13 @@ namespace JMS\Serializer\Tests\Fixtures\Doctrine\Embeddable; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Embeddable() */ +#[ORM\Embeddable] class BlogPostSeo { /** @@ -16,5 +18,6 @@ class BlogPostSeo * * @var string */ + #[ORM\Column(type: Types::STRING, name: 'meta_title')] private $metaTitle; } diff --git a/tests/Fixtures/Doctrine/Embeddable/BlogPostWithEmbedded.php b/tests/Fixtures/Doctrine/Embeddable/BlogPostWithEmbedded.php index 5f6868603..036276584 100644 --- a/tests/Fixtures/Doctrine/Embeddable/BlogPostWithEmbedded.php +++ b/tests/Fixtures/Doctrine/Embeddable/BlogPostWithEmbedded.php @@ -4,11 +4,13 @@ namespace JMS\Serializer\Tests\Fixtures\Doctrine\Embeddable; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ +#[ORM\Entity] class BlogPostWithEmbedded { /** @@ -16,10 +18,14 @@ class BlogPostWithEmbedded * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Id] + #[ORM\Column(type: Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] protected $id; /** * @ORM\Embedded(class="BlogPostSeo", columnPrefix="seo_") */ + #[ORM\Embedded(class: BlogPostSeo::class, columnPrefix: 'seo_')] private $seo; } diff --git a/tests/Fixtures/Doctrine/Entity/Author.php b/tests/Fixtures/Doctrine/Entity/Author.php index 5c04d19ee..468cbc013 100644 --- a/tests/Fixtures/Doctrine/Entity/Author.php +++ b/tests/Fixtures/Doctrine/Entity/Author.php @@ -4,11 +4,13 @@ namespace JMS\Serializer\Tests\Fixtures\Doctrine\Entity; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation\Groups; use JMS\Serializer\Annotation\SerializedName; /** @ORM\Entity */ +#[ORM\Entity] class Author { /** @@ -17,6 +19,9 @@ class Author * * @Groups({"id_group"}) */ + #[ORM\Id] + #[ORM\Column(type: Types::INTEGER)] + #[Groups(groups: ['id_group'])] protected $id; /** @@ -24,6 +29,8 @@ class Author * * @SerializedName("full_name") */ + #[ORM\Column(type: Types::STRING)] + #[SerializedName(name: 'full_name')] private $name; public function __construct($name, $id = null) diff --git a/tests/Fixtures/Doctrine/Entity/AuthorExcludedId.php b/tests/Fixtures/Doctrine/Entity/AuthorExcludedId.php index 215160554..f3617af7d 100644 --- a/tests/Fixtures/Doctrine/Entity/AuthorExcludedId.php +++ b/tests/Fixtures/Doctrine/Entity/AuthorExcludedId.php @@ -4,11 +4,13 @@ namespace JMS\Serializer\Tests\Fixtures\Doctrine\Entity; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation\Exclude; use JMS\Serializer\Annotation\SerializedName; /** @ORM\Entity */ +#[ORM\Entity] class AuthorExcludedId { /** @@ -17,6 +19,8 @@ class AuthorExcludedId * * @Exclude */ + #[ORM\Id] + #[ORM\Column(type: Types::INTEGER)] #[Exclude] protected $id; @@ -25,6 +29,7 @@ class AuthorExcludedId * * @SerializedName("full_name") */ + #[ORM\Column(type: Types::STRING)] #[SerializedName(name: 'full_name')] private $name; diff --git a/tests/Fixtures/Doctrine/Entity/BlogPost.php b/tests/Fixtures/Doctrine/Entity/BlogPost.php index d49b7e903..665c72fd4 100644 --- a/tests/Fixtures/Doctrine/Entity/BlogPost.php +++ b/tests/Fixtures/Doctrine/Entity/BlogPost.php @@ -5,6 +5,7 @@ namespace JMS\Serializer\Tests\Fixtures\Doctrine\Entity; use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation as Serializer; use JMS\Serializer\Annotation\Groups; @@ -19,6 +20,7 @@ * * @XmlRoot("blog-post") */ +#[ORM\Entity] #[XmlRoot(name: 'blog-post')] class BlogPost { @@ -27,11 +29,15 @@ class BlogPost * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Id] + #[ORM\Column(type: Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] protected $id; /** * @ORM\Column(type="guid") */ + #[ORM\Column(type: Types::GUID)] private $guid; /** @@ -39,12 +45,14 @@ class BlogPost * * @Groups({"comments","post"}) */ + #[ORM\Column(type: Types::STRING)] #[Groups(groups: ['comments', 'post'])] private $title; /** * @ORM\Column(type="some_custom_type") */ + #[ORM\Column(type: 'some_custom_type')] protected $slug; /** @@ -52,6 +60,7 @@ class BlogPost * * @XmlAttribute */ + #[ORM\Column(type: Types::DATETIME_MUTABLE)] #[XmlAttribute] private $createdAt; @@ -66,6 +75,7 @@ class BlogPost * @Groups({"post"}) * @XmlAttribute */ + #[ORM\Column(type: Types::BOOLEAN)] #[Type(name: 'integer')] #[SerializedName(name: 'is_published')] #[Groups(groups: ['post'])] @@ -78,6 +88,7 @@ class BlogPost * @XmlList(inline=true, entry="comment") * @Groups({"comments"}) */ + #[ORM\OneToMany(targetEntity: Comment::class, mappedBy: 'blogPost')] #[XmlList(entry: 'comment', inline: true)] #[Groups(groups: ['comments'])] private $comments; @@ -87,13 +98,15 @@ class BlogPost * * @Groups({"post"}) */ + #[ORM\OneToOne(targetEntity: Author::class)] #[Groups(groups: ['post'])] private $author; /** - * @Serializer\Exclude() * @ORM\Column(type="integer") + * @Serializer\Exclude() */ + #[ORM\Column(type: Types::INTEGER)] #[Serializer\Exclude] private $ref; diff --git a/tests/Fixtures/Doctrine/Entity/Comment.php b/tests/Fixtures/Doctrine/Entity/Comment.php index 402685f70..7b09e0853 100644 --- a/tests/Fixtures/Doctrine/Entity/Comment.php +++ b/tests/Fixtures/Doctrine/Entity/Comment.php @@ -5,28 +5,35 @@ namespace JMS\Serializer\Tests\Fixtures\Doctrine\Entity; use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; /** @ORM\Entity */ +#[ORM\Entity] class Comment { /** * @ORM\Id * @ORM\Column(type="integer") */ + #[ORM\Id] + #[ORM\Column(type: Types::INTEGER)] protected $id; /** - * @ORM\Column(type="Author") + * @ORM\OneToOne(targetEntity="Author") */ + #[ORM\OneToOne(targetEntity: Author::class)] private $author; /** @ORM\ManyToOne(targetEntity="BlogPost") */ + #[ORM\ManyToOne(targetEntity: BlogPost::class)] private $blogPost; /** * @ORM\Column(type="string") */ + #[ORM\Column(type: Types::STRING)] private $text; public function __construct(Author $author, $text) diff --git a/tests/Fixtures/Doctrine/IdentityFields/Server.php b/tests/Fixtures/Doctrine/IdentityFields/Server.php index cdd20f73d..329dd85eb 100644 --- a/tests/Fixtures/Doctrine/IdentityFields/Server.php +++ b/tests/Fixtures/Doctrine/IdentityFields/Server.php @@ -4,10 +4,12 @@ namespace JMS\Serializer\Tests\Fixtures\Doctrine\IdentityFields; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation as Serializer; /** @ORM\Entity */ +#[ORM\Entity] class Server { /** @@ -18,6 +20,8 @@ class Server * @var string */ #[Serializer\Type(name: 'string')] + #[ORM\Id] + #[ORM\Column(type: Types::STRING, name: 'ip_address')] protected $ipAddress; /** @@ -30,6 +34,8 @@ class Server */ #[Serializer\SerializedName(name: 'server_id_extracted')] #[Serializer\Type(name: 'string')] + #[ORM\Id] + #[ORM\Column(type: Types::STRING, name: 'server_id')] protected $serverId; /** @@ -39,6 +45,7 @@ class Server * @var string */ #[Serializer\Type(name: 'string')] + #[ORM\Column(type: Types::STRING)] private $name; /** diff --git a/tests/Fixtures/Doctrine/PersistendCollection/App.php b/tests/Fixtures/Doctrine/PersistendCollection/App.php index e10cd85b3..dd6a9a86c 100644 --- a/tests/Fixtures/Doctrine/PersistendCollection/App.php +++ b/tests/Fixtures/Doctrine/PersistendCollection/App.php @@ -4,10 +4,12 @@ namespace JMS\Serializer\Tests\Fixtures\Doctrine\PersistendCollection; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation as Serializer; /** @ORM\Entity */ +#[ORM\Entity] class App { /** @@ -18,7 +20,10 @@ class App * * @var string */ + #[Serializer\SerializedName(name: 'id')] #[Serializer\Type(name: 'string')] + #[ORM\Id] + #[ORM\Column(type: Types::STRING, name: 'id')] protected $id; /** @@ -28,13 +33,16 @@ class App * @var string */ #[Serializer\Type(name: 'string')] + #[ORM\Column(type: Types::STRING)] private $name; /** * @ORM\ManyToOne(targetEntity="SmartPhone") + * @Serializer\Type("JMS\Serializer\Tests\Fixtures\Doctrine\PersistendCollection\SmartPhone") * * @var SmartPhone */ + #[ORM\ManyToOne(targetEntity: SmartPhone::class)] #[Serializer\Type(name: SmartPhone::class)] private $smartPhone; diff --git a/tests/Fixtures/Doctrine/PersistendCollection/SmartPhone.php b/tests/Fixtures/Doctrine/PersistendCollection/SmartPhone.php index 8622d5874..9e68aab4c 100644 --- a/tests/Fixtures/Doctrine/PersistendCollection/SmartPhone.php +++ b/tests/Fixtures/Doctrine/PersistendCollection/SmartPhone.php @@ -7,10 +7,12 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Criteria; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation as Serializer; /** @ORM\Entity */ +#[ORM\Entity] class SmartPhone { /** @@ -23,6 +25,8 @@ class SmartPhone */ #[Serializer\SerializedName(name: 'id')] #[Serializer\Type(name: 'string')] + #[ORM\Id] + #[ORM\Column(type: Types::STRING, name: 'id')] protected $id; /** @@ -32,6 +36,7 @@ class SmartPhone * @var string */ #[Serializer\Type(name: 'string')] + #[ORM\Column(type: Types::STRING)] private $name; /** @@ -43,6 +48,7 @@ class SmartPhone */ #[Serializer\SerializedName(name: 'applications')] #[Serializer\Type(name: 'ArrayCollection')] + #[ORM\OneToMany(targetEntity: App::class, mappedBy: 'smartPhone', cascade: ['persist'], orphanRemoval: true)] private $apps; /** diff --git a/tests/Fixtures/Doctrine/SingleTableInheritance/Clazz.php b/tests/Fixtures/Doctrine/SingleTableInheritance/Clazz.php index 001f9223e..4702053fd 100644 --- a/tests/Fixtures/Doctrine/SingleTableInheritance/Clazz.php +++ b/tests/Fixtures/Doctrine/SingleTableInheritance/Clazz.php @@ -5,11 +5,13 @@ namespace JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance; use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ +#[ORM\Entity] class Clazz extends AbstractModel { /** @@ -17,12 +19,17 @@ class Clazz extends AbstractModel * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Id] + #[ORM\Column(type: Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; /** @ORM\ManyToOne(targetEntity = "JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Teacher") */ + #[ORM\ManyToOne(targetEntity: Teacher::class)] private $teacher; /** @ORM\ManyToMany(targetEntity = "JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Student") */ + #[ORM\ManyToMany(targetEntity: Student::class)] private $students; public function __construct(Teacher $teacher, array $students) diff --git a/tests/Fixtures/Doctrine/SingleTableInheritance/Organization.php b/tests/Fixtures/Doctrine/SingleTableInheritance/Organization.php index 8c2edb809..f04eae6c5 100644 --- a/tests/Fixtures/Doctrine/SingleTableInheritance/Organization.php +++ b/tests/Fixtures/Doctrine/SingleTableInheritance/Organization.php @@ -4,6 +4,7 @@ namespace JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; /** @@ -14,6 +15,10 @@ * "school" = "JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\School" * }) */ +#[ORM\Entity] +#[ORM\InheritanceType('SINGLE_TABLE')] +#[ORM\DiscriminatorColumn(name: 'type', type: Types::STRING)] +#[ORM\DiscriminatorMap(['school' => School::class])] abstract class Organization { /** @@ -21,5 +26,8 @@ abstract class Organization * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ + #[ORM\Id] + #[ORM\Column(type: Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; } diff --git a/tests/Fixtures/Doctrine/SingleTableInheritance/Person.php b/tests/Fixtures/Doctrine/SingleTableInheritance/Person.php index b10e33ee1..ea887bb27 100644 --- a/tests/Fixtures/Doctrine/SingleTableInheritance/Person.php +++ b/tests/Fixtures/Doctrine/SingleTableInheritance/Person.php @@ -4,6 +4,7 @@ namespace JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; /** @@ -15,6 +16,10 @@ * "teacher" = "JMS\Serializer\Tests\Fixtures\Doctrine\SingleTableInheritance\Teacher", * }) */ +#[ORM\Entity] +#[ORM\InheritanceType('SINGLE_TABLE')] +#[ORM\DiscriminatorColumn(name: 'type', type: Types::STRING)] +#[ORM\DiscriminatorMap(['student' => Student::class, 'teacher' => Teacher::class])] abstract class Person extends AbstractModel { /** @@ -22,5 +27,8 @@ abstract class Person extends AbstractModel * @ORM\Column(type = "integer") * @ORM\GeneratedValue(strategy = "AUTO") */ + #[ORM\Id] + #[ORM\Column(type: Types::INTEGER)] + #[ORM\GeneratedValue(strategy: 'AUTO')] private $id; } diff --git a/tests/Fixtures/Doctrine/SingleTableInheritance/School.php b/tests/Fixtures/Doctrine/SingleTableInheritance/School.php index a74dad85c..c9d163a0d 100644 --- a/tests/Fixtures/Doctrine/SingleTableInheritance/School.php +++ b/tests/Fixtures/Doctrine/SingleTableInheritance/School.php @@ -9,6 +9,7 @@ /** * @ORM\Entity */ +#[ORM\Entity] class School extends Organization { } diff --git a/tests/Fixtures/Doctrine/SingleTableInheritance/Student.php b/tests/Fixtures/Doctrine/SingleTableInheritance/Student.php index 7e6412760..7ef4eba91 100644 --- a/tests/Fixtures/Doctrine/SingleTableInheritance/Student.php +++ b/tests/Fixtures/Doctrine/SingleTableInheritance/Student.php @@ -9,6 +9,7 @@ /** * @ORM\Entity */ +#[ORM\Entity] class Student extends Person { } diff --git a/tests/Fixtures/Doctrine/SingleTableInheritance/Teacher.php b/tests/Fixtures/Doctrine/SingleTableInheritance/Teacher.php index 4f3bd2597..eae0374c1 100644 --- a/tests/Fixtures/Doctrine/SingleTableInheritance/Teacher.php +++ b/tests/Fixtures/Doctrine/SingleTableInheritance/Teacher.php @@ -9,6 +9,7 @@ /** * @ORM\Entity */ +#[ORM\Entity] class Teacher extends Person { } diff --git a/tests/Metadata/Driver/DoctrineDriverTest.php b/tests/Metadata/Driver/DoctrineDriverTest.php index 88fd2a0f0..6f25c0bc1 100644 --- a/tests/Metadata/Driver/DoctrineDriverTest.php +++ b/tests/Metadata/Driver/DoctrineDriverTest.php @@ -7,7 +7,8 @@ use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\ORM\Configuration; use Doctrine\ORM\EntityManager; -use Doctrine\ORM\Mapping\Driver\AnnotationDriver as DoctrineDriver; +use Doctrine\ORM\Mapping\Driver\AnnotationDriver as DoctrineAnnotationDriver; +use Doctrine\ORM\Mapping\Driver\AttributeDriver as DoctrineAttributeDriver; use Doctrine\ORM\Version as ORMVersion; use Doctrine\Persistence\ManagerRegistry; use JMS\Serializer\Metadata\Driver\AnnotationDriver; @@ -134,9 +135,16 @@ protected function getEntityManager() $config = new Configuration(); $config->setProxyDir(sys_get_temp_dir() . '/JMSDoctrineTestProxies'); $config->setProxyNamespace('JMS\Tests\Proxies'); - $config->setMetadataDriverImpl( - new DoctrineDriver(new AnnotationReader(), __DIR__ . '/../../Fixtures/Doctrine') - ); + + if (PHP_VERSION_ID >= 80000 && class_exists(DoctrineAttributeDriver::class)) { + $config->setMetadataDriverImpl( + new DoctrineAttributeDriver([__DIR__ . '/../../Fixtures/Doctrine'], true) + ); + } else { + $config->setMetadataDriverImpl( + new DoctrineAnnotationDriver(new AnnotationReader(), __DIR__ . '/../../Fixtures/Doctrine') + ); + } $conn = [ 'driver' => 'pdo_sqlite', diff --git a/tests/Serializer/Doctrine/IntegrationTest.php b/tests/Serializer/Doctrine/IntegrationTest.php index c8f5ae5ae..eb9111872 100644 --- a/tests/Serializer/Doctrine/IntegrationTest.php +++ b/tests/Serializer/Doctrine/IntegrationTest.php @@ -11,6 +11,7 @@ use Doctrine\ORM\Configuration; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\Driver\AnnotationDriver; +use Doctrine\ORM\Mapping\Driver\AttributeDriver; use Doctrine\ORM\ORMException; use Doctrine\ORM\Tools\SchemaTool; use Doctrine\Persistence\AbstractManagerRegistry; @@ -135,9 +136,17 @@ private function createConnection() private function createEntityManager(Connection $con) { $cfg = new Configuration(); - $cfg->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader(), [ - __DIR__ . '/../../Fixtures/Doctrine/SingleTableInheritance', - ])); + + if (PHP_VERSION_ID >= 80000 && class_exists(AttributeDriver::class)) { + $cfg->setMetadataDriverImpl(new AttributeDriver([ + __DIR__ . '/../../Fixtures/Doctrine/SingleTableInheritance', + ])); + } else { + $cfg->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader(), [ + __DIR__ . '/../../Fixtures/Doctrine/SingleTableInheritance', + ])); + } + $cfg->setAutoGenerateProxyClasses(true); $cfg->setProxyNamespace('JMS\Serializer\DoctrineProxy'); $cfg->setProxyDir(sys_get_temp_dir() . '/serializer-test-proxies'); diff --git a/tests/Serializer/Doctrine/ObjectConstructorTest.php b/tests/Serializer/Doctrine/ObjectConstructorTest.php index f32d526c5..fb376d227 100644 --- a/tests/Serializer/Doctrine/ObjectConstructorTest.php +++ b/tests/Serializer/Doctrine/ObjectConstructorTest.php @@ -13,6 +13,7 @@ use Doctrine\ORM\Configuration; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\Driver\AnnotationDriver; +use Doctrine\ORM\Mapping\Driver\AttributeDriver; use Doctrine\ORM\Mapping\Driver\XmlDriver; use Doctrine\ORM\ORMException; use Doctrine\ORM\PersistentCollection; @@ -534,11 +535,20 @@ private function createEntityManager(Connection $con, ?Configuration $cfg = null { if (!$cfg) { $cfg = new Configuration(); - $cfg->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader(), [ - __DIR__ . '/../../Fixtures/Doctrine/Entity', - __DIR__ . '/../../Fixtures/Doctrine/IdentityFields', - __DIR__ . '/../../Fixtures/Doctrine/PersistendCollection', - ])); + + if (PHP_VERSION_ID >= 80000 && class_exists(AttributeDriver::class)) { + $cfg->setMetadataDriverImpl(new AttributeDriver([ + __DIR__ . '/../../Fixtures/Doctrine/Entity', + __DIR__ . '/../../Fixtures/Doctrine/IdentityFields', + __DIR__ . '/../../Fixtures/Doctrine/PersistendCollection', + ])); + } else { + $cfg->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader(), [ + __DIR__ . '/../../Fixtures/Doctrine/Entity', + __DIR__ . '/../../Fixtures/Doctrine/IdentityFields', + __DIR__ . '/../../Fixtures/Doctrine/PersistendCollection', + ])); + } } $cfg->setAutoGenerateProxyClasses(true); From 6f05f72bf24b8844d627ef9d6c13d1e08de8ec0a Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Fri, 13 Oct 2023 17:12:44 -0400 Subject: [PATCH 11/38] Bump minimum dependencies to match what's actually tested, normalize Composer manifest --- composer.json | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/composer.json b/composer.json index c25a1e4fc..647680c68 100644 --- a/composer.json +++ b/composer.json @@ -16,12 +16,12 @@ } ], "require": { - "php": "^7.2||^8.0", - "doctrine/annotations": "^1.13 || ^2.0", - "doctrine/instantiator": "^1.0.3 || ^2.0", + "php": "^7.2 || ^8.0", + "doctrine/annotations": "^1.14 || ^2.0", + "doctrine/instantiator": "^1.3.1 || ^2.0", "doctrine/lexer": "^2.0 || ^3.0", "jms/metadata": "^2.6", - "phpstan/phpdoc-parser": "^0.4 || ^0.5 || ^1.0" + "phpstan/phpdoc-parser": "^1.20" }, "suggest": { "doctrine/collections": "Required if you like to use doctrine collection types as ArrayCollection.", @@ -32,24 +32,24 @@ "require-dev": { "ext-pdo_sqlite": "*", "doctrine/coding-standard": "^12.0", - "doctrine/orm": "~2.1", - "doctrine/persistence": "^1.3.3|^2.0|^3.0", - "doctrine/phpcr-odm": "^1.3|^2.0", - "jackalope/jackalope-doctrine-dbal": "^1.1.5", - "ocramius/proxy-manager": "^1.0|^2.0", + "doctrine/orm": "^2.14", + "doctrine/persistence": "^2.5.2 || ^3.0", + "doctrine/phpcr-odm": "^1.5.2 || ^2.0", + "jackalope/jackalope-doctrine-dbal": "^1.3", + "ocramius/proxy-manager": "^1.0 || ^2.0", "phpbench/phpbench": "^1.0", "phpstan/phpstan": "^1.0.2", - "phpunit/phpunit": "^8.5.21||^9.0||^10.0", - "psr/container": "^1.0|^2.0", - "symfony/dependency-injection": "^3.0|^4.0|^5.0|^6.0|^7.0", - "symfony/expression-language": "^3.2|^4.0|^5.0|^6.0|^7.0", - "symfony/filesystem": "^3.0|^4.0|^5.0|^6.0|^7.0", - "symfony/form": "^3.0|^4.0|^5.0|^6.0|^7.0", - "symfony/translation": "^3.0|^4.0|^5.0|^6.0|^7.0", - "symfony/uid": "^5.1|^6.0|^7.0", - "symfony/validator": "^3.1.9|^4.0|^5.0|^6.0|^7.0", - "symfony/yaml": "^3.3|^4.0|^5.0|^6.0|^7.0", - "twig/twig": "~1.34|~2.4|^3.0" + "phpunit/phpunit": "^8.5.21 || ^9.0 || ^10.0", + "psr/container": "^1.0 || ^2.0", + "symfony/dependency-injection": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", + "symfony/expression-language": "^3.2 || ^4.0 || ^5.0 || ^6.0 || ^7.0", + "symfony/filesystem": "^4.2 || ^5.0 || ^6.0 || ^7.0", + "symfony/form": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", + "symfony/translation": "^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0", + "symfony/uid": "^5.1 || ^6.0 || ^7.0", + "symfony/validator": "^3.1.9 || ^4.0 || ^5.0 || ^6.0 || ^7.0", + "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", + "twig/twig": "^1.34 || ^2.4 || ^3.0" }, "autoload": { "psr-4": { From 660a9860d4e5490cd4d0615157f2080199dc8363 Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Tue, 17 Oct 2023 18:52:24 -0400 Subject: [PATCH 12/38] Inject an attribute metadata driver into the DoctrineDriver when testing --- tests/Metadata/Driver/DoctrineDriverTest.php | 24 ++++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/tests/Metadata/Driver/DoctrineDriverTest.php b/tests/Metadata/Driver/DoctrineDriverTest.php index 6f25c0bc1..4fe357754 100644 --- a/tests/Metadata/Driver/DoctrineDriverTest.php +++ b/tests/Metadata/Driver/DoctrineDriverTest.php @@ -12,9 +12,12 @@ use Doctrine\ORM\Version as ORMVersion; use Doctrine\Persistence\ManagerRegistry; use JMS\Serializer\Metadata\Driver\AnnotationDriver; +use JMS\Serializer\Metadata\Driver\AnnotationOrAttributeDriver; use JMS\Serializer\Metadata\Driver\DoctrineTypeDriver; +use JMS\Serializer\Metadata\Driver\NullDriver; use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; use JMS\Serializer\Tests\Fixtures\Doctrine\Embeddable\BlogPostWithEmbedded; +use Metadata\Driver\DriverChain; use PHPUnit\Framework\TestCase; class DoctrineDriverTest extends TestCase @@ -94,7 +97,7 @@ public function testNonDoctrineEntityClassIsNotModified() // because it has no Doctrine metadata. $refClass = new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost'); - $plainMetadata = $this->getAnnotationDriver()->loadMetadataForClass($refClass); + $plainMetadata = $this->getMetadataDriver()->loadMetadataForClass($refClass); $doctrineMetadata = $this->getDoctrineDriver()->loadMetadataForClass($refClass); // Do not compare timestamps @@ -107,7 +110,7 @@ public function testNonDoctrineEntityClassIsNotModified() public function testExcludePropertyNoPublicAccessorException() { - $first = $this->getAnnotationDriver() + $first = $this->getMetadataDriver() ->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\ExcludePublicAccessor')); self::assertArrayHasKey('id', $first->propertyMetadata); @@ -154,9 +157,20 @@ protected function getEntityManager() return EntityManager::create($conn, $config); } - public function getAnnotationDriver() + public function getMetadataDriver() { - return new AnnotationDriver(new AnnotationReader(), new IdenticalPropertyNamingStrategy()); + $driver = new DriverChain(); + $namingStrategy = new IdenticalPropertyNamingStrategy(); + + if (PHP_VERSION_ID >= 80000) { + $driver->addDriver(new AnnotationOrAttributeDriver($namingStrategy)); + } else { + $driver->addDriver(new AnnotationDriver(new AnnotationReader(), $namingStrategy)); + } + + $driver->addDriver(new NullDriver($namingStrategy)); + + return $driver; } protected function getDoctrineDriver() @@ -167,7 +181,7 @@ protected function getDoctrineDriver() ->will($this->returnValue($this->getEntityManager())); return new DoctrineTypeDriver( - $this->getAnnotationDriver(), + $this->getMetadataDriver(), $registry ); } From 9cbffa87c3b3b2da6b3fb913a95eec78b210f14e Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Tue, 24 Oct 2023 21:13:07 +0200 Subject: [PATCH 13/38] refactor(test): Stop using ORM Version class --- tests/Serializer/Doctrine/ObjectConstructorTest.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/Serializer/Doctrine/ObjectConstructorTest.php b/tests/Serializer/Doctrine/ObjectConstructorTest.php index fb376d227..67ddef9f2 100644 --- a/tests/Serializer/Doctrine/ObjectConstructorTest.php +++ b/tests/Serializer/Doctrine/ObjectConstructorTest.php @@ -19,7 +19,6 @@ use Doctrine\ORM\PersistentCollection; use Doctrine\ORM\Tools\SchemaTool; use Doctrine\ORM\UnitOfWork; -use Doctrine\ORM\Version as ORMVersion; use Doctrine\Persistence\AbstractManagerRegistry; use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\Mapping\ClassMetadata as DoctrineClassMetadata; @@ -359,10 +358,6 @@ public function testPersistendCollectionIsNotReplaced(string $data, string $type public function testFallbackOnEmbeddableClassWithXmlDriver() { - if (ORMVersion::compare('2.5') >= 0) { - $this->markTestSkipped('Not using Doctrine ORM >= 2.5 with Embedded entities'); - } - $fallback = $this->getMockBuilder(ObjectConstructorInterface::class)->getMock(); $fallback->expects($this->once())->method('construct'); @@ -393,10 +388,6 @@ static function ($id) use ($connection, $entityManager) { public function testFallbackOnEmbeddableClassWithXmlDriverAndXmlData() { - if (ORMVersion::compare('2.5') >= 0) { - $this->markTestSkipped('Not using Doctrine ORM >= 2.5 with Embedded entities'); - } - $fallback = $this->getMockBuilder(ObjectConstructorInterface::class)->getMock(); $fallback->expects($this->once())->method('construct'); From b01d21fbb016f9435380ef54bc751c9842f7e7f8 Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Fri, 27 Oct 2023 15:37:41 +0200 Subject: [PATCH 14/38] refactor(test): Stop using EntityManager::create() method. Use constructor instead --- tests/Metadata/Driver/DoctrineDriverTest.php | 12 ++++-------- tests/Serializer/Doctrine/IntegrationTest.php | 2 +- tests/Serializer/Doctrine/ObjectConstructorTest.php | 2 +- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/Metadata/Driver/DoctrineDriverTest.php b/tests/Metadata/Driver/DoctrineDriverTest.php index 4fe357754..1dc3565a4 100644 --- a/tests/Metadata/Driver/DoctrineDriverTest.php +++ b/tests/Metadata/Driver/DoctrineDriverTest.php @@ -5,11 +5,11 @@ namespace JMS\Serializer\Tests\Metadata\Driver; use Doctrine\Common\Annotations\AnnotationReader; +use Doctrine\DBAL\DriverManager; use Doctrine\ORM\Configuration; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\Driver\AnnotationDriver as DoctrineAnnotationDriver; use Doctrine\ORM\Mapping\Driver\AttributeDriver as DoctrineAttributeDriver; -use Doctrine\ORM\Version as ORMVersion; use Doctrine\Persistence\ManagerRegistry; use JMS\Serializer\Metadata\Driver\AnnotationDriver; use JMS\Serializer\Metadata\Driver\AnnotationOrAttributeDriver; @@ -31,10 +31,6 @@ public function getMetadata() public function testMetadataForEmbedded() { - if (ORMVersion::compare('2.5') >= 0) { - $this->markTestSkipped('Not using Doctrine ORM >= 2.5 with Embedded entities'); - } - $refClass = new \ReflectionClass(BlogPostWithEmbedded::class); $meta = $this->getDoctrineDriver()->loadMetadataForClass($refClass); self::assertNotNull($meta); @@ -149,12 +145,12 @@ protected function getEntityManager() ); } - $conn = [ + $conn = DriverManager::getConnection([ 'driver' => 'pdo_sqlite', 'memory' => true, - ]; + ]); - return EntityManager::create($conn, $config); + return new EntityManager($conn, $config); } public function getMetadataDriver() diff --git a/tests/Serializer/Doctrine/IntegrationTest.php b/tests/Serializer/Doctrine/IntegrationTest.php index eb9111872..4ce720acf 100644 --- a/tests/Serializer/Doctrine/IntegrationTest.php +++ b/tests/Serializer/Doctrine/IntegrationTest.php @@ -151,7 +151,7 @@ private function createEntityManager(Connection $con) $cfg->setProxyNamespace('JMS\Serializer\DoctrineProxy'); $cfg->setProxyDir(sys_get_temp_dir() . '/serializer-test-proxies'); - return EntityManager::create($con, $cfg); + return new EntityManager($con, $cfg); } } diff --git a/tests/Serializer/Doctrine/ObjectConstructorTest.php b/tests/Serializer/Doctrine/ObjectConstructorTest.php index 67ddef9f2..f519f561f 100644 --- a/tests/Serializer/Doctrine/ObjectConstructorTest.php +++ b/tests/Serializer/Doctrine/ObjectConstructorTest.php @@ -546,7 +546,7 @@ private function createEntityManager(Connection $con, ?Configuration $cfg = null $cfg->setProxyNamespace('JMS\Serializer\DoctrineProxy'); $cfg->setProxyDir(sys_get_temp_dir() . '/serializer-test-proxies'); - return EntityManager::create($con, $cfg); + return new EntityManager($con, $cfg); } /** From 81f596c8f52dd7de63514a76d7f3c90409fc6915 Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Fri, 13 Oct 2023 22:34:03 +0200 Subject: [PATCH 15/38] build(tests): Run tests without Doctrine ODM --- .github/workflows/ci.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index dd6c11f95..4d7c7e1b1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -45,6 +45,9 @@ jobs: if: ${{ matrix.composer-stability }} run: composer config minimum-stability ${{ matrix.composer-stability }} + - name: Uninstall Doctrine ODM + run: composer remove doctrine/phpcr-odm jackalope/jackalope-doctrine-dbal --no-update --dev + - name: "Install dependencies with Composer" uses: "ramsey/composer-install@v1" with: From 11f21f3993f326e3b89cd79ba09da554b596731c Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Sun, 29 Oct 2023 23:36:09 +0100 Subject: [PATCH 16/38] chore(deps): Allow doctrine/orm 3.0 --- composer.json | 5 +++-- ...er.Tests.Fixtures.Doctrine.Embeddable.BlogPostSeo.dcm.xml | 2 +- tests/Serializer/Doctrine/IntegrationTest.php | 1 + tests/Serializer/Doctrine/ObjectConstructorTest.php | 5 ++--- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 647680c68..33c326caa 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "require-dev": { "ext-pdo_sqlite": "*", "doctrine/coding-standard": "^12.0", - "doctrine/orm": "^2.14", + "doctrine/orm": "^2.14 || ^3.0", "doctrine/persistence": "^2.5.2 || ^3.0", "doctrine/phpcr-odm": "^1.5.2 || ^2.0", "jackalope/jackalope-doctrine-dbal": "^1.3", @@ -72,5 +72,6 @@ "branch-alias": { "dev-master": "3.x-dev" } - } + }, + "minimum-stability": "dev" } diff --git a/tests/Fixtures/Doctrine/XmlMapping/JMS.Serializer.Tests.Fixtures.Doctrine.Embeddable.BlogPostSeo.dcm.xml b/tests/Fixtures/Doctrine/XmlMapping/JMS.Serializer.Tests.Fixtures.Doctrine.Embeddable.BlogPostSeo.dcm.xml index 87cce5a0d..4b13399d8 100644 --- a/tests/Fixtures/Doctrine/XmlMapping/JMS.Serializer.Tests.Fixtures.Doctrine.Embeddable.BlogPostSeo.dcm.xml +++ b/tests/Fixtures/Doctrine/XmlMapping/JMS.Serializer.Tests.Fixtures.Doctrine.Embeddable.BlogPostSeo.dcm.xml @@ -1,5 +1,5 @@ - + diff --git a/tests/Serializer/Doctrine/IntegrationTest.php b/tests/Serializer/Doctrine/IntegrationTest.php index 4ce720acf..ca17e247d 100644 --- a/tests/Serializer/Doctrine/IntegrationTest.php +++ b/tests/Serializer/Doctrine/IntegrationTest.php @@ -141,6 +141,7 @@ private function createEntityManager(Connection $con) $cfg->setMetadataDriverImpl(new AttributeDriver([ __DIR__ . '/../../Fixtures/Doctrine/SingleTableInheritance', ])); + AnnotationReader::addGlobalIgnoredNamespace('Doctrine\ORM\Mapping'); } else { $cfg->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader(), [ __DIR__ . '/../../Fixtures/Doctrine/SingleTableInheritance', diff --git a/tests/Serializer/Doctrine/ObjectConstructorTest.php b/tests/Serializer/Doctrine/ObjectConstructorTest.php index f519f561f..f6725d928 100644 --- a/tests/Serializer/Doctrine/ObjectConstructorTest.php +++ b/tests/Serializer/Doctrine/ObjectConstructorTest.php @@ -58,7 +58,6 @@ use ReflectionClass; use RuntimeException; use SimpleXMLElement; - use function assert; class ObjectConstructorTest extends TestCase @@ -471,8 +470,7 @@ public function testArrayKeyExistsOnObject(): void protected function setUp(): void { $this->visitor = $this->getMockBuilder(DeserializationVisitorInterface::class)->getMock(); - $this->context = $this->getMockBuilder('JMS\Serializer\DeserializationContext')->getMock(); - + $this->context = $this->getMockBuilder(DeserializationContext::class)->getMock(); $connection = $this->createConnection(); $entityManager = $this->createEntityManager($connection); @@ -528,6 +526,7 @@ private function createEntityManager(Connection $con, ?Configuration $cfg = null $cfg = new Configuration(); if (PHP_VERSION_ID >= 80000 && class_exists(AttributeDriver::class)) { + AnnotationReader::addGlobalIgnoredNamespace('Doctrine\ORM\Mapping'); $cfg->setMetadataDriverImpl(new AttributeDriver([ __DIR__ . '/../../Fixtures/Doctrine/Entity', __DIR__ . '/../../Fixtures/Doctrine/IdentityFields', From f30108d9b8050be9df3804aa7286bf4db9de419b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Mon, 4 Dec 2023 20:57:25 +0100 Subject: [PATCH 17/38] qa: add test to verify metadata parser can handle missing attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- tests/Fixtures/MissingAttributeObject.php | 21 +++++++++++++++++++ ...aseAnnotationOrAttributeDriverTestCase.php | 14 +++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tests/Fixtures/MissingAttributeObject.php diff --git a/tests/Fixtures/MissingAttributeObject.php b/tests/Fixtures/MissingAttributeObject.php new file mode 100644 index 000000000..508485f4e --- /dev/null +++ b/tests/Fixtures/MissingAttributeObject.php @@ -0,0 +1,21 @@ +markTestSkipped('Short expose syntax not supported on annotations or attribute'); } + + public function testCanHandleMissingAttributes(): void + { + $metadata = $this->getDriver()->loadMetadataForClass(new ReflectionClass(MissingAttributeObject::class)); + self::assertArrayHasKey('property', $metadata->propertyMetadata); + + if (PHP_VERSION_ID >= 80000) { + self::assertArrayHasKey('propertyFromMethod', $metadata->propertyMetadata); + } + } } From 545f455ff28586f3fbbe2ebc0584658812cf04be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Mon, 4 Dec 2023 20:57:40 +0100 Subject: [PATCH 18/38] bugfix: handle missing attributes when parsing metadata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- .../Driver/AnnotationOrAttributeDriver.php | 23 ++++++++++++++++--- src/Metadata/Driver/AttributeDriver.php | 23 ++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/Metadata/Driver/AnnotationOrAttributeDriver.php b/src/Metadata/Driver/AnnotationOrAttributeDriver.php index 9f6f514c5..a3d14f035 100644 --- a/src/Metadata/Driver/AnnotationOrAttributeDriver.php +++ b/src/Metadata/Driver/AnnotationOrAttributeDriver.php @@ -48,6 +48,8 @@ use Metadata\Driver\DriverInterface; use Metadata\MethodMetadata; +use function array_filter; + class AnnotationOrAttributeDriver implements DriverInterface { use ExpressionMetadataTrait; @@ -309,7 +311,12 @@ protected function getClassAnnotations(\ReflectionClass $class): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - $class->getAttributes() + array_filter( + $class->getAttributes(), + static function (\ReflectionAttribute $attribute): bool { + return class_exists($attribute->getName()); + } + ) ); } @@ -332,7 +339,12 @@ protected function getMethodAnnotations(\ReflectionMethod $method): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - $method->getAttributes() + array_filter( + $method->getAttributes(), + static function (\ReflectionAttribute $attribute): bool { + return class_exists($attribute->getName()); + } + ) ); } @@ -355,7 +367,12 @@ protected function getPropertyAnnotations(\ReflectionProperty $property): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - $property->getAttributes() + array_filter( + $property->getAttributes(), + static function (\ReflectionAttribute $attribute): bool { + return class_exists($attribute->getName()); + } + ) ); } diff --git a/src/Metadata/Driver/AttributeDriver.php b/src/Metadata/Driver/AttributeDriver.php index 8d794c64b..8c2437613 100644 --- a/src/Metadata/Driver/AttributeDriver.php +++ b/src/Metadata/Driver/AttributeDriver.php @@ -4,6 +4,8 @@ namespace JMS\Serializer\Metadata\Driver; +use function array_filter; + class AttributeDriver extends AnnotationOrAttributeDriver { /** @@ -15,7 +17,12 @@ protected function getClassAnnotations(\ReflectionClass $class): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - $class->getAttributes() + array_filter( + $class->getAttributes(), + static function (\ReflectionAttribute $attribute): bool { + return class_exists($attribute->getName()); + } + ) ); } @@ -28,7 +35,12 @@ protected function getMethodAnnotations(\ReflectionMethod $method): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - $method->getAttributes() + array_filter( + $method->getAttributes(), + static function (\ReflectionAttribute $attribute): bool { + return class_exists($attribute->getName()); + } + ) ); } @@ -41,7 +53,12 @@ protected function getPropertyAnnotations(\ReflectionProperty $property): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - $property->getAttributes() + array_filter( + $property->getAttributes(), + static function (\ReflectionAttribute $attribute): bool { + return class_exists($attribute->getName()); + } + ) ); } } From 64da5ffebb807ff3a16909abccc30de4715ff8e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Tue, 5 Dec 2023 10:54:01 +0100 Subject: [PATCH 19/38] qa: ignore missing attribute in static analysis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The attribute is missing on purpose and therefore, ignoring that error should be legit. Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- phpstan/ignore-by-php-version.neon.php | 3 +++ phpstan/ignore-missing-attribute.neon | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 phpstan/ignore-missing-attribute.neon diff --git a/phpstan/ignore-by-php-version.neon.php b/phpstan/ignore-by-php-version.neon.php index a7156b63c..a569893de 100644 --- a/phpstan/ignore-by-php-version.neon.php +++ b/phpstan/ignore-by-php-version.neon.php @@ -9,6 +9,9 @@ if (PHP_VERSION_ID < 80100) { $includes[] = __DIR__ . '/no-enum.neon'; } +if (PHP_VERSION_ID >= 80000) { + $includes[] = __DIR__ . '/ignore-missing-attributes.neon'; +} if (PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80200) { $includes[] = __DIR__ . '/php-81.neon'; } diff --git a/phpstan/ignore-missing-attribute.neon b/phpstan/ignore-missing-attribute.neon new file mode 100644 index 000000000..22b569d97 --- /dev/null +++ b/phpstan/ignore-missing-attribute.neon @@ -0,0 +1,3 @@ +parameters: + ignoreErrors: + - '#^Attribute class JMS\\Serializer\\Tests\\Fixtures\\MissingAttribute does not exist\.$#' From e0fd33c73259dc85d5e0e72630848e9c718ecc94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20B=C3=B6sing?= <2189546+boesing@users.noreply.github.com> Date: Thu, 7 Dec 2023 16:13:02 +0100 Subject: [PATCH 20/38] qa: add annotation so that test is passing for both metadata drivers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com> --- tests/Fixtures/MissingAttributeObject.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/Fixtures/MissingAttributeObject.php b/tests/Fixtures/MissingAttributeObject.php index 508485f4e..15f09af75 100644 --- a/tests/Fixtures/MissingAttributeObject.php +++ b/tests/Fixtures/MissingAttributeObject.php @@ -12,6 +12,9 @@ final class MissingAttributeObject #[MissingAttribute] public $property; + /** + * @VirtualProperty(name="propertyFromMethod") + */ #[MissingAttribute] #[VirtualProperty(name: 'propertyFromMethod')] public function propertyMethod() From b69fe07004ae2dc5602ce3007f11377c2479eccf Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Sat, 9 Dec 2023 12:50:37 +0100 Subject: [PATCH 21/38] Update phpstan/ignore-by-php-version.neon.php --- phpstan/ignore-by-php-version.neon.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan/ignore-by-php-version.neon.php b/phpstan/ignore-by-php-version.neon.php index a569893de..d5d5a0520 100644 --- a/phpstan/ignore-by-php-version.neon.php +++ b/phpstan/ignore-by-php-version.neon.php @@ -10,7 +10,7 @@ $includes[] = __DIR__ . '/no-enum.neon'; } if (PHP_VERSION_ID >= 80000) { - $includes[] = __DIR__ . '/ignore-missing-attributes.neon'; + $includes[] = __DIR__ . '/ignore-missing-attribute.neon'; } if (PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80200) { $includes[] = __DIR__ . '/php-81.neon'; From 50d7d6e75dabc8898685552ecd68824d6e523384 Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Wed, 13 Dec 2023 12:41:07 -0500 Subject: [PATCH 22/38] Introduce a marker interface for annotation/attribute classes --- src/Annotation/AccessType.php | 2 +- src/Annotation/Accessor.php | 2 +- src/Annotation/AccessorOrder.php | 2 +- src/Annotation/Discriminator.php | 2 +- src/Annotation/Exclude.php | 2 +- src/Annotation/ExclusionPolicy.php | 2 +- src/Annotation/Expose.php | 2 +- src/Annotation/Groups.php | 2 +- src/Annotation/Inline.php | 2 +- src/Annotation/MaxDepth.php | 2 +- src/Annotation/PostDeserialize.php | 2 +- src/Annotation/PostSerialize.php | 2 +- src/Annotation/PreSerialize.php | 2 +- src/Annotation/ReadOnlyProperty.php | 2 +- src/Annotation/SerializedName.php | 2 +- src/Annotation/SerializerAttribute.php | 12 ++++++++ src/Annotation/SkipWhenEmpty.php | 2 +- src/Annotation/Type.php | 2 +- src/Annotation/Version.php | 2 +- src/Annotation/VirtualProperty.php | 2 +- src/Annotation/XmlAttribute.php | 2 +- src/Annotation/XmlAttributeMap.php | 2 +- src/Annotation/XmlCollection.php | 2 +- src/Annotation/XmlDiscriminator.php | 2 +- src/Annotation/XmlElement.php | 2 +- src/Annotation/XmlKeyValuePairs.php | 2 +- src/Annotation/XmlNamespace.php | 2 +- src/Annotation/XmlRoot.php | 2 +- src/Annotation/XmlValue.php | 2 +- .../Driver/AnnotationOrAttributeDriver.php | 30 +++++-------------- src/Metadata/Driver/AttributeDriver.php | 29 +++++------------- .../AttributeDriver/AttributeReader.php | 30 ++++++++++--------- 32 files changed, 70 insertions(+), 87 deletions(-) create mode 100644 src/Annotation/SerializerAttribute.php diff --git a/src/Annotation/AccessType.php b/src/Annotation/AccessType.php index 514a91616..bdcab3800 100644 --- a/src/Annotation/AccessType.php +++ b/src/Annotation/AccessType.php @@ -11,7 +11,7 @@ * @author Johannes M. Schmitt */ #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_PROPERTY)] -final class AccessType +final class AccessType implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/Accessor.php b/src/Annotation/Accessor.php index da88e782f..d9257db5d 100644 --- a/src/Annotation/Accessor.php +++ b/src/Annotation/Accessor.php @@ -11,7 +11,7 @@ * @author Johannes M. Schmitt */ #[\Attribute(\Attribute::TARGET_PROPERTY)] -final class Accessor +final class Accessor implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/AccessorOrder.php b/src/Annotation/AccessorOrder.php index 392bb72c0..af2b98e7a 100644 --- a/src/Annotation/AccessorOrder.php +++ b/src/Annotation/AccessorOrder.php @@ -13,7 +13,7 @@ * @author Johannes M. Schmitt */ #[\Attribute(\Attribute::TARGET_CLASS)] -final class AccessorOrder +final class AccessorOrder implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/Discriminator.php b/src/Annotation/Discriminator.php index b84a311be..f010036f8 100644 --- a/src/Annotation/Discriminator.php +++ b/src/Annotation/Discriminator.php @@ -9,7 +9,7 @@ * @Target("CLASS") */ #[\Attribute(\Attribute::TARGET_CLASS)] -class Discriminator +class Discriminator implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/Exclude.php b/src/Annotation/Exclude.php index 8660e9a42..c599062a4 100644 --- a/src/Annotation/Exclude.php +++ b/src/Annotation/Exclude.php @@ -9,7 +9,7 @@ * @Target({"PROPERTY", "CLASS", "METHOD", "ANNOTATION"}) */ #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD)] -final class Exclude +final class Exclude implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/ExclusionPolicy.php b/src/Annotation/ExclusionPolicy.php index 90eb1fde5..968ced874 100644 --- a/src/Annotation/ExclusionPolicy.php +++ b/src/Annotation/ExclusionPolicy.php @@ -11,7 +11,7 @@ * @Target("CLASS") */ #[\Attribute(\Attribute::TARGET_CLASS)] -final class ExclusionPolicy +final class ExclusionPolicy implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/Expose.php b/src/Annotation/Expose.php index 3f03743a1..31087c3cd 100644 --- a/src/Annotation/Expose.php +++ b/src/Annotation/Expose.php @@ -9,7 +9,7 @@ * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) */ #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] -final class Expose +final class Expose implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/Groups.php b/src/Annotation/Groups.php index 740a89bc6..c82388e7a 100644 --- a/src/Annotation/Groups.php +++ b/src/Annotation/Groups.php @@ -9,7 +9,7 @@ * @Target({"PROPERTY","METHOD","ANNOTATION"}) */ #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] -final class Groups +final class Groups implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/Inline.php b/src/Annotation/Inline.php index d3d61e12c..5d2e42404 100644 --- a/src/Annotation/Inline.php +++ b/src/Annotation/Inline.php @@ -9,6 +9,6 @@ * @Target({"PROPERTY","METHOD","ANNOTATION"}) */ #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] -final class Inline +final class Inline implements SerializerAttribute { } diff --git a/src/Annotation/MaxDepth.php b/src/Annotation/MaxDepth.php index 82e7506b7..e459ca983 100644 --- a/src/Annotation/MaxDepth.php +++ b/src/Annotation/MaxDepth.php @@ -9,7 +9,7 @@ * @Target({"PROPERTY","METHOD","ANNOTATION"}) */ #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] -final class MaxDepth +final class MaxDepth implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/PostDeserialize.php b/src/Annotation/PostDeserialize.php index ddfabd411..2e3e8b89f 100644 --- a/src/Annotation/PostDeserialize.php +++ b/src/Annotation/PostDeserialize.php @@ -16,6 +16,6 @@ * @author Johannes M. Schmitt */ #[\Attribute(\Attribute::TARGET_METHOD)] -final class PostDeserialize +final class PostDeserialize implements SerializerAttribute { } diff --git a/src/Annotation/PostSerialize.php b/src/Annotation/PostSerialize.php index 070be6b4b..7efc7ec01 100644 --- a/src/Annotation/PostSerialize.php +++ b/src/Annotation/PostSerialize.php @@ -9,6 +9,6 @@ * @Target("METHOD") */ #[\Attribute(\Attribute::TARGET_METHOD)] -final class PostSerialize +final class PostSerialize implements SerializerAttribute { } diff --git a/src/Annotation/PreSerialize.php b/src/Annotation/PreSerialize.php index b1adf2f79..6b2be0a57 100644 --- a/src/Annotation/PreSerialize.php +++ b/src/Annotation/PreSerialize.php @@ -17,6 +17,6 @@ * @author Johannes M. Schmitt */ #[\Attribute(\Attribute::TARGET_METHOD)] -final class PreSerialize +final class PreSerialize implements SerializerAttribute { } diff --git a/src/Annotation/ReadOnlyProperty.php b/src/Annotation/ReadOnlyProperty.php index d748b68c8..4df6b3e1b 100644 --- a/src/Annotation/ReadOnlyProperty.php +++ b/src/Annotation/ReadOnlyProperty.php @@ -11,7 +11,7 @@ * @final */ #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_PROPERTY)] -/* final */ class ReadOnlyProperty +/* final */ class ReadOnlyProperty implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/SerializedName.php b/src/Annotation/SerializedName.php index f2b5a6446..de2a34f4f 100644 --- a/src/Annotation/SerializedName.php +++ b/src/Annotation/SerializedName.php @@ -9,7 +9,7 @@ * @Target({"PROPERTY","METHOD", "ANNOTATION"}) */ #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] -final class SerializedName +final class SerializedName implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/SerializerAttribute.php b/src/Annotation/SerializerAttribute.php new file mode 100644 index 000000000..e314de16d --- /dev/null +++ b/src/Annotation/SerializerAttribute.php @@ -0,0 +1,12 @@ + */ #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] -final class VirtualProperty +final class VirtualProperty implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/XmlAttribute.php b/src/Annotation/XmlAttribute.php index 31fc46376..724b5cfa8 100644 --- a/src/Annotation/XmlAttribute.php +++ b/src/Annotation/XmlAttribute.php @@ -9,7 +9,7 @@ * @Target({"PROPERTY", "METHOD","ANNOTATION"}) */ #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] -final class XmlAttribute +final class XmlAttribute implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/XmlAttributeMap.php b/src/Annotation/XmlAttributeMap.php index bde6d013b..65370c0be 100644 --- a/src/Annotation/XmlAttributeMap.php +++ b/src/Annotation/XmlAttributeMap.php @@ -9,6 +9,6 @@ * @Target({"PROPERTY", "METHOD"}) */ #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] -final class XmlAttributeMap +final class XmlAttributeMap implements SerializerAttribute { } diff --git a/src/Annotation/XmlCollection.php b/src/Annotation/XmlCollection.php index e34ff58a0..99d3133a5 100644 --- a/src/Annotation/XmlCollection.php +++ b/src/Annotation/XmlCollection.php @@ -4,7 +4,7 @@ namespace JMS\Serializer\Annotation; -abstract class XmlCollection +abstract class XmlCollection implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/XmlDiscriminator.php b/src/Annotation/XmlDiscriminator.php index bcb0e7950..bfd6fba48 100644 --- a/src/Annotation/XmlDiscriminator.php +++ b/src/Annotation/XmlDiscriminator.php @@ -9,7 +9,7 @@ * @Target("CLASS") */ #[\Attribute(\Attribute::TARGET_CLASS)] -class XmlDiscriminator +class XmlDiscriminator implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/XmlElement.php b/src/Annotation/XmlElement.php index bbf198283..7dcb8edf8 100644 --- a/src/Annotation/XmlElement.php +++ b/src/Annotation/XmlElement.php @@ -9,7 +9,7 @@ * @Target({"PROPERTY", "METHOD","ANNOTATION"}) */ #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] -final class XmlElement +final class XmlElement implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/XmlKeyValuePairs.php b/src/Annotation/XmlKeyValuePairs.php index f3a135033..38e3a645b 100644 --- a/src/Annotation/XmlKeyValuePairs.php +++ b/src/Annotation/XmlKeyValuePairs.php @@ -9,6 +9,6 @@ * @Target({"PROPERTY","METHOD","ANNOTATION"}) */ #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] -final class XmlKeyValuePairs +final class XmlKeyValuePairs implements SerializerAttribute { } diff --git a/src/Annotation/XmlNamespace.php b/src/Annotation/XmlNamespace.php index 5568aede6..681462cbd 100644 --- a/src/Annotation/XmlNamespace.php +++ b/src/Annotation/XmlNamespace.php @@ -9,7 +9,7 @@ * @Target("CLASS") */ #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] -final class XmlNamespace +final class XmlNamespace implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/XmlRoot.php b/src/Annotation/XmlRoot.php index 9034d35da..041bd63ad 100644 --- a/src/Annotation/XmlRoot.php +++ b/src/Annotation/XmlRoot.php @@ -9,7 +9,7 @@ * @Target("CLASS") */ #[\Attribute(\Attribute::TARGET_CLASS)] -final class XmlRoot +final class XmlRoot implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Annotation/XmlValue.php b/src/Annotation/XmlValue.php index bb49967f6..12535cdf7 100644 --- a/src/Annotation/XmlValue.php +++ b/src/Annotation/XmlValue.php @@ -9,7 +9,7 @@ * @Target({"PROPERTY","METHOD","ANNOTATION"}) */ #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] -final class XmlValue +final class XmlValue implements SerializerAttribute { use AnnotationUtilsTrait; diff --git a/src/Metadata/Driver/AnnotationOrAttributeDriver.php b/src/Metadata/Driver/AnnotationOrAttributeDriver.php index a3d14f035..5454f42ab 100644 --- a/src/Metadata/Driver/AnnotationOrAttributeDriver.php +++ b/src/Metadata/Driver/AnnotationOrAttributeDriver.php @@ -20,6 +20,7 @@ use JMS\Serializer\Annotation\PreSerialize; use JMS\Serializer\Annotation\ReadOnlyProperty; use JMS\Serializer\Annotation\SerializedName; +use JMS\Serializer\Annotation\SerializerAttribute; use JMS\Serializer\Annotation\Since; use JMS\Serializer\Annotation\SkipWhenEmpty; use JMS\Serializer\Annotation\Type; @@ -48,8 +49,6 @@ use Metadata\Driver\DriverInterface; use Metadata\MethodMetadata; -use function array_filter; - class AnnotationOrAttributeDriver implements DriverInterface { use ExpressionMetadataTrait; @@ -300,7 +299,7 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat } /** - * @return list + * @return list */ protected function getClassAnnotations(\ReflectionClass $class): array { @@ -311,12 +310,7 @@ protected function getClassAnnotations(\ReflectionClass $class): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - array_filter( - $class->getAttributes(), - static function (\ReflectionAttribute $attribute): bool { - return class_exists($attribute->getName()); - } - ) + $class->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF) ); } @@ -328,7 +322,7 @@ static function (\ReflectionAttribute $attribute): bool { } /** - * @return list + * @return list */ protected function getMethodAnnotations(\ReflectionMethod $method): array { @@ -339,12 +333,7 @@ protected function getMethodAnnotations(\ReflectionMethod $method): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - array_filter( - $method->getAttributes(), - static function (\ReflectionAttribute $attribute): bool { - return class_exists($attribute->getName()); - } - ) + $method->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF) ); } @@ -356,7 +345,7 @@ static function (\ReflectionAttribute $attribute): bool { } /** - * @return list + * @return list */ protected function getPropertyAnnotations(\ReflectionProperty $property): array { @@ -367,12 +356,7 @@ protected function getPropertyAnnotations(\ReflectionProperty $property): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - array_filter( - $property->getAttributes(), - static function (\ReflectionAttribute $attribute): bool { - return class_exists($attribute->getName()); - } - ) + $property->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF) ); } diff --git a/src/Metadata/Driver/AttributeDriver.php b/src/Metadata/Driver/AttributeDriver.php index 8c2437613..d00615a13 100644 --- a/src/Metadata/Driver/AttributeDriver.php +++ b/src/Metadata/Driver/AttributeDriver.php @@ -4,12 +4,12 @@ namespace JMS\Serializer\Metadata\Driver; -use function array_filter; +use JMS\Serializer\Annotation\SerializerAttribute; class AttributeDriver extends AnnotationOrAttributeDriver { /** - * @return list + * @return list */ protected function getClassAnnotations(\ReflectionClass $class): array { @@ -17,17 +17,12 @@ protected function getClassAnnotations(\ReflectionClass $class): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - array_filter( - $class->getAttributes(), - static function (\ReflectionAttribute $attribute): bool { - return class_exists($attribute->getName()); - } - ) + $class->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF) ); } /** - * @return list + * @return list */ protected function getMethodAnnotations(\ReflectionMethod $method): array { @@ -35,17 +30,12 @@ protected function getMethodAnnotations(\ReflectionMethod $method): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - array_filter( - $method->getAttributes(), - static function (\ReflectionAttribute $attribute): bool { - return class_exists($attribute->getName()); - } - ) + $method->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF) ); } /** - * @return list + * @return list */ protected function getPropertyAnnotations(\ReflectionProperty $property): array { @@ -53,12 +43,7 @@ protected function getPropertyAnnotations(\ReflectionProperty $property): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - array_filter( - $property->getAttributes(), - static function (\ReflectionAttribute $attribute): bool { - return class_exists($attribute->getName()); - } - ) + $property->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF) ); } } diff --git a/src/Metadata/Driver/AttributeDriver/AttributeReader.php b/src/Metadata/Driver/AttributeDriver/AttributeReader.php index 454019039..add4432f2 100644 --- a/src/Metadata/Driver/AttributeDriver/AttributeReader.php +++ b/src/Metadata/Driver/AttributeDriver/AttributeReader.php @@ -5,6 +5,7 @@ namespace JMS\Serializer\Metadata\Driver\AttributeDriver; use Doctrine\Common\Annotations\Reader; +use JMS\Serializer\Annotation\SerializerAttribute; use ReflectionClass; use ReflectionMethod; use ReflectionProperty; @@ -26,42 +27,42 @@ public function __construct(Reader $reader) public function getClassAnnotations(ReflectionClass $class): array { - $attributes = $class->getAttributes(); + $attributes = $class->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF); return array_merge($this->reader->getClassAnnotations($class), $this->buildAnnotations($attributes)); } public function getClassAnnotation(ReflectionClass $class, $annotationName): ?object { - $attributes = $class->getAttributes($annotationName); + $attributes = $class->getAttributes($annotationName, \ReflectionAttribute::IS_INSTANCEOF); return $this->reader->getClassAnnotation($class, $annotationName) ?? $this->buildAnnotation($attributes); } public function getMethodAnnotations(ReflectionMethod $method): array { - $attributes = $method->getAttributes(); + $attributes = $method->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF); return array_merge($this->reader->getMethodAnnotations($method), $this->buildAnnotations($attributes)); } public function getMethodAnnotation(ReflectionMethod $method, $annotationName): ?object { - $attributes = $method->getAttributes($annotationName); + $attributes = $method->getAttributes($annotationName, \ReflectionAttribute::IS_INSTANCEOF); return $this->reader->getClassAnnotation($method, $annotationName) ?? $this->buildAnnotation($attributes); } public function getPropertyAnnotations(ReflectionProperty $property): array { - $attributes = $property->getAttributes(); + $attributes = $property->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF); return array_merge($this->reader->getPropertyAnnotations($property), $this->buildAnnotations($attributes)); } public function getPropertyAnnotation(ReflectionProperty $property, $annotationName): ?object { - $attributes = $property->getAttributes($annotationName); + $attributes = $property->getAttributes($annotationName, \ReflectionAttribute::IS_INSTANCEOF); return $this->reader->getClassAnnotation($property, $annotationName) ?? $this->buildAnnotation($attributes); } @@ -75,15 +76,16 @@ private function buildAnnotation(array $attributes): ?object return $attributes[0]->newInstance(); } + /** + * @return list + */ private function buildAnnotations(array $attributes): array { - $result = []; - foreach ($attributes as $attribute) { - if (0 === strpos($attribute->getName(), 'JMS\Serializer\Annotation\\')) { - $result[] = $attribute->newInstance(); - } - } - - return $result; + return array_map( + static function (\ReflectionAttribute $attribute): object { + return $attribute->newInstance(); + }, + $attributes + ); } } From 3233781608ae814842be55735281abd14e05af82 Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Sat, 9 Dec 2023 11:19:25 -0500 Subject: [PATCH 23/38] Require PHP 7.4 and Symfony 5.4 --- .github/workflows/benchmark.yaml | 4 +- .github/workflows/ci.yaml | 2 - .github/workflows/coding-standards.yaml | 2 +- composer.json | 20 +-- phpcs.xml.dist | 2 +- src/Annotation/Type.php | 4 +- src/Builder/DefaultDriverFactory.php | 4 +- src/Exception/NonCastableTypeException.php | 4 +- src/Exception/NonVisitableTypeException.php | 2 +- src/Exception/RuntimeException.php | 2 +- .../DeserializationGraphNavigator.php | 2 +- src/Handler/DateHandler.php | 2 +- src/Handler/FormErrorHandler.php | 2 +- src/JsonDeserializationVisitor.php | 2 +- src/Metadata/ClassMetadata.php | 8 +- .../Driver/AnnotationOrAttributeDriver.php | 10 +- src/Metadata/Driver/AttributeDriver.php | 6 +- .../AttributeDriver/AttributeReader.php | 7 +- src/Metadata/Driver/DocBlockDriver.php | 4 +- .../DocBlockDriver/DocBlockTypeResolver.php | 2 +- src/Metadata/Driver/DoctrineTypeDriver.php | 2 +- src/Metadata/Driver/TypedPropertiesDriver.php | 4 - src/Metadata/Driver/XmlDriver.php | 4 +- src/Metadata/Driver/YamlDriver.php | 22 +-- .../AlphabeticalPropertyOrderingStrategy.php | 2 +- src/Serializer.php | 12 +- src/SerializerBuilder.php | 12 +- src/Type/Parser.php | 8 +- .../XmlSerializationVisitorFactory.php | 2 +- src/XmlDeserializationVisitor.php | 4 +- src/XmlSerializationVisitor.php | 2 +- .../Benchmark/AbstractSerializationBench.php | 2 +- ...jectWithXmlKeyValuePairsWithObjectType.php | 2 +- .../ObjectWithXmlKeyValuePairsWithType.php | 4 +- tests/Handler/DateHandlerTest.php | 12 +- tests/Handler/FormErrorHandlerTest.php | 12 +- tests/Handler/IteratorHandlerTest.php | 8 +- tests/Handler/SymfonyUidHandlerTest.php | 12 +- tests/Metadata/Driver/BaseDriverTestCase.php | 12 +- .../Driver/DefaultDriverFactoryTest.php | 4 - tests/Metadata/Driver/DocBlockDriverTest.php | 150 +++++------------- .../Driver/DocBlockTypeResolverTest.php | 12 +- tests/Metadata/Driver/DoctrineDriverTest.php | 16 +- .../Driver/DoctrinePHPCRDriverTest.php | 12 +- .../Driver/TypedPropertiesDriverTest.php | 7 - .../Driver/UnionTypedPropertiesDriverTest.php | 2 +- tests/Metadata/Driver/YamlDriverTest.php | 2 +- .../CustomPropertyOrderingStrategyTest.php | 2 +- tests/Serializer/ArrayTest.php | 2 +- .../Serializer/BaseSerializationTestCase.php | 130 +++++++-------- tests/Serializer/Doctrine/IntegrationTest.php | 4 +- .../Doctrine/ObjectConstructorTest.php | 27 ++-- ...ymfonyValidatorValidatorSubscriberTest.php | 2 +- tests/Serializer/JsonSerializationTest.php | 6 +- tests/Serializer/Type/ParserTest.php | 2 +- tests/Serializer/XmlSerializationTest.php | 42 ++--- tests/SerializerBuilderTest.php | 10 +- tests/Twig/SerializerExtensionTest.php | 8 +- 58 files changed, 282 insertions(+), 387 deletions(-) diff --git a/.github/workflows/benchmark.yaml b/.github/workflows/benchmark.yaml index 484b1ea99..4dd2b6f26 100644 --- a/.github/workflows/benchmark.yaml +++ b/.github/workflows/benchmark.yaml @@ -14,7 +14,7 @@ jobs: strategy: matrix: php-version: - - "7.2" + - "7.4" - "8.0" - "8.1" @@ -29,7 +29,7 @@ jobs: - name: "Install dependencies with Composer" uses: "ramsey/composer-install@v1" - + - name: Run performance benchmarks run: | vendor/bin/phpbench run tests/Benchmark/Performance --report=aggregate diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4d7c7e1b1..4cc603b62 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,8 +15,6 @@ jobs: fail-fast: false matrix: php-version: - - "7.2" - - "7.3" - "7.4" - "8.0" - "8.1" diff --git a/.github/workflows/coding-standards.yaml b/.github/workflows/coding-standards.yaml index af0b7c184..2a80321cd 100644 --- a/.github/workflows/coding-standards.yaml +++ b/.github/workflows/coding-standards.yaml @@ -14,7 +14,7 @@ jobs: strategy: matrix: php-version: - - "7.2" + - "7.4" steps: - name: "Checkout" diff --git a/composer.json b/composer.json index 33c326caa..857e77617 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": "^7.2 || ^8.0", + "php": "^7.4 || ^8.0", "doctrine/annotations": "^1.14 || ^2.0", "doctrine/instantiator": "^1.3.1 || ^2.0", "doctrine/lexer": "^2.0 || ^3.0", @@ -39,16 +39,16 @@ "ocramius/proxy-manager": "^1.0 || ^2.0", "phpbench/phpbench": "^1.0", "phpstan/phpstan": "^1.0.2", - "phpunit/phpunit": "^8.5.21 || ^9.0 || ^10.0", + "phpunit/phpunit": "^9.0 || ^10.0", "psr/container": "^1.0 || ^2.0", - "symfony/dependency-injection": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "symfony/expression-language": "^3.2 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "symfony/filesystem": "^4.2 || ^5.0 || ^6.0 || ^7.0", - "symfony/form": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "symfony/translation": "^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "symfony/uid": "^5.1 || ^6.0 || ^7.0", - "symfony/validator": "^3.1.9 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", + "symfony/expression-language": "^5.4 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", + "symfony/form": "^5.4 || ^6.0 || ^7.0", + "symfony/translation": "^5.4 || ^6.0 || ^7.0", + "symfony/uid": "^5.4 || ^6.0 || ^7.0", + "symfony/validator": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0", "twig/twig": "^1.34 || ^2.4 || ^3.0" }, "autoload": { diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 95a364845..e2ed35f0c 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -10,7 +10,7 @@ - + src/ tests/ diff --git a/src/Annotation/Type.php b/src/Annotation/Type.php index 0f499e9c5..ef4cf7173 100644 --- a/src/Annotation/Type.php +++ b/src/Annotation/Type.php @@ -23,7 +23,7 @@ public function __construct($values = [], $name = null) { if ((null !== $name) && !is_string($name) && !(is_object($name) && method_exists($name, '__toString'))) { throw new \RuntimeException( - 'Type must be either string, null or object implements __toString() method.' + 'Type must be either string, null or object implements __toString() method.', ); } @@ -34,7 +34,7 @@ public function __construct($values = [], $name = null) if (is_object($values)) { if (false === method_exists($values, '__toString')) { throw new \RuntimeException( - 'Type must be either string or object implements __toString() method.' + 'Type must be either string or object implements __toString() method.', ); } diff --git a/src/Builder/DefaultDriverFactory.php b/src/Builder/DefaultDriverFactory.php index 041ca4a71..afe2e4e30 100644 --- a/src/Builder/DefaultDriverFactory.php +++ b/src/Builder/DefaultDriverFactory.php @@ -84,9 +84,7 @@ public function createDriver(array $metadataDirs, Reader $annotationReader): Dri $driver = new EnumPropertiesDriver($driver); } - if (PHP_VERSION_ID >= 70400) { - $driver = new TypedPropertiesDriver($driver, $this->typeParser); - } + $driver = new TypedPropertiesDriver($driver, $this->typeParser); if (PHP_VERSION_ID >= 80000) { $driver = new DefaultValuePropertyDriver($driver); diff --git a/src/Exception/NonCastableTypeException.php b/src/Exception/NonCastableTypeException.php index 97d0be2a7..7aa297c20 100644 --- a/src/Exception/NonCastableTypeException.php +++ b/src/Exception/NonCastableTypeException.php @@ -22,8 +22,8 @@ public function __construct(string $expectedType, $value) sprintf( 'Cannot convert value of type "%s" to %s', gettype($value), - $expectedType - ) + $expectedType, + ), ); } diff --git a/src/Exception/NonVisitableTypeException.php b/src/Exception/NonVisitableTypeException.php index 53f05ecf0..ee011b728 100644 --- a/src/Exception/NonVisitableTypeException.php +++ b/src/Exception/NonVisitableTypeException.php @@ -20,7 +20,7 @@ public static function fromDataAndType($data, array $type, ?RuntimeException $pr return new self( sprintf('Type %s cannot be visited as %s', get_debug_type($data), $type['name']), 0, - $previous + $previous, ); } } diff --git a/src/Exception/RuntimeException.php b/src/Exception/RuntimeException.php index e71f661ce..a84f5416e 100644 --- a/src/Exception/RuntimeException.php +++ b/src/Exception/RuntimeException.php @@ -16,7 +16,7 @@ public static function noMetadataForProperty(string $class, string $prop): self return new RuntimeException(sprintf( 'You must define a type for %s::$%s.', $class, - $prop + $prop, )); } } diff --git a/src/GraphNavigator/DeserializationGraphNavigator.php b/src/GraphNavigator/DeserializationGraphNavigator.php index 495df3f1f..a29e43c12 100644 --- a/src/GraphNavigator/DeserializationGraphNavigator.php +++ b/src/GraphNavigator/DeserializationGraphNavigator.php @@ -243,7 +243,7 @@ private function resolveMetadata($data, ClassMetadata $metadata): ?ClassMetadata 'The type value "%s" does not exist in the discriminator map of class "%s". Available types: %s', $typeValue, $metadata->name, - implode(', ', array_keys($metadata->discriminatorMap)) + implode(', ', array_keys($metadata->discriminatorMap)), )); } diff --git a/src/Handler/DateHandler.php b/src/Handler/DateHandler.php index da187b28a..ada72f76b 100644 --- a/src/Handler/DateHandler.php +++ b/src/Handler/DateHandler.php @@ -256,7 +256,7 @@ private function parseDateTime($data, array $type, bool $immutable = false): \Da throw new RuntimeException(sprintf( 'Invalid datetime "%s", expected one of the format %s.', $data, - '"' . implode('", "', $formatTried) . '"' + '"' . implode('", "', $formatTried) . '"', )); } diff --git a/src/Handler/FormErrorHandler.php b/src/Handler/FormErrorHandler.php index 48a8d8a0a..6951f3292 100644 --- a/src/Handler/FormErrorHandler.php +++ b/src/Handler/FormErrorHandler.php @@ -63,7 +63,7 @@ public function __construct(?object $translator = null, string $translationDomai self::class, TranslatorInterface::class, TranslatorContract::class, - get_class($translator) + get_class($translator), )); } diff --git a/src/JsonDeserializationVisitor.php b/src/JsonDeserializationVisitor.php index 2437521e9..625c8c722 100644 --- a/src/JsonDeserializationVisitor.php +++ b/src/JsonDeserializationVisitor.php @@ -142,7 +142,7 @@ public function visitDiscriminatorMapProperty($data, ClassMetadata $metadata): s throw new LogicException(sprintf( 'The discriminator field name "%s" for base-class "%s" was not found in input data.', $metadata->discriminatorFieldName, - $metadata->name + $metadata->name, )); } diff --git a/src/Metadata/ClassMetadata.php b/src/Metadata/ClassMetadata.php index 805ec294b..660f1e456 100644 --- a/src/Metadata/ClassMetadata.php +++ b/src/Metadata/ClassMetadata.php @@ -240,7 +240,7 @@ public function merge(MergeableInterface $object): void 'The discriminator of class "%s" would overwrite the discriminator of the parent class "%s". Please define all possible sub-classes in the discriminator of %s.', $object->name, $this->discriminatorBaseClass, - $this->discriminatorBaseClass + $this->discriminatorBaseClass, )); } elseif (!$this->discriminatorFieldName && $object->discriminatorFieldName) { $this->discriminatorFieldName = $object->discriminatorFieldName; @@ -359,7 +359,7 @@ private function handleDiscriminatorProperty(): void throw new InvalidMetadataException(sprintf( 'The sub-class "%s" is not listed in the discriminator of the base class "%s".', $this->name, - $this->discriminatorBaseClass + $this->discriminatorBaseClass, )); } @@ -373,7 +373,7 @@ private function handleDiscriminatorProperty(): void 'The discriminator field name "%s" of the base-class "%s" conflicts with a regular property of the sub-class "%s".', $this->discriminatorFieldName, $this->discriminatorBaseClass, - $this->name + $this->name, )); } @@ -381,7 +381,7 @@ private function handleDiscriminatorProperty(): void $this->name, $this->discriminatorFieldName, $typeValue, - $this->discriminatorGroups + $this->discriminatorGroups, ); $discriminatorProperty->serializedName = $this->discriminatorFieldName; $discriminatorProperty->xmlAttribute = $this->xmlDiscriminatorAttribute; diff --git a/src/Metadata/Driver/AnnotationOrAttributeDriver.php b/src/Metadata/Driver/AnnotationOrAttributeDriver.php index 5454f42ab..8e1b52343 100644 --- a/src/Metadata/Driver/AnnotationOrAttributeDriver.php +++ b/src/Metadata/Driver/AnnotationOrAttributeDriver.php @@ -132,7 +132,7 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat $virtualPropertyMetadata = new ExpressionPropertyMetadata( $name, $annot->name, - $this->parseExpression($annot->exp) + $this->parseExpression($annot->exp), ); $propertiesMetadata[] = $virtualPropertyMetadata; $propertiesAnnotations[] = $annot->options; @@ -248,7 +248,7 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat throw new InvalidMetadataException(sprintf( 'Invalid group name "%s" on "%s", did you mean to create multiple groups?', implode(', ', $propertyMetadata->groups), - $propertyMetadata->class . '->' . $propertyMetadata->name + $propertyMetadata->class . '->' . $propertyMetadata->name, )); } } @@ -310,7 +310,7 @@ protected function getClassAnnotations(\ReflectionClass $class): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - $class->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF) + $class->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF), ); } @@ -333,7 +333,7 @@ protected function getMethodAnnotations(\ReflectionMethod $method): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - $method->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF) + $method->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF), ); } @@ -356,7 +356,7 @@ protected function getPropertyAnnotations(\ReflectionProperty $property): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - $property->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF) + $property->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF), ); } diff --git a/src/Metadata/Driver/AttributeDriver.php b/src/Metadata/Driver/AttributeDriver.php index d00615a13..e966791c2 100644 --- a/src/Metadata/Driver/AttributeDriver.php +++ b/src/Metadata/Driver/AttributeDriver.php @@ -17,7 +17,7 @@ protected function getClassAnnotations(\ReflectionClass $class): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - $class->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF) + $class->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF), ); } @@ -30,7 +30,7 @@ protected function getMethodAnnotations(\ReflectionMethod $method): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - $method->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF) + $method->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF), ); } @@ -43,7 +43,7 @@ protected function getPropertyAnnotations(\ReflectionProperty $property): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - $property->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF) + $property->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF), ); } } diff --git a/src/Metadata/Driver/AttributeDriver/AttributeReader.php b/src/Metadata/Driver/AttributeDriver/AttributeReader.php index add4432f2..91e8aa83a 100644 --- a/src/Metadata/Driver/AttributeDriver/AttributeReader.php +++ b/src/Metadata/Driver/AttributeDriver/AttributeReader.php @@ -67,7 +67,10 @@ public function getPropertyAnnotation(ReflectionProperty $property, $annotationN return $this->reader->getClassAnnotation($property, $annotationName) ?? $this->buildAnnotation($attributes); } - private function buildAnnotation(array $attributes): ?object + /** + * @param list<\ReflectionAttribute> $attributes + */ + private function buildAnnotation(array $attributes): ?SerializerAttribute { if (!isset($attributes[0])) { return null; @@ -85,7 +88,7 @@ private function buildAnnotations(array $attributes): array static function (\ReflectionAttribute $attribute): object { return $attribute->newInstance(); }, - $attributes + $attributes, ); } } diff --git a/src/Metadata/Driver/DocBlockDriver.php b/src/Metadata/Driver/DocBlockDriver.php index f7b1f97e3..b8ce046b3 100644 --- a/src/Metadata/Driver/DocBlockDriver.php +++ b/src/Metadata/Driver/DocBlockDriver.php @@ -70,11 +70,11 @@ public function loadMetadataForClass(ReflectionClass $class): ?ClassMetadata try { if ($propertyMetadata instanceof VirtualPropertyMetadata) { $type = $this->docBlockTypeResolver->getMethodDocblockTypeHint( - new ReflectionMethod($propertyMetadata->class, $propertyMetadata->getter) + new ReflectionMethod($propertyMetadata->class, $propertyMetadata->getter), ); } else { $type = $this->docBlockTypeResolver->getPropertyDocblockTypeHint( - new ReflectionProperty($propertyMetadata->class, $propertyMetadata->name) + new ReflectionProperty($propertyMetadata->class, $propertyMetadata->name), ); } diff --git a/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php b/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php index f3ff04645..4e43cf6e0 100644 --- a/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php +++ b/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php @@ -429,7 +429,7 @@ private function getPhpstanType(\ReflectionClass $declaringClass, string $typeHi ',', array_map(static function (string $type) use ($reflector, $self) { return $self->resolveType(trim($type), $reflector); - }, $types) + }, $types), )); } } diff --git a/src/Metadata/Driver/DoctrineTypeDriver.php b/src/Metadata/Driver/DoctrineTypeDriver.php index 63592e8be..e51f8d5c4 100644 --- a/src/Metadata/Driver/DoctrineTypeDriver.php +++ b/src/Metadata/Driver/DoctrineTypeDriver.php @@ -27,7 +27,7 @@ protected function setDiscriminator(DoctrineClassMetadata $doctrineMetadata, Cla ) { $classMetadata->setDiscriminator( $doctrineMetadata->discriminatorColumn['name'], - $doctrineMetadata->discriminatorMap + $doctrineMetadata->discriminatorMap, ); } } diff --git a/src/Metadata/Driver/TypedPropertiesDriver.php b/src/Metadata/Driver/TypedPropertiesDriver.php index c3ebbefe4..ed41807eb 100644 --- a/src/Metadata/Driver/TypedPropertiesDriver.php +++ b/src/Metadata/Driver/TypedPropertiesDriver.php @@ -74,10 +74,6 @@ public function loadMetadataForClass(ReflectionClass $class): ?ClassMetadata \assert($classMetadata instanceof SerializerClassMetadata); - if (PHP_VERSION_ID <= 70400) { - return $classMetadata; - } - // We base our scan on the internal driver's property list so that we // respect any internal allow/blocklist like in the AnnotationDriver foreach ($classMetadata->propertyMetadata as $propertyMetadata) { diff --git a/src/Metadata/Driver/XmlDriver.php b/src/Metadata/Driver/XmlDriver.php index dd5436709..a6ba580ec 100644 --- a/src/Metadata/Driver/XmlDriver.php +++ b/src/Metadata/Driver/XmlDriver.php @@ -155,7 +155,7 @@ protected function loadMetadataFromFile(\ReflectionClass $class, string $path): $virtualPropertyMetadata = new ExpressionPropertyMetadata( $name, (string) $method->attributes()->name, - $this->parseExpression((string) $method->attributes()->expression) + $this->parseExpression((string) $method->attributes()->expression), ); } else { if (!isset($method->attributes()->method)) { @@ -326,7 +326,7 @@ protected function loadMetadataFromFile(\ReflectionClass $class, string $path): $pMetadata->setAccessor( (string) ($pElem->attributes()->{'access-type'} ?: $classAccessType), $getter ? (string) $getter : null, - $setter ? (string) $setter : null + $setter ? (string) $setter : null, ); if (null !== $inline = $pElem->attributes()->inline) { diff --git a/src/Metadata/Driver/YamlDriver.php b/src/Metadata/Driver/YamlDriver.php index 60d52762d..8dd61f10e 100644 --- a/src/Metadata/Driver/YamlDriver.php +++ b/src/Metadata/Driver/YamlDriver.php @@ -74,8 +74,8 @@ public function getAllClassNames(): array throw new RuntimeException( sprintf( 'Locator "%s" must be an instance of "AdvancedFileLocatorInterface".', - get_class($this->locator) - ) + get_class($this->locator), + ), ); } @@ -95,7 +95,7 @@ protected function loadMetadataFromFile(ReflectionClass $class, string $file): ? if (!isset($config[$name = $class->name])) { throw new InvalidMetadataException( - sprintf('Expected metadata for class %s to be defined in %s.', $class->name, $file) + sprintf('Expected metadata for class %s to be defined in %s.', $class->name, $file), ); } @@ -126,13 +126,13 @@ protected function loadMetadataFromFile(ReflectionClass $class, string $file): ? $virtualPropertyMetadata = new ExpressionPropertyMetadata( $name, $methodName, - $this->parseExpression($propertySettings['exp']) + $this->parseExpression($propertySettings['exp']), ); unset($propertySettings['exp']); } else { if (!$class->hasMethod($methodName)) { throw new InvalidMetadataException( - 'The method ' . $methodName . ' not found in class ' . $class->name + 'The method ' . $methodName . ' not found in class ' . $class->name, ); } @@ -290,7 +290,7 @@ protected function loadMetadataFromFile(ReflectionClass $class, string $file): ? $pMetadata->setAccessor( $pConfig['access_type'] ?? $classAccessType, $pConfig['accessor']['getter'] ?? null, - $pConfig['accessor']['setter'] ?? null + $pConfig['accessor']['setter'] ?? null, ); if (isset($pConfig['inline'])) { @@ -397,7 +397,7 @@ private function addClassProperties(ClassMetadata $metadata, array $config): voi if (!isset($config['discriminator']['map']) || !is_array($config['discriminator']['map'])) { throw new InvalidMetadataException( - 'The "map" attribute must be set, and be an array for discriminators.' + 'The "map" attribute must be set, and be an array for discriminators.', ); } @@ -405,7 +405,7 @@ private function addClassProperties(ClassMetadata $metadata, array $config): voi $metadata->setDiscriminator( $config['discriminator']['field_name'], $config['discriminator']['map'], - $groups + $groups, ); if (isset($config['discriminator']['xml_attribute'])) { @@ -436,8 +436,8 @@ private function getCallbackMetadata(ReflectionClass $class, $config): array throw new InvalidMetadataException( sprintf( 'callback methods expects a string, or an array of strings that represent method names, but got %s.', - json_encode($config['pre_serialize']) - ) + json_encode($config['pre_serialize']), + ), ); } @@ -445,7 +445,7 @@ private function getCallbackMetadata(ReflectionClass $class, $config): array foreach ($config as $name) { if (!$class->hasMethod($name)) { throw new InvalidMetadataException( - sprintf('The method %s does not exist in class %s.', $name, $class->name) + sprintf('The method %s does not exist in class %s.', $name, $class->name), ); } diff --git a/src/Ordering/AlphabeticalPropertyOrderingStrategy.php b/src/Ordering/AlphabeticalPropertyOrderingStrategy.php index 09d8a65a5..a60d3cb09 100644 --- a/src/Ordering/AlphabeticalPropertyOrderingStrategy.php +++ b/src/Ordering/AlphabeticalPropertyOrderingStrategy.php @@ -17,7 +17,7 @@ public function order(array $properties): array $properties, static function (PropertyMetadata $a, PropertyMetadata $b): int { return strcmp($a->name, $b->name); - } + }, ); return $properties; diff --git a/src/Serializer.php b/src/Serializer.php index af0540596..1dc7e6ca8 100644 --- a/src/Serializer.php +++ b/src/Serializer.php @@ -119,8 +119,8 @@ private function getNavigator(int $direction): GraphNavigatorInterface throw new RuntimeException( sprintf( 'Can not find a graph navigator for the direction "%s".', - GraphNavigatorInterface::DIRECTION_SERIALIZATION === $direction ? 'serialization' : 'deserialization' - ) + GraphNavigatorInterface::DIRECTION_SERIALIZATION === $direction ? 'serialization' : 'deserialization', + ), ); } @@ -138,8 +138,8 @@ private function getVisitor(int $direction, string $format): VisitorInterface sprintf( 'The format "%s" is not supported for %s.', $format, - GraphNavigatorInterface::DIRECTION_SERIALIZATION === $direction ? 'serialization' : 'deserialization' - ) + GraphNavigatorInterface::DIRECTION_SERIALIZATION === $direction ? 'serialization' : 'deserialization', + ), ); } @@ -206,7 +206,7 @@ public function toArray($data, ?SerializationContext $context = null, ?string $t throw new RuntimeException(sprintf( 'The input data of type "%s" did not convert to an array, but got a result of type "%s".', \is_object($data) ? \get_class($data) : \gettype($data), - \is_object($result) ? \get_class($result) : \gettype($result) + \is_object($result) ? \get_class($result) : \gettype($result), )); } @@ -239,7 +239,7 @@ private function visit(GraphNavigatorInterface $navigator, VisitorInterface $vis $format, $visitor, $navigator, - $this->factory + $this->factory, ); $visitor->setNavigator($navigator); diff --git a/src/SerializerBuilder.php b/src/SerializerBuilder.php index 47fa2d299..45f42f4a8 100644 --- a/src/SerializerBuilder.php +++ b/src/SerializerBuilder.php @@ -497,7 +497,7 @@ public function setSerializationContextFactory($serializationContextFactory): se $this->serializationContextFactory = $serializationContextFactory; } elseif (is_callable($serializationContextFactory)) { $this->serializationContextFactory = new CallableSerializationContextFactory( - $serializationContextFactory + $serializationContextFactory, ); } else { throw new InvalidArgumentException('expected SerializationContextFactoryInterface or callable.'); @@ -515,7 +515,7 @@ public function setDeserializationContextFactory($deserializationContextFactory) $this->deserializationContextFactory = $deserializationContextFactory; } elseif (is_callable($deserializationContextFactory)) { $this->deserializationContextFactory = new CallableDeserializationContextFactory( - $deserializationContextFactory + $deserializationContextFactory, ); } else { throw new InvalidArgumentException('expected DeserializationContextFactoryInterface or callable.'); @@ -562,7 +562,7 @@ public function build(): Serializer $this->driverFactory = new DefaultDriverFactory( $this->propertyNamingStrategy, $this->typeParser, - $this->expressionEvaluator instanceof CompilableExpressionEvaluatorInterface ? $this->expressionEvaluator : null + $this->expressionEvaluator instanceof CompilableExpressionEvaluatorInterface ? $this->expressionEvaluator : null, ); $this->driverFactory->enableEnumSupport($this->enableEnumSupport); } @@ -611,7 +611,7 @@ public function build(): Serializer $this->deserializationVisitors, $this->serializationContextFactory, $this->deserializationContextFactory, - $this->typeParser + $this->typeParser, ); } @@ -622,7 +622,7 @@ private function getSerializationNavigatorFactory(MetadataFactoryInterface $meta $this->handlerRegistry, $this->getAccessorStrategy(), $this->eventDispatcher, - $this->expressionEvaluator + $this->expressionEvaluator, ); } @@ -634,7 +634,7 @@ private function getDeserializationNavigatorFactory(MetadataFactoryInterface $me $this->objectConstructor ?: new UnserializeObjectConstructor(), $this->getAccessorStrategy(), $this->eventDispatcher, - $this->expressionEvaluator + $this->expressionEvaluator, ); } diff --git a/src/Type/Parser.php b/src/Type/Parser.php index ab7d361a7..560345c13 100644 --- a/src/Type/Parser.php +++ b/src/Type/Parser.php @@ -39,7 +39,7 @@ private function visit() if (!$this->lexer->token) { throw new SyntaxError( - 'Syntax error, unexpected end of stream' + 'Syntax error, unexpected end of stream', ); } @@ -66,7 +66,7 @@ private function visit() throw new SyntaxError(sprintf( 'Syntax error, unexpected "%s" (%s)', $this->lexer->token->value, - $this->getConstant($this->lexer->token->type) + $this->getConstant($this->lexer->token->type), )); } @@ -135,7 +135,7 @@ private function match(int $token): void { if (!$this->lexer->lookahead) { throw new SyntaxError( - sprintf('Syntax error, unexpected end of stream, expected %s', $this->getConstant($token)) + sprintf('Syntax error, unexpected end of stream, expected %s', $this->getConstant($token)), ); } @@ -149,7 +149,7 @@ private function match(int $token): void 'Syntax error, unexpected "%s" (%s), expected was %s', $this->lexer->lookahead->value, $this->getConstant($this->lexer->lookahead->type), - $this->getConstant($token) + $this->getConstant($token), )); } diff --git a/src/Visitor/Factory/XmlSerializationVisitorFactory.php b/src/Visitor/Factory/XmlSerializationVisitorFactory.php index 10541a457..be7f0eb05 100644 --- a/src/Visitor/Factory/XmlSerializationVisitorFactory.php +++ b/src/Visitor/Factory/XmlSerializationVisitorFactory.php @@ -44,7 +44,7 @@ public function getVisitor(): SerializationVisitorInterface $this->defaultEncoding, $this->defaultVersion, $this->defaultRootName, - $this->defaultRootNamespace + $this->defaultRootNamespace, ); } diff --git a/src/XmlDeserializationVisitor.php b/src/XmlDeserializationVisitor.php index a2ba33016..1efa3c90c 100644 --- a/src/XmlDeserializationVisitor.php +++ b/src/XmlDeserializationVisitor.php @@ -88,7 +88,7 @@ public function prepare($data) if (!in_array($internalSubset, $this->doctypeAllowList, true)) { throw new InvalidArgumentException(sprintf( 'The document type "%s" is not allowed. If it is safe, you may add it to the allowlist configuration.', - $internalSubset + $internalSubset, )); } } @@ -288,7 +288,7 @@ public function visitDiscriminatorMapProperty($data, ClassMetadata $metadata): s throw new LogicException(sprintf( 'The discriminator field name "%s" for base-class "%s" was not found in input data.', $metadata->discriminatorFieldName, - $metadata->name + $metadata->name, )); } } diff --git a/src/XmlSerializationVisitor.php b/src/XmlSerializationVisitor.php index ffa1e1419..ae150aa66 100644 --- a/src/XmlSerializationVisitor.php +++ b/src/XmlSerializationVisitor.php @@ -401,7 +401,7 @@ public function getResult($node) $this->document->documentElement->setAttributeNS( 'http://www.w3.org/2000/xmlns/', 'xmlns:xsi', - 'http://www.w3.org/2001/XMLSchema-instance' + 'http://www.w3.org/2001/XMLSchema-instance', ); } diff --git a/tests/Benchmark/AbstractSerializationBench.php b/tests/Benchmark/AbstractSerializationBench.php index c0fd5dbf8..8925f5920 100644 --- a/tests/Benchmark/AbstractSerializationBench.php +++ b/tests/Benchmark/AbstractSerializationBench.php @@ -81,7 +81,7 @@ private function createPost() 'FooooooooooooooooooooooBAR', new Author('Foo'), new \DateTime(), - new Publisher('bar') + new Publisher('bar'), ); for ($i = 0; $i < $this->amountOfComments; $i++) { $post->addComment(new Comment(new Author('foo'), 'foobar')); diff --git a/tests/Fixtures/ObjectWithXmlKeyValuePairsWithObjectType.php b/tests/Fixtures/ObjectWithXmlKeyValuePairsWithObjectType.php index 548e4a85d..c625b1f69 100644 --- a/tests/Fixtures/ObjectWithXmlKeyValuePairsWithObjectType.php +++ b/tests/Fixtures/ObjectWithXmlKeyValuePairsWithObjectType.php @@ -29,7 +29,7 @@ public static function create1() [ 'key_first' => ObjectWithXmlKeyValuePairsWithType::create1(), 'key_second' => ObjectWithXmlKeyValuePairsWithType::create2(), - ] + ], ); } } diff --git a/tests/Fixtures/ObjectWithXmlKeyValuePairsWithType.php b/tests/Fixtures/ObjectWithXmlKeyValuePairsWithType.php index 77e5bd59d..d0bece018 100644 --- a/tests/Fixtures/ObjectWithXmlKeyValuePairsWithType.php +++ b/tests/Fixtures/ObjectWithXmlKeyValuePairsWithType.php @@ -37,7 +37,7 @@ public static function create1() [ 'key-one' => 'foo', 'key-two' => 'bar', - ] + ], ); } @@ -49,7 +49,7 @@ public static function create2() 'key_02' => 'Two', 'key_03' => 'Three', ], - ['Four'] + ['Four'], ); } } diff --git a/tests/Handler/DateHandlerTest.php b/tests/Handler/DateHandlerTest.php index 78c99061c..17b00c0ac 100644 --- a/tests/Handler/DateHandlerTest.php +++ b/tests/Handler/DateHandlerTest.php @@ -90,7 +90,7 @@ public function testTimePartGetsRemoved() $type = ['name' => 'DateTime', 'params' => ['Y-m-d', '', 'Y-m-d|']]; self::assertEquals( \DateTime::createFromFormat('Y-m-d|', '2017-06-18', $this->timezone), - $this->handler->deserializeDateTimeFromJson($visitor, '2017-06-18', $type) + $this->handler->deserializeDateTimeFromJson($visitor, '2017-06-18', $type), ); } @@ -101,7 +101,7 @@ public function testMultiFormatCase() $type = ['name' => 'DateTime', 'params' => ['Y-m-d', '', ['Y-m-d|', 'Y/m/d']]]; self::assertEquals( \DateTime::createFromFormat('Y/m/d', '2017/06/18', $this->timezone), - $this->handler->deserializeDateTimeFromJson($visitor, '2017/06/18', $type) + $this->handler->deserializeDateTimeFromJson($visitor, '2017/06/18', $type), ); } @@ -121,14 +121,14 @@ public function testTimePartGetsPreserved() $type = ['name' => 'DateTime', 'params' => ['Y-m-d']]; self::assertEquals( $expectedDateTime, - $this->handler->deserializeDateTimeFromJson($visitor, '2017-06-18', $type) + $this->handler->deserializeDateTimeFromJson($visitor, '2017-06-18', $type), ); // custom deserialization format specified $type = ['name' => 'DateTime', 'params' => ['Y-m-d', '', 'Y-m-d']]; self::assertEquals( $expectedDateTime, - $this->handler->deserializeDateTimeFromJson($visitor, '2017-06-18', $type) + $this->handler->deserializeDateTimeFromJson($visitor, '2017-06-18', $type), ); } @@ -147,7 +147,7 @@ public function testTimeZoneGetsPreservedWithUnixTimestamp() self::assertEquals( $expectedDateTime->format(\DateTime::RFC3339), - $actualDateTime->format(\DateTime::RFC3339) + $actualDateTime->format(\DateTime::RFC3339), ); } @@ -166,7 +166,7 @@ public function testImmutableTimeZoneGetsPreservedWithUnixTimestamp() self::assertEquals( $expectedDateTime->format(\DateTime::RFC3339), - $actualDateTime->format(\DateTime::RFC3339) + $actualDateTime->format(\DateTime::RFC3339), ); } } diff --git a/tests/Handler/FormErrorHandlerTest.php b/tests/Handler/FormErrorHandlerTest.php index 5f15f92da..353b6c20a 100644 --- a/tests/Handler/FormErrorHandlerTest.php +++ b/tests/Handler/FormErrorHandlerTest.php @@ -150,7 +150,7 @@ public function testDefaultTranslationDomain() ->with( $this->equalTo('error!'), $this->equalTo([]), - $this->equalTo('validators') + $this->equalTo('validators'), ); $formError = $this->getMockBuilder('Symfony\Component\Form\FormError')->disableOriginalConstructor()->getMock(); @@ -177,7 +177,7 @@ public function testDefaultTranslationDomainWithPluralTranslation() ->with( $this->equalTo('error!'), $this->equalTo(['%count%' => 0]), - $this->equalTo('validators') + $this->equalTo('validators'), ); } else { $translator->expects($this->once()) @@ -186,7 +186,7 @@ public function testDefaultTranslationDomainWithPluralTranslation() $this->equalTo('error!'), $this->equalTo(0), $this->equalTo([]), - $this->equalTo('validators') + $this->equalTo('validators'), ); } @@ -213,7 +213,7 @@ public function testCustomTranslationDomain() ->with( $this->equalTo('error!'), $this->equalTo([]), - $this->equalTo('custom_domain') + $this->equalTo('custom_domain'), ); $formError = $this->getMockBuilder('Symfony\Component\Form\FormError')->disableOriginalConstructor()->getMock(); @@ -241,7 +241,7 @@ public function testCustomTranslationDomainWithPluralTranslation() ->with( $this->equalTo('error!'), $this->equalTo(['%count%' => 0]), - $this->equalTo('custom_domain') + $this->equalTo('custom_domain'), ); } else { $translator->expects($this->once()) @@ -250,7 +250,7 @@ public function testCustomTranslationDomainWithPluralTranslation() $this->equalTo('error!'), $this->equalTo(0), $this->equalTo([]), - $this->equalTo('custom_domain') + $this->equalTo('custom_domain'), ); } diff --git a/tests/Handler/IteratorHandlerTest.php b/tests/Handler/IteratorHandlerTest.php index ec40747b4..bc2affafd 100644 --- a/tests/Handler/IteratorHandlerTest.php +++ b/tests/Handler/IteratorHandlerTest.php @@ -46,7 +46,7 @@ public function testSerialize(\Iterator $iterator): void $serializationHandler = $this->handlerRegistry->getHandler( GraphNavigatorInterface::DIRECTION_SERIALIZATION, $type, - 'json' + 'json', ); self::assertIsCallable($serializationHandler); @@ -54,14 +54,14 @@ public function testSerialize(\Iterator $iterator): void $this->createSerializationVisitor(), $iterator, ['name' => $type, 'params' => []], - $this->getMockBuilder(SerializationContext::class)->getMock() + $this->getMockBuilder(SerializationContext::class)->getMock(), ); self::assertSame(self::DATA, $serialized); $deserializationHandler = $this->handlerRegistry->getHandler( GraphNavigatorInterface::DIRECTION_DESERIALIZATION, $type, - 'json' + 'json', ); self::assertIsCallable($deserializationHandler); @@ -69,7 +69,7 @@ public function testSerialize(\Iterator $iterator): void $this->createDeserializationVisitor(), $serialized, ['name' => $type, 'params' => []], - $this->getMockBuilder(DeserializationContext::class)->getMock() + $this->getMockBuilder(DeserializationContext::class)->getMock(), ); self::assertEquals($iterator, $deserialized); } diff --git a/tests/Handler/SymfonyUidHandlerTest.php b/tests/Handler/SymfonyUidHandlerTest.php index 7f0dbf956..1a5a2f41a 100644 --- a/tests/Handler/SymfonyUidHandlerTest.php +++ b/tests/Handler/SymfonyUidHandlerTest.php @@ -50,7 +50,7 @@ public function testSerializeUidToJson(AbstractUid $uid): void { self::assertJsonStringEqualsJsonString( sprintf('"%s"', (string) $uid), - $this->createSerializer()->serialize($uid, 'json', null, AbstractUid::class) + $this->createSerializer()->serialize($uid, 'json', null, AbstractUid::class), ); } @@ -61,7 +61,7 @@ public function testSerializeUidToXmlWithCData(AbstractUid $uid): void { self::assertXmlStringEqualsXmlString( sprintf('%s', (string) $uid), - $this->createSerializer()->serialize($uid, 'xml', null, AbstractUid::class) + $this->createSerializer()->serialize($uid, 'xml', null, AbstractUid::class), ); } @@ -72,7 +72,7 @@ public function testSerializeUidToXmlWithoutCData(AbstractUid $uid): void { self::assertXmlStringEqualsXmlString( sprintf('%s', (string) $uid), - $this->createSerializer(false)->serialize($uid, 'xml', null, AbstractUid::class) + $this->createSerializer(false)->serialize($uid, 'xml', null, AbstractUid::class), ); } @@ -82,7 +82,7 @@ public function testSerializeUidToBase32(): void self::assertJsonStringEqualsJsonString( sprintf('"%s"', $uid->toBase32()), - $this->createSerializer()->serialize($uid, 'json', null, sprintf('%s<%s>', AbstractUid::class, SymfonyUidHandler::FORMAT_BASE32)) + $this->createSerializer()->serialize($uid, 'json', null, sprintf('%s<%s>', AbstractUid::class, SymfonyUidHandler::FORMAT_BASE32)), ); } @@ -92,7 +92,7 @@ public function testSerializeUidToBase58(): void self::assertJsonStringEqualsJsonString( sprintf('"%s"', $uid->toBase58()), - $this->createSerializer()->serialize($uid, 'json', null, sprintf('%s<%s>', AbstractUid::class, SymfonyUidHandler::FORMAT_BASE58)) + $this->createSerializer()->serialize($uid, 'json', null, sprintf('%s<%s>', AbstractUid::class, SymfonyUidHandler::FORMAT_BASE58)), ); } @@ -102,7 +102,7 @@ public function testSerializeUidToRfc4122(): void self::assertJsonStringEqualsJsonString( sprintf('"%s"', $uid->toRfc4122()), - $this->createSerializer()->serialize($uid, 'json', null, sprintf('%s<%s>', AbstractUid::class, SymfonyUidHandler::FORMAT_RFC4122)) + $this->createSerializer()->serialize($uid, 'json', null, sprintf('%s<%s>', AbstractUid::class, SymfonyUidHandler::FORMAT_RFC4122)), ); } diff --git a/tests/Metadata/Driver/BaseDriverTestCase.php b/tests/Metadata/Driver/BaseDriverTestCase.php index 8236d84b8..656adca7a 100644 --- a/tests/Metadata/Driver/BaseDriverTestCase.php +++ b/tests/Metadata/Driver/BaseDriverTestCase.php @@ -240,7 +240,7 @@ public function testLoadDiscriminator() 'car' => 'JMS\Serializer\Tests\Fixtures\Discriminator\Car', 'moped' => 'JMS\Serializer\Tests\Fixtures\Discriminator\Moped', ], - $m->discriminatorMap + $m->discriminatorMap, ); } @@ -257,7 +257,7 @@ public function testLoadDiscriminatorWhenParentIsInDiscriminatorMap() 'post' => 'JMS\Serializer\Tests\Fixtures\Discriminator\Post', 'image_post' => 'JMS\Serializer\Tests\Fixtures\Discriminator\ImagePost', ], - $m->discriminatorMap + $m->discriminatorMap, ); } @@ -273,7 +273,7 @@ public function testLoadXmlDiscriminator() [ 'child' => ObjectWithXmlAttributeDiscriminatorChild::class, ], - $m->discriminatorMap + $m->discriminatorMap, ); self::assertTrue($m->xmlDiscriminatorAttribute); self::assertFalse($m->xmlDiscriminatorCData); @@ -291,7 +291,7 @@ public function testLoadXmlDiscriminatorWithNamespaces() [ 'child' => ObjectWithXmlNamespaceDiscriminatorChild::class, ], - $m->discriminatorMap + $m->discriminatorMap, ); self::assertEquals('http://example.com/', $m->xmlDiscriminatorNamespace); self::assertFalse($m->xmlDiscriminatorAttribute); @@ -320,7 +320,7 @@ public function testLoadXmlDiscriminatorWithAttributeNamespaces() [ 'child' => ObjectWithXmlNamespaceAttributeDiscriminatorChild::class, ], - $m->discriminatorMap + $m->discriminatorMap, ); self::assertEquals('http://example.com/', $m->xmlDiscriminatorNamespace); self::assertTrue($m->xmlDiscriminatorAttribute); @@ -337,7 +337,7 @@ public function testLoadDiscriminatorWithGroup() self::assertEquals($m->name, $m->discriminatorBaseClass); self::assertEquals( ['car' => 'JMS\Serializer\Tests\Fixtures\DiscriminatorGroup\Car'], - $m->discriminatorMap + $m->discriminatorMap, ); } diff --git a/tests/Metadata/Driver/DefaultDriverFactoryTest.php b/tests/Metadata/Driver/DefaultDriverFactoryTest.php index cd9258871..6f068c875 100644 --- a/tests/Metadata/Driver/DefaultDriverFactoryTest.php +++ b/tests/Metadata/Driver/DefaultDriverFactoryTest.php @@ -15,10 +15,6 @@ class DefaultDriverFactoryTest extends TestCase { public function testDefaultDriverFactoryLoadsTypedPropertiesDriver() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', __METHOD__)); - } - $factory = new DefaultDriverFactory(new IdenticalPropertyNamingStrategy()); $driver = $factory->createDriver([], new AnnotationReader()); diff --git a/tests/Metadata/Driver/DocBlockDriverTest.php b/tests/Metadata/Driver/DocBlockDriverTest.php index 74ada8afa..414aa4a78 100644 --- a/tests/Metadata/Driver/DocBlockDriverTest.php +++ b/tests/Metadata/Driver/DocBlockDriverTest.php @@ -62,9 +62,7 @@ private function resolve(string $classToResolve): ClassMetadata new NullDriver($namingStrategy), ]); - if (PHP_VERSION_ID > 70400) { - $driver = new TypedPropertiesDriver($driver); - } + $driver = new TypedPropertiesDriver($driver); $driver = new DocBlockDriver($driver); @@ -76,122 +74,86 @@ private function resolve(string $classToResolve): ClassMetadata public function testInferDocBlockCollectionOfScalars() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfScalars::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => 'string', 'params' => []]]], - $m->propertyMetadata['productIds']->type + $m->propertyMetadata['productIds']->type, ); } public function testInferDocBlockCollectionAsList(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionAsList::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => 'int', 'params' => []], ['name' => 'string', 'params' => []]]], - $m->propertyMetadata['productIds']->type + $m->propertyMetadata['productIds']->type, ); } public function testInferDocBlockCollectionOfClassesFromSameNamespace() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfClassesFromSameNamespace::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => Product::class, 'params' => []]]], - $m->propertyMetadata['productIds']->type + $m->propertyMetadata['productIds']->type, ); } public function testInferDocBlockCollectionOfClassesFromUsingFullNamespacePath() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfClassesWithFullNamespacePath::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => Product::class, 'params' => []]]], - $m->propertyMetadata['productIds']->type + $m->propertyMetadata['productIds']->type, ); } public function testInferDocBlockCollectionFromGenericLikeClass() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionTypedAsGenericClass::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => Product::class, 'params' => []]]], - $m->propertyMetadata['productIds']->type + $m->propertyMetadata['productIds']->type, ); } public function testInferDocBlockMapFromGenericLikeClass() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(MapTypedAsGenericClass::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => 'int', 'params' => []], ['name' => Product::class, 'params' => []]]], - $m->propertyMetadata['productIds']->type + $m->propertyMetadata['productIds']->type, ); } public function testInferDocBlockCollectionOfClassesIgnoringNullTypeHint() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfClassesWithNull::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => Product::class, 'params' => []]]], - $m->propertyMetadata['productIds']->type + $m->propertyMetadata['productIds']->type, ); } public function testInferDocBlockCollectionOfClassesIgnoringNullTypeHintWithSingleLinePhpDoc() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfClassesWithNullSingleLinePhpDoc::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => Product::class, 'params' => []]]], - $m->propertyMetadata['productIds']->type + $m->propertyMetadata['productIds']->type, ); } public function testThrowingExceptionWhenNotExistingClassWasGiven() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $this->expectException(\InvalidArgumentException::class); $this->resolve(CollectionOfNotExistingClasses::class); @@ -199,149 +161,109 @@ public function testThrowingExceptionWhenNotExistingClassWasGiven() public function testInferDocBlockCollectionOfClassesFromDifferentNamespace() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfClassesFromDifferentNamespace::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => ProductDescription::class, 'params' => []]]], - $m->propertyMetadata['productDescriptions']->type + $m->propertyMetadata['productDescriptions']->type, ); } public function testInferDocBlockCollectionOfClassesFromGlobalNamespace() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfClassesFromGlobalNamespace::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => \stdClass::class, 'params' => []]]], - $m->propertyMetadata['products']->type + $m->propertyMetadata['products']->type, ); } public function testInferDocBlockCollectionOfClassesFromDifferentNamespaceUsingSingleAlias() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfClassesFromDifferentNamespaceUsingSingleAlias::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => ProductDescription::class, 'params' => []]]], - $m->propertyMetadata['productDescriptions']->type + $m->propertyMetadata['productDescriptions']->type, ); } public function testInferDocBlockCollectionOfClassesFromDifferentNamespaceUsingGroupAlias() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfClassesFromDifferentNamespaceUsingGroupAlias::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => ProductDescription::class, 'params' => []]]], - $m->propertyMetadata['productDescriptions']->type + $m->propertyMetadata['productDescriptions']->type, ); self::assertEquals( ['name' => 'array', 'params' => [['name' => ProductName::class, 'params' => []]]], - $m->propertyMetadata['productNames']->type + $m->propertyMetadata['productNames']->type, ); } public function testInferDocBlockCollectionOfClassesFromTraits() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfClassesFromTrait::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => ProductDescription::class, 'params' => []]]], - $m->propertyMetadata['productDescriptions']->type + $m->propertyMetadata['productDescriptions']->type, ); self::assertEquals( ['name' => 'array', 'params' => [['name' => ProductName::class, 'params' => []]]], - $m->propertyMetadata['productNames']->type + $m->propertyMetadata['productNames']->type, ); } public function testInferDocBlockCollectionOfClassesFromTraitInsideTrait() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfClassesFromTraitInsideTrait::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => ProductDescription::class, 'params' => []]]], - $m->propertyMetadata['productDescriptions']->type + $m->propertyMetadata['productDescriptions']->type, ); } public function testInferDocBlockCollectionOfInterfacesFromDifferentNamespace() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfInterfacesFromDifferentNamespace::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => ProductColor::class, 'params' => []]]], - $m->propertyMetadata['productColors']->type + $m->propertyMetadata['productColors']->type, ); } public function testInferDocBlockCollectionOfInterfacesFromGlobalNamespace() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfInterfacesFromGlobalNamespace::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => ProductColor::class, 'params' => []]]], - $m->propertyMetadata['productColors']->type + $m->propertyMetadata['productColors']->type, ); } public function testInferDocBlockCollectionOfInterfacesFromSameNamespace() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfInterfacesFromSameNamespace::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => Vehicle::class, 'params' => []]]], - $m->propertyMetadata['vehicles']->type + $m->propertyMetadata['vehicles']->type, ); } public function testInferDocBlockCollectionOfInterfacesWithFullNamespacePath() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - $m = $this->resolve(CollectionOfInterfacesWithFullNamespacePath::class); self::assertEquals( ['name' => 'array', 'params' => [['name' => ProductColor::class, 'params' => []]]], - $m->propertyMetadata['productColors']->type + $m->propertyMetadata['productColors']->type, ); } @@ -351,7 +273,7 @@ public function testInferTypeForNonCollectionFromSameNamespaceType() self::assertEquals( ['name' => \stdClass::class, 'params' => []], - $m->propertyMetadata['data']->type + $m->propertyMetadata['data']->type, ); } @@ -361,7 +283,7 @@ public function testInferTypeForNonCollectionFromDifferentNamespaceType() self::assertEquals( ['name' => ProductDescription::class, 'params' => []], - $m->propertyMetadata['data']->type + $m->propertyMetadata['data']->type, ); } @@ -371,7 +293,7 @@ public function testInferTypeForNonUnionDocblockType() self::assertEquals( null, - $m->propertyMetadata['data']->type + $m->propertyMetadata['data']->type, ); } @@ -385,7 +307,7 @@ public function testInferTypeForConstructorPropertyPromotion() self::assertEquals( ['name' => 'array', 'params' => [['name' => 'string', 'params' => []]]], - $m->propertyMetadata['data']->type + $m->propertyMetadata['data']->type, ); } @@ -399,7 +321,7 @@ public function testInferTypeForConstructorPropertyPromotionWithoutDocblock() self::assertEquals( null, - $m->propertyMetadata['data']->type + $m->propertyMetadata['data']->type, ); } @@ -413,7 +335,7 @@ public function testInferTypeForConstructorPropertyPromotionWithScalar() self::assertEquals( ['name' => 'string', 'params' => []], - $m->propertyMetadata['data']->type + $m->propertyMetadata['data']->type, ); } @@ -423,7 +345,7 @@ public function testInferTypeForPhpstanArray() self::assertEquals( ['name' => 'array', 'params' => []], - $m->propertyMetadata['data']->type + $m->propertyMetadata['data']->type, ); } @@ -433,7 +355,7 @@ public function testInferTypeForPhpstanNestedArrayShape() self::assertEquals( ['name' => 'array', 'params' => []], - $m->propertyMetadata['data']->type + $m->propertyMetadata['data']->type, ); } @@ -443,11 +365,11 @@ public function testInferTypeForMultiplePhpstanArray() self::assertEquals( ['name' => 'array', 'params' => []], - $m->propertyMetadata['data']->type + $m->propertyMetadata['data']->type, ); self::assertEquals( ['name' => 'array', 'params' => []], - $m->propertyMetadata['details']->type + $m->propertyMetadata['details']->type, ); } @@ -457,7 +379,7 @@ public function testInferTypeForPhpstanArrayCollection() self::assertEquals( ['name' => 'array', 'params' => [['name' => 'int', 'params' => []], ['name' => ProductType::class, 'params' => []]]], - $m->propertyMetadata['data']->type + $m->propertyMetadata['data']->type, ); } @@ -467,7 +389,7 @@ public function testInferTypeForVirtualPropertyGetter() self::assertEquals( ['name' => 'array', 'params' => [['name' => 'string', 'params' => []]]], - $m->propertyMetadata['arrayOfStrings']->type + $m->propertyMetadata['arrayOfStrings']->type, ); } @@ -477,17 +399,17 @@ public function testAlternativeNames() self::assertEquals( ['name' => 'integer', 'params' => []], - $m->propertyMetadata['integer']->type + $m->propertyMetadata['integer']->type, ); self::assertEquals( ['name' => 'double', 'params' => []], - $m->propertyMetadata['double']->type + $m->propertyMetadata['double']->type, ); self::assertEquals( ['name' => 'boolean', 'params' => []], - $m->propertyMetadata['boolean']->type + $m->propertyMetadata['boolean']->type, ); } } diff --git a/tests/Metadata/Driver/DocBlockTypeResolverTest.php b/tests/Metadata/Driver/DocBlockTypeResolverTest.php index 2ad9372da..827a8c622 100644 --- a/tests/Metadata/Driver/DocBlockTypeResolverTest.php +++ b/tests/Metadata/Driver/DocBlockTypeResolverTest.php @@ -18,8 +18,8 @@ public function testGetPropertyDocblockTypeHintDoesNotCrash(): void $resolver = new DocBlockTypeResolver(); self::assertNull( $resolver->getPropertyDocblockTypeHint( - new ReflectionProperty(ObjectWithPhpDocProperty::class, 'emptyBlock') - ) + new ReflectionProperty(ObjectWithPhpDocProperty::class, 'emptyBlock'), + ), ); } @@ -29,14 +29,14 @@ public function testGetPropertyDocblockTypeHintDoesNotCrashWhenUnionType(): void self::assertSame( 'string', $resolver->getPropertyDocblockTypeHint( - new ReflectionProperty(ObjectWithPhpDocProperty::class, 'firstname') - ) + new ReflectionProperty(ObjectWithPhpDocProperty::class, 'firstname'), + ), ); self::assertSame( 'string', $resolver->getPropertyDocblockTypeHint( - new ReflectionProperty(ObjectWithPhpDocProperty::class, 'lastname') - ) + new ReflectionProperty(ObjectWithPhpDocProperty::class, 'lastname'), + ), ); } } diff --git a/tests/Metadata/Driver/DoctrineDriverTest.php b/tests/Metadata/Driver/DoctrineDriverTest.php index 1dc3565a4..976f02b91 100644 --- a/tests/Metadata/Driver/DoctrineDriverTest.php +++ b/tests/Metadata/Driver/DoctrineDriverTest.php @@ -42,7 +42,7 @@ public function testTypelessPropertyIsGivenTypeFromDoctrineMetadata() self::assertEquals( ['name' => 'DateTime', 'params' => []], - $metadata->propertyMetadata['createdAt']->type + $metadata->propertyMetadata['createdAt']->type, ); } @@ -51,7 +51,7 @@ public function testSingleValuedAssociationIsProperlyHinted() $metadata = $this->getMetadata(); self::assertEquals( ['name' => 'JMS\Serializer\Tests\Fixtures\Doctrine\Entity\Author', 'params' => []], - $metadata->propertyMetadata['author']->type + $metadata->propertyMetadata['author']->type, ); } @@ -66,7 +66,7 @@ public function testMultiValuedAssociationIsProperlyHinted() ['name' => 'JMS\Serializer\Tests\Fixtures\Doctrine\Entity\Comment', 'params' => []], ], ], - $metadata->propertyMetadata['comments']->type + $metadata->propertyMetadata['comments']->type, ); } @@ -77,7 +77,7 @@ public function testTypeGuessByDoctrineIsOverwrittenByDelegateDriver() // This would be guessed as boolean but we've overriden it to integer self::assertEquals( ['name' => 'integer', 'params' => []], - $metadata->propertyMetadata['published']->type + $metadata->propertyMetadata['published']->type, ); } @@ -125,7 +125,7 @@ public function testGuidPropertyIsGivenStringType() self::assertEquals( ['name' => 'string', 'params' => []], - $metadata->propertyMetadata['guid']->type + $metadata->propertyMetadata['guid']->type, ); } @@ -137,11 +137,11 @@ protected function getEntityManager() if (PHP_VERSION_ID >= 80000 && class_exists(DoctrineAttributeDriver::class)) { $config->setMetadataDriverImpl( - new DoctrineAttributeDriver([__DIR__ . '/../../Fixtures/Doctrine'], true) + new DoctrineAttributeDriver([__DIR__ . '/../../Fixtures/Doctrine'], true), ); } else { $config->setMetadataDriverImpl( - new DoctrineAnnotationDriver(new AnnotationReader(), __DIR__ . '/../../Fixtures/Doctrine') + new DoctrineAnnotationDriver(new AnnotationReader(), __DIR__ . '/../../Fixtures/Doctrine'), ); } @@ -178,7 +178,7 @@ protected function getDoctrineDriver() return new DoctrineTypeDriver( $this->getMetadataDriver(), - $registry + $registry, ); } } diff --git a/tests/Metadata/Driver/DoctrinePHPCRDriverTest.php b/tests/Metadata/Driver/DoctrinePHPCRDriverTest.php index ea1e5980a..b05ac295d 100644 --- a/tests/Metadata/Driver/DoctrinePHPCRDriverTest.php +++ b/tests/Metadata/Driver/DoctrinePHPCRDriverTest.php @@ -35,7 +35,7 @@ public function testTypelessPropertyIsGivenTypeFromDoctrineMetadata() $metadata = $this->getMetadata(); self::assertEquals( ['name' => 'DateTime', 'params' => []], - $metadata->propertyMetadata['createdAt']->type + $metadata->propertyMetadata['createdAt']->type, ); } @@ -44,7 +44,7 @@ public function testSingleValuedAssociationIsProperlyHinted() $metadata = $this->getMetadata(); self::assertEquals( ['name' => 'JMS\Serializer\Tests\Fixtures\DoctrinePHPCR\Author', 'params' => []], - $metadata->propertyMetadata['author']->type + $metadata->propertyMetadata['author']->type, ); } @@ -59,7 +59,7 @@ public function testMultiValuedAssociationIsProperlyHinted() ['name' => 'JMS\Serializer\Tests\Fixtures\DoctrinePHPCR\Comment', 'params' => []], ], ], - $metadata->propertyMetadata['comments']->type + $metadata->propertyMetadata['comments']->type, ); } @@ -70,7 +70,7 @@ public function testTypeGuessByDoctrineIsOverwrittenByDelegateDriver() // This would be guessed as boolean but we've overridden it to integer self::assertEquals( ['name' => 'integer', 'params' => []], - $metadata->propertyMetadata['published']->type + $metadata->propertyMetadata['published']->type, ); } @@ -97,7 +97,7 @@ protected function getDocumentManager() $config->setProxyDir(sys_get_temp_dir() . '/JMSDoctrineTestProxies'); $config->setProxyNamespace('JMS\Tests\Proxies'); $config->setMetadataDriverImpl( - new DoctrinePHPCRDriver(new AnnotationReader(), __DIR__ . '/../../Fixtures/DoctrinePHPCR') + new DoctrinePHPCRDriver(new AnnotationReader(), __DIR__ . '/../../Fixtures/DoctrinePHPCR'), ); $session = $this->getMockBuilder('PHPCR\SessionInterface')->getMock(); @@ -119,7 +119,7 @@ protected function getDoctrinePHPCRDriver() return new DoctrinePHPCRTypeDriver( $this->getAnnotationDriver(), - $registry + $registry, ); } } diff --git a/tests/Metadata/Driver/TypedPropertiesDriverTest.php b/tests/Metadata/Driver/TypedPropertiesDriverTest.php index 618197523..70540d2f1 100644 --- a/tests/Metadata/Driver/TypedPropertiesDriverTest.php +++ b/tests/Metadata/Driver/TypedPropertiesDriverTest.php @@ -15,13 +15,6 @@ class TypedPropertiesDriverTest extends TestCase { - protected function setUp(): void - { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', TypedPropertiesDriver::class)); - } - } - public function testInferPropertiesFromTypes() { $m = $this->resolve(User::class); diff --git a/tests/Metadata/Driver/UnionTypedPropertiesDriverTest.php b/tests/Metadata/Driver/UnionTypedPropertiesDriverTest.php index c3a6357e3..cd3257aa4 100644 --- a/tests/Metadata/Driver/UnionTypedPropertiesDriverTest.php +++ b/tests/Metadata/Driver/UnionTypedPropertiesDriverTest.php @@ -30,7 +30,7 @@ public function testInferUnionTypesShouldResultInNoType() self::assertEquals( null, - $m->propertyMetadata['data']->type + $m->propertyMetadata['data']->type, ); } diff --git a/tests/Metadata/Driver/YamlDriverTest.php b/tests/Metadata/Driver/YamlDriverTest.php index f2a31cc6b..4b528bc94 100644 --- a/tests/Metadata/Driver/YamlDriverTest.php +++ b/tests/Metadata/Driver/YamlDriverTest.php @@ -108,7 +108,7 @@ public function testLoadingMultipleMetadataExtensions(): void BlogPost::class, Person::class, ], - $classNames + $classNames, ); } diff --git a/tests/Ordering/CustomPropertyOrderingStrategyTest.php b/tests/Ordering/CustomPropertyOrderingStrategyTest.php index 065b07beb..73d5be866 100644 --- a/tests/Ordering/CustomPropertyOrderingStrategyTest.php +++ b/tests/Ordering/CustomPropertyOrderingStrategyTest.php @@ -19,7 +19,7 @@ public function testOrder(array $ordering, array $keysToSort, array $expectedRes $properties = array_combine( $keysToSort, - array_pad([], count($keysToSort), $this->createMock(PropertyMetadata::class)) + array_pad([], count($keysToSort), $this->createMock(PropertyMetadata::class)), ); $sortedProperties = $strategy->order($properties); self::assertEquals($expectedResult, array_keys($sortedProperties)); diff --git a/tests/Serializer/ArrayTest.php b/tests/Serializer/ArrayTest.php index a74418438..d548ac96f 100644 --- a/tests/Serializer/ArrayTest.php +++ b/tests/Serializer/ArrayTest.php @@ -44,7 +44,7 @@ public function testToArrayWithScalar($input) $this->expectExceptionMessage(sprintf( 'The input data of type "%s" did not convert to an array, but got a result of type "%s".', gettype($input), - gettype($input) + gettype($input), )); $result = $this->serializer->toArray($input); diff --git a/tests/Serializer/BaseSerializationTestCase.php b/tests/Serializer/BaseSerializationTestCase.php index c30ba90af..7400151ff 100644 --- a/tests/Serializer/BaseSerializationTestCase.php +++ b/tests/Serializer/BaseSerializationTestCase.php @@ -178,7 +178,7 @@ public function testSerializeNullArray() self::assertEquals( static::getContent('nullable'), - $this->serializer->serialize($arr, $this->getFormat(), SerializationContext::create()->setSerializeNull(true)) + $this->serializer->serialize($arr, $this->getFormat(), SerializationContext::create()->setSerializeNull(true)), ); } @@ -189,7 +189,7 @@ public function testSerializeNullRoot() self::assertEquals( static::getContent('nullable_root'), - $this->serializer->serialize(null, $this->getFormat(), $context) + $this->serializer->serialize(null, $this->getFormat(), $context), ); } @@ -207,7 +207,7 @@ public function testDeserializeObjectWithMissingTypedArrayProp() $dObj = $this->serializer->deserialize( static::getContent('empty_object'), ObjectWithTypedArraySetter::class, - $this->getFormat() + $this->getFormat(), ); assert($dObj instanceof ObjectWithTypedArraySetter); @@ -222,7 +222,7 @@ public function testSerializeNullArrayExcludingNulls() self::assertEquals( static::getContent('nullable_skip'), - $this->serializer->serialize($arr, $this->getFormat(), SerializationContext::create()->setSerializeNull(false)) + $this->serializer->serialize($arr, $this->getFormat(), SerializationContext::create()->setSerializeNull(false)), ); } @@ -233,7 +233,7 @@ public function testObjectUsingTypeCasting() self::assertEquals( static::getContent('type_casting'), - $this->serialize($typeAliasing) + $this->serialize($typeAliasing), ); } @@ -243,7 +243,7 @@ public function testSerializeNullObject() self::assertEquals( static::getContent('simple_object_nullable'), - $this->serializer->serialize($obj, $this->getFormat(), SerializationContext::create()->setSerializeNull(true)) + $this->serializer->serialize($obj, $this->getFormat(), SerializationContext::create()->setSerializeNull(true)), ); } @@ -258,7 +258,7 @@ public function testDeserializeNullObject() $dObj = $this->serializer->deserialize( static::getContent('simple_object_nullable'), ObjectWithNullProperty::class, - $this->getFormat() + $this->getFormat(), ); assert($dObj instanceof ObjectWithNullProperty); @@ -1275,10 +1275,6 @@ public function testNestedFormErrors($type) */ public function testFormErrorsWithNonFormComponents($type) { - if (!class_exists('Symfony\Component\Form\Extension\Core\Type\SubmitType')) { - $this->markTestSkipped('Not using Symfony Form >= 2.3 with submit type'); - } - $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); $factoryBuilder = new FormFactoryBuilder(); @@ -1388,27 +1384,27 @@ public function testGroups() self::assertEquals( static::getContent('groups_foo'), - $this->serializer->serialize($groupsObject, $this->getFormat(), SerializationContext::create()->setGroups(['foo'])) + $this->serializer->serialize($groupsObject, $this->getFormat(), SerializationContext::create()->setGroups(['foo'])), ); self::assertEquals( static::getContent('groups_foobar'), - $this->serializer->serialize($groupsObject, $this->getFormat(), SerializationContext::create()->setGroups(['foo', 'bar'])) + $this->serializer->serialize($groupsObject, $this->getFormat(), SerializationContext::create()->setGroups(['foo', 'bar'])), ); self::assertEquals( static::getContent('groups_all'), - $this->serializer->serialize($groupsObject, $this->getFormat()) + $this->serializer->serialize($groupsObject, $this->getFormat()), ); self::assertEquals( static::getContent('groups_default'), - $this->serializer->serialize($groupsObject, $this->getFormat(), SerializationContext::create()->setGroups([GroupsExclusionStrategy::DEFAULT_GROUP])) + $this->serializer->serialize($groupsObject, $this->getFormat(), SerializationContext::create()->setGroups([GroupsExclusionStrategy::DEFAULT_GROUP])), ); self::assertEquals( static::getContent('groups_default'), - $this->serializer->serialize($groupsObject, $this->getFormat(), SerializationContext::create()->setGroups([GroupsExclusionStrategy::DEFAULT_GROUP])) + $this->serializer->serialize($groupsObject, $this->getFormat(), SerializationContext::create()->setGroups([GroupsExclusionStrategy::DEFAULT_GROUP])), ); } @@ -1422,21 +1418,21 @@ public function testAdvancedGroups() [ new GroupsUser( 'John Manager friend 1', - new GroupsUser('John Manager friend 1 manager') + new GroupsUser('John Manager friend 1 manager'), ), new GroupsUser('John Manager friend 2'), - ] + ], ), [ new GroupsUser( 'John friend 1', - new GroupsUser('John friend 1 manager') + new GroupsUser('John friend 1 manager'), ), new GroupsUser( 'John friend 2', - new GroupsUser('John friend 2 manager') + new GroupsUser('John friend 2 manager'), ), - ] + ], ); self::assertEquals( @@ -1459,8 +1455,8 @@ public function testAdvancedGroups() 'manager_group', 'nickname_group', ], - ]) - ) + ]), + ), ); } @@ -1489,17 +1485,17 @@ public function testVirtualVersions() self::assertEquals( static::getContent('virtual_properties_low'), - $serializer->serialize(new ObjectWithVersionedVirtualProperties(), $this->getFormat(), SerializationContext::create()->setVersion('2')) + $serializer->serialize(new ObjectWithVersionedVirtualProperties(), $this->getFormat(), SerializationContext::create()->setVersion('2')), ); self::assertEquals( static::getContent('virtual_properties_all'), - $serializer->serialize(new ObjectWithVersionedVirtualProperties(), $this->getFormat(), SerializationContext::create()->setVersion('7')) + $serializer->serialize(new ObjectWithVersionedVirtualProperties(), $this->getFormat(), SerializationContext::create()->setVersion('7')), ); self::assertEquals( static::getContent('virtual_properties_high'), - $serializer->serialize(new ObjectWithVersionedVirtualProperties(), $this->getFormat(), SerializationContext::create()->setVersion('9')) + $serializer->serialize(new ObjectWithVersionedVirtualProperties(), $this->getFormat(), SerializationContext::create()->setVersion('9')), ); } @@ -1522,10 +1518,6 @@ public function testCustomHandler() public function testTypedProperties() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', __METHOD__)); - } - $builder = SerializerBuilder::create($this->handlerRegistry, $this->dispatcher); $builder->includeInterfaceMetadata(true); $this->serializer = $builder->build(); @@ -1579,10 +1571,6 @@ public function testConstructorPromotionWithDefaultValues() public function testUninitializedTypedProperties() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped(sprintf('%s requires PHP 7.4', __METHOD__)); - } - $builder = SerializerBuilder::create($this->handlerRegistry, $this->dispatcher); $builder->includeInterfaceMetadata(true); $this->serializer = $builder->build(); @@ -1634,12 +1622,12 @@ public function testSerializeObjectWhenNull() { self::assertEquals( static::getContent('object_when_null'), - $this->serialize(new Comment(null, 'foo'), SerializationContext::create()->setSerializeNull(false)) + $this->serialize(new Comment(null, 'foo'), SerializationContext::create()->setSerializeNull(false)), ); self::assertEquals( static::getContent('object_when_null_and_serialized'), - $this->serialize(new Comment(null, 'foo'), SerializationContext::create()->setSerializeNull(true)) + $this->serialize(new Comment(null, 'foo'), SerializationContext::create()->setSerializeNull(true)), ); } @@ -1653,7 +1641,7 @@ public function testPolymorphicObjectsWithGroup() self::assertEquals( static::getContent('car'), - $this->serialize(new DiscriminatorGroupCar(5), $context) + $this->serialize(new DiscriminatorGroupCar(5), $context), ); } @@ -1680,7 +1668,7 @@ public function testDiscrimatorObjects($data, $contentId) $context = SerializationContext::create()->setGroups(['entity.identification']); self::assertEquals( static::getContent($contentId), - $this->serialize($data, $context) + $this->serialize($data, $context), ); } @@ -1691,15 +1679,15 @@ public function testPolymorphicObjects() { self::assertEquals( static::getContent('car'), - $this->serialize(new Car(5)) + $this->serialize(new Car(5)), ); self::assertEquals( static::getContent('post'), - $this->serialize(new Post('Post Title')) + $this->serialize(new Post('Post Title')), ); self::assertEquals( static::getContent('image_post'), - $this->serialize(new ImagePost('Image Post Title')) + $this->serialize(new ImagePost('Image Post Title')), ); if ($this->hasDeserializer()) { @@ -1707,54 +1695,54 @@ public function testPolymorphicObjects() new Car(5), $this->deserialize( static::getContent('car'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\Car' + 'JMS\Serializer\Tests\Fixtures\Discriminator\Car', ), - 'Class is resolved correctly when concrete sub-class is used.' + 'Class is resolved correctly when concrete sub-class is used.', ); self::assertEquals( new Car(5), $this->deserialize( static::getContent('car'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle' + 'JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle', ), - 'Class is resolved correctly when least supertype is used.' + 'Class is resolved correctly when least supertype is used.', ); self::assertEquals( new Car(5), $this->deserialize( static::getContent('car_without_type'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\Car' + 'JMS\Serializer\Tests\Fixtures\Discriminator\Car', ), - 'Class is resolved correctly when concrete sub-class is used and no type is defined.' + 'Class is resolved correctly when concrete sub-class is used and no type is defined.', ); self::assertEquals( new Post('Post Title'), $this->deserialize( static::getContent('post'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\Post' + 'JMS\Serializer\Tests\Fixtures\Discriminator\Post', ), - 'Class is resolved correctly when parent class is used and type is set.' + 'Class is resolved correctly when parent class is used and type is set.', ); self::assertEquals( new ImagePost('Image Post Title'), $this->deserialize( static::getContent('image_post'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\Post' + 'JMS\Serializer\Tests\Fixtures\Discriminator\Post', ), - 'Class is resolved correctly when least supertype is used.' + 'Class is resolved correctly when least supertype is used.', ); self::assertEquals( new ImagePost('Image Post Title'), $this->deserialize( static::getContent('image_post'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\ImagePost' + 'JMS\Serializer\Tests\Fixtures\Discriminator\ImagePost', ), - 'Class is resolved correctly when concrete sub-class is used and no type is defined.' + 'Class is resolved correctly when concrete sub-class is used and no type is defined.', ); } } @@ -1767,7 +1755,7 @@ public function testNestedPolymorphicObjects() $garage = new Garage([new Car(3), new Moped(1)]); self::assertEquals( static::getContent('garage'), - $this->serialize($garage) + $this->serialize($garage), ); if ($this->hasDeserializer()) { @@ -1775,8 +1763,8 @@ public function testNestedPolymorphicObjects() $garage, $this->deserialize( static::getContent('garage'), - 'JMS\Serializer\Tests\Fixtures\Garage' - ) + 'JMS\Serializer\Tests\Fixtures\Garage', + ), ); } } @@ -1789,7 +1777,7 @@ public function testNestedPolymorphicInterfaces() $garage = new VehicleInterfaceGarage([new Car(3), new Moped(1)]); self::assertEquals( static::getContent('garage'), - $this->serialize($garage) + $this->serialize($garage), ); if ($this->hasDeserializer()) { @@ -1797,8 +1785,8 @@ public function testNestedPolymorphicInterfaces() $garage, $this->deserialize( static::getContent('garage'), - 'JMS\Serializer\Tests\Fixtures\VehicleInterfaceGarage' - ) + 'JMS\Serializer\Tests\Fixtures\VehicleInterfaceGarage', + ), ); } } @@ -1816,7 +1804,7 @@ public function testPolymorphicObjectsInvalidDeserialization() $this->deserialize( static::getContent('car_without_type'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle' + 'JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle', ); } @@ -1834,7 +1822,7 @@ public function testDepthExclusionStrategy() ]), ]), ]), - ]) + ]), ); self::assertEquals(static::getContent('tree'), $this->serializer->serialize($data, $this->getFormat(), $context)); @@ -1891,7 +1879,7 @@ public function testDeserializingIntoExistingObject() static::getContent('order'), get_class($order), $this->getFormat(), - $context + $context, ); self::assertSame($order, $deseralizedOrder); @@ -1920,7 +1908,7 @@ public function testSerializeNullArrayObjectWithExclusionStrategy(bool $serializ $serializationContext->addExclusionStrategy(new AlwaysExcludeExclusionStrategy()); self::assertEquals( static::getContent('array_objects_nullable'), - $this->serializer->serialize($arr, $this->getFormat(), $serializationContext) + $this->serializer->serialize($arr, $this->getFormat(), $serializationContext), ); } @@ -1936,7 +1924,7 @@ static function ($visitor, $data) use (&$invoked) { self::assertEquals('foo', $data); return null; - } + }, ); $this->serializer->serialize('foo', $this->getFormat(), null, 'Virtual'); @@ -1967,7 +1955,7 @@ public function testFirstClassListCollections($items, $expected, ?FirstClassList self::assertSame($expected, $this->serialize($collection)); self::assertEquals( $expectedDeserializatrion ?: $collection, - $this->deserialize($expected, get_class($collection)) + $this->deserialize($expected, get_class($collection)), ); } @@ -2039,7 +2027,7 @@ public function testIterable(): void self::assertEquals( new ObjectWithIterable(Functions::iterableToArray($generator())), - $this->deserialize(static::getContent('iterable'), get_class($withIterable)) + $this->deserialize(static::getContent('iterable'), get_class($withIterable)), ); } @@ -2058,7 +2046,7 @@ public function testGenerator(): void self::assertEquals( $withGenerator, - $this->deserialize(static::getContent('generator'), get_class($withGenerator)) + $this->deserialize(static::getContent('generator'), get_class($withGenerator)), ); } @@ -2077,7 +2065,7 @@ public function testIterator(): void self::assertEquals( $withIterator, - $this->deserialize(static::getContent('iterator'), get_class($withIterator)) + $this->deserialize(static::getContent('iterator'), get_class($withIterator)), ); } @@ -2096,7 +2084,7 @@ public function testArrayIterator(): void self::assertEquals( $withArrayIterator, - $this->deserialize(static::getContent('iterator'), get_class($withArrayIterator)) + $this->deserialize(static::getContent('iterator'), get_class($withArrayIterator)), ); } @@ -2144,7 +2132,7 @@ protected function setUp(): void $this->getFormat(), static function (SerializationVisitorInterface $visitor, $object, array $type, Context $context) { return $visitor->visitArray(iterator_to_array($object), $type); - } + }, ); $this->handlerRegistry->registerHandler( GraphNavigatorInterface::DIRECTION_DESERIALIZATION, @@ -2166,7 +2154,7 @@ static function (DeserializationVisitorInterface $visitor, $data, $type, Context } return $list; - } + }, ); $this->dispatcher = new EventDispatcher(); diff --git a/tests/Serializer/Doctrine/IntegrationTest.php b/tests/Serializer/Doctrine/IntegrationTest.php index ca17e247d..fcee0228a 100644 --- a/tests/Serializer/Doctrine/IntegrationTest.php +++ b/tests/Serializer/Doctrine/IntegrationTest.php @@ -100,7 +100,7 @@ static function ($id) use ($connection, $entityManager) { default: throw new \RuntimeException(sprintf('Unknown service id "%s".', $id)); } - } + }, ); $this->serializer = SerializerBuilder::create() @@ -109,7 +109,7 @@ static function (array $metadataDirs, Reader $annotationReader) use ($registry) $defaultFactory = new DefaultDriverFactory(new IdenticalPropertyNamingStrategy()); return new DoctrineTypeDriver($defaultFactory->createDriver($metadataDirs, $annotationReader), $registry); - } + }, )) ->build(); diff --git a/tests/Serializer/Doctrine/ObjectConstructorTest.php b/tests/Serializer/Doctrine/ObjectConstructorTest.php index f6725d928..6faf53ead 100644 --- a/tests/Serializer/Doctrine/ObjectConstructorTest.php +++ b/tests/Serializer/Doctrine/ObjectConstructorTest.php @@ -58,6 +58,7 @@ use ReflectionClass; use RuntimeException; use SimpleXMLElement; + use function assert; class ObjectConstructorTest extends TestCase @@ -271,7 +272,7 @@ public function testNamingForIdentifierColumnIsConsidered() self::assertSame( $em->getUnitOfWork()->getEntityState($serverDeserialized), - UnitOfWork::STATE_MANAGED + UnitOfWork::STATE_MANAGED, ); } @@ -326,7 +327,7 @@ public function testPersistendCollectionIsNotReplaced(string $data, string $type self::assertSame( $em->getUnitOfWork()->getEntityState($smartPhoneDeserialized), - UnitOfWork::STATE_MANAGED + UnitOfWork::STATE_MANAGED, ); self::assertInstanceOf(PersistentCollection::class, $smartPhoneDeserialized->getAppsRaw()); @@ -336,14 +337,14 @@ public function testPersistendCollectionIsNotReplaced(string $data, string $type self::assertCount( 1, $smartPhoneDeserialized->getApps( - $criteria - ) + $criteria, + ), ); $firstApp = $smartPhoneDeserialized->getApps()->first(); self::assertSame( $em->getUnitOfWork()->getEntityState($firstApp), - UnitOfWork::STATE_MANAGED + UnitOfWork::STATE_MANAGED, ); $em->flush(); @@ -375,7 +376,7 @@ static function ($id) use ($connection, $entityManager) { default: throw new RuntimeException(sprintf('Unknown service id "%s".', $id)); } - } + }, ); $type = ['name' => BlogPostSeo::class, 'params' => []]; @@ -405,7 +406,7 @@ static function ($id) use ($connection, $entityManager) { default: throw new RuntimeException(sprintf('Unknown service id "%s".', $id)); } - } + }, ); $type = ['name' => BlogPostSeo::class, 'params' => []]; @@ -486,7 +487,7 @@ static function ($id) use ($connection, $entityManager) { default: throw new RuntimeException(sprintf('Unknown service id "%s".', $id)); } - } + }, ); $this->driver = &$driver; @@ -496,7 +497,7 @@ static function (array $metadataDirs, Reader $annotationReader) use ($registry, $defaultFactory = new DefaultDriverFactory(new IdenticalPropertyNamingStrategy()); return $driver = new DoctrineTypeDriver($defaultFactory->createDriver($metadataDirs, $annotationReader), $registry); - } + }, )) ->build(); @@ -573,16 +574,16 @@ private function createSerializerWithDoctrineObjectConstructor() new DoctrineObjectConstructor( $this->registry, new UnserializeObjectConstructor(), - DoctrineObjectConstructor::ON_MISSING_FALLBACK - ) + DoctrineObjectConstructor::ON_MISSING_FALLBACK, + ), ) ->addDefaultHandlers() ->configureHandlers(function (HandlerRegistryInterface $handlerRegistry) { $handlerRegistry->registerSubscribingHandler( new ArrayCollectionHandler( true, - $this->registry - ) + $this->registry, + ), ); }) ->build(); diff --git a/tests/Serializer/EventDispatcher/Subscriber/SymfonyValidatorValidatorSubscriberTest.php b/tests/Serializer/EventDispatcher/Subscriber/SymfonyValidatorValidatorSubscriberTest.php index d318a421b..68f9cf020 100644 --- a/tests/Serializer/EventDispatcher/Subscriber/SymfonyValidatorValidatorSubscriberTest.php +++ b/tests/Serializer/EventDispatcher/Subscriber/SymfonyValidatorValidatorSubscriberTest.php @@ -80,7 +80,7 @@ public function testValidationIsOnlyPerformedOnRootObject(): void '{"authors":[{"full_name":"foo"},{"full_name":"bar"}]}', AuthorList::class, 'json', - DeserializationContext::create()->setAttribute('validation_groups', ['Foo']) + DeserializationContext::create()->setAttribute('validation_groups', ['Foo']), ); self::assertCount(2, $list); diff --git a/tests/Serializer/JsonSerializationTest.php b/tests/Serializer/JsonSerializationTest.php index af8c57996..0c6800e89 100644 --- a/tests/Serializer/JsonSerializationTest.php +++ b/tests/Serializer/JsonSerializationTest.php @@ -182,7 +182,7 @@ public function testFirstClassMapCollections($items, $expected): void self::assertSame($expected, $this->serialize($collection)); self::assertEquals( $collection, - $this->deserialize($expected, get_class($collection)) + $this->deserialize($expected, get_class($collection)), ); } @@ -204,7 +204,7 @@ public function testAddLinksToOutput() 'json', static function (SerializationVisitorInterface $visitor, AuthorList $data, array $type, Context $context) { return $visitor->visitArray(iterator_to_array($data), $type); - } + }, ); $list = new AuthorList(); @@ -223,7 +223,7 @@ public function testReplaceNameInOutput() 'json', static function (SerializationVisitorInterface $visitor, AuthorList $data, array $type, Context $context) { return $visitor->visitArray(iterator_to_array($data), $type); - } + }, ); $list = new AuthorList(); diff --git a/tests/Serializer/Type/ParserTest.php b/tests/Serializer/Type/ParserTest.php index 6fd9f0551..eecdab5ab 100644 --- a/tests/Serializer/Type/ParserTest.php +++ b/tests/Serializer/Type/ParserTest.php @@ -26,7 +26,7 @@ public function testParse(string $sourceType, array $expectedType): void { self::assertSame( $expectedType, - $this->parser->parse($sourceType) + $this->parser->parse($sourceType), ); } diff --git a/tests/Serializer/XmlSerializationTest.php b/tests/Serializer/XmlSerializationTest.php index 3701d95e3..6fcb01c77 100644 --- a/tests/Serializer/XmlSerializationTest.php +++ b/tests/Serializer/XmlSerializationTest.php @@ -83,7 +83,7 @@ public function testAccessorSetterDeserialization() collectionEntry ', - 'JMS\Serializer\Tests\Fixtures\AccessorSetter' + 'JMS\Serializer\Tests\Fixtures\AccessorSetter', ); \assert($object instanceof AccessorSetter); @@ -171,7 +171,7 @@ public function testVirtualAttributes() { self::assertEquals( self::getContent('virtual_attributes'), - $this->serialize(new ObjectWithVirtualXmlProperties(), SerializationContext::create()->setGroups(['attributes'])) + $this->serialize(new ObjectWithVirtualXmlProperties(), SerializationContext::create()->setGroups(['attributes'])), ); } @@ -179,7 +179,7 @@ public function testVirtualValues() { self::assertEquals( self::getContent('virtual_values'), - $this->serialize(new ObjectWithVirtualXmlProperties(), SerializationContext::create()->setGroups(['values'])) + $this->serialize(new ObjectWithVirtualXmlProperties(), SerializationContext::create()->setGroups(['values'])), ); } @@ -187,7 +187,7 @@ public function testVirtualXmlList() { self::assertEquals( self::getContent('virtual_properties_list'), - $this->serialize(new ObjectWithVirtualXmlProperties(), SerializationContext::create()->setGroups(['list'])) + $this->serialize(new ObjectWithVirtualXmlProperties(), SerializationContext::create()->setGroups(['list'])), ); } @@ -195,7 +195,7 @@ public function testVirtualXmlMap() { self::assertEquals( self::getContent('virtual_properties_map'), - $this->serialize(new ObjectWithVirtualXmlProperties(), SerializationContext::create()->setGroups(['map'])) + $this->serialize(new ObjectWithVirtualXmlProperties(), SerializationContext::create()->setGroups(['map'])), ); } @@ -234,11 +234,11 @@ public function testObjectWithNamespacesAndList() self::assertEquals( self::getContent('object_with_namespaces_and_list'), - $this->serialize($object, SerializationContext::create()) + $this->serialize($object, SerializationContext::create()), ); self::assertEquals( $object, - $this->deserialize(self::getContent('object_with_namespaces_and_list'), get_class($object)) + $this->deserialize(self::getContent('object_with_namespaces_and_list'), get_class($object)), ); } @@ -261,11 +261,11 @@ public function testObjectWithNamespaceAndNestedList() self::assertEquals( self::getContent('object_with_namespaces_and_nested_list'), - $this->serialize($object, SerializationContext::create()) + $this->serialize($object, SerializationContext::create()), ); self::assertEquals( $object, - $this->deserialize(self::getContent('object_with_namespaces_and_nested_list'), get_class($object)) + $this->deserialize(self::getContent('object_with_namespaces_and_nested_list'), get_class($object)), ); } @@ -356,7 +356,7 @@ public function testObjectWithOnlyNamespacesAndList() self::assertEquals( self::getContent('object_with_only_namespaces_and_list'), - $this->serialize($object, SerializationContext::create()) + $this->serialize($object, SerializationContext::create()), ); $deserialized = $this->deserialize(self::getContent('object_with_only_namespaces_and_list'), get_class($object)); @@ -423,7 +423,7 @@ static function (XmlSerializationVisitor $visitor, $data, $type, Context $contex $metadata->xmlNamespace = $classMetadata->xmlRootNamespace; $visitor->visitProperty($metadata, $author); - } + }, ); $serialized = $this->serialize($object); @@ -481,8 +481,8 @@ public function testDiscriminatorAsXmlAttribute() ObjectWithXmlAttributeDiscriminatorChild::class, $this->deserialize( $xml, - ObjectWithXmlAttributeDiscriminatorParent::class - ) + ObjectWithXmlAttributeDiscriminatorParent::class, + ), ); } @@ -494,8 +494,8 @@ public function testDiscriminatorAsNotCData() ObjectWithXmlNotCDataDiscriminatorChild::class, $this->deserialize( $xml, - ObjectWithXmlNotCDataDiscriminatorParent::class - ) + ObjectWithXmlNotCDataDiscriminatorParent::class, + ), ); } @@ -508,8 +508,8 @@ public function testDiscriminatorWithNamespace() ObjectWithXmlNamespaceDiscriminatorChild::class, $this->deserialize( $xml, - ObjectWithXmlNamespaceDiscriminatorParent::class - ) + ObjectWithXmlNamespaceDiscriminatorParent::class, + ), ); } @@ -522,8 +522,8 @@ public function testDiscriminatorAsXmlAttributeWithNamespace() ObjectWithXmlNamespaceAttributeDiscriminatorChild::class, $this->deserialize( $xml, - ObjectWithXmlNamespaceAttributeDiscriminatorParent::class - ) + ObjectWithXmlNamespaceAttributeDiscriminatorParent::class, + ), ); } @@ -575,7 +575,7 @@ public function testSerialisationWithPrecisionForFloat(): void 1.555, 1.5, 1.555, - 1.555 + 1.555, ); $result = $this->serialize($objectWithFloat, SerializationContext::create()); @@ -593,7 +593,7 @@ public function testSerialisationWithPrecisionForFloat(): void 1.6 1.560 ', - $result + $result, ); } diff --git a/tests/SerializerBuilderTest.php b/tests/SerializerBuilderTest.php index 8551ae2c5..232bcfdd3 100644 --- a/tests/SerializerBuilderTest.php +++ b/tests/SerializerBuilderTest.php @@ -102,7 +102,7 @@ public function testDoesNotAddOtherVisitorsWhenConfiguredExplicitly() { self::assertSame( $this->builder, - $this->builder->setSerializationVisitor('json', new JsonSerializationVisitorFactory()) + $this->builder->setSerializationVisitor('json', new JsonSerializationVisitorFactory()), ); $this->expectException(UnsupportedFormatException::class); @@ -115,22 +115,22 @@ public function testIncludeInterfaceMetadata() { self::assertFalse( $this->getIncludeInterfaces($this->builder), - 'Interface metadata are not included by default' + 'Interface metadata are not included by default', ); self::assertTrue( $this->getIncludeInterfaces($this->builder->includeInterfaceMetadata(true)), - 'Force including interface metadata' + 'Force including interface metadata', ); self::assertFalse( $this->getIncludeInterfaces($this->builder->includeInterfaceMetadata(false)), - 'Force not including interface metadata' + 'Force not including interface metadata', ); self::assertSame( $this->builder, - $this->builder->includeInterfaceMetadata(true) + $this->builder->includeInterfaceMetadata(true), ); } diff --git a/tests/Twig/SerializerExtensionTest.php b/tests/Twig/SerializerExtensionTest.php index 2ef2b14af..79c729f4a 100644 --- a/tests/Twig/SerializerExtensionTest.php +++ b/tests/Twig/SerializerExtensionTest.php @@ -32,7 +32,7 @@ public function testSerialize() self::assertEquals( [new TwigFunction('serialization_context', '\JMS\Serializer\SerializationContext::create')], - $serializerExtension->getFunctions() + $serializerExtension->getFunctions(), ); } @@ -55,7 +55,7 @@ public function testSerializeWithPrefix() self::assertEquals( [new TwigFunction('foo_serialization_context', '\JMS\Serializer\SerializationContext::create')], - $serializerExtension->getFunctions() + $serializerExtension->getFunctions(), ); } @@ -80,11 +80,11 @@ public function testRuntimeSerializerExtension() self::assertEquals('jms_serializer', $serializerExtension->getName()); self::assertEquals( [new TwigFilter('serialize', [SerializerRuntimeHelper::class, 'serialize'])], - $serializerExtension->getFilters() + $serializerExtension->getFilters(), ); self::assertEquals( [new TwigFunction('serialization_context', '\JMS\Serializer\SerializationContext::create')], - $serializerExtension->getFunctions() + $serializerExtension->getFunctions(), ); } } From 90a077d5045a917411f7cc233ce957ec8e0c7272 Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Sun, 10 Dec 2023 10:41:06 -0600 Subject: [PATCH 24/38] Update .github/workflows/benchmark.yaml Co-authored-by: Marcin Czarnecki --- .github/workflows/benchmark.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/benchmark.yaml b/.github/workflows/benchmark.yaml index 4dd2b6f26..596977094 100644 --- a/.github/workflows/benchmark.yaml +++ b/.github/workflows/benchmark.yaml @@ -15,8 +15,7 @@ jobs: matrix: php-version: - "7.4" - - "8.0" - - "8.1" + - "8.2" steps: - name: Checkout code From e8e2dd8e2b8c7251dc90b4a1218887fbfaf49203 Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Tue, 2 Jan 2024 16:15:24 +0100 Subject: [PATCH 25/38] build(ci): Add Rector into static analysis. --- .github/workflows/static-analysis.yaml | 4 ++++ composer.json | 1 + rector.php | 13 +++++++++++++ 3 files changed, 18 insertions(+) create mode 100644 rector.php diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index cbda4cc36..c1d5d635c 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -38,3 +38,7 @@ jobs: - name: "Run a static analysis with phpstan/phpstan" run: "vendor/bin/phpstan analyse --error-format=checkstyle | cs2pr" + + - name: "Run a static analysis with rector/rector" + run: "vendor/bin/rector --dry-run" + if: ${{ matrix.php-version == 8.2 }} diff --git a/composer.json b/composer.json index 857e77617..4d754518e 100644 --- a/composer.json +++ b/composer.json @@ -41,6 +41,7 @@ "phpstan/phpstan": "^1.0.2", "phpunit/phpunit": "^9.0 || ^10.0", "psr/container": "^1.0 || ^2.0", + "rector/rector": "^0.18.13", "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", "symfony/expression-language": "^5.4 || ^6.0 || ^7.0", "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", diff --git a/rector.php b/rector.php new file mode 100644 index 000000000..6cc8584b1 --- /dev/null +++ b/rector.php @@ -0,0 +1,13 @@ +paths([ + __DIR__ . '/src', + ]); + $rectorConfig->sets([LevelSetList::UP_TO_PHP_74]); +}; From fb5a502d92516ad69e8c14982da338a31c548bed Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Tue, 2 Jan 2024 16:24:50 +0100 Subject: [PATCH 26/38] build(code style): Update src to 7.4 --- src/Accessor/DefaultAccessorStrategy.php | 4 +--- src/Annotation/ReadOnly.php | 4 +++- .../Driver/AnnotationOrAttributeDriver.php | 16 +++++----------- src/Metadata/Driver/AttributeDriver.php | 12 +++--------- .../Driver/AttributeDriver/AttributeReader.php | 4 +--- .../DocBlockDriver/DocBlockTypeResolver.php | 16 ++++------------ .../AlphabeticalPropertyOrderingStrategy.php | 4 +--- src/XmlSerializationVisitor.php | 4 +--- 8 files changed, 19 insertions(+), 45 deletions(-) diff --git a/src/Accessor/DefaultAccessorStrategy.php b/src/Accessor/DefaultAccessorStrategy.php index a3c25a326..ed8d647ce 100644 --- a/src/Accessor/DefaultAccessorStrategy.php +++ b/src/Accessor/DefaultAccessorStrategy.php @@ -86,9 +86,7 @@ public function getValue(object $object, PropertyMetadata $metadata, Serializati $accessor = $this->readAccessors[$metadata->class] ?? null; if (null === $accessor) { - $accessor = \Closure::bind(static function ($o, $name) { - return $o->$name; - }, null, $metadata->class); + $accessor = \Closure::bind(static fn ($o, $name) => $o->$name, null, $metadata->class); $this->readAccessors[$metadata->class] = $accessor; } diff --git a/src/Annotation/ReadOnly.php b/src/Annotation/ReadOnly.php index 23bff2630..b5344e10e 100644 --- a/src/Annotation/ReadOnly.php +++ b/src/Annotation/ReadOnly.php @@ -2,4 +2,6 @@ declare(strict_types=1); -class_alias('JMS\Serializer\Annotation\DeprecatedReadOnly', 'JMS\Serializer\Annotation\ReadOnly'); +use JMS\Serializer\Annotation\DeprecatedReadOnly; + +class_alias(DeprecatedReadOnly::class, 'JMS\Serializer\Annotation\ReadOnly'); diff --git a/src/Metadata/Driver/AnnotationOrAttributeDriver.php b/src/Metadata/Driver/AnnotationOrAttributeDriver.php index 8e1b52343..92becb724 100644 --- a/src/Metadata/Driver/AnnotationOrAttributeDriver.php +++ b/src/Metadata/Driver/AnnotationOrAttributeDriver.php @@ -290,10 +290,10 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat } } - if (!$configured) { + // if (!$configured) { // return null; // uncomment the above line afetr a couple of months - } + // } return $classMetadata; } @@ -307,9 +307,7 @@ protected function getClassAnnotations(\ReflectionClass $class): array if (PHP_VERSION_ID >= 80000) { $annotations = array_map( - static function (\ReflectionAttribute $attribute): object { - return $attribute->newInstance(); - }, + static fn (\ReflectionAttribute $attribute): object => $attribute->newInstance(), $class->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF), ); } @@ -330,9 +328,7 @@ protected function getMethodAnnotations(\ReflectionMethod $method): array if (PHP_VERSION_ID >= 80000) { $annotations = array_map( - static function (\ReflectionAttribute $attribute): object { - return $attribute->newInstance(); - }, + static fn (\ReflectionAttribute $attribute): object => $attribute->newInstance(), $method->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF), ); } @@ -353,9 +349,7 @@ protected function getPropertyAnnotations(\ReflectionProperty $property): array if (PHP_VERSION_ID >= 80000) { $annotations = array_map( - static function (\ReflectionAttribute $attribute): object { - return $attribute->newInstance(); - }, + static fn (\ReflectionAttribute $attribute): object => $attribute->newInstance(), $property->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF), ); } diff --git a/src/Metadata/Driver/AttributeDriver.php b/src/Metadata/Driver/AttributeDriver.php index e966791c2..2c6c1a2c9 100644 --- a/src/Metadata/Driver/AttributeDriver.php +++ b/src/Metadata/Driver/AttributeDriver.php @@ -14,9 +14,7 @@ class AttributeDriver extends AnnotationOrAttributeDriver protected function getClassAnnotations(\ReflectionClass $class): array { return array_map( - static function (\ReflectionAttribute $attribute): object { - return $attribute->newInstance(); - }, + static fn (\ReflectionAttribute $attribute): object => $attribute->newInstance(), $class->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF), ); } @@ -27,9 +25,7 @@ static function (\ReflectionAttribute $attribute): object { protected function getMethodAnnotations(\ReflectionMethod $method): array { return array_map( - static function (\ReflectionAttribute $attribute): object { - return $attribute->newInstance(); - }, + static fn (\ReflectionAttribute $attribute): object => $attribute->newInstance(), $method->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF), ); } @@ -40,9 +36,7 @@ static function (\ReflectionAttribute $attribute): object { protected function getPropertyAnnotations(\ReflectionProperty $property): array { return array_map( - static function (\ReflectionAttribute $attribute): object { - return $attribute->newInstance(); - }, + static fn (\ReflectionAttribute $attribute): object => $attribute->newInstance(), $property->getAttributes(SerializerAttribute::class, \ReflectionAttribute::IS_INSTANCEOF), ); } diff --git a/src/Metadata/Driver/AttributeDriver/AttributeReader.php b/src/Metadata/Driver/AttributeDriver/AttributeReader.php index 91e8aa83a..12da20f58 100644 --- a/src/Metadata/Driver/AttributeDriver/AttributeReader.php +++ b/src/Metadata/Driver/AttributeDriver/AttributeReader.php @@ -85,9 +85,7 @@ private function buildAnnotation(array $attributes): ?SerializerAttribute private function buildAnnotations(array $attributes): array { return array_map( - static function (\ReflectionAttribute $attribute): object { - return $attribute->newInstance(); - }, + static fn (\ReflectionAttribute $attribute): object => $attribute->newInstance(), $attributes, ); } diff --git a/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php b/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php index 4e43cf6e0..d5fad5b64 100644 --- a/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php +++ b/src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php @@ -115,17 +115,13 @@ private function getDocBlocTypeHint($reflector): ?string // Generic array syntax: array | array<\Foo\Bar\Product> | array if ($type instanceof GenericTypeNode) { if ($this->isSimpleType($type->type, 'array')) { - $resolvedTypes = array_map(function (TypeNode $node) use ($reflector) { - return $this->resolveTypeFromTypeNode($node, $reflector); - }, $type->genericTypes); + $resolvedTypes = array_map(fn (TypeNode $node) => $this->resolveTypeFromTypeNode($node, $reflector), $type->genericTypes); return 'array<' . implode(',', $resolvedTypes) . '>'; } if ($this->isSimpleType($type->type, 'list')) { - $resolvedTypes = array_map(function (TypeNode $node) use ($reflector) { - return $this->resolveTypeFromTypeNode($node, $reflector); - }, $type->genericTypes); + $resolvedTypes = array_map(fn (TypeNode $node) => $this->resolveTypeFromTypeNode($node, $reflector), $type->genericTypes); return 'array'; } @@ -194,9 +190,7 @@ private function flattenParamTagValueTypes(string $parameterName, array $varTagV */ private function filterNullFromTypes(array $types): array { - return array_values(array_filter(array_map(function (TypeNode $node) { - return $this->isNullType($node) ? null : $node; - }, $types))); + return array_values(array_filter(array_map(fn (TypeNode $node) => $this->isNullType($node) ? null : $node, $types))); } /** @@ -427,9 +421,7 @@ private function getPhpstanType(\ReflectionClass $declaringClass, string $typeHi return sprintf('array<%s>', implode( ',', - array_map(static function (string $type) use ($reflector, $self) { - return $self->resolveType(trim($type), $reflector); - }, $types), + array_map(static fn (string $type) => $self->resolveType(trim($type), $reflector), $types), )); } } diff --git a/src/Ordering/AlphabeticalPropertyOrderingStrategy.php b/src/Ordering/AlphabeticalPropertyOrderingStrategy.php index a60d3cb09..68db769c0 100644 --- a/src/Ordering/AlphabeticalPropertyOrderingStrategy.php +++ b/src/Ordering/AlphabeticalPropertyOrderingStrategy.php @@ -15,9 +15,7 @@ public function order(array $properties): array { uasort( $properties, - static function (PropertyMetadata $a, PropertyMetadata $b): int { - return strcmp($a->name, $b->name); - }, + static fn (PropertyMetadata $a, PropertyMetadata $b): int => strcmp($a->name, $b->name), ); return $properties; diff --git a/src/XmlSerializationVisitor.php b/src/XmlSerializationVisitor.php index ae150aa66..8406d75b4 100644 --- a/src/XmlSerializationVisitor.php +++ b/src/XmlSerializationVisitor.php @@ -318,9 +318,7 @@ public function visitProperty(PropertyMetadata $metadata, $v): void } if ($addEnclosingElement = !$this->isInLineCollection($metadata) && !$metadata->inline) { - $namespace = null !== $metadata->xmlNamespace - ? $metadata->xmlNamespace - : $this->getClassDefaultNamespace($this->objectMetadataStack->top()); + $namespace = $metadata->xmlNamespace ?? $this->getClassDefaultNamespace($this->objectMetadataStack->top()); $element = $this->createElement($metadata->serializedName, $namespace); $this->currentNode->appendChild($element); From 1d1271cabb2123e0f4ad05ec972a798857a94e50 Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Mon, 5 Feb 2024 23:15:13 +0100 Subject: [PATCH 27/38] Remove min-stability --- composer.json | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 4d754518e..d20febac9 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,13 @@ "name": "jms/serializer", "type": "library", "description": "Library for (de-)serializing data of any complexity; supports XML, and JSON.", - "keywords": ["serialization", "deserialization", "json", "jaxb", "xml"], + "keywords": [ + "serialization", + "deserialization", + "json", + "jaxb", + "xml" + ], "homepage": "http://jmsyst.com/libs/serializer", "license": "MIT", "authors": [ @@ -73,6 +79,5 @@ "branch-alias": { "dev-master": "3.x-dev" } - }, - "minimum-stability": "dev" + } } From e46adfcf6f4cd9dbeffa9ea1045ca3f5e3c3f768 Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Mon, 5 Feb 2024 23:24:34 +0100 Subject: [PATCH 28/38] Fix Sphinx build --- doc/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/requirements.txt b/doc/requirements.txt index 48cdd9b64..6d5ef871a 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -3,3 +3,4 @@ git+https://github.com/fabpot/sphinx-php.git sphinx_rtd_theme Jinja2<3.0 MarkupSafe<2.1 +alabaster<0.7.14 From 872588b038ffcb502e2777170adc19273bdef09c Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Mon, 5 Feb 2024 23:37:35 +0100 Subject: [PATCH 29/38] Bump rector --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d20febac9..27d22ec5e 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,7 @@ "phpstan/phpstan": "^1.0.2", "phpunit/phpunit": "^9.0 || ^10.0", "psr/container": "^1.0 || ^2.0", - "rector/rector": "^0.18.13", + "rector/rector": "^0.19.0", "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", "symfony/expression-language": "^5.4 || ^6.0 || ^7.0", "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", From 7d7e87d8d4ab7ea3872d1328d4e684a8cab796b8 Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Tue, 30 Jan 2024 22:53:43 +0100 Subject: [PATCH 30/38] docs(annotations): Prefer Attributes over Annotations --- doc/reference/annotations.rst | 592 ++++++++++++++++------------------ 1 file changed, 274 insertions(+), 318 deletions(-) diff --git a/doc/reference/annotations.rst b/doc/reference/annotations.rst index 0cb5e385a..180120708 100644 --- a/doc/reference/annotations.rst +++ b/doc/reference/annotations.rst @@ -1,96 +1,168 @@ -Annotations -=========== +Attributes and annotations +========================== -@ExclusionPolicy -~~~~~~~~~~~~~~~~ -This annotation can be defined on a class to indicate the exclusion strategy +PHP 8 support +~~~~~~~~~~~~~~~ +JMS serializer now supports PHP 8 attributes, with a few caveats: +- Due to the missing support for nested attributes, the syntax for a few attributes has changed +(see the ``VirtualProperty`` ``options`` syntax here below) +- There is an edge case when setting this exact serialization group ``#[Groups(['value' => 'any value here'])]``. +(when there is only one item in th serialization groups array and has as key ``value`` the attribute will not work as expected, +please use the alternative syntax ``#[Groups(groups: ['value' => 'any value here'])]`` that works with no issues), + +Converting your annotations to attributes +----------------------------------------- + +Example: + +.. code-block :: php + + /** + * @VirtualProperty( + * "classlow", + * exp="object.getVirtualValue(1)", + * options={@Until("8")} + * ) + * @VirtualProperty( + * "classhigh", + * exp="object.getVirtualValue(8)", + * options={@Since("6")} + * ) + */ + #[VirtualProperty('classlow', exp: 'object.getVirtualValue(1)', options: [[Until::class, ['8']]])] + #[VirtualProperty('classhigh', exp: 'object.getVirtualValue(8)', options: [[Since::class, ['6']]])] + class ObjectWithVersionedVirtualProperties + { + /** + * @Groups({"versions"}) + * @VirtualProperty + * @SerializedName("low") + * @Until("8") + */ + #[Groups(['versions'])] + #[VirtualProperty] + #[SerializedName('low')] + #[Until('8')] + public function getVirtualLowValue() + { + return 1; + } + ... + +To automate migration of Annotations to Attributes you can use `rector/rector` with following config: + +.. code-block :: php + + paths([ + __DIR__ . '/src', + ]); + $rectorConfig->sets([ + JMSSetList::ANNOTATIONS_TO_ATTRIBUTES, + LevelSetList::UP_TO_PHP_80, + ]); + }; + + + +#[ExclusionPolicy] +~~~~~~~~~~~~~~~~~~ +This attribute can be defined on a class to indicate the exclusion strategy that should be used for the class. +----------+----------------------------------------------------------------+ | Policy | Description | +==========+================================================================+ | all | all properties are excluded by default; only properties marked | -| | with @Expose will be serialized/unserialized | +| | with #Expose will be serialized/unserialized | +----------+----------------------------------------------------------------+ | none | no properties are excluded by default; all properties except | -| | those marked with @Exclude will be serialized/unserialized | +| | those marked with #Exclude will be serialized/unserialized | +----------+----------------------------------------------------------------+ -@Exclude -~~~~~~~~ -This annotation can be defined on a property or a class to indicate that the property or class +#[Exclude] +~~~~~~~~~~ +This attribute can be defined on a property or a class to indicate that the property or class should not be serialized/unserialized. Works only in combination with NoneExclusionPolicy. If the ``ExpressionLanguageExclusionStrategy`` exclusion strategy is enabled, it will -be possible to use ``@Exclude(if="expression")`` to exclude dynamically a property +be possible to use ``#[Exclude(if:"expression")]`` to exclude dynamically a property or an object if used on class level. -@Expose -~~~~~~~ -This annotation can be defined on a property to indicate that the property should +#[Expose] +~~~~~~~~~ +This attribute can be defined on a property to indicate that the property should be serialized/unserialized. Works only in combination with AllExclusionPolicy. If the ``ExpressionLanguageExclusionStrategy`` exclusion strategy is enabled, will -be possible to use ``@Expose(if="expression")`` to expose dynamically a property. +be possible to use ``#Expose[if:"expression"]`` to expose dynamically a property. -@SkipWhenEmpty -~~~~~~~~~~~~~~ -This annotation can be defined on a property to indicate that the property should +#[SkipWhenEmpty] +~~~~~~~~~~~~~~~~ +This attribute can be defined on a property to indicate that the property should not be serialized if the result will be "empty". Works option works only when serializing. -@SerializedName -~~~~~~~~~~~~~~~ -This annotation can be defined on a property to define the serialized name for a +#[SerializedName] +~~~~~~~~~~~~~~~~~ +This attribute can be defined on a property to define the serialized name for a property. If this is not defined, the property will be translated from camel-case to a lower-cased underscored name, e.g. camelCase -> camel_case. -Note that this annotation is not used when you're using any other naming +Note that this attribute is not used when you're using any other naming strategy than the default configuration (which includes the -``SerializedNameAnnotationStrategy``). In order to re-enable the annotation, you -will need to wrap your custom strategy with the ``SerializedNameAnnotationStrategy``. +``SerializedNameattributeStrategy``). In order to re-enable the attribute, you +will need to wrap your custom strategy with the ``SerializedNameattributeStrategy``. .. code-block :: php setPropertyNamingStrategy( - new \JMS\Serializer\Naming\SerializedNameAnnotationStrategy( + new \JMS\Serializer\Naming\SerializedNameattributeStrategy( new \JMS\Serializer\Naming\IdenticalPropertyNamingStrategy() ) ) ->build(); -@Since -~~~~~~ -This annotation can be defined on a property to specify starting from which +#[Since] +~~~~~~~~ +This attribute can be defined on a property to specify starting from which version this property is available. If an earlier version is serialized, then this property is excluded automatically. The version must be in a format that is understood by PHP's ``version_compare`` function. -@Until -~~~~~~ -This annotation can be defined on a property to specify until which version this +#[Until] +~~~~~~~~ +This attribute can be defined on a property to specify until which version this property was available. If a later version is serialized, then this property is excluded automatically. The version must be in a format that is understood by PHP's ``version_compare`` function. -@Groups -~~~~~~~ -This annotation can be defined on a property to specify if the property +#[Groups] +~~~~~~~~~ +This attribute can be defined on a property to specify if the property should be serialized when only serializing specific groups (see :doc:`../cookbook/exclusion_strategies`). -@MaxDepth -~~~~~~~~~ -This annotation can be defined on a property to limit the depth to which the +#[MaxDepth] +~~~~~~~~~~~ +This attribute can be defined on a property to limit the depth to which the content will be serialized. It is very useful when a property will contain a large object graph. -@AccessType -~~~~~~~~~~~ -This annotation can be defined on a property, or a class to specify in which way +#[AccessType] +~~~~~~~~~~~~~ +This attribute can be defined on a property, or a class to specify in which way the properties should be accessed. By default, the serializer will retrieve, or set the value via reflection, but you may change this to use a public method instead: @@ -99,7 +171,7 @@ set the value via reflection, but you may change this to use a public method ins lastName; } - public function getFirstName() + public function getFirstName(): string { return $this->firstName; } @@ -259,14 +312,14 @@ In this example: - ``firstName`` is exposed using the ``object.getFirstName()`` expression (``exp`` can contain any valid symfony expression). -``@VirtualProperty()`` can also have an optional property ``name``, used to define the internal property name +``#[VirtualProperty]`` can also have an optional property ``name``, used to define the internal property name (for sorting proposes as example). When not specified, it defaults to the method name with the "get" prefix removed. .. note :: This only works for serialization and is completely ignored during deserialization. -In PHP 8, due to the missing support for nested annotations, in the options array you need to pass an array with the class name and an array with the arguments for its constructor. +In PHP 8, due to the missing support for nested attributes, in the options array you need to pass an array with the class name and an array with the arguments for its constructor. .. code-block :: php @@ -282,64 +335,60 @@ In PHP 8, due to the missing support for nested annotations, in the options arra { ... -@Inline -~~~~~~~ -This annotation can be defined on a property to indicate that the data of the property +#[Inline] +~~~~~~~~~ +This attribute can be defined on a property to indicate that the data of the property should be inlined. **Note**: AccessorOrder will be using the name of the property to determine the order. -@ReadOnlyProperty -~~~~~~~~~~~~~~~~~ -This annotation can be defined on a property to indicate that the data of the property +#[ReadOnlyProperty] +~~~~~~~~~~~~~~~~~~~ +This attribute can be defined on a property to indicate that the data of the property is read only and cannot be set during deserialization. -A property can be marked as non read only with ``@ReadOnlyProperty(false)`` annotation +A property can be marked as non read only with ``#[ReadOnlyProperty(readOnly: false)]`` attribute (useful when a class is marked as read only). -@PreSerialize -~~~~~~~~~~~~~ -This annotation can be defined on a method which is supposed to be called before +#[PreSerialize] +~~~~~~~~~~~~~~~ +This attribute can be defined on a method which is supposed to be called before the serialization of the object starts. -@PostSerialize -~~~~~~~~~~~~~~ -This annotation can be defined on a method which is then called directly after the +#[PostSerialize] +~~~~~~~~~~~~~~~~ +This attribute can be defined on a method which is then called directly after the object has been serialized. -@PostDeserialize -~~~~~~~~~~~~~~~~ -This annotation can be defined on a method which is supposed to be called after +#[PostDeserialize] +~~~~~~~~~~~~~~~~~~ +This attribute can be defined on a method which is supposed to be called after the object has been deserialized. -@Discriminator -~~~~~~~~~~~~~~ - -.. versionadded : 0.12 +#[Discriminator] +~~~~~~~~~~~~~~~~ - @Discriminator was added +This attribute allows serialization/deserialization of relations which are polymorphic, but +where a common base class exists. The ``#[Discriminator]`` attribute has to be applied +to the least super type: -This annotation allows serialization/deserialization of relations which are polymorphic, but -where a common base class exists. The ``@Discriminator`` annotation has to be applied -to the least super type:: +.. code-block :: php - /** - * @Discriminator(field = "type", disabled = false, map = {"car": "Car", "moped": "Moped"}, groups={"foo", "bar"}) - */ + #[Serializer\Discriminator(field: 'type', disabled: false, map: ['car' => 'Car', 'moped' => 'Moped'], groups=["foo", "bar"])] abstract class Vehicle { } class Car extends Vehicle { } class Moped extends Vehicle { } - + ... .. note :: `groups` is optional and is used as exclusion policy. -@Type -~~~~~ -This annotation can be defined on a property to specify the type of that property. -For deserialization, this annotation must be defined. -The ``@Type`` annotation can have parameters and parameters can be used by serialization/deserialization +#[Type] +~~~~~~~ +This attribute can be defined on a property to specify the type of that property. +For deserialization, this attribute must be defined. +The ``#[Type]`` attribute can have parameters and parameters can be used by serialization/deserialization handlers to enhance the serialization or deserialization result; for example, you may want to force a certain format to be used for serializing DateTime types and specifying at the same time a different format used when deserializing them. @@ -521,94 +570,74 @@ Examples: class BlogPost { - /** - * @Type("ArrayCollection") - */ + #[Type(name: "ArrayCollection")] private $comments; - /** - * @Type("string") - */ + #[Type(name: "string")] private $title; - /** - * @Type("MyNamespace\Author") - */ + #[Type(name: Author:class)] private $author; - /** - * @Type("DateTime") - */ + #[Type(name: DateTime:class)] private $startAt; - /** - * @Type("DateTime<'Y-m-d'>") - */ + #[Type(name: 'DateTime<'Y-m-d'>')] private $endAt; - /** - * @Type("DateTime<'Y-m-d', '', ['Y-m-d', 'Y/m/d']>") - */ + #[Type(name: 'DateTime<'Y-m-d'>')] + + #[Type(name:"DateTime<'Y-m-d', '', ['Y-m-d', 'Y/m/d']>")] private $publishedAt; - /** - * @Type("DateTimeImmutable") - */ + #[Type(name:'DateTimeImmutable')] private $createdAt; - /** - * @Type("DateTimeImmutable<'Y-m-d'>") - */ + #[Type(name:"DateTimeImmutable<'Y-m-d'>")] private $updatedAt; - /** - * @Type("DateTimeImmutable<'Y-m-d', '', ['Y-m-d', 'Y/m/d']>") - */ + #[Type(name:"DateTimeImmutable<'Y-m-d', '', ['Y-m-d', 'Y/m/d']>")] private $deletedAt; - /** - * @Type("boolean") - */ + #[Type(name:'boolean')] private $published; - /** - * @Type("array") - */ + #[Type(name:'array')] private $keyValueStore; } .. note :: if you are using ``PHP attributes`` with PHP 8.1 you can pass an object which implements ``__toString()`` method as a value for ``#[Type]`` attribute. - + .. code-block :: php - "; - } - } + class BlogPost + { + #[Type(new ArrayOf(Comment::class))] + private $comments; + } + + class ArrayOf implements \Stringable + { + public function __construct(private string $className) {} + + public function __toString(): string + { + return "array<$className>"; + } + } .. _configuration: https://jmsyst.com/bundles/JMSSerializerBundle/master/configuration#configuration-block-2-0 -@XmlRoot -~~~~~~~~ +#[XmlRoot] +~~~~~~~~~~ This allows you to specify the name of the top-level element. .. code-block :: php @@ -617,7 +646,7 @@ This allows you to specify the name of the top-level element. use JMS\Serializer\Annotation\XmlRoot; - /** @XmlRoot("user") */ + #[XmlRoot('user')] class User { private $name = 'Johannes'; @@ -633,12 +662,12 @@ Resulting XML: .. note :: - @XmlRoot only applies to the root element, but is for example not taken into + #[XmlRoot] only applies to the root element, but is for example not taken into account for collections. You can define the entry name for collections using - @XmlList, or @XmlMap. + #[XmlList], or #[XmlMap]. -@XmlAttribute -~~~~~~~~~~~~~ +#[XmlAttribute] +~~~~~~~~~~~~~~~ This allows you to mark properties which should be set as attributes, and not as child elements. @@ -650,7 +679,7 @@ and not as child elements. class User { - /** @XmlAttribute */ + #[XmlAttribute] private $id = 1; private $name = 'Johannes'; } @@ -664,9 +693,9 @@ Resulting XML: -@XmlDiscriminator -~~~~~~~~~~~~~~~~~ -This annotation allows to modify the behaviour of @Discriminator regarding handling of XML. +#[XmlDiscriminator] +~~~~~~~~~~~~~~~~~~~ +This attribute allows to modify the behaviour of ``#[Discriminator]`` regarding handling of XML. Available Options: @@ -690,10 +719,8 @@ Example for "attribute": use JMS\Serializer\Annotation\Discriminator; use JMS\Serializer\Annotation\XmlDiscriminator; - /** - * @Discriminator(field = "type", map = {"car": "Car", "moped": "Moped"}, groups={"foo", "bar"}) - * @XmlDiscriminator(attribute=true) - */ + #[Discriminator(field: 'type', map: ['car' => 'Car', 'moped' => 'Moped'], groups: ['foo', 'bar'])] + #[XmlDiscriminator(attribute: true)] abstract class Vehicle { } class Car extends Vehicle { } @@ -713,12 +740,8 @@ Example for "cdata": use JMS\Serializer\Annotation\Discriminator; use JMS\Serializer\Annotation\XmlDiscriminator; - - - /** - * @Discriminator(field = "type", map = {"car": "Car", "moped": "Moped"}, groups={"foo", "bar"}) - * @XmlDiscriminator(attribute=true) - */ + #[Discriminator(field: 'type', map: ['car' => 'Car', 'moped' => 'Moped'], groups: ['foo', 'bar'])] + #[XmlDiscriminator] abstract class Vehicle { } class Car extends Vehicle { } @@ -729,11 +752,11 @@ Resulting XML: car -@XmlValue -~~~~~~~~~ +#[XmlValue] +~~~~~~~~~~~ This allows you to mark properties which should be set as the value of the current element. Note that this has the limitation that any additional -properties of that object must have the @XmlAttribute annotation. +properties of that object must have the #[XmlAttribute] attribute. XMlValue also has property cdata. Which has the same meaning as the one in XMLElement. @@ -745,26 +768,27 @@ XMLElement. use JMS\Serializer\Annotation\XmlValue; use JMS\Serializer\Annotation\XmlRoot; - /** @XmlRoot("price") */ + #[XmlRoot('price')] class Price { - /** @XmlAttribute */ + #[XmlAttribute] private $currency = 'EUR'; - /** @XmlValue */ + #[XmlValue] private $amount = 1.23; } + Resulting XML: .. code-block :: xml 1.23 -@XmlList -~~~~~~~~ +#[XmlList] +~~~~~~~~~~ This allows you to define several properties of how arrays should be -serialized. This is very similar to @XmlMap, and should be used if the +serialized. This is very similar to #[XmlMap], and should be used if the keys of the array are not important. .. code-block :: php @@ -774,37 +798,24 @@ keys of the array are not important. use JMS\Serializer\Annotation\XmlList; use JMS\Serializer\Annotation\XmlRoot; - /** @XmlRoot("post") */ + #[XmlRoot('post')] class Post { - /** - * @XmlList(inline = true, entry = "comment") - */ - private $comments = []; - - public function __construct(array $comments) + public function __construct( + #[XmlList(inline: true, entry: 'comment')] + private array $comments + ) { - $this->comments = $comments; } } class Comment { - private $text; - - public function __construct(string $text) + public function __construct(private string $text) { - $this->text = $text; } } - // usage - $post = new Post( - new Comment('Foo'), - new Comment('Bar'), - ); - $xml = $serializer->serialize($post, 'xml'); - Resulting XML: .. code-block :: xml @@ -818,64 +829,59 @@ Resulting XML: -You can also specify the entry tag namespace using the ``namespace`` attribute (``@XmlList(inline = true, entry = "comment", namespace="http://www.example.com/ns")``). +You can also specify the entry tag namespace using the ``namespace`` attribute (``#[XmlList(inline: true, entry: 'comment', namespace: 'http://www.example.com/ns')]``). -@XmlMap -~~~~~~~ -Similar to @XmlList, but the keys of the array are meaningful. +#[XmlMap] +~~~~~~~~~ +Similar to #[XmlList], but the keys of the array are meaningful. -@XmlKeyValuePairs -~~~~~~~~~~~~~~~~~ +#[XmlKeyValuePairs] +~~~~~~~~~~~~~~~~~~~ This allows you to use the keys of an array as xml tags. .. note :: When a key is an invalid xml tag name (e.g. 1_foo) the tag name *entry* will be used instead of the key. -@XmlAttributeMap -~~~~~~~~~~~~~~~~ +#[XmlAttributeMap] +~~~~~~~~~~~~~~~~~~ -This is similar to the @XmlKeyValuePairs, but instead of creating child elements, it creates attributes. +This is similar to the #[XmlKeyValuePairs], but instead of creating child elements, it creates attributes. .. code-block :: php 'firstname', - 'value' => 'Adrien', - ); + #[XmlAttributeMap] + private $id = ['name' => 'firstname', 'value' => 'Adrien']; } + Resulting XML: .. code-block :: xml -@XmlElement -~~~~~~~~~~~ -This annotation can be defined on a property to add additional xml serialization/deserialization properties. +#[XmlElement] +~~~~~~~~~~~~~ +This attribute can be defined on a property to add additional xml serialization/deserialization properties. .. code-block :: php my_id -@XmlNamespace -~~~~~~~~~~~~~ -This annotation allows you to specify Xml namespace/s and prefix used. +#[XmlNamespace] +~~~~~~~~~~~~~~~ +This attribute allows you to specify Xml namespace/s and prefix used. .. code-block :: php -PHP 8 support -~~~~~~~~~~~~~ - -JMS serializer now supports PHP 8 attributes, with a few caveats: -- Due to the missing support for nested annotations, the syntax for a few annotations has changed -(see the ``VirtualProperty`` ``options`` syntax here below) -- There is an edge case when setting this exact serialization group ``#[Groups(['value' => 'any value here'])]``. -(when there is only one item in th serialization groups array and has as key ``value`` the attribute will not work as expected, -please use the alternative syntax ``#[Groups(groups: ['value' => 'any value here'])]`` that works with no issues), - -Converting your annotations to attributes ------------------------------------------ - -Example: - -.. code-block :: php - - /** - * @VirtualProperty( - * "classlow", - * exp="object.getVirtualValue(1)", - * options={@Until("8")} - * ) - * @VirtualProperty( - * "classhigh", - * exp="object.getVirtualValue(8)", - * options={@Since("6")} - * ) - */ - #[VirtualProperty('classlow', exp: 'object.getVirtualValue(1)', options: [[Until::class, ['8']]])] - #[VirtualProperty('classhigh', exp: 'object.getVirtualValue(8)', options: [[Since::class, ['6']]])] - class ObjectWithVersionedVirtualProperties - { - /** - * @Groups({"versions"}) - * @VirtualProperty - * @SerializedName("low") - * @Until("8") - */ - #[Groups(['versions'])] - #[VirtualProperty] - #[SerializedName('low')] - #[Until('8')] - public function getVirtualLowValue() - { - return 1; - } - ... - Enum support -~~~~~~~~~~~~ +~~~~~~~~~~~~~~ Enum support is disabled by default, to enable it run: @@ -994,7 +950,7 @@ Enum support is disabled by default, to enable it run: With the enum support enabled, enums are automatically detected using typed properties typehints. When typed properties are no available (virtual properties as example), it is necessary to explicitly typehint -the underlying type using the ``@Type`` annotation. +the underlying type using the ``#[Type]`` attribute. - If the enum is a ``BackedEnum``, the case value will be used for serialization and deserialization by default; - If the enum is not a ``BackedEnum``, the case name will be used for serialization and deserialization by default; From c952f9d95bbd249c5e0aef9c397918383d5a2cfb Mon Sep 17 00:00:00 2001 From: Jakub Pastuszek Date: Tue, 6 Feb 2024 08:37:40 +0100 Subject: [PATCH 31/38] Add Backed Enum without name/value specification to test --- doc/reference/annotations.rst | 6 ++---- tests/Fixtures/ObjectWithEnums.php | 17 +++++++++++++++-- tests/Serializer/JsonSerializationTest.php | 2 +- tests/Serializer/xml/object_with_enums.xml | 7 ++++++- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/doc/reference/annotations.rst b/doc/reference/annotations.rst index 0cb5e385a..c2f4b1123 100644 --- a/doc/reference/annotations.rst +++ b/doc/reference/annotations.rst @@ -387,10 +387,8 @@ Available Types: | | Examples: array, | | | array, etc. | +------------------------------------------------------------+--------------------------------------------------+ -| enum<'Color'> | Enum of type Color, use its case values | -| | for serialization and deserialization | -| | if the enum is a backed enum, | -| | use its case names if it is not a backed enum. | +| enum<'Color'> | Enum of type Color, use its case names | +| | for serialization and deserialization. | +------------------------------------------------------------+--------------------------------------------------+ | enum<'Color', 'name'> | Enum of type Color, use its case names | | | (as string) for serialization | diff --git a/tests/Fixtures/ObjectWithEnums.php b/tests/Fixtures/ObjectWithEnums.php index f7761f086..84f84d2c8 100644 --- a/tests/Fixtures/ObjectWithEnums.php +++ b/tests/Fixtures/ObjectWithEnums.php @@ -15,10 +15,16 @@ class ObjectWithEnums * @Serializer\Type("enum<'JMS\Serializer\Tests\Fixtures\Enum\Suit', 'name'>") */ public Suit $ordinary; + /** * @Serializer\Type("enum<'JMS\Serializer\Tests\Fixtures\Enum\BackedSuit', 'value'>") */ - public BackedSuit $backed; + public BackedSuit $backedValue; + + /** + * @Serializer\Type("enum<'JMS\Serializer\Tests\Fixtures\Enum\BackedSuit'>") + */ + public BackedSuit $backedWithoutParam; /** * @Serializer\Type("array>") @@ -30,6 +36,11 @@ class ObjectWithEnums */ public array $backedArray; + /** + * @Serializer\Type("array>") + */ + public array $backedArrayWithoutParam; + public Suit $ordinaryAutoDetect; public BackedSuit $backedAutoDetect; @@ -46,9 +57,11 @@ public function __construct() { $this->ordinary = Suit::Clubs; - $this->backed = BackedSuit::Clubs; + $this->backedValue = BackedSuit::Clubs; + $this->backedWithoutParam = BackedSuit::Clubs; $this->backedArray = [BackedSuit::Clubs, BackedSuit::Hearts]; + $this->backedArrayWithoutParam = [BackedSuit::Clubs, BackedSuit::Hearts]; $this->ordinaryArray = [Suit::Clubs, Suit::Spades]; $this->ordinaryAutoDetect = Suit::Clubs; diff --git a/tests/Serializer/JsonSerializationTest.php b/tests/Serializer/JsonSerializationTest.php index 0c6800e89..4c7bb0302 100644 --- a/tests/Serializer/JsonSerializationTest.php +++ b/tests/Serializer/JsonSerializationTest.php @@ -141,7 +141,7 @@ protected static function getContent($key) $outputs['custom_datetimeinterface'] = '{"custom":"2021-09-07"}'; $outputs['data_integer'] = '{"data":10000}'; $outputs['uid'] = '"66b3177c-e03b-4a22-9dee-ddd7d37a04d5"'; - $outputs['object_with_enums'] = '{"ordinary":"Clubs","backed":"C","ordinary_array":["Clubs","Spades"],"backed_array":["C","H"],"ordinary_auto_detect":"Clubs","backed_auto_detect":"C","backed_int_auto_detect":3,"backed_int":3,"backed_name":"C","backed_int_forced_str":3}'; + $outputs['object_with_enums'] = '{"ordinary":"Clubs","backed_value":"C","backed_without_param":"C","ordinary_array":["Clubs","Spades"],"backed_array":["C","H"],"backed_array_without_param":["C","H"],"ordinary_auto_detect":"Clubs","backed_auto_detect":"C","backed_int_auto_detect":3,"backed_int":3,"backed_name":"C","backed_int_forced_str":3}'; $outputs['object_with_autodetect_enums'] = '{"ordinary_array_auto_detect":["Clubs","Spades"],"backed_array_auto_detect":["C","H"],"mixed_array_auto_detect":["Clubs","H"]}'; $outputs['object_with_enums_disabled'] = '{"ordinary_array_auto_detect":[{"name":"Clubs"},{"name":"Spades"}],"backed_array_auto_detect":[{"name":"Clubs","value":"C"},{"name":"Hearts","value":"H"}],"mixed_array_auto_detect":[{"name":"Clubs"},{"name":"Hearts","value":"H"}]}'; } diff --git a/tests/Serializer/xml/object_with_enums.xml b/tests/Serializer/xml/object_with_enums.xml index bba1a2b00..ab0017713 100644 --- a/tests/Serializer/xml/object_with_enums.xml +++ b/tests/Serializer/xml/object_with_enums.xml @@ -1,7 +1,8 @@ - + + @@ -10,6 +11,10 @@ + + + + 3 From 91d59c7963a35d77e176fee4e5be3d8a18a33cf9 Mon Sep 17 00:00:00 2001 From: Jakub Pastuszek Date: Tue, 6 Feb 2024 10:18:10 +0100 Subject: [PATCH 32/38] Fix serialization of BackedEnum - annotation without name/value --- doc/reference/annotations.rst | 6 ++++-- src/Handler/EnumHandler.php | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/reference/annotations.rst b/doc/reference/annotations.rst index c2f4b1123..0cb5e385a 100644 --- a/doc/reference/annotations.rst +++ b/doc/reference/annotations.rst @@ -387,8 +387,10 @@ Available Types: | | Examples: array, | | | array, etc. | +------------------------------------------------------------+--------------------------------------------------+ -| enum<'Color'> | Enum of type Color, use its case names | -| | for serialization and deserialization. | +| enum<'Color'> | Enum of type Color, use its case values | +| | for serialization and deserialization | +| | if the enum is a backed enum, | +| | use its case names if it is not a backed enum. | +------------------------------------------------------------+--------------------------------------------------+ | enum<'Color', 'name'> | Enum of type Color, use its case names | | | (as string) for serialization | diff --git a/src/Handler/EnumHandler.php b/src/Handler/EnumHandler.php index 1adbc051a..916f3b8d7 100644 --- a/src/Handler/EnumHandler.php +++ b/src/Handler/EnumHandler.php @@ -44,7 +44,7 @@ public function serializeEnum( array $type, SerializationContext $context ) { - if (isset($type['params'][1]) && 'value' === $type['params'][1]) { + if ((isset($type['params'][1]) && 'value' === $type['params'][1]) || (!isset($type['params'][1]) && is_a($enum, \BackedEnum::class, true))) { if (!$enum instanceof \BackedEnum) { throw new InvalidMetadataException(sprintf('The type "%s" is not a backed enum, thus you can not use "value" as serialization mode for its value.', get_class($enum))); } From c7e6eb13f404013f57e5d3c5aea345c653634fb4 Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Sun, 5 Feb 2023 13:24:23 -0500 Subject: [PATCH 33/38] Make the Annotations package optional in the builder API --- composer.json | 2 +- src/Builder/CallbackDriverFactory.php | 6 +++++- src/Builder/DefaultDriverFactory.php | 13 +++++++++++-- src/Builder/DocBlockDriverFactory.php | 2 +- src/Builder/DriverFactoryInterface.php | 2 +- src/SerializerBuilder.php | 5 ++--- 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 27d22ec5e..231ab583e 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,6 @@ ], "require": { "php": "^7.4 || ^8.0", - "doctrine/annotations": "^1.14 || ^2.0", "doctrine/instantiator": "^1.3.1 || ^2.0", "doctrine/lexer": "^2.0 || ^3.0", "jms/metadata": "^2.6", @@ -37,6 +36,7 @@ }, "require-dev": { "ext-pdo_sqlite": "*", + "doctrine/annotations": "^1.14 || ^2.0", "doctrine/coding-standard": "^12.0", "doctrine/orm": "^2.14 || ^3.0", "doctrine/persistence": "^2.5.2 || ^3.0", diff --git a/src/Builder/CallbackDriverFactory.php b/src/Builder/CallbackDriverFactory.php index 1bf2fc913..b35d4f5e1 100644 --- a/src/Builder/CallbackDriverFactory.php +++ b/src/Builder/CallbackDriverFactory.php @@ -12,15 +12,19 @@ final class CallbackDriverFactory implements DriverFactoryInterface { /** * @var callable + * @phpstan-var callable(array $metadataDirs, Reader|null $reader): DriverInterface */ private $callback; + /** + * @phpstan-param callable(array $metadataDirs, Reader|null $reader): DriverInterface $callable + */ public function __construct(callable $callable) { $this->callback = $callable; } - public function createDriver(array $metadataDirs, Reader $reader): DriverInterface + public function createDriver(array $metadataDirs, ?Reader $reader = null): DriverInterface { $driver = \call_user_func($this->callback, $metadataDirs, $reader); if (!$driver instanceof DriverInterface) { diff --git a/src/Builder/DefaultDriverFactory.php b/src/Builder/DefaultDriverFactory.php index afe2e4e30..74ca1d9ed 100644 --- a/src/Builder/DefaultDriverFactory.php +++ b/src/Builder/DefaultDriverFactory.php @@ -5,6 +5,7 @@ namespace JMS\Serializer\Builder; use Doctrine\Common\Annotations\Reader; +use JMS\Serializer\Exception\RuntimeException; use JMS\Serializer\Expression\CompilableExpressionEvaluatorInterface; use JMS\Serializer\Metadata\Driver\AnnotationOrAttributeDriver; use JMS\Serializer\Metadata\Driver\DefaultValuePropertyDriver; @@ -55,8 +56,12 @@ public function enableEnumSupport(bool $enableEnumSupport = true): void $this->enableEnumSupport = $enableEnumSupport; } - public function createDriver(array $metadataDirs, Reader $annotationReader): DriverInterface + public function createDriver(array $metadataDirs, ?Reader $annotationReader = null): DriverInterface { + if (PHP_VERSION_ID < 80000 && empty($metadataDirs) && !interface_exists(Reader::class)) { + throw new RuntimeException(sprintf('To use "%s", either a list of metadata directories must be provided, the "doctrine/annotations" package installed, or use PHP 8.0 or later.', self::class)); + } + /* * Build the sorted list of metadata drivers based on the environment. The final order should be: * @@ -65,7 +70,11 @@ public function createDriver(array $metadataDirs, Reader $annotationReader): Dri * - Annotations/Attributes Driver * - Null (Fallback) Driver */ - $metadataDrivers = [new AnnotationOrAttributeDriver($this->propertyNamingStrategy, $this->typeParser, $this->expressionEvaluator, $annotationReader)]; + $metadataDrivers = []; + + if (PHP_VERSION_ID >= 80000 || $annotationReader instanceof Reader) { + $metadataDrivers[] = new AnnotationOrAttributeDriver($this->propertyNamingStrategy, $this->typeParser, $this->expressionEvaluator, $annotationReader); + } if (!empty($metadataDirs)) { $fileLocator = new FileLocator($metadataDirs); diff --git a/src/Builder/DocBlockDriverFactory.php b/src/Builder/DocBlockDriverFactory.php index 3188a01db..67f0ec527 100644 --- a/src/Builder/DocBlockDriverFactory.php +++ b/src/Builder/DocBlockDriverFactory.php @@ -26,7 +26,7 @@ public function __construct(DriverFactoryInterface $driverFactoryToDecorate, ?Pa $this->typeParser = $typeParser; } - public function createDriver(array $metadataDirs, Reader $annotationReader): DriverInterface + public function createDriver(array $metadataDirs, ?Reader $annotationReader = null): DriverInterface { $driver = $this->driverFactoryToDecorate->createDriver($metadataDirs, $annotationReader); diff --git a/src/Builder/DriverFactoryInterface.php b/src/Builder/DriverFactoryInterface.php index d7655e115..7bfade916 100644 --- a/src/Builder/DriverFactoryInterface.php +++ b/src/Builder/DriverFactoryInterface.php @@ -9,5 +9,5 @@ interface DriverFactoryInterface { - public function createDriver(array $metadataDirs, Reader $annotationReader): DriverInterface; + public function createDriver(array $metadataDirs, ?Reader $annotationReader = null): DriverInterface; } diff --git a/src/SerializerBuilder.php b/src/SerializerBuilder.php index 45f42f4a8..996078599 100644 --- a/src/SerializerBuilder.php +++ b/src/SerializerBuilder.php @@ -552,9 +552,8 @@ public function setDocBlockTypeResolver(bool $docBlockTypeResolver): self public function build(): Serializer { $annotationReader = $this->annotationReader; - if (null === $annotationReader) { - $annotationReader = new AnnotationReader(); - $annotationReader = $this->decorateAnnotationReader($annotationReader); + if (null === $annotationReader && class_exists(AnnotationReader::class)) { + $annotationReader = $this->decorateAnnotationReader(new AnnotationReader()); } if (null === $this->driverFactory) { From 3a3518a5b568cd2919ed95b3d749ba823ad52140 Mon Sep 17 00:00:00 2001 From: Jakub Pastuszek Date: Tue, 20 Feb 2024 16:31:44 +0100 Subject: [PATCH 34/38] Use instanceof instead of is_a() --- src/Handler/EnumHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Handler/EnumHandler.php b/src/Handler/EnumHandler.php index 916f3b8d7..44e223bed 100644 --- a/src/Handler/EnumHandler.php +++ b/src/Handler/EnumHandler.php @@ -44,7 +44,7 @@ public function serializeEnum( array $type, SerializationContext $context ) { - if ((isset($type['params'][1]) && 'value' === $type['params'][1]) || (!isset($type['params'][1]) && is_a($enum, \BackedEnum::class, true))) { + if ((isset($type['params'][1]) && 'value' === $type['params'][1]) || (!isset($type['params'][1]) && $enum instanceof \BackedEnum)) { if (!$enum instanceof \BackedEnum) { throw new InvalidMetadataException(sprintf('The type "%s" is not a backed enum, thus you can not use "value" as serialization mode for its value.', get_class($enum))); } From d0801a4fd600d18cb5217b4258501e97f777312c Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Wed, 28 Feb 2024 21:02:05 +0100 Subject: [PATCH 35/38] docs(annotations): Link new Changelog. Add docs for 3.30.0 --- CHANGELOG.md | 2 ++ UPGRADING.md | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f93b3b59..9f5579068 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +New versions can be found on the [realeases page](https://github.com/schmittjoh/serializer/releases) + ## [3.15.0](https://github.com/schmittjoh/serializer/tree/3.15.0) (2021-10-14) **Merged pull requests:** diff --git a/UPGRADING.md b/UPGRADING.md index 4c5b0c8c5..1784b1099 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -5,6 +5,15 @@ Unreleased - Deprecated the `@ReadOnly` annotation due to `readonly` becoming a keyword in PHP 8.1, use the `@ReadOnlyProperty` annotation instead - Doctrine type `decimal` is now correctly mapped to `string` instead of `float` +From 3.x to 3.30.0 +================== + +Starting from this release [doctrine/annotations](https://github.com/doctrine/annotations) is an optional package. +If you still want to use them, please make sure that you require in `composer.json` file. + +We strongly recommend to start using [Attributes](https://www.php.net/manual/en/language.attributes.overview.php) with PHP 8. +You can easily migrate annotations to attributes with [rector](https://github.com/rectorphp/rector) and `Rector\Symfony\Set::ANNOTATIONS_TO_ATTRIBUTES` rules. + From 2.x to 3.0.0 ================= From ffb930c664e3f3937464443c92cd6810a9c5e96a Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Mon, 4 Mar 2024 19:49:47 +0100 Subject: [PATCH 36/38] deps(composer): Update to PHPUnit 11 & Rector 1.0 --- composer.json | 6 +- phpstan/ignore-by-php-version.neon.php | 9 ++- phpstan/no-phpunit-attributes.neon | 3 + rector.php | 2 +- .../Deserializer/BaseDeserializationTest.php | 3 + .../DisjunctExclusionStrategyTest.php | 20 ++--- .../Exclusion/GroupsExclusionStrategyTest.php | 9 +-- tests/Handler/ArrayCollectionDepthTest.php | 2 + tests/Handler/ArrayCollectionHandlerTest.php | 3 + tests/Handler/DateHandlerTest.php | 12 +-- tests/Handler/IteratorHandlerTest.php | 2 + tests/Handler/SymfonyUidHandlerTest.php | 6 ++ tests/Metadata/ClassMetadataTest.php | 23 +++--- tests/Metadata/Driver/DoctrineDriverTest.php | 2 +- .../Driver/DoctrinePHPCRDriverTest.php | 17 +++-- .../CustomPropertyOrderingStrategyTest.php | 2 + tests/Serializer/ArrayTest.php | 7 +- .../Serializer/BaseSerializationTestCase.php | 76 +++++++++---------- tests/Serializer/ContextTest.php | 35 +++++---- .../Doctrine/ObjectConstructorTest.php | 6 +- tests/Serializer/GraphNavigatorTest.php | 20 +++-- tests/Serializer/JsonSerializationTest.php | 56 +++++--------- .../JsonStrictSerializationTest.php | 7 +- .../Naming/CamelCaseNamingStrategyTest.php | 2 + .../IdenticalPropertyNamingStrategyTest.php | 2 + .../SerializationContextFactoryTest.php | 18 +++-- tests/Serializer/Type/ParserTest.php | 3 + tests/Serializer/XmlSerializationTest.php | 7 ++ tests/SerializerBuilderTest.php | 12 ++- 29 files changed, 213 insertions(+), 159 deletions(-) create mode 100644 phpstan/no-phpunit-attributes.neon diff --git a/composer.json b/composer.json index 231ab583e..08406fc41 100644 --- a/composer.json +++ b/composer.json @@ -44,10 +44,10 @@ "jackalope/jackalope-doctrine-dbal": "^1.3", "ocramius/proxy-manager": "^1.0 || ^2.0", "phpbench/phpbench": "^1.0", - "phpstan/phpstan": "^1.0.2", - "phpunit/phpunit": "^9.0 || ^10.0", + "phpstan/phpstan": "^1.10.57", + "phpunit/phpunit": "^9.0 || ^10.0 || ^11.0", "psr/container": "^1.0 || ^2.0", - "rector/rector": "^0.19.0", + "rector/rector": "^1.0.0", "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", "symfony/expression-language": "^5.4 || ^6.0 || ^7.0", "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", diff --git a/phpstan/ignore-by-php-version.neon.php b/phpstan/ignore-by-php-version.neon.php index d5d5a0520..b3ef4e83b 100644 --- a/phpstan/ignore-by-php-version.neon.php +++ b/phpstan/ignore-by-php-version.neon.php @@ -1,5 +1,8 @@ = 80000) { $includes[] = __DIR__ . '/ignore-missing-attribute.neon'; + if(!class_exists(DataProvider::class)) { + $includes[] = __DIR__ . '/no-phpunit-attributes.neon'; + } } if (PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80200) { $includes[] = __DIR__ . '/php-81.neon'; } -if(!class_exists(Symfony\Component\Uid\UuidV7::class)) { +if(!class_exists(UuidV7::class)) { $includes[] = __DIR__ . '/no-uuid-7.neon'; } + $config = []; $config['includes'] = $includes; $config['parameters']['phpVersion'] = PHP_VERSION_ID; diff --git a/phpstan/no-phpunit-attributes.neon b/phpstan/no-phpunit-attributes.neon new file mode 100644 index 000000000..a66b213b9 --- /dev/null +++ b/phpstan/no-phpunit-attributes.neon @@ -0,0 +1,3 @@ +parameters: + ignoreErrors: + - '~Attribute class PHPUnit\\Framework\\Attributes\\.* does not exist~' diff --git a/rector.php b/rector.php index 6cc8584b1..154c683ee 100644 --- a/rector.php +++ b/rector.php @@ -9,5 +9,5 @@ $rectorConfig->paths([ __DIR__ . '/src', ]); - $rectorConfig->sets([LevelSetList::UP_TO_PHP_74]); + $rectorConfig->phpVersion(74); }; diff --git a/tests/Deserializer/BaseDeserializationTest.php b/tests/Deserializer/BaseDeserializationTest.php index 8aaf6b71a..736b8ef83 100644 --- a/tests/Deserializer/BaseDeserializationTest.php +++ b/tests/Deserializer/BaseDeserializationTest.php @@ -11,6 +11,7 @@ use JMS\Serializer\Tests\Fixtures\GroupsObject; use JMS\Serializer\Tests\Fixtures\Price; use JMS\Serializer\Tests\Fixtures\Publisher; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class BaseDeserializationTest extends TestCase @@ -18,6 +19,7 @@ class BaseDeserializationTest extends TestCase /** * @dataProvider dataTypeCannotBeCasted */ + #[DataProvider('dataTypeCannotBeCasted')] public function testDeserializationInvalidDataCausesException($data, string $type): void { $serializer = SerializerBuilder::create()->build(); @@ -48,6 +50,7 @@ public static function dataTypeCannotBeCasted(): iterable /** * @dataProvider dataDeserializerGroupExclusion */ + #[DataProvider('dataDeserializerGroupExclusion')] public function testDeserializerGroupExclusion(array $data, array $groups, array $expected): void { $serializer = SerializerBuilder::create()->build(); diff --git a/tests/Exclusion/DisjunctExclusionStrategyTest.php b/tests/Exclusion/DisjunctExclusionStrategyTest.php index 5b25d59d9..4ad965d48 100644 --- a/tests/Exclusion/DisjunctExclusionStrategyTest.php +++ b/tests/Exclusion/DisjunctExclusionStrategyTest.php @@ -25,7 +25,7 @@ public function testShouldSkipClassShortCircuiting() $first->expects($this->once()) ->method('shouldSkipClass') ->with($metadata, $context) - ->will($this->returnValue(true)); + ->willReturn(true); $last->expects($this->never()) ->method('shouldSkipClass'); @@ -46,12 +46,12 @@ public function testShouldSkipClassDisjunctBehavior() $first->expects($this->once()) ->method('shouldSkipClass') ->with($metadata, $context) - ->will($this->returnValue(false)); + ->willReturn(false); $last->expects($this->once()) ->method('shouldSkipClass') ->with($metadata, $context) - ->will($this->returnValue(true)); + ->willReturn(true); self::assertTrue($strat->shouldSkipClass($metadata, $context)); } @@ -69,12 +69,12 @@ public function testShouldSkipClassReturnsFalseIfNoPredicateMatched() $first->expects($this->once()) ->method('shouldSkipClass') ->with($metadata, $context) - ->will($this->returnValue(false)); + ->willReturn(false); $last->expects($this->once()) ->method('shouldSkipClass') ->with($metadata, $context) - ->will($this->returnValue(false)); + ->willReturn(false); self::assertFalse($strat->shouldSkipClass($metadata, $context)); } @@ -92,7 +92,7 @@ public function testShouldSkipPropertyShortCircuiting() $first->expects($this->once()) ->method('shouldSkipProperty') ->with($metadata, $context) - ->will($this->returnValue(true)); + ->willReturn(true); $last->expects($this->never()) ->method('shouldSkipProperty'); @@ -113,12 +113,12 @@ public function testShouldSkipPropertyDisjunct() $first->expects($this->once()) ->method('shouldSkipProperty') ->with($metadata, $context) - ->will($this->returnValue(false)); + ->willReturn(false); $last->expects($this->once()) ->method('shouldSkipProperty') ->with($metadata, $context) - ->will($this->returnValue(true)); + ->willReturn(true); self::assertTrue($strat->shouldSkipProperty($metadata, $context)); } @@ -136,12 +136,12 @@ public function testShouldSkipPropertyReturnsFalseIfNoPredicateMatches() $first->expects($this->once()) ->method('shouldSkipProperty') ->with($metadata, $context) - ->will($this->returnValue(false)); + ->willReturn(false); $last->expects($this->once()) ->method('shouldSkipProperty') ->with($metadata, $context) - ->will($this->returnValue(false)); + ->willReturn(false); self::assertFalse($strat->shouldSkipProperty($metadata, $context)); } diff --git a/tests/Exclusion/GroupsExclusionStrategyTest.php b/tests/Exclusion/GroupsExclusionStrategyTest.php index 02ea11069..05f4c29d6 100644 --- a/tests/Exclusion/GroupsExclusionStrategyTest.php +++ b/tests/Exclusion/GroupsExclusionStrategyTest.php @@ -7,18 +7,16 @@ use JMS\Serializer\Exclusion\GroupsExclusionStrategy; use JMS\Serializer\Metadata\StaticPropertyMetadata; use JMS\Serializer\SerializationContext; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class GroupsExclusionStrategyTest extends TestCase { /** - * @param array $propertyGroups - * @param array $groups - * @param bool $exclude - * * @dataProvider getExclusionRules */ - public function testUninitializedContextIsWorking(array $propertyGroups, array $groups, $exclude) + #[DataProvider('getExclusionRules')] + public function testUninitializedContextIsWorking(array $propertyGroups, array $groups, bool $exclude) { $metadata = new StaticPropertyMetadata('stdClass', 'prop', 'propVal'); $metadata->groups = $propertyGroups; @@ -57,6 +55,7 @@ public static function getExclusionRules() /** * @dataProvider getGroupsFor */ + #[DataProvider('getGroupsFor')] public function testGroupsFor(array $groups, array $propsVisited, array $resultingGroups) { $exclusion = new GroupsExclusionStrategy($groups); diff --git a/tests/Handler/ArrayCollectionDepthTest.php b/tests/Handler/ArrayCollectionDepthTest.php index d0ddcf143..1c924635a 100644 --- a/tests/Handler/ArrayCollectionDepthTest.php +++ b/tests/Handler/ArrayCollectionDepthTest.php @@ -11,6 +11,7 @@ use JMS\Serializer\SerializationContext; use JMS\Serializer\Serializer as JMSSerializer; use JMS\Serializer\SerializerBuilder; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class ArrayCollectionDepthTest extends TestCase @@ -28,6 +29,7 @@ protected function setUp(): void * * @dataProvider getCollections */ + #[DataProvider('getCollections')] public function testDepth($collection) { $context = SerializationContext::create() diff --git a/tests/Handler/ArrayCollectionHandlerTest.php b/tests/Handler/ArrayCollectionHandlerTest.php index 3fc13e34c..00053fd6f 100644 --- a/tests/Handler/ArrayCollectionHandlerTest.php +++ b/tests/Handler/ArrayCollectionHandlerTest.php @@ -11,6 +11,7 @@ use JMS\Serializer\Tests\Fixtures\ExclusionStrategy\AlwaysExcludeExclusionStrategy; use JMS\Serializer\Visitor\SerializationVisitorInterface; use Metadata\MetadataFactoryInterface; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\TestCase; class ArrayCollectionHandlerTest extends TestCase @@ -18,6 +19,7 @@ class ArrayCollectionHandlerTest extends TestCase /** * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testSerializeArray() { $handler = new ArrayCollectionHandler(); @@ -36,6 +38,7 @@ public function testSerializeArray() /** * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testSerializeArraySkipByExclusionStrategy() { $handler = new ArrayCollectionHandler(false); diff --git a/tests/Handler/DateHandlerTest.php b/tests/Handler/DateHandlerTest.php index 17b00c0ac..86d4955da 100644 --- a/tests/Handler/DateHandlerTest.php +++ b/tests/Handler/DateHandlerTest.php @@ -9,6 +9,8 @@ use JMS\Serializer\SerializationContext; use JMS\Serializer\Visitor\DeserializationVisitorInterface; use JMS\Serializer\Visitor\SerializationVisitorInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\TestCase; class DateHandlerTest extends TestCase @@ -39,11 +41,11 @@ public static function getParams() } /** - * @param array $params - * * @doesNotPerformAssertions * @dataProvider getParams */ + #[DataProvider('getParams')] + #[DoesNotPerformAssertions] public function testSerializeDate(array $params) { $context = $this->getMockBuilder(SerializationContext::class)->getMock(); @@ -57,12 +59,10 @@ public function testSerializeDate(array $params) } /** - * @param string $dateInterval - * @param \DateTime $expected - * * @dataProvider getDeserializeDateInterval */ - public function testDeserializeDateInterval($dateInterval, $expected) + #[DataProvider('getDeserializeDateInterval')] + public function testDeserializeDateInterval(string $dateInterval, array $expected) { $visitor = $this->getMockBuilder(DeserializationVisitorInterface::class)->getMock(); $visitor->method('visitString')->with('2017-06-18'); diff --git a/tests/Handler/IteratorHandlerTest.php b/tests/Handler/IteratorHandlerTest.php index bc2affafd..d49f32b90 100644 --- a/tests/Handler/IteratorHandlerTest.php +++ b/tests/Handler/IteratorHandlerTest.php @@ -11,6 +11,7 @@ use JMS\Serializer\SerializationContext; use JMS\Serializer\Visitor\DeserializationVisitorInterface; use JMS\Serializer\Visitor\SerializationVisitorInterface; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; final class IteratorHandlerTest extends TestCase @@ -40,6 +41,7 @@ public static function iteratorsProvider(): array /** * @dataProvider iteratorsProvider */ + #[DataProvider('iteratorsProvider')] public function testSerialize(\Iterator $iterator): void { $type = get_class($iterator); diff --git a/tests/Handler/SymfonyUidHandlerTest.php b/tests/Handler/SymfonyUidHandlerTest.php index 1a5a2f41a..9c7cf1b59 100644 --- a/tests/Handler/SymfonyUidHandlerTest.php +++ b/tests/Handler/SymfonyUidHandlerTest.php @@ -10,6 +10,7 @@ use JMS\Serializer\Handler\SymfonyUidHandler; use JMS\Serializer\SerializerBuilder; use JMS\Serializer\SerializerInterface; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Uid\AbstractUid; use Symfony\Component\Uid\Ulid; @@ -46,6 +47,7 @@ public static function dataUid(): \Generator /** * @dataProvider dataUid */ + #[DataProvider('dataUid')] public function testSerializeUidToJson(AbstractUid $uid): void { self::assertJsonStringEqualsJsonString( @@ -57,6 +59,7 @@ public function testSerializeUidToJson(AbstractUid $uid): void /** * @dataProvider dataUid */ + #[DataProvider('dataUid')] public function testSerializeUidToXmlWithCData(AbstractUid $uid): void { self::assertXmlStringEqualsXmlString( @@ -68,6 +71,7 @@ public function testSerializeUidToXmlWithCData(AbstractUid $uid): void /** * @dataProvider dataUid */ + #[DataProvider('dataUid')] public function testSerializeUidToXmlWithoutCData(AbstractUid $uid): void { self::assertXmlStringEqualsXmlString( @@ -117,6 +121,7 @@ public function testSerializeUidRejectsInvalidFormat(): void /** * @dataProvider dataUid */ + #[DataProvider('dataUid')] public function testDeserializeUidFromJson(AbstractUid $uid): void { self::assertTrue($uid->equals($this->createSerializer()->deserialize(sprintf('"%s"', (string) $uid), \get_class($uid), 'json'))); @@ -125,6 +130,7 @@ public function testDeserializeUidFromJson(AbstractUid $uid): void /** * @dataProvider dataUid */ + #[DataProvider('dataUid')] public function testDeserializeUidFromXml(AbstractUid $uid): void { self::assertTrue($uid->equals($this->createSerializer()->deserialize(sprintf('%s', (string) $uid), \get_class($uid), 'xml'))); diff --git a/tests/Metadata/ClassMetadataTest.php b/tests/Metadata/ClassMetadataTest.php index 6b523cfeb..eb31e4954 100644 --- a/tests/Metadata/ClassMetadataTest.php +++ b/tests/Metadata/ClassMetadataTest.php @@ -4,8 +4,10 @@ namespace JMS\Serializer\Tests\Metadata; +use JMS\Serializer\Exception\InvalidMetadataException; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\PropertyMetadata; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class ClassMetadataTest extends TestCase @@ -23,14 +25,14 @@ public static function getAccessOrderCases() public function testSerialization() { - $meta = new PropertyMetadata('JMS\Serializer\Tests\Metadata\PropertyMetadataOrder', 'b'); + $meta = new PropertyMetadata(PropertyMetadataOrder::class, 'b'); $restoredMeta = unserialize(serialize($meta)); self::assertEquals($meta, $restoredMeta); } public function testSerializationClass() { - $meta = new ClassMetadata('JMS\Serializer\Tests\Metadata\PropertyMetadataOrder'); + $meta = new ClassMetadata(PropertyMetadataOrder::class); $meta->xmlRootPrefix = 'foo'; $meta->xmlDiscriminatorCData = true; $meta->xmlDiscriminatorAttribute = false; @@ -43,11 +45,12 @@ public function testSerializationClass() /** * @dataProvider getAccessOrderCases */ + #[DataProvider('getAccessOrderCases')] public function testSetAccessorOrderCustom(array $order, array $expected) { - $metadata = new ClassMetadata('JMS\Serializer\Tests\Metadata\PropertyMetadataOrder'); - $metadata->addPropertyMetadata(new PropertyMetadata('JMS\Serializer\Tests\Metadata\PropertyMetadataOrder', 'b')); - $metadata->addPropertyMetadata(new PropertyMetadata('JMS\Serializer\Tests\Metadata\PropertyMetadataOrder', 'a')); + $metadata = new ClassMetadata(PropertyMetadataOrder::class); + $metadata->addPropertyMetadata(new PropertyMetadata(PropertyMetadataOrder::class, 'b')); + $metadata->addPropertyMetadata(new PropertyMetadata(PropertyMetadataOrder::class, 'a')); self::assertEquals(['b', 'a'], array_keys($metadata->propertyMetadata)); $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_CUSTOM, $order); @@ -56,9 +59,9 @@ public function testSetAccessorOrderCustom(array $order, array $expected) public function testSetAccessorOrderAlphabetical() { - $metadata = new ClassMetadata('JMS\Serializer\Tests\Metadata\PropertyMetadataOrder'); - $metadata->addPropertyMetadata(new PropertyMetadata('JMS\Serializer\Tests\Metadata\PropertyMetadataOrder', 'b')); - $metadata->addPropertyMetadata(new PropertyMetadata('JMS\Serializer\Tests\Metadata\PropertyMetadataOrder', 'a')); + $metadata = new ClassMetadata(PropertyMetadataOrder::class); + $metadata->addPropertyMetadata(new PropertyMetadata(PropertyMetadataOrder::class, 'b')); + $metadata->addPropertyMetadata(new PropertyMetadata(PropertyMetadataOrder::class, 'a')); self::assertEquals(['b', 'a'], array_keys($metadata->propertyMetadata)); $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_ALPHABETICAL); @@ -68,6 +71,7 @@ public function testSetAccessorOrderAlphabetical() /** * @dataProvider providerPublicMethodData */ + #[DataProvider('providerPublicMethodData')] public function testAccessorTypePublicMethod($property, $getterInit, $setterInit, $getterName, $setterName) { $object = new PropertyMetadataPublicMethod(); @@ -82,9 +86,10 @@ public function testAccessorTypePublicMethod($property, $getterInit, $setterInit /** * @dataProvider providerPublicMethodException */ + #[DataProvider('providerPublicMethodException')] public function testAccessorTypePublicMethodException($getter, $setter, $message) { - $this->expectException('\JMS\Serializer\Exception\InvalidMetadataException'); + $this->expectException(InvalidMetadataException::class); $this->expectExceptionMessage($message); $object = new PropertyMetadataPublicMethod(); diff --git a/tests/Metadata/Driver/DoctrineDriverTest.php b/tests/Metadata/Driver/DoctrineDriverTest.php index 976f02b91..bfaf44f90 100644 --- a/tests/Metadata/Driver/DoctrineDriverTest.php +++ b/tests/Metadata/Driver/DoctrineDriverTest.php @@ -174,7 +174,7 @@ protected function getDoctrineDriver() $registry = $this->getMockBuilder(ManagerRegistry::class)->getMock(); $registry->expects($this->atLeastOnce()) ->method('getManagerForClass') - ->will($this->returnValue($this->getEntityManager())); + ->willReturn($this->getEntityManager()); return new DoctrineTypeDriver( $this->getMetadataDriver(), diff --git a/tests/Metadata/Driver/DoctrinePHPCRDriverTest.php b/tests/Metadata/Driver/DoctrinePHPCRDriverTest.php index b05ac295d..37c92e7a7 100644 --- a/tests/Metadata/Driver/DoctrinePHPCRDriverTest.php +++ b/tests/Metadata/Driver/DoctrinePHPCRDriverTest.php @@ -12,6 +12,11 @@ use JMS\Serializer\Metadata\Driver\AnnotationDriver; use JMS\Serializer\Metadata\Driver\DoctrinePHPCRTypeDriver; use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; +use JMS\Serializer\Tests\Fixtures\BlogPost; +use JMS\Serializer\Tests\Fixtures\DoctrinePHPCR\Author; +use JMS\Serializer\Tests\Fixtures\DoctrinePHPCR\BlogPost as BlogPostPHPCR; +use JMS\Serializer\Tests\Fixtures\DoctrinePHPCR\Comment; +use PHPCR\SessionInterface; use PHPUnit\Framework\TestCase; class DoctrinePHPCRDriverTest extends TestCase @@ -25,7 +30,7 @@ protected function setUp(): void public function getMetadata() { - $refClass = new \ReflectionClass('JMS\Serializer\Tests\Fixtures\DoctrinePHPCR\BlogPost'); + $refClass = new \ReflectionClass(BlogPostPHPCR::class); return $this->getDoctrinePHPCRDriver()->loadMetadataForClass($refClass); } @@ -43,7 +48,7 @@ public function testSingleValuedAssociationIsProperlyHinted() { $metadata = $this->getMetadata(); self::assertEquals( - ['name' => 'JMS\Serializer\Tests\Fixtures\DoctrinePHPCR\Author', 'params' => []], + ['name' => Author::class, 'params' => []], $metadata->propertyMetadata['author']->type, ); } @@ -56,7 +61,7 @@ public function testMultiValuedAssociationIsProperlyHinted() [ 'name' => 'ArrayCollection', 'params' => [ - ['name' => 'JMS\Serializer\Tests\Fixtures\DoctrinePHPCR\Comment', 'params' => []], + ['name' => Comment::class, 'params' => []], ], ], $metadata->propertyMetadata['comments']->type, @@ -78,7 +83,7 @@ public function testNonDoctrineDocumentClassIsNotModified() { // Note: Using regular BlogPost fixture here instead of Doctrine fixture // because it has no Doctrine metadata. - $refClass = new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost'); + $refClass = new \ReflectionClass(BlogPost::class); $plainMetadata = $this->getAnnotationDriver()->loadMetadataForClass($refClass); $doctrineMetadata = $this->getDoctrinePHPCRDriver()->loadMetadataForClass($refClass); @@ -100,7 +105,7 @@ protected function getDocumentManager() new DoctrinePHPCRDriver(new AnnotationReader(), __DIR__ . '/../../Fixtures/DoctrinePHPCR'), ); - $session = $this->getMockBuilder('PHPCR\SessionInterface')->getMock(); + $session = $this->getMockBuilder(SessionInterface::class)->getMock(); return DocumentManager::create($session, $config); } @@ -115,7 +120,7 @@ protected function getDoctrinePHPCRDriver() $registry = $this->getMockBuilder(ManagerRegistry::class)->getMock(); $registry->expects($this->atLeastOnce()) ->method('getManagerForClass') - ->will($this->returnValue($this->getDocumentManager())); + ->willReturn($this->getDocumentManager()); return new DoctrinePHPCRTypeDriver( $this->getAnnotationDriver(), diff --git a/tests/Ordering/CustomPropertyOrderingStrategyTest.php b/tests/Ordering/CustomPropertyOrderingStrategyTest.php index 73d5be866..b1062bd04 100644 --- a/tests/Ordering/CustomPropertyOrderingStrategyTest.php +++ b/tests/Ordering/CustomPropertyOrderingStrategyTest.php @@ -6,6 +6,7 @@ use JMS\Serializer\Metadata\PropertyMetadata; use JMS\Serializer\Ordering\CustomPropertyOrderingStrategy; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class CustomPropertyOrderingStrategyTest extends TestCase @@ -13,6 +14,7 @@ class CustomPropertyOrderingStrategyTest extends TestCase /** * @dataProvider dataOrder */ + #[DataProvider('dataOrder')] public function testOrder(array $ordering, array $keysToSort, array $expectedResult): void { $strategy = new CustomPropertyOrderingStrategy(array_flip($ordering)); diff --git a/tests/Serializer/ArrayTest.php b/tests/Serializer/ArrayTest.php index d548ac96f..a59c03a51 100644 --- a/tests/Serializer/ArrayTest.php +++ b/tests/Serializer/ArrayTest.php @@ -4,12 +4,14 @@ namespace JMS\Serializer\Tests\Serializer; +use JMS\Serializer\Exception\RuntimeException; use JMS\Serializer\SerializerBuilder; use JMS\Serializer\Tests\Fixtures\Author; use JMS\Serializer\Tests\Fixtures\AuthorList; use JMS\Serializer\Tests\Fixtures\Order; use JMS\Serializer\Tests\Fixtures\Price; use JMS\Serializer\Tests\Fixtures\TypedProperties\ConstructorPromotion\DefaultValuesAndAccessors; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class ArrayTest extends TestCase @@ -38,9 +40,10 @@ public function testToArray() /** * @dataProvider scalarValues */ + #[DataProvider('scalarValues')] public function testToArrayWithScalar($input) { - $this->expectException('JMS\Serializer\Exception\RuntimeException'); + $this->expectException(RuntimeException::class); $this->expectExceptionMessage(sprintf( 'The input data of type "%s" did not convert to an array, but got a result of type "%s".', gettype($input), @@ -68,7 +71,7 @@ public function testFromArray() ]; $expected = new Order(new Price(2.5)); - $result = $this->serializer->fromArray($data, 'JMS\Serializer\Tests\Fixtures\Order'); + $result = $this->serializer->fromArray($data, Order::class); self::assertEquals($expected, $result); } diff --git a/tests/Serializer/BaseSerializationTestCase.php b/tests/Serializer/BaseSerializationTestCase.php index 7400151ff..d9acd9574 100644 --- a/tests/Serializer/BaseSerializationTestCase.php +++ b/tests/Serializer/BaseSerializationTestCase.php @@ -5,6 +5,7 @@ namespace JMS\Serializer\Tests\Serializer; use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\ORM\Version; use JMS\Serializer\Construction\UnserializeObjectConstructor; use JMS\Serializer\Context; use JMS\Serializer\DeserializationContext; @@ -62,6 +63,7 @@ use JMS\Serializer\Tests\Fixtures\Discriminator\Post; use JMS\Serializer\Tests\Fixtures\Discriminator\Serialization\ExtendedUser; use JMS\Serializer\Tests\Fixtures\Discriminator\Serialization\User; +use JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle; use JMS\Serializer\Tests\Fixtures\DiscriminatorGroup\Car as DiscriminatorGroupCar; use JMS\Serializer\Tests\Fixtures\DocBlockType\UnionTypedDocBLockProperty; use JMS\Serializer\Tests\Fixtures\ExclusionStrategy\AlwaysExcludeExclusionStrategy; @@ -127,9 +129,14 @@ use JMS\Serializer\Tests\Fixtures\VehicleInterfaceGarage; use JMS\Serializer\Visitor\DeserializationVisitorInterface; use JMS\Serializer\Visitor\SerializationVisitorInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\ExpressionLanguage\ExpressionFunction; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; +use Symfony\Component\Form\DataMapperInterface; use Symfony\Component\Form\Extension\Core\Type\ButtonType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Form; @@ -269,6 +276,7 @@ public function testDeserializeNullObject() /** * @dataProvider getTypes */ + #[DataProvider('getTypes')] public function testNull($type) { if ($this->hasDeserializer()) { @@ -286,6 +294,7 @@ public function testNull($type) /** * @dataProvider getTypes */ + #[DataProvider('getTypes')] public function testNullAllowed($type) { $context = SerializationContext::create()->setSerializeNull(true); @@ -551,6 +560,7 @@ public static function expressionFunctionProvider() * * @dataProvider expressionFunctionProvider */ + #[DataProvider('expressionFunctionProvider')] public function testExpressionExclusion($person, ExpressionFunction $function, $json) { $language = new ExpressionLanguage(); @@ -566,6 +576,7 @@ public function testExpressionExclusion($person, ExpressionFunction $function, $ /** * @dataProvider getBooleans */ + #[DataProvider('getBooleans')] public function testBooleans($strBoolean, $boolean) { self::assertEquals(static::getContent('boolean_' . $strBoolean), $this->serialize($boolean)); @@ -583,6 +594,7 @@ public static function getBooleans() /** * @dataProvider getNumerics */ + #[DataProvider('getNumerics')] public function testNumerics($key, $value, $type) { self::assertSame(static::getContent($key), $this->serialize($value)); @@ -816,9 +828,6 @@ public function testNamedDateTimeArrays() } } - /** - * @group datetime - */ public function testNamedDateTimeImmutableArrays() { $data = [ @@ -857,6 +866,7 @@ public function testArrayMixed() * @dataProvider getDateTime * @group datetime */ + #[DataProvider('getDateTime')] public function testDateTime($key, $value, $type) { self::assertEquals(static::getContent($key), $this->serialize($value)); @@ -882,6 +892,7 @@ public static function getDateTime() * @dataProvider getDateTimeImmutable * @group datetime */ + #[DataProvider('getDateTimeImmutable')] public function testDateTimeImmutable($key, $value, $type) { self::assertEquals(static::getContent($key), $this->serialize($value)); @@ -1245,13 +1256,14 @@ public function testFormErrors() /** * @dataProvider initialFormTypeProvider */ + #[DataProvider('initialFormTypeProvider')] public function testNestedFormErrors($type) { - $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); + $dispatcher = $this->getMockBuilder(EventDispatcherInterface::class)->getMock(); $formConfigBuilder = new FormConfigBuilder('foo', null, $dispatcher); $formConfigBuilder->setCompound(true); - $formConfigBuilder->setDataMapper($this->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock()); + $formConfigBuilder->setDataMapper($this->getMockBuilder(DataMapperInterface::class)->getMock()); $fooConfig = $formConfigBuilder->getFormConfig(); $form = new Form($fooConfig); @@ -1273,9 +1285,11 @@ public function testNestedFormErrors($type) * @doesNotPerformAssertions * @dataProvider initialFormTypeProvider */ + #[DataProvider('initialFormTypeProvider')] + #[DoesNotPerformAssertions] public function testFormErrorsWithNonFormComponents($type) { - $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); + $dispatcher = $this->getMockBuilder(EventDispatcherInterface::class)->getMock(); $factoryBuilder = new FormFactoryBuilder(); $factoryBuilder->addType(new SubmitType()); @@ -1285,7 +1299,7 @@ public function testFormErrorsWithNonFormComponents($type) $formConfigBuilder = new FormConfigBuilder('foo', null, $dispatcher); $formConfigBuilder->setFormFactory($factory); $formConfigBuilder->setCompound(true); - $formConfigBuilder->setDataMapper($this->getMockBuilder('Symfony\Component\Form\DataMapperInterface')->getMock()); + $formConfigBuilder->setDataMapper($this->getMockBuilder(DataMapperInterface::class)->getMock()); $fooConfig = $formConfigBuilder->getFormConfig(); $form = new Form($fooConfig); @@ -1327,7 +1341,7 @@ public function testConstraintViolationList() public function testDoctrineProxy() { - if (!class_exists('Doctrine\ORM\Version')) { + if (!class_exists(Version::class)) { $this->markTestSkipped('Doctrine is not available.'); } @@ -1338,7 +1352,7 @@ public function testDoctrineProxy() public function testInitializedDoctrineProxy() { - if (!class_exists('Doctrine\ORM\Version')) { + if (!class_exists(Version::class)) { $this->markTestSkipped('Doctrine is not available.'); } @@ -1362,7 +1376,7 @@ public function testMixedAccessTypes() self::assertEquals(static::getContent('mixed_access_types'), $this->serialize($object)); if ($this->hasDeserializer()) { - $object = $this->deserialize(static::getContent('mixed_access_types'), 'JMS\Serializer\Tests\Fixtures\GetSetObject'); + $object = $this->deserialize(static::getContent('mixed_access_types'), GetSetObject::class); self::assertSame(1, $this->getField($object, 'id')); self::assertSame('Johannes', $this->getField($object, 'name')); self::assertSame(42, $this->getField($object, 'readOnlyProperty')); @@ -1592,6 +1606,7 @@ public function testUninitializedTypedProperties() /** * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testCustomHandlerVisitingNull() { $handler = static function ($visitor, $attachment, array $type, Context $context) { @@ -1615,9 +1630,6 @@ public function testObjectWithEmptyHash() self::assertEquals(static::getContent('hash_empty'), $this->serializer->serialize(new ObjectWithEmptyHash(), $this->getFormat())); } - /** - * @group null - */ public function testSerializeObjectWhenNull() { self::assertEquals( @@ -1631,9 +1643,6 @@ public function testSerializeObjectWhenNull() ); } - /** - * @group polymorphic - */ public function testPolymorphicObjectsWithGroup() { $context = SerializationContext::create(); @@ -1663,6 +1672,7 @@ public static function getDiscrimatorObjectsSamples(): array * * @dataProvider getDiscrimatorObjectsSamples */ + #[DataProvider('getDiscrimatorObjectsSamples')] public function testDiscrimatorObjects($data, $contentId) { $context = SerializationContext::create()->setGroups(['entity.identification']); @@ -1672,9 +1682,6 @@ public function testDiscrimatorObjects($data, $contentId) ); } - /** - * @group polymorphic - */ public function testPolymorphicObjects() { self::assertEquals( @@ -1695,7 +1702,7 @@ public function testPolymorphicObjects() new Car(5), $this->deserialize( static::getContent('car'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\Car', + Car::class, ), 'Class is resolved correctly when concrete sub-class is used.', ); @@ -1704,7 +1711,7 @@ public function testPolymorphicObjects() new Car(5), $this->deserialize( static::getContent('car'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle', + Vehicle::class, ), 'Class is resolved correctly when least supertype is used.', ); @@ -1713,7 +1720,7 @@ public function testPolymorphicObjects() new Car(5), $this->deserialize( static::getContent('car_without_type'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\Car', + Car::class, ), 'Class is resolved correctly when concrete sub-class is used and no type is defined.', ); @@ -1722,7 +1729,7 @@ public function testPolymorphicObjects() new Post('Post Title'), $this->deserialize( static::getContent('post'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\Post', + Post::class, ), 'Class is resolved correctly when parent class is used and type is set.', ); @@ -1731,7 +1738,7 @@ public function testPolymorphicObjects() new ImagePost('Image Post Title'), $this->deserialize( static::getContent('image_post'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\Post', + Post::class, ), 'Class is resolved correctly when least supertype is used.', ); @@ -1740,16 +1747,13 @@ public function testPolymorphicObjects() new ImagePost('Image Post Title'), $this->deserialize( static::getContent('image_post'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\ImagePost', + ImagePost::class, ), 'Class is resolved correctly when concrete sub-class is used and no type is defined.', ); } } - /** - * @group polymorphic - */ public function testNestedPolymorphicObjects() { $garage = new Garage([new Car(3), new Moped(1)]); @@ -1763,15 +1767,12 @@ public function testNestedPolymorphicObjects() $garage, $this->deserialize( static::getContent('garage'), - 'JMS\Serializer\Tests\Fixtures\Garage', + Garage::class, ), ); } } - /** - * @group polymorphic - */ public function testNestedPolymorphicInterfaces() { $garage = new VehicleInterfaceGarage([new Car(3), new Moped(1)]); @@ -1785,15 +1786,12 @@ public function testNestedPolymorphicInterfaces() $garage, $this->deserialize( static::getContent('garage'), - 'JMS\Serializer\Tests\Fixtures\VehicleInterfaceGarage', + VehicleInterfaceGarage::class, ), ); } } - /** - * @group polymorphic - */ public function testPolymorphicObjectsInvalidDeserialization() { $this->expectException(\LogicException::class); @@ -1804,7 +1802,7 @@ public function testPolymorphicObjectsInvalidDeserialization() $this->deserialize( static::getContent('car_without_type'), - 'JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle', + Vehicle::class, ); } @@ -1896,6 +1894,7 @@ public function testObjectWithNullableArrays() /** * @dataProvider getSerializeNullCases */ + #[DataProvider('getSerializeNullCases')] public function testSerializeNullArrayObjectWithExclusionStrategy(bool $serializeNull) { $arr = [ @@ -1948,6 +1947,7 @@ public static function getFirstClassListCollectionsValues() * * @dataProvider getFirstClassListCollectionsValues */ + #[DataProvider('getFirstClassListCollectionsValues')] public function testFirstClassListCollections($items, $expected, ?FirstClassListCollection $expectedDeserializatrion = null) { $collection = new FirstClassListCollection($items); @@ -2143,7 +2143,7 @@ static function (DeserializationVisitorInterface $visitor, $data, $type, Context 'name' => 'array', 'params' => [ ['name' => 'integer', 'params' => []], - ['name' => 'JMS\Serializer\Tests\Fixtures\Author', 'params' => []], + ['name' => Author::class, 'params' => []], ], ]; diff --git a/tests/Serializer/ContextTest.php b/tests/Serializer/ContextTest.php index b70227985..c5fe9078f 100644 --- a/tests/Serializer/ContextTest.php +++ b/tests/Serializer/ContextTest.php @@ -5,6 +5,7 @@ namespace JMS\Serializer\Tests\Serializer; use JMS\Serializer\Exception\LogicException; +use JMS\Serializer\Exclusion\ExclusionStrategyInterface; use JMS\Serializer\GraphNavigator; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\PropertyMetadata; @@ -18,6 +19,7 @@ use JMS\Serializer\Tests\Fixtures\VersionedObject; use JMS\Serializer\VisitorInterface; use Metadata\MetadataFactoryInterface; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class ContextTest extends TestCase @@ -32,7 +34,7 @@ public function testSerializationContextPathAndDepth() $self = $this; - $exclusionStrategy = $this->getMockBuilder('JMS\Serializer\Exclusion\ExclusionStrategyInterface')->getMock(); + $exclusionStrategy = $this->getMockBuilder(ExclusionStrategyInterface::class)->getMock(); $exclusionStrategy->expects($this->any()) ->method('shouldSkipClass') ->with($this->anything(), $this->callback(static function (SerializationContext $context) use ($self, $objects) { @@ -40,7 +42,7 @@ public function testSerializationContextPathAndDepth() if ($context->getObject() === $objects[0]) { $expectedDepth = 1; - $expectedPath = 'JMS\Serializer\Tests\Fixtures\Node'; + $expectedPath = Node::class; } elseif ($context->getObject() === $objects[1]) { $expectedDepth = 2; $expectedPath = 'JMS\Serializer\Tests\Fixtures\Node -> JMS\Serializer\Tests\Fixtures\Node'; @@ -57,7 +59,7 @@ public function testSerializationContextPathAndDepth() return true; })) - ->will($this->returnValue(false)); + ->willReturn(false); $exclusionStrategy->expects($this->any()) ->method('shouldSkipProperty') @@ -66,7 +68,7 @@ public function testSerializationContextPathAndDepth() if ($context->getObject() === $objects[0]) { $expectedDepth = 1; - $expectedPath = 'JMS\Serializer\Tests\Fixtures\Node'; + $expectedPath = Node::class; } elseif ($context->getObject() === $objects[1]) { $expectedDepth = 2; $expectedPath = 'JMS\Serializer\Tests\Fixtures\Node -> JMS\Serializer\Tests\Fixtures\Node'; @@ -83,7 +85,7 @@ public function testSerializationContextPathAndDepth() return true; })) - ->will($this->returnValue(false)); + ->willReturn(false); $serializer = SerializerBuilder::create()->build(); @@ -97,10 +99,10 @@ public function testSerializationMetadataStack() ]); $self = $this; - $exclusionStrategy = $this->getMockBuilder('JMS\Serializer\Exclusion\ExclusionStrategyInterface')->getMock(); - $exclusionStrategy->expects($this->any()) + $exclusionStrategy = $this->getMockBuilder(ExclusionStrategyInterface::class)->getMock(); + $exclusionStrategy ->method('shouldSkipClass') - ->will($this->returnCallback(static function (ClassMetadata $classMetadata, SerializationContext $context) use ($self, $object, $child) { + ->willReturnCallback(static function (ClassMetadata $classMetadata, SerializationContext $context) use ($self, $object, $child) { $stack = $context->getMetadataStack(); if ($object === $context->getObject()) { @@ -109,32 +111,32 @@ public function testSerializationMetadataStack() if ($child === $context->getObject()) { $self->assertEquals(2, $stack->count()); - $self->assertEquals('JMS\Serializer\Tests\Fixtures\Node', $stack[1]->name); + $self->assertEquals(Node::class, $stack[1]->name); $self->assertEquals('children', $stack[0]->name); } return false; - })); + }); - $exclusionStrategy->expects($this->any()) + $exclusionStrategy ->method('shouldSkipProperty') - ->will($this->returnCallback(static function (PropertyMetadata $propertyMetadata, SerializationContext $context) use ($self) { + ->willReturnCallback(static function (PropertyMetadata $propertyMetadata, SerializationContext $context) use ($self) { $stack = $context->getMetadataStack(); if ('JMS\Serializer\Tests\Fixtures\Node' === $propertyMetadata->class && 'children' === $propertyMetadata->name) { $self->assertEquals(1, $stack->count()); - $self->assertEquals('JMS\Serializer\Tests\Fixtures\Node', $stack[0]->name); + $self->assertEquals(Node::class, $stack[0]->name); } if ('JMS\Serializer\Tests\Fixtures\InlineChild' === $propertyMetadata->class) { $self->assertEquals(3, $stack->count()); - $self->assertEquals('JMS\Serializer\Tests\Fixtures\Node', $stack[2]->name); + $self->assertEquals(Node::class, $stack[2]->name); $self->assertEquals('children', $stack[1]->name); - $self->assertEquals('JMS\Serializer\Tests\Fixtures\InlineChild', $stack[0]->name); + $self->assertEquals(InlineChild::class, $stack[0]->name); } return false; - })); + }); $serializer = SerializerBuilder::create()->build(); $serializer->serialize($object, 'json', SerializationContext::create()->addExclusionStrategy($exclusionStrategy)); @@ -153,6 +155,7 @@ public static function getScalars() /** * @dataProvider getScalars */ + #[DataProvider('getScalars')] public function testCanVisitScalars($scalar) { $context = SerializationContext::create(); diff --git a/tests/Serializer/Doctrine/ObjectConstructorTest.php b/tests/Serializer/Doctrine/ObjectConstructorTest.php index 6faf53ead..fad75ccaf 100644 --- a/tests/Serializer/Doctrine/ObjectConstructorTest.php +++ b/tests/Serializer/Doctrine/ObjectConstructorTest.php @@ -54,6 +54,7 @@ use LogicException; use Metadata\Driver\AdvancedDriverInterface; use Metadata\MetadataFactoryInterface; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use ReflectionClass; use RuntimeException; @@ -305,7 +306,8 @@ public static function dataProviderPersistendCollectionIsNotReplaced(): array /** * @dataProvider dataProviderPersistendCollectionIsNotReplaced */ - public function testPersistendCollectionIsNotReplaced(string $data, string $type): void + #[DataProvider('dataProviderPersistendCollectionIsNotReplaced')] + public function testPersistendCollectionIsNotReplaced(string $serializedData, string $type): void { $serializer = $this->createSerializerWithDoctrineObjectConstructor(); @@ -322,7 +324,7 @@ public function testPersistendCollectionIsNotReplaced(string $data, string $type $em->flush(); $em->clear(); - $smartPhoneDeserialized = $serializer->deserialize($data, SmartPhone::class, $type); + $smartPhoneDeserialized = $serializer->deserialize($serializedData, SmartPhone::class, $type); self::assertInstanceOf(SmartPhone::class, $smartPhoneDeserialized); self::assertSame( diff --git a/tests/Serializer/GraphNavigatorTest.php b/tests/Serializer/GraphNavigatorTest.php index 8425be6d5..7b8de3708 100644 --- a/tests/Serializer/GraphNavigatorTest.php +++ b/tests/Serializer/GraphNavigatorTest.php @@ -29,6 +29,7 @@ use JMS\Serializer\VisitorInterface; use Metadata\Driver\DriverChain; use Metadata\MetadataFactory; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\TestCase; class GraphNavigatorTest extends TestCase @@ -60,29 +61,29 @@ public function testNavigatorPassesInstanceOnSerialization() $metadata = $this->metadataFactory->getMetadataForClass(get_class($object)); $self = $this; - $this->context = $this->getMockBuilder(SerializationContext::class)->getMock(); + $this->context = $this->createMock(SerializationContext::class); $context = $this->context; - $exclusionStrategy = $this->getMockBuilder('JMS\Serializer\Exclusion\ExclusionStrategyInterface')->getMock(); + $exclusionStrategy = $this->createMock(ExclusionStrategyInterface::class); $exclusionStrategy->expects($this->once()) ->method('shouldSkipClass') - ->will($this->returnCallback(static function ($passedMetadata, $passedContext) use ($metadata, $context, $self) { + ->willReturnCallback(static function ($passedMetadata, $passedContext) use ($metadata, $context, $self) { $self->assertSame($metadata, $passedMetadata); $self->assertSame($context, $passedContext); return false; - })); + }); $exclusionStrategy->expects($this->once()) ->method('shouldSkipProperty') - ->will($this->returnCallback(static function ($propertyMetadata, $passedContext) use ($context, $metadata, $self) { + ->willReturnCallback(static function ($propertyMetadata, $passedContext) use ($context, $metadata, $self) { $self->assertSame($metadata->propertyMetadata['foo'], $propertyMetadata); $self->assertSame($context, $passedContext); return false; - })); + }); $this->context->expects($this->once()) ->method('getExclusionStrategy') - ->will($this->returnValue($exclusionStrategy)); + ->willReturn($exclusionStrategy); $navigator = new SerializationGraphNavigator($this->metadataFactory, $this->handlerRegistry, $this->accessor, $this->dispatcher); $navigator->initialize($this->serializationVisitor, $this->context); @@ -112,7 +113,7 @@ public function testNavigatorPassesNullOnDeserialization() $this->context->expects($this->once()) ->method('getExclusionStrategy') - ->will($this->returnValue($exclusionStrategy)); + ->willReturn($exclusionStrategy); $navigator = new DeserializationGraphNavigator($this->metadataFactory, $this->handlerRegistry, $this->objectConstructor, $this->accessor, $this->dispatcher); $navigator->initialize($this->deserializationVisitor, $this->context); @@ -122,6 +123,7 @@ public function testNavigatorPassesNullOnDeserialization() /** * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testNavigatorChangeTypeOnSerialization() { $object = new SerializableClass(); @@ -184,6 +186,7 @@ public function testHandlerIsExecutedOnSerialization() /** * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testFilterableHandlerIsSkippedOnSerialization() { $object = new SerializableClass(); @@ -217,6 +220,7 @@ public function testFilterableHandlerIsNotSkippedOnSerialization() /** * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testNavigatorDoesNotCrashWhenObjectConstructorReturnsNull() { $objectConstructor = $this->getMockBuilder(ObjectConstructorInterface::class)->getMock(); diff --git a/tests/Serializer/JsonSerializationTest.php b/tests/Serializer/JsonSerializationTest.php index 4c7bb0302..4a2fcd1d9 100644 --- a/tests/Serializer/JsonSerializationTest.php +++ b/tests/Serializer/JsonSerializationTest.php @@ -16,9 +16,11 @@ use JMS\Serializer\Tests\Fixtures\FirstClassMapCollection; use JMS\Serializer\Tests\Fixtures\ObjectWithEmptyArrayAndHash; use JMS\Serializer\Tests\Fixtures\ObjectWithInlineArray; +use JMS\Serializer\Tests\Fixtures\ObjectWithObjectProperty; use JMS\Serializer\Tests\Fixtures\Tag; use JMS\Serializer\Visitor\Factory\JsonSerializationVisitorFactory; use JMS\Serializer\Visitor\SerializationVisitorInterface; +use PHPUnit\Framework\Attributes\DataProvider; class JsonSerializationTest extends BaseSerializationTestCase { @@ -170,12 +172,10 @@ public static function getFirstClassMapCollectionsValues() } /** - * @param array $items - * @param array $expected - * * @dataProvider getFirstClassMapCollectionsValues */ - public function testFirstClassMapCollections($items, $expected): void + #[DataProvider('getFirstClassMapCollectionsValues')] + public function testFirstClassMapCollections(array $items, string $expected): void { $collection = new FirstClassMapCollection($items); @@ -190,17 +190,17 @@ public function testAddLinksToOutput() { $this->dispatcher->addListener('serializer.post_serialize', static function (Event $event) { self::assertFalse($event->getVisitor()->hasData('_links')); - }, 'JMS\Serializer\Tests\Fixtures\Author', 'json'); + }, Author::class, 'json'); $this->dispatcher->addSubscriber(new LinkAddingSubscriber()); $this->dispatcher->addListener('serializer.post_serialize', static function (Event $event) { self::assertTrue($event->getVisitor()->hasData('_links')); - }, 'JMS\Serializer\Tests\Fixtures\Author', 'json'); + }, Author::class, 'json'); $this->handlerRegistry->registerHandler( GraphNavigatorInterface::DIRECTION_SERIALIZATION, - 'JMS\Serializer\Tests\Fixtures\AuthorList', + AuthorList::class, 'json', static function (SerializationVisitorInterface $visitor, AuthorList $data, array $type, Context $context) { return $visitor->visitArray(iterator_to_array($data), $type); @@ -219,7 +219,7 @@ public function testReplaceNameInOutput() $this->dispatcher->addSubscriber(new ReplaceNameSubscriber()); $this->handlerRegistry->registerHandler( GraphNavigatorInterface::DIRECTION_SERIALIZATION, - 'JMS\Serializer\Tests\Fixtures\AuthorList', + AuthorList::class, 'json', static function (SerializationVisitorInterface $visitor, AuthorList $data, array $type, Context $context) { return $visitor->visitArray(iterator_to_array($data), $type); @@ -240,15 +240,15 @@ public function testDeserializingObjectWithObjectPropertyWithNoArrayToObject() $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('Invalid data "baz" (string), expected "JMS\Serializer\Tests\Fixtures\Author".'); - $this->deserialize($content, 'JMS\Serializer\Tests\Fixtures\ObjectWithObjectProperty'); + $this->deserialize($content, ObjectWithObjectProperty::class); } public function testDeserializingObjectWithObjectProperty() { $content = self::getContent('object_with_object_property'); - $object = $this->deserialize($content, 'JMS\Serializer\Tests\Fixtures\ObjectWithObjectProperty'); + $object = $this->deserialize($content, ObjectWithObjectProperty::class); self::assertEquals('bar', $object->getFoo()); - self::assertInstanceOf('JMS\Serializer\Tests\Fixtures\Author', $object->getAuthor()); + self::assertInstanceOf(Author::class, $object->getAuthor()); self::assertEquals('baz', $object->getAuthor()->getName()); } @@ -277,29 +277,24 @@ public static function getPrimitiveTypes() /** * @dataProvider getPrimitiveTypes */ - public function testPrimitiveTypes($primitiveType, $data) + #[DataProvider('getPrimitiveTypes')] + public function testPrimitiveTypes(string $type, $data) { $navigator = $this->getMockBuilder(GraphNavigatorInterface::class)->getMock(); $factory = new JsonSerializationVisitorFactory(); $visitor = $factory->getVisitor(); $visitor->setNavigator($navigator); - $functionToCall = 'visit' . ucfirst($primitiveType); + $functionToCall = 'visit' . ucfirst($type); $result = $visitor->$functionToCall($data, [], $this->getMockBuilder(SerializationContext::class)->getMock()); - self::{'assertIs' . (['boolean' => 'bool', 'integer' => 'int', 'double' => 'float'][$primitiveType] ?? $primitiveType)}($result); + self::{'assertIs' . (['boolean' => 'bool', 'integer' => 'int', 'double' => 'float'][$type] ?? $type)}($result); } - /** - * @group empty-object - */ public function testSerializeEmptyObject() { self::assertEquals('{}', $this->serialize(new Author(null))); } - /** - * @group encoding - */ public function testSerializeWithNonUtf8EncodingWhenDisplayErrorsOff() { ini_set('display_errors', '1'); @@ -310,9 +305,6 @@ public function testSerializeWithNonUtf8EncodingWhenDisplayErrorsOff() $this->serialize(['foo' => 'bar', 'bar' => pack('H*', 'c32e')]); } - /** - * @group encoding - */ public function testSerializeWithNonUtf8EncodingWhenDisplayErrorsOn() { ini_set('display_errors', '0'); @@ -394,13 +386,10 @@ public static function getTypeHintedArrays() } /** - * @param array $array - * @param string $expected - * @param SerializationContext|null $context - * * @dataProvider getTypeHintedArrays */ - public function testTypeHintedArraySerialization(array $array, $expected, $context = null) + #[DataProvider('getTypeHintedArrays')] + public function testTypeHintedArraySerialization(array $array, string $expected, ?SerializationContext $context = null) { self::assertEquals($expected, $this->serialize($array, $context)); } @@ -435,13 +424,10 @@ public static function getTypeHintedArraysAndStdClass() } /** - * @param array $array - * @param string $expected - * @param SerializationContext|null $context - * * @dataProvider getTypeHintedArraysAndStdClass */ - public function testTypeHintedArrayAncdtdClassSerialization(array $array, $expected, $context = null) + #[DataProvider('getTypeHintedArraysAndStdClass')] + public function testTypeHintedArrayAncdtdClassSerialization(array $array, string $expected, ?SerializationContext $context = null) { self::assertEquals($expected, $this->serialize($array, $context)); } @@ -467,7 +453,7 @@ public function onPostSerialize(ObjectEvent $event) public static function getSubscribedEvents() { return [ - ['event' => 'serializer.post_serialize', 'method' => 'onPostSerialize', 'format' => 'json', 'class' => 'JMS\Serializer\Tests\Fixtures\Author'], + ['event' => 'serializer.post_serialize', 'method' => 'onPostSerialize', 'format' => 'json', 'class' => Author::class], ]; } } @@ -482,7 +468,7 @@ public function onPostSerialize(Event $event) public static function getSubscribedEvents() { return [ - ['event' => 'serializer.post_serialize', 'method' => 'onPostSerialize', 'format' => 'json', 'class' => 'JMS\Serializer\Tests\Fixtures\Author'], + ['event' => 'serializer.post_serialize', 'method' => 'onPostSerialize', 'format' => 'json', 'class' => Author::class], ]; } } diff --git a/tests/Serializer/JsonStrictSerializationTest.php b/tests/Serializer/JsonStrictSerializationTest.php index 8bc0562bf..c0227fd28 100644 --- a/tests/Serializer/JsonStrictSerializationTest.php +++ b/tests/Serializer/JsonStrictSerializationTest.php @@ -6,6 +6,7 @@ use JMS\Serializer\SerializerBuilder; use JMS\Serializer\Visitor\Factory\JsonDeserializationVisitorFactory; +use PHPUnit\Framework\Attributes\DataProvider; class JsonStrictSerializationTest extends JsonSerializationTest { @@ -17,12 +18,10 @@ protected function extendBuilder(SerializerBuilder $builder): void } /** - * @param array $items - * @param array $expected - * * @dataProvider getFirstClassMapCollectionsValues */ - public function testFirstClassMapCollections($items, $expected): void + #[DataProvider('getFirstClassMapCollectionsValues')] + public function testFirstClassMapCollections(array $items, string $expected): void { self::markTestIncomplete('Fixtures are broken'); } diff --git a/tests/Serializer/Naming/CamelCaseNamingStrategyTest.php b/tests/Serializer/Naming/CamelCaseNamingStrategyTest.php index 1f73c8c9c..d2f58b7af 100644 --- a/tests/Serializer/Naming/CamelCaseNamingStrategyTest.php +++ b/tests/Serializer/Naming/CamelCaseNamingStrategyTest.php @@ -5,6 +5,7 @@ namespace JMS\Serializer\Tests\Serializer\Naming; use JMS\Serializer\Naming\CamelCaseNamingStrategy; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class CamelCaseNamingStrategyTest extends TestCase @@ -20,6 +21,7 @@ public static function providePropertyNames() /** * @dataProvider providePropertyNames */ + #[DataProvider('providePropertyNames')] public function testCamelCaseNamingHandlesMultipleUppercaseLetters($propertyName, $expected) { $mockProperty = $this->getMockBuilder('JMS\Serializer\Metadata\PropertyMetadata')->disableOriginalConstructor()->getMock(); diff --git a/tests/Serializer/Naming/IdenticalPropertyNamingStrategyTest.php b/tests/Serializer/Naming/IdenticalPropertyNamingStrategyTest.php index be1f68d84..e5b39e08e 100644 --- a/tests/Serializer/Naming/IdenticalPropertyNamingStrategyTest.php +++ b/tests/Serializer/Naming/IdenticalPropertyNamingStrategyTest.php @@ -5,6 +5,7 @@ namespace JMS\Serializer\Tests\Serializer\Naming; use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class IdenticalPropertyNamingStrategyTest extends TestCase @@ -21,6 +22,7 @@ public static function providePropertyNames() /** * @dataProvider providePropertyNames */ + #[DataProvider('providePropertyNames')] public function testTranslateName($propertyName) { $mockProperty = $this->getMockBuilder('JMS\Serializer\Metadata\PropertyMetadata')->disableOriginalConstructor()->getMock(); diff --git a/tests/Serializer/SerializationContextFactoryTest.php b/tests/Serializer/SerializationContextFactoryTest.php index bb2d079b3..6f12b95c3 100644 --- a/tests/Serializer/SerializationContextFactoryTest.php +++ b/tests/Serializer/SerializationContextFactoryTest.php @@ -6,6 +6,8 @@ use Doctrine\Common\Annotations\AnnotationReader; use JMS\Serializer\Construction\UnserializeObjectConstructor; +use JMS\Serializer\ContextFactory\DeserializationContextFactoryInterface; +use JMS\Serializer\ContextFactory\SerializationContextFactoryInterface; use JMS\Serializer\DeserializationContext; use JMS\Serializer\Handler\HandlerRegistry; use JMS\Serializer\Metadata\Driver\AnnotationDriver; @@ -42,14 +44,14 @@ protected function setUp(): void public function testSerializeUseProvidedSerializationContext() { - $contextFactoryMock = $this->getMockForAbstractClass('JMS\\Serializer\\ContextFactory\\SerializationContextFactoryInterface'); + $contextFactoryMock = $this->createMock(SerializationContextFactoryInterface::class); $context = new SerializationContext(); $context->setSerializeNull(true); $contextFactoryMock ->expects($this->once()) ->method('createSerializationContext') - ->will($this->returnValue($context)); + ->willReturn($context); $builder = SerializerBuilder::create(); $builder->setSerializationContextFactory($contextFactoryMock); @@ -62,13 +64,13 @@ public function testSerializeUseProvidedSerializationContext() public function testDeserializeUseProvidedDeserializationContext() { - $contextFactoryMock = $this->getMockForAbstractClass('JMS\\Serializer\\ContextFactory\\DeserializationContextFactoryInterface'); + $contextFactoryMock = $this->createMock(DeserializationContextFactoryInterface::class); $context = new DeserializationContext(); $contextFactoryMock ->expects($this->once()) ->method('createDeserializationContext') - ->will($this->returnValue($context)); + ->willReturn($context); $builder = SerializerBuilder::create(); $builder->setDeserializationContextFactory($contextFactoryMock); @@ -81,14 +83,14 @@ public function testDeserializeUseProvidedDeserializationContext() public function testToArrayUseProvidedSerializationContext() { - $contextFactoryMock = $this->getMockForAbstractClass('JMS\\Serializer\\ContextFactory\\SerializationContextFactoryInterface'); + $contextFactoryMock = $this->createMock(SerializationContextFactoryInterface::class); $context = new SerializationContext(); $context->setSerializeNull(true); $contextFactoryMock ->expects($this->once()) ->method('createSerializationContext') - ->will($this->returnValue($context)); + ->willReturn($context); $builder = SerializerBuilder::create(); $builder->setSerializationContextFactory($contextFactoryMock); @@ -101,13 +103,13 @@ public function testToArrayUseProvidedSerializationContext() public function testFromArrayUseProvidedDeserializationContext() { - $contextFactoryMock = $this->getMockForAbstractClass('JMS\\Serializer\\ContextFactory\\DeserializationContextFactoryInterface'); + $contextFactoryMock = $this->createMock(DeserializationContextFactoryInterface::class); $context = new DeserializationContext(); $contextFactoryMock ->expects($this->once()) ->method('createDeserializationContext') - ->will($this->returnValue($context)); + ->willReturn($context); $builder = SerializerBuilder::create(); $builder->setDeserializationContextFactory($contextFactoryMock); diff --git a/tests/Serializer/Type/ParserTest.php b/tests/Serializer/Type/ParserTest.php index eecdab5ab..65c7d74d9 100644 --- a/tests/Serializer/Type/ParserTest.php +++ b/tests/Serializer/Type/ParserTest.php @@ -7,6 +7,7 @@ use JMS\Serializer\Type\Exception\SyntaxError; use JMS\Serializer\Type\Parser; use JMS\Serializer\Type\ParserInterface; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class ParserTest extends TestCase @@ -22,6 +23,7 @@ protected function setUp(): void /** * @dataProvider validTypesProvider */ + #[DataProvider('validTypesProvider')] public function testParse(string $sourceType, array $expectedType): void { self::assertSame( @@ -149,6 +151,7 @@ public static function validTypesProvider(): iterable /** * @dataProvider wrongSyntax */ + #[DataProvider('wrongSyntax')] public function testSyntaxError($value): void { $this->expectException(SyntaxError::class); diff --git a/tests/Serializer/XmlSerializationTest.php b/tests/Serializer/XmlSerializationTest.php index 6fcb01c77..201a748cf 100644 --- a/tests/Serializer/XmlSerializationTest.php +++ b/tests/Serializer/XmlSerializationTest.php @@ -46,6 +46,9 @@ use JMS\Serializer\Visitor\Factory\XmlDeserializationVisitorFactory; use JMS\Serializer\Visitor\Factory\XmlSerializationVisitorFactory; use JMS\Serializer\XmlSerializationVisitor; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\Group; class XmlSerializationTest extends BaseSerializationTestCase { @@ -61,6 +64,7 @@ public function testInvalidUsageOfXmlValue() /** * @dataProvider getXMLBooleans */ + #[DataProvider('getXMLBooleans')] public function testXMLBooleans($xmlBoolean, $boolean) { if ($this->hasDeserializer()) { @@ -143,6 +147,7 @@ public function testDocumentTypesAreNotAllowed() /** * @doesNotPerformAssertions */ + #[DoesNotPerformAssertions] public function testWhitelistedDocumentTypesAreAllowed() { $xmlVisitor = new XmlDeserializationVisitorFactory(); @@ -302,6 +307,7 @@ public function testDeserializeTypedAndNestedArrayKeyValues() * @dataProvider getDateTime * @group datetime */ + #[DataProvider('getDateTime')] public function testDateTimeNoCData($key, $value, $type) { $builder = SerializerBuilder::create(); @@ -317,6 +323,7 @@ public function testDateTimeNoCData($key, $value, $type) * @dataProvider getDateTimeImmutable * @group datetime */ + #[DataProvider('getDateTimeImmutable')] public function testDateTimeImmutableNoCData($key, $value, $type) { $builder = SerializerBuilder::create(); diff --git a/tests/SerializerBuilderTest.php b/tests/SerializerBuilderTest.php index 232bcfdd3..73fb575f9 100644 --- a/tests/SerializerBuilderTest.php +++ b/tests/SerializerBuilderTest.php @@ -4,6 +4,8 @@ namespace JMS\Serializer\Tests; +use JMS\Serializer\ContextFactory\DeserializationContextFactoryInterface; +use JMS\Serializer\ContextFactory\SerializationContextFactoryInterface; use JMS\Serializer\DeserializationContext; use JMS\Serializer\Exception\UnsupportedFormatException; use JMS\Serializer\Expression\ExpressionEvaluator; @@ -16,6 +18,7 @@ use JMS\Serializer\Tests\Fixtures\PersonSecretWithVariables; use JMS\Serializer\Type\ParserInterface; use JMS\Serializer\Visitor\Factory\JsonSerializationVisitorFactory; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Constraint\FileExists; use PHPUnit\Framework\Constraint\LogicalNot; use PHPUnit\Framework\TestCase; @@ -136,14 +139,14 @@ public function testIncludeInterfaceMetadata() public function testSetSerializationContext() { - $contextFactoryMock = $this->getMockForAbstractClass('JMS\\Serializer\\ContextFactory\\SerializationContextFactoryInterface'); + $contextFactoryMock = $this->createMock(SerializationContextFactoryInterface::class); $context = new SerializationContext(); $context->setSerializeNull(true); $contextFactoryMock ->expects($this->once()) ->method('createSerializationContext') - ->will($this->returnValue($context)); + ->willReturn($context); $this->builder->setSerializationContextFactory($contextFactoryMock); @@ -156,13 +159,13 @@ public function testSetSerializationContext() public function testSetDeserializationContext() { - $contextFactoryMock = $this->getMockForAbstractClass('JMS\\Serializer\\ContextFactory\\DeserializationContextFactoryInterface'); + $contextFactoryMock = $this->createMock(DeserializationContextFactoryInterface::class); $context = new DeserializationContext(); $contextFactoryMock ->expects($this->once()) ->method('createDeserializationContext') - ->will($this->returnValue($context)); + ->willReturn($context); $this->builder->setDeserializationContextFactory($contextFactoryMock); @@ -229,6 +232,7 @@ public static function expressionFunctionProvider() * * @dataProvider expressionFunctionProvider */ + #[DataProvider('expressionFunctionProvider')] public function testExpressionEngine(ExpressionFunction $function, $json) { $language = new ExpressionLanguage(); From f79eadbad8b41dc8fffea0c131cab9309f10a97c Mon Sep 17 00:00:00 2001 From: Taras Andrusiak Date: Wed, 6 Mar 2024 09:41:55 +0200 Subject: [PATCH 37/38] Fix incorrect namespace for ANNOTATIONS_TO_ATTRIBUTES class. --- UPGRADING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index 1784b1099..93ae1ced1 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -12,7 +12,7 @@ Starting from this release [doctrine/annotations](https://github.com/doctrine/an If you still want to use them, please make sure that you require in `composer.json` file. We strongly recommend to start using [Attributes](https://www.php.net/manual/en/language.attributes.overview.php) with PHP 8. -You can easily migrate annotations to attributes with [rector](https://github.com/rectorphp/rector) and `Rector\Symfony\Set::ANNOTATIONS_TO_ATTRIBUTES` rules. +You can easily migrate annotations to attributes with [rector](https://github.com/rectorphp/rector) and `Rector\Symfony\Set\SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES` rules. From 2.x to 3.0.0 ================= From 7a2799c73c96da50bc00629fc0013cb66d79dc06 Mon Sep 17 00:00:00 2001 From: Marcin Czarnecki Date: Sat, 23 Mar 2024 17:21:29 +0100 Subject: [PATCH 38/38] Fix code style --- src/Context.php | 3 --- src/EventDispatcher/PreSerializeEvent.php | 3 --- src/Handler/DateHandler.php | 6 ------ src/Handler/FormErrorHandler.php | 12 ------------ tests/Fixtures/ObjectWithInlineArray.php | 3 --- 5 files changed, 27 deletions(-) diff --git a/src/Context.php b/src/Context.php index 63fcfb6f4..ca8472966 100644 --- a/src/Context.php +++ b/src/Context.php @@ -241,9 +241,6 @@ public function getMetadataStack(): \SplStack return $this->metadataStack; } - /** - * @return array - */ public function getCurrentPath(): array { if (!$this->metadataStack) { diff --git a/src/EventDispatcher/PreSerializeEvent.php b/src/EventDispatcher/PreSerializeEvent.php index 2e9a575f5..38f15fce6 100644 --- a/src/EventDispatcher/PreSerializeEvent.php +++ b/src/EventDispatcher/PreSerializeEvent.php @@ -6,9 +6,6 @@ class PreSerializeEvent extends ObjectEvent { - /** - * @param array $params - */ public function setType(string $typeName, array $params = []): void { $this->type = ['name' => $typeName, 'params' => $params]; diff --git a/src/Handler/DateHandler.php b/src/Handler/DateHandler.php index ada72f76b..bc8fe94a6 100644 --- a/src/Handler/DateHandler.php +++ b/src/Handler/DateHandler.php @@ -279,9 +279,6 @@ private function parseDateInterval(string $data): \DateInterval return $dateInterval; } - /** - * @param array $type - */ private function getDeserializationFormats(array $type): array { if (isset($type['params'][2])) { @@ -291,9 +288,6 @@ private function getDeserializationFormats(array $type): array return [$this->getFormat($type)]; } - /** - * @param array $type - */ private function getFormat(array $type): string { return $type['params'][0] ?? $this->defaultFormat; diff --git a/src/Handler/FormErrorHandler.php b/src/Handler/FormErrorHandler.php index 6951f3292..c794e2b2f 100644 --- a/src/Handler/FormErrorHandler.php +++ b/src/Handler/FormErrorHandler.php @@ -71,9 +71,6 @@ public function __construct(?object $translator = null, string $translationDomai $this->translationDomain = $translationDomain; } - /** - * @param array $type - */ public function serializeFormToXml(XmlSerializationVisitor $visitor, FormInterface $form, array $type): \DOMElement { $formNode = $visitor->getDocument()->createElement('form'); @@ -98,25 +95,16 @@ public function serializeFormToXml(XmlSerializationVisitor $visitor, FormInterfa return $formNode; } - /** - * @param array $type - */ public function serializeFormToJson(SerializationVisitorInterface $visitor, FormInterface $form, array $type): \ArrayObject { return $this->convertFormToArray($visitor, $form); } - /** - * @param array $type - */ public function serializeFormErrorToXml(XmlSerializationVisitor $visitor, FormError $formError, array $type): \DOMCdataSection { return $visitor->getDocument()->createCDATASection($this->getErrorMessage($formError)); } - /** - * @param array $type - */ public function serializeFormErrorToJson(SerializationVisitorInterface $visitor, FormError $formError, array $type): string { return $this->getErrorMessage($formError); diff --git a/tests/Fixtures/ObjectWithInlineArray.php b/tests/Fixtures/ObjectWithInlineArray.php index 83b236e7c..cfa3b89e7 100644 --- a/tests/Fixtures/ObjectWithInlineArray.php +++ b/tests/Fixtures/ObjectWithInlineArray.php @@ -16,9 +16,6 @@ final class ObjectWithInlineArray #[Serializer\Type(name: 'array')] public $array; - /** - * @param array $array - */ public function __construct(array $array) { $this->array = $array;