Файловый менеджер - Редактировать - /var/www/html/mediawiki-1.43.1/extensions/Math/src/MathRenderer.php
Ðазад
<?php /** * MediaWiki math extension * * @copyright 2002-2012 Tomasz Wegrzanowski, Brion Vibber, Moritz Schubotz, * and other MediaWiki contributors * @license GPL-2.0-or-later * * @file */ namespace MediaWiki\Extension\Math; use MediaWiki\Context\RequestContext; use MediaWiki\Extension\Math\InputCheck\BaseChecker; use MediaWiki\Logger\LoggerFactory; use MediaWiki\MediaWikiServices; use MediaWiki\Message\Message; use MediaWiki\Parser\Parser; use MediaWiki\Parser\Sanitizer; use Psr\Log\LoggerInterface; use StringUtils; use Wikimedia\ObjectCache\WANObjectCache; /** * Abstract base class with static methods for rendering the <math> tags using * different technologies. These static methods create a new instance of the * extending classes and render the math tags based on the mode setting of the user. * Furthermore, this class handles the caching of the rendered output. * * @author Tomasz Wegrzanowski * @author Brion Vibber * @author Moritz Schubotz */ abstract class MathRenderer { // REPRESENTATIONS OF THE MATHEMATICAL CONTENT /** @var ?string tex representation */ protected $tex = ''; /** @var string MathML content and presentation */ protected $mathml = ''; /** @var string SVG layout only (no semantics) */ protected $svg = ''; /** @var string the original user input string (which was used to calculate the inputhash) */ protected $userInputTex = ''; // FURTHER PROPERTIES OF THE MATHEMATICAL CONTENT /** @var string ('inlineDisplaystyle'|'display'|'inline'|'linebreak') the rendering style */ protected $mathStyle = 'inlineDisplaystyle'; /** @var array with userdefined parameters passed to the extension (not used) */ protected $params = []; /** @var string a userdefined identifier to link to the equation. */ protected $id = ''; // STATE OF THE CLASS INSTANCE /** @var bool has variable tex been security-checked */ protected $texSecure = false; /** @var bool has the mathematical content changed */ protected $changed = false; /** @var bool|null is there a database entry for the mathematical content */ protected $storedInCache = null; /** @var bool is there a request to purge the existing mathematical content */ protected $purge = false; /** @var string with last occurred error */ protected $lastError = ''; /** @var string binary packed inputhash */ protected $inputHash = ''; /** @var string rendering mode */ protected $mode = MathConfig::MODE_MATHML; /** @var string input type */ protected $inputType = 'tex'; /** @var MathRestbaseInterface used for checking */ protected $rbi; /** @var array with rendering warnings */ protected $warnings; /** @var LoggerInterface */ private $logger; private WANObjectCache $cache; private MathConfig $mathConfig; private bool $rawError = false; public function setRawError( bool $rawError ): void { $this->rawError = $rawError; } /** * Constructs a base MathRenderer * * @param string $tex (optional) LaTeX markup * @param array $params (optional) HTML attributes * @param WANObjectCache|null $cache (optional) * @param MathConfig|null $mathConfig (optional) */ public function __construct( string $tex = '', $params = [], $cache = null, $mathConfig = null ) { $this->cache = $cache ?? MediaWikiServices::getInstance()->getMainWANObjectCache(); $this->mathConfig = $mathConfig ?? Math::getMathConfig(); $this->params = $params; if ( isset( $params['id'] ) ) { $this->id = $params['id']; } if ( isset( $params['display'] ) ) { $layoutMode = $params['display']; if ( $layoutMode == 'block' ) { $this->mathStyle = 'display'; $tex = '{\displaystyle ' . $tex . '}'; $this->inputType = 'tex'; } elseif ( $layoutMode == 'inline' ) { $this->mathStyle = 'inline'; $this->inputType = 'inline-tex'; $tex = '{\textstyle ' . $tex . '}'; } elseif ( $layoutMode == 'linebreak' ) { $this->mathStyle = 'linebreak'; $tex = '\[ ' . $tex . ' \]'; } } // TODO: Implement caching for attributes of the math tag // Currently the key for the database entry relating to an equation // is md5($tex) the new option to determine if the tex input // is rendered in displaystyle or textstyle would require a database // layout change to use a composite key e.g. (md5($tex),$mathStyle). // As a workaround we use the prefix \displaystyle so that the key becomes // md5((\{\\displaystyle|\{\\textstyle)?\s?$tex\}?) // The new value of $tex string describes now how the rendering should look like. // The variable MathRenderer::mathStyle determines if the rendered equation should // be centered in a new line, or just in be displayed in the current line. $this->userInputTex = $tex; $this->tex = $tex; $this->logger = LoggerFactory::getInstance( 'Math' ); } /** * Static factory method for getting a renderer based on mode * * @deprecated since 3.0.0. Use Math.RendererFactory service instead. * @param string $tex LaTeX markup * @param array $params HTML attributes * @param string $mode indicating rendering mode * @return self appropriate renderer for mode */ public static function getRenderer( $tex, $params = [], $mode = MathConfig::MODE_MATHML ) { return MediaWikiServices::getInstance() ->get( 'Math.RendererFactory' ) ->getRenderer( $tex, $params, $mode ); } /** * Performs the rendering * * @return bool if rendering was successful. */ abstract public function render(); /** * @param bool $svg * @return string Html output that is embedded in the page */ abstract public function getHtmlOutput( bool $svg = true ): string; /** * texvc error messages * TODO: update to MathML * Returns an internationalized HTML error string * * @param string $msg message key for specific error * @param string ...$parameters zero or more message * parameters for specific error * * @return string HTML error string */ public function getError( $msg, ...$parameters ) { if ( $this->rawError ) { return 'Error: ' . $msg . ' param ' . implode( ',', $parameters ); } $mf = wfMessage( 'math_failure' )->inContentLanguage()->escaped(); $errmsg = wfMessage( $msg, $parameters )->inContentLanguage()->escaped(); $source = htmlspecialchars( str_replace( "\n", ' ', $this->tex ) ); return "<strong class=\"error texerror\">$mf ($errmsg): $source</strong>\n"; } /** * Return hash of input * * @return string hash */ public function getInputHash(): string { if ( !$this->inputHash ) { $this->inputHash = hash( 'md5', // xxh128 might be better when dropping php 7 support $this->mode . $this->userInputTex . implode( $this->params ) ); } return $this->inputHash; } /** * Reads rendering data from database * * @return bool true if read successfully, false otherwise */ public function readFromCache(): bool { $rpage = $this->cache->get( $this->getCacheKey() ); if ( $rpage !== false ) { $this->initializeFromCache( $rpage ); return true; } else { # Missing from the database and/or the render cache return false; } } /** * @return array with the database column names */ protected function dbInArray() { $in = [ 'math_inputhash', 'math_mathml', 'math_inputtex', 'math_tex', 'math_svg' ]; return $in; } /** * Reads the values from the database but does not overwrite set values with empty values * @param array $rpage (a database row) */ public function initializeFromCache( $rpage ) { $this->inputHash = $rpage['math_inputhash']; // MUST NOT BE NULL if ( isset( $rpage['math_mathml'] ) ) { $this->mathml = $rpage['math_mathml']; } if ( isset( $rpage['math_inputtex'] ) ) { $this->userInputTex = $rpage['math_inputtex']; } if ( isset( $rpage['math_tex'] ) ) { $this->tex = $rpage['math_tex']; } if ( isset( $rpage['math_svg'] ) ) { $this->svg = $rpage['math_svg']; } $this->changed = false; } /** * Writes rendering entry to cache. * * WARNING: Use writeCache() instead of this method to be sure that all * renderer specific (such as squid caching) are taken into account. * This function stores the values that are currently present in the class * to the cache even if they are empty. * * This function can be seen as protected function. */ public function writeToCache() { $outArray = $this->dbOutArray(); $this->cache->set( $this->getCacheKey(), $outArray ); } /** * Gets an array that matches the variables of the class to the database columns * @return array */ protected function dbOutArray() { $out = [ 'math_inputhash' => $this->getInputHash(), 'math_mathml' => $this->mathml, 'math_inputtex' => $this->userInputTex, 'math_tex' => $this->tex, 'math_svg' => $this->svg, 'math_mode' => $this->mode ]; return $out; } /** * @param MathRestbaseInterface $param */ public function setRestbaseInterface( $param ) { $this->rbi = $param; $this->rbi->setPurge( $this->isPurge() ); } public function hasWarnings() { if ( is_array( $this->warnings ) && count( $this->warnings ) ) { return true; } return false; } /** * Adds tracking categories to the parser * * @param Parser $parser */ public function addTrackingCategories( $parser ) { if ( !$this->checkTeX() ) { $parser->addTrackingCategory( 'math-tracking-category-error' ); } if ( $this->lastError ) { // Add a tracking category specialized on render errors. $parser->addTrackingCategory( 'math-tracking-category-render-error' ); } } protected function getChecker(): BaseChecker { return Math::getCheckerFactory() ->newDefaultChecker( $this->tex, $this->getInputType(), $this->rbi, $this->isPurge() ); } /** * Returns sanitized attributes * * @param string $tag element name * @param array $defaults default attributes * @param array $overrides attributes to override defaults * @return array HTML attributes */ protected function getAttributes( $tag, $defaults = [], $overrides = [] ) { $attribs = Sanitizer::validateTagAttributes( $this->params, $tag ); $attribs = Sanitizer::mergeAttributes( $defaults, $attribs ); return Sanitizer::mergeAttributes( $attribs, $overrides ); } /** * Writes cache. Writes the database entry if values were changed * @return bool */ public function writeCache() { $this->debug( 'Writing of cache requested' ); if ( $this->isChanged() ) { $this->debug( 'Change detected. Perform writing' ); $this->writeToCache(); return true; } else { $this->debug( "Nothing was changed. Don't write to database" ); return false; } } /** * Gets TeX markup * * @return string TeX markup */ public function getTex() { return $this->tex; } /** * Gets the rendering mode * * @return string */ public function getMode() { return $this->mode; } /** * Sets the rendering mode * @param string $newMode element of the array $wgMathValidModes * @return bool */ public function setMode( string $newMode ): bool { if ( $this->mathConfig->isValidRenderingMode( $newMode ) ) { $this->mode = $newMode; return true; } else { return false; } } /** * Sets the TeX code * * @param ?string $tex */ public function setTex( ?string $tex ) { if ( $this->tex != $tex ) { $this->changed = true; $this->tex = $tex; } } /** * Gets the MathML XML element * @return string in UTF-8 encoding */ public function getMathml() { if ( !StringUtils::isUtf8( $this->mathml ) ) { $this->setMathml( '' ); } return $this->mathml; } /** * @param string $mathml use UTF-8 encoding */ public function setMathml( $mathml ) { $this->changed = true; $this->mathml = $mathml; } /** * Get the attributes of the math tag * * @return array */ public function getParams() { return $this->params; } /** * @param array $params */ public function setParams( $params ) { // $changed is not set to true here, because the attributes do not affect // the rendering in the current implementation. // If this behavior will change in the future $this->tex is no longer a // primary key and the input hash cannot be calculate form $this->tex // only. See the discussion 'Tag extensions in Block mode' on wikitech-l. $this->params = $params; } /** * Checks if the instance was modified i.e., because math was rendered * * @return bool true if something was changed false otherwise */ public function isChanged() { return $this->changed; } /** * Checks if there is an explicit user request to rerender the math-tag. * @return bool purge state */ public function isPurge() { if ( $this->purge ) { return true; } $refererHeader = RequestContext::getMain()->getRequest()->getHeader( 'REFERER' ); if ( $refererHeader ) { $url = parse_url( $refererHeader, PHP_URL_QUERY ); if ( !is_string( $url ) ) { return false; } parse_str( $url, $refererParam ); if ( isset( $refererParam['action'] ) && $refererParam['action'] === 'purge' ) { $this->logger->debug( 'Re-Rendering on user request' ); return true; } } return false; } /** * Sets purge. If set to true the render is forced to rerender and must not * use a cached version. * @param bool $purge */ public function setPurge( $purge = true ) { $this->changed = true; $this->purge = $purge; } public function getLastError(): string { return $this->lastError; } /** * @param string $mathStyle ('inlineDisplaystyle'|'display'|'inline') */ public function setMathStyle( $mathStyle = 'display' ) { if ( $this->mathStyle !== $mathStyle ) { $this->mathStyle = $mathStyle; $this->changed = true; $this->inputType = $mathStyle === 'inline' ? 'inline-tex' : 'tex'; } } /** * Returns the value of the DisplayStyle attribute * @return string ('inlineDisplaystyle'|'display'|'inline'|'linebreak') the DisplayStyle */ public function getMathStyle() { return $this->mathStyle; } /** * Get if the input tex was marked as secure * @return bool */ public function isTexSecure() { return $this->texSecure; } /** * @return bool */ public function checkTeX() { if ( $this->texSecure ) { // equation was already checked return true; } $texCheckDisabled = MediaWikiServices::getInstance() ->get( 'Math.Config' ) ->texCheckDisabled(); if ( $texCheckDisabled === MathConfig::ALWAYS ) { // checking is disabled $this->debug( 'Skip TeX check ' ); return true; } else { if ( $texCheckDisabled === MathConfig::NEW && $this->mode != MathConfig::MODE_SOURCE ) { if ( $this->readFromCache() ) { $this->debug( 'Skip TeX check' ); $this->texSecure = true; return true; } } $this->debug( 'Perform TeX check' ); return $this->doCheck(); } } public function isInDatabase(): bool { if ( $this->storedInCache === null ) { $this->storedInCache = $this->readFromCache(); } return $this->storedInCache; } /** * @return string TeX the original tex string specified by the user */ public function getUserInputTex() { return $this->userInputTex; } /** * @return string user defined ID */ public function getID() { return $this->id; } /** * @param string $id user defined ID */ public function setID( $id ) { // Changes in the ID affect the container for the math element on the current page // only. Therefore an id change does not affect the $this->changed variable, which // indicates if database relevant fields have been changed. $this->id = $id; } /** * @param string $svg */ public function setSvg( $svg ) { $this->changed = true; $this->svg = trim( $svg ); } /** * Gets the SVG image * * @param string $render if set to 'render' (default) and no SVG image exists, the function * tries to generate it on the fly. * Otherwise, if set to 'cached', and there is no SVG in the database * cache, an empty string is returned. * * @return string XML-Document of the rendered SVG */ public function getSvg( $render = 'render' ) { // Spaces will prevent the image from being displayed correctly in the browser if ( !$this->svg && $this->rbi ) { $this->svg = $this->rbi->getSvg(); } return trim( $this->svg ); } /** * @return string */ abstract protected function getMathTableName(); protected function getModeName(): Message { return MediaWikiServices::getInstance() ->get( 'Math.Config' ) ->getRenderingModeName( $this->getMode() ); } public function setInputType( string $inputType ) { $this->inputType = $inputType; } public function getInputType(): string { return $this->inputType; } protected function doCheck(): bool { $checker = $this->getChecker(); if ( $checker->isValid() ) { $this->setTex( $checker->getValidTex() ); $this->texSecure = true; return true; } $checkerError = $checker->getError(); $this->lastError = $checkerError === null ? $this->getError( 'math_unknown_error' ) : $this->getError( $checkerError->getKey(), ...$checkerError->getParams() ); return false; } protected function debug( string $msg ) { $this->logger->debug( "$msg for \"{tex}\".", [ 'tex' => $this->userInputTex ] ); } private function getCacheKey(): string { return $this->cache->makeGlobalKey( self::class, $this->getInputHash() ); } }
| ver. 1.1 | |
.
| PHP 8.4.18 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка