Merge "Add support for wikidiff2_multi_format_diff()"
This commit is contained in:
commit
1d5e4f3d0a
12 changed files with 178 additions and 20 deletions
|
|
@ -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 ) {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
/***************************************************************************/
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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' ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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'] ?? []
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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' ) );
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue