Physikerwelt has uploaded a new change for review.
https://gerrit.wikimedia.org/r/267878
Change subject: Render all math tags in parallel
......................................................................
Render all math tags in parallel
Change-Id: Ia2febf2c0309e5de514445ad2aad58b7e5ce6837
---
M Math.hooks.php
M MathInputCheckRestbase.php
M MathMathML.php
M MathRenderer.php
M MathRestbaseInterface.php
M extension.json
M tests/MathRestBaseInterfaceTest.php
7 files changed, 160 insertions(+), 58 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Math
refs/changes/78/267878/1
diff --git a/Math.hooks.php b/Math.hooks.php
index 895e785..e8c4c47 100644
--- a/Math.hooks.php
+++ b/Math.hooks.php
@@ -9,6 +9,7 @@
use MediaWiki\Logger\LoggerFactory;
class MathHooks {
+ private static $tags = array();
const MATHCACHEKEY = 'math=';
public static function mathConstantToString( $value, array $defs,
$prefix, $default ) {
@@ -178,10 +179,13 @@
* @return array
*/
static function mathTagHook( $content, $attributes, $parser ) {
-
+ static $n = 1;
if ( trim( $content ) === '' ) { // bug 8372
return '';
}
+ $marker = Parser::MARKER_PREFIX .
+ '-postMath-' . sprintf( '%08X', $n ++ ) .
+ Parser::MARKER_SUFFIX;
$mode = self::mathModeToString( $parser->getUser()->getOption(
'math' ) );
// Indicate that this page uses math.
@@ -191,9 +195,28 @@
} else {
$parser->getOptions()->optionUsed( 'math' );
}
-
$renderer = MathRenderer::getRenderer( $content, $attributes,
$mode );
+ self::$tags[$marker] = array( $renderer, $parser );
+ $parser->getOutput()->addModuleStyles( array( 'ext.math.styles'
) );
+ // if ( $mode == 'mathml' ) {
+ $parser->getOutput()->addModuleStyles( array(
'ext.math.desktop.styles' ) );
+ $parser->getOutput()->addModules( array(
'ext.math.scripts' ) );
+ // }
+ return $marker;
+
+ }
+
+ /**
+ * Callback function for the <math> parser hook.
+ *
+ * @param Parser $parser
+ * @param MathRenderer $renderer
+ * @return array
+ * @throws FatalError
+ * @throws MWException
+ */
+ private static function mathPostTagHook( $renderer, $parser ) {
$checkResult = $renderer->checkTeX();
if ( $checkResult !== true ) {
@@ -211,15 +234,11 @@
}
Hooks::run( 'MathFormulaPostRender',
array( $parser, &$renderer, &$renderedMath ) );//
Enables indexing of math formula
- $parser->getOutput()->addModuleStyles( array( 'ext.math.styles'
) );
- if ( $mode == 'mathml' ) {
- $parser->getOutput()->addModuleStyles( array(
'ext.math.desktop.styles' ) );
- $parser->getOutput()->addModules( array(
'ext.math.scripts' ) );
- }
+
// Writes cache if rendering was successful
$renderer->writeCache();
- return array( $renderedMath, "markerType" => 'nowiki' );
+ return $renderedMath;
}
/**
@@ -353,6 +372,30 @@
}
/**
+ * @param Parser $parser
+ * @param $text
+ * @return bool
+ */
+ public static function onParserBeforeTidy( &$parser, &$text ) {
+ $rbis = array();
+ $t0= microtime( true );
+ foreach ( self::$tags as $key => $tag ){
+ /** @var MathRenderer $renderer */
+ $renderer = $tag[0];
+ $rbi = new MathRestbaseInterface( $renderer->getTex(),
$renderer->getInputType() );
+ $renderer->setRestbaseInterface( $rbi );
+ $rbis[] = $rbi;
+ }
+ MathRestbaseInterface::batchEvaluate( $rbis );
+ foreach ( self::$tags as $key => $tag ){
+ $value = call_user_func_array( array(
"MathHooks","mathPostTagHook" ), $tag );
+ $text = str_replace( $key, $value, $text );
+ }
+ $time = ( microtime( true ) -$t0 );
+ $text= "$time s RBI THE SIZE IS ". count( $rbis ). $text;
+ return true;
+ }
+ /**
*
* @global type $wgOut
* @param type $toolbar
diff --git a/MathInputCheckRestbase.php b/MathInputCheckRestbase.php
index 8d21b63..d73d8d5 100644
--- a/MathInputCheckRestbase.php
+++ b/MathInputCheckRestbase.php
@@ -17,10 +17,16 @@
* (performs no checking)
* @param string $tex the TeX input string to be checked
* @param string $type
+ * @param MathRestbaseInterface $ref
*/
- public function __construct( $tex = '', $type = 'tex' ) {
+ public function __construct( $tex = '', $type = 'tex', &$ref = null ) {
parent::__construct( $tex );
- $this->restbaseInterface = new MathRestbaseInterface( $tex,
$type );
+ if ( $ref ) {
+ $this->restbaseInterface = $ref;
+ } else {
+ $this->restbaseInterface = new MathRestbaseInterface(
$tex, $type );
+ $ref = $this->restbaseInterface;
+ }
}
/**
@@ -56,7 +62,7 @@
* @return boolean
*/
public function isValid() {
- return $this->restbaseInterface->checkTeX();
+ return $this->restbaseInterface->getSuccess();
}
/**
diff --git a/MathMathML.php b/MathMathML.php
index 515925e..0083c0d 100644
--- a/MathMathML.php
+++ b/MathMathML.php
@@ -80,7 +80,6 @@
$rbi = $this->rbi;
if ( !$rbi ){
$rbi = new MathRestbaseInterface(
$this->getTex(), $this->getInputType() );
- $rbi->checkTeX();
}
if ( $rbi->getSuccess() ) {
$this->mathml = $rbi->getMathML();
diff --git a/MathRenderer.php b/MathRenderer.php
index e61a5b3..76a9221 100644
--- a/MathRenderer.php
+++ b/MathRenderer.php
@@ -377,6 +377,13 @@
}
/**
+ * @param MathRestbaseInterface $param
+ */
+ public function setRestbaseInterface( $param ) {
+ $this->rbi = $param;
+ }
+
+ /**
* Returns sanitized attributes
*
* @param string $tag element name
@@ -583,12 +590,11 @@
return true;
}
}
- $checker = new MathInputCheckRestbase( $this->tex,
$this->getInputType() );
+ $checker = new MathInputCheckRestbase( $this->tex,
$this->getInputType(), $this->rbi );
try {
if ( $checker->isValid() ) {
$this->setTex( $checker->getValidTex()
);
$this->texSecure = true;
- $this->rbi = $checker->getRbi();
return true;
}
} catch ( MWException $e ) {
diff --git a/MathRestbaseInterface.php b/MathRestbaseInterface.php
index 2e24e22..b1e845b 100644
--- a/MathRestbaseInterface.php
+++ b/MathRestbaseInterface.php
@@ -16,6 +16,7 @@
private $success;
private $identifiers;
private $error;
+ private $mml;
/**
* MathRestbaseInterface constructor.
@@ -32,7 +33,10 @@
* @throws MWException
*/
public function getMathML() {
- return $this->getContent( 'mml' );
+ if ( $this->mml === null ){
+ return $this->getContent( 'mml' );
+ }
+ return $this->mml;
}
private function getContent( $type ) {
@@ -64,27 +68,9 @@
}
public function checkTeX() {
- $postData = array(
- 'type' => $this->type,
- 'q' => $this->tex
- );
- $requestResult = $this->makeRestbaseCheckRequest( $postData,
$res );
- $json = json_decode( $res );
- if ( $requestResult ) {
- $this->success = $json->success;
- $this->checkedTex = $json->checked;
- $this->identifiers = $json->identifiers;
- return true;
- } else {
- if ( isset( $json->detail ) && isset(
$json->detail->success ) ) {
- $this->success = $json->detail->success;
- $this->error = $json->detail;
- } else {
- $this->success = false;
- $this->setErrorMessage( 'Math extension cannot
connect to Restbase.' );
- }
- return false;
- }
+ $request = $this->getCheckRequest();
+ $requestResult = $this->executeRestbaseCheckRequest( $request );
+ return $this->evaluateRestbaseCheckResponse( $requestResult );
}
/**
@@ -92,33 +78,47 @@
* Generates error messages on failure
* @see Http::post()
*
- * @param string $post the encoded post request
- * @param mixed $res the result
+ * @param array $request the request object
* @return bool success
*/
- private function makeRestbaseCheckRequest( $post, &$res ) {
+ private function executeRestbaseCheckRequest( $request ) {
$res = null;
- $request = array(
- 'method' => 'POST',
- 'body' => $post
- );
$serviceClient = $this->getServiceClient();
- $request['url'] = $this->getUrl(
"media/math/check/{$this->type}" );
- $response = $serviceClient->run( $request );
- if ( $response['code'] === 200 ) {
- $res = $response['body'];
- $headers = $response['headers'];
- $this->hash = $headers['x-resource-location'];
- return true;
- } else {
- $res = $response['body'];
+ $response = $serviceClient->run( $request );
+ if ( $response['code'] !== 200 ) {
$this->log()->info( 'Tex check failed:', array(
- 'post' => $post,
- 'error' => $response['error'],
- 'url' => $request['url']
+ 'post' => $request['body'],
+ 'error' => $response['error'],
+ 'url' => $request['url']
) );
- return false;
}
+ return $response;
+
+ }
+
+ /**
+ * @param array $rbis array of MathRestbaseInterface instances
+ */
+ public static function batchEvaluate( $rbis ) {
+ if ( count( $rbis ) == 0 ){
+ return;
+ }
+ $requests = array();
+ /** @var MathRestbaseInterface $first */
+ $first = $rbis[0];
+ $serviceClient = $first->getServiceClient();
+ foreach ( $rbis as $rbi ) {
+ /** @var MathRestbaseInterface $rbi */
+ $requests[] = $rbi->getCheckRequest();
+ }
+ $results = $serviceClient->runMulti( $requests );
+ $i = 0;
+ foreach ( $results as $response ) {
+ /** @var MathRestbaseInterface $rbi */
+ $rbi = $rbis[$i ++];
+ $rbi->evaluateRestbaseCheckResponse( $response );
+ }
+
}
private function getServiceClient() {
@@ -258,6 +258,9 @@
* @return boolean
*/
public function getSuccess() {
+ if ( $this->success === null ) {
+ $this->checkTeX();
+ }
return $this->success;
}
@@ -293,4 +296,48 @@
$this->error = (object)array( 'error' => (object)array(
'message' => $msg ) );
}
+ /**
+ * @return array
+ * @throws MWException
+ */
+ public function getCheckRequest() {
+ $request = array(
+ 'method' => 'POST',
+ 'body' => array(
+ 'type' => $this->type,
+ 'q' => $this->tex
+ ),
+ 'url' => $this->getUrl(
"media/math/check/{$this->type}" )
+ );
+ return $request;
+ }
+
+ /**
+ * @param $response
+ * @return bool
+ */
+ public function evaluateRestbaseCheckResponse( $response ) {
+ $json = json_decode( $response['body'] );
+ if ( $response['code'] === 200 ) {
+ $headers = $response['headers'];
+ $this->hash = $headers['x-resource-location'];
+ $this->success = $json->success;
+ $this->checkedTex = $json->checked;
+ $this->identifiers = $json->identifiers;
+ if ( isset( $json->mml ) ){
+ $this->mml = $json->mml;
+ }
+ return true;
+ } else {
+ if ( isset( $json->detail ) && isset(
$json->detail->success ) ) {
+ $this->success = $json->detail->success;
+ $this->error = $json->detail;
+ } else {
+ $this->success = false;
+ $this->setErrorMessage( 'Math extension cannot
connect to Restbase.' );
+ }
+ return false;
+ }
+ }
+
}
diff --git a/extension.json b/extension.json
index 9a00606..90e1512 100644
--- a/extension.json
+++ b/extension.json
@@ -67,6 +67,9 @@
],
"WikibaseRepoDataTypes": [
"MathWikidataHook::onWikibaseRepoDataTypes"
+ ],
+ "ParserBeforeTidy":[
+ "MathHooks::onParserBeforeTidy"
]
},
"config": {
diff --git a/tests/MathRestBaseInterfaceTest.php
b/tests/MathRestBaseInterfaceTest.php
index 9bab719..e48ca4c 100644
--- a/tests/MathRestBaseInterfaceTest.php
+++ b/tests/MathRestBaseInterfaceTest.php
@@ -34,7 +34,6 @@
public function testSuccess() {
$input = '\\sin x^2';
$rbi = new MathRestbaseInterface( $input );
- $this->assertTrue( $rbi->checkTeX(), "Assuming that $input is
valid input." );
$this->assertTrue( $rbi->getSuccess(), "Assuming that $input is
valid input." );
$this->assertEquals( '\\sin x^{2}', $rbi->getCheckedTex() );
$this->assertContains( '<mi>sin</mi>', $rbi->getMathML() );
@@ -48,7 +47,6 @@
public function testFail() {
$input = '\\sin\\newcommand';
$rbi = new MathRestbaseInterface( $input );
- $this->assertFalse( $rbi->checkTeX(), "Assuming that $input is
invalid input." );
$this->assertFalse( $rbi->getSuccess(), "Assuming that $input
is invalid input." );
$this->assertEquals( '', $rbi->getCheckedTex() );
$this->assertEquals( 'Illegal TeX function',
$rbi->getError()->error->message );
--
To view, visit https://gerrit.wikimedia.org/r/267878
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia2febf2c0309e5de514445ad2aad58b7e5ce6837
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Math
Gerrit-Branch: master
Gerrit-Owner: Physikerwelt <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits