Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
67.35% |
33 / 49 |
|
36.36% |
8 / 22 |
CRAP | |
0.00% |
0 / 1 |
ScribuntoEngineBase | |
67.35% |
33 / 49 |
|
36.36% |
8 / 22 |
55.30 | |
0.00% |
0 / 1 |
newModule | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
runConsole | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
getSoftwareInfo | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
__construct | |
80.00% |
4 / 5 |
|
0.00% |
0 / 1 |
3.07 | |||
__destruct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
destroy | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
setTitle | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getTitle | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getOption | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
newException | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDefaultExceptionParams | |
80.00% |
4 / 5 |
|
0.00% |
0 / 1 |
2.03 | |||
fetchModuleFromParser | |
81.82% |
9 / 11 |
|
0.00% |
0 / 1 |
4.10 | |||
validate | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getResourceUsage | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getGeSHiLanguage | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getCodeEditorLanguage | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getParser | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getLibraries | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
getLibraryPaths | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
reportLimitData | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
formatLimitData | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
updateRedirect | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getRedirectTarget | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
makeRedirectContent | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
supportsRedirects | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * Wikitext scripting infrastructure for MediaWiki: base classes. |
4 | * Copyright (C) 2012 Victor Vasiliev <vasilvv@gmail.com> et al |
5 | * https://www.mediawiki.org/ |
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 | |
23 | namespace MediaWiki\Extension\Scribunto; |
24 | |
25 | use MediaWiki\Extension\Scribunto\Hooks\HookRunner; |
26 | use MediaWiki\MediaWikiServices; |
27 | use MediaWiki\Parser\ParserOutput; |
28 | use MediaWiki\Status\Status; |
29 | use MediaWiki\Title\Title; |
30 | use Parser; |
31 | |
32 | /** |
33 | * Base class for all script engines. Includes all code |
34 | * not related to particular modules, like tracking links between |
35 | * modules or loading module texts. |
36 | */ |
37 | abstract class ScribuntoEngineBase { |
38 | |
39 | // Flags for ScribuntoEngineBase::getResourceUsage() |
40 | public const CPU_SECONDS = 1; |
41 | public const MEM_PEAK_BYTES = 2; |
42 | |
43 | /** |
44 | * @var Title|null |
45 | */ |
46 | protected $title; |
47 | |
48 | /** |
49 | * @var array |
50 | */ |
51 | protected $options; |
52 | |
53 | /** |
54 | * @var (ScribuntoModuleBase|null)[] |
55 | */ |
56 | protected $modules = []; |
57 | |
58 | /** |
59 | * @var Parser|null |
60 | */ |
61 | protected $parser; |
62 | |
63 | /** |
64 | * Creates a new module object within this engine |
65 | * |
66 | * @param string $text |
67 | * @param string|bool $chunkName |
68 | * @return ScribuntoModuleBase |
69 | */ |
70 | abstract protected function newModule( $text, $chunkName ); |
71 | |
72 | /** |
73 | * Run an interactive console request |
74 | * |
75 | * @param array $params Associative array. Options are: |
76 | * - title: The title object for the module being debugged |
77 | * - content: The text content of the module |
78 | * - prevQuestions: An array of previous "questions" used to establish the state |
79 | * - question: The current "question", a string script |
80 | * |
81 | * @return array containing: |
82 | * - print: The resulting print buffer |
83 | * - return: The resulting return value |
84 | */ |
85 | abstract public function runConsole( array $params ); |
86 | |
87 | /** |
88 | * Get software information for Special:Version |
89 | * @param array &$software |
90 | */ |
91 | abstract public function getSoftwareInfo( array &$software ); |
92 | |
93 | /** |
94 | * @param array $options Associative array of options: |
95 | * - parser: A Parser object |
96 | */ |
97 | public function __construct( array $options ) { |
98 | $this->options = $options; |
99 | if ( isset( $options['parser'] ) ) { |
100 | $this->parser = $options['parser']; |
101 | } |
102 | if ( isset( $options['title'] ) ) { |
103 | $this->title = $options['title']; |
104 | } |
105 | } |
106 | |
107 | public function __destruct() { |
108 | $this->destroy(); |
109 | } |
110 | |
111 | public function destroy() { |
112 | // Break reference cycles |
113 | $this->parser = null; |
114 | $this->title = null; |
115 | $this->modules = []; |
116 | } |
117 | |
118 | /** |
119 | * @param Title $title |
120 | */ |
121 | public function setTitle( $title ) { |
122 | $this->title = $title; |
123 | } |
124 | |
125 | /** |
126 | * @return Title |
127 | */ |
128 | public function getTitle() { |
129 | return $this->title; |
130 | } |
131 | |
132 | /** |
133 | * Get an element from the configuration array |
134 | * |
135 | * @param string $optionName |
136 | * @return mixed |
137 | */ |
138 | public function getOption( $optionName ) { |
139 | return $this->options[$optionName] ?? null; |
140 | } |
141 | |
142 | /** |
143 | * @param string $message |
144 | * @param array $params |
145 | * @return ScribuntoException |
146 | */ |
147 | public function newException( $message, array $params = [] ) { |
148 | return new ScribuntoException( $message, $this->getDefaultExceptionParams() + $params ); |
149 | } |
150 | |
151 | /** |
152 | * @return array |
153 | */ |
154 | public function getDefaultExceptionParams() { |
155 | $params = []; |
156 | if ( $this->title ) { |
157 | $params['title'] = $this->title; |
158 | } else { |
159 | wfDeprecated( __METHOD__ . ' without valid title for engine', '1.42' ); |
160 | } |
161 | return $params; |
162 | } |
163 | |
164 | /** |
165 | * Load a module from some parser-defined template loading mechanism and |
166 | * register a parser output dependency. |
167 | * |
168 | * Does not initialize the module, i.e. do not expect it to complain if the module |
169 | * text is garbage or has syntax error. Returns a module or null if it doesn't exist. |
170 | * |
171 | * @param Title $title The title of the module |
172 | * @return ScribuntoModuleBase|null |
173 | */ |
174 | public function fetchModuleFromParser( Title $title ) { |
175 | $key = $title->getPrefixedDBkey(); |
176 | if ( !array_key_exists( $key, $this->modules ) ) { |
177 | [ $text, $finalTitle ] = $this->parser->fetchTemplateAndTitle( $title ); |
178 | if ( $text === false ) { |
179 | $this->modules[$key] = null; |
180 | return null; |
181 | } |
182 | |
183 | $finalKey = $finalTitle->getPrefixedDBkey(); |
184 | if ( !isset( $this->modules[$finalKey] ) ) { |
185 | $this->modules[$finalKey] = $this->newModule( $text, $finalKey ); |
186 | } |
187 | // $finalKey may be different from $key in the case of redirects; |
188 | // store the module in both places. |
189 | // @phan-suppress-next-line PhanTypeMismatchProperty |
190 | $this->modules[$key] = $this->modules[$finalKey]; |
191 | } |
192 | return $this->modules[$key]; |
193 | } |
194 | |
195 | /** |
196 | * Validates the script and returns a Status object containing the syntax |
197 | * errors for the given code. |
198 | * |
199 | * @param string $text |
200 | * @param string|bool $chunkName |
201 | * @return Status |
202 | */ |
203 | public function validate( $text, $chunkName = false ) { |
204 | $module = $this->newModule( $text, $chunkName ); |
205 | return $module->validate(); |
206 | } |
207 | |
208 | /** |
209 | * Get CPU and memory usage information, if the script engine |
210 | * provides it. |
211 | * |
212 | * If the script engine is capable of reporting CPU and memory usage |
213 | * data, it should override this implementation. |
214 | * |
215 | * @param int $resource One of ScribuntoEngineBase::CPU_SECONDS |
216 | * or ScribuntoEngineBase::MEM_PEAK_BYTES. |
217 | * @return float|int|false Resource usage for the specified resource |
218 | * or false if not available. |
219 | */ |
220 | public function getResourceUsage( $resource ) { |
221 | return false; |
222 | } |
223 | |
224 | /** |
225 | * Get the language for GeSHi syntax highlighter. |
226 | * @return string|false |
227 | */ |
228 | public function getGeSHiLanguage() { |
229 | return false; |
230 | } |
231 | |
232 | /** |
233 | * Get the language for Ace code editor. |
234 | * @return string|false |
235 | */ |
236 | public function getCodeEditorLanguage() { |
237 | return false; |
238 | } |
239 | |
240 | /** |
241 | * @return Parser |
242 | */ |
243 | public function getParser() { |
244 | return $this->parser; |
245 | } |
246 | |
247 | /** |
248 | * Load a list of all libraries supported by this engine |
249 | * |
250 | * The return value is an array with keys being the library name seen by |
251 | * the module and values being either a PHP class name or an array with the |
252 | * following elements: |
253 | * - class: (string) Class to load (required) |
254 | * - deferLoad: (bool) Library should not be loaded at startup; modules |
255 | * needing the library must request it (e.g. via 'require' in Lua) |
256 | * |
257 | * @param string $engine script engine we're using (eg: lua) |
258 | * @param array $coreLibraries Array of core libraries we support |
259 | * @return array |
260 | */ |
261 | protected function getLibraries( $engine, array $coreLibraries = [] ) { |
262 | $extraLibraries = []; |
263 | ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) ) |
264 | ->onScribuntoExternalLibraries( $engine, $extraLibraries ); |
265 | return $coreLibraries + $extraLibraries; |
266 | } |
267 | |
268 | /** |
269 | * Load a list of all paths libraries can be in for this engine |
270 | * |
271 | * @param string $engine script engine we're using (eg: lua) |
272 | * @param array $coreLibraryPaths Array of library paths to use by default |
273 | * @return array |
274 | */ |
275 | protected function getLibraryPaths( $engine, array $coreLibraryPaths = [] ) { |
276 | $extraLibraryPaths = []; |
277 | ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) ) |
278 | ->onScribuntoExternalLibraryPaths( $engine, $extraLibraryPaths ); |
279 | return array_merge( $coreLibraryPaths, $extraLibraryPaths ); |
280 | } |
281 | |
282 | /** |
283 | * Add limit report data to a ParserOutput object |
284 | * |
285 | * @param ParserOutput $output ParserOutput object in which to add limit data |
286 | */ |
287 | public function reportLimitData( ParserOutput $output ) { |
288 | } |
289 | |
290 | /** |
291 | * Format limit report data |
292 | * |
293 | * @param string $key |
294 | * @param mixed &$value |
295 | * @param string &$report |
296 | * @param bool $isHTML |
297 | * @param bool $localize |
298 | * @return bool |
299 | */ |
300 | public function formatLimitData( $key, &$value, &$report, $isHTML, $localize ) { |
301 | return true; |
302 | } |
303 | |
304 | /** |
305 | * @see Content::updateRedirect |
306 | * |
307 | * @param ScribuntoContent $content |
308 | * @param Title $target |
309 | * @return ScribuntoContent |
310 | */ |
311 | public function updateRedirect( ScribuntoContent $content, Title $target ): ScribuntoContent { |
312 | return $content; |
313 | } |
314 | |
315 | /** |
316 | * @see Content::getRedirectTarget |
317 | * |
318 | * @param ScribuntoContent $content |
319 | * @return Title|null |
320 | */ |
321 | public function getRedirectTarget( ScribuntoContent $content ) { |
322 | return null; |
323 | } |
324 | |
325 | /** |
326 | * @see ContentHandler::makeRedirectContent |
327 | * @param Title $destination |
328 | * @param string $text |
329 | * @return ScribuntoContent|null |
330 | */ |
331 | public function makeRedirectContent( Title $destination, $text = '' ) { |
332 | return null; |
333 | } |
334 | |
335 | /** |
336 | * @see ContentHandler::supportsRedirects |
337 | * @return bool false |
338 | */ |
339 | public function supportsRedirects(): bool { |
340 | return false; |
341 | } |
342 | } |