diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
index 085ceb5dafabb..62c19e9ee75d7 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -934,6 +934,7 @@ private function addSerializerSection(ArrayNodeDefinition $rootNode)
->end()
->end()
->end()
+ ->scalarNode('default_version')->end()
->end()
->end()
->end()
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index e929724c7fd86..700eb4da3ca98 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -1598,6 +1598,12 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder
$defaultContext += ['max_depth_handler' => new Reference($config['max_depth_handler'])];
$container->getDefinition('serializer.normalizer.object')->replaceArgument(6, $defaultContext);
}
+
+ if (isset($config['default_version']) && $config['default_version']) {
+ $defaultContext = $container->getDefinition('serializer.normalizer.object')->getArgument(6);
+ $defaultContext += ['version' => $config['default_version']];
+ $container->getDefinition('serializer.normalizer.object')->replaceArgument(6, $defaultContext);
+ }
}
private function registerPropertyInfoConfiguration(ContainerBuilder $container, PhpFileLoader $loader)
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
index 08cea8ecee7ab..a54d5fc981fe3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
@@ -251,6 +251,7 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
index 647044e613798..91f522fb1eae8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
@@ -67,6 +67,7 @@
'name_converter' => 'serializer.name_converter.camel_case_to_snake_case',
'circular_reference_handler' => 'my.circular.reference.handler',
'max_depth_handler' => 'my.max.depth.handler',
+ 'default_version' => '1.0.0',
],
'property_info' => true,
'ide' => 'file%%link%%format',
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
index 9207066f1c183..5ceccf58e9b47 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
@@ -33,7 +33,7 @@
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
index 2206585863baa..390aaaca73df4 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
@@ -55,6 +55,7 @@ framework:
name_converter: serializer.name_converter.camel_case_to_snake_case
circular_reference_handler: my.circular.reference.handler
max_depth_handler: my.max.depth.handler
+ default_version: 1.0.0
property_info: ~
ide: file%%link%%format
request:
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
index 99054524d004c..f013178fea31a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
@@ -1108,6 +1108,8 @@ public function testSerializerEnabled()
$this->assertArrayHasKey('circular_reference_handler', $container->getDefinition('serializer.normalizer.object')->getArgument(6));
$this->assertArrayHasKey('max_depth_handler', $container->getDefinition('serializer.normalizer.object')->getArgument(6));
$this->assertEquals($container->getDefinition('serializer.normalizer.object')->getArgument(6)['max_depth_handler'], new Reference('my.max.depth.handler'));
+ $this->assertArrayHasKey('version', $container->getDefinition('serializer.normalizer.object')->getArgument(6));
+ $this->assertEquals($container->getDefinition('serializer.normalizer.object')->getArgument(6)['version'], '1.0.0');
}
public function testRegisterSerializerExtractor()
diff --git a/src/Symfony/Component/Serializer/Annotation/Since.php b/src/Symfony/Component/Serializer/Annotation/Since.php
new file mode 100644
index 0000000000000..7117e9ccef50a
--- /dev/null
+++ b/src/Symfony/Component/Serializer/Annotation/Since.php
@@ -0,0 +1,48 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Serializer\Annotation;
+
+use Symfony\Component\Serializer\Exception\InvalidArgumentException;
+
+/**
+ * Annotation class for @Since().
+ *
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD"})
+ *
+ * @author Arnaud Tarroux
+ */
+class Since
+{
+ /**
+ * @var string
+ */
+ private $version;
+
+ public function __construct(array $data)
+ {
+ if (!isset($data['value'])) {
+ throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" should be set.', static::class));
+ }
+
+ if (!\is_string($data['value']) || empty($data['value'])) {
+ throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be a non-empty string.', static::class));
+ }
+
+ $this->version = $data['value'];
+ }
+
+ public function getVersion(): string
+ {
+ return $this->version;
+ }
+}
diff --git a/src/Symfony/Component/Serializer/Annotation/Until.php b/src/Symfony/Component/Serializer/Annotation/Until.php
new file mode 100644
index 0000000000000..16f1616addfe5
--- /dev/null
+++ b/src/Symfony/Component/Serializer/Annotation/Until.php
@@ -0,0 +1,48 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Serializer\Annotation;
+
+use Symfony\Component\Serializer\Exception\InvalidArgumentException;
+
+/**
+ * Annotation class for @Until().
+ *
+ * @Annotation
+ * @Target({"PROPERTY", "METHOD"})
+ *
+ * @author Arnaud Tarroux
+ */
+class Until
+{
+ /**
+ * @var string
+ */
+ private $version;
+
+ public function __construct(array $data)
+ {
+ if (!isset($data['value'])) {
+ throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" should be set.', static::class));
+ }
+
+ if (!\is_string($data['value']) || empty($data['value'])) {
+ throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be a non-empty string.', static::class));
+ }
+
+ $this->version = $data['value'];
+ }
+
+ public function getVersion(): string
+ {
+ return $this->version;
+ }
+}
diff --git a/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php b/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php
index 732e0bd5908cc..fd3ff0d5ca614 100644
--- a/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php
+++ b/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php
@@ -59,6 +59,24 @@ class AttributeMetadata implements AttributeMetadataInterface
*/
public $ignore = false;
+ /**
+ * @var string|null
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getSince()} instead.
+ */
+ public $since;
+
+ /**
+ * @var string|null
+ *
+ * @internal This property is public in order to reduce the size of the
+ * class' serialized representation. Do not access it. Use
+ * {@link getUntil()} instead.
+ */
+ public $until;
+
public function __construct(string $name)
{
$this->name = $name;
@@ -162,6 +180,38 @@ public function merge(AttributeMetadataInterface $attributeMetadata)
}
}
+ /**
+ * {@inheritdoc}
+ */
+ public function setSince(string $version)
+ {
+ $this->since = $version;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSince(): ?string
+ {
+ return $this->since;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setUntil(string $version)
+ {
+ $this->until = $version;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getUntil(): ?string
+ {
+ return $this->until;
+ }
+
/**
* Returns the names of the properties that should be serialized.
*
@@ -169,6 +219,6 @@ public function merge(AttributeMetadataInterface $attributeMetadata)
*/
public function __sleep()
{
- return ['name', 'groups', 'maxDepth', 'serializedName', 'ignore'];
+ return ['name', 'groups', 'maxDepth', 'serializedName', 'ignore', 'since', 'until'];
}
}
diff --git a/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php b/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php
index 9e78cf0d31743..00f8608fd73c5 100644
--- a/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php
+++ b/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php
@@ -75,4 +75,24 @@ public function isIgnored(): bool;
* Merges an {@see AttributeMetadataInterface} with in the current one.
*/
public function merge(self $attributeMetadata);
+
+ /**
+ * Sets the version number from which the attribute must be serialized.
+ */
+ public function setSince(string $version);
+
+ /**
+ * Gets the version number from which the attribute must be serialized.
+ */
+ public function getSince(): ?string;
+
+ /**
+ * Sets the version number after which the attribute must not be serialized.
+ */
+ public function setUntil(string $version);
+
+ /**
+ * Gets the version number after which the attribute must not be serialized.
+ */
+ public function getUntil(): ?string;
}
diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/AnnotationLoader.php b/src/Symfony/Component/Serializer/Mapping/Loader/AnnotationLoader.php
index 978fe659bbbce..7883be8200c4e 100644
--- a/src/Symfony/Component/Serializer/Mapping/Loader/AnnotationLoader.php
+++ b/src/Symfony/Component/Serializer/Mapping/Loader/AnnotationLoader.php
@@ -17,6 +17,8 @@
use Symfony\Component\Serializer\Annotation\Ignore;
use Symfony\Component\Serializer\Annotation\MaxDepth;
use Symfony\Component\Serializer\Annotation\SerializedName;
+use Symfony\Component\Serializer\Annotation\Since;
+use Symfony\Component\Serializer\Annotation\Until;
use Symfony\Component\Serializer\Exception\MappingException;
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
@@ -74,6 +76,10 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata)
$attributesMetadata[$property->name]->setSerializedName($annotation->getSerializedName());
} elseif ($annotation instanceof Ignore) {
$attributesMetadata[$property->name]->setIgnore(true);
+ } elseif ($annotation instanceof Since) {
+ $attributesMetadata[$property->name]->setSince($annotation->getVersion());
+ } elseif ($annotation instanceof Until) {
+ $attributesMetadata[$property->name]->setUntil($annotation->getVersion());
}
$loaded = true;
@@ -121,6 +127,18 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata)
$attributeMetadata->setSerializedName($annotation->getSerializedName());
} elseif ($annotation instanceof Ignore) {
$attributeMetadata->setIgnore(true);
+ } elseif ($annotation instanceof Since) {
+ if (!$accessorOrMutator) {
+ throw new MappingException(sprintf('Since on "%s::%s" cannot be added. Since can only be added on methods beginning with "get", "is", "has" or "set".', $className, $method->name));
+ }
+
+ $attributeMetadata->setSince($annotation->getVersion());
+ } elseif ($annotation instanceof Until) {
+ if (!$accessorOrMutator) {
+ throw new MappingException(sprintf('Until on "%s::%s" cannot be added. Until can only be added on methods beginning with "get", "is", "has" or "set".', $className, $method->name));
+ }
+
+ $attributeMetadata->setUntil($annotation->getVersion());
}
$loaded = true;
diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php b/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php
index 696007afb83ad..ed4fe080fd6bd 100644
--- a/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php
+++ b/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php
@@ -74,6 +74,14 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata)
if (isset($attribute['ignore'])) {
$attributeMetadata->setIgnore((bool) $attribute['ignore']);
}
+
+ if (isset($attribute['since'])) {
+ $attributeMetadata->setSince((string) $attribute['since']);
+ }
+
+ if (isset($attribute['until'])) {
+ $attributeMetadata->setUntil((string) $attribute['until']);
+ }
}
if (isset($xml->{'discriminator-map'})) {
diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php
index ff50e622eeadf..997f81ae65044 100644
--- a/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php
+++ b/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php
@@ -101,6 +101,14 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata)
$attributeMetadata->setIgnore($data['ignore']);
}
+
+ if (isset($data['since'])) {
+ $attributeMetadata->setSince((string) $data['since']);
+ }
+
+ if (isset($data['until'])) {
+ $attributeMetadata->setUntil((string) $data['until']);
+ }
}
}
diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd b/src/Symfony/Component/Serializer/Mapping/Loader/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd
index b427a36e368c1..b5065c6b7b63a 100644
--- a/src/Symfony/Component/Serializer/Mapping/Loader/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd
+++ b/src/Symfony/Component/Serializer/Mapping/Loader/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd
@@ -79,6 +79,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
index 4a03ab851a3a2..1a91a9d0a33d2 100644
--- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
+++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
@@ -251,7 +251,8 @@ protected function getAllowedAttributes($classOrObject, array $context, bool $at
if (
!$ignore &&
(false === $groups || array_intersect(array_merge($attributeMetadata->getGroups(), ['*']), $groups)) &&
- $this->isAllowedAttribute($classOrObject, $name = $attributeMetadata->getName(), null, $context)
+ $this->isAllowedAttribute($classOrObject, $name = $attributeMetadata->getName(), null, $context) &&
+ $this->attributeAllowedWithVersion($context, $attributeMetadata->getSince(), $attributeMetadata->getUntil())
) {
$allowedAttributes[] = $attributesAsString ? $name : $attributeMetadata;
}
@@ -447,4 +448,25 @@ protected function createChildContext(array $parentContext, string $attribute, ?
return $parentContext;
}
+
+ /**
+ * @internal
+ */
+ private function attributeAllowedWithVersion(array $context, ?string $sinceVersion, ?string $untilVersion)
+ {
+ if (!isset($context['version']) && !isset($this->defaultContext['version'])) {
+ return true;
+ }
+
+ $version = $context['version'] ?? $this->defaultContext['version'];
+ if (null !== $sinceVersion && version_compare($version, $sinceVersion, '<')) {
+ return false;
+ }
+
+ if (null !== $untilVersion && version_compare($version, $untilVersion, '>=')) {
+ return false;
+ }
+
+ return true;
+ }
}
diff --git a/src/Symfony/Component/Serializer/Tests/Annotation/SinceTest.php b/src/Symfony/Component/Serializer/Tests/Annotation/SinceTest.php
new file mode 100644
index 0000000000000..8fa8cf8c5339f
--- /dev/null
+++ b/src/Symfony/Component/Serializer/Tests/Annotation/SinceTest.php
@@ -0,0 +1,57 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Serializer\Tests\Annotation;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Serializer\Annotation\Since;
+use Symfony\Component\Serializer\Exception\InvalidArgumentException;
+
+/**
+ * @author Arnaud Tarroux
+ */
+class SinceTest extends TestCase
+{
+ public function testNotSetVersionParameter()
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage(
+ 'Parameter of annotation "Symfony\Component\Serializer\Annotation\Since" should be set.'
+ );
+ new Since([]);
+ }
+
+ public function provideInvalidValues()
+ {
+ return [
+ [''],
+ [0],
+ ];
+ }
+
+ /**
+ * @dataProvider provideInvalidValues
+ */
+ public function testNotAStringVersionParameter($value)
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage(
+ 'Parameter of annotation "Symfony\Component\Serializer\Annotation\Since" must be a non-empty string.'
+ );
+ new Since(['value' => $value]);
+ }
+
+ public function testVersionParameters()
+ {
+ $since = new Since(['value' => '1.1.2']);
+ $this->assertSame('1.1.2', $since->getVersion());
+ }
+}
diff --git a/src/Symfony/Component/Serializer/Tests/Annotation/UntilTest.php b/src/Symfony/Component/Serializer/Tests/Annotation/UntilTest.php
new file mode 100644
index 0000000000000..9021a23b56f4c
--- /dev/null
+++ b/src/Symfony/Component/Serializer/Tests/Annotation/UntilTest.php
@@ -0,0 +1,57 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Serializer\Tests\Annotation;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Serializer\Annotation\Until;
+use Symfony\Component\Serializer\Exception\InvalidArgumentException;
+
+/**
+ * @author Arnaud Tarroux
+ */
+class UntilTest extends TestCase
+{
+ public function testNotSetVersionParameter()
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage(
+ 'Parameter of annotation "Symfony\Component\Serializer\Annotation\Until" should be set.'
+ );
+ new Until([]);
+ }
+
+ public function provideInvalidValues()
+ {
+ return [
+ [''],
+ [0],
+ ];
+ }
+
+ /**
+ * @dataProvider provideInvalidValues
+ */
+ public function testNotAStringVersionParameter($value)
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage(
+ 'Parameter of annotation "Symfony\Component\Serializer\Annotation\Until" must be a non-empty string.'
+ );
+ new Until(['value' => $value]);
+ }
+
+ public function testVersionParameters()
+ {
+ $since = new Until(['value' => '1.1.2']);
+ $this->assertSame('1.1.2', $since->getVersion());
+ }
+}
diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/VersioningDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/VersioningDummy.php
new file mode 100644
index 0000000000000..b07bfe3ab9394
--- /dev/null
+++ b/src/Symfony/Component/Serializer/Tests/Fixtures/VersioningDummy.php
@@ -0,0 +1,38 @@
+foo;
+ }
+
+ /**
+ * @Until("1.3.0")
+ */
+ public function getUsername()
+ {
+ return $this->username;
+ }
+}
diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.xml b/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.xml
index 257d838b4965e..cf93a19afc2f8 100644
--- a/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.xml
+++ b/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.xml
@@ -39,4 +39,8 @@
+
+
+
+
diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.yml b/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.yml
index 4d98c73b04c16..91719d8eeb4c3 100644
--- a/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.yml
+++ b/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.yml
@@ -30,3 +30,9 @@
ignore: true
ignored2:
ignore: true
+
+'Symfony\Component\Serializer\Tests\Fixtures\VersionDummy':
+ attributes:
+ foo:
+ since: '1.0.0'
+ until: '1.1.9'
diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/Loader/AnnotationLoaderTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/Loader/AnnotationLoaderTest.php
index 9c5a9943e31ef..3e3299250e25b 100644
--- a/src/Symfony/Component/Serializer/Tests/Mapping/Loader/AnnotationLoaderTest.php
+++ b/src/Symfony/Component/Serializer/Tests/Mapping/Loader/AnnotationLoaderTest.php
@@ -20,8 +20,8 @@
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummy;
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummyFirstChild;
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummySecondChild;
-use Symfony\Component\Serializer\Tests\Fixtures\IgnoreDummy;
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummyThirdChild;
+use Symfony\Component\Serializer\Tests\Fixtures\IgnoreDummy;
use Symfony\Component\Serializer\Tests\Mapping\TestClassMetadataFactory;
/**
@@ -118,4 +118,17 @@ public function testLoadIgnore()
$this->assertTrue($attributesMetadata['ignored1']->isIgnored());
$this->assertTrue($attributesMetadata['ignored2']->isIgnored());
}
+
+ public function testLoadVersion()
+ {
+ $classMetadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\VersioningDummy');
+ $this->loader->loadClassMetadata($classMetadata);
+
+ $attributesMetadata = $classMetadata->getAttributesMetadata();
+
+ $this->assertSame('1.0.0', $attributesMetadata['foo']->getSince());
+ $this->assertSame('1.1.2', $attributesMetadata['bar']->getSince());
+ $this->assertSame('1.1.9', $attributesMetadata['foo']->getUntil());
+ $this->assertSame('1.3.0', $attributesMetadata['username']->getUntil());
+ }
}
diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/Loader/XmlFileLoaderTest.php
index 4d30c8e2cbfe9..b71fbfd27a44e 100644
--- a/src/Symfony/Component/Serializer/Tests/Mapping/Loader/XmlFileLoaderTest.php
+++ b/src/Symfony/Component/Serializer/Tests/Mapping/Loader/XmlFileLoaderTest.php
@@ -103,4 +103,15 @@ public function testLoadIgnore()
$this->assertTrue($attributesMetadata['ignored1']->isIgnored());
$this->assertTrue($attributesMetadata['ignored2']->isIgnored());
}
+
+ public function testVersion()
+ {
+ $classMetadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\VersionDummy');
+ $this->loader->loadClassMetadata($classMetadata);
+
+ $attributesMetadata = $classMetadata->getAttributesMetadata();
+
+ $this->assertSame('1.2.0', $attributesMetadata['foo']->getSince());
+ $this->assertSame('1.9.1', $attributesMetadata['foo']->getUntil());
+ }
}
diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/Loader/YamlFileLoaderTest.php
index 6d2ff5c0bdb8e..32d5d217b5f89 100644
--- a/src/Symfony/Component/Serializer/Tests/Mapping/Loader/YamlFileLoaderTest.php
+++ b/src/Symfony/Component/Serializer/Tests/Mapping/Loader/YamlFileLoaderTest.php
@@ -125,4 +125,15 @@ public function testLoadInvalidIgnore()
(new YamlFileLoader(__DIR__.'/../../Fixtures/invalid-ignore.yml'))->loadClassMetadata(new ClassMetadata(IgnoreDummy::class));
}
+
+ public function testVersion()
+ {
+ $classMetadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\VersionDummy');
+ $this->loader->loadClassMetadata($classMetadata);
+
+ $attributesMetadata = $classMetadata->getAttributesMetadata();
+
+ $this->assertSame('1.0.0', $attributesMetadata['foo']->getSince());
+ $this->assertSame('1.1.9', $attributesMetadata['foo']->getUntil());
+ }
}
diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php
index 082b427ab7caa..3f308591e946c 100644
--- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php
+++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php
@@ -190,4 +190,42 @@ public function testIgnore()
$this->assertSame([], $normalizer->normalize($dummy));
}
+
+ public function testObjectWithVersioning()
+ {
+ $classMetadata = new ClassMetadata('c');
+
+ $a = new AttributeMetadata('a');
+ $a->setSince('1.8.0');
+ $a->addGroup('test');
+ $classMetadata->addAttributeMetadata($a);
+
+ $b = new AttributeMetadata('b');
+ $b->setUntil('2.1.0');
+ $b->addGroup('test');
+ $classMetadata->addAttributeMetadata($b);
+
+ $c = new AttributeMetadata('c');
+ $c->setSince('1.8.0');
+ $c->setUntil('2.0.0');
+ $c->addGroup('test');
+ $classMetadata->addAttributeMetadata($c);
+
+ $this->classMetadata->method('getMetadataFor')->willReturn($classMetadata);
+
+ $result = $this->normalizer->getAllowedAttributes('c', [
+ AbstractNormalizer::GROUPS => ['test'], 'version' => '1.8.0',
+ ], true);
+ $this->assertSame(['a', 'b', 'c'], $result);
+
+ $result = $this->normalizer->getAllowedAttributes('c', [
+ AbstractNormalizer::GROUPS => ['test'], 'version' => '1.7.0',
+ ], true);
+ $this->assertSame(['b'], $result);
+
+ $result = $this->normalizer->getAllowedAttributes('c', [
+ AbstractNormalizer::GROUPS => ['test'], 'version' => '2.3.0',
+ ], true);
+ $this->assertSame(['a'], $result);
+ }
}