PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php

https://github.com/jdewit/symfony
PHP | 363 lines | 287 code | 64 blank | 12 comment | 1 complexity | f9a8d563c3d1131bf66cc0ec37e7156a MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Serializer\Tests\Encoder;
  11. use Symfony\Component\Serializer\Tests\Fixtures\Dummy;
  12. use Symfony\Component\Serializer\Tests\Fixtures\ScalarDummy;
  13. use Symfony\Component\Serializer\Encoder\XmlEncoder;
  14. use Symfony\Component\Serializer\Serializer;
  15. use Symfony\Component\Serializer\Exception\UnexpectedValueException;
  16. use Symfony\Component\Serializer\Normalizer\CustomNormalizer;
  17. class XmlEncoderTest extends \PHPUnit_Framework_TestCase
  18. {
  19. protected function setUp()
  20. {
  21. $this->encoder = new XmlEncoder;
  22. $serializer = new Serializer(array(new CustomNormalizer()), array('xml' => new XmlEncoder()));
  23. $this->encoder->setSerializer($serializer);
  24. }
  25. public function testEncodeScalar()
  26. {
  27. $obj = new ScalarDummy;
  28. $obj->xmlFoo = "foo";
  29. $expected = '<?xml version="1.0"?>'."\n".
  30. '<response>foo</response>'."\n";
  31. $this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
  32. }
  33. public function testSetRootNodeName()
  34. {
  35. $obj = new ScalarDummy;
  36. $obj->xmlFoo = "foo";
  37. $this->encoder->setRootNodeName('test');
  38. $expected = '<?xml version="1.0"?>'."\n".
  39. '<test>foo</test>'."\n";
  40. $this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
  41. }
  42. /**
  43. * @expectedException UnexpectedValueException
  44. * @expectedExceptionMessage Document types are not allowed.
  45. */
  46. public function testDocTypeIsNotAllowed()
  47. {
  48. $this->encoder->decode('<?xml version="1.0"?><!DOCTYPE foo><foo></foo>', 'foo');
  49. }
  50. public function testAttributes()
  51. {
  52. $obj = new ScalarDummy;
  53. $obj->xmlFoo = array(
  54. 'foo-bar' => array(
  55. '@id' => 1,
  56. '@name' => 'Bar'
  57. ),
  58. 'Foo' => array(
  59. 'Bar' => "Test",
  60. '@Type' => 'test'
  61. ),
  62. 'föo_bär' => 'a',
  63. "Bar" => array(1,2,3),
  64. 'a' => 'b',
  65. );
  66. $expected = '<?xml version="1.0"?>'."\n".
  67. '<response>'.
  68. '<foo-bar id="1" name="Bar"/>'.
  69. '<Foo Type="test"><Bar>Test</Bar></Foo>'.
  70. '<föo_bär>a</föo_bär>'.
  71. '<Bar>1</Bar>'.
  72. '<Bar>2</Bar>'.
  73. '<Bar>3</Bar>'.
  74. '<a>b</a>'.
  75. '</response>'."\n";
  76. $this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
  77. }
  78. public function testElementNameValid()
  79. {
  80. $obj = new ScalarDummy;
  81. $obj->xmlFoo = array(
  82. 'foo-bar' => 'a',
  83. 'foo_bar' => 'a',
  84. 'föo_bär' => 'a',
  85. );
  86. $expected = '<?xml version="1.0"?>'."\n".
  87. '<response>'.
  88. '<foo-bar>a</foo-bar>'.
  89. '<foo_bar>a</foo_bar>'.
  90. '<föo_bär>a</föo_bär>'.
  91. '</response>'."\n";
  92. $this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
  93. }
  94. public function testEncodeSimpleXML()
  95. {
  96. $xml = simplexml_load_string('<firstname>Peter</firstname>');
  97. $array = array('person' => $xml);
  98. $expected = '<?xml version="1.0"?>'."\n".
  99. '<response><person><firstname>Peter</firstname></person></response>'."\n";
  100. $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
  101. }
  102. public function testEncodeXmlAttributes()
  103. {
  104. $xml = simplexml_load_string('<firstname>Peter</firstname>');
  105. $array = array('person' => $xml);
  106. $expected = '<?xml version="1.1" encoding="utf-8" standalone="yes"?>'."\n".
  107. '<response><person><firstname>Peter</firstname></person></response>'."\n";
  108. $context = array(
  109. 'xml_version' => '1.1',
  110. 'xml_encoding' => 'utf-8',
  111. 'xml_standalone' => true,
  112. );
  113. $this->assertSame($expected, $this->encoder->encode($array, 'xml', $context));
  114. }
  115. public function testEncodeScalarRootAttributes()
  116. {
  117. $array = array(
  118. '#' => 'Paul',
  119. '@gender' => 'm'
  120. );
  121. $expected = '<?xml version="1.0"?>'."\n".
  122. '<response gender="m">Paul</response>'."\n";
  123. $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
  124. }
  125. public function testEncodeRootAttributes()
  126. {
  127. $array = array(
  128. 'firstname' => 'Paul',
  129. '@gender' => 'm'
  130. );
  131. $expected = '<?xml version="1.0"?>'."\n".
  132. '<response gender="m"><firstname>Paul</firstname></response>'."\n";
  133. $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
  134. }
  135. public function testEncodeCdataWrapping()
  136. {
  137. $array = array(
  138. 'firstname' => 'Paul <or Me>',
  139. );
  140. $expected = '<?xml version="1.0"?>'."\n".
  141. '<response><firstname><![CDATA[Paul <or Me>]]></firstname></response>'."\n";
  142. $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
  143. }
  144. public function testEncodeScalarWithAttribute()
  145. {
  146. $array = array(
  147. 'person' => array('@gender' => 'M', '#' => 'Peter'),
  148. );
  149. $expected = '<?xml version="1.0"?>'."\n".
  150. '<response><person gender="M">Peter</person></response>'."\n";
  151. $this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
  152. }
  153. public function testDecodeScalar()
  154. {
  155. $source = '<?xml version="1.0"?>'."\n".
  156. '<response>foo</response>'."\n";
  157. $this->assertEquals('foo', $this->encoder->decode($source, 'xml'));
  158. }
  159. public function testEncode()
  160. {
  161. $source = $this->getXmlSource();
  162. $obj = $this->getObject();
  163. $this->assertEquals($source, $this->encoder->encode($obj, 'xml'));
  164. }
  165. public function testEncodeSerializerXmlRootNodeNameOption()
  166. {
  167. $options = array('xml_root_node_name' => 'test');
  168. $this->encoder = new XmlEncoder;
  169. $serializer = new Serializer(array(), array('xml' => new XmlEncoder()));
  170. $this->encoder->setSerializer($serializer);
  171. $array = array(
  172. 'person' => array('@gender' => 'M', '#' => 'Peter'),
  173. );
  174. $expected = '<?xml version="1.0"?>'."\n".
  175. '<test><person gender="M">Peter</person></test>'."\n";
  176. $this->assertEquals($expected, $serializer->serialize($array, 'xml', $options));
  177. }
  178. public function testDecode()
  179. {
  180. $source = $this->getXmlSource();
  181. $obj = $this->getObject();
  182. $this->assertEquals(get_object_vars($obj), $this->encoder->decode($source, 'xml'));
  183. }
  184. public function testDecodeScalarWithAttribute()
  185. {
  186. $source = '<?xml version="1.0"?>'."\n".
  187. '<response><person gender="M">Peter</person></response>'."\n";
  188. $expected = array(
  189. 'person' => array('@gender' => 'M', '#' => 'Peter'),
  190. );
  191. $this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
  192. }
  193. public function testDecodeScalarRootAttributes()
  194. {
  195. $source = '<?xml version="1.0"?>'."\n".
  196. '<person gender="M">Peter</person>'."\n";
  197. $expected = array(
  198. '#' => 'Peter',
  199. '@gender' => 'M'
  200. );
  201. $this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
  202. }
  203. public function testDecodeRootAttributes()
  204. {
  205. $source = '<?xml version="1.0"?>'."\n".
  206. '<person gender="M"><firstname>Peter</firstname><lastname>Mac Calloway</lastname></person>'."\n";
  207. $expected = array(
  208. 'firstname' => 'Peter',
  209. 'lastname' => 'Mac Calloway',
  210. '@gender' => 'M'
  211. );
  212. $this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
  213. }
  214. public function testDecodeArray()
  215. {
  216. $source = '<?xml version="1.0"?>'."\n".
  217. '<response>'.
  218. '<people>'.
  219. '<person><firstname>Benjamin</firstname><lastname>Alexandre</lastname></person>'.
  220. '<person><firstname>Damien</firstname><lastname>Clay</lastname></person>'.
  221. '</people>'.
  222. '</response>'."\n";
  223. $expected = array(
  224. 'people' => array('person' => array(
  225. array('firstname' => 'Benjamin', 'lastname' => 'Alexandre'),
  226. array('firstname' => 'Damien', 'lastname' => 'Clay')
  227. ))
  228. );
  229. $this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
  230. }
  231. public function testDecodeWithoutItemHash()
  232. {
  233. $obj = new ScalarDummy;
  234. $obj->xmlFoo = array(
  235. 'foo-bar' => array(
  236. '@key' => "value",
  237. 'item' => array("@key" => 'key', "key-val" => 'val')
  238. ),
  239. 'Foo' => array(
  240. 'Bar' => "Test",
  241. '@Type' => 'test'
  242. ),
  243. 'föo_bär' => 'a',
  244. "Bar" => array(1,2,3),
  245. 'a' => 'b',
  246. );
  247. $expected = array(
  248. 'foo-bar' => array(
  249. '@key' => "value",
  250. 'key' => array('@key' => 'key', "key-val" => 'val')
  251. ),
  252. 'Foo' => array(
  253. 'Bar' => "Test",
  254. '@Type' => 'test'
  255. ),
  256. 'föo_bär' => 'a',
  257. "Bar" => array(1,2,3),
  258. 'a' => 'b',
  259. );
  260. $xml = $this->encoder->encode($obj, 'xml');
  261. $this->assertEquals($expected, $this->encoder->decode($xml, 'xml'));
  262. }
  263. public function testPreventsComplexExternalEntities()
  264. {
  265. $oldCwd = getcwd();
  266. chdir(__DIR__);
  267. try {
  268. $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');
  269. chdir($oldCwd);
  270. $this->fail('No exception was thrown.');
  271. } catch (\Exception $e) {
  272. chdir($oldCwd);
  273. if (!$e instanceof UnexpectedValueException) {
  274. $this->fail('Expected UnexpectedValueException');
  275. }
  276. }
  277. }
  278. protected function getXmlSource()
  279. {
  280. return '<?xml version="1.0"?>'."\n".
  281. '<response>'.
  282. '<foo>foo</foo>'.
  283. '<bar>a</bar><bar>b</bar>'.
  284. '<baz><key>val</key><key2>val</key2><item key="A B">bar</item>'.
  285. '<item><title>title1</title></item><item><title>title2</title></item>'.
  286. '<Barry><FooBar id="1"><Baz>Ed</Baz></FooBar></Barry></baz>'.
  287. '<qux>1</qux>'.
  288. '</response>'."\n";
  289. }
  290. protected function getObject()
  291. {
  292. $obj = new Dummy;
  293. $obj->foo = 'foo';
  294. $obj->bar = array('a', 'b');
  295. $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)));
  296. $obj->qux = "1";
  297. return $obj;
  298. }
  299. }