Skip to content

Commit 7d6b1ff

Browse files
committed
:octocat:
1 parent 634c3a4 commit 7d6b1ff

15 files changed

+377
-129
lines changed

src/Attr.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
/**
3+
* Class Attr
4+
*
5+
* @filesource Attr.php
6+
* @created 08.05.2017
7+
* @package chillerlan\PrototypeDOM
8+
* @author Smiley <smiley@chillerlan.net>
9+
* @copyright 2017 Smiley
10+
* @license MIT
11+
*/
12+
13+
namespace chillerlan\PrototypeDOM;
14+
15+
use DOMAttr;
16+
17+
class Attr extends DOMAttr{}

src/CharacterData.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@
1515
use DOMCharacterData;
1616

1717
class CharacterData extends DOMCharacterData {
18-
use NodeTraversalTrait, NodeManipulationTrait;
18+
use TraversalTrait, ManipulationTrait;
1919
}

src/Comment.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
/**
3+
* Class Comment
4+
*
5+
* @filesource Comment.php
6+
* @created 08.05.2017
7+
* @package chillerlan\PrototypeDOM
8+
* @author Smiley <smiley@chillerlan.net>
9+
* @copyright 2017 Smiley
10+
* @license MIT
11+
*/
12+
13+
namespace chillerlan\PrototypeDOM;
14+
15+
use DOMComment;
16+
17+
class Comment extends DOMComment{}

src/Document.php

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ public function __construct($version = null, $encoding = null){
3030
$this->registerNodeClass('DOMText', Text::class);
3131
$this->registerNodeClass('DOMCharacterData', CharacterData::class);
3232
$this->registerNodeClass('DOMDocumentFragment', DocumentFragment::class);
33+
$this->registerNodeClass('DOMDocumentType', DocumentType::class);
34+
$this->registerNodeClass('DOMComment', Comment::class);
35+
$this->registerNodeClass('DOMAttr', Attr::class);
3336
}
3437

3538
/**
@@ -46,20 +49,20 @@ public function selector2xpath(string $selector, string $axis = '//'):string{
4649
* @param string $xpath
4750
* @param \DOMNode|null $contextNode
4851
*
49-
* @return \DOMNodeList
52+
* @return \chillerlan\PrototypeDOM\NodeList
5053
*/
51-
public function query(string $xpath, DOMNode $contextNode = null):DOMNodeList{
52-
return (new DOMXPath($this))->query($xpath, $contextNode);
54+
public function query(string $xpath, DOMNode $contextNode = null):NodeList{
55+
return new NodeList((new DOMXPath($this))->query($xpath, $contextNode));
5356
}
5457

5558
/**
5659
* @param string $selector
5760
* @param \DOMNode|null $contextNode
5861
* @param string $axis
5962
*
60-
* @return \DOMNodeList
63+
* @return \chillerlan\PrototypeDOM\NodeList
6164
*/
62-
public function getElementsBySelector(string $selector, DOMNode $contextNode = null, string $axis = 'descendant-or-self::'):DOMNodeList{
65+
public function querySelectorAll(string $selector, DOMNode $contextNode = null, string $axis = 'descendant-or-self::'):NodeList{
6366
return $this->query($this->selector2xpath($selector, $axis), $contextNode);
6467
}
6568

@@ -69,9 +72,9 @@ public function getElementsBySelector(string $selector, DOMNode $contextNode = n
6972
* @param string $axis
7073
* @param int $nodeType
7174
*
72-
* @return \DOMNode[]
75+
* @return \chillerlan\PrototypeDOM\NodeList
7376
*/
74-
public function select($selectors = null, DOMNode $contextNode = null, string $axis = 'descendant-or-self::', int $nodeType = XML_ELEMENT_NODE):array{
77+
public function select($selectors = null, DOMNode $contextNode = null, string $axis = 'descendant-or-self::', int $nodeType = XML_ELEMENT_NODE):NodeList{
7578

7679
if(is_string($selectors)){
7780
$selectors = [trim($selectors)];
@@ -81,11 +84,11 @@ public function select($selectors = null, DOMNode $contextNode = null, string $a
8184
$selectors = ['*'];
8285
}
8386

84-
$elements = [];
87+
$elements = new NodeList;
8588

8689
foreach($selectors as $selector){
8790

88-
foreach($this->getElementsBySelector($selector, $contextNode, $axis) as $element){
91+
foreach($this->querySelectorAll($selector, $contextNode, $axis) as $element){
8992

9093
if($element->nodeType === $nodeType){
9194
$elements[] = $element;
@@ -98,6 +101,19 @@ public function select($selectors = null, DOMNode $contextNode = null, string $a
98101
return $elements;
99102
}
100103

104+
public function _loadHTMLFragment(string $content):NodeList{
105+
$document = new Document;
106+
$document->loadHTML('<html><body id="-import-content">'.$content.'</body></html>');
107+
108+
return new NodeList($document->getElementById('-import-content')->childNodes);
109+
110+
/*
111+
$document->loadHTML('<!DOCTYPE html>' .$content);
112+
return $document->getElementsByTagName('head')[0]->childNodes
113+
?? $document->getElementsByTagName('body')[0]->childNodes;
114+
*/
115+
}
116+
101117
/**
102118
* @param \DOMNode|null $context
103119
* @param bool $xml
@@ -132,32 +148,26 @@ public function removeElementsBySelector($selectors, DOMNode $contextNode = null
132148
}
133149

134150
/**
135-
* @param string|\DOMNode|\DOMNodeList $content
151+
* @param string|\DOMNode|\DOMNodeList|\chillerlan\PrototypeDOM\NodeList $content
136152
*
137-
* @return \DOMNodeList
153+
* @return \chillerlan\PrototypeDOM\NodeList
138154
* @throws \Exception
139155
*/
140-
public function _toDOMNodeList($content):DOMNodeList{
156+
public function _toNodeList($content):NodeList{
141157

142-
if($content instanceof DOMNodeList){
143-
return $content;
158+
if($content instanceof NodeList || $content instanceof DOMNodeList || is_array($content)){
159+
return new NodeList($content);
144160
}
145-
146-
$document = new Document;
147-
148-
if($content instanceof DOMNode){
149-
$document->loadHTML('<html><body id="content"></body></html>');
150-
151-
$document->getElementById('content')->appendChild($document->importNode($content, true));
161+
elseif($content instanceof DOMNode){
162+
return new NodeList([$content]);
152163
}
153164
elseif(is_string($content)){
154-
$document->loadHTML('<html><body id="content">'.$content.'</body></html>');
165+
return $this->_loadHTMLFragment($content);
155166
}
156167
else{
157168
throw new \Exception('invalid content'); // @codeCoverageIgnore
158169
}
159170

160-
return $document->getElementById('content')->childNodes;
161171
}
162172

163173
/**
@@ -166,10 +176,10 @@ public function _toDOMNodeList($content):DOMNodeList{
166176
* @param int $maxLength
167177
* @param int $nodeType
168178
*
169-
* @return \DOMNode[]
179+
* @return \chillerlan\PrototypeDOM\NodeList
170180
*/
171-
public function recursivelyCollect(DOMNode $element, string $property, int $maxLength = -1, int $nodeType = XML_ELEMENT_NODE):array{
172-
$nodes = [];
181+
public function recursivelyCollect(DOMNode $element, string $property, int $maxLength = -1, int $nodeType = XML_ELEMENT_NODE):NodeList{
182+
$nodes = new NodeList;
173183

174184
if(in_array($property, ['parentNode', 'previousSibling', 'nextSibling'])){
175185

src/DocumentFragment.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@
1717
/**
1818
*/
1919
class DocumentFragment extends DOMDocumentFragment{
20-
use NodeTraversalTrait, NodeManipulationTrait;
20+
use TraversalTrait, ManipulationTrait;
2121
}

src/DocumentType.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
/**
3+
* Class DocumentType
4+
*
5+
* @filesource DocumentType.php
6+
* @created 08.05.2017
7+
* @package chillerlan\PrototypeDOM
8+
* @author Smiley <smiley@chillerlan.net>
9+
* @copyright 2017 Smiley
10+
* @license MIT
11+
*/
12+
13+
namespace chillerlan\PrototypeDOM;
14+
15+
use DOMDocumentType;
16+
17+
class DocumentType extends DOMDocumentType{}

src/Element.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use DOMElement;
1616

1717
class Element extends DOMElement{
18-
use NodeTraversalTrait, NodeManipulationTrait;
18+
use ManipulationTrait, TraversalTrait;
1919

2020
/**
2121
* @param string|null $newID
Lines changed: 58 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?php
22
/**
3-
* Trait NodeManipulationTrait
3+
* Trait ManipulationTrait
44
*
5-
* @filesource NodeManipulationTrait.php
5+
* @filesource ManipulationTrait.php
66
* @created 08.05.2017
77
* @package chillerlan\PrototypeDOM
88
* @author Smiley <smiley@chillerlan.net>
@@ -17,7 +17,7 @@
1717
/**
1818
* @extends \DOMNode
1919
*/
20-
trait NodeManipulationTrait{
20+
trait ManipulationTrait{
2121

2222
/**
2323
* @link http://php.net/manual/class.domnode.php#domnode.props.ownerdocument
@@ -137,91 +137,99 @@ public function _importNode(DOMNode $newNode):DOMNode{
137137
}
138138

139139
/**
140-
* @param \DOMNodeList $nodes
140+
* Accepted insertion points are:
141+
* - before (as element's previous sibling)
142+
* - after (as element's next sibling)
143+
* - top (as element's first child)
144+
* - bottom (as element's last child)
145+
*
146+
* @param string|array|\DOMNode|\DOMNodeList $content
141147
*
142148
* @return \DOMNode
143149
*/
144-
public function _insertBottom(DOMNodeList $nodes):DOMNode{
150+
public function insert($content):DOMNode{
151+
152+
if(is_array($content)){
153+
154+
foreach(['before', 'after', 'top', 'bottom'] as $pos){
155+
156+
if(array_key_exists($pos, $content)){
157+
$nodes = $this->ownerDocument->_toNodeList($content[$pos]);
158+
159+
if($pos === 'top'){
160+
$nodes->reverse();
161+
}
162+
163+
foreach($nodes as $node){
164+
call_user_func_array([$this, 'insert_'.$pos], [$node]);
165+
}
166+
167+
}
168+
169+
}
145170

146-
foreach($nodes as $node){
147-
$this->appendChild($this->_importNode($node));
171+
}
172+
else{
173+
foreach($this->ownerDocument->_toNodeList($content) as $node){
174+
$this->insert_bottom($node);
175+
}
148176
}
149177

150178
/** @var \chillerlan\PrototypeDOM\Element $this */
151179
return $this;
152180
}
153181

154182
/**
155-
* @param \DOMNodeList $nodes
183+
* @param \DOMNode $node
184+
* @param \DOMNode|null $refNode
156185
*
157186
* @return \DOMNode
158187
*/
159-
public function _insertBefore(DOMNodeList $nodes){
188+
public function insert_before(DOMNode $node, DOMNode $refNode = null):DOMNode{
160189

161190
if($this->parentNode){
162-
163-
foreach($nodes as $node){
164-
$this->parentNode->insertBefore($this->_importNode($node), $this);
165-
}
166-
191+
$this->parentNode->insertBefore($this->_importNode($node), $refNode ?? $this);
167192
}
168193

169194
/** @var \chillerlan\PrototypeDOM\Element $this */
170195
return $this;
171196
}
172197

173198
/**
174-
* @param \DOMNodeList $nodes
199+
* @param \DOMNode $node
175200
*
176201
* @return \DOMNode
177202
*/
178-
public function _insertTop(DOMNodeList $nodes):DOMNode{
179-
return $this->hasChildNodes()
180-
? $this->firstChild->_insertBefore($nodes)
181-
: $this->_insertBottom($nodes);
203+
public function insert_after(DOMNode $node):DOMNode{
204+
!$this->nextSibling && $this->parentNode
205+
? $this->parentNode->insert_bottom($node)
206+
: $this->nextSibling->insert_before($node);
207+
208+
/** @var \chillerlan\PrototypeDOM\Element $this */
209+
return $this;
182210
}
183211

184212
/**
185-
* @param \DOMNodeList $nodes
213+
* @param \DOMNode $node
186214
*
187215
* @return \DOMNode
188216
*/
189-
public function _insertAfter(DOMNodeList $nodes):DOMNode{
190-
return !$this->nextSibling && $this->parentNode
191-
? $this->parentNode->_insertBottom($nodes)
192-
: $this->nextSibling->_insertBefore($nodes);
217+
public function insert_top(DOMNode $node):DOMNode{
218+
$this->hasChildNodes()
219+
? $this->firstChild->insert_before($node, $this->firstChild)
220+
: $this->insert_bottom($node);
221+
222+
/** @var \chillerlan\PrototypeDOM\Element $this */
223+
return $this;
193224
}
194225

195226
/**
196-
* Accepted insertion points are:
197-
* - before (as element's previous sibling)
198-
* - after (as element's next sibling)
199-
* - top (as element's first child)
200-
* - bottom (as element's last child)
201-
*
202-
* @param string|array|\DOMNode|\DOMNodeList $content
227+
* @param \DOMNode $node
203228
*
204229
* @return \DOMNode
205230
*/
206-
public function insert($content):DOMNode{
207-
208-
if(is_string($content) || $content instanceof DOMNode || $content instanceof DOMNodeList){
209-
$this->_insertBottom($this->ownerDocument->_toDOMNodeList($content));
210-
}
211-
elseif(is_array($content)){
212-
213-
foreach(['before', 'after', 'top', 'bottom'] as $pos){
214-
215-
if(array_key_exists($pos, $content)){
216-
call_user_func_array(
217-
[$this, '_insert'.ucfirst($pos)],
218-
[$this->ownerDocument->_toDOMNodeList($content[$pos])]
219-
);
220-
}
221-
222-
}
223-
224-
}
231+
public function insert_bottom(DOMNode $node):DOMNode{
232+
$this->appendChild($this->_importNode($node));
225233

226234
/** @var \chillerlan\PrototypeDOM\Element $this */
227235
return $this;

0 commit comments

Comments
 (0)