Issues (50)

src/Node/PrototypeTraversalTrait.php (10 issues)

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
 * @implements \chillerlan\PrototypeDOM\Node\PrototypeTraversal
27
 *
28
 * @property \chillerlan\PrototypeDOM\Document $ownerDocument
29
 */
30
trait PrototypeTraversalTrait{
31
	use PrototypeNodeTrait;
32
33
	/**
34
	 * @inheritDoc
35
	 */
36
	public function recursivelyFind(
37
		string $selector = null,
38
		int $index = null,
39
		string $property = null,
40
		int $nodeType = XML_ELEMENT_NODE
41
	):?PrototypeTraversal{
42
43
		if(is_numeric($selector)){
44
			return $this->ownerDocument->recursivelyFind($this, $property, null, $selector, $nodeType);
0 ignored issues
show
$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

44
			return $this->ownerDocument->recursivelyFind($this, $property, null, /** @scrutinizer ignore-type */ $selector, $nodeType);
Loading history...
$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

44
			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...
45
		}
46
47
		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...
48
	}
49
50
	/**
51
	 * @inheritDoc
52
	 */
53
	public function select(array $selectors = null):NodeList{
54
		return $this->ownerDocument->select($selectors, $this, 'descendant::');
0 ignored issues
show
$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

54
		return $this->ownerDocument->select($selectors, /** @scrutinizer ignore-type */ $this, 'descendant::');
Loading history...
55
	}
56
57
	/**
58
	 * @inheritDoc
59
	 */
60
	public function down($expression = null, int $index = null):?PrototypeTraversal{
61
62
		if($expression === null && $index === null){
63
			return $this->firstDescendant();
64
		}
65
66
		$index = $index ?? 0;
67
68
		if(is_int($expression)){
69
			return $this->select(['*'])->item($expression);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->select(arr...*'))->item($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...
70
		}
71
72
		if(is_array($expression)){
73
			return $this->select($expression)->item($index);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->select($expression)->item($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...
74
		}
75
76
		return $this->select([$expression])->item($index);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->select(arr...ression))->item($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...
77
	}
78
79
	/**
80
	 * @inheritDoc
81
	 */
82
	public function up($expression = null, int $index = null):?PrototypeTraversal{
83
		return $this->recursivelyFind($expression, $index, 'parentNode');
84
	}
85
86
	/**
87
	 * @inheritDoc
88
	 */
89
	public function previous($expression = null, int $index = null):?PrototypeTraversal{
90
		return $this->recursivelyFind($expression, $index, 'previousSibling');
91
	}
92
93
	/**
94
	 * @inheritDoc
95
	 */
96
	public function next($expression = null, int $index = null):?PrototypeTraversal{
97
		return $this->recursivelyFind($expression, $index, 'nextSibling');
98
	}
99
100
	/**
101
	 * @inheritDoc
102
	 */
103
	public function childElements(int $nodeType = null):NodeList{
104
		$nodeType = $nodeType ?? XML_ELEMENT_NODE;
105
		$children = new NodeList;
106
107
		if(!$this->hasChildNodes()){
0 ignored issues
show
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

107
		if(!$this->/** @scrutinizer ignore-call */ hasChildNodes()){
Loading history...
108
			return $children;
109
		}
110
111
		foreach($this->childNodes as $child){
112
113
			if($child->nodeType === $nodeType){
114
				$children[] = $child;
115
			}
116
117
		}
118
119
		return $children;
120
	}
121
122
	/**
123
	 * @inheritDoc
124
	 */
125
	public function descendantOf(DOMNode $ancestor):bool{
126
		return $this->ancestors()->match($ancestor);
127
	}
128
129
	/**
130
	 * @inheritDoc
131
	 */
132
	public function ancestors():NodeList{
133
		return $this->recursivelyCollect('parentNode');
134
	}
135
136
	/**
137
	 * @inheritDoc
138
	 */
139
	public function siblings():NodeList{
140
		return $this->previousSiblings()->reverse()->merge($this->nextSiblings());
141
	}
142
143
	/**
144
	 * @inheritDoc
145
	 */
146
	public function descendants():NodeList{
147
		return $this->select();
148
	}
149
150
	/**
151
	 * @inheritDoc
152
	 */
153
	public function firstDescendant():?PrototypeTraversal{
154
		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...
155
	}
156
157
	/**
158
	 * @inheritDoc
159
	 */
160
	public function previousSiblings():NodeList{
161
		return $this->recursivelyCollect('previousSibling');
162
	}
163
164
	/**
165
	 * @inheritDoc
166
	 */
167
	public function nextSiblings():NodeList{
168
		return $this->recursivelyCollect('nextSibling');
169
	}
170
171
}
172