Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
60.80% |
107 / 176 |
|
43.18% |
19 / 44 |
CRAP | |
0.00% |
0 / 1 |
MathRenderer | |
60.80% |
107 / 176 |
|
43.18% |
19 / 44 |
476.35 | |
0.00% |
0 / 1 |
setRawError | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
__construct | |
61.90% |
13 / 21 |
|
0.00% |
0 / 1 |
7.99 | |||
getRenderer | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
render | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
getHtmlOutput | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
getError | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
getInputHash | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
2 | |||
readFromCache | |
80.00% |
4 / 5 |
|
0.00% |
0 / 1 |
2.03 | |||
dbInArray | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
initializeFromCache | |
90.00% |
9 / 10 |
|
0.00% |
0 / 1 |
5.03 | |||
writeToCache | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
dbOutArray | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
1 | |||
setRestbaseInterface | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
hasWarnings | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
addTrackingCategories | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
getChecker | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getAttributes | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
writeCache | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
2 | |||
getTex | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getMode | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setMode | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
setTex | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
getMathml | |
66.67% |
2 / 3 |
|
0.00% |
0 / 1 |
2.15 | |||
setMathml | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getParams | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setParams | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isChanged | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isPurge | |
41.67% |
5 / 12 |
|
0.00% |
0 / 1 |
13.15 | |||
setPurge | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getLastError | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setMathStyle | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
getMathStyle | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isTexSecure | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
checkTeX | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
6 | |||
isInDatabase | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getUserInputTex | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getID | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setID | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setSvg | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getSvg | |
66.67% |
2 / 3 |
|
0.00% |
0 / 1 |
3.33 | |||
getMathTableName | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
getModeName | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
setInputType | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getInputType | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
doCheck | |
50.00% |
5 / 10 |
|
0.00% |
0 / 1 |
4.12 | |||
debug | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getCacheKey | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | /** |
3 | * MediaWiki math extension |
4 | * |
5 | * @copyright 2002-2012 Tomasz Wegrzanowski, Brion Vibber, Moritz Schubotz, |
6 | * and other MediaWiki contributors |
7 | * @license GPL-2.0-or-later |
8 | * |
9 | * @file |
10 | */ |
11 | |
12 | namespace MediaWiki\Extension\Math; |
13 | |
14 | use MediaWiki\Context\RequestContext; |
15 | use MediaWiki\Extension\Math\InputCheck\BaseChecker; |
16 | use MediaWiki\Logger\LoggerFactory; |
17 | use MediaWiki\MediaWikiServices; |
18 | use MediaWiki\Message\Message; |
19 | use MediaWiki\Parser\Parser; |
20 | use MediaWiki\Parser\Sanitizer; |
21 | use Psr\Log\LoggerInterface; |
22 | use StringUtils; |
23 | use Wikimedia\ObjectCache\WANObjectCache; |
24 | |
25 | /** |
26 | * Abstract base class with static methods for rendering the <math> tags using |
27 | * different technologies. These static methods create a new instance of the |
28 | * extending classes and render the math tags based on the mode setting of the user. |
29 | * Furthermore, this class handles the caching of the rendered output. |
30 | * |
31 | * @author Tomasz Wegrzanowski |
32 | * @author Brion Vibber |
33 | * @author Moritz Schubotz |
34 | */ |
35 | abstract class MathRenderer { |
36 | |
37 | // REPRESENTATIONS OF THE MATHEMATICAL CONTENT |
38 | /** @var ?string tex representation */ |
39 | protected $tex = ''; |
40 | /** @var string MathML content and presentation */ |
41 | protected $mathml = ''; |
42 | /** @var string SVG layout only (no semantics) */ |
43 | protected $svg = ''; |
44 | /** @var string the original user input string (which was used to calculate the inputhash) */ |
45 | protected $userInputTex = ''; |
46 | // FURTHER PROPERTIES OF THE MATHEMATICAL CONTENT |
47 | /** @var string ('inlineDisplaystyle'|'display'|'inline'|'linebreak') the rendering style */ |
48 | protected $mathStyle = 'inlineDisplaystyle'; |
49 | /** @var array with userdefined parameters passed to the extension (not used) */ |
50 | protected $params = []; |
51 | /** @var string a userdefined identifier to link to the equation. */ |
52 | protected $id = ''; |
53 | |
54 | // STATE OF THE CLASS INSTANCE |
55 | /** @var bool has variable tex been security-checked */ |
56 | protected $texSecure = false; |
57 | /** @var bool has the mathematical content changed */ |
58 | protected $changed = false; |
59 | /** @var bool|null is there a database entry for the mathematical content */ |
60 | protected $storedInCache = null; |
61 | /** @var bool is there a request to purge the existing mathematical content */ |
62 | protected $purge = false; |
63 | /** @var string with last occurred error */ |
64 | protected $lastError = ''; |
65 | /** @var string binary packed inputhash */ |
66 | protected $inputHash = ''; |
67 | /** @var string rendering mode */ |
68 | protected $mode = MathConfig::MODE_MATHML; |
69 | /** @var string input type */ |
70 | protected $inputType = 'tex'; |
71 | /** @var MathRestbaseInterface used for checking */ |
72 | protected $rbi; |
73 | /** @var array with rendering warnings */ |
74 | protected $warnings; |
75 | /** @var LoggerInterface */ |
76 | private $logger; |
77 | |
78 | private WANObjectCache $cache; |
79 | private MathConfig $mathConfig; |
80 | private bool $rawError = false; |
81 | |
82 | public function setRawError( bool $rawError ): void { |
83 | $this->rawError = $rawError; |
84 | } |
85 | |
86 | /** |
87 | * Constructs a base MathRenderer |
88 | * |
89 | * @param string $tex (optional) LaTeX markup |
90 | * @param array $params (optional) HTML attributes |
91 | * @param WANObjectCache|null $cache (optional) |
92 | * @param MathConfig|null $mathConfig (optional) |
93 | */ |
94 | public function __construct( string $tex = '', $params = [], $cache = null, $mathConfig = null ) { |
95 | $this->cache = $cache ?? MediaWikiServices::getInstance()->getMainWANObjectCache(); |
96 | $this->mathConfig = $mathConfig ?? Math::getMathConfig(); |
97 | $this->params = $params; |
98 | if ( isset( $params['id'] ) ) { |
99 | $this->id = $params['id']; |
100 | } |
101 | if ( isset( $params['display'] ) ) { |
102 | $layoutMode = $params['display']; |
103 | if ( $layoutMode == 'block' ) { |
104 | $this->mathStyle = 'display'; |
105 | $tex = '{\displaystyle ' . $tex . '}'; |
106 | $this->inputType = 'tex'; |
107 | } elseif ( $layoutMode == 'inline' ) { |
108 | $this->mathStyle = 'inline'; |
109 | $this->inputType = 'inline-tex'; |
110 | $tex = '{\textstyle ' . $tex . '}'; |
111 | } elseif ( $layoutMode == 'linebreak' ) { |
112 | $this->mathStyle = 'linebreak'; |
113 | $tex = '\[ ' . $tex . ' \]'; |
114 | } |
115 | } |
116 | // TODO: Implement caching for attributes of the math tag |
117 | // Currently the key for the database entry relating to an equation |
118 | // is md5($tex) the new option to determine if the tex input |
119 | // is rendered in displaystyle or textstyle would require a database |
120 | // layout change to use a composite key e.g. (md5($tex),$mathStyle). |
121 | // As a workaround we use the prefix \displaystyle so that the key becomes |
122 | // md5((\{\\displaystyle|\{\\textstyle)?\s?$tex\}?) |
123 | // The new value of $tex string describes now how the rendering should look like. |
124 | // The variable MathRenderer::mathStyle determines if the rendered equation should |
125 | // be centered in a new line, or just in be displayed in the current line. |
126 | $this->userInputTex = $tex; |
127 | $this->tex = $tex; |
128 | $this->logger = LoggerFactory::getInstance( 'Math' ); |
129 | } |
130 | |
131 | /** |
132 | * Static factory method for getting a renderer based on mode |
133 | * |
134 | * @deprecated since 3.0.0. Use Math.RendererFactory service instead. |
135 | * @param string $tex LaTeX markup |
136 | * @param array $params HTML attributes |
137 | * @param string $mode indicating rendering mode |
138 | * @return self appropriate renderer for mode |
139 | */ |
140 | public static function getRenderer( $tex, $params = [], $mode = MathConfig::MODE_MATHML ) { |
141 | return MediaWikiServices::getInstance() |
142 | ->get( 'Math.RendererFactory' ) |
143 | ->getRenderer( $tex, $params, $mode ); |
144 | } |
145 | |
146 | /** |
147 | * Performs the rendering |
148 | * |
149 | * @return bool if rendering was successful. |
150 | */ |
151 | abstract public function render(); |
152 | |
153 | /** |
154 | * @param bool $svg |
155 | * @return string Html output that is embedded in the page |
156 | */ |
157 | abstract public function getHtmlOutput( bool $svg = true ): string; |
158 | |
159 | /** |
160 | * texvc error messages |
161 | * TODO: update to MathML |
162 | * Returns an internationalized HTML error string |
163 | * |
164 | * @param string $msg message key for specific error |
165 | * @param string ...$parameters zero or more message |
166 | * parameters for specific error |
167 | * |
168 | * @return string HTML error string |
169 | */ |
170 | public function getError( $msg, ...$parameters ) { |
171 | if ( $this->rawError ) { |
172 | return 'Error: ' . $msg . ' param ' . implode( ',', $parameters ); |
173 | } |
174 | $mf = wfMessage( 'math_failure' )->inContentLanguage()->escaped(); |
175 | $errmsg = wfMessage( $msg, $parameters )->inContentLanguage()->escaped(); |
176 | $source = htmlspecialchars( str_replace( "\n", ' ', $this->tex ) ); |
177 | return "<strong class=\"error texerror\">$mf ($errmsg): $source</strong>\n"; |
178 | } |
179 | |
180 | /** |
181 | * Return hash of input |
182 | * |
183 | * @return string hash |
184 | */ |
185 | public function getInputHash(): string { |
186 | if ( !$this->inputHash ) { |
187 | $this->inputHash = hash( 'md5', // xxh128 might be better when dropping php 7 support |
188 | $this->mode . |
189 | $this->userInputTex . |
190 | implode( $this->params ) |
191 | ); |
192 | } |
193 | return $this->inputHash; |
194 | } |
195 | |
196 | /** |
197 | * Reads rendering data from database |
198 | * |
199 | * @return bool true if read successfully, false otherwise |
200 | */ |
201 | public function readFromCache(): bool { |
202 | $rpage = $this->cache->get( $this->getCacheKey() ); |
203 | if ( $rpage !== false ) { |
204 | $this->initializeFromCache( $rpage ); |
205 | return true; |
206 | } else { |
207 | # Missing from the database and/or the render cache |
208 | return false; |
209 | } |
210 | } |
211 | |
212 | /** |
213 | * @return array with the database column names |
214 | */ |
215 | protected function dbInArray() { |
216 | $in = [ 'math_inputhash', |
217 | 'math_mathml', |
218 | 'math_inputtex', |
219 | 'math_tex', |
220 | 'math_svg' |
221 | ]; |
222 | return $in; |
223 | } |
224 | |
225 | /** |
226 | * Reads the values from the database but does not overwrite set values with empty values |
227 | * @param array $rpage (a database row) |
228 | */ |
229 | public function initializeFromCache( $rpage ) { |
230 | $this->inputHash = $rpage['math_inputhash']; // MUST NOT BE NULL |
231 | if ( isset( $rpage['math_mathml'] ) ) { |
232 | $this->mathml = $rpage['math_mathml']; |
233 | } |
234 | if ( isset( $rpage['math_inputtex'] ) ) { |
235 | $this->userInputTex = $rpage['math_inputtex']; |
236 | } |
237 | if ( isset( $rpage['math_tex'] ) ) { |
238 | $this->tex = $rpage['math_tex']; |
239 | } |
240 | if ( isset( $rpage['math_svg'] ) ) { |
241 | $this->svg = $rpage['math_svg']; |
242 | } |
243 | $this->changed = false; |
244 | } |
245 | |
246 | /** |
247 | * Writes rendering entry to cache. |
248 | * |
249 | * WARNING: Use writeCache() instead of this method to be sure that all |
250 | * renderer specific (such as squid caching) are taken into account. |
251 | * This function stores the values that are currently present in the class |
252 | * to the cache even if they are empty. |
253 | * |
254 | * This function can be seen as protected function. |
255 | */ |
256 | public function writeToCache() { |
257 | $outArray = $this->dbOutArray(); |
258 | $this->cache->set( $this->getCacheKey(), $outArray ); |
259 | } |
260 | |
261 | /** |
262 | * Gets an array that matches the variables of the class to the database columns |
263 | * @return array |
264 | */ |
265 | protected function dbOutArray() { |
266 | $out = [ |
267 | 'math_inputhash' => $this->getInputHash(), |
268 | 'math_mathml' => $this->mathml, |
269 | 'math_inputtex' => $this->userInputTex, |
270 | 'math_tex' => $this->tex, |
271 | 'math_svg' => $this->svg, |
272 | 'math_mode' => $this->mode |
273 | ]; |
274 | return $out; |
275 | } |
276 | |
277 | /** |
278 | * @param MathRestbaseInterface $param |
279 | */ |
280 | public function setRestbaseInterface( $param ) { |
281 | $this->rbi = $param; |
282 | $this->rbi->setPurge( $this->isPurge() ); |
283 | } |
284 | |
285 | public function hasWarnings(): bool { |
286 | if ( is_array( $this->warnings ) && count( $this->warnings ) ) { |
287 | return true; |
288 | } |
289 | |
290 | return false; |
291 | } |
292 | |
293 | /** |
294 | * Adds tracking categories to the parser |
295 | * |
296 | * @param Parser $parser |
297 | */ |
298 | public function addTrackingCategories( $parser ) { |
299 | if ( !$this->checkTeX() ) { |
300 | $parser->addTrackingCategory( 'math-tracking-category-error' ); |
301 | } |
302 | if ( $this->lastError ) { |
303 | // Add a tracking category specialized on render errors. |
304 | $parser->addTrackingCategory( 'math-tracking-category-render-error' ); |
305 | } |
306 | } |
307 | |
308 | protected function getChecker(): BaseChecker { |
309 | return Math::getCheckerFactory() |
310 | ->newDefaultChecker( $this->tex, $this->getInputType(), $this->rbi, $this->isPurge() ); |
311 | } |
312 | |
313 | /** |
314 | * Returns sanitized attributes |
315 | * |
316 | * @param string $tag element name |
317 | * @param array $defaults default attributes |
318 | * @param array $overrides attributes to override defaults |
319 | * @return array HTML attributes |
320 | */ |
321 | protected function getAttributes( $tag, $defaults = [], $overrides = [] ) { |
322 | $attribs = Sanitizer::validateTagAttributes( $this->params, $tag ); |
323 | $attribs = Sanitizer::mergeAttributes( $defaults, $attribs ); |
324 | return Sanitizer::mergeAttributes( $attribs, $overrides ); |
325 | } |
326 | |
327 | /** |
328 | * Writes cache. Writes the database entry if values were changed |
329 | * @return bool |
330 | */ |
331 | public function writeCache() { |
332 | $this->debug( 'Writing of cache requested' ); |
333 | if ( $this->isChanged() ) { |
334 | $this->debug( 'Change detected. Perform writing' ); |
335 | $this->writeToCache(); |
336 | return true; |
337 | } else { |
338 | $this->debug( "Nothing was changed. Don't write to database" ); |
339 | return false; |
340 | } |
341 | } |
342 | |
343 | /** |
344 | * Gets TeX markup |
345 | * |
346 | * @return string TeX markup |
347 | */ |
348 | public function getTex() { |
349 | return $this->tex; |
350 | } |
351 | |
352 | /** |
353 | * Gets the rendering mode |
354 | * |
355 | * @return string |
356 | */ |
357 | public function getMode() { |
358 | return $this->mode; |
359 | } |
360 | |
361 | /** |
362 | * Sets the rendering mode |
363 | * @param string $newMode element of the array $wgMathValidModes |
364 | * @return bool |
365 | */ |
366 | public function setMode( string $newMode ): bool { |
367 | if ( $this->mathConfig->isValidRenderingMode( $newMode ) ) { |
368 | $this->mode = $newMode; |
369 | return true; |
370 | } else { |
371 | return false; |
372 | } |
373 | } |
374 | |
375 | /** |
376 | * Sets the TeX code |
377 | * |
378 | * @param ?string $tex |
379 | */ |
380 | public function setTex( ?string $tex ) { |
381 | if ( $this->tex != $tex ) { |
382 | $this->changed = true; |
383 | $this->tex = $tex; |
384 | } |
385 | } |
386 | |
387 | /** |
388 | * Gets the MathML XML element |
389 | * @return string in UTF-8 encoding |
390 | */ |
391 | public function getMathml() { |
392 | if ( !StringUtils::isUtf8( $this->mathml ) ) { |
393 | $this->setMathml( '' ); |
394 | } |
395 | return $this->mathml; |
396 | } |
397 | |
398 | /** |
399 | * @param string $mathml use UTF-8 encoding |
400 | */ |
401 | public function setMathml( $mathml ) { |
402 | $this->changed = true; |
403 | $this->mathml = $mathml; |
404 | } |
405 | |
406 | /** |
407 | * Get the attributes of the math tag |
408 | * |
409 | * @return array |
410 | */ |
411 | public function getParams() { |
412 | return $this->params; |
413 | } |
414 | |
415 | /** |
416 | * @param array $params |
417 | */ |
418 | public function setParams( $params ) { |
419 | // $changed is not set to true here, because the attributes do not affect |
420 | // the rendering in the current implementation. |
421 | // If this behavior will change in the future $this->tex is no longer a |
422 | // primary key and the input hash cannot be calculate form $this->tex |
423 | // only. See the discussion 'Tag extensions in Block mode' on wikitech-l. |
424 | $this->params = $params; |
425 | } |
426 | |
427 | /** |
428 | * Checks if the instance was modified i.e., because math was rendered |
429 | * |
430 | * @return bool true if something was changed false otherwise |
431 | */ |
432 | public function isChanged() { |
433 | return $this->changed; |
434 | } |
435 | |
436 | /** |
437 | * Checks if there is an explicit user request to rerender the math-tag. |
438 | * @return bool purge state |
439 | */ |
440 | public function isPurge() { |
441 | if ( $this->purge ) { |
442 | return true; |
443 | } |
444 | $refererHeader = RequestContext::getMain()->getRequest()->getHeader( 'REFERER' ); |
445 | if ( $refererHeader ) { |
446 | $url = parse_url( $refererHeader, PHP_URL_QUERY ); |
447 | if ( !is_string( $url ) ) { |
448 | return false; |
449 | } |
450 | parse_str( $url, $refererParam ); |
451 | if ( isset( $refererParam['action'] ) && $refererParam['action'] === 'purge' ) { |
452 | $this->logger->debug( 'Re-Rendering on user request' ); |
453 | return true; |
454 | } |
455 | } |
456 | return false; |
457 | } |
458 | |
459 | /** |
460 | * Sets purge. If set to true the render is forced to rerender and must not |
461 | * use a cached version. |
462 | * @param bool $purge |
463 | */ |
464 | public function setPurge( $purge = true ) { |
465 | $this->changed = true; |
466 | $this->purge = $purge; |
467 | } |
468 | |
469 | public function getLastError(): string { |
470 | return $this->lastError; |
471 | } |
472 | |
473 | /** |
474 | * @param string $mathStyle ('inlineDisplaystyle'|'display'|'inline') |
475 | */ |
476 | public function setMathStyle( $mathStyle = 'display' ) { |
477 | if ( $this->mathStyle !== $mathStyle ) { |
478 | $this->mathStyle = $mathStyle; |
479 | $this->changed = true; |
480 | $this->inputType = $mathStyle === 'inline' ? 'inline-tex' : 'tex'; |
481 | } |
482 | } |
483 | |
484 | /** |
485 | * Returns the value of the DisplayStyle attribute |
486 | * @return string ('inlineDisplaystyle'|'display'|'inline'|'linebreak') the DisplayStyle |
487 | */ |
488 | public function getMathStyle() { |
489 | return $this->mathStyle; |
490 | } |
491 | |
492 | /** |
493 | * Get if the input tex was marked as secure |
494 | * @return bool |
495 | */ |
496 | public function isTexSecure() { |
497 | return $this->texSecure; |
498 | } |
499 | |
500 | /** |
501 | * @return bool |
502 | */ |
503 | public function checkTeX() { |
504 | if ( $this->texSecure ) { |
505 | // equation was already checked |
506 | return true; |
507 | } |
508 | $texCheckDisabled = MediaWikiServices::getInstance() |
509 | ->get( 'Math.Config' ) |
510 | ->texCheckDisabled(); |
511 | if ( $texCheckDisabled === MathConfig::ALWAYS ) { |
512 | // checking is disabled |
513 | $this->debug( 'Skip TeX check ' ); |
514 | return true; |
515 | } else { |
516 | if ( $texCheckDisabled === MathConfig::NEW && $this->mode != MathConfig::MODE_SOURCE ) { |
517 | if ( $this->readFromCache() ) { |
518 | $this->debug( 'Skip TeX check' ); |
519 | $this->texSecure = true; |
520 | return true; |
521 | } |
522 | } |
523 | $this->debug( 'Perform TeX check' ); |
524 | return $this->doCheck(); |
525 | } |
526 | } |
527 | |
528 | public function isInDatabase(): bool { |
529 | if ( $this->storedInCache === null ) { |
530 | $this->storedInCache = $this->readFromCache(); |
531 | } |
532 | return $this->storedInCache; |
533 | } |
534 | |
535 | /** |
536 | * @return string TeX the original tex string specified by the user |
537 | */ |
538 | public function getUserInputTex() { |
539 | return $this->userInputTex; |
540 | } |
541 | |
542 | /** |
543 | * @return string user defined ID |
544 | */ |
545 | public function getID() { |
546 | return $this->id; |
547 | } |
548 | |
549 | /** |
550 | * @param string $id user defined ID |
551 | */ |
552 | public function setID( $id ) { |
553 | // Changes in the ID affect the container for the math element on the current page |
554 | // only. Therefore an id change does not affect the $this->changed variable, which |
555 | // indicates if database relevant fields have been changed. |
556 | $this->id = $id; |
557 | } |
558 | |
559 | /** |
560 | * @param string $svg |
561 | */ |
562 | public function setSvg( $svg ) { |
563 | $this->changed = true; |
564 | $this->svg = trim( $svg ); |
565 | } |
566 | |
567 | /** |
568 | * Gets the SVG image |
569 | * |
570 | * @param string $render if set to 'render' (default) and no SVG image exists, the function |
571 | * tries to generate it on the fly. |
572 | * Otherwise, if set to 'cached', and there is no SVG in the database |
573 | * cache, an empty string is returned. |
574 | * |
575 | * @return string XML-Document of the rendered SVG |
576 | */ |
577 | public function getSvg( $render = 'render' ) { |
578 | // Spaces will prevent the image from being displayed correctly in the browser |
579 | if ( !$this->svg && $this->rbi ) { |
580 | $this->svg = $this->rbi->getSvg(); |
581 | } |
582 | return trim( $this->svg ); |
583 | } |
584 | |
585 | /** |
586 | * @return string |
587 | */ |
588 | abstract protected function getMathTableName(); |
589 | |
590 | protected function getModeName(): Message { |
591 | return MediaWikiServices::getInstance() |
592 | ->get( 'Math.Config' ) |
593 | ->getRenderingModeName( $this->getMode() ); |
594 | } |
595 | |
596 | public function setInputType( string $inputType ) { |
597 | $this->inputType = $inputType; |
598 | } |
599 | |
600 | public function getInputType(): string { |
601 | return $this->inputType; |
602 | } |
603 | |
604 | protected function doCheck(): bool { |
605 | $checker = $this->getChecker(); |
606 | |
607 | if ( $checker->isValid() ) { |
608 | $this->setTex( $checker->getValidTex() ); |
609 | $this->texSecure = true; |
610 | return true; |
611 | } |
612 | |
613 | $checkerError = $checker->getError(); |
614 | $this->lastError = $checkerError === null ? |
615 | $this->getError( 'math_unknown_error' ) : |
616 | $this->getError( $checkerError->getKey(), ...$checkerError->getParams() ); |
617 | return false; |
618 | } |
619 | |
620 | protected function debug( string $msg ) { |
621 | $this->logger->debug( "$msg for \"{tex}\".", [ 'tex' => $this->userInputTex ] ); |
622 | } |
623 | |
624 | private function getCacheKey(): string { |
625 | return $this->cache->makeGlobalKey( |
626 | self::class, |
627 | $this->getInputHash() |
628 | ); |
629 | } |
630 | } |