Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
95.82% |
275 / 287 |
|
50.00% |
5 / 10 |
CRAP | |
0.00% |
0 / 1 |
BlockLevelPass | |
96.15% |
275 / 286 |
|
50.00% |
5 / 10 |
119 | |
0.00% |
0 / 1 |
doBlockLevels | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
hasOpenParagraph | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
closeParagraph | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
getCommon | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
openList | |
91.67% |
11 / 12 |
|
0.00% |
0 / 1 |
5.01 | |||
nextItem | |
91.67% |
11 / 12 |
|
0.00% |
0 / 1 |
7.03 | |||
closeList | |
90.91% |
10 / 11 |
|
0.00% |
0 / 1 |
5.02 | |||
execute | |
97.04% |
131 / 135 |
|
0.00% |
0 / 1 |
54 | |||
findColonNoLinks | |
95.92% |
94 / 98 |
|
0.00% |
0 / 1 |
39 |
1 | <?php |
2 | |
3 | /** |
4 | * This is the part of the wikitext parser which handles automatic paragraphs |
5 | * and conversion of start-of-line prefixes to HTML lists. |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. |
11 | * |
12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU General Public License along |
18 | * with this program; if not, write to the Free Software Foundation, Inc., |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
20 | * http://www.gnu.org/copyleft/gpl.html |
21 | * |
22 | * @file |
23 | * @ingroup Parser |
24 | * @internal |
25 | */ |
26 | |
27 | namespace MediaWiki\Parser; |
28 | |
29 | use LogicException; |
30 | use StringUtils; |
31 | |
32 | class BlockLevelPass { |
33 | /** @var bool */ |
34 | private $DTopen = false; |
35 | /** @var bool */ |
36 | private $inPre = false; |
37 | /** @var string */ |
38 | private $lastParagraph = ''; |
39 | /** @var bool */ |
40 | private $lineStart; |
41 | /** @var string */ |
42 | private $text; |
43 | |
44 | # State constants for the definition list colon extraction |
45 | private const COLON_STATE_TEXT = 0; |
46 | private const COLON_STATE_TAG = 1; |
47 | private const COLON_STATE_TAGSTART = 2; |
48 | private const COLON_STATE_CLOSETAG = 3; |
49 | private const COLON_STATE_TAGSLASH = 4; |
50 | private const COLON_STATE_COMMENT = 5; |
51 | private const COLON_STATE_COMMENTDASH = 6; |
52 | private const COLON_STATE_COMMENTDASHDASH = 7; |
53 | private const COLON_STATE_LC = 8; |
54 | |
55 | /** |
56 | * Make lists from lines starting with ':', '*', '#', etc. |
57 | * |
58 | * @param string $text |
59 | * @param bool $lineStart Whether or not this is at the start of a line. |
60 | * @return string The lists rendered as HTML |
61 | * @internal |
62 | */ |
63 | public static function doBlockLevels( $text, $lineStart ) { |
64 | $pass = new self( $text, $lineStart ); |
65 | return $pass->execute(); |
66 | } |
67 | |
68 | /** |
69 | * @param string $text |
70 | * @param bool $lineStart |
71 | */ |
72 | private function __construct( $text, $lineStart ) { |
73 | $this->text = $text; |
74 | $this->lineStart = $lineStart; |
75 | } |
76 | |
77 | /** |
78 | * @return bool |
79 | */ |
80 | private function hasOpenParagraph() { |
81 | return $this->lastParagraph !== ''; |
82 | } |
83 | |
84 | /** |
85 | * If a pre or p is open, return the corresponding close tag and update |
86 | * the state. If no tag is open, return an empty string. |
87 | * @param bool $atTheEnd Omit trailing newline if we've reached the end. |
88 | * @return string |
89 | */ |
90 | private function closeParagraph( $atTheEnd = false ) { |
91 | $result = ''; |
92 | if ( $this->hasOpenParagraph() ) { |
93 | $result = '</' . $this->lastParagraph . '>'; |
94 | if ( !$atTheEnd ) { |
95 | $result .= "\n"; |
96 | } |
97 | } |
98 | $this->inPre = false; |
99 | $this->lastParagraph = ''; |
100 | return $result; |
101 | } |
102 | |
103 | /** |
104 | * getCommon() returns the length of the longest common substring |
105 | * of both arguments, starting at the beginning of both. |
106 | * |
107 | * @param string $st1 |
108 | * @param string $st2 |
109 | * |
110 | * @return int |
111 | */ |
112 | private function getCommon( $st1, $st2 ) { |
113 | $shorter = min( strlen( $st1 ), strlen( $st2 ) ); |
114 | |
115 | for ( $i = 0; $i < $shorter; ++$i ) { |
116 | if ( $st1[$i] !== $st2[$i] ) { |
117 | break; |
118 | } |
119 | } |
120 | return $i; |
121 | } |
122 | |
123 | /** |
124 | * Open the list item element identified by the prefix character. |
125 | * |
126 | * @param string $char |
127 | * |
128 | * @return string |
129 | */ |
130 | private function openList( $char ) { |
131 | $result = $this->closeParagraph(); |
132 | |
133 | if ( $char === '*' ) { |
134 | $result .= "<ul><li>"; |
135 | } elseif ( $char === '#' ) { |
136 | $result .= "<ol><li>"; |
137 | } elseif ( $char === ':' ) { |
138 | $result .= "<dl><dd>"; |
139 | } elseif ( $char === ';' ) { |
140 | $result .= "<dl><dt>"; |
141 | $this->DTopen = true; |
142 | } else { |
143 | $result = '<!-- ERR 1 -->'; |
144 | } |
145 | |
146 | return $result; |
147 | } |
148 | |
149 | /** |
150 | * Close the current list item and open the next one. |
151 | * @param string $char |
152 | * |
153 | * @return string |
154 | */ |
155 | private function nextItem( $char ) { |
156 | if ( $char === '*' || $char === '#' ) { |
157 | return "</li>\n<li>"; |
158 | } elseif ( $char === ':' || $char === ';' ) { |
159 | $close = "</dd>\n"; |
160 | if ( $this->DTopen ) { |
161 | $close = "</dt>\n"; |
162 | } |
163 | if ( $char === ';' ) { |
164 | $this->DTopen = true; |
165 | return $close . '<dt>'; |
166 | } else { |
167 | $this->DTopen = false; |
168 | return $close . '<dd>'; |
169 | } |
170 | } |
171 | return '<!-- ERR 2 -->'; |
172 | } |
173 | |
174 | /** |
175 | * Close the current list item identified by the prefix character. |
176 | * @param string $char |
177 | * |
178 | * @return string |
179 | */ |
180 | private function closeList( $char ) { |
181 | if ( $char === '*' ) { |
182 | $text = "</li></ul>"; |
183 | } elseif ( $char === '#' ) { |
184 | $text = "</li></ol>"; |
185 | } elseif ( $char === ':' ) { |
186 | if ( $this->DTopen ) { |
187 | $this->DTopen = false; |
188 | $text = "</dt></dl>"; |
189 | } else { |
190 | $text = "</dd></dl>"; |
191 | } |
192 | } else { |
193 | return '<!-- ERR 3 -->'; |
194 | } |
195 | return $text; |
196 | } |
197 | |
198 | /** |
199 | * Execute the pass. |
200 | * @return string |
201 | */ |
202 | private function execute() { |