MediaWiki REL1_37
PPNode_Hash_Tree.php
Go to the documentation of this file.
1<?php
25// phpcs:ignore Squiz.Classes.ValidClassName.NotCamelCaps
26class PPNode_Hash_Tree implements PPNode {
27
29 public $name;
30
37 private $rawChildren;
38
43 private $store;
44
49 private $index;
50
55 public const NAME = 0;
56
61 public const CHILDREN = 1;
62
70 public function __construct( array $store, $index ) {
71 $this->store = $store;
72 $this->index = $index;
73 list( $this->name, $this->rawChildren ) = $this->store[$index];
74 }
75
85 public static function factory( array $store, $index ) {
86 if ( !isset( $store[$index] ) ) {
87 return false;
88 }
89
90 $descriptor = $store[$index];
91 if ( is_string( $descriptor ) ) {
92 $class = PPNode_Hash_Text::class;
93 } elseif ( is_array( $descriptor ) ) {
94 if ( $descriptor[self::NAME][0] === '@' ) {
95 $class = PPNode_Hash_Attr::class;
96 } else {
97 $class = self::class;
98 }
99 } else {
100 throw new MWException( __METHOD__ . ': invalid node descriptor' );
101 }
102 return new $class( $store, $index );
103 }
104
109 public function __toString() {
110 $inner = '';
111 $attribs = '';
112 for ( $node = $this->getFirstChild(); $node; $node = $node->getNextSibling() ) {
113 if ( $node instanceof PPNode_Hash_Attr ) {
114 $attribs .= ' ' . $node->name . '="' . htmlspecialchars( $node->value ) . '"';
115 } else {
116 $inner .= $node->__toString();
117 }
118 }
119 if ( $inner === '' ) {
120 return "<{$this->name}$attribs/>";
121 } else {
122 return "<{$this->name}$attribs>$inner</{$this->name}>";
123 }
124 }
125
129 public function getChildren() {
130 $children = [];
131 foreach ( $this->rawChildren as $i => $child ) {
132 $children[] = self::factory( $this->rawChildren, $i );
133 }
134 return new PPNode_Hash_Array( $children );
135 }
136
144 public function getFirstChild() {
145 if ( !isset( $this->rawChildren[0] ) ) {
146 return false;
147 } else {
148 return self::factory( $this->rawChildren, 0 );
149 }
150 }
151
159 public function getNextSibling() {
160 return self::factory( $this->store, $this->index + 1 );
161 }
162
169 public function getChildrenOfType( $name ) {
170 $children = [];
171 foreach ( $this->rawChildren as $i => $child ) {
172 if ( is_array( $child ) && $child[self::NAME] === $name ) {
173 $children[] = self::factory( $this->rawChildren, $i );
174 }
175 }
176 return new PPNode_Hash_Array( $children );
177 }
178
183 public function getRawChildren() {
184 return $this->rawChildren;
185 }
186
190 public function getLength() {
191 return false;
192 }
193
198 public function item( $i ) {
199 return false;
200 }
201
205 public function getName() {
206 return $this->name;
207 }
208
218 public function splitArg() {
219 return self::splitRawArg( $this->rawChildren );
220 }
221
227 public static function splitRawArg( array $children ) {
228 $bits = [];
229 foreach ( $children as $i => $child ) {
230 if ( !is_array( $child ) ) {
231 continue;
232 }
233 if ( $child[self::NAME] === 'name' ) {
234 $bits['name'] = new self( $children, $i );
235 if ( isset( $child[self::CHILDREN][0][self::NAME] )
236 && $child[self::CHILDREN][0][self::NAME] === '@index'
237 ) {
238 $bits['index'] = $child[self::CHILDREN][0][self::CHILDREN][0];
239 }
240 } elseif ( $child[self::NAME] === 'value' ) {
241 $bits['value'] = new self( $children, $i );
242 }
243 }
244
245 if ( !isset( $bits['name'] ) ) {
246 throw new MWException( 'Invalid brace node passed to ' . __METHOD__ );
247 }
248 if ( !isset( $bits['index'] ) ) {
249 $bits['index'] = '';
250 }
251 return $bits;
252 }
253
261 public function splitExt() {
262 return self::splitRawExt( $this->rawChildren );
263 }
264
270 public static function splitRawExt( array $children ) {
271 $bits = [];
272 foreach ( $children as $i => $child ) {
273 if ( !is_array( $child ) ) {
274 continue;
275 }
276 switch ( $child[self::NAME] ) {
277 case 'name':
278 $bits['name'] = new self( $children, $i );
279 break;
280 case 'attr':
281 $bits['attr'] = new self( $children, $i );
282 break;
283 case 'inner':
284 $bits['inner'] = new self( $children, $i );
285 break;
286 case 'close':
287 $bits['close'] = new self( $children, $i );
288 break;
289 }
290 }
291 if ( !isset( $bits['name'] ) ) {
292 throw new MWException( 'Invalid ext node passed to ' . __METHOD__ );
293 }
294 return $bits;
295 }
296
303 public function splitHeading() {
304 if ( $this->name !== 'h' ) {
305 throw new MWException( 'Invalid h node passed to ' . __METHOD__ );
306 }
307 return self::splitRawHeading( $this->rawChildren );
308 }
309
315 public static function splitRawHeading( array $children ) {
316 $bits = [];
317 foreach ( $children as $i => $child ) {
318 if ( !is_array( $child ) ) {
319 continue;
320 }
321 if ( $child[self::NAME] === '@i' ) {
322 $bits['i'] = $child[self::CHILDREN][0];
323 } elseif ( $child[self::NAME] === '@level' ) {
324 $bits['level'] = $child[self::CHILDREN][0];
325 }
326 }
327 if ( !isset( $bits['i'] ) ) {
328 throw new MWException( 'Invalid h node passed to ' . __METHOD__ );
329 }
330 return $bits;
331 }
332
339 public function splitTemplate() {
340 return self::splitRawTemplate( $this->rawChildren );
341 }
342
349 public static function splitRawTemplate( array $children ) {
350 $parts = [];
351 $bits = [ 'lineStart' => '' ];
352 foreach ( $children as $i => $child ) {
353 if ( !is_array( $child ) ) {
354 continue;
355 }
356 switch ( $child[self::NAME] ) {
357 case 'title':
358 $bits['title'] = new self( $children, $i );
359 break;
360 case 'part':
361 $parts[] = new self( $children, $i );
362 break;
363 case '@lineStart':
364 $bits['lineStart'] = '1';
365 break;
366 }
367 }
368 if ( !isset( $bits['title'] ) ) {
369 throw new MWException( 'Invalid node passed to ' . __METHOD__ );
370 }
371 $bits['parts'] = new PPNode_Hash_Array( $parts );
372 return $bits;
373 }
374}
MediaWiki exception.
static factory(array $store, $index)
Construct an appropriate PPNode_Hash_* object with a class that depends on what is at the relevant st...
splitExt()
Split an "<ext>" node into an associative array containing name, attr, inner and close All values in ...
static splitRawArg(array $children)
Like splitArg() but for a raw child array.
int $index
The index into $this->store which contains the descriptor of this node.
splitArg()
Split a "<part>" node into an associative array containing:
getNextSibling()
Get the next sibling, or false if there is none.
static splitRawTemplate(array $children)
Like splitTemplate() but for a raw child array.
array $store
The store array for the siblings of this node, including this node itself.
splitHeading()
Split an "<h>" node.
array $rawChildren
The store array for children of this node.
splitTemplate()
Split a "<template>" or "<tplarg>" node.
static splitRawHeading(array $children)
Like splitHeading() but for a raw child array.
static splitRawExt(array $children)
Like splitExt() but for a raw child array.
__construct(array $store, $index)
Construct an object using the data from $store[$index].
getChildrenOfType( $name)
Get an array of the children with a given node name.
__toString()
Convert a node to XML, for debugging.
const CHILDREN
The offset of the child list within descriptors, used in some places for readability.
getFirstChild()
Get the first child, or false if there is none.
getRawChildren()
Get the raw child array.
const NAME
The offset of the name within descriptors, used in some places for readability.
There are three types of nodes:
Definition PPNode.php:35