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