mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Math
synced 2024-11-28 01:10:09 +00:00
211 lines
5.7 KiB
PHP
211 lines
5.7 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* MediaWiki math extension
|
||
|
*
|
||
|
* (c)2012 Moritz Schubotz
|
||
|
* GPLv2 license; info in main package.
|
||
|
*
|
||
|
* Contains the driver function for the MathML daemon
|
||
|
* @file
|
||
|
*/
|
||
|
class MathMathML extends MathRenderer {
|
||
|
|
||
|
protected $defaultAllowedRootElements = array( 'math' );
|
||
|
protected $allowedRootElements = '';
|
||
|
protected $hosts;
|
||
|
/** @var boolean if false MathML output is not validated */
|
||
|
private $XMLValidation = true;
|
||
|
|
||
|
/**
|
||
|
* Gets the allowed root elements the rendered math tag might have.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getAllowedRootElements() {
|
||
|
if ( $this->allowedRootElements ) {
|
||
|
return $this->allowedRootElements;
|
||
|
} else {
|
||
|
return $this->defaultAllowedRootElements;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the XML validation.
|
||
|
* If set to false the output of MathML is not validated.
|
||
|
* @param boolean $validation
|
||
|
*/
|
||
|
public function setXMLValidation( $validation = true ) {
|
||
|
$this->XMLValidation = $validation;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the allowed root elements the rendered math tag might have.
|
||
|
* An empty value indicates to use the default settings.
|
||
|
* @param array $settings
|
||
|
*/
|
||
|
public function setAllowedRootElments( $settings ) {
|
||
|
$this->allowedRootElements = $settings;
|
||
|
}
|
||
|
|
||
|
/* (non-PHPdoc)
|
||
|
* @see MathRenderer::render()
|
||
|
*/
|
||
|
public function render( $forceReRendering = false ) {
|
||
|
wfProfileIn( __METHOD__ );
|
||
|
if ( $forceReRendering ) {
|
||
|
$this->setPurge( true );
|
||
|
}
|
||
|
if ( $this->renderingRequired() ) {
|
||
|
$res = $this->doRender( );
|
||
|
if ( ! $res ) {
|
||
|
wfProfileOut( __METHOD__ );
|
||
|
return $this->getLastError();
|
||
|
}
|
||
|
}
|
||
|
$result = $this->getMathMLTag();
|
||
|
wfProfileOut( __METHOD__ );
|
||
|
return $result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Helper function to checks if the math tag must be rendered.
|
||
|
* @return boolean
|
||
|
*/
|
||
|
private function renderingRequired() {
|
||
|
if ( $this->isPurge() ) {
|
||
|
wfDebugLog( "Math", "Rerendering was requested." );
|
||
|
return true;
|
||
|
} else {
|
||
|
$dbres = $this->readFromDatabase();
|
||
|
if ( $dbres ) {
|
||
|
if ( $this->isValidMathML( $this->getMathml() ) ) {
|
||
|
wfDebugLog( "Math", "Valid entry found in database." );
|
||
|
return false;
|
||
|
} else {
|
||
|
wfDebugLog( "Math", "Malformatted entry found in database" );
|
||
|
return true;
|
||
|
}
|
||
|
} else {
|
||
|
wfDebugLog( "Math", "No entry found in database." );
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Performs a HTTP Post request to the given host.
|
||
|
* Uses $wgMathLaTeXMLTimeout as timeout.
|
||
|
* Generates error messages on failure
|
||
|
* @see Http::post()
|
||
|
*
|
||
|
* @global int $wgMathLaTeXMLTimeout
|
||
|
* @param string $host
|
||
|
* @param string $post the encoded post request
|
||
|
* @param mixed $res the result
|
||
|
* @param mixed $error the formatted error message or null
|
||
|
* @param String $httpRequestClass class name of MWHttpRequest (needed for testing only)
|
||
|
* @return boolean success
|
||
|
*/
|
||
|
public function makeRequest( $host, $post, &$res, &$error = '', $httpRequestClass = 'MWHttpRequest' ) {
|
||
|
// TODO: Change the timeout mechanism.
|
||
|
global $wgMathLaTeXMLTimeout;
|
||
|
|
||
|
wfProfileIn( __METHOD__ );
|
||
|
$error = '';
|
||
|
$res = null;
|
||
|
$options = array( 'method' => 'POST', 'postData' => $post, 'timeout' => $wgMathLaTeXMLTimeout );
|
||
|
/** @var $req (CurlHttpRequest|PhpHttpRequest) the request object */
|
||
|
$req = $httpRequestClass::factory( $host, $options );
|
||
|
$status = $req->execute();
|
||
|
if ( $status->isGood() ) {
|
||
|
$res = $req->getContent();
|
||
|
wfProfileOut( __METHOD__ );
|
||
|
return true;
|
||
|
} else {
|
||
|
if ( $status->hasMessage( 'http-timed-out' ) ) {
|
||
|
$error = $this->getError( 'math_timeout', $this->getModeStr(), $host );
|
||
|
$res = false;
|
||
|
wfDebugLog( "Math", "\nTimeout:"
|
||
|
. var_export( array( 'post' => $post, 'host' => $host
|
||
|
, 'timeout' => $wgMathLaTeXMLTimeout ), true ) . "\n\n" );
|
||
|
} else {
|
||
|
// for any other unkonwn http error
|
||
|
$errormsg = $status->getHtml();
|
||
|
$error = $this->getError( 'math_invalidresponse', $this->getModeStr(), $host, $errormsg, $this->getModeStr( MW_MATH_MATHML ) );
|
||
|
wfDebugLog( "Math", "\nNoResponse:"
|
||
|
. var_export( array( 'post' => $post, 'host' => $host
|
||
|
, 'errormsg' => $errormsg ), true ) . "\n\n" );
|
||
|
}
|
||
|
wfProfileOut( __METHOD__ );
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks if the input is valid MathML,
|
||
|
* and if the root element has the name math
|
||
|
* @param string $XML
|
||
|
* @return boolean
|
||
|
*/
|
||
|
public function isValidMathML( $XML ) {
|
||
|
$out = false;
|
||
|
if ( !$this->XMLValidation ) {
|
||
|
return true;
|
||
|
}
|
||
|
// depends on https://gerrit.wikimedia.org/r/#/c/66365/
|
||
|
if ( !is_callable( 'XmlTypeCheck::newFromString' ) ) {
|
||
|
$msg = wfMessage( 'math_xmlversion' )->inContentLanguage()->escaped();
|
||
|
trigger_error( $msg, E_USER_NOTICE );
|
||
|
wfDebugLog( 'Math', $msg );
|
||
|
return true;
|
||
|
}
|
||
|
$xmlObject = new XmlTypeCheck( $XML, null, false );
|
||
|
if ( !$xmlObject->wellFormed ) {
|
||
|
wfDebugLog( "Math", "XML validation error:\n " . var_export( $XML, true ) . "\n" );
|
||
|
} else {
|
||
|
$name = $xmlObject->getRootElement();
|
||
|
$elementSplit = explode( ':', $name );
|
||
|
if ( is_array($elementSplit) ){
|
||
|
$localName = end( $elementSplit );
|
||
|
} else {
|
||
|
$localName = $name;
|
||
|
}
|
||
|
if ( in_array( $localName , $this->getAllowedRootElements() ) ) {
|
||
|
$out = true;
|
||
|
} else {
|
||
|
wfDebugLog( "Math", "got wrong root element : $name" );
|
||
|
}
|
||
|
}
|
||
|
return $out;
|
||
|
}
|
||
|
|
||
|
/* (non-PHPdoc)
|
||
|
* @see MathRenderer::writeCache()
|
||
|
*/
|
||
|
public function writeCache() {
|
||
|
if ( $this->isChanged() ) {
|
||
|
$this->writeToDatabase();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Picks a daemon.
|
||
|
* If more than one demon are available one is chosen from the
|
||
|
* hosts array.
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function pickHost() {
|
||
|
if ( is_array( $this->hosts ) ) {
|
||
|
$host = array_rand( $this->hosts );
|
||
|
} else {
|
||
|
$host = $this->hosts;
|
||
|
}
|
||
|
wfDebugLog( "Math", "picking host " . $host );
|
||
|
return $host;
|
||
|
}
|
||
|
|
||
|
|
||
|
protected function getMathTableName() {
|
||
|
return 'mathoid';
|
||
|
}
|
||
|
}
|