* * 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 PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Tests\Fixtures\Dummy; use Symfony\Component\Serializer\Tests\Fixtures\NormalizableTraversableDummy; use Symfony\Component\Serializer\Tests\Fixtures\ScalarDummy; use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Normalizer\CustomNormalizer; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; class XmlEncoderTest extends TestCase { /** * @var XmlEncoder */ private $encoder; private $exampleDateTimeString = '2017-02-19T15:16:08+0300'; protected function setUp() { $this->encoder = new XmlEncoder(); $serializer = new Serializer(array(new CustomNormalizer()), array('xml' => new XmlEncoder())); $this->encoder->setSerializer($serializer); } public function testEncodeScalar() { $obj = new ScalarDummy(); $obj->xmlFoo = 'foo'; $expected = ''."\n". 'foo'."\n"; $this->assertEquals($expected, $this->encoder->encode($obj, 'xml')); } public function testSetRootNodeName() { $obj = new ScalarDummy(); $obj->xmlFoo = 'foo'; $this->encoder->setRootNodeName('test'); $expected = ''."\n". 'foo'."\n"; $this->assertEquals($expected, $this->encoder->encode($obj, 'xml')); } /** * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException * @expectedExceptionMessage Document types are not allowed. */ public function testDocTypeIsNotAllowed() { $this->encoder->decode('', 'foo'); } public function testAttributes() { $obj = new ScalarDummy(); $obj->xmlFoo = array( 'foo-bar' => array( '@id' => 1, '@name' => 'Bar', ), 'Foo' => array( 'Bar' => 'Test', '@Type' => 'test', ), 'föo_bär' => 'a', 'Bar' => array(1, 2, 3), 'a' => 'b', ); $expected = ''."\n". ''. ''. 'Test'. 'a'. '1'. '2'. '3'. 'b'. ''."\n"; $this->assertEquals($expected, $this->encoder->encode($obj, 'xml')); } public function testElementNameValid() { $obj = new ScalarDummy(); $obj->xmlFoo = array( 'foo-bar' => 'a', 'foo_bar' => 'a', 'föo_bär' => 'a', ); $expected = ''."\n". ''. 'a'. 'a'. 'a'. ''."\n"; $this->assertEquals($expected, $this->encoder->encode($obj, 'xml')); } public function testEncodeSimpleXML() { $xml = simplexml_load_string('Peter'); $array = array('person' => $xml); $expected = ''."\n". 'Peter'."\n"; $this->assertEquals($expected, $this->encoder->encode($array, 'xml')); } public function testEncodeXmlAttributes() { $xml = simplexml_load_string('Peter'); $array = array('person' => $xml); $expected = ''."\n". 'Peter'."\n"; $context = array( 'xml_version' => '1.1', 'xml_encoding' => 'utf-8', 'xml_standalone' => true, ); $this->assertSame($expected, $this->encoder->encode($array, 'xml', $context)); } public function testEncodeRemovingEmptyTags() { $array = array('person' => array('firstname' => 'Peter', 'lastname' => null)); $expected = ''."\n". 'Peter'."\n"; $context = array('remove_empty_tags' => true); $this->assertSame($expected, $this->encoder->encode($array, 'xml', $context)); } public function testEncodeNotRemovingEmptyTags() { $array = array('person' => array('firstname' => 'Peter', 'lastname' => null)); $expected = ''."\n". 'Peter'."\n"; $this->assertSame($expected, $this->encoder->encode($array, 'xml')); } public function testContext() { $array = array('person' => array('name' => 'George Abitbol')); $expected = <<<'XML' George Abitbol XML; $context = array( 'xml_format_output' => true, ); $this->assertSame($expected, $this->encoder->encode($array, 'xml', $context)); } public function testEncodeScalarRootAttributes() { $array = array( '#' => 'Paul', '@gender' => 'm', ); $expected = ''."\n". 'Paul'."\n"; $this->assertEquals($expected, $this->encoder->encode($array, 'xml')); } public function testEncodeRootAttributes() { $array = array( 'firstname' => 'Paul', '@gender' => 'm', ); $expected = ''."\n". 'Paul'."\n"; $this->assertEquals($expected, $this->encoder->encode($array, 'xml')); } public function testEncodeCdataWrapping() { $array = array( 'firstname' => 'Paul ', ); $expected = ''."\n". ']]>'."\n"; $this->assertEquals($expected, $this->encoder->encode($array, 'xml')); } public function testEncodeScalarWithAttribute() { $array = array( 'person' => array('@gender' => 'M', '#' => 'Peter'), ); $expected = ''."\n". 'Peter'."\n"; $this->assertEquals($expected, $this->encoder->encode($array, 'xml')); } public function testDecodeScalar() { $source = ''."\n". 'foo'."\n"; $this->assertEquals('foo', $this->encoder->decode($source, 'xml')); } public function testDecodeBigDigitAttributes() { $source = << Name XML; $this->assertSame(array('@index' => 182077241760011681341821060401202210011000045913000000017100, '#' => 'Name'), $this->encoder->decode($source, 'xml')); } public function testDecodeNegativeIntAttribute() { $source = << Name XML; $this->assertSame(array('@index' => -1234, '#' => 'Name'), $this->encoder->decode($source, 'xml')); } public function testDecodeFloatAttribute() { $source = << Name XML; $this->assertSame(array('@index' => -12.11, '#' => 'Name'), $this->encoder->decode($source, 'xml')); } public function testDecodeNegativeFloatAttribute() { $source = << Name XML; $this->assertSame(array('@index' => -12.11, '#' => 'Name'), $this->encoder->decode($source, 'xml')); } public function testNoTypeCastAttribute() { $source = << XML; $data = $this->encoder->decode($source, 'xml', array('xml_type_cast_attributes' => false)); $expected = array( '@a' => '018', '@b' => '-12.11', 'node' => array( '@a' => '018', '@b' => '-12.11', '#' => '', ), ); $this->assertSame($expected, $data); } public function testEncode() { $source = $this->getXmlSource(); $obj = $this->getObject(); $this->assertEquals($source, $this->encoder->encode($obj, 'xml')); } public function testEncodeWithNamespace() { $source = $this->getNamespacedXmlSource(); $array = $this->getNamespacedArray(); $this->assertEquals($source, $this->encoder->encode($array, 'xml')); } public function testEncodeSerializerXmlRootNodeNameOption() { $options = array('xml_root_node_name' => 'test'); $this->encoder = new XmlEncoder(); $serializer = new Serializer(array(), array('xml' => new XmlEncoder())); $this->encoder->setSerializer($serializer); $array = array( 'person' => array('@gender' => 'M', '#' => 'Peter'), ); $expected = ''."\n". 'Peter'."\n"; $this->assertEquals($expected, $serializer->serialize($array, 'xml', $options)); } public function testEncodeTraversableWhenNormalizable() { $this->encoder = new XmlEncoder(); $serializer = new Serializer(array(new CustomNormalizer()), array('xml' => new XmlEncoder())); $this->encoder->setSerializer($serializer); $expected = <<<'XML' normalizedFoonormalizedBar XML; $this->assertEquals($expected, $serializer->serialize(new NormalizableTraversableDummy(), 'xml')); } public function testDecode() { $source = $this->getXmlSource(); $obj = $this->getObject(); $this->assertEquals(get_object_vars($obj), $this->encoder->decode($source, 'xml')); } public function testDecodeCdataWrapping() { $expected = array( 'firstname' => 'Paul ', ); $xml = ''."\n". ']]>'."\n"; $this->assertEquals($expected, $this->encoder->decode($xml, 'xml')); } public function testDecodeCdataWrappingAndWhitespace() { $expected = array( 'firstname' => 'Paul ', ); $xml = ''."\n". ''."\n". ']]>'."\n"; $this->assertEquals($expected, $this->encoder->decode($xml, 'xml')); } public function testDecodeWithNamespace() { $source = $this->getNamespacedXmlSource(); $array = $this->getNamespacedArray(); $this->assertEquals($array, $this->encoder->decode($source, 'xml')); } public function testDecodeScalarWithAttribute() { $source = ''."\n". 'Peter'."\n"; $expected = array( 'person' => array('@gender' => 'M', '#' => 'Peter'), ); $this->assertEquals($expected, $this->encoder->decode($source, 'xml')); } public function testDecodeScalarRootAttributes() { $source = ''."\n". 'Peter'."\n"; $expected = array( '#' => 'Peter', '@gender' => 'M', ); $this->assertEquals($expected, $this->encoder->decode($source, 'xml')); } public function testDecodeRootAttributes() { $source = ''."\n". 'PeterMac Calloway'."\n"; $expected = array( 'firstname' => 'Peter', 'lastname' => 'Mac Calloway', '@gender' => 'M', ); $this->assertEquals($expected, $this->encoder->decode($source, 'xml')); } public function testDecodeArray() { $source = ''."\n". ''. ''. 'BenjaminAlexandre'. 'DamienClay'. ''. ''."\n"; $expected = array( 'people' => array('person' => array( array('firstname' => 'Benjamin', 'lastname' => 'Alexandre'), array('firstname' => 'Damien', 'lastname' => 'Clay'), )), ); $this->assertEquals($expected, $this->encoder->decode($source, 'xml')); } public function testDecodeXMLWithProcessInstruction() { $source = <<<'XML' foo a b val val bar title1 title2 Ed 1 ?> XML; $obj = $this->getObject(); $this->assertEquals(get_object_vars($obj), $this->encoder->decode($source, 'xml')); } public function testDecodeIgnoreWhiteSpace() { $source = <<<'XML' Benjamin Alexandre Damien Clay XML; $expected = array('person' => array( array('firstname' => 'Benjamin', 'lastname' => 'Alexandre'), array('firstname' => 'Damien', 'lastname' => 'Clay'), )); $this->assertEquals($expected, $this->encoder->decode($source, 'xml')); } public function testDecodeWithoutItemHash() { $obj = new ScalarDummy(); $obj->xmlFoo = array( 'foo-bar' => array( '@key' => 'value', 'item' => array('@key' => 'key', 'key-val' => 'val'), ), 'Foo' => array( 'Bar' => 'Test', '@Type' => 'test', ), 'föo_bär' => 'a', 'Bar' => array(1, 2, 3), 'a' => 'b', ); $expected = array( 'foo-bar' => array( '@key' => 'value', 'key' => array('@key' => 'key', 'key-val' => 'val'), ), 'Foo' => array( 'Bar' => 'Test', '@Type' => 'test', ), 'föo_bär' => 'a', 'Bar' => array(1, 2, 3), 'a' => 'b', ); $xml = $this->encoder->encode($obj, 'xml'); $this->assertEquals($expected, $this->encoder->decode($xml, 'xml')); } /** * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException */ public function testDecodeInvalidXml() { $this->encoder->decode('', 'xml'); } /** * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException */ public function testPreventsComplexExternalEntities() { $this->encoder->decode(']>&test;', 'xml'); } public function testDecodeEmptyXml() { if (method_exists($this, 'expectException')) { $this->expectException('Symfony\Component\Serializer\Exception\UnexpectedValueException'); $this->expectExceptionMessage('Invalid XML data, it can not be empty.'); } else { $this->setExpectedException('Symfony\Component\Serializer\Exception\UnexpectedValueException', 'Invalid XML data, it can not be empty.'); } $this->encoder->decode(' ', 'xml'); } protected function getXmlSource() { return ''."\n". ''. 'foo'. 'ab'. 'valvalbar'. 'title1title2'. 'Ed'. '1'. ''."\n"; } protected function getNamespacedXmlSource() { return ''."\n". ''. '1'. 'foo'. 'ab'. 'valvalbar'. 'title1title2'. 'Ed'. ''."\n"; } protected function getNamespacedArray() { return array( '@xmlns' => 'http://www.w3.org/2005/Atom', '@xmlns:app' => 'http://www.w3.org/2007/app', '@xmlns:media' => 'http://search.yahoo.com/mrss/', '@xmlns:gd' => 'http://schemas.google.com/g/2005', '@xmlns:yt' => 'http://gdata.youtube.com/schemas/2007', 'qux' => '1', 'app:foo' => 'foo', 'yt:bar' => array('a', 'b'), 'media:baz' => array( 'media:key' => 'val', 'media:key2' => 'val', 'A B' => 'bar', 'item' => array( array( 'title' => 'title1', ), array( 'title' => 'title2', ), ), 'Barry' => array( '@size' => 'large', 'FooBar' => array( 'Baz' => 'Ed', '@gd:id' => 1, ), ), ), ); } protected function getObject() { $obj = new Dummy(); $obj->foo = 'foo'; $obj->bar = array('a', 'b'); $obj->baz = array('key' => 'val', 'key2' => 'val', 'A B' => 'bar', 'item' => array(array('title' => 'title1'), array('title' => 'title2')), 'Barry' => array('FooBar' => array('Baz' => 'Ed', '@id' => 1))); $obj->qux = '1'; return $obj; } public function testEncodeXmlWithBoolValue() { $expectedXml = <<<'XML' 10 XML; $actualXml = $this->encoder->encode(array('foo' => true, 'bar' => false), 'xml'); $this->assertEquals($expectedXml, $actualXml); } public function testEncodeXmlWithDateTimeObjectValue() { $xmlEncoder = $this->createXmlEncoderWithDateTimeNormalizer(); $actualXml = $xmlEncoder->encode(array('dateTime' => new \DateTime($this->exampleDateTimeString)), 'xml'); $this->assertEquals($this->createXmlWithDateTime(), $actualXml); } public function testEncodeXmlWithDateTimeObjectField() { $xmlEncoder = $this->createXmlEncoderWithDateTimeNormalizer(); $actualXml = $xmlEncoder->encode(array('foo' => array('@dateTime' => new \DateTime($this->exampleDateTimeString))), 'xml'); $this->assertEquals($this->createXmlWithDateTimeField(), $actualXml); } /** * @return XmlEncoder */ private function createXmlEncoderWithDateTimeNormalizer() { $encoder = new XmlEncoder(); $serializer = new Serializer(array($this->createMockDateTimeNormalizer()), array('xml' => new XmlEncoder())); $encoder->setSerializer($serializer); return $encoder; } /** * @return \PHPUnit_Framework_MockObject_MockObject|NormalizerInterface */ private function createMockDateTimeNormalizer() { $mock = $this->getMockBuilder('\Symfony\Component\Serializer\Normalizer\CustomNormalizer')->getMock(); $mock ->expects($this->once()) ->method('normalize') ->with(new \DateTime($this->exampleDateTimeString), 'xml', array()) ->willReturn($this->exampleDateTimeString); $mock ->expects($this->once()) ->method('supportsNormalization') ->with(new \DateTime($this->exampleDateTimeString), 'xml') ->willReturn(true); return $mock; } /** * @return string */ private function createXmlWithDateTime() { return sprintf(' %s ', $this->exampleDateTimeString); } /** * @return string */ private function createXmlWithDateTimeField() { return sprintf(' ', $this->exampleDateTimeString); } } __halt_compiler();----SIGNATURE:----qg9EatgCYMMLzwDdEyphRX/9kiGByVFhuS/2vdN6Z8WtaAO6HeufIabCH+o0ShDeB9kSPBg6hErPiyLwqEjOw6Ii8iifiCM/rCF/F6lCMtvm9JROeTsVLaS5v65031yKZqG04fsHPEFJv1AcOMXyzTe5B+FOOnEpXEibMB4BdGydfZ4a8r7LMCLIghcis71Wacc9eHFwqPJP4vlswex2a9dO3VR/nollns7GE94osotEMn20TNPoJZYnn4D3jsEgiZIN/6IecYsVAafd22a56xUWQgNSMLEul3ZNjQ0XqQPOSppXFhmn3CSK4GgLLGeA6L8vwYrPdQ9e5RIhqcIEWoFIKZuWAh+2YfXtauaAzDjIvIEtBa4MzgOW10fCEhdzDR4sVnccQoRZoRKFw7KkDYb8gBQKCybXS2fsAHDUNcwLB3BPp2RE04lwdu/Zw0fXW3gbDVvRIHKGHIIKOxFWYK/xiHuEeq69xQzrQ1fYhJ9sTaVNvKQN1ailNJi9gwNeDCt4itDZNtyev+X8IpFe6LU6fjHkHpQJhWXS7TErnu5wt7qEk7MKhuhU3koAHyVR+dDY5EW/FuQiZatr2Rbr98UV0t1RocoVGZu+rRWwCZLxXxfSSB8nvRsmNgbZrlWpnt9MzyD3TK1WGthA2mkxKVnlPVxZQjpGadGJWQynW4Y=----ATTACHMENT:----MzM2NTEzMzk4MjY5NzYzMCA5NjM1NzExODgzOTY3NjI2IDkyMDA2NDgxNjc2NjAwOTg=