From ed1677e14d740e91d67c4d115f2068d17fce8b86 Mon Sep 17 00:00:00 2001 From: Muhammad Imangazaliev Date: Tue, 21 Jan 2020 08:12:36 +0300 Subject: [PATCH] Add support of document fragments --- src/DiDom/Document.php | 8 +++ src/DiDom/DocumentFragment.php | 34 +++++++++++ src/DiDom/Node.php | 30 +++++----- tests/DocumentFragmentTest.php | 30 ++++++++++ tests/DocumentTest.php | 12 +++- tests/ElementTest.php | 106 ++++++++++++++++++++++++++++++++- 6 files changed, 203 insertions(+), 17 deletions(-) create mode 100644 src/DiDom/DocumentFragment.php create mode 100644 tests/DocumentFragmentTest.php diff --git a/src/DiDom/Document.php b/src/DiDom/Document.php index 03d3d5b..8bafc5d 100644 --- a/src/DiDom/Document.php +++ b/src/DiDom/Document.php @@ -164,6 +164,14 @@ public function createCdataSection($data) return new Element(new DOMCdataSection($data)); } + /** + * @return DocumentFragment + */ + public function createDocumentFragment() + { + return new DocumentFragment($this->document->createDocumentFragment()); + } + /** * Adds a new child at the end of the children. * diff --git a/src/DiDom/DocumentFragment.php b/src/DiDom/DocumentFragment.php new file mode 100644 index 0000000..35c615f --- /dev/null +++ b/src/DiDom/DocumentFragment.php @@ -0,0 +1,34 @@ +setNode($documentFragment); + } + + /** + * Append raw XML data. + * + * @param string $data + */ + public function appendXml($data) + { + $this->node->appendXML($data); + } +} diff --git a/src/DiDom/Node.php b/src/DiDom/Node.php index 7544ebf..2b35d32 100644 --- a/src/DiDom/Node.php +++ b/src/DiDom/Node.php @@ -6,6 +6,7 @@ use DOMCdataSection; use DOMComment; use DOMDocument; +use DOMDocumentFragment; use DOMElement; use DOMNode; use DOMText; @@ -21,14 +22,14 @@ abstract class Node /** * The DOM element instance. * - * @var DOMElement|DOMText|DOMComment|DOMCdataSection + * @var DOMElement|DOMText|DOMComment|DOMCdataSection|DOMDocumentFragment */ protected $node; /** * Adds a new child at the start of the children. * - * @param Element|DOMNode|array $nodes The prepended child + * @param Node|DOMNode|array $nodes The prepended child * * @return Element|Element[] * @@ -67,7 +68,7 @@ public function prependChild($nodes) /** * Adds a new child at the end of the children. * - * @param Element|DOMNode|array $nodes The appended child + * @param Node|DOMNode|array $nodes The appended child * * @return Element|Element[] * @@ -119,7 +120,7 @@ public function appendChild($nodes) /** * Adds a new child before a reference node. * - * @param Element|DOMNode $node The new node + * @param Node|DOMNode $node The new node * @param Element|DOMNode|null $referenceNode The reference node * * @return Element @@ -167,7 +168,7 @@ public function insertBefore($node, $referenceNode = null) /** * Adds a new child after a reference node. * - * @param Element|DOMNode $node The new node + * @param Node|DOMNode $node The new node * @param Element|DOMNode|null $referenceNode The reference node * * @return Element @@ -378,9 +379,10 @@ public function innerXml($delimiter = '') * * @param string $html * - * @return Element + * @return static * * @throws InvalidArgumentException if passed argument is not a string + * @throws InvalidSelectorException */ public function setInnerHtml($html) { @@ -438,7 +440,7 @@ public function text() * * @param string $value The new value of the node * - * @return Element + * @return static * * @throws InvalidArgumentException if value is not string */ @@ -907,7 +909,7 @@ public function children() /** * Removes child from list of children. * - * @param DOMNode|Element $childNode + * @param Node|DOMNode $childNode * * @return Element the node that has been removed */ @@ -973,7 +975,7 @@ public function remove() /** * Replaces a child. * - * @param DOMNode|Element $newNode The new node + * @param Node|DOMNode $newNode The new node * @param bool $clone Clone the node if true, otherwise move it * * @return Element The node that has been replaced @@ -1032,16 +1034,16 @@ public function cloneNode($deep = true) /** * Sets current node instance. * - * @param DOMElement|DOMText|DOMComment|DOMCdataSection $node + * @param DOMElement|DOMText|DOMComment|DOMCdataSection|DOMDocumentFragment $node * - * @return Element + * @return static */ protected function setNode($node) { - $allowedClasses = ['DOMElement', 'DOMText', 'DOMComment', 'DOMCdataSection']; + $allowedClasses = ['DOMElement', 'DOMText', 'DOMComment', 'DOMCdataSection', 'DOMDocumentFragment']; if ( ! is_object($node) || ! in_array(get_class($node), $allowedClasses, true)) { - throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of DOMElement, DOMText, DOMComment or DOMCdataSection, %s given', __METHOD__, (is_object($node) ? get_class($node) : gettype($node)))); + throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of DOMElement, DOMText, DOMComment, DOMCdataSection or DOMDocumentFragment, %s given', __METHOD__, (is_object($node) ? get_class($node) : gettype($node)))); } $this->node = $node; @@ -1052,7 +1054,7 @@ protected function setNode($node) /** * Returns current node instance. * - * @return DOMElement|DOMText|DOMComment|DOMCdataSection + * @return DOMElement|DOMText|DOMComment|DOMCdataSection|DOMDocumentFragment */ public function getNode() { diff --git a/tests/DocumentFragmentTest.php b/tests/DocumentFragmentTest.php new file mode 100644 index 0000000..35ffd4f --- /dev/null +++ b/tests/DocumentFragmentTest.php @@ -0,0 +1,30 @@ +createDocumentFragment(); + + $documentFragment->appendXml('bar'); + + $this->assertEquals('bar', $documentFragment->innerXml()); + } +} diff --git a/tests/DocumentTest.php b/tests/DocumentTest.php index 28fa7bc..99b0a3f 100644 --- a/tests/DocumentTest.php +++ b/tests/DocumentTest.php @@ -143,7 +143,7 @@ public function testCreateComment() $this->assertEquals('foo bar baz', $comment->text()); } - public function testCreateCDATASection() + public function testCreateCdataSection() { $document = new Document(); @@ -154,6 +154,16 @@ public function testCreateCDATASection() $this->assertEquals('foo bar baz', $cdataSection->text()); } + public function testCreateDocumentFragment() + { + $document = new Document(); + + $documentFragment = $document->createDocumentFragment(); + + $this->assertInstanceOf('DiDom\DocumentFragment', $documentFragment); + $this->assertInstanceOf('DOMDocumentFragment', $documentFragment->getNode()); + } + /** * @expectedException InvalidArgumentException * @expectedExceptionMessage Argument 1 passed to DiDom\Document::appendChild must be an instance of DiDom\Element or DOMNode, string given diff --git a/tests/ElementTest.php b/tests/ElementTest.php index 6c5e67c..b17ea4c 100644 --- a/tests/ElementTest.php +++ b/tests/ElementTest.php @@ -179,6 +179,40 @@ public function testPrependChildWithArrayOfNodes() } } + public function testPrependDocumentFragment() + { + $xml = ' + + Foo + Bar + Baz + + '; + + $document = new Document(); + + $document->loadXml($xml); + + $fragmentXml = ' + Qux + Quux + Quuz + '; + + $documentFragment = $document->createDocumentFragment(); + + $documentFragment->appendXml($fragmentXml); + + $document->first('list')->prependChild($documentFragment); + + $expectedContent = ['Qux', 'Quux', 'Quuz', 'Foo', 'Bar', 'Baz']; + + foreach ($document->find('item') as $index => $childNode) { + $this->assertEquals('item', $childNode->tag); + $this->assertEquals($expectedContent[$index], $childNode->text()); + } + } + /** * @expectedException InvalidArgumentException */ @@ -253,6 +287,40 @@ public function testAppendChildWithArray() } } + public function testAppendDocumentFragment() + { + $xml = ' + + Foo + Bar + Baz + + '; + + $document = new Document(); + + $document->loadXml($xml); + + $fragmentXml = ' + Qux + Quux + Quuz + '; + + $documentFragment = $document->createDocumentFragment(); + + $documentFragment->appendXml($fragmentXml); + + $document->first('list')->appendChild($documentFragment); + + $expectedContent = ['Foo', 'Bar', 'Baz', 'Qux', 'Quux', 'Quuz']; + + foreach ($document->find('item') as $index => $childNode) { + $this->assertEquals('item', $childNode->tag); + $this->assertEquals($expectedContent[$index], $childNode->text()); + } + } + /** * @expectedException InvalidArgumentException */ @@ -1918,7 +1986,7 @@ public function testReplace() $this->assertCount(2, $document->find('li')); } - public function testReplaceToNewElement() + public function testReplaceWithNewElement() { $html = ''; @@ -1944,7 +2012,7 @@ public function testReplaceToNewElement() $anchor->replace($textNode); } - public function testReplaceWithDifferentDocuments() + public function testReplaceWithElementFromAnotherDocument() { $html = ''; @@ -1957,6 +2025,40 @@ public function testReplaceWithDifferentDocuments() $first->replace($third); } + public function testReplaceWithDocumentFragment() + { + $xml = ' + + Foo + Bar + Baz + + '; + + $document = new Document(); + + $document->loadXml($xml); + + $fragmentXml = ' + Qux + Quux + Quuz + '; + + $documentFragment = $document->createDocumentFragment(); + + $documentFragment->appendXml($fragmentXml); + + $document->first('item:nth-child(2)')->replace($documentFragment); + + $expectedContent = ['Foo', 'Qux', 'Quux', 'Quuz', 'Baz']; + + foreach ($document->find('item') as $index => $childNode) { + $this->assertEquals('item', $childNode->tag); + $this->assertEquals($expectedContent[$index], $childNode->text()); + } + } + /** * @expectedException InvalidArgumentException */