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 <w...@physikerwelt.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits