From 9366a7dc774299cdeb722f61349525f5b717e92c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sun, 10 Jul 2016 11:41:46 +0200 Subject: [PATCH] [Serializer][FrameworkBundle] Add a YAML encoder --- .../FrameworkExtension.php | 8 ++ .../Serializer/Encoder/YamlEncoder.php | 73 +++++++++++++++++++ .../Tests/Encoder/YamlEncoderTest.php | 68 +++++++++++++++++ .../Component/Serializer/composer.json | 5 +- 4 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/Serializer/Encoder/YamlEncoder.php create mode 100644 src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 8cd1fea64a..fcbda5951e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -26,12 +26,14 @@ use Symfony\Component\Finder\Finder; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\Config\FileLocator; use Symfony\Component\PropertyAccess\PropertyAccessor; +use Symfony\Component\Serializer\Encoder\YamlEncoder; use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; use Symfony\Component\Serializer\Normalizer\DataUriNormalizer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer; use Symfony\Component\Validator\Validation; use Symfony\Component\Workflow; +use Symfony\Component\Yaml\Yaml; /** * FrameworkExtension. @@ -977,6 +979,12 @@ class FrameworkExtension extends Extension $definition->addTag('serializer.normalizer', array('priority' => -900)); } + if (class_exists(YamlEncoder::class) && defined('Symfony\Component\Yaml\Yaml::DUMP_OBJECT')) { + $definition = $container->register('serializer.encoder.yaml', YamlEncoder::class); + $definition->setPublic(false); + $definition->addTag('serializer.encoder'); + } + $loader->load('serializer.xml'); $chainLoader = $container->getDefinition('serializer.mapping.chain_loader'); diff --git a/src/Symfony/Component/Serializer/Encoder/YamlEncoder.php b/src/Symfony/Component/Serializer/Encoder/YamlEncoder.php new file mode 100644 index 0000000000..48eff39611 --- /dev/null +++ b/src/Symfony/Component/Serializer/Encoder/YamlEncoder.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Encoder; + +use Symfony\Component\Yaml\Dumper; +use Symfony\Component\Yaml\Parser; +use Symfony\Component\Yaml\Yaml; + +/** + * Encodes YAML data. + * + * @author Kévin Dunglas + */ +class YamlEncoder implements EncoderInterface, DecoderInterface +{ + const FORMAT = 'yaml'; + + private $dumper; + private $parser; + private $defaultContext = array('yaml_inline' => 0, 'yaml_indent' => 0, 'yaml_flags' => 0); + + public function __construct(Dumper $dumper = null, Parser $parser = null, array $defaultContext = array()) + { + $this->dumper = $dumper ?: new Dumper(); + $this->parser = $parser ?: new Parser(); + $this->defaultContext = array_merge($this->defaultContext, $defaultContext); + } + + /** + * {@inheritdoc} + */ + public function encode($data, $format, array $context = array()) + { + $context = array_merge($this->defaultContext, $context); + + return $this->dumper->dump($data, $context['yaml_inline'], $context['yaml_indent'], $context['yaml_flags']); + } + + /** + * {@inheritdoc} + */ + public function supportsEncoding($format) + { + return self::FORMAT === $format; + } + + /** + * {@inheritdoc} + */ + public function decode($data, $format, array $context = array()) + { + $context = array_merge($this->defaultContext, $context); + + return Yaml::parse($data, $context['yaml_flags']); + } + + /** + * {@inheritdoc} + */ + public function supportsDecoding($format) + { + return self::FORMAT === $format; + } +} diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php new file mode 100644 index 0000000000..8627460a97 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Encoder; + +use Symfony\Component\Serializer\Encoder\YamlEncoder; +use Symfony\Component\Yaml\Dumper; +use Symfony\Component\Yaml\Parser; +use Symfony\Component\Yaml\Yaml; + +/** + * @author Kévin Dunglas + */ +class YamlEncoderTest extends \PHPUnit_Framework_TestCase +{ + public function testEncode() + { + $encoder = new YamlEncoder(); + + $this->assertEquals('foo', $encoder->encode('foo', 'yaml')); + $this->assertEquals('{ foo: 1 }', $encoder->encode(array('foo' => 1), 'yaml')); + } + + public function testSupportsEncoding() + { + $encoder = new YamlEncoder(); + + $this->assertTrue($encoder->supportsEncoding('yaml')); + $this->assertFalse($encoder->supportsEncoding('json')); + } + + public function testDecode() + { + $encoder = new YamlEncoder(); + + $this->assertEquals('foo', $encoder->decode('foo', 'yaml')); + $this->assertEquals(array('foo' => 1), $encoder->decode('{ foo: 1 }', 'yaml')); + } + + public function testSupportsDecoding() + { + $encoder = new YamlEncoder(); + + $this->assertTrue($encoder->supportsDecoding('yaml')); + $this->assertFalse($encoder->supportsDecoding('json')); + } + + public function testContext() + { + $encoder = new YamlEncoder(new Dumper(), new Parser(), array('yaml_inline' => 1, 'yaml_indent' => 4, 'yaml_flags' => Yaml::DUMP_OBJECT | Yaml::PARSE_OBJECT)); + + $obj = new \stdClass(); + $obj->bar = 2; + + $this->assertEquals(" foo: !php/object:O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}\n", $encoder->encode(array('foo' => $obj), 'yaml')); + $this->assertEquals(' { foo: null }', $encoder->encode(array('foo' => $obj), 'yaml', array('yaml_inline' => 0, 'yaml_indent' => 2, 'yaml_flags' => 0))); + $this->assertEquals(array('foo' => $obj), $encoder->decode('foo: !php/object:O:8:"stdClass":1:{s:3:"bar";i:2;}', 'yaml')); + $this->assertEquals(array('foo' => null), $encoder->decode('foo: !php/object:O:8:"stdClass":1:{s:3:"bar";i:2;}', 'yaml', array('yaml_flags' => 0))); + } +} diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index 13d60e1a9e..91fe7bcf12 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -19,7 +19,7 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/yaml": "~2.8|~3.0", + "symfony/yaml": "~3.1", "symfony/config": "~2.8|~3.0", "symfony/property-access": "~2.8|~3.0", "symfony/http-foundation": "~2.8|~3.0", @@ -29,7 +29,8 @@ "doctrine/cache": "~1.0" }, "conflict": { - "symfony/property-access": ">=3.0,<3.0.4|>=2.8,<2.8.4" + "symfony/property-access": ">=3.0,<3.0.4|>=2.8,<2.8.4", + "symfony/yaml": "<3.1" }, "suggest": { "psr/cache-implementation": "For using the metadata cache.",