Passed
Push — master ( 8e4c14...93bf08 )
by smiley
06:58
created

PrototypeTraversalTrait::match()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
c 0
b 0
f 0
rs 10
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * Trait PrototypeTraversalTrait
4
 *
5
 * @filesource   PrototypeTraversalTrait.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
 * @noinspection PhpParamsInspection
13
 * @noinspection PhpIncompatibleReturnTypeInspection
14
 */
15
16
namespace chillerlan\PrototypeDOM\Node;
17
18
use chillerlan\PrototypeDOM\NodeList;
19
use DOMNode;
20
21
use function is_array, is_int, is_numeric;
22
23
use const XML_ELEMENT_NODE;
24
25
/**
26
 * @property \chillerlan\PrototypeDOM\Document $ownerDocument
27
 */
28
trait PrototypeTraversalTrait{
29
	use PrototypeNodeTrait;
30
31
	/**
32
	 * @see https://secure.php.net/manual/dom.constants.php
33
	 *
34
	 * @return \chillerlan\PrototypeDOM\Node\PrototypeTraversal|\DOMNode|null
35
	 */
36
	public function recursivelyFind(string $selector = null, int $index = null, string $property = null, int $nodeType = XML_ELEMENT_NODE):?PrototypeTraversal{
37
38
		if(is_numeric($selector)){
39
			return $this->ownerDocument->recursivelyFind($this, $property, null, $selector, $nodeType);
0 ignored issues
show
Bug introduced by
$this of type chillerlan\PrototypeDOM\...PrototypeTraversalTrait is incompatible with the type chillerlan\PrototypeDOM\Node\PrototypeNode expected by parameter $element of chillerlan\PrototypeDOM\...ment::recursivelyFind(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

39
			return $this->ownerDocument->recursivelyFind(/** @scrutinizer ignore-type */ $this, $property, null, $selector, $nodeType);
Loading history...
Bug Best Practice introduced by
The expression return $this->ownerDocum..., $selector, $nodeType) could return the type DOMNode which is incompatible with the type-hinted return chillerlan\PrototypeDOM\...PrototypeTraversal|null. Consider adding an additional type-check to rule them out.
Loading history...
Bug introduced by
$selector of type string is incompatible with the type integer|null expected by parameter $index of chillerlan\PrototypeDOM\...ment::recursivelyFind(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

39
			return $this->ownerDocument->recursivelyFind($this, $property, null, /** @scrutinizer ignore-type */ $selector, $nodeType);
Loading history...
40
		}
41
42
		return $this->ownerDocument->recursivelyFind($this, $property, $selector, $index ?? 0, $nodeType);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->ownerDocum...$index ?? 0, $nodeType) could return the type DOMNode which is incompatible with the type-hinted return chillerlan\PrototypeDOM\...PrototypeTraversal|null. Consider adding an additional type-check to rule them out.
Loading history...
43
	}
44
45
	/**
46
	 * @inheritDoc
47
	 */
48
	public function select(array $selectors = null):NodeList{
49
		return $this->ownerDocument->select($selectors, $this, 'descendant::');
0 ignored issues
show
Bug introduced by
$this of type chillerlan\PrototypeDOM\...PrototypeTraversalTrait is incompatible with the type DOMNode|null expected by parameter $contextNode of chillerlan\PrototypeDOM\Document::select(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

49
		return $this->ownerDocument->select($selectors, /** @scrutinizer ignore-type */ $this, 'descendant::');
Loading history...
50
	}
51
52
	/**
53
	 * @inheritDoc
54
	 */
55
	public function down($expression = null, int $index = null):?PrototypeTraversal{
56
57
		if($expression === null && $index === null){
58
			return $this->firstDescendant();
59
		}
60
61
		$index = $index ?? 0;
62
63
		if(is_int($expression)){
64
			return $this->select(['*'])->offsetGet($expression);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->select(arr...>offsetGet($expression) could return the type DOMNode which is incompatible with the type-hinted return chillerlan\PrototypeDOM\...PrototypeTraversal|null. Consider adding an additional type-check to rule them out.
Loading history...
65
		}
66
67
		if(is_array($expression)){
68
			return $this->select($expression)->offsetGet($index);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->select($ex...ion)->offsetGet($index) could return the type DOMNode which is incompatible with the type-hinted return chillerlan\PrototypeDOM\...PrototypeTraversal|null. Consider adding an additional type-check to rule them out.
Loading history...
69
		}
70
71
		return $this->select([$expression])->offsetGet($index);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->select(arr...on))->offsetGet($index) could return the type DOMNode which is incompatible with the type-hinted return chillerlan\PrototypeDOM\...PrototypeTraversal|null. Consider adding an additional type-check to rule them out.
Loading history...
72
	}
73
74
	/**
75
	 * @inheritDoc
76
	 */
77
	public function up($expression = null, int $index = null):?PrototypeTraversal{
78
		return $this->recursivelyFind($expression, $index, 'parentNode');
79
	}
80
81
	/**
82
	 * @inheritDoc
83
	 */
84
	public function previous($expression = null, int $index = null):?PrototypeTraversal{
85
		return $this->recursivelyFind($expression, $index, 'previousSibling');
86
	}
87
88
	/**
89
	 * @inheritDoc
90
	 */
91
	public function next($expression = null, int $index = null):?PrototypeTraversal{
92
		return $this->recursivelyFind($expression, $index, 'nextSibling');
93
	}
94
95
	/**
96
	 * @inheritDoc
97
	 */
98
	public function childElements(int $nodeType = null):NodeList{
99
		$nodeType = $nodeType ?? XML_ELEMENT_NODE;
100
		$children = new NodeList;
101
102
		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? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

102
		if(!$this->/** @scrutinizer ignore-call */ hasChildNodes()){
Loading history...
103
			return $children;
104
		}
105
106
		foreach($this->childNodes as $child){
107
108
			if($child->nodeType === $nodeType){
109
				$children[] = $child;
110
			}
111
112
		}
113
114
		return $children;
115
	}
116
117
	/**
118
	 * @inheritDoc
119
	 */
120
	public function descendantOf(DOMNode $ancestor):bool{
121
		return $this->ancestors()->match($ancestor);
122
	}
123
124
	/**
125
	 * @inheritDoc
126
	 */
127
	public function ancestors():NodeList{
128
		return $this->recursivelyCollect('parentNode');
129
	}
130
131
	/**
132
	 * @inheritDoc
133
	 */
134
	public function siblings():NodeList{
135
		return $this->previousSiblings()->reverse()->merge($this->nextSiblings());
136
	}
137
138
	/**
139
	 * @inheritDoc
140
	 */
141
	public function descendants():NodeList{
142
		return $this->select();
143
	}
144
145
	/**
146
	 * @inheritDoc
147
	 */
148
	public function firstDescendant():?PrototypeTraversal{
149
		return $this->descendants()->first();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->descendants()->first() could return the type DOMNode which is incompatible with the type-hinted return chillerlan\PrototypeDOM\...PrototypeTraversal|null. Consider adding an additional type-check to rule them out.
Loading history...
150
	}
151
152
	/**
153
	 * @inheritDoc
154
	 */
155
	public function previousSiblings():NodeList{
156
		return $this->recursivelyCollect('previousSibling');
157
	}
158
159
	/**
160
	 * @inheritDoc
161
	 */
162
	public function nextSiblings():NodeList{
163
		return $this->recursivelyCollect('nextSibling');
164
	}
165
166
}
167