Skip to content

Commit 6c12aa8

Browse files
committed
bug #21671 [Serializer] Xml encoder throws exception for valid data (gr1ev0us)
This PR was squashed before being merged into the 2.7 branch (closes #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 | #21617 | License | MIT | Doc PR | None #21617 Xml encoder throws exception for valid data - add tests for bool and object encoding - fix encoding for object in array and field Commits ------- 5c2d4c671e [Serializer] Xml encoder throws exception for valid data
2 parents 979adb9 + 1a1c1d1 commit 6c12aa8

File tree

2 files changed

+96
-2
lines changed

2 files changed

+96
-2
lines changed

Encoder/XmlEncoder.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,10 @@ private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null)
369369
if (is_array($data) || ($data instanceof \Traversable && !$this->serializer->supportsNormalization($data, $this->format))) {
370370
foreach ($data as $key => $data) {
371371
//Ah this is the magic @ attribute types.
372-
if (0 === strpos($key, '@') && is_scalar($data) && $this->isElementNameValid($attributeName = substr($key, 1))) {
372+
if (0 === strpos($key, '@') && $this->isElementNameValid($attributeName = substr($key, 1))) {
373+
if (!is_scalar($data)) {
374+
$data = $this->serializer->normalize($data, $this->format, $this->context);
375+
}
373376
$parentNode->setAttribute($attributeName, $data);
374377
} elseif ($key === '#') {
375378
$append = $this->selectNodeType($parentNode, $data);
@@ -474,7 +477,7 @@ private function selectNodeType(\DOMNode $node, $val)
474477
} elseif ($val instanceof \Traversable) {
475478
$this->buildXml($node, $val);
476479
} elseif (is_object($val)) {
477-
return $this->buildXml($node, $this->serializer->normalize($val, $this->format, $this->context));
480+
return $this->selectNodeType($node, $this->serializer->normalize($val, $this->format, $this->context));
478481
} elseif (is_numeric($val)) {
479482
return $this->appendText($node, (string) $val);
480483
} elseif (is_string($val) && $this->needsCdataWrapping($val)) {

Tests/Encoder/XmlEncoderTest.php

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,17 @@
1919
use Symfony\Component\Serializer\Serializer;
2020
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
2121
use Symfony\Component\Serializer\Normalizer\CustomNormalizer;
22+
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
2223

2324
class XmlEncoderTest extends TestCase
2425
{
26+
/**
27+
* @var XmlEncoder
28+
*/
2529
private $encoder;
2630

31+
private $exampleDateTimeString = '2017-02-19T15:16:08+0300';
32+
2733
protected function setUp()
2834
{
2935
$this->encoder = new XmlEncoder();
@@ -529,4 +535,89 @@ protected function getObject()
529535

530536
return $obj;
531537
}
538+
539+
public function testEncodeXmlWithBoolValue()
540+
{
541+
$expectedXml = <<<'XML'
542+
<?xml version="1.0"?>
543+
<response><foo>1</foo><bar>0</bar></response>
544+
545+
XML;
546+
547+
$actualXml = $this->encoder->encode(array('foo' => true, 'bar' => false), 'xml');
548+
549+
$this->assertEquals($expectedXml, $actualXml);
550+
}
551+
552+
public function testEncodeXmlWithDateTimeObjectValue()
553+
{
554+
$xmlEncoder = $this->createXmlEncoderWithDateTimeNormalizer();
555+
556+
$actualXml = $xmlEncoder->encode(array('dateTime' => new \DateTime($this->exampleDateTimeString)), 'xml');
557+
558+
$this->assertEquals($this->createXmlWithDateTime(), $actualXml);
559+
}
560+
561+
public function testEncodeXmlWithDateTimeObjectField()
562+
{
563+
$xmlEncoder = $this->createXmlEncoderWithDateTimeNormalizer();
564+
565+
$actualXml = $xmlEncoder->encode(array('foo' => array('@dateTime' => new \DateTime($this->exampleDateTimeString))), 'xml');
566+
567+
$this->assertEquals($this->createXmlWithDateTimeField(), $actualXml);
568+
}
569+
570+
/**
571+
* @return XmlEncoder
572+
*/
573+
private function createXmlEncoderWithDateTimeNormalizer()
574+
{
575+
$encoder = new XmlEncoder();
576+
$serializer = new Serializer(array($this->createMockDateTimeNormalizer()), array('xml' => new XmlEncoder()));
577+
$encoder->setSerializer($serializer);
578+
579+
return $encoder;
580+
}
581+
582+
/**
583+
* @return \PHPUnit_Framework_MockObject_MockObject|NormalizerInterface
584+
*/
585+
private function createMockDateTimeNormalizer()
586+
{
587+
$mock = $this->getMockBuilder('\Symfony\Component\Serializer\Normalizer\CustomNormalizer')->getMock();
588+
589+
$mock
590+
->expects($this->once())
591+
->method('normalize')
592+
->with(new \DateTime($this->exampleDateTimeString), 'xml', array())
593+
->willReturn($this->exampleDateTimeString);
594+
595+
$mock
596+
->expects($this->once())
597+
->method('supportsNormalization')
598+
->with(new \DateTime($this->exampleDateTimeString), 'xml')
599+
->willReturn(true);
600+
601+
return $mock;
602+
}
603+
604+
/**
605+
* @return string
606+
*/
607+
private function createXmlWithDateTime()
608+
{
609+
return sprintf('<?xml version="1.0"?>
610+
<response><dateTime>%s</dateTime></response>
611+
', $this->exampleDateTimeString);
612+
}
613+
614+
/**
615+
* @return string
616+
*/
617+
private function createXmlWithDateTimeField()
618+
{
619+
return sprintf('<?xml version="1.0"?>
620+
<response><foo dateTime="%s"/></response>
621+
', $this->exampleDateTimeString);
622+
}
532623
}

0 commit comments

Comments
 (0)