Merge "Add support for wikidiff2_multi_format_diff()"

This commit is contained in:
jenkins-bot 2023-07-31 11:54:12 +00:00 committed by Gerrit Code Review
commit 1d5e4f3d0a
12 changed files with 178 additions and 20 deletions

View file

@ -45,3 +45,12 @@ function wikidiff2_inline_diff( $text1, $text2, $numContextLines ) {
*/
function wikidiff2_inline_json_diff( $text1, $text2, $numContextLines ) {
}
/**
* @param string $text1
* @param string $text2
* @param array $options
* @return array
*/
function wikidiff2_multi_format_diff( $text1, $text2, $options ) {
}

View file

@ -2125,6 +2125,29 @@ config-schema:
- string
- boolean
description: 'Name of the external diff engine to use.'
Wikidiff2Options:
default: { }
type: object
description: |-
Options for wikidiff2:
- useMultiFormat: (bool) Whether to use wikidiff2_multi_format_diff()
if it is available. This temporarily defaults to false, during
migration to the new code. It is available in wikidiff2 1.14.0+.
The following options are only effective if wikidiff2_multi_format_diff()
is enabled. See README.md in wikidiff2 for details:
- numContextLines
- changeThreshold
- movedLineThreshold
- maxMovedLines
- maxWordLevelDiffComplexity
- maxSplitSize
- initialSplitThreshold
- finalSplitThreshold
Also:
- formatOptions: An array of format-specific overrides. The key may
be "inline" or "table" and the value is an array with keys
numContextLines, changeThreshold, etc.
@since 1.41
RequestTimeLimit:
default: null
type:

View file

@ -1307,6 +1307,12 @@ $wgDiffEngine = null;
*/
$wgExternalDiffEngine = null;
/**
* Config variable stub for the Wikidiff2Options setting, for use by phpdoc and IDEs.
* @see MediaWiki\MainConfigSchema::Wikidiff2Options
*/
$wgWikidiff2Options = null;
/**
* Config variable stub for the RequestTimeLimit setting, for use by phpdoc and IDEs.
* @see MediaWiki\MainConfigSchema::RequestTimeLimit

View file

@ -1322,6 +1322,12 @@ class MainConfigNames {
*/
public const ExternalDiffEngine = 'ExternalDiffEngine';
/**
* Name constant for the Wikidiff2Options setting, for use with Config::get()
* @see MainConfigSchema::Wikidiff2Options
*/
public const Wikidiff2Options = 'Wikidiff2Options';
/**
* Name constant for the RequestTimeLimit setting, for use with Config::get()
* @see MainConfigSchema::RequestTimeLimit

View file

@ -3467,6 +3467,35 @@ class MainConfigSchema {
'type' => 'string|false',
];
/**
* Options for wikidiff2:
* - useMultiFormat: (bool) Whether to use wikidiff2_multi_format_diff()
* if it is available. This temporarily defaults to false, during
* migration to the new code. It is available in wikidiff2 1.14.0+.
*
* The following options are only effective if wikidiff2_multi_format_diff()
* is enabled. See README.md in wikidiff2 for details:
*
* - numContextLines
* - changeThreshold
* - movedLineThreshold
* - maxMovedLines
* - maxWordLevelDiffComplexity
* - maxSplitSize
* - initialSplitThreshold
* - finalSplitThreshold
*
* Also:
* - formatOptions: An array of format-specific overrides. The key may
* be "inline" or "table" and the value is an array with keys
* numContextLines, changeThreshold, etc.
* @since 1.41
*/
public const Wikidiff2Options = [
'default' => [],
'type' => 'map'
];
// endregion -- end of Content handlers and storage
/***************************************************************************/

View file

@ -422,6 +422,8 @@ return [
'PageLanguageUseDB' => false,
'DiffEngine' => null,
'ExternalDiffEngine' => false,
'Wikidiff2Options' => [
],
'RequestTimeLimit' => null,
'TransactionalTimeLimit' => 120,
'CriticalSectionTimeLimit' => 180.0,
@ -2621,6 +2623,7 @@ return [
0 => 'string',
1 => 'boolean',
],
'Wikidiff2Options' => 'object',
'RequestTimeLimit' => [
0 => 'integer',
1 => 'null',

View file

@ -711,7 +711,8 @@ abstract class ContentHandler {
RequestContext::getMain(),
$language,
$config->get( MainConfigNames::DiffEngine ),
$config->get( MainConfigNames::ExternalDiffEngine )
$config->get( MainConfigNames::ExternalDiffEngine ),
$config->get( MainConfigNames::Wikidiff2Options )
);
}
$format = $options['diff-type'] ?? 'table';

View file

@ -2241,7 +2241,8 @@ class DifferenceEngine extends ContextSource {
$this->getContext(),
$this->getDiffLang(),
$this->getConfig()->get( MainConfigNames::DiffEngine ),
$this->getConfig()->get( MainConfigNames::ExternalDiffEngine )
$this->getConfig()->get( MainConfigNames::ExternalDiffEngine ),
$this->getConfig()->get( MainConfigNames::Wikidiff2Options )
);
}
return $this->textDiffer;

View file

@ -27,6 +27,8 @@ class ManifoldTextDiffer implements TextDiffer {
private $differs;
/** @var TextDiffer[]|null The differ to use for each format */
private $differsByFormat;
/** @var array */
private $wikidiff2Options;
/**
* @internal For use by DifferenceEngine, ContentHandler
@ -35,17 +37,20 @@ class ManifoldTextDiffer implements TextDiffer {
* @param Language|null $contentLanguage
* @param string|null $diffEngine The DiffEngine config variable
* @param string|false|null $externalPath The ExternalDiffEngine config variable
* @param array $wikidiff2Options The Wikidiff2Options config variable
*/
public function __construct(
MessageLocalizer $localizer,
?Language $contentLanguage,
$diffEngine,
$externalPath
$externalPath,
$wikidiff2Options
) {
$this->localizer = $localizer;
$this->contentLanguage = $contentLanguage;
$this->diffEngine = $diffEngine;
$this->externalPath = $externalPath;
$this->wikidiff2Options = $wikidiff2Options;
}
public function getName(): string {
@ -243,7 +248,9 @@ class ManifoldTextDiffer implements TextDiffer {
case 'wikidiff2':
if ( Wikidiff2TextDiffer::isInstalled() ) {
return new Wikidiff2TextDiffer;
return new Wikidiff2TextDiffer(
$this->wikidiff2Options
);
}
$failureReason = 'wikidiff2 is not available';
return null;

View file

@ -14,7 +14,26 @@ class Wikidiff2TextDiffer extends BaseTextDiffer {
/** @var bool */
private $haveMoveSupport;
/** @var bool */
private $haveMultiFormatSupport;
/** @var bool */
private $haveCutoffParameter;
/** @var bool */
private $useMultiFormat;
/** @var array */
private $defaultOptions;
/** @var array[] */
private $formatOptions;
private const OPT_NAMES = [
'numContextLines',
'changeThreshold',
'movedLineThreshold',
'maxMovedLines',
'maxWordLevelDiffComplexity',
'maxSplitSize',
'initialSplitThreshold',
'finalSplitThreshold',
];
/**
* Fake wikidiff2 extension version for PHPUnit testing
@ -32,11 +51,23 @@ class Wikidiff2TextDiffer extends BaseTextDiffer {
|| function_exists( 'wikidiff2_do_diff' );
}
public function __construct() {
/**
* @param array $options
*/
public function __construct( $options ) {
$this->version = self::$fakeVersionForTesting ?? phpversion( 'wikidiff2' );
$this->haveMoveSupport = version_compare( $this->version, '1.5.0', '>=' );
$this->haveMultiFormatSupport = version_compare( $this->version, '1.14.0', '>=' );
$this->haveCutoffParameter = $this->haveMoveSupport
&& version_compare( $this->version, '1.8.0', '<' );
$this->useMultiFormat = $this->haveMultiFormatSupport && !empty( $options['useMultiFormat'] );
$validOpts = array_fill_keys( self::OPT_NAMES, true );
$this->defaultOptions = array_intersect_key( $options, $validOpts );
$this->formatOptions = [];
foreach ( $options['formatOptions'] ?? [] as $format => $formatOptions ) {
$this->formatOptions[$format] = array_intersect_key( $formatOptions, $validOpts );
}
}
public function getName(): string {
@ -52,16 +83,38 @@ class Wikidiff2TextDiffer extends BaseTextDiffer {
}
public function doRenderBatch( string $oldText, string $newText, array $formats ): array {
$result = [];
foreach ( $formats as $format ) {
switch ( $format ) {
case 'table':
$result['table'] = $this->doTableFormat( $oldText, $newText );
break;
if ( $this->useMultiFormat ) {
if ( !$this->formatOptions ) {
/** @var array $result */
$result = wikidiff2_multi_format_diff(
$oldText,
$newText,
[ 'formats' => $formats ] + $this->defaultOptions
);
} else {
$result = [];
foreach ( $formats as $format ) {
$result[$format] = wikidiff2_multi_format_diff(
$oldText,
$newText,
[ 'formats' => $formats ]
+ ( $this->formatOptions[$format] ?? [] )
+ $this->defaultOptions
);
}
}
} else {
$result = [];
foreach ( $formats as $format ) {
switch ( $format ) {
case 'table':
$result['table'] = $this->doTableFormat( $oldText, $newText );
break;
case 'inline':
$result['inline'] = $this->doInlineFormat( $oldText, $newText );
break;
case 'inline':
$result['inline'] = $this->doInlineFormat( $oldText, $newText );
break;
}
}
}
return $result;
@ -162,4 +215,11 @@ class Wikidiff2TextDiffer extends BaseTextDiffer {
return strtr( $text, $replacements );
}
public function getPreferredFormatBatch( string $format ): array {
if ( $this->formatOptions ) {
return [ $format ];
} else {
return [ 'table', 'inline' ];
}
}
}

View file

@ -14,7 +14,8 @@ class ManifoldTextDifferTest extends MediaWikiIntegrationTestCase {
RequestContext::getMain(),
$services->getLanguageFactory()->getLanguage( 'en' ),
$configVars['DiffEngine'] ?? null,
$configVars['ExternalDiffEngine'] ?? null
$configVars['ExternalDiffEngine'] ?? null,
$configVars['Wikidiff2Options'] ?? []
);
}

View file

@ -10,7 +10,7 @@ use Wikimedia\TestingAccessWrapper;
*/
class Wikidiff2TextDifferTest extends MediaWikiIntegrationTestCase {
private function createDiffer() {
$differ = new Wikidiff2TextDiffer();
$differ = new Wikidiff2TextDiffer( [] );
$localizer = RequestContext::getMain();
$localizer->setLanguage( 'qqx' );
$differ->setLocalizer( $localizer );
@ -18,13 +18,25 @@ class Wikidiff2TextDifferTest extends MediaWikiIntegrationTestCase {
return $differ;
}
public static function provideRenderBatch() {
return [
[ false ],
[ true ]
];
}
/**
* @requires extension wikidiff2
* @dataProvider provideRenderBatch
* @param bool $useMultiFormat
*/
public function testRenderBatch() {
public function testRenderBatch( $useMultiFormat ) {
if ( !function_exists( 'wikidiff2_multi_format_diff' ) && $useMultiFormat ) {
$this->markTestSkipped( 'Need wikidiff2 1.14.0+' );
}
$oldText = 'foo';
$newText = 'bar';
$differ = new Wikidiff2TextDiffer();
$differ = new Wikidiff2TextDiffer( [ 'useMultiFormat' => $useMultiFormat ] );
// Should not need a MessageLocalizer
$result = $differ->renderBatch( $oldText, $newText, [ 'table', 'inline' ] );
$this->assertSame(
@ -37,12 +49,12 @@ class Wikidiff2TextDifferTest extends MediaWikiIntegrationTestCase {
}
public function testGetName() {
$differ = new Wikidiff2TextDiffer();
$differ = new Wikidiff2TextDiffer( [] );
$this->assertSame( 'wikidiff2', $differ->getName() );
}
public function testGetFormatContext() {
$differ = new Wikidiff2TextDiffer();
$differ = new Wikidiff2TextDiffer( [] );
$this->assertSame( TextDiffer::CONTEXT_ROW, $differ->getFormatContext( 'table' ) );
}