2011-04-09 00:39:40 +00:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* MediaWiki math extension
|
|
|
|
*
|
2012-10-27 14:30:50 +00:00
|
|
|
* (c) 2002-2012 Tomasz Wegrzanowski, Brion Vibber, Moritz Schubotz, and other MediaWiki contributors
|
2011-04-09 00:39:40 +00:00
|
|
|
* GPLv2 license; info in main package.
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2013-04-24 08:21:35 +00:00
|
|
|
* 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,
|
|
|
|
* if run in mathdebug mode.
|
2011-04-09 00:39:40 +00:00
|
|
|
*
|
2012-10-27 14:30:50 +00:00
|
|
|
* @author Tomasz Wegrzanowski
|
|
|
|
* @author Brion Vibber
|
|
|
|
* @author Moritz Schubotz
|
2011-04-09 00:39:40 +00:00
|
|
|
*/
|
2012-10-27 14:30:50 +00:00
|
|
|
abstract class MathRenderer {
|
|
|
|
/**
|
2013-04-24 08:21:35 +00:00
|
|
|
* The following variables should made private, as soon it can be verified
|
|
|
|
* that they are not being directly accessed by other extensions.
|
2012-10-27 14:30:50 +00:00
|
|
|
*/
|
2011-11-28 22:30:33 +00:00
|
|
|
var $mode = MW_MATH_PNG;
|
2011-04-09 00:39:40 +00:00
|
|
|
var $tex = '';
|
2013-04-24 08:21:35 +00:00
|
|
|
/**
|
|
|
|
* is calculated by texvc.
|
|
|
|
* @var string
|
|
|
|
*/
|
2011-04-09 00:39:40 +00:00
|
|
|
var $hash = '';
|
|
|
|
var $html = '';
|
|
|
|
var $mathml = '';
|
|
|
|
var $conservativeness = 0;
|
2012-10-27 14:30:50 +00:00
|
|
|
var $params = '';
|
|
|
|
protected $recall;
|
2011-04-09 00:39:40 +00:00
|
|
|
|
2012-10-27 14:30:50 +00:00
|
|
|
/**
|
|
|
|
* Constructs a base MathRenderer
|
|
|
|
*
|
2013-04-24 08:21:35 +00:00
|
|
|
* @param string $tex (optional) LaTeX markup
|
|
|
|
* @param array $params (optional) HTML attributes
|
2012-10-27 14:30:50 +00:00
|
|
|
*/
|
2013-04-24 08:21:35 +00:00
|
|
|
public function __construct( $tex='', $params = array() ) {
|
2011-04-09 00:39:40 +00:00
|
|
|
$this->tex = $tex;
|
|
|
|
$this->params = $params;
|
2012-04-06 15:19:12 +00:00
|
|
|
}
|
2011-04-09 00:39:40 +00:00
|
|
|
|
2012-08-20 22:11:16 +00:00
|
|
|
/**
|
2012-10-27 14:30:50 +00:00
|
|
|
* Static method for rendering math tag
|
|
|
|
*
|
|
|
|
* @param string $tex LaTeX markup
|
|
|
|
* @param array $params HTML attributes
|
|
|
|
* @param int $mode constant indicating rendering mode
|
|
|
|
* @return string HTML for math tag
|
2012-08-20 22:11:16 +00:00
|
|
|
*/
|
2012-10-27 14:30:50 +00:00
|
|
|
public static function renderMath( $tex, $params = array(), $mode = MW_MATH_PNG ) {
|
2013-02-16 12:38:02 +00:00
|
|
|
$renderer = self::getRenderer( $tex, $params, $mode );
|
2012-10-27 14:30:50 +00:00
|
|
|
return $renderer->render();
|
2012-08-20 22:11:16 +00:00
|
|
|
}
|
|
|
|
|
2012-10-27 14:30:50 +00:00
|
|
|
/**
|
|
|
|
* Static factory method for getting a renderer based on mode
|
|
|
|
*
|
|
|
|
* @param string $tex LaTeX markup
|
|
|
|
* @param array $params HTML attributes
|
|
|
|
* @param int $mode constant indicating rendering mode
|
|
|
|
* @return MathRenderer appropriate renderer for mode
|
|
|
|
*/
|
|
|
|
public static function getRenderer( $tex, $params = array(), $mode = MW_MATH_PNG ) {
|
|
|
|
global $wgDefaultUserOptions;
|
2012-03-05 20:34:29 +00:00
|
|
|
$validModes = array( MW_MATH_PNG, MW_MATH_SOURCE, MW_MATH_MATHJAX );
|
2012-10-27 14:30:50 +00:00
|
|
|
if ( !in_array( $mode, $validModes ) )
|
|
|
|
$mode = $wgDefaultUserOptions['math'];
|
|
|
|
switch ( $mode ) {
|
|
|
|
case MW_MATH_SOURCE:
|
|
|
|
$renderer = new MathSource( $tex, $params );
|
|
|
|
break;
|
|
|
|
case MW_MATH_MATHJAX:
|
|
|
|
$renderer = new MathMathJax( $tex, $params );
|
|
|
|
break;
|
|
|
|
case MW_MATH_PNG:
|
|
|
|
default:
|
|
|
|
$renderer = new MathTexvc( $tex, $params );
|
2011-11-28 22:30:33 +00:00
|
|
|
}
|
2013-04-24 08:21:35 +00:00
|
|
|
wfDebugLog ( "Math", 'start rendering $' . $renderer->tex . '$' );
|
2012-10-27 14:30:50 +00:00
|
|
|
return $renderer;
|
2011-04-09 00:39:40 +00:00
|
|
|
}
|
|
|
|
|
2012-10-27 14:30:50 +00:00
|
|
|
/**
|
2013-04-24 08:21:35 +00:00
|
|
|
* Performs the rendering and returns the rendered element that needs to be embedded.
|
2012-10-27 14:30:50 +00:00
|
|
|
*
|
|
|
|
* @return string of rendered HTML
|
|
|
|
*/
|
|
|
|
abstract public function render();
|
2011-04-09 00:39:40 +00:00
|
|
|
|
2013-04-24 08:21:35 +00:00
|
|
|
|
2012-10-27 14:30:50 +00:00
|
|
|
/**
|
2013-04-24 08:21:35 +00:00
|
|
|
* texvc error messages
|
|
|
|
* TODO: update to MathML
|
2012-10-27 14:30:50 +00:00
|
|
|
* Returns an internationalized HTML error string
|
|
|
|
*
|
|
|
|
* @param string $msg message key for specific error
|
|
|
|
* @param string $append string to append after error
|
|
|
|
* @return string HTML error string
|
|
|
|
*/
|
|
|
|
protected function getError( $msg, $append = '' ) {
|
2012-09-07 17:43:09 +00:00
|
|
|
$mf = wfMessage( 'math_failure' )->inContentLanguage()->escaped();
|
|
|
|
$errmsg = wfMessage( $msg )->inContentLanguage()->escaped();
|
2011-04-09 00:39:40 +00:00
|
|
|
$source = htmlspecialchars( str_replace( "\n", ' ', $this->tex ) );
|
|
|
|
return "<strong class='error'>$mf ($errmsg$append): $source</strong>\n";
|
|
|
|
}
|
|
|
|
|
2012-10-27 14:30:50 +00:00
|
|
|
/**
|
|
|
|
* Return hash of input
|
|
|
|
*
|
|
|
|
* @return string hash
|
|
|
|
*/
|
|
|
|
public function getInputHash() {
|
|
|
|
// TODO: What happens if $tex is empty?
|
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
|
|
|
return $dbr->encodeBlob( pack( "H32", md5( $this->tex ) ) ); # Binary packed, not hex
|
|
|
|
}
|
2011-04-09 00:39:40 +00:00
|
|
|
|
2012-10-27 14:30:50 +00:00
|
|
|
/**
|
|
|
|
* Reads rendering data from database
|
|
|
|
*
|
|
|
|
* @return boolean true if read successfully, false otherwise
|
|
|
|
*/
|
2013-04-24 06:01:53 +00:00
|
|
|
public function readFromDatabase() {
|
2011-04-09 00:39:40 +00:00
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
2011-04-09 15:13:22 +00:00
|
|
|
$rpage = $dbr->selectRow(
|
|
|
|
'math',
|
|
|
|
array(
|
|
|
|
'math_outputhash', 'math_html_conservativeness', 'math_html',
|
|
|
|
'math_mathml'
|
|
|
|
),
|
|
|
|
array(
|
2012-10-27 14:30:50 +00:00
|
|
|
'math_inputhash' => $this->getInputHash()
|
2011-04-09 15:13:22 +00:00
|
|
|
),
|
2011-04-09 00:39:40 +00:00
|
|
|
__METHOD__
|
|
|
|
);
|
2012-10-27 14:30:50 +00:00
|
|
|
if ( $rpage !== false ) {
|
2012-08-20 22:11:16 +00:00
|
|
|
# Trailing 0x20s can get dropped by the database, add it back on if necessary:
|
2011-04-09 15:13:22 +00:00
|
|
|
$xhash = unpack( 'H32md5', $dbr->decodeBlob( $rpage->math_outputhash ) . " " );
|
|
|
|
$this->hash = $xhash['md5'];
|
2011-04-09 00:39:40 +00:00
|
|
|
$this->conservativeness = $rpage->math_html_conservativeness;
|
|
|
|
$this->html = $rpage->math_html;
|
|
|
|
$this->mathml = $rpage->math_mathml;
|
2012-10-27 14:30:50 +00:00
|
|
|
$this->recall = true;
|
|
|
|
return true;
|
2011-04-09 00:39:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Missing from the database and/or the render cache
|
2012-10-27 14:30:50 +00:00
|
|
|
$this->recall = false;
|
2011-04-09 00:39:40 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-04-24 08:21:35 +00:00
|
|
|
* Writes rendering entry to database.
|
|
|
|
*
|
|
|
|
* WARNING: Use writeCache() instead of this method to be sure that all
|
|
|
|
* renderer specific (such as squid caching) are taken into account.
|
|
|
|
* This function stores the values that are currently present in the class to the database even if they are empty.
|
|
|
|
*
|
|
|
|
* This function can be seen as protected function.
|
2011-04-09 00:39:40 +00:00
|
|
|
*/
|
2013-04-24 06:01:53 +00:00
|
|
|
public function writeToDatabase() {
|
2012-10-27 14:30:50 +00:00
|
|
|
# Now save it back to the DB:
|
|
|
|
if ( !wfReadOnly() ) {
|
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2013-03-13 10:57:41 +00:00
|
|
|
if ( $this->hash !== '' ) {
|
2012-10-27 14:30:50 +00:00
|
|
|
$outmd5_sql = $dbw->encodeBlob( pack( 'H32', $this->hash ) );
|
|
|
|
} else {
|
2013-03-13 10:57:41 +00:00
|
|
|
$outmd5_sql = '';
|
2012-10-27 14:30:50 +00:00
|
|
|
}
|
2013-04-26 12:14:07 +00:00
|
|
|
wfDebugLog( "Math", 'store entry for $' . $this->tex . '$ in database (hash:' . $this->hash . ')\n' );
|
2012-10-27 14:30:50 +00:00
|
|
|
$dbw->replace(
|
|
|
|
'math',
|
|
|
|
array( 'math_inputhash' ),
|
|
|
|
array(
|
|
|
|
'math_inputhash' => $this->getInputHash(),
|
|
|
|
'math_outputhash' => $outmd5_sql ,
|
|
|
|
'math_html_conservativeness' => $this->conservativeness,
|
|
|
|
'math_html' => $this->html,
|
|
|
|
'math_mathml' => $this->mathml,
|
|
|
|
),
|
|
|
|
__METHOD__
|
2011-04-09 15:13:22 +00:00
|
|
|
);
|
2011-04-09 00:39:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-27 14:30:50 +00:00
|
|
|
/**
|
|
|
|
* Returns sanitized attributes
|
|
|
|
*
|
|
|
|
* @param string $tag element name
|
|
|
|
* @param array $defaults default attributes
|
|
|
|
* @param array $overrides attributes to override defaults
|
|
|
|
* @return array HTML attributes
|
|
|
|
*/
|
|
|
|
protected function getAttributes( $tag, $defaults = array(), $overrides = array() ) {
|
2011-04-09 00:39:40 +00:00
|
|
|
$attribs = Sanitizer::validateTagAttributes( $this->params, $tag );
|
|
|
|
$attribs = Sanitizer::mergeAttributes( $defaults, $attribs );
|
|
|
|
$attribs = Sanitizer::mergeAttributes( $attribs, $overrides );
|
|
|
|
return $attribs;
|
|
|
|
}
|
2012-10-27 14:30:50 +00:00
|
|
|
/**
|
|
|
|
* Writes cache. Does nothing by default
|
|
|
|
*/
|
|
|
|
public function writeCache() {
|
2011-04-09 00:39:40 +00:00
|
|
|
}
|
|
|
|
|
2012-10-27 14:30:50 +00:00
|
|
|
/**
|
|
|
|
* Determines if this is a cached/recalled render
|
|
|
|
*
|
|
|
|
* @return boolean true if recalled, false otherwise
|
|
|
|
*/
|
|
|
|
public function isRecall() {
|
|
|
|
return $this->recall;
|
2011-04-09 00:39:40 +00:00
|
|
|
}
|
2011-07-25 22:09:05 +00:00
|
|
|
|
2012-10-27 14:30:50 +00:00
|
|
|
/**
|
|
|
|
* Gets TeX markup
|
|
|
|
*
|
|
|
|
* @return string TeX markup
|
|
|
|
*/
|
|
|
|
public function getTex() {
|
|
|
|
return $this->tex;
|
2011-04-09 00:39:40 +00:00
|
|
|
}
|
|
|
|
}
|