Skip to content

Commit

Permalink
bug symfony#21671 [Serializer] Xml encoder throws exception for valid…
Browse files Browse the repository at this point in the history
… data (gr1ev0us)

This PR was squashed before being merged into the 2.7 branch (closes symfony#21671).

Discussion
----------

[Serializer] Xml encoder throws exception for valid data

| Q             | A
| ------------- | ---
| Branch?       |  2.7
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | symfony#21617
| License       | MIT
| Doc PR        | None

symfony#21617  Xml encoder throws exception for valid data

- add tests for bool and object encoding
- fix encoding for object in array and field

Commits
-------

5c2d4c6 [Serializer] Xml encoder throws exception for valid data
  • Loading branch information
fabpot committed Mar 5, 2017
2 parents 979adb9 + 1a1c1d1 commit 6c12aa8
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 2 deletions.
7 changes: 5 additions & 2 deletions Encoder/XmlEncoder.php
Expand Up @@ -369,7 +369,10 @@ private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null)
if (is_array($data) || ($data instanceof \Traversable && !$this->serializer->supportsNormalization($data, $this->format))) {
foreach ($data as $key => $data) {
//Ah this is the magic @ attribute types.
if (0 === strpos($key, '@') && is_scalar($data) && $this->isElementNameValid($attributeName = substr($key, 1))) {
if (0 === strpos($key, '@') && $this->isElementNameValid($attributeName = substr($key, 1))) {
if (!is_scalar($data)) {
$data = $this->serializer->normalize($data, $this->format, $this->context);
}
$parentNode->setAttribute($attributeName, $data);
} elseif ($key === '#') {
$append = $this->selectNodeType($parentNode, $data);
Expand Down Expand Up @@ -474,7 +477,7 @@ private function selectNodeType(\DOMNode $node, $val)
} elseif ($val instanceof \Traversable) {
$this->buildXml($node, $val);
} elseif (is_object($val)) {
return $this->buildXml($node, $this->serializer->normalize($val, $this->format, $this->context));
return $this->selectNodeType($node, $this->serializer->normalize($val, $this->format, $this->context));
} elseif (is_numeric($val)) {
return $this->appendText($node, (string) $val);
} elseif (is_string($val) && $this->needsCdataWrapping($val)) {
Expand Down
91 changes: 91 additions & 0 deletions Tests/Encoder/XmlEncoderTest.php
Expand Up @@ -19,11 +19,17 @@
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
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();
Expand Down Expand Up @@ -529,4 +535,89 @@ protected function getObject()

return $obj;
}

public function testEncodeXmlWithBoolValue()
{
$expectedXml = <<<'XML'
<?xml version="1.0"?>
<response><foo>1</foo><bar>0</bar></response>
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('<?xml version="1.0"?>
<response><dateTime>%s</dateTime></response>
', $this->exampleDateTimeString);
}

/**
* @return string
*/
private function createXmlWithDateTimeField()
{
return sprintf('<?xml version="1.0"?>
<response><foo dateTime="%s"/></response>
', $this->exampleDateTimeString);
}
}

0 comments on commit 6c12aa8

Please sign in to comment.