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",
|
||||
"Moritz Schubotz",
|
||||
"Derk-Jan Hartman",
|
||||
"André Greiner-Petter"
|
||||
"André Greiner-Petter",
|
||||
"Johannes Stegmüller"
|
||||
],
|
||||
"url": "https://www.mediawiki.org/wiki/Extension:Math",
|
||||
"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.",
|
||||
"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": {
|
||||
"value": 240
|
||||
},
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
namespace MediaWiki\Extension\Math\InputCheck;
|
||||
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use MediaWiki\Config\ServiceOptions;
|
||||
use MediaWiki\Extension\Math\MathRestbaseInterface;
|
||||
use MediaWiki\Http\HttpRequestFactory;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WANObjectCache;
|
||||
|
@ -12,6 +15,7 @@ class InputCheckFactory {
|
|||
public const CONSTRUCTOR_OPTIONS = [
|
||||
'MathMathMLUrl',
|
||||
'MathLaTeXMLTimeout',
|
||||
'MathTexVCService'
|
||||
];
|
||||
/** @var string */
|
||||
private $url;
|
||||
|
@ -23,6 +27,8 @@ class InputCheckFactory {
|
|||
private $httpFactory;
|
||||
/** @var LoggerInterface */
|
||||
private $logger;
|
||||
/** @var string */
|
||||
private $texVCmode;
|
||||
|
||||
/**
|
||||
* @param ServiceOptions $options
|
||||
|
@ -39,15 +45,16 @@ class InputCheckFactory {
|
|||
$options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
|
||||
$this->url = $options->get( 'MathMathMLUrl' );
|
||||
$this->timeout = $options->get( 'MathLaTeXMLTimeout' );
|
||||
$this->texVCmode = $options->get( 'MathTexVCService' );
|
||||
$this->cache = $cache;
|
||||
$this->httpFactory = $httpFactory;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $input
|
||||
* @param string $type
|
||||
* @return MathoidChecker
|
||||
* @param string $input input string to be checked
|
||||
* @param string $type type of input
|
||||
* @return MathoidChecker checker based on mathoid
|
||||
*/
|
||||
public function newMathoidChecker( string $input, string $type ): MathoidChecker {
|
||||
return new MathoidChecker(
|
||||
|
@ -60,4 +67,55 @@ class InputCheckFactory {
|
|||
$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