mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Math
synced 2024-11-23 23:25:02 +00:00
Add Integration for the TexVC-PHP check to Math
Bug: T312528 Change-Id: I0eda7d4213a5f703ab7ae7887aa364af9e576dbe
This commit is contained in:
parent
8333e2541a
commit
c27f7edef9
|
@ -6,7 +6,8 @@
|
||||||
"Brion Vibber",
|
"Brion Vibber",
|
||||||
"Moritz Schubotz",
|
"Moritz Schubotz",
|
||||||
"Derk-Jan Hartman",
|
"Derk-Jan Hartman",
|
||||||
"André Greiner-Petter"
|
"André Greiner-Petter",
|
||||||
|
"Johannes Stegmüller"
|
||||||
],
|
],
|
||||||
"url": "https://www.mediawiki.org/wiki/Extension:Math",
|
"url": "https://www.mediawiki.org/wiki/Extension:Math",
|
||||||
"descriptionmsg": "math-desc",
|
"descriptionmsg": "math-desc",
|
||||||
|
@ -102,6 +103,10 @@
|
||||||
"description": "Fallback value for wbEntitySelector if wbRepo is not configured. See https://www.mediawiki.org/wiki/Manual:CORS for cross wiki communication.",
|
"description": "Fallback value for wbEntitySelector if wbRepo is not configured. See https://www.mediawiki.org/wiki/Manual:CORS for cross wiki communication.",
|
||||||
"value": "https://www.wikidata.org/w/api.php"
|
"value": "https://www.wikidata.org/w/api.php"
|
||||||
},
|
},
|
||||||
|
"MathTexVCService": {
|
||||||
|
"description": "Determine which TexVC variant is used, currently available: 'mathoid', 'restbase' (default) and 'local'.",
|
||||||
|
"value": "restbase"
|
||||||
|
},
|
||||||
"MathLaTeXMLTimeout": {
|
"MathLaTeXMLTimeout": {
|
||||||
"value": 240
|
"value": 240
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
namespace MediaWiki\Extension\Math\InputCheck;
|
namespace MediaWiki\Extension\Math\InputCheck;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use InvalidArgumentException;
|
||||||
use MediaWiki\Config\ServiceOptions;
|
use MediaWiki\Config\ServiceOptions;
|
||||||
|
use MediaWiki\Extension\Math\MathRestbaseInterface;
|
||||||
use MediaWiki\Http\HttpRequestFactory;
|
use MediaWiki\Http\HttpRequestFactory;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use WANObjectCache;
|
use WANObjectCache;
|
||||||
|
@ -12,6 +15,7 @@ class InputCheckFactory {
|
||||||
public const CONSTRUCTOR_OPTIONS = [
|
public const CONSTRUCTOR_OPTIONS = [
|
||||||
'MathMathMLUrl',
|
'MathMathMLUrl',
|
||||||
'MathLaTeXMLTimeout',
|
'MathLaTeXMLTimeout',
|
||||||
|
'MathTexVCService'
|
||||||
];
|
];
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $url;
|
private $url;
|
||||||
|
@ -23,6 +27,8 @@ class InputCheckFactory {
|
||||||
private $httpFactory;
|
private $httpFactory;
|
||||||
/** @var LoggerInterface */
|
/** @var LoggerInterface */
|
||||||
private $logger;
|
private $logger;
|
||||||
|
/** @var string */
|
||||||
|
private $texVCmode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ServiceOptions $options
|
* @param ServiceOptions $options
|
||||||
|
@ -39,15 +45,16 @@ class InputCheckFactory {
|
||||||
$options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
|
$options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
|
||||||
$this->url = $options->get( 'MathMathMLUrl' );
|
$this->url = $options->get( 'MathMathMLUrl' );
|
||||||
$this->timeout = $options->get( 'MathLaTeXMLTimeout' );
|
$this->timeout = $options->get( 'MathLaTeXMLTimeout' );
|
||||||
|
$this->texVCmode = $options->get( 'MathTexVCService' );
|
||||||
$this->cache = $cache;
|
$this->cache = $cache;
|
||||||
$this->httpFactory = $httpFactory;
|
$this->httpFactory = $httpFactory;
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $input
|
* @param string $input input string to be checked
|
||||||
* @param string $type
|
* @param string $type type of input
|
||||||
* @return MathoidChecker
|
* @return MathoidChecker checker based on mathoid
|
||||||
*/
|
*/
|
||||||
public function newMathoidChecker( string $input, string $type ): MathoidChecker {
|
public function newMathoidChecker( string $input, string $type ): MathoidChecker {
|
||||||
return new MathoidChecker(
|
return new MathoidChecker(
|
||||||
|
@ -60,4 +67,55 @@ class InputCheckFactory {
|
||||||
$type
|
$type
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $input input string to be checked
|
||||||
|
* @param string $type type of input
|
||||||
|
* @param MathRestbaseInterface|null &$restbaseInterface restbase interface which is used for remote communication
|
||||||
|
* @return RestbaseChecker checker based on communication with restbase interface
|
||||||
|
*/
|
||||||
|
public function newRestbaseChecker( string $input, string $type,
|
||||||
|
MathRestbaseInterface &$restbaseInterface = null ): RestbaseChecker {
|
||||||
|
return new RestbaseChecker(
|
||||||
|
$input,
|
||||||
|
$type,
|
||||||
|
$restbaseInterface
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $input input string to be checked
|
||||||
|
* @param string $type type of input (only 'tex')
|
||||||
|
* @return LocalChecker checker based on php implementation of TexVC within Math-extension
|
||||||
|
* @throws InvalidArgumentException|Exception if the type is not correct.
|
||||||
|
*/
|
||||||
|
public function newLocalChecker( string $input, string $type ): LocalChecker {
|
||||||
|
return new LocalChecker(
|
||||||
|
$input,
|
||||||
|
$type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of BaseChecker based on the configuration parameter for the texVC Service.
|
||||||
|
* By default, this sets the checker to the local PHP variant of TexVC.
|
||||||
|
*
|
||||||
|
* @param string $input input string which is checked
|
||||||
|
* @param string $type input type, for some configurations this has to be 'tex'
|
||||||
|
* @param MathRestbaseInterface|null &$restbaseInterface restbase interface,
|
||||||
|
* only necessary when using 'restbase' configuration
|
||||||
|
* @return BaseChecker a checker object which has the results of the check.
|
||||||
|
*/
|
||||||
|
public function newDefaultChecker( string $input, string $type,
|
||||||
|
MathRestbaseInterface &$restbaseInterface = null ): BaseChecker {
|
||||||
|
switch ( $this->texVCmode ) {
|
||||||
|
case "mathoid":
|
||||||
|
return $this->newMathoidChecker( $input, $type );
|
||||||
|
case "local":
|
||||||
|
return $this->newLocalChecker( $input, $type );
|
||||||
|
case "restbase":
|
||||||
|
default:
|
||||||
|
return $this->newRestbaseChecker( $input, $type, $restbaseInterface );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
63
src/InputCheck/LocalChecker.php
Normal file
63
src/InputCheck/LocalChecker.php
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MediaWiki\Extension\Math\InputCheck;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use MediaWiki\Extension\Math\TexVC\TexVC;
|
||||||
|
use Message;
|
||||||
|
|
||||||
|
class LocalChecker extends BaseChecker {
|
||||||
|
|
||||||
|
/** @var TexVC */
|
||||||
|
private $texVC;
|
||||||
|
/** @var array */
|
||||||
|
private $result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $tex the TeX input string to be checked
|
||||||
|
* @param string $type the input type, only tex allowed
|
||||||
|
* @throws InvalidArgumentException|Exception if the type is not correct.
|
||||||
|
*/
|
||||||
|
public function __construct( $tex = '', $type = 'tex' ) {
|
||||||
|
parent::__construct( $tex );
|
||||||
|
if ( $type !== 'tex' ) {
|
||||||
|
// this type check will be refactored with the introduction of chem-types:
|
||||||
|
// see: https://phabricator.wikimedia.org/T321262
|
||||||
|
throw new InvalidArgumentException( "Non supported type passed to LocalChecker: " . $type );
|
||||||
|
}
|
||||||
|
$this->texVC = new TexVC();
|
||||||
|
$this->result = $this->texVC->check( $tex );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isValid() {
|
||||||
|
return $this->result["status"] === "+";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some TeX checking programs may return
|
||||||
|
* a modified tex string after having checked it.
|
||||||
|
* You can get the altered tex string with this method
|
||||||
|
* @return string|null A valid Tex string or null if no output
|
||||||
|
*/
|
||||||
|
public function getValidTex() {
|
||||||
|
return array_key_exists( "output", $this->result ) ? $this->result["output"] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string of the last error.
|
||||||
|
* @return ?Message
|
||||||
|
*/
|
||||||
|
public function getError(): ?Message {
|
||||||
|
if ( $this->result["success"] ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$errorOb = (object)[ "error" => null ];
|
||||||
|
$errorOb->error = (object)$this->result["error"];
|
||||||
|
return $this->errorObjectToMessage( $errorOb, "LocalCheck" );
|
||||||
|
}
|
||||||
|
}
|
95
tests/phpunit/InputCheck/InputCheckFactoryTest.php
Normal file
95
tests/phpunit/InputCheck/InputCheckFactoryTest.php
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace phpunit\InputCheck;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use MediaWiki\Config\ServiceOptions;
|
||||||
|
use MediaWiki\Extension\Math\InputCheck\InputCheckFactory;
|
||||||
|
use MediaWiki\Extension\Math\InputCheck\LocalChecker;
|
||||||
|
use MediaWiki\Extension\Math\InputCheck\MathoidChecker;
|
||||||
|
use MediaWiki\Extension\Math\InputCheck\RestbaseChecker;
|
||||||
|
use MediaWiki\Http\HttpRequestFactory;
|
||||||
|
use MediaWiki\Logger\LoggerFactory;
|
||||||
|
use MediaWiki\Tests\Unit\MockServiceDependenciesTrait;
|
||||||
|
use MediaWikiIntegrationTestCase;
|
||||||
|
use WANObjectCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method InputCheckFactory newServiceInstance(string $serviceClass, array $parameterOverrides)
|
||||||
|
* @covers \MediaWiki\Extension\Math\InputCheck\InputCheckFactory
|
||||||
|
*/
|
||||||
|
class InputCheckFactoryTest extends MediaWikiIntegrationTestCase {
|
||||||
|
|
||||||
|
use MockServiceDependenciesTrait;
|
||||||
|
|
||||||
|
private $fakeHTTP;
|
||||||
|
private $fakeWAN;
|
||||||
|
|
||||||
|
protected function setUp(): void {
|
||||||
|
parent::setUp();
|
||||||
|
$this->fakeHTTP = $this->createMock( HttpRequestFactory::class );
|
||||||
|
$this->fakeWAN = $this->createMock( WANObjectCache::class );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNewMathoidChecker() {
|
||||||
|
$checker = $this->newServiceInstance( InputCheckFactory::class, [] )
|
||||||
|
->newMathoidChecker( 'FORMULA', 'TYPE' );
|
||||||
|
$this->assertInstanceOf( MathoidChecker::class, $checker );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNewRestbaseChecker() {
|
||||||
|
$checker = $this->newServiceInstance( InputCheckFactory::class, [] )
|
||||||
|
->newRestbaseChecker( 'FORMULA', 'TYPE' );
|
||||||
|
$this->assertInstanceOf( RestbaseChecker::class, $checker );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNewLocalChecker() {
|
||||||
|
$checker = $this->newServiceInstance( InputCheckFactory::class, [] )
|
||||||
|
->newLocalChecker( 'FORMULA', 'tex' );
|
||||||
|
$this->assertInstanceOf( LocalChecker::class, $checker );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalidLocalChecker() {
|
||||||
|
$this->expectException( InvalidArgumentException::class );
|
||||||
|
$this->newServiceInstance( InputCheckFactory::class, [] )
|
||||||
|
->newLocalChecker( 'FORMULA', 'invalidtype' );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNewDefaultChecker() {
|
||||||
|
$checker = $this->newServiceInstance( InputCheckFactory::class, [] )
|
||||||
|
->newDefaultChecker( 'FORMULA', 'TYPE' );
|
||||||
|
$this->assertInstanceOf( RestbaseChecker::class, $checker );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNewMLocalCheckerDefault() {
|
||||||
|
$myFactory = new InputCheckFactory(
|
||||||
|
new ServiceOptions( InputCheckFactory::CONSTRUCTOR_OPTIONS, [
|
||||||
|
'MathMathMLUrl' => 'something',
|
||||||
|
'MathTexVCService' => 'local',
|
||||||
|
'MathLaTeXMLTimeout' => 240
|
||||||
|
] ),
|
||||||
|
$this->fakeWAN,
|
||||||
|
$this->fakeHTTP,
|
||||||
|
LoggerFactory::getInstance( 'Math' )
|
||||||
|
);
|
||||||
|
|
||||||
|
$checker = $myFactory->newDefaultChecker( 'FORMULA', 'tex' );
|
||||||
|
$this->assertInstanceOf( LocalChecker::class, $checker );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMathoidCheckerInDefault() {
|
||||||
|
$myFactory = new InputCheckFactory(
|
||||||
|
new ServiceOptions( InputCheckFactory::CONSTRUCTOR_OPTIONS, [
|
||||||
|
'MathMathMLUrl' => 'something',
|
||||||
|
'MathTexVCService' => 'mathoid',
|
||||||
|
'MathLaTeXMLTimeout' => 240
|
||||||
|
] ),
|
||||||
|
$this->fakeWAN,
|
||||||
|
$this->fakeHTTP,
|
||||||
|
LoggerFactory::getInstance( 'Math' )
|
||||||
|
);
|
||||||
|
|
||||||
|
$checker = $myFactory->newDefaultChecker( 'FORMULA', 'TYPE' );
|
||||||
|
$this->assertInstanceOf( MathoidChecker::class, $checker );
|
||||||
|
}
|
||||||
|
}
|
65
tests/phpunit/InputCheck/LocalCheckerTest.php
Normal file
65
tests/phpunit/InputCheck/LocalCheckerTest.php
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MediaWiki\Extension\Math\InputCheck;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use MediaWikiIntegrationTestCase;
|
||||||
|
use Message;
|
||||||
|
use MockHttpTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group Math
|
||||||
|
* @license GPL-2.0-or-later
|
||||||
|
* tbd move this to unittests
|
||||||
|
* @covers \MediaWiki\Extension\Math\InputCheck\LocalChecker
|
||||||
|
*/
|
||||||
|
class LocalCheckerTest extends MediaWikiIntegrationTestCase {
|
||||||
|
use MockHttpTrait;
|
||||||
|
|
||||||
|
public function testValid() {
|
||||||
|
$checker = new LocalChecker( '\sin x^2' );
|
||||||
|
$this->assertNull( $checker->getError() );
|
||||||
|
$this->assertTrue( $checker->isValid() );
|
||||||
|
$this->assertNull( $checker->getError() );
|
||||||
|
$this->assertSame( '\\sin x^{2}', $checker->getValidTex() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidType() {
|
||||||
|
$checker = new LocalChecker( '\sin x^2', 'tex' );
|
||||||
|
$this->assertTrue( $checker->isValid() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalidType() {
|
||||||
|
$this->expectException( InvalidArgumentException::class );
|
||||||
|
new LocalChecker( '\sin x^2', 'chem' );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalid() {
|
||||||
|
$checker = new LocalChecker( '\sin\newcommand' );
|
||||||
|
$this->assertFalse( $checker->isValid() );
|
||||||
|
|
||||||
|
$this->assertStringContainsString(
|
||||||
|
Message::newFromKey( 'math_unknown_function', '\newcommand' )
|
||||||
|
->inContentLanguage()
|
||||||
|
->escaped(),
|
||||||
|
$checker->getError()
|
||||||
|
->inContentLanguage()
|
||||||
|
->escaped()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertNull( $checker->getValidTex() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testErrorSyntax() {
|
||||||
|
$checker = new LocalChecker( '\left(' );
|
||||||
|
$this->assertFalse( $checker->isValid() );
|
||||||
|
$this->assertStringContainsString(
|
||||||
|
Message::newFromKey( 'math_syntax_error' )
|
||||||
|
->inContentLanguage()
|
||||||
|
->escaped(),
|
||||||
|
$checker->getError()
|
||||||
|
->inContentLanguage()
|
||||||
|
->escaped()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use MediaWiki\Extension\Math\InputCheck\InputCheckFactory;
|
|
||||||
use MediaWiki\Extension\Math\InputCheck\MathoidChecker;
|
|
||||||
use MediaWiki\Tests\Unit\MockServiceDependenciesTrait;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @method InputCheckFactory newServiceInstance( string $serviceClass, array $parameterOverrides )
|
|
||||||
* @covers \MediaWiki\Extension\Math\InputCheck\InputCheckFactory
|
|
||||||
*/
|
|
||||||
class InputCheckFactoryTest extends MediaWikiUnitTestCase {
|
|
||||||
use MockServiceDependenciesTrait;
|
|
||||||
|
|
||||||
public function testNewMathoidChecker() {
|
|
||||||
$checker = $this->newServiceInstance( InputCheckFactory::class, [] )
|
|
||||||
->newMathoidChecker( 'FORMULA', 'TYPE' );
|
|
||||||
$this->assertInstanceOf( MathoidChecker::class, $checker );
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue