jenkins-bot has submitted this change and it was merged.

Change subject: New rendering option LaTeXML
......................................................................


New rendering option LaTeXML

Introduces a new rending option to render TeX to MathML
via LaTeXML.

Bug: 43222
Change-Id: I5d29e219c0d3b907e22ea0bb3b30f000d8a7a9f8
---
M Math.hooks.php
M Math.i18n.php
M Math.php
A MathLaTeXML.php
M MathRenderer.php
M README
M db/math.sql
M tests/MathDatabaseTest.php
A tests/MathLaTeXMLTest.php
M tests/MathRendererTest.php
10 files changed, 552 insertions(+), 38 deletions(-)

Approvals:
  MaxSem: Verified; Looks good to me, approved
  jenkins-bot: Verified



diff --git a/Math.hooks.php b/Math.hooks.php
index a1d9fea..3489da5 100644
--- a/Math.hooks.php
+++ b/Math.hooks.php
@@ -81,7 +81,7 @@
         * @return array of strings
         */
        private static function getMathNames() {
-               global $wgUseMathJax;
+               global $wgUseMathJax, $wgUseLaTeXML;
                $names = array(
                        MW_MATH_PNG => wfMessage( 'mw_math_png' )->escaped(),
                        MW_MATH_SOURCE => wfMessage( 'mw_math_source' 
)->escaped(),
@@ -89,7 +89,9 @@
                if ( $wgUseMathJax ) {
                        $names[MW_MATH_MATHJAX] = wfMessage( 'mw_math_mathjax' 
)->escaped();
                }
-
+               if ( $wgUseLaTeXML ) {
+                       $names[MW_MATH_LATEXML] = wfMessage( 'mw_math_latexml' 
)->escaped();
+               }
                return $names;
        }
 
diff --git a/Math.i18n.php b/Math.i18n.php
index 1b42f56..9f5fd34 100644
--- a/Math.i18n.php
+++ b/Math.i18n.php
@@ -22,6 +22,7 @@
        'mw_math_png' => 'Always render PNG',
        'mw_math_source' => 'Leave it as TeX (for text browsers)',
        'mw_math_mathjax' => 'MathJax (experimental; best for most browsers)',
+       'mw_math_latexml' => 'LaTeXML (experimental; uses MathML)',
 
        // Math errors
        'math_failure' => 'Failed to parse',
@@ -34,6 +35,10 @@
        'math_bad_output' => 'Cannot write to or create math output directory',
        'math_notexvc' => 'Missing texvc executable; please see math/README to 
configure.',
        'math_output_error' => 'Cannot store math image on filesystem.',
+       'math_latexml_timeout' => 'LaTeXML Timeout from \'$1\'',
+       'math_latexml_invalidresponse' => 'LaTeXML Invalid response from server 
\'$1\':',
+       'math_latexml_invalidxml' => 'LaTeXML MathML is invalid XML.',
+       'math_latexml_invalidjson'  => 'LaTeXML Server response is invalid 
JSON.',
 );
 
 /** Message documentation (Message documentation)
@@ -41,6 +46,7 @@
  * @author Kizito
  * @author Shirayuki
  * @author Siebrand
+ * @author Physikerwelt
  */
 $messages['qqq'] = array(
        'math-desc' => 
'{{desc|name=Math|url=http://www.mediawiki.org/wiki/Extension:Math}}',
@@ -53,19 +59,28 @@
 
 See also:
 * {{msg-mw|Mw math source}}
-* {{msg-mw|Mw math mathjax}}',
+* {{msg-mw|Mw math mathjax}}
+* {{msg-mw|Mw math latexml}}',
        'mw_math_source' => 'In user preferences (math). All mw_math_* messages 
MUST be different, things will break otherwise!
 
-Used as label for radio button.
+Used as label for source radio button.
 
 See also:
 * {{msg-mw|Mw math png}}
+* {{msg-mw|Mw math mathjax}}
+* {{msg-mw|Mw math latexml}}',
+       'mw_math_mathjax' => 'Used as label for mathjax radio button.
+
+See also:
+* {{msg-mw|Mw math png}}
+* {{msg-mw|Mw math source}}
+* {{msg-mw|Mw math latexml}}',
+       'mw_math_latexml' => 'Used as label for latexml radio button.
+
+See also:
+* {{msg-mw|Mw math png}}
+* {{msg-mw|Mw math source}}
 * {{msg-mw|Mw math mathjax}}',
-       'mw_math_mathjax' => 'Used as label for radio button.
-
-See also:
-* {{msg-mw|Mw math png}}
-* {{msg-mw|Mw math source}}',
        'math_failure' => 'Used as error message.
 
 This message is followed by "(", Error message(*1), Additional message, "): "  
and Source code.
@@ -79,7 +94,12 @@
 * {{msg-mw|Math bad tmpdir}}
 * {{msg-mw|Math bad output}}
 * {{msg-mw|Math notexvc}}
-* {{msg-mw|Math output error}}',
+* {{msg-mw|Math output error}}
+* {{msg-mw|Math latexml timeout}}
+* {{msg-mw|Math latexml noresponse}}
+* {{msg-mw|Math latexml invalidxml}}
+* {{msg-mw|Math latexml invalidjson}}
+',
        'math_unknown_error' => 'Used as error message for unknown texvc error.
 
 This message follows the message {{msg-mw|Math failure}}.
@@ -113,6 +133,18 @@
        'math_output_error' => 'Used as error message if the texvc output file 
could not be stored.
 
 This message follows the message {{msg-mw|Math failure}}.',
+       'math_latexml_timeout' => 'Used as error message.
+
+This message follows the message {{msg-mw|Math failure}}. ',
+       'math_latexml_invalidresponse' => 'Used as error message.
+
+This message follows the message {{msg-mw|Math failure}}. ',
+       'math_latexml_invalidxml' => 'Used as error message.
+
+This message follows the message {{msg-mw|Math failure}}. ',
+       'math_latexml_invalidjson'  => 'Used as error message.
+
+This message follows the message {{msg-mw|Math failure}}. ',
 );
 
 /** Achinese (Acèh)
diff --git a/Math.php b/Math.php
index 83bd58a..9314cb7 100644
--- a/Math.php
+++ b/Math.php
@@ -22,7 +22,7 @@
 $wgExtensionCredits['parserhook'][] = array(
        'path' => __FILE__,
        'name' => 'Math',
-       'version' => '1.0',
+       'version' => '1.1',
        'author' => array( 'Tomasz Wegrzanowski', 'Brion Vibber', '...' ),
        'descriptionmsg' => 'math-desc',
        'url' => 'https://www.mediawiki.org/wiki/Extension:Math',
@@ -38,6 +38,7 @@
 define( 'MW_MATH_MODERN', 4 ); /// @deprecated
 define( 'MW_MATH_MATHML', 5 ); /// @deprecated
 define( 'MW_MATH_MATHJAX', 6 ); /// new in 1.19/1.20
+define( 'MW_MATH_LATEXML', 7 ); /// new in 1.22
 /**@}*/
 
 /** For back-compat */
@@ -101,6 +102,32 @@
  */
 $wgUseMathJax = false;
 
+/**
+ * Use of LaTeXML for details see
+ * <http://latexml.mathweb.org/help>
+ *
+ * If you want or need to run your own server, follow these installation
+ * instructions and override $wgLaTeXMLUrl:
+ * <https://svn.mathweb.org/repos/LaTeXML/branches/arXMLiv/INSTALL>
+ *
+ * If you expect heavy load you can specify multiple servers. In that case one
+ * server is randomly chosen for each rendering process. Specify the list of
+ * servers in an array e.g $wgLaTeXMLUrl = array ( 
'http://latexml.example.com/convert',
+ * 'http://latexml2.example.com/convert');
+ */
+$wgLaTeXMLUrl = 'http://latexml.mathweb.org/convert';
+
+/**
+ * Allows to use LaTeXML as renderer for mathematical equation.
+ */
+$wgUseLaTeXML = false;
+
+/**
+ * The timeout for the HTTP-Request sent to the LaTeXML to render an equation,
+ * in seconds.
+ */
+$wgLaTeXMLTimeout = 240;
+
 ////////// end of config settings.
 
 $wgDefaultUserOptions['math'] = MW_MATH_PNG;
@@ -119,6 +146,7 @@
 $wgAutoloadClasses['MathTexvc'] = $dir . 'MathTexvc.php';
 $wgAutoloadClasses['MathSource'] = $dir . 'MathSource.php';
 $wgAutoloadClasses['MathMathJax'] = $dir . 'MathMathJax.php';
+$wgAutoloadClasses['MathLaTeXML'] = $dir . 'MathLaTeXML.php';
 $wgExtensionMessagesFiles['Math'] = $dir . 'Math.i18n.php';
 
 $wgParserTestFiles[] = $dir . 'mathParserTests.txt';
diff --git a/MathLaTeXML.php b/MathLaTeXML.php
new file mode 100644
index 0000000..ee38317
--- /dev/null
+++ b/MathLaTeXML.php
@@ -0,0 +1,247 @@
+<?php
+/**
+ * MediaWiki math extension
+ *
+ * (c)2012 Moritz Schubotz
+ * GPLv2 license; info in main package.
+ *
+ * Contains the driver function for the LaTeXML daemon
+ * @file
+ */
+
+class MathLaTeXML extends MathRenderer {
+
+       /**
+        * @var String settings for LaTeXML daemon
+        */
+       private $LaTeXMLSettings = '';
+       const DEFAULT_LATEXML_SETTING = 
'format=xhtml&whatsin=math&whatsout=math&pmml&cmml&nodefaultresources&preload=LaTeX.pool&preload=article.cls&preload=amsmath.sty&preload=amsthm.sty&preload=amstext.sty&preload=amssymb.sty&preload=eucal.sty&preload=[dvipsnames]xcolor.sty&preload=url.sty&preload=hyperref.sty&preload=[ids]latexml.sty&preload=texvc';
+
+       /**
+        * Gets the settings for the LaTeXML daemon.
+        *
+        * @return string
+        */
+       public function getLaTeXMLSettings() {
+               if ( $this->LaTeXMLSettings ) {
+                       return $this->LaTeXMLSettings;
+               } else {
+                       return self::DEFAULT_LATEXML_SETTING;
+               }
+       }
+
+       /**
+        * Sets the settings for the LaTeXML daemon.
+        * The settings affect only the current instance of the class.
+        * For a list of possible settings see:
+        * http://dlmf.nist.gov/LaTeXML/manual/commands/latexmlpost.xhtml
+        * An empty value indicates to use the default settings.
+        * @param string $settings
+        */
+       public function setLaTeXMLSettings( $settings ) {
+               $this->LaTeXMLSettings = $settings;
+       }
+
+       /* (non-PHPdoc)
+        * @see MathRenderer::render()
+       */
+       public function render( $forceReRendering = false ) {
+               if ( $forceReRendering ) {
+                       $this->setPurge( true );
+               }
+               if ( $this->renderingRequired() ) {
+                       $res = $this->doRender( );
+                       if ( ! $res ) {
+                               return $this->getLastError();
+                       }
+               }
+               return $this->getMathMLTag();
+       }
+
+       /**
+        * 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 ( self::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 $wgLaTeXMLTimeout as timeout.
+        * Generates error messages on failure
+        * @see Http::post()
+        *
+        * @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' ) {
+               global $wgLaTeXMLTimeout;
+               $error = '';
+               $res = null;
+               $options = array( 'method' => 'POST', 'postData' => $post, 
'timeout' => $wgLaTeXMLTimeout );
+               $req = $httpRequestClass::factory( $host, $options );
+               $status = $req->execute();
+               if ( $status->isGood() ) {
+                       $res = $req->getContent();
+                       return true;
+               } else {
+                       if ( $status->hasMessage( 'http-timed-out' ) ) {
+                               $error = $this->getError( 
'math_latexml_timeout', $host );
+                               $res = false;
+                               wfDebugLog( "Math", "\nLaTeXML Timeout:"
+                                       . var_export( array( 'post' => $post, 
'host' => $host
+                                               , 'wgLaTeXMLTimeout' => 
$wgLaTeXMLTimeout ), true ) . "\n\n" );
+                       } else {
+                               // for any other unkonwn http error
+                               $errormsg = $status->getHtml();
+                               $error = $this->getError( 
'math_latexml_invalidresponse', $host, $errormsg );
+                               wfDebugLog( "Math", "\nLaTeXML NoResponse:"
+                                       . var_export( array( 'post' => $post, 
'host' => $host
+                                               , 'errormsg' => $errormsg ), 
true ) . "\n\n" );
+                       }
+                       return false;
+               }
+       }
+
+       /* (non-PHPdoc)
+        * @see MathRenderer::writeCache()
+       */
+       public function writeCache() {
+               if ( $this->isChanged() ) {
+                       $this->writeToDatabase();
+               }
+       }
+
+       /**
+        * Picks a LaTeXML daemon.
+        * If more than one demon are availible one is chosen from the
+        * $wgLaTeXMLUrl array.
+        * @return string
+        */
+       private static function pickHost() {
+               global $wgLaTeXMLUrl;
+               if ( is_array( $wgLaTeXMLUrl ) ) {
+                       $host = array_rand( $wgLaTeXMLUrl );
+               } else {
+                       $host = $wgLaTeXMLUrl;
+               }
+               wfDebugLog( "Math", "picking host " . $host );
+               return $host;
+       }
+
+       /**
+        * Does the actual web request to convert TeX to MathML.
+        * @return boolean
+        */
+       private function doRender( ) {
+               $host = self::pickHost();
+               $texcmd = urlencode( $this->tex );
+               $post = $this->getLaTeXMLSettings();
+               $post .= '&tex=' . $texcmd;
+               $this->lastError = '';
+               if ( $this->makeRequest( $host, $post, $res, $this->lastError ) 
) {
+                       $result = json_decode( $res );
+                       if ( json_last_error() === JSON_ERROR_NONE ) {
+                               if ( self::isValidMathML( $result->result ) ) {
+                                       $this->setMathml( $result->result );
+                                       return true;
+                               } else {
+                                       // Do not print bad mathml. It's 
probably too verbose and might
+                                       // mess up the browser output.
+                                       $this->lastError = $this->getError( 
'math_latexml_invalidxml', $host );
+                                       wfDebugLog( "Math", "\nLaTeXML 
InvalidMathML:"
+                                               . var_export( array( 'post' => 
$post, 'host' => $host
+                                                       , 'result' => $result 
), true ) . "\n\n" );
+                                       return false;
+                               }
+                       } else {
+                                       $this->lastError = $this->getError( 
'math_latexml_invalidjson', $host );
+                                       wfDebugLog( "Math", "\nLaTeXML 
InvalidJSON:"
+                                               . var_export( array( 'post' => 
$post, 'host' => $host
+                                                       , 'res' => $res ), true 
) . "\n\n" );
+                                       return false;
+                               }
+               } else {
+                       // Error message has already been set.
+                       return false;
+               }
+       }
+
+       /**
+        * Checks if the input is valid MathML,
+        * and if the root element has the name math
+        * @param string $XML
+        * @return boolean
+        */
+       static public function isValidMathML( $XML ) {
+               $out = false;
+               $prevInternalErrors = libxml_use_internal_errors( true );
+               $xmlObject = simplexml_load_string( $XML );
+               if ( !$xmlObject ) {
+                       wfDebugLog( "Math", "XML validation error:\n " . 
var_export( $XML, true ) . "\n" );
+                       foreach ( libxml_get_errors() as $error ) {
+                               wfDebugLog( "Math", "\t" . $error->message );
+                       }
+                       libxml_clear_errors();
+               } else {
+                       $name = $xmlObject->getName();
+                       if ( $name == "math" or $name == "table" or $name == 
"div" ) {
+                               $out = true;
+                       } else {
+                               wfDebugLog( "Math", "got wrong root element " . 
$name );
+                       }
+               }
+               libxml_use_internal_errors( $prevInternalErrors );
+               return $out;
+       }
+
+       /**
+        * Internal version of @link self::embedMathML
+        * @return string
+        * @return html element with rendered math
+        */
+       private function getMathMLTag() {
+               return self::embedMathML( $this->getMathml(), urldecode( 
$this->getTex() ) );
+       }
+
+       /**
+        * Embeds the MathML-XML element in a HTML span element with class tex
+        * @param string $mml: the MathML string
+        * @param string $tagId: optional tagID for references like 
(pagename#equation2)
+        * @return html element with rendered math
+        */
+       public static function embedMathML( $mml, $tagId = '', $attribs = false 
) {
+               $mml = str_replace( "\n", " ", $mml );
+               if ( ! $attribs ) {
+                       $attribs = array( 'class' => 'tex', 'dir' => 'ltr' );
+                       if ( $tagId ) {
+                               $attribs['id'] = $tagId;
+                       }
+                       $attribs = Sanitizer::validateTagAttributes( $attribs, 
'span' );
+               }
+               return Xml::tags( 'span', $attribs, $mml );
+       }
+
+}
\ No newline at end of file
diff --git a/MathRenderer.php b/MathRenderer.php
index 868a4dd..b2fc50c 100644
--- a/MathRenderer.php
+++ b/MathRenderer.php
@@ -9,8 +9,8 @@
  */
 
 /**
- * Abstract base class with static methods for rendering the <math> tags using 
- * different technologies. These static methods create a new instance of the 
+ * 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 and 
provides
  *  debug information,
@@ -25,19 +25,24 @@
         *  The following variables should made private, as soon it can be 
verified
         *  that they are not being directly accessed by other extensions.
         */
-       var $mode = MW_MATH_PNG;
-       var $tex = '';
+       protected $mode = MW_MATH_PNG;
+       protected $tex = '';
        /**
         * is calculated by texvc.
         * @var string
         */
-       var $hash = '';
-       var $html = '';
-       var $mathml = '';
-       var $conservativeness = 0;
-       var $params = '';
-       var $changed = false;
+       protected $hash = '';
+       protected $html = '';
+       protected $mathml = '';
+       protected $conservativeness = 0;
+       protected $params = '';
+       protected $changed = false;
+       /**
+        * @var boolean forces rerendering if set to true
+        */
+       protected $purge = false;
        protected $recall;
+       protected $lastError = '';
 
        /**
         * Constructs a base MathRenderer
@@ -45,7 +50,7 @@
         * @param string $tex (optional) LaTeX markup
         * @param array $params (optional) HTML attributes
         */
-       public function __construct( $tex='', $params = array() ) {
+       public function __construct( $tex = '', $params = array() ) {
                $this->tex = $tex;
                $this->params = $params;
        }
@@ -73,7 +78,7 @@
         */
        public static function getRenderer( $tex, $params = array(),  $mode = 
MW_MATH_PNG ) {
                global $wgDefaultUserOptions;
-               $validModes = array( MW_MATH_PNG, MW_MATH_SOURCE, 
MW_MATH_MATHJAX );
+               $validModes = array( MW_MATH_PNG, MW_MATH_SOURCE, 
MW_MATH_MATHJAX, MW_MATH_LATEXML );
                if ( !in_array( $mode, $validModes ) )
                        $mode = $wgDefaultUserOptions['math'];
                switch ( $mode ) {
@@ -83,11 +88,14 @@
                        case MW_MATH_MATHJAX:
                                $renderer = new MathMathJax( $tex, $params );
                                break;
+                       case MW_MATH_LATEXML:
+                               $renderer = new MathLaTeXML( $tex, $params );
+                               break;
                        case MW_MATH_PNG:
                        default:
                                $renderer = new MathTexvc( $tex, $params );
                }
-               wfDebugLog ( "Math", 'start rendering $' . $renderer->tex . '$' 
);
+               wfDebugLog ( "Math", 'start rendering $' . $renderer->tex . '$ 
in mode ' . $mode );
                return $renderer;
        }
 
@@ -152,9 +160,11 @@
                        $this->hash = $xhash['md5'];
                        $this->conservativeness = 
$rpage->math_html_conservativeness;
                        $this->html = $rpage->math_html;
-                       $this->mathml = $rpage->math_mathml;
-                       $this->recall = true;
-                       return true;
+                       $this->mathml = utf8_decode( $rpage->math_mathml);
+                       if ( StringUtils::isUtf8( $this->mathml ) ) {
+                               $this->recall = true;
+                               return true;
+                       }
                }
 
                # Missing from the database and/or the render cache
@@ -189,7 +199,7 @@
                                        'math_outputhash' => $outmd5_sql ,
                                        'math_html_conservativeness' => 
$this->conservativeness,
                                        'math_html' => $this->html,
-                                       'math_mathml' => $this->mathml,
+                                       'math_mathml' => utf8_encode( 
$this->mathml ),
                                        ),
                                __METHOD__
                        );
@@ -210,6 +220,8 @@
                $attribs = Sanitizer::mergeAttributes( $attribs, $overrides );
                return $attribs;
        }
+
+
        /**
         * Writes cache.  Does nothing by default
         */
@@ -255,7 +267,7 @@
 
        /**
         * Get the hash calculated by texvc
-        * 
+        *
         * @return string hash
         */
        public function getHash() {
@@ -321,7 +333,7 @@
 
        /**
         * Get the attributes of the math tag
-        * 
+        *
         * @return array()
         */
        public function getParams() {
@@ -332,11 +344,11 @@
         * @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.
+               // $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;
        }
 
@@ -349,5 +361,32 @@
                return $this->changed;
        }
 
+       /**
+        * Checks if there is an explicit user request to rerender the math-tag.
+        * @return boolean
+        */
+       function isPurge( ) {
+               if ( $this->purge ) {
+                       return true;
+               }
+               // TODO: Figure out if ?action=purge
+               // until this issue is resolved we use ?mathpurge=true instead
+               global $wgRequest;
+               return ( $wgRequest->getVal( 'mathpurge' ) === "true" );
+       }
+
+       /**
+        * Sets purge. If set to true the render is forced to rerender and must 
not
+        * use a cached version.
+        * @return boolean
+        */
+       function setPurge( $purge = true ) {
+               $this->changed = true;
+               $this->purge = $purge;
+       }
+
+       function getLastError(){
+               return $this->lastError;
+       }
 }
 
diff --git a/README b/README
index 8846d84..f003860 100644
--- a/README
+++ b/README
@@ -7,6 +7,16 @@
 See the README in the math subdirectory for more info on setting up the
 low-level conversion tools.
 
+MathML support:
+If you prefer MathML rather than images you can use LaTeXML to convert the
+math tags to MathML. To use that feature you have to enable LaTeXML by setting
+$wgUseLaTeXML = true;
+It is possible to choose LaTeXML as default option (for anonymous user) by 
setting
+$wgDefaultUserOptions['math'] = MW_MATH_LATEXML;
+in the LocalSettings.php file.
+The LaTeXML option requires php5-curl to be installed. Without php5-curl no 
proper
+error handling can be guaranteed.
+
 MathJax configuration:
 Client-side configuration of MathJax can be done by specifying a mathJax.config
 table, which takes a table as described in:
diff --git a/db/math.sql b/db/math.sql
index e89991c..f509555 100644
--- a/db/math.sql
+++ b/db/math.sql
@@ -16,7 +16,7 @@
   -- HTML output from texvc, if any
   math_html text,
 
-  -- MathML output from texvc, if any
+  -- MathML output from texvc, or from LaTeXML
   math_mathml text
 ) /*$wgDBTableOptions*/;
 
diff --git a/tests/MathDatabaseTest.php b/tests/MathDatabaseTest.php
index f909f7f..99fb00e 100644
--- a/tests/MathDatabaseTest.php
+++ b/tests/MathDatabaseTest.php
@@ -72,8 +72,8 @@
                // comparing the class object does now work due to null values 
etc.
                // $this->assertEquals($this->renderer,$renderer2);
                $this->assertEquals( $this->renderer->getTex(), 
$renderer2->getTex(), "test if tex is the same" );
-               $this->assertEquals( $this->renderer->mathml, 
$renderer2->mathml, "Check MathML encoding" );
-               $this->assertEquals( $this->renderer->html, $renderer2->html );
+               $this->assertEquals( $this->renderer->getMathml(), 
$renderer2->getMathml(), "Check MathML encoding" );
+               $this->assertEquals( $this->renderer->getHtml(), 
$renderer2->getHtml() );
        }
 
 
diff --git a/tests/MathLaTeXMLTest.php b/tests/MathLaTeXMLTest.php
new file mode 100644
index 0000000..30adf0d
--- /dev/null
+++ b/tests/MathLaTeXMLTest.php
@@ -0,0 +1,146 @@
+<?php
+/**
+* Test the LaTeXML output format.
+*
+* @group Math
+*/
+class MathLaTeXMLTest extends MediaWikiTestCase {
+
+       // State-variables for HTTP Mockup classes
+       public static $content = null;
+       public static $good = false;
+       public static $html = false;
+       public static $timeout = false;
+
+       /**
+        * Set the mock values for the HTTP Mockup classes
+        *
+        * @param boolean $good
+        * @param mixed $html HTML of the error message or false if no error is 
present.
+        * @param boolean $timeout true if
+        */
+       public static function setMockValues( $good, $html, $timeout ) {
+               self::$good = $good;
+               self::$html = $html;
+               self::$timeout = $timeout;
+       }
+
+       /**
+        * Tests behavior of makeRequest() that communicates with the host.
+        * Testcase: Invalid request.
+        * @covers MathTexvc::makeRequest
+        */
+       public function testMakeRequestInvalid() {
+               self::setMockValues( false, false, false );
+               $url = 'http://example.com/invalid';
+
+               $renderer = $this->getMockBuilder( 'MathLaTeXML' )
+                       ->setMethods( NULL )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $requestReturn = $renderer->makeRequest( $url, 'a+b', $res, 
$error
+                       , 'LaTeXMLHttpRequestTester' );
+               $this->assertEquals( false, $requestReturn
+                       , "requestReturn is false if HTTP::post returns false." 
);
+               $this->assertEquals( false, $res
+                       , "res is false if HTTP:post returns false." );
+               $errmsg = wfMessage( 'math_latexml_invalidresponse' , $url )
+                       ->inContentLanguage()->escaped();
+               $this->assertContains( $errmsg, $error
+                       , "return an error if HTTP::post returns false" );
+       }
+
+       /**
+        * Tests behavior of makeRequest() that communicates with the host.
+        * Testcase: Valid request.
+        * @covers MathTexvc::makeRequest
+        */
+       public function testMakeRequestSuccess() {
+               self::setMockValues( true, true, false );
+               $url = 'http://example.com/valid';
+               $renderer = $this->getMockBuilder( 'MathLaTeXML' )
+                       ->setMethods( NULL )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $requestReturn = $renderer->makeRequest( $url, 'a+b', $res, 
$error
+                       , 'LaTeXMLHttpRequestTester' );
+               $this->assertEquals( true, $requestReturn, "successful call 
return" );
+               $this->isTrue( $res, "successfull call" );
+               $this->assertEquals( $error,'', "successfull call errormessage" 
);
+       }
+
+       /**
+        * Tests behavior of makeRequest() that communicates with the host.
+        * Testcase: Timeout.
+        * @covers MathTexvc::makeRequest
+        */
+       public function testMakeRequestTimeout() {
+               self::setMockValues( false, true, true );
+               $url = 'http://example.com/timeout';
+               $renderer = $this->getMockBuilder( 'MathLaTeXML' )
+                       ->setMethods( NULL )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $requestReturn = $renderer->makeRequest( $url, 
'$\longcommand$', $res
+                       , $error, 'LaTeXMLHttpRequestTester' );
+               $this->assertEquals( false, $requestReturn, "timeout call 
return" );
+               $this->assertEquals( false, $res, "timeout call return" );
+               $errmsg = wfMessage( 'math_latexml_timeout', $url )
+                       ->inContentLanguage()->escaped();
+               $this->assertContains( $errmsg, $error, "timeout call 
errormessage" );
+       }
+
+       /**
+        * Checks the basic functionallity
+        * i.e. if the span element is generated right.
+        */
+       public function testIntegration() {
+               global $wgLaTeXMLTimeout;
+               $wgLaTeXMLTimeout = 20;
+               $renderer = MathRenderer::getRenderer( "a+b", array(), 
MW_MATH_LATEXML );
+               $real = $renderer->render( true );
+               $expected = '<span class="tex" dir="ltr" id="a_b"><math 
xmlns="http://www.w3.org/1998/Math/MathML"; id="p1.1.m1" class="ltx_Math" 
alttext="a+b" xml:id="p1.1.m1.1" display="inline" xref="p1.1.m1.1.cmml">   
<semantics xml:id="p1.1.m1.1a" xref="p1.1.m1.1.cmml">     <mrow 
xml:id="p1.1.m1.1.4" xref="p1.1.m1.1.4.cmml">       <mi xml:id="p1.1.m1.1.1" 
xref="p1.1.m1.1.1.cmml">a</mi>       <mo xml:id="p1.1.m1.1.2" 
xref="p1.1.m1.1.2.cmml">+</mo>       <mi xml:id="p1.1.m1.1.3" 
xref="p1.1.m1.1.3.cmml">b</mi>     </mrow>     <annotation-xml 
xml:id="p1.1.m1.1.cmml" encoding="MathML-Content" xref="p1.1.m1.1">       
<apply xml:id="p1.1.m1.1.4.cmml" xref="p1.1.m1.1.4">         <plus 
xml:id="p1.1.m1.1.2.cmml" xref="p1.1.m1.1.2"/>         <ci 
xml:id="p1.1.m1.1.1.cmml" xref="p1.1.m1.1.1">a</ci>         <ci 
xml:id="p1.1.m1.1.3.cmml" xref="p1.1.m1.1.3">b</ci>       </apply>     
</annotation-xml>     <annotation xml:id="p1.1.m1.1b" 
encoding="application/x-tex" xref="p1.1.m1.1.cmml">a+b</annotation>   
</semantics> </math></span>';
+               $this->assertEquals( $expected, $real
+                               , "Rendering of a+b in plain Text mode" );
+       }
+}
+
+/**
+ * Helper class for testing
+ * @author physikerwelt
+ * @see MWHttpRequestTester
+ *
+ */
+class LaTeXMLHttpRequestTester {
+       public static function factory() {
+               return new LaTeXMLHttpRequestTester();
+       }
+       public static function execute() {
+               return new LaTeXMLTestStatus();
+       }
+       public static function getContent() {
+               return MathLaTeXMLTest::$content;
+       }
+}
+
+/**
+ * Helper class for testing
+ * @author physikerwelt
+ * @see Status
+ */
+class LaTeXMLTestStatus {
+       static function isGood() {
+               return MathLaTeXMLTest::$good;
+       }
+
+       static function hasMessage( $s ) {
+               if ( $s == 'http-timed-out' ) {
+                       return MathLaTeXMLTest::$timeout;
+               } else {
+                       return false;
+               }
+       }
+       static function getHtml() {
+               return MathLaTeXMLTest::$html;
+       }
+}
\ No newline at end of file
diff --git a/tests/MathRendererTest.php b/tests/MathRendererTest.php
index ea6c96b..325fcac 100644
--- a/tests/MathRendererTest.php
+++ b/tests/MathRendererTest.php
@@ -63,4 +63,14 @@
                $this->assertEquals( $renderer->isChanged(), true
                        , "assumes that changing a hash sets changed to true");
        }
+
+       public function testSetPurge(){
+               $renderer = $this->getMockBuilder( 'MathRenderer' )
+               ->setMethods( array( 'render' ) )
+               ->disableOriginalConstructor()
+               ->getMock();
+               $renderer->setPurge();
+               $this->assertEquals( $renderer->isPurge(), true, "Test purge." 
);
+
+       }
 }
\ No newline at end of file

-- 
To view, visit https://gerrit.wikimedia.org/r/61987
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I5d29e219c0d3b907e22ea0bb3b30f000d8a7a9f8
Gerrit-PatchSet: 34
Gerrit-Project: mediawiki/extensions/Math
Gerrit-Branch: master
Gerrit-Owner: Physikerwelt <[email protected]>
Gerrit-Reviewer: Cjucovschi <[email protected]>
Gerrit-Reviewer: Deyan <[email protected]>
Gerrit-Reviewer: JanZerebecki <[email protected]>
Gerrit-Reviewer: Mattflaschen <[email protected]>
Gerrit-Reviewer: MaxSem <[email protected]>
Gerrit-Reviewer: Ori.livneh <[email protected]>
Gerrit-Reviewer: Physikerwelt <[email protected]>
Gerrit-Reviewer: PleaseStand <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: TheDJ <[email protected]>
Gerrit-Reviewer: Worden.lee <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to