XmlEncoderTest.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. <?php
  2. namespace Symfony\Tests\Component\Serializer\Encoder;
  3. require_once __DIR__.'/../Fixtures/Dummy.php';
  4. require_once __DIR__.'/../Fixtures/ScalarDummy.php';
  5. use Symfony\Tests\Component\Serializer\Fixtures\Dummy;
  6. use Symfony\Tests\Component\Serializer\Fixtures\ScalarDummy;
  7. use Symfony\Component\Serializer\Encoder\XmlEncoder;
  8. use Symfony\Component\Serializer\Serializer;
  9. use Symfony\Component\Serializer\Exception\UnexpectedValueException;
  10. use Symfony\Component\Serializer\Normalizer\CustomNormalizer;
  11. /*
  12. * This file is part of the Symfony framework.
  13. *
  14. * (c) Fabien Potencier <fabien@symfony.com>
  15. *
  16. * This source file is subject to the MIT license that is bundled
  17. * with this source code in the file LICENSE.
  18. */
  19. class XmlEncoderTest extends \PHPUnit_Framework_TestCase
  20. {
  21. public function setUp()
  22. {
  23. $this->encoder = new XmlEncoder;
  24. $serializer = new Serializer(array(new CustomNormalizer), array('xml' => new XmlEncoder()));
  25. $this->encoder->setSerializer($serializer);
  26. }
  27. public function testEncodeScalar()
  28. {
  29. $obj = new ScalarDummy;
  30. $obj->xmlFoo = "foo";
  31. $expected = '<?xml version="1.0"?>'."\n".
  32. '<response><![CDATA[foo]]></response>'."\n";
  33. $this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
  34. }
  35. public function testSetRootNodeName()
  36. {
  37. $obj = new ScalarDummy;
  38. $obj->xmlFoo = "foo";
  39. $this->encoder->setRootNodeName('test');
  40. $expected = '<?xml version="1.0"?>'."\n".
  41. '<test><![CDATA[foo]]></test>'."\n";
  42. $this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
  43. }
  44. /**
  45. * @expectedException \InvalidArgumentException
  46. * @expectedExceptionMessage Document types are not allowed.
  47. */
  48. public function testDocTypeIsNotAllowed()
  49. {
  50. $this->encoder->decode('<?xml version="1.0"?><!DOCTYPE foo><foo></foo>', 'foo');
  51. }
  52. public function testAttributes()
  53. {
  54. $obj = new ScalarDummy;
  55. $obj->xmlFoo = array(
  56. 'foo-bar' => array(
  57. '@id' => 1,
  58. '@name' => 'Bar'
  59. ),
  60. 'Foo' => array(
  61. 'Bar' => "Test",
  62. '@Type' => 'test'
  63. ),
  64. 'föo_bär' => 'a',
  65. "Bar" => array(1,2,3),
  66. 'a' => 'b',
  67. );
  68. $expected = '<?xml version="1.0"?>'."\n".
  69. '<response>'.
  70. '<foo-bar id="1" name="Bar"/>'.
  71. '<Foo Type="test"><Bar><![CDATA[Test]]></Bar></Foo>'.
  72. '<föo_bär><![CDATA[a]]></föo_bär>'.
  73. '<Bar>1</Bar>'.
  74. '<Bar>2</Bar>'.
  75. '<Bar>3</Bar>'.
  76. '<a><![CDATA[b]]></a>'.
  77. '</response>'."\n";
  78. $this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
  79. }
  80. public function testElementNameValid()
  81. {
  82. $obj = new ScalarDummy;
  83. $obj->xmlFoo = array(
  84. 'foo-bar' => 'a',
  85. 'foo_bar' => 'a',
  86. 'föo_bär' => 'a',
  87. );
  88. $expected = '<?xml version="1.0"?>'."\n".
  89. '<response>'.
  90. '<foo-bar><![CDATA[a]]></foo-bar>'.
  91. '<foo_bar><![CDATA[a]]></foo_bar>'.
  92. '<föo_bär><![CDATA[a]]></föo_bär>'.
  93. '</response>'."\n";
  94. $this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
  95. }
  96. public function testEncodeSimpleXML()
  97. {
  98. $xml = simplexml_load_string('<firstname>Peter</firstname>');
  99. $array = array('person' => $xml);
  100. $expected = '<?xml version="1.0"?>'."\n".
  101. '<response><person><firstname>Peter</firstname></person></response>'."\n";
  102. $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
  103. }
  104. public function testEncodeScalarRootAttributes()
  105. {
  106. $array = array(
  107. '#' => 'Paul',
  108. '@gender' => 'm'
  109. );
  110. $expected = '<?xml version="1.0"?>'."\n".
  111. '<response gender="m"><![CDATA[Paul]]></response>'."\n";
  112. $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
  113. }
  114. public function testEncodeRootAttributes()
  115. {
  116. $array = array(
  117. 'firstname' => 'Paul',
  118. '@gender' => 'm'
  119. );
  120. $expected = '<?xml version="1.0"?>'."\n".
  121. '<response gender="m"><firstname><![CDATA[Paul]]></firstname></response>'."\n";
  122. $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
  123. }
  124. public function testEncodeScalarWithAttribute()
  125. {
  126. $array = array(
  127. 'person' => array('@gender' => 'M', '#' => 'Peter'),
  128. );
  129. $expected = '<?xml version="1.0"?>'."\n".
  130. '<response><person gender="M"><![CDATA[Peter]]></person></response>'."\n";
  131. $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
  132. }
  133. public function testDecodeScalar()
  134. {
  135. $source = '<?xml version="1.0"?>'."\n".
  136. '<response>foo</response>'."\n";
  137. $this->assertEquals('foo', $this->encoder->decode($source, 'xml'));
  138. }
  139. public function testEncode()
  140. {
  141. $source = $this->getXmlSource();
  142. $obj = $this->getObject();
  143. $this->assertEquals($source, $this->encoder->encode($obj, 'xml'));
  144. }
  145. public function testDecode()
  146. {
  147. $source = $this->getXmlSource();
  148. $obj = $this->getObject();
  149. $this->assertEquals(get_object_vars($obj), $this->encoder->decode($source, 'xml'));
  150. }
  151. public function testDecodeScalarWithAttribute()
  152. {
  153. $source = '<?xml version="1.0"?>'."\n".
  154. '<response><person gender="M">Peter</person></response>'."\n";
  155. $expected = array(
  156. 'person' => array('@gender' => 'M', '#' => 'Peter'),
  157. );
  158. $this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
  159. }
  160. public function testDecodeScalarRootAttributes()
  161. {
  162. $source = '<?xml version="1.0"?>'."\n".
  163. '<person gender="M">Peter</person>'."\n";
  164. $expected = array(
  165. '#' => 'Peter',
  166. '@gender' => 'M'
  167. );
  168. $this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
  169. }
  170. public function testDecodeRootAttributes()
  171. {
  172. $source = '<?xml version="1.0"?>'."\n".
  173. '<person gender="M"><firstname>Peter</firstname><lastname>Mac Calloway</lastname></person>'."\n";
  174. $expected = array(
  175. 'firstname' => 'Peter',
  176. 'lastname' => 'Mac Calloway',
  177. '@gender' => 'M'
  178. );
  179. $this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
  180. }
  181. public function testDecodeArray()
  182. {
  183. $source = '<?xml version="1.0"?>'."\n".
  184. '<response>'.
  185. '<people>'.
  186. '<person><firstname>Benjamin</firstname><lastname>Alexandre</lastname></person>'.
  187. '<person><firstname>Damien</firstname><lastname>Clay</lastname></person>'.
  188. '</people>'.
  189. '</response>'."\n";
  190. $expected = array(
  191. 'people' => array('person' => array(
  192. array('firstname' => 'Benjamin', 'lastname' => 'Alexandre'),
  193. array('firstname' => 'Damien', 'lastname' => 'Clay')
  194. ))
  195. );
  196. $this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
  197. }
  198. public function testPreventsComplexExternalEntities()
  199. {
  200. $oldCwd = getcwd();
  201. chdir(__DIR__);
  202. try {
  203. $this->encoder->decode('<?xml version="1.0"?><!DOCTYPE scan[<!ENTITY test SYSTEM "php://filter/read=convert.base64-encode/resource=XmlEncoderTest.php">]><scan>&test;</scan>', 'xml');
  204. chdir($oldCwd);
  205. $this->fail('No exception was thrown.');
  206. } catch (\Exception $e) {
  207. chdir($oldCwd);
  208. if (!$e instanceof \InvalidArgumentException) {
  209. $this->fail('Expected InvalidArgumentException');
  210. }
  211. }
  212. }
  213. protected function getXmlSource()
  214. {
  215. return '<?xml version="1.0"?>'."\n".
  216. '<response>'.
  217. '<foo><![CDATA[foo]]></foo>'.
  218. '<bar><![CDATA[a]]></bar><bar><![CDATA[b]]></bar>'.
  219. '<baz><key><![CDATA[val]]></key><key2><![CDATA[val]]></key2><item key="A B"><![CDATA[bar]]></item>'.
  220. '<Barry><FooBar id="1"><Baz><![CDATA[Ed]]></Baz></FooBar></Barry></baz>'.
  221. '<qux>1</qux>'.
  222. '</response>'."\n";
  223. }
  224. protected function getObject()
  225. {
  226. $obj = new Dummy;
  227. $obj->foo = 'foo';
  228. $obj->bar = array('a', 'b');
  229. $obj->baz = array('key' => 'val', 'key2' => 'val', 'A B' => 'bar', "Barry" => array('FooBar' => array("Baz"=>"Ed", "@id"=>1)));
  230. $obj->qux = "1";
  231. return $obj;
  232. }
  233. }