MediaWiki REL1_39
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 .
115 '="' . htmlspecialchars( $node->value, ENT_COMPAT ) . '"';
116 } else {
117 $inner .= $node->__toString();
118 }
119 }
120 if ( $inner === '' ) {
121 return "<{$this->name}$attribs/>";
122 } else {
123 return "<{$this->name}$attribs>$inner</{$this->name}>";
124 }
125 }
126
130 public function getChildren() {
131 $children = [];
132 foreach ( $this->rawChildren as $i => $child ) {
133 $children[] = self::factory( $this->rawChildren, $i );
134 }
135 return new PPNode_Hash_Array( $children );
136 }
137
145 public function getFirstChild() {
146 if ( !isset( $this->rawChildren[0] ) ) {
147 return false;
148 } else {
149 return self::factory( $this->rawChildren, 0 );
150 }
151 }
152
160 public function getNextSibling() {
161 return self::factory( $this->store, $this->index + 1 );
162 }
163
170 public function getChildrenOfType( $name ) {
171 $children = [];
172 foreach ( $this->rawChildren as $i => $child ) {
173 if ( is_array( $child ) && $child[self::NAME] === $name ) {
174 $children[] = self::factory( $this->rawChildren, $i );
175 }
176 }
177 return new PPNode_Hash_Array( $children );
178 }
179
184 public function getRawChildren() {
185 return $this->rawChildren;
186 }
187
191 public function getLength() {
192 return false;
193 }
194
199 public function item( $i ) {
200 return false;
201 }
202
206 public function getName() {
207 return $this->name;
208 }
209
219 public function splitArg() {
220 return self::splitRawArg( $this->rawChildren );
221 }
222
228 public static function splitRawArg( array $children ) {
229 $bits = [];
230 foreach ( $children as $i => $child ) {
231 if ( !is_array( $child ) ) {
232 continue;
233 }
234 if ( $child[self::NAME] === 'name' ) {
235 $bits['name'] = new self( $children, $i );
236 if ( isset( $child[self::CHILDREN][0][self::NAME] )
237 && $child[self::CHILDREN][0][self::NAME] === '@index'
238 ) {
239 $bits['index'] = $child[self::CHILDREN][0][self::CHILDREN][0];
240 }
241 } elseif ( $child[self::NAME] === 'value' ) {
242 $bits['value'] = new self( $children, $i );
243 }
244 }
245
246 if ( !isset( $bits['name'] ) ) {
247 throw new MWException( 'Invalid brace node passed to ' . __METHOD__ );
248 }
249 if ( !isset( $bits['index'] ) ) {
250 $bits['index'] = '';
251 }
252 return $bits;
253 }
254
262 public function splitExt() {
263 return self::splitRawExt( $this->rawChildren );
264 }
265
271 public static function splitRawExt( array $children ) {
272 $bits = [];
273 foreach ( $children as $i => $child ) {
274 if ( !is_array( $child ) ) {
275 continue;
276 }
277 switch ( $child[self::NAME] ) {
278 case 'name':
279 $bits['name'] = new self( $children, $i );
280 break;
281 case 'attr':
282 $bits['attr'] = new self( $children, $i );
283 break;
284 case 'inner':
285 $bits['inner'] = new self( $children, $i );
286 break;
287 case 'close':
288 $bits['close'] = new self( $children, $i );
289 break;
290 }
291 }
292 if ( !isset( $bits['name'] ) ) {
293 throw new MWException( 'Invalid ext node passed to ' . __METHOD__ );
294 }
295 return $bits;
296 }
297
304 public function splitHeading() {
305 if ( $this->name !== 'h' ) {
306 throw new MWException( 'Invalid h node passed to ' . __METHOD__ );
307 }
308 return self::splitRawHeading( $this->rawChildren );
309 }
310
316 public static function splitRawHeading( array $children ) {
317 $bits = [];
318 foreach ( $children as $i => $child ) {
319 if ( !is_array( $child ) ) {
320 continue;
321 }
322 if ( $child[self::NAME] === '@i' ) {
323 $bits['i'] = $child[self::CHILDREN][0];
324 } elseif ( $child[self::NAME] === '@level' ) {
325 $bits['level'] = $child[self::CHILDREN][0];
326 }
327 }
328 if ( !isset( $bits['i'] ) ) {
329 throw new MWException( 'Invalid h node passed to ' . __METHOD__ );
330 }
331 return $bits;
332 }
333
340 public function splitTemplate() {
341 return self::splitRawTemplate( $this->rawChildren );
342 }
343
350 public static function splitRawTemplate( array $children ) {
351 $parts = [];
352 $bits = [ 'lineStart' => '' ];
353 foreach ( $children as $i => $child ) {
354 if ( !is_array( $child ) ) {
355 continue;
356 }
357 switch ( $child[self::NAME] ) {
358 case 'title':
359 $bits['title'] = new self( $children, $i );
360 break;
361 case 'part':
362 $parts[] = new self( $children, $i );
363 break;
364 case '@lineStart':
365 $bits['lineStart'] = '1';
366 break;
367 }
368 }
369 if ( !isset( $bits['title'] ) ) {
370 throw new MWException( 'Invalid node passed to ' . __METHOD__ );
371 }
372 $bits['parts'] = new PPNode_Hash_Array( $parts );
373 return $bits;
374 }
375}
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.
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.
splitHeading()
Split an "<h>" 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