Split parser related files to have one class in one file
[lhc/web/wiklou.git] / includes / parser / PPNode_DOM.php
1 <?php
2 /**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 * @ingroup Parser
20 */
21
22 /**
23 * @ingroup Parser
24 */
25 // phpcs:ignore Squiz.Classes.ValidClassName.NotCamelCaps
26 class PPNode_DOM implements PPNode {
27
28 /**
29 * @var DOMElement
30 */
31 public $node;
32 public $xpath;
33
34 public function __construct( $node, $xpath = false ) {
35 $this->node = $node;
36 }
37
38 /**
39 * @return DOMXPath
40 */
41 public function getXPath() {
42 if ( $this->xpath === null ) {
43 $this->xpath = new DOMXPath( $this->node->ownerDocument );
44 }
45 return $this->xpath;
46 }
47
48 public function __toString() {
49 if ( $this->node instanceof DOMNodeList ) {
50 $s = '';
51 foreach ( $this->node as $node ) {
52 $s .= $node->ownerDocument->saveXML( $node );
53 }
54 } else {
55 $s = $this->node->ownerDocument->saveXML( $this->node );
56 }
57 return $s;
58 }
59
60 /**
61 * @return bool|PPNode_DOM
62 */
63 public function getChildren() {
64 return $this->node->childNodes ? new self( $this->node->childNodes ) : false;
65 }
66
67 /**
68 * @return bool|PPNode_DOM
69 */
70 public function getFirstChild() {
71 return $this->node->firstChild ? new self( $this->node->firstChild ) : false;
72 }
73
74 /**
75 * @return bool|PPNode_DOM
76 */
77 public function getNextSibling() {
78 return $this->node->nextSibling ? new self( $this->node->nextSibling ) : false;
79 }
80
81 /**
82 * @param string $type
83 *
84 * @return bool|PPNode_DOM
85 */
86 public function getChildrenOfType( $type ) {
87 return new self( $this->getXPath()->query( $type, $this->node ) );
88 }
89
90 /**
91 * @return int
92 */
93 public function getLength() {
94 if ( $this->node instanceof DOMNodeList ) {
95 return $this->node->length;
96 } else {
97 return false;
98 }
99 }
100
101 /**
102 * @param int $i
103 * @return bool|PPNode_DOM
104 */
105 public function item( $i ) {
106 $item = $this->node->item( $i );
107 return $item ? new self( $item ) : false;
108 }
109
110 /**
111 * @return string
112 */
113 public function getName() {
114 if ( $this->node instanceof DOMNodeList ) {
115 return '#nodelist';
116 } else {
117 return $this->node->nodeName;
118 }
119 }
120
121 /**
122 * Split a "<part>" node into an associative array containing:
123 * - name PPNode name
124 * - index String index
125 * - value PPNode value
126 *
127 * @throws MWException
128 * @return array
129 */
130 public function splitArg() {
131 $xpath = $this->getXPath();
132 $names = $xpath->query( 'name', $this->node );
133 $values = $xpath->query( 'value', $this->node );
134 if ( !$names->length || !$values->length ) {
135 throw new MWException( 'Invalid brace node passed to ' . __METHOD__ );
136 }
137 $name = $names->item( 0 );
138 $index = $name->getAttribute( 'index' );
139 return [
140 'name' => new self( $name ),
141 'index' => $index,
142 'value' => new self( $values->item( 0 ) ) ];
143 }
144
145 /**
146 * Split an "<ext>" node into an associative array containing name, attr, inner and close
147 * All values in the resulting array are PPNodes. Inner and close are optional.
148 *
149 * @throws MWException
150 * @return array
151 */
152 public function splitExt() {
153 $xpath = $this->getXPath();
154 $names = $xpath->query( 'name', $this->node );
155 $attrs = $xpath->query( 'attr', $this->node );
156 $inners = $xpath->query( 'inner', $this->node );
157 $closes = $xpath->query( 'close', $this->node );
158 if ( !$names->length || !$attrs->length ) {
159 throw new MWException( 'Invalid ext node passed to ' . __METHOD__ );
160 }
161 $parts = [
162 'name' => new self( $names->item( 0 ) ),
163 'attr' => new self( $attrs->item( 0 ) ) ];
164 if ( $inners->length ) {
165 $parts['inner'] = new self( $inners->item( 0 ) );
166 }
167 if ( $closes->length ) {
168 $parts['close'] = new self( $closes->item( 0 ) );
169 }
170 return $parts;
171 }
172
173 /**
174 * Split a "<h>" node
175 * @throws MWException
176 * @return array
177 */
178 public function splitHeading() {
179 if ( $this->getName() !== 'h' ) {
180 throw new MWException( 'Invalid h node passed to ' . __METHOD__ );
181 }
182 return [
183 'i' => $this->node->getAttribute( 'i' ),
184 'level' => $this->node->getAttribute( 'level' ),
185 'contents' => $this->getChildren()
186 ];
187 }
188 }