MediaWiki REL1_34
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
28 public $name;
29
35 private $rawChildren;
36
40 private $store;
41
45 private $index;
46
51 const NAME = 0;
52
57 const CHILDREN = 1;
58
66 public function __construct( array $store, $index ) {
67 $this->store = $store;
68 $this->index = $index;
69 list( $this->name, $this->rawChildren ) = $this->store[$index];
70 }
71
81 public static function factory( array $store, $index ) {
82 if ( !isset( $store[$index] ) ) {
83 return false;
84 }
85
86 $descriptor = $store[$index];
87 if ( is_string( $descriptor ) ) {
88 $class = PPNode_Hash_Text::class;
89 } elseif ( is_array( $descriptor ) ) {
90 if ( $descriptor[self::NAME][0] === '@' ) {
91 $class = PPNode_Hash_Attr::class;
92 } else {
93 $class = self::class;
94 }
95 } else {
96 throw new MWException( __METHOD__ . ': invalid node descriptor' );
97 }
98 return new $class( $store, $index );
99 }
100
105 public function __toString() {
106 $inner = '';
107 $attribs = '';
108 for ( $node = $this->getFirstChild(); $node; $node = $node->getNextSibling() ) {
109 if ( $node instanceof PPNode_Hash_Attr ) {
110 $attribs .= ' ' . $node->name . '="' . htmlspecialchars( $node->value ) . '"';
111 } else {
112 $inner .= $node->__toString();
113 }
114 }
115 if ( $inner === '' ) {
116 return "<{$this->name}$attribs/>";
117 } else {
118 return "<{$this->name}$attribs>$inner</{$this->name}>";
119 }
120 }
121
125 public function getChildren() {
126 $children = [];
127 foreach ( $this->rawChildren as $i => $child ) {
128 $children[] = self::factory( $this->rawChildren, $i );
129 }
130 return new PPNode_Hash_Array( $children );
131 }
132
140 public function getFirstChild() {
141 if ( !isset( $this->rawChildren[0] ) ) {
142 return false;
143 } else {
144 return self::factory( $this->rawChildren, 0 );
145 }
146 }
147
155 public function getNextSibling() {
156 return self::factory( $this->store, $this->index + 1 );
157 }
158
165 public function getChildrenOfType( $name ) {
166 $children = [];
167 foreach ( $this->rawChildren as $i => $child ) {
168 if ( is_array( $child ) && $child[self::NAME] === $name ) {
169 $children[] = self::factory( $this->rawChildren, $i );
170 }
171 }
172 return new PPNode_Hash_Array( $children );
173 }
174
179 public function getRawChildren() {
180 return $this->rawChildren;
181 }
182
186 public function getLength() {
187 return false;
188 }
189
194 public function item( $i ) {
195 return false;
196 }
197
201 public function getName() {
202 return $this->name;
203 }
204
214 public function splitArg() {
215 return self::splitRawArg( $this->rawChildren );
216 }
217
223 public static function splitRawArg( array $children ) {
224 $bits = [];
225 foreach ( $children as $i => $child ) {
226 if ( !is_array( $child ) ) {
227 continue;
228 }
229 if ( $child[self::NAME] === 'name' ) {
230 $bits['name'] = new self( $children, $i );
231 if ( isset( $child[self::CHILDREN][0][self::NAME] )
232 && $child[self::CHILDREN][0][self::NAME] === '@index'
233 ) {
234 $bits['index'] = $child[self::CHILDREN][0][self::CHILDREN][0];
235 }
236 } elseif ( $child[self::NAME] === 'value' ) {
237 $bits['value'] = new self( $children, $i );
238 }
239 }
240
241 if ( !isset( $bits['name'] ) ) {
242 throw new MWException( 'Invalid brace node passed to ' . __METHOD__ );
243 }
244 if ( !isset( $bits['index'] ) ) {
245 $bits['index'] = '';
246 }
247 return $bits;
248 }
249
257 public function splitExt() {
258 return self::splitRawExt( $this->rawChildren );
259 }
260
266 public static function splitRawExt( array $children ) {
267 $bits = [];
268 foreach ( $children as $i => $child ) {
269 if ( !is_array( $child ) ) {
270 continue;
271 }
272 switch ( $child[self::NAME] ) {
273 case 'name':
274 $bits['name'] = new self( $children, $i );
275 break;
276 case 'attr':
277 $bits['attr'] = new self( $children, $i );
278 break;
279 case 'inner':
280 $bits['inner'] = new self( $children, $i );
281 break;
282 case 'close':
283 $bits['close'] = new self( $children, $i );
284 break;
285 }
286 }
287 if ( !isset( $bits['name'] ) ) {
288 throw new MWException( 'Invalid ext node passed to ' . __METHOD__ );
289 }
290 return $bits;
291 }
292
299 public function splitHeading() {
300 if ( $this->name !== 'h' ) {
301 throw new MWException( 'Invalid h node passed to ' . __METHOD__ );
302 }
303 return self::splitRawHeading( $this->rawChildren );
304 }
305
311 public static function splitRawHeading( array $children ) {
312 $bits = [];
313 foreach ( $children as $i => $child ) {
314 if ( !is_array( $child ) ) {
315 continue;
316 }
317 if ( $child[self::NAME] === '@i' ) {
318 $bits['i'] = $child[self::CHILDREN][0];
319 } elseif ( $child[self::NAME] === '@level' ) {
320 $bits['level'] = $child[self::CHILDREN][0];
321 }
322 }
323 if ( !isset( $bits['i'] ) ) {
324 throw new MWException( 'Invalid h node passed to ' . __METHOD__ );
325 }
326 return $bits;
327 }
328
335 public function splitTemplate() {
336 return self::splitRawTemplate( $this->rawChildren );
337 }
338
344 public static function splitRawTemplate( array $children ) {
345 $parts = [];
346 $bits = [ 'lineStart' => '' ];
347 foreach ( $children as $i => $child ) {
348 if ( !is_array( $child ) ) {
349 continue;
350 }
351 switch ( $child[self::NAME] ) {
352 case 'title':
353 $bits['title'] = new self( $children, $i );
354 break;
355 case 'part':
356 $parts[] = new self( $children, $i );
357 break;
358 case '@lineStart':
359 $bits['lineStart'] = '1';
360 break;
361 }
362 }
363 if ( !isset( $bits['title'] ) ) {
364 throw new MWException( 'Invalid node passed to ' . __METHOD__ );
365 }
366 $bits['parts'] = new PPNode_Hash_Array( $parts );
367 return $bits;
368 }
369}
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:
$index
The index into $this->store which contains the descriptor of this node.
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.
$store
The store array for the siblings of this node, including this node itself.
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.
$rawChildren
The store array for children of this node.
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