69 return $this->engine === self::ENGINE_WIKIDIFF2_INLINE ? [
70 phpversion(
'wikidiff2' ),
'inline' 80 public static function diff( $oldText, $newText ) {
84 '@phan-var TextSlotDiffRenderer $slotDiffRenderer';
85 return $slotDiffRenderer->getTextDiff( $oldText, $newText );
102 $engines = [ self::ENGINE_PHP, self::ENGINE_WIKIDIFF2, self::ENGINE_EXTERNAL,
103 self::ENGINE_WIKIDIFF2_INLINE ];
104 Assert::parameter( in_array(
$type, $engines,
true ),
'$type',
105 'must be one of the TextSlotDiffRenderer::ENGINE_* constants' );
106 if (
$type === self::ENGINE_EXTERNAL ) {
107 Assert::parameter( is_string( $executable ) && is_executable( $executable ),
'$executable',
108 'must be a path to a valid executable' );
110 Assert::parameter( is_null( $executable ),
'$executable',
111 'must not be set unless $type is ENGINE_EXTERNAL' );
113 $this->engine =
$type;
114 $this->externalEngine = $executable;
121 $oldText = $oldContent->serialize();
122 $newText = $newContent->serialize();
134 Assert::parameterType(
'string', $oldText,
'$oldText' );
135 Assert::parameterType(
'string', $newText,
'$newText' );
137 $diff =
function () use ( $oldText, $newText ) {
138 $time = microtime(
true );
142 $time = intval( ( microtime(
true ) - $time ) * 1000 );
143 if ( $this->statsdDataFactory ) {
144 $this->statsdDataFactory->timing(
'diff_time', $time );
163 $error =
function ( $status ) {
164 throw new FatalError( $status->getWikiText() );
168 if ( strlen( $oldText ) + strlen( $newText ) > 20000 ) {
170 md5( $oldText ) . md5( $newText ),
171 [
'doWork' => $diff,
'error' => $error ]
173 return $work->execute();
191 $oldText = str_replace(
"\r\n",
"\n", $oldText );
192 $newText = str_replace(
"\r\n",
"\n", $newText );
196 if ( $this->engine === self::ENGINE_WIKIDIFF2 ) {
197 $wikidiff2Version = phpversion(
'wikidiff2' );
199 $wikidiff2Version !==
false &&
200 version_compare( $wikidiff2Version,
'1.5.0',
'>=' ) &&
201 version_compare( $wikidiff2Version,
'1.8.0',
'<' )
203 $text = wikidiff2_do_diff(
211 $text = wikidiff2_do_diff(
219 } elseif ( $this->engine === self::ENGINE_EXTERNAL ) {
222 $tempName1 = tempnam( $tmpDir,
'diff_' );
223 $tempName2 = tempnam( $tmpDir,
'diff_' );
225 $tempFile1 = fopen( $tempName1,
"w" );
229 $tempFile2 = fopen( $tempName2,
"w" );
233 fwrite( $tempFile1, $oldText );
234 fwrite( $tempFile2, $newText );
235 fclose( $tempFile1 );
236 fclose( $tempFile2 );
238 $result = Shell::command( $cmd )
240 $exitCode = $result->getExitCode();
241 if ( $exitCode !== 0 ) {
242 throw new Exception(
"External diff command returned code {$exitCode}. Stderr: " 246 $difftext = $result->getStdout();
247 unlink( $tempName1 );
248 unlink( $tempName2 );
251 } elseif ( $this->engine === self::ENGINE_PHP ) {
252 if ( $this->language ) {
253 $oldText = $this->language->segmentForDiff( $oldText );
254 $newText = $this->language->segmentForDiff( $newText );
256 $ota = explode(
"\n", $oldText );
257 $nta = explode(
"\n", $newText );
258 $diffs =
new Diff( $ota, $nta );
260 $difftext = $formatter->format( $diffs );
261 if ( $this->language ) {
262 $difftext = $this->language->unsegmentForDiff( $difftext );
266 } elseif ( $this->engine === self::ENGINE_WIKIDIFF2_INLINE ) {
271 return '<tr><td colspan="4">' . wikidiff2_inline_diff( $oldText, $newText, 2 ) .
'</td></tr>';
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking, formatting, etc.
setEngine( $type, $executable=null)
Set which diff engine to use.
string $externalEngine
Path to an executable to be used as the diff engine.
setLanguage(Language $language)
getTextDiff( $oldText, $newText)
Diff the text representations of two content objects (or just two pieces of text in general)...
normalizeContents(Content &$oldContent=null, Content &$newContent=null, $allowedClasses=null)
Helper method to normalize the input of getDiff().
getTextDiffInternal( $oldText, $newText)
Diff the text representations of two content objects (or just two pieces of text in general)...
Convenience class for dealing with PoolCounters using callbacks.
wfTempDir()
Tries to get the system directory for temporary files.
static getMain()
Get the RequestContext object associated with the main request.
static getForModelID( $modelId)
Returns the ContentHandler singleton for the given model ID.
Renders a slot diff by doing a text diff on the native representation.
Language null $language
The language this content is in.
Renders a diff for a single slot (that is, a diff between two content objects).
Class representing a 'diff' between two sequences of strings.
string $engine
One of the ENGINE_* constants.
static diff( $oldText, $newText)
Convenience helper to use getTextDiff without an instance.
const ENGINE_PHP
Use the PHP diff implementation (DiffEngine).
Abort the web request with a custom HTML string that will represent the entire response.
const ENGINE_WIKIDIFF2
Use the wikidiff2 PHP module.
getDiff(Content $oldContent=null, Content $newContent=null)
setStatsdDataFactory(IBufferingStatsdDataFactory $statsdDataFactory)
const ENGINE_EXTERNAL
Use an external executable.
const ENGINE_WIKIDIFF2_INLINE
Use the wikidiff2 PHP module.
IBufferingStatsdDataFactory null $statsdDataFactory