From c679878917f0a1cec8ce5415cb024d3766fbf639 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Thu, 20 Jul 2023 08:56:42 +0200 Subject: [PATCH] Add dom cdata helpers --- docs/dom.md | 47 +++++++++++++++++++ src/Xml/Dom/Assert/assert_cdata.php | 18 +++++++ src/Xml/Dom/Builder/cdata.php | 31 ++++++++++++ src/Xml/Dom/Predicate/is_cdata.php | 16 +++++++ src/bootstrap.php | 3 ++ tests/Xml/Dom/Assert/AssertCDataTest.php | 42 +++++++++++++++++ tests/Xml/Dom/Builder/CdataTest.php | 34 ++++++++++++++ tests/Xml/Dom/Builder/ChildrenTest.php | 19 +++++++- tests/Xml/Dom/Builder/NodesTest.php | 2 +- tests/Xml/Dom/Manipulator/Node/RenameTest.php | 1 - tests/Xml/Dom/Predicate/IsCDataTest.php | 36 ++++++++++++++ 11 files changed, 246 insertions(+), 3 deletions(-) create mode 100644 src/Xml/Dom/Assert/assert_cdata.php create mode 100644 src/Xml/Dom/Builder/cdata.php create mode 100644 src/Xml/Dom/Predicate/is_cdata.php create mode 100644 tests/Xml/Dom/Assert/AssertCDataTest.php create mode 100644 tests/Xml/Dom/Builder/CdataTest.php create mode 100644 tests/Xml/Dom/Predicate/IsCDataTest.php diff --git a/docs/dom.md b/docs/dom.md index 96d26db..246605e 100644 --- a/docs/dom.md +++ b/docs/dom.md @@ -75,6 +75,21 @@ try { } ``` +#### assert_cdata + +Assert if a node is of type `DOMCdataSection`. + +```php +use Psl\Type\Exception\AssertException; +use function VeeWee\Xml\Dom\Assert\assert_cdata; + +try { + assert_cdata($someNode) +} catch (AssertException $e) { + // Deal with it +} +``` + #### assert_document Assert if a node is of type `DOMDocument`. @@ -205,6 +220,26 @@ element('foo', ``` +#### cdata + +Operates on a `DOMNode` and creates a `DOMCdataSection`. +It can contain a set of configurators that can be used to dynamically change the cdata's contents. + +```php +use function VeeWee\Xml\Dom\Builder\attribute; +use function VeeWee\Xml\Dom\Builder\element; +use function VeeWee\Xml\Dom\Builder\cdata; +use function VeeWee\Xml\Dom\Builder\children; + +element('hello', children( + cdata('world') +)); +``` + +```xml +world]]> +``` + #### children Operates on a `DOMNode` and attaches multiple child nodes. @@ -1157,6 +1192,18 @@ if (is_attribute($someNode)) { } ``` +#### is_cdata + +Checks if a node is of type `DOMCdataSection`. + +```php +use function VeeWee\Xml\Dom\Predicate\is_cdata; + +if (is_cdata($someNode)) { + // ... +} +``` + #### is_default_xmlns_attribute Checks if a node is of type `DOMNameSpaceNode` and is the default xmlns. diff --git a/src/Xml/Dom/Assert/assert_cdata.php b/src/Xml/Dom/Assert/assert_cdata.php new file mode 100644 index 0000000..de96d00 --- /dev/null +++ b/src/Xml/Dom/Assert/assert_cdata.php @@ -0,0 +1,18 @@ +assert($node); +} diff --git a/src/Xml/Dom/Builder/cdata.php b/src/Xml/Dom/Builder/cdata.php new file mode 100644 index 0000000..186e387 --- /dev/null +++ b/src/Xml/Dom/Builder/cdata.php @@ -0,0 +1,31 @@ + $configurators + * + * @return \Closure(DOMNode): DOMCdataSection + */ +function cdata(string $data, ...$configurators): Closure +{ + return static function (DOMNode $node) use ($data, $configurators): DOMCdataSection { + $document = is_document($node) ? $node : $node->ownerDocument; + Assert::isInstanceOf($document, DOMDocument::class, 'Can not create cdata without a DOM document.'); + + return assert_cdata( + configure(...$configurators)($document->createCDATASection($data)) + ); + }; +} diff --git a/src/Xml/Dom/Predicate/is_cdata.php b/src/Xml/Dom/Predicate/is_cdata.php new file mode 100644 index 0000000..ee4884d --- /dev/null +++ b/src/Xml/Dom/Predicate/is_cdata.php @@ -0,0 +1,16 @@ +expectException(AssertException::class); + } + + $actual = assert_cdata($node); + static::assertSame($node, $actual); + } + + public function provideTestCases() + { + $doc = Document::fromXmlString( + <<HELLO + EOXML + )->toUnsafeDocument(); + + yield [$doc, false]; + yield [$doc->documentElement, false]; + yield [$doc->documentElement->firstChild, true]; + yield [null, false]; + } +} diff --git a/tests/Xml/Dom/Builder/CdataTest.php b/tests/Xml/Dom/Builder/CdataTest.php new file mode 100644 index 0000000..e2915d6 --- /dev/null +++ b/tests/Xml/Dom/Builder/CdataTest.php @@ -0,0 +1,34 @@ +hello')($doc); + + static::assertInstanceOf(DOMCdataSection::class, $node); + static::assertSame($data, $node->textContent); + static::assertSame(xml_string()($node), ''); + } + + public function test_it_can_build_cdata_with_configurators(): void + { + $doc = new DOMDocument(); + $node = cdata($data = 'hello', identity())($doc); + + static::assertInstanceOf(DOMCdataSection::class, $node); + static::assertSame($data, $node->textContent); + } +} diff --git a/tests/Xml/Dom/Builder/ChildrenTest.php b/tests/Xml/Dom/Builder/ChildrenTest.php index 5d38300..6f24d5c 100644 --- a/tests/Xml/Dom/Builder/ChildrenTest.php +++ b/tests/Xml/Dom/Builder/ChildrenTest.php @@ -6,8 +6,10 @@ use DOMDocument; use PHPUnit\Framework\TestCase; +use function VeeWee\Xml\Dom\Builder\cdata; use function VeeWee\Xml\Dom\Builder\children; use function VeeWee\Xml\Dom\Builder\element; +use function VeeWee\Xml\Dom\Mapper\xml_string; final class ChildrenTest extends TestCase { @@ -27,7 +29,6 @@ public function test_it_can_build_document_children(): void static::assertSame('world2', $children->item(1)->nodeName); } - public function test_it_can_build_an_element_with_children(): void { $doc = new DOMDocument(); @@ -48,4 +49,20 @@ public function test_it_can_build_an_element_with_children(): void static::assertSame('world1', $children->item(0)->nodeName); static::assertSame('world2', $children->item(1)->nodeName); } + + public function test_it_can_add_cdata(): void + { + $doc = new DOMDocument(); + $node = element( + 'hello', + children( + cdata('world'), + ) + )($doc); + + static::assertXmlStringEqualsXmlString( + 'world]]>', + xml_string()($node) + ); + } } diff --git a/tests/Xml/Dom/Builder/NodesTest.php b/tests/Xml/Dom/Builder/NodesTest.php index 36cb1d7..810cf40 100644 --- a/tests/Xml/Dom/Builder/NodesTest.php +++ b/tests/Xml/Dom/Builder/NodesTest.php @@ -20,7 +20,7 @@ public function test_it_can_build_nodes(): void static fn (DOMDocument $doc): array => [ element('many1')($doc), element('many2')($doc), - ] + ], )($doc); static::assertCount(4, $nodes); diff --git a/tests/Xml/Dom/Manipulator/Node/RenameTest.php b/tests/Xml/Dom/Manipulator/Node/RenameTest.php index 4337d90..83f41bf 100644 --- a/tests/Xml/Dom/Manipulator/Node/RenameTest.php +++ b/tests/Xml/Dom/Manipulator/Node/RenameTest.php @@ -13,7 +13,6 @@ use function VeeWee\Xml\Dom\Locator\document_element; use function VeeWee\Xml\Dom\Manipulator\Node\remove_namespace; use function VeeWee\Xml\Dom\Manipulator\Node\rename; -use function VeeWee\Xml\Dom\Mapper\xml_string; use function VeeWee\Xml\Dom\Xpath\Configurator\namespaces; final class RenameTest extends TestCase diff --git a/tests/Xml/Dom/Predicate/IsCDataTest.php b/tests/Xml/Dom/Predicate/IsCDataTest.php new file mode 100644 index 0000000..779d834 --- /dev/null +++ b/tests/Xml/Dom/Predicate/IsCDataTest.php @@ -0,0 +1,36 @@ +HELLO + EOXML + )->toUnsafeDocument(); + + yield [$doc, false]; + yield [$doc->documentElement, false]; + yield [$doc->documentElement->firstChild, true]; + } +}