Physikerwelt has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/135495

Change subject: WIP: Add separate database table for LaTeXML (step 3)
......................................................................

WIP: Add separate database table for LaTeXML (step 3)

Currently the PNG and the LaTeXML rendering mode
use a common table in the database. If both rendering
modes are allowed in a wiki simultaneously this causes
problems, because the fields are continuously overwritten.

Change-Id: I8b11ffd0a39fadd7d3c8de1e94e74ff5f490430d
---
M MathLaTeXML.php
M MathRenderer.php
M MathSource.php
M MathTexvc.php
A db/mathlatexml.pg.sql
A db/mathlatexml.sqllite.sql
M tests/MathDatabaseTest.php
M tests/MathLaTeXMLDatabaseTest.php
M tests/MathRendererTest.php
9 files changed, 493 insertions(+), 188 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Math 
refs/changes/95/135495/1

diff --git a/MathLaTeXML.php b/MathLaTeXML.php
index 1bdd70c..674673f 100644
--- a/MathLaTeXML.php
+++ b/MathLaTeXML.php
@@ -192,7 +192,7 @@
 
        /**
         * Picks a LaTeXML daemon.
-        * If more than one demon are availible one is chosen from the
+        * If more than one daemon are available one is chosen from the
         * $wgMathLaTeXMLUrl array.
         * @return string
         */
@@ -230,8 +230,15 @@
         * Does the actual web request to convert TeX to MathML.
         * @return boolean
         */
-       private function doRender( ) {
+       protected function doRender() {
+               global $wgMathDebug;
                wfProfileIn( __METHOD__ );
+               if ( trim( $this->getTex() ) === '' ) {
+                       wfDebugLog( "Math", "Rendering was requested, but no 
TeX string is specified." );
+                       $this->lastError = $this->getError( 'math_empty_tex' );
+                       return false;
+               }
+               $res = '';
                $host = self::pickHost();
                $post = $this->getPostData();
                // There is an API-inconsistency between different versions of 
the LaTeXML daemon
@@ -240,26 +247,30 @@
                        $post = preg_replace( '/&tex=/' , '&tex=literal:', 
$post , 1);
                }
                $this->lastError = '';
-               if ( $this->makeRequest( $host, $post, $res, $this->lastError ) 
) {
-                       $result = json_decode( $res );
-                       if ( json_last_error() === JSON_ERROR_NONE ) {
-                               if ( $this->isValidMathML( $result->result ) ) {
-                                       $this->setMathml( $result->result );
-                                       wfProfileOut( __METHOD__ );
+               $requestResult = $this->makeRequest( $host, $post, $res, 
$this->lastError );
+               if ( $requestResult ) {
+                       $jsonResult = json_decode( $res );
+                       if ( $jsonResult && json_last_error() === 
JSON_ERROR_NONE ) {
+                               if ( $this->isValidMathML( $jsonResult->result 
) ) {
+                                       $this->setMathml( $jsonResult->result );
+                                       if ( $wgMathDebug ) {
+                                               $this->setLog( $jsonResult->log 
);
+                                               $this->setStatusCode( 
$jsonResult->status_code );
+                                       }
                                        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 );
+                                       $this->lastError = $this->getError( 
'math_invalidxml', $this->getModeStr(), $host );
                                        wfDebugLog( "Math", "\nLaTeXML 
InvalidMathML:"
-                                               . var_export( array( 'post' => 
$post, 'host' => $host
-                                                       , 'result' => $result 
), true ) . "\n\n" );
+                                                       . var_export( array( 
'post' => $post, 'host' => $host
+                                                               , 'result' => 
$res ), true ) . "\n\n" );
                                        wfProfileOut( __METHOD__ );
                                        return false;
                                }
                        } else {
-                                       $this->lastError = $this->getError( 
'math_latexml_invalidjson', $host );
-                                       wfDebugLog( "Math", "\nLaTeXML 
InvalidJSON:"
+                               $this->lastError = $this->getError( 
'math_invalidjson', $this->getModeStr(), $host );
+                               wfDebugLog( "Math", "\nLaTeXML InvalidJSON:"
                                                . var_export( array( 'post' => 
$post, 'host' => $host
                                                        , 'res' => $res ), true 
) . "\n\n" );
                                        wfProfileOut( __METHOD__ );
@@ -347,4 +358,8 @@
                return Xml::tags( 'span', $attribs, $mml );
        }
 
+       protected function getMathTableName() {
+               return 'mathlatexml';
+       }
 }
+
diff --git a/MathRenderer.php b/MathRenderer.php
index 088c351..7ef2bce 100644
--- a/MathRenderer.php
+++ b/MathRenderer.php
@@ -21,35 +21,50 @@
  * @author Moritz Schubotz
  */
 abstract class MathRenderer {
-       /**
-        *  The following variables should made private, as soon it can be 
verified
-        *  that they are not being directly accessed by other extensions.
-        */
-       protected $mode = MW_MATH_PNG;
+
+       // REPRESENTATIONS OF THE MATHEMATICAL CONTENT
+       /** @var string tex representation */
        protected $tex = '';
-       /** @var string the original user input string (which was used to 
caculate the inputhash) */
+       /** @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 
(MW_MATHSTYLE_INLINE_DISPLAYSTYLE|MW_MATHSTYLE_DISPLAY|MW_MATHSTYLE_INLINE) the 
rendering style */
        protected $mathStyle = MW_MATHSTYLE_INLINE_DISPLAYSTYLE;
-       /**
-        * is calculated by texvc.
-        * @var string
-        */
-       protected $hash = '';
-       protected $html = '';
-       protected $mathml = '';
-       protected $conservativeness = 0;
-       protected $params = '';
+       /** @var array with userdefined parameters passed to the extension (not 
used) */
+       protected $params = array();
+       /** @var string a userdefined identifier to link to the equation. */
+       protected $id = '';
+
+       // DEBUG VARIABLES
+       // Available, if Math extension runs in debug mode ($wgMathDebug = 
true) only.
+       /** @var int LaTeXML return code (will be available in future Mathoid 
versions as well)*/
+       protected $statusCode = 0;
+       /** @var timestamp of the last modification of the database entry */
+       protected $timestamp;
+       /** @var log messages generated during conversion of mathematical 
content */
+       protected $log = '';
+
        // STATE OF THE CLASS INSTANCE
        /** @var boolean has variable tex been security-checked */
        protected $texSecure = false;
+       /** @var boolean has the mathematical content changed */
        protected $changed = false;
-       /**
-        * @var boolean forces rerendering if set to true
-        */
+       /** @var boolean is there a database entry for the mathematical content 
*/
+       protected $storedInDatabase = null;
+       /** @var boolean is there a request to purge the existing mathematical 
content */
        protected $purge = false;
-       protected $recall;
+       /** @var string with last occurred error */
        protected $lastError = '';
+       /** @var string md5 value from userInputTex */
+       protected $md5 = '';
+       /** @var binary packed inputhash */
+       protected $inputHash = '';
+       /** @var int rendering mode MW_MATH_(PNG|MATHML|SOURCE...) */
+       protected $mode = MW_MATH_PNG;
 
        /**
         * Constructs a base MathRenderer
@@ -158,10 +173,45 @@
         *
         * @return string hash
         */
+       public function getMd5() {
+               if ( ! $this->md5 ) {
+                       $this->md5 = md5( $this->userInputTex );
+               }
+               return $this->md5;
+       }
+
+       /**
+        * set the input hash (if user input tex is not available)
+        *
+        * @return string hash
+        */
+       public function setMd5( $md5 ) {
+               $this->md5 = $md5;
+       }
+
+       /**
+        * Return hash of input
+        *
+        * @return string hash
+        */
        public function getInputHash() {
                // TODO: What happens if $tex is empty?
+               if ( !$this->inputHash ) {
+                       $dbr = wfGetDB( DB_SLAVE );
+                       return $dbr->encodeBlob( pack( "H32", $this->getMd5() ) 
); # Binary packed, not hex
+               }
+               return $this->inputHash;
+       }
+
+       /**
+        * Decode binary packed hash from the database to md5 of input_tex
+        * @param binary $hash
+        * @return string md5
+        */
+       private static function dbHash2md5( $hash ) {
                $dbr = wfGetDB( DB_SLAVE );
-               return $dbr->encodeBlob( pack( "H32", md5( 
$this->getUserInputTex() ) ) ); # Binary packed, not hex
+               $xhash = unpack( 'H32md5', $dbr->decodeBlob( $hash ) . "        
        " );
+               return $xhash['md5'];
        }
 
        /**
@@ -171,53 +221,79 @@
         */
        public function readFromDatabase() {
                wfProfileIn( __METHOD__ );
+               /** @var DatabaseBase */
                $dbr = wfGetDB( DB_SLAVE );
-               $rpage = $dbr->selectRow( 'math', $this->dbInArray(),
-                       array( 'math_inputhash' => $this->getInputHash() ), 
__METHOD__ );
+               /** @var ResultWrapper asdf */
+               $rpage = $dbr->selectRow( $this->getMathTableName(),
+                               $this->dbInArray(),
+                               array( 'math_inputhash' => 
$this->getInputHash() ),
+                               __METHOD__ );
+
                if ( $rpage !== false ) {
                        $this->initializeFromDatabaseRow( $rpage );
-                       if ( ! is_callable( 'StringUtils::isUtf8' ) ) {
-                               $msg = wfMessage( 'math_latexml_xmlversion' 
)->inContentLanguage()->escaped();
-                               trigger_error( $msg, E_USER_NOTICE );
-                               wfDebugLog( 'Math', $msg );
-                               // If we can not check if mathml output is 
valid, we skip the test and assume that it is valid.
-                               $this->recall = true;
-                               wfProfileOut( __METHOD__ );
-                               return true;
-                       } elseif ( StringUtils::isUtf8( $this->mathml ) ) {
-                               $this->recall = true;
-                               wfProfileOut( __METHOD__ );
-                               return true;
-                       }
+                       $this->storedInDatabase = true;
+                       wfProfileOut( __METHOD__ );
+                       return true;
+               } else {
+                       # Missing from the database and/or the render cache
+                       $this->storedInDatabase = false;
+                       wfProfileOut( __METHOD__ );
+                       return false;
                }
-
-               # Missing from the database and/or the render cache
-               $this->recall = false;
-               wfProfileOut( __METHOD__ );
-               return false;
        }
-       /**
-        *
-        * @param database_row $rpage
-        */
-       public function initializeFromDatabaseRow( $rpage ) {
-               $dbr = wfGetDB( DB_SLAVE );
-               $xhash = unpack( 'H32md5',
-                       $dbr->decodeBlob( $rpage->math_outputhash ) . "         
       " );
-               $this->hash = $xhash['md5'];
-               $this->conservativeness = $rpage->math_html_conservativeness;
-               $this->html = $rpage->math_html;
-               $this->mathml = utf8_decode( $rpage->math_mathml );
-               $this->storedInDatabase = true;
-       }
-
        /**
         * @return array with the database column names
         */
-       private function dbInArray() {
-               return array( 'math_inputhash', 'math_outputhash', 
'math_html_conservativeness', 'math_html',
-                               'math_mathml' );
+       protected function dbInArray() {
+               global $wgMathDebug;
+               $in = array( '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 database_row $rpage
+        */
+       protected function initializeFromDatabaseRow( $rpage ) {
+               global $wgMathDebug;
+               $this->inputHash = $rpage->math_inputhash; // MUST NOT BE NULL
+               $this->md5 = self::dbHash2md5( $this->inputHash );
+               if ( ! empty( $rpage->math_mathml ) ) {
+                       $this->mathml = utf8_decode ( $rpage->math_mathml );
+       }
+               if ( ! empty( $rpage->math_inputtex ) ) { // in the current 
database the field is probably not set.
+                       $this->userInputTex = $rpage->math_inputtex;
+               }
+               if ( ! empty( $rpage->math_tex ) ) {
+                       $this->tex = $rpage->math_tex;
+               }
+               if ( ! empty( $rpage->math_svg ) ) {
+                       $this->svg = $rpage->math_svg;
+               }
+               if ( $wgMathDebug ) {
+                       if ( ! empty( $rpage->math_status ) ) {
+                               $this->statusCode = $rpage->math_status;
+                       }
+                       if ( ! empty( $rpage->math_log ) ) {
+                               $this->timestamp = $rpage->math_log;
+                       }
+                       if ( ! empty( $rpage->math_timestamp ) ) {
+                               $this->log = $rpage->math_log;
+                       }
+                       if ( $this->userInputTex ) {
+                               if ( $this->md5 !== md5( 
$this->getUserInputTex() ) ) {
+                                               wfDebugLog ( "Math", 'Hash in 
the database does not match the hash of the user inputtext.' );
+                                       }
+                       }
+               }
+               $this->changed = false;
+       }
+
        /**
         * Writes rendering entry to database.
         *
@@ -226,17 +302,37 @@
         * This function stores the values that are currently present in the 
class to the database even if they are empty.
         *
         * This function can be seen as protected function.
+        * @param DatabaseBase $dbw
         */
        public function writeToDatabase( $dbw = null ) {
+               global $wgMathDebug;
                # Now save it back to the DB:
                if ( !wfReadOnly() ) {
                        $dbw = $dbw ? : wfGetDB( DB_MASTER );
-                       wfDebugLog( "Math", 'store entry for $' . $this->tex . 
'$ in database (hash:' . bin2hex( $this->hash ) . ")\n" );
+                       wfDebugLog( "Math", 'store entry for $' . $this->tex . 
'$ in database (hash:' . $this->getMd5() . ")\n" );
                        $outArray = $this->dbOutArray();
-                       $dbw->onTransactionIdle(
-                                       function() use( $dbw, $outArray ) {
-                                               $dbw->replace( 'math', array( 
'math_inputhash' ), $outArray, __METHOD__ );
+                       $method = __METHOD__;
+                       $mathTableName = $this->getMathTableName();
+                       if ( $this->isInDatabase() ) {
+                               $inputHash = $this->getInputHash();
+                               $dbw->onTransactionIdle(
+                                       function() use( $dbw, $outArray, 
$wgMathDebug, $inputHash, $method, $mathTableName ) {
+                                               $dbw->update( $mathTableName, 
$outArray , array( 'math_inputhash' => $inputHash ), $method );
+                                               if ( $wgMathDebug ) wfDebugLog( 
"Math", 'Row updated after db transaction was idle: ' . var_export( $outArray , 
true ) . " to database \n" );
                                        } );
+                       } else {
+                               $dbw->onTransactionIdle(
+                                       function() use( $dbw, $outArray, 
$wgMathDebug, $method, $mathTableName ) {
+                                               $dbw->insert( $mathTableName, 
$outArray, $method , array ( 'IGNORE' ) );
+                                               if ( $wgMathDebug ) {
+                                                       wfDebugLog( "Math", 
'Row inserted after db transaction was idle ' . var_export( $outArray , true ) 
. " to database \n" );
+                                                       if ( 
$dbw->affectedRows() == 0 ) {
+                                                               // That's the 
price for the delayed update.
+                                                               wfDebugLog( 
"Math", 'Entry could not be written. Might be changed in between. ' );
+                                                       }
+                                               }
+                                       } );
+                       }
                }
        }
 
@@ -244,18 +340,14 @@
         * Gets an array that matches the variables of the class to the 
database columns
         * @return array
         */
-       private function dbOutArray() {
-               $dbr = wfGetDB( DB_SLAVE );
-               if ( $this->hash ) {
-                       $outmd5_sql = $dbr->encodeBlob( pack( 'H32', 
$this->hash ) );
-               } else {
-                       $outmd5_sql = 0; // field cannot be null
-                       // TODO: Change Database layout to allow for null values
-               }
-               $out = array( 'math_inputhash' => $this->getInputHash(), 
'math_outputhash' => $outmd5_sql,
-                               'math_html_conservativeness' => 
$this->conservativeness, 'math_html' => $this->html,
-                               'math_mathml' => utf8_encode( $this->mathml ) );
-               wfDebugLog( "Math", "Store Data:" . var_export( $out, true ) . 
"\n\n" );
+       protected function dbOutArray() {
+               global $wgMathDebug;
+               $out = array( 'math_inputhash' => $this->getInputHash (),
+                       'math_mathml' => utf8_encode ( $this->mathml ),
+                       'math_inputtex' => $this->userInputTex,
+                       'math_tex' => $this->tex,
+                       'math_svg' => $this->svg
+                       );
                return $out;
        }
 
@@ -279,18 +371,16 @@
         * Writes cache. Writes the database entry if values were changed
         */
        public function writeCache() {
+               global $wgMathDebug;
+               if ( $wgMathDebug) wfDebugLog( "Math" , "writing of cache 
requested." );
                if ( $this->isChanged() ) {
+                       if ( $wgMathDebug) wfDebugLog( "Math" , "Change 
detected. Perform writing." );
                        $this->writeToDatabase();
+                       return true;
+               } else {
+                       if ( $wgMathDebug) wfDebugLog( "Math" , "Nothing was 
changed. Don't write to database." );
+                       return false;
                }
-       }
-
-       /**
-        * Determines if this is a cached/recalled render
-        *
-        * @return boolean true if recalled, false otherwise
-        */
-       public function isRecall() {
-               return $this->recall;
        }
 
        /**
@@ -303,6 +393,14 @@
        }
 
        /**
+        * gets the timestamp, of the last rendering of that equation
+        * @return int
+        */
+       public function getTimestamp() {
+               return $this->timestamp;
+       }
+
+       /**
         * gets the rendering mode MW_MATH_*
         *
         * @return int
@@ -312,46 +410,29 @@
        }
 
        /**
+        * Sets the rendering mode
+        * @param int $newMode element of the array $wgMathValidModes
+        * @return bool
+        */
+       public function setMode( $newMode ){
+               global$wgMathValidModes;
+               if ( in_array($newMode, $wgMathValidModes ) ) {
+                       $this->mode = $newMode;
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+       /**
         * Sets the TeX code
         *
         * @param string $tex
         */
        public function setTex( $tex ) {
-               $this->changed = true;
-               $this->tex = $tex;
-       }
-
-       /**
-        * Get the hash calculated by texvc
-        *
-        * @return string hash
-        */
-       public function getHash() {
-               return $this->hash;
-       }
-
-       /**
-        * @param string $hash
-        */
-       public function setHash( $hash ) {
-               $this->changed = true;
-               $this->hash = $hash;
-       }
-
-       /**
-        * Returns the html-representation of the mathematical formula.
-        * @return string
-        */
-       public function getHtml() {
-               return $this->html;
-       }
-
-       /**
-        * @param string $html
-        */
-       public function setHtml( $html ) {
-               $this->changed = true;
-               $this->html = $html;
+               if ( $this->tex != $tex ) {
+                       $this->changed = true;
+                       $this->tex = $tex;
+               }
        }
 
        /**
@@ -359,6 +440,14 @@
         * @return string in UTF-8 encoding
         */
        public function getMathml() {
+               if ( ! is_callable( 'StringUtils::isUtf8' ) ) {
+                       $msg = wfMessage( 'math_latexml_xmlversion' 
)->inContentLanguage()->escaped();
+                       trigger_error( $msg, E_USER_NOTICE );
+                       wfDebugLog( 'Math', $msg );
+                       // If we can not check if mathml output is valid, we 
skip the test and assume that it is valid.
+               } elseif ( ! StringUtils::isUtf8( $this->mathml ) ) {
+                       $this->setMathml( '' );
+               }
                return $this->mathml;
        }
 
@@ -368,23 +457,6 @@
        public function setMathml( $mathml ) {
                $this->changed = true;
                $this->mathml = $mathml;
-       }
-
-       /**
-        * Gets the so called 'conservativeness' calculated by texvc
-        *
-        * @return int
-        */
-       public function getConservativeness() {
-               return $this->conservativeness;
-       }
-
-       /**
-        * @param int $conservativeness
-        */
-       public function setConservativeness( $conservativeness ) {
-               $this->changed = true;
-               $this->conservativeness = $conservativeness;
        }
 
        /**
@@ -446,6 +518,12 @@
                return $this->lastError;
        }
 
+       /**
+        * @return string
+        */
+       public function getLog() {
+               return $this->log;
+       }
 
        /**
         *
@@ -465,7 +543,28 @@
        public function getMathStyle() {
                return $this->mathStyle;
        }
+       /**
+        * @param string $log
+        */
+       public function setLog( $log ) {
+               $this->changed = true;
+               $this->log = $log;
+       }
 
+       /**
+        * @return int
+        */
+       public function getStatusCode() {
+               return $this->statusCode;
+       }
+
+       /**
+        * @param unknown_type $statusCode
+        */
+       public function setStatusCode( $statusCode ) {
+               $this->changed = true;
+               $this->statusCode = $statusCode;
+       }
        /**
         * Get if the input tex was marked as secure
         * @return boolean
@@ -490,11 +589,59 @@
                }
        }
 
+
+
+       public function isInDatabase() {
+               if ( $this->storedInDatabase === null ) {
+                       $this->readFromDatabase();
+               }
+               return $this->storedInDatabase;
+       }
+
        /**
-        * @return string original tex string specified by the user
+        *
+        * @return string TeX the original tex string specified by the user
         */
        public function getUserInputTex() {
                return $this->userInputTex;
        }
-}
 
+       /**
+        * @return string Userdefined ID
+        */
+       public function getID() {
+               return $this->id;
+       }
+
+       /**
+        * @return string Userdefined ID
+        */
+       public function setID( $id ) {
+               return $this->id = $id;
+       }
+
+               /**
+        *
+        * @param type $svg
+        */
+       public function setSvg( $svg ) {
+               $this->changed = true;
+               $this->svg = trim( $svg );
+       }
+
+       /**
+        *
+        * @return type
+        */
+       public function getSvg() {
+               // Spaces will prevent the image from being displayed correctly 
in the browser
+               return trim( $this->svg );
+       }
+
+       protected abstract function getMathTableName();
+
+       public function getModeStr() {
+               $names = MathHooks::getMathNames();
+               return $names[ $this->getMode() ];
+       }
+}
diff --git a/MathSource.php b/MathSource.php
index 8eabaef..6b395e5 100644
--- a/MathSource.php
+++ b/MathSource.php
@@ -46,4 +46,7 @@
                );
        }
 
+       protected function getMathTableName() {
+               throw new MWException ( 'in math source mode no database 
caching should happen');
+       }
 }
diff --git a/MathTexvc.php b/MathTexvc.php
index 37e4b70..bb6c51a 100644
--- a/MathTexvc.php
+++ b/MathTexvc.php
@@ -16,12 +16,63 @@
  * @author Tomasz Wegrzanowski
  * @author Brion Vibber
  * @author Moritz Schubotz
+ * @deprecated will be deleted in one of the next versions without further 
notice
  */
 class MathTexvc extends MathRenderer {
+       private $hash = '';
+       private $html = '';
+       private $conservativeness = 0;
        const CONSERVATIVE = 2;
        const MODERATE = 1;
        const LIBERAL = 0;
        const MW_TEXVC_SUCCESS = -1;
+
+     /**
+        * Gets an array that matches the variables of the class to the 
database columns
+        * @return array
+        */
+       public function dbOutArray() {
+               global $wgMathDebug;
+               $out = array();
+               $dbr = wfGetDB( DB_SLAVE );
+               $outmd5_sql = $dbr->encodeBlob( pack( 'H32', $this->hash ) );
+               if ( $outmd5_sql instanceof Blob ){
+                       $outmd5_sql = $outmd5_sql->fetch();
+               }
+               $out['math_outputhash'] = $outmd5_sql;
+               $out['math_html_conservativeness'] = $this->conservativeness;
+               $out['math_html'] = $this->html;
+               $out['math_mathml'] = $this->getMathml();
+               $out['math_inputhash'] = $this->getInputHash();
+               if ( $wgMathDebug )     wfDebugLog( 'Math', 'Store Hashpath of 
image' . bin2hex( $outmd5_sql ) );
+               return $out;
+       }
+
+       protected function dbInArray() {
+               return array( 'math_inputhash', 'math_outputhash',
+                               'math_html_conservativeness', 'math_html', 
'math_mathml' );
+       }
+
+       /**
+        * @param database_row $rpage
+        */
+       protected function initializeFromDatabaseRow( $rpage ) {
+               $result = parent::initializeFromDatabaseRow( $rpage );
+               // get deprecated fields
+               if ( $rpage->math_outputhash ) {
+                       $dbr = wfGetDB( DB_SLAVE );
+                       $xhash = unpack( 'H32md5',
+                               $dbr->decodeBlob( $rpage->math_outputhash ) . " 
               " );
+                       $this->hash = $xhash['md5'];
+                       wfDebugLog( 'Math', 'Hashpath of PNG-File:' . bin2hex( 
$this->hash ) );
+                       $this->conservativeness = 
$rpage->math_html_conservativeness;
+                       $this->html = $rpage->math_html;
+                       $this->setMathml( $rpage->math_mathml );
+                       return true;
+               } else {
+                       return false;
+               }
+       }
 
        /**
         * Renders TeX using texvc
@@ -203,7 +254,7 @@
                if ( !$errmsg ) {
                        $newHash = substr( $contents, 1, 32 );
                        if ( $this->hash !== $newHash ) {
-                               $this->recall = false; // DB needs update in 
writeCache() (bug 60997)
+                               $this->isInDatabase( false ); // DB needs 
update in writeCache() (bug 60997)
                        }
                        $this->setHash( $newHash );
                }
@@ -314,14 +365,9 @@
                global $wgUseSquid;
 
                wfProfileIn( __METHOD__ );
-               // If cache hit, don't write anything.
-               if ( $this->isRecall() ) {
-                       wfProfileOut( __METHOD__ );
-                       return;
-               }
-               $this->writeToDatabase();
+               $updated = parent::writeCache();
                // If we're replacing an older version of the image, make sure 
it's current.
-               if ( $wgUseSquid ) {
+               if ( $updated && $wgUseSquid ) {
                        $urls = array( $this->getMathImageUrl() );
                        $u = new SquidUpdate( $urls );
                        $u->doUpdate();
@@ -359,5 +405,75 @@
                wfProfileOut( __METHOD__ );
                return false;
        }
+       public function getPng() {
+               $backend = $this->getBackend();
+               return $backend->getFileContents( array( 'src' => 
$this->getHashPath() . "/" . $this->getHash() . '.png' ) );
+       }
+
+       public function readFromDatabase() {
+               $return = parent::readFromDatabase();
+               if ( $this->hash && $return ) {
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+       /**
+        * Get the hash calculated by texvc
+        *
+        * @return string hash
+        */
+       public function getHash() {
+               return $this->hash;
+       }
+
+       /**
+        * @param string $hash
+        */
+       public function setHash( $hash ) {
+               $this->changed = true;
+               $this->hash = $hash;
+       }
+
+       /**
+        * Returns the html-representation of the mathematical formula.
+        * @return string
+        */
+       public function getHtml() {
+               return $this->html;
+       }
+
+       /**
+        * @param string $html
+        */
+       public function setHtml( $html ) {
+               $this->changed = true;
+               $this->html = $html;
+       }
+
+       /**
+        * Gets the so called 'conservativeness' calculated by texvc
+        *
+        * @return int
+        */
+       public function getConservativeness() {
+               return $this->conservativeness;
+       }
+
+       /**
+        * @param int $conservativeness
+        */
+       public function setConservativeness( $conservativeness ) {
+               $this->changed = true;
+               $this->conservativeness = $conservativeness;
+       }
+
+       protected function getMathTableName() {
+               return 'math';
+       }
+
+       public function setOutputHash( $hash ) {
+               $this->hash = $hash;
+       }
 
 }
diff --git a/db/mathlatexml.pg.sql b/db/mathlatexml.pg.sql
new file mode 100644
index 0000000..6d2971b
--- /dev/null
+++ b/db/mathlatexml.pg.sql
@@ -0,0 +1,18 @@
+--
+-- Used by the math module to keep track
+-- of previously-rendered items.
+--
+CREATE TABLE /*_*/mathlatexml (
+  -- Binary MD5 hash of math_inputtex, used as an identifier key.
+  math_inputhash BYTEA PRIMARY KEY,
+  -- the user input
+  math_inputtex TEXT NOT NULL,
+  -- the validated tex
+  math_tex TEXT,
+  -- MathML output LaTeXML
+  math_mathml TEXT,
+  -- SVG output mathoid
+  math_svg TEXT,
+  -- MW_MATHSTYLE_(INLINE_DISPLAYSTYLE|DISPLAY|INLINE)
+  math_style SMALLINT
+) /*$wgDBTableOptions*/;
diff --git a/db/mathlatexml.sqllite.sql b/db/mathlatexml.sqllite.sql
new file mode 100644
index 0000000..89d8a6c
--- /dev/null
+++ b/db/mathlatexml.sqllite.sql
@@ -0,0 +1,18 @@
+--
+-- Used by the math module to keep track
+-- of previously-rendered items.
+--
+CREATE TABLE /*_*/mathlatexml (
+  -- Binary MD5 hash of math_inputtex, used as an identifier key.
+  math_inputhash varbinary(16) NOT NULL PRIMARY KEY,
+  -- the user input
+  math_inputtex text NOT NULL,
+  -- the validated tex
+  math_tex text,
+  -- MathML output LaTeXML
+  math_mathml text,
+  -- SVG output mathoid
+  math_svg text,
+  -- MW_MATHSTYLE_(INLINE_DISPLAYSTYLE|DISPLAY|INLINE)
+  math_style tinyint
+) /*$wgDBTableOptions*/;
diff --git a/tests/MathDatabaseTest.php b/tests/MathDatabaseTest.php
index b3d5dbb..53adcf6 100644
--- a/tests/MathDatabaseTest.php
+++ b/tests/MathDatabaseTest.php
@@ -11,8 +11,6 @@
        const SOME_HTML = "a<sub>b</sub> and so on";
        const SOME_MATHML = "iℏ∂_tΨ=H^Ψ<mrow><\ci>";
        const SOME_CONSERVATIVENESS = 2;
-       const SOME_OUTPUTHASH = 'C65c884f742c8591808a121a828bc09f8<';
-       const NUM_BASIC_FIELDS = 5;
 
 
 
@@ -51,6 +49,7 @@
                $this->renderer->setTex( self::SOME_TEX );
                $this->renderer->setMathml( self::SOME_MATHML );
                $this->renderer->setHtml( self::SOME_HTML );
+               $this->renderer->setOutputHash( self::SOME_OUTPUTHASH);
        }
        /**
         * Checks database access. Writes an entry and reads it back.
@@ -84,6 +83,6 @@
                $this->renderer->writeToDatabase();
                $res = $this->db->select( "math", "*" );
                $row = $res->fetchRow();
-               $this->assertEquals( count( $row ), 2 * self::NUM_BASIC_FIELDS 
);
+               $this->assertEquals( 10,  sizeof( $row ) );
        }
 }
diff --git a/tests/MathLaTeXMLDatabaseTest.php 
b/tests/MathLaTeXMLDatabaseTest.php
index 47b53eb..f5ac662 100644
--- a/tests/MathLaTeXMLDatabaseTest.php
+++ b/tests/MathLaTeXMLDatabaseTest.php
@@ -28,6 +28,11 @@
                parent::setUp();
                // TODO: figure out why this is necessary
                $this->db = wfGetDB( DB_MASTER );
+               if ( $this->db->getType() === 'sqlite' ){
+                       $this->markTestSkipped( "SQLite is currently not 
supported as a database " .
+                               "backend for the LaTeXML rendering mode."
+                       );
+               }
                // Create a new instance of MathSource
                $this->renderer = new MathLaTeXML( self::SOME_TEX );
                self::setupTestDB( $this->db, "mathtest" );
@@ -63,7 +68,6 @@
                // comparing the class object does now work due to null values 
etc.
                $this->assertEquals( $this->renderer->getTex(), 
$renderer2->getTex(), "test if tex is the same" );
                $this->assertEquals( $this->renderer->getMathml(), 
$renderer2->getMathml(), "Check MathML encoding" );
-
        }
 
 
@@ -78,7 +82,11 @@
                $dbu = DatabaseUpdater::newForDB( $this->db );
                $dbu->doUpdates( array( "extensions" ) );
                $this->expectOutputRegex( '/(.*)Creating mathlatexml 
table(.*)/' );
+               $this->setValues();
+               $this->renderer->writeToDatabase();
                $res = $this->db->select( "mathlatexml", "*" );
+               $row = $res->fetchRow();
+               $this->assertEquals( 20,  sizeof( $row ) );
        }
 
 }
diff --git a/tests/MathRendererTest.php b/tests/MathRendererTest.php
index 9ee43f1..0a23f1a 100644
--- a/tests/MathRendererTest.php
+++ b/tests/MathRendererTest.php
@@ -1,10 +1,11 @@
 <?php
 /**
- * Test the database access and core functionallity of MathRenderer.
+ * Test the database access and core functionality of MathRenderer.
  *
  * @group Math
  */
 class MathRendererTest extends MediaWikiTestCase {
+       const SOME_TEX = "a+b";
        /**
         * Checks the tex and hash functions
         * @covers MathRenderer::getTex()
@@ -12,9 +13,9 @@
         */
        public function testBasics() {
                $renderer = $this->getMockForAbstractClass( 'MathRenderer'
-                       , array ( MathDatabaseTest::SOME_TEX ) );
+                       , array ( self::SOME_TEX ) );
                // check if the TeX input was corretly passed to the class
-               $this->assertEquals( MathDatabaseTest::SOME_TEX, 
$renderer->getTex()
+               $this->assertEquals( self::SOME_TEX, $renderer->getTex()
                        , "test getTex" );
                $this->assertEquals( $renderer->isChanged(), false
                        , "test if changed is initially false" );
@@ -26,7 +27,7 @@
         */
        public function testWriteCacheSkip() {
                $renderer = $this->getMockBuilder( 'MathRenderer' )
-                       ->setMethods( array( 'writeToDatabase' , 'render' ) )
+                       ->setMethods( array( 'writeToDatabase' , 'render', 
'getMathTableName' ) )
                        ->disableOriginalConstructor()
                        ->getMock();
                $renderer->expects( $this->never() )
@@ -40,7 +41,7 @@
         */
        public function testWriteCache() {
                $renderer = $this->getMockBuilder( 'MathRenderer' )
-                       ->setMethods( array( 'writeToDatabase' , 'render' ) )
+                       ->setMethods( array( 'writeToDatabase' , 'render' , 
'getMathTableName' ) )
                        ->disableOriginalConstructor()
                        ->getMock();
                $renderer->expects( $this->never() )
@@ -48,30 +49,10 @@
                $renderer->writeCache();
        }
 
-       /**
-        * Test behavior $change when the rendered hash was changed
-        * @covers MathRenderer::setHash()
-        */
-       public function testChangeHash() {
-               $renderer = $this->getMockBuilder( 'MathRenderer' )
-               ->setMethods( array( 'render' ) )
-               ->disableOriginalConstructor()
-               ->getMock();
-               $this->assertEquals(
-                       $renderer->isChanged(),
-                       false,
-                       "test if changed is initially false"
-               );
-               $renderer->setHash( '0000' );
-               $this->assertEquals(
-                       $renderer->isChanged(),
-                       true,
-                       "assumes that changing a hash sets changed to true" );
-       }
 
        public function testSetPurge() {
                $renderer = $this->getMockBuilder( 'MathRenderer' )
-               ->setMethods( array( 'render' ) )
+               ->setMethods( array( 'render', 'getMathTableName' ) )
                ->disableOriginalConstructor()
                ->getMock();
                $renderer->setPurge();

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I8b11ffd0a39fadd7d3c8de1e94e74ff5f490430d
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Math
Gerrit-Branch: master
Gerrit-Owner: Physikerwelt <w...@physikerwelt.de>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to