MediaWiki  master
PPNode_Hash_Tree.php
Go to the documentation of this file.
1 <?php
25 // phpcs:ignore Squiz.Classes.ValidClassName.NotCamelCaps
26 class 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  [ $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 $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.
Definition: MWException.php:32
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