Completed
Push — master ( 14b45d...d8ec9e )
by smiley
04:40
created

TraversalTrait::next()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
crap 1
1
<?php
2
/**
3
 * Trait TraversalTrait
4
 *
5
 * @filesource   TraversalTrait.php
6
 * @created      06.05.2017
7
 * @package      chillerlan\PrototypeDOM\Traits
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2017 Smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\PrototypeDOM\Traits;
14
15
use chillerlan\PrototypeDOM\Node\PrototypeNode;
16
use chillerlan\PrototypeDOM\NodeList;
17
18
trait TraversalTrait{
19
	use  NodeTrait;
20
21
	/**
22
	 * @param        $selector
23
	 * @param        $index
24
	 * @param string $property
25
	 * @param int    $nodeType
26
	 *
27
	 * @return \chillerlan\PrototypeDOM\Node\PrototypeNode|null
28
	 */
29 4
	public function _recursivelyFind($selector, $index, string $property, int $nodeType = XML_ELEMENT_NODE){
30
31 4
		if(is_numeric($selector)){
32 4
			$index    = $selector;
33 4
			$selector = null;
34
		}
35
36 4
		return $this->ownerDocument->_recursivelyFind($this, $property, $selector, $index ?? 0, $nodeType);
37
	}
38
39
	/**
40
	 * @link http://api.prototypejs.org/dom/Element/select/
41
	 *
42
	 * @param string|array $selectors
43
	 *
44
	 * @return \chillerlan\PrototypeDOM\NodeList
45
	 */
46 3
	public function select($selectors = null):NodeList{
47 3
		return $this->ownerDocument->select($selectors, $this, 'descendant::');
48
	}
49
50
	/**
51
	 * @link http://api.prototypejs.org/dom/Element/match/
52
	 *
53
	 * @param string $selector
54
	 *
55
	 * @return bool
56
	 */
57 4
	public function match(string $selector):bool{
58 4
		return $this->ownerDocument->match($this, $selector);
59
	}
60
61
	/**
62
	 * @link http://api.prototypejs.org/dom/Element/down/
63
	 *
64
	 * @param null $expression
65
	 * @param int  $index
66
	 *
67
	 * @return \chillerlan\PrototypeDOM\Node\PrototypeNode|null
68
	 */
69 1
	public function down($expression = null, int $index = null){
70
71 1
		if(count(func_get_args()) === 0){
72 1
			return $this->firstDescendant();
73
		}
74
75 1
		if(is_int($expression)){
76 1
			$index      = $expression;
77 1
			$expression = '*';
78
		}
79
		else{
80 1
			$index = $index ?? 0;
81
		}
82
83 1
		return $this->select($expression ?? null)->item($index);
84
	}
85
86
	/**
87
	 * @link http://api.prototypejs.org/dom/Element/up/
88
	 *
89
	 * @param string|null $expression
90
	 * @param int|null    $index
91
	 *
92
	 * @return \chillerlan\PrototypeDOM\Node\PrototypeNode|null
93
	 */
94 2
	public function up($expression = null, int $index = null){
95 2
		return $this->_recursivelyFind($expression, $index, 'parentNode');
96
	}
97
98
	/**
99
	 * @link http://api.prototypejs.org/dom/Element/previous/
100
	 *
101
	 * @param string|null $expression
102
	 * @param int|null    $index
103
	 *
104
	 * @return \chillerlan\PrototypeDOM\Node\PrototypeNode|null
105
	 */
106 1
	public function previous($expression = null, int $index = null){
107 1
		return $this->_recursivelyFind($expression, $index, 'previousSibling');
108
	}
109
110
	/**
111
	 * @link http://api.prototypejs.org/dom/Element/next/
112
	 *
113
	 * @param string|null $expression
114
	 * @param int|null    $index
115
	 *
116
	 * @return \chillerlan\PrototypeDOM\Node\PrototypeNode|null
117
	 */
118 2
	public function next($expression = null, int $index = null){
119 2
		return $this->_recursivelyFind($expression, $index, 'nextSibling');
120
	}
121
122
	/**
123
	 * @link http://api.prototypejs.org/dom/Element/childElements/
124
	 *
125
	 * @param int $nodeType
126
	 *
127
	 * @return \chillerlan\PrototypeDOM\NodeList
128
	 */
129 2
	public function childElements(int $nodeType = XML_ELEMENT_NODE):NodeList{
130 2
		$children = new NodeList;
131
132 2
		if($this->hasChildNodes()){
0 ignored issues
show
Bug introduced by
It seems like hasChildNodes() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
133
134 2
			foreach($this->childNodes as $child){
135
136 2
				if($child->nodeType === $nodeType){
137 2
					$children[] = $child;
138
				}
139
140
			}
141
142
		}
143
144 2
		return $children;
145
	}
146
147
	/**
148
	 * @link http://api.prototypejs.org/dom/Element/descendantOf/
149
	 *
150
	 * @param \chillerlan\PrototypeDOM\Node\PrototypeNode $ancestor
151
	 *
152
	 * @return bool
153
	 */
154 1
	public function descendantOf(PrototypeNode $ancestor):bool{
155 1
		return $this->ancestors()->match($ancestor);
156
	}
157
158
	/**
159
	 * @link http://api.prototypejs.org/dom/Element/ancestors/
160
	 *
161
	 * @return \chillerlan\PrototypeDOM\NodeList
162
	 */
163 2
	public function ancestors():NodeList{
164 2
		return $this->recursivelyCollect('parentNode');
165
	}
166
167
	/**
168
	 * @link http://api.prototypejs.org/dom/Element/siblings/
169
	 *
170
	 * @return \chillerlan\PrototypeDOM\NodeList
171
	 */
172 1
	public function siblings():NodeList{
173 1
		return $this->previousSiblings()->reverse()->merge($this->nextSiblings());
174
	}
175
176
	/**
177
	 * @link http://api.prototypejs.org/dom/Element/descendants/
178
	 *
179
	 * @return \chillerlan\PrototypeDOM\NodeList
180
	 */
181 2
	public function descendants():NodeList{
182 2
		return $this->select();
183
	}
184
185
	/**
186
	 * @link http://api.prototypejs.org/dom/Element/firstDescendant/
187
	 *
188
	 * @return \chillerlan\PrototypeDOM\Node\Element|null
189
	 */
190 2
	public function firstDescendant(){
191 2
		return $this->descendants()->first();
192
	}
193
194
	/**
195
	 * @link http://api.prototypejs.org/dom/Element/previousSiblings/
196
	 *
197
	 * @return \chillerlan\PrototypeDOM\NodeList
198
	 */
199 1
	public function previousSiblings():NodeList{
200 1
		return $this->recursivelyCollect('previousSibling');
201
	}
202
203
	/**
204
	 * @link http://api.prototypejs.org/dom/Element/nextSiblings/
205
	 *
206
	 * @return \chillerlan\PrototypeDOM\NodeList
207
	 */
208 1
	public function nextSiblings():NodeList{
209 1
		return $this->recursivelyCollect('nextSibling');
210
	}
211
212
}
213