8000 [Serializer] Add XmlEncoder::CDATA_WRAPPING_PATTERN context option · symfony/symfony@105a952 · GitHub
[go: up one dir, main page]

Skip to content

Commit 105a952

Browse files
committed
[Serializer] Add XmlEncoder::CDATA_WRAPPING_PATTERN context option
1 parent a2d03c5 commit 105a952

File tree

5 files changed

+38
-4
lines changed

5 files changed

+38
-4
lines changed

src/Symfony/Component/Serializer/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ CHANGELOG
99
* Add `Default` and "class name" default groups
1010
* Add `AbstractNormalizer::FILTER_BOOL` context option
1111
* Add `CamelCaseToSnakeCaseNameConverter::REQUIRE_SNAKE_CASE_PROPERTIES` context option
12+
* Add `XmlEncoder::CDATA_WRAPPING_PATTERN` context option
1213

1314
7.0
1415
---

src/Symfony/Component/Serializer/Context/Encoder/XmlEncoderContextBuilder.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,12 @@ public function withCdataWrapping(?bool $cdataWrapping): static
152152
{
153153
return $this->with(XmlEncoder::CDATA_WRAPPING, $cdataWrapping);
154154
}
155+
156+
/**
157+
* Configures the pattern used to evaluate if a CDATA section should be added.
158+
*/
159+
public function withCdataWrappingPattern(?string $cdataWrappingPattern): static
160+
{
161+
return $this->with(XmlEncoder::CDATA_WRAPPING_PATTERN, $cdataWrappingPattern);
162+
}
155163
}

src/Symfony/Component/Serializer/Encoder/XmlEncoder.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwa
5959
public const TYPE_CAST_ATTRIBUTES = 'xml_type_cast_attributes';
6060
public const VERSION = 'xml_version';
6161
public const CDATA_WRAPPING = 'cdata_wrapping';
62+
public const CDATA_WRAPPING_PATTERN = 'cdata_wrapping_pattern';
6263

6364
private array $defaultContext = [
6465
self::AS_COLLECTION => false,
@@ -70,6 +71,7 @@ class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwa
7071
self::ROOT_NODE_NAME => 'response',
7172
self::TYPE_CAST_ATTRIBUTES => true,
7273
self::CDATA_WRAPPING => true,
74+
self::CDATA_WRAPPING_PATTERN => '/[<>&]/',
7375
];
7476

7577
public function __construct(array $defaultContext = [])
@@ -406,7 +408,7 @@ private function buildXml(\DOMNode $parentNode, mixed $data, string $format, arr
406408
return $this->appendNode($parentNode, $data, $format, $context, 'data');
407409
}
408410

409-
throw new NotEncodableValueException('An unexpected value could not be serialized: '.(!\is_resource($data) ? var_export($data, true) : sprintf('%s resource', get_resource_type($data))));
411+
throw new NotEncodableValueException('An unexpected value could not be serialized: '.(!\is_resource($data) ? var_export($data, true) : sprintf('"%s" resource', get_resource_type($data))));
410412
}
411413

412414
/**
@@ -433,7 +435,10 @@ private function appendNode(\DOMNode $parentNode, mixed $data, string $format, a
433435
*/
434436
private function needsCdataWrapping(string $val, array $context): bool
435437
{
436-
return ($context[self::CDATA_WRAPPING] ?? $this->defaultContext[self::CDATA_WRAPPING]) && preg_match('/[<>&]/', $val);
438+
return
439+
($context[self::CDATA_WRAPPING] ?? $this->defaultContext[self::CDATA_WRAPPING])
440+
&& preg_match($context[self::CDATA_WRAPPING_PATTERN] ?? $this->defaultContext[self::CDATA_WRAPPING_PATTERN], $val)
441+
;
437442
}
438443

439444
/**

src/Symfony/Component/Serializer/Tests/Context/Encoder/XmlEncoderContextBuilderTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public function testWithers(array $values)
4646
->withTypeCastAttributes($values[XmlEncoder::TYPE_CAST_ATTRIBUTES])
4747
->withVersion($values[XmlEncoder::VERSION])
4848
->withCdataWrapping($values[XmlEncoder::CDATA_WRAPPING])
49+
->withCdataWrappingPattern($values[XmlEncoder::CDATA_WRAPPING_PATTERN])
4950
->toArray();
5051

5152
$this->assertSame($values, $context);
@@ -67,6 +68,7 @@ public static function withersDataProvider(): iterable
6768
XmlEncoder::TYPE_CAST_ATTRIBUTES => true,
6869
XmlEncoder::VERSION => '1.0',
6970
XmlEncoder::CDATA_WRAPPING => false,
71+
XmlEncoder::CDATA_WRAPPING_PATTERN => '/[<>&"\']/',
7072
]];
7173

7274
yield 'With null values' => [[
@@ -83,6 +85,7 @@ public static function withersDataProvider(): iterable
8385
XmlEncoder::TYPE_CAST_ATTRIBUTES => null,
8486
XmlEncoder::VERSION => null,
8587
XmlEncoder::CDATA_WRAPPING => null,
88+
XmlEncoder::CDATA_WRAPPING_PATTERN => null,
8689
]];
8790
}
8891
}

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

Lines changed: 19 additions & 2 deletions
-
$this->expectExceptionMessage('An unexpected value could not be serialized: stream resource');
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ public function testEncodeRootAttributes()
231231
$this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
232232
}
233233

234-
public function testEncodeCdataWrapping()
234+
public function testEncodeCdataWrappingWithDefaultPattern()
235235
{
236236
$array = [
237237
'firstname' => 'Paul & Martha <or Me>',
@@ -243,6 +243,23 @@ public function testEncodeCdataWrapping()
243243
$this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
244244
}
245245

246+
public function testEncodeCdataWrappingWithCustomPattern()
247+
{
248+
$array = [
249+
'lastname' => 'O\'Donnel',
250+
];
251+
252+
$expectedUnwrapped = '<?xml version="1.0"?>'."\n".
253+
'<response><lastname>O\'Donnel</lastname></response>'."\n";
254+
255+
$this->assertEquals($expectedUnwrapped, $this->encoder->encode($array, 'xml'));
256+
257+
$expectedWrapped = '<?xml version="1.0"?>'."\n".
258+
'<response><lastname><![CDATA[O\'Donnel]]></lastname></response>'."\n";
259+
260+
$this->assertEquals($expectedWrapped, $this->encoder->encode($array, 'xml', ['cdata_wrapping_pattern' => '/[<>&"\']/']));
261+
}
262+
246263
public function testEnableCdataWrapping()
247264
{
248265
$array = [
@@ -895,7 +912,7 @@ public function testEncodeXmlWithDateTimeObjectField()
895912
public function testNotEncodableValueExceptionMessageForAResource()
896913
{
897914
$this->expectException(NotEncodableValueException::class);
898
915+
$this->expectExceptionMessage('An unexpected value could not be serialized: "stream" resource');
899916

900917
(new XmlEncoder())->encode(tmpfile(), 'xml');
901918
}

0 commit comments

Comments
 (0)
0