X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=includes%2Fdiff%2FDifferenceEngine.php;h=e76bffcacec444c8178fb75d14c459669f0daa24;hp=6a2837b43a0448607e18f45e090dbe7e2966e3c3;hb=d77dfda69e491d536bd33fa098d7539db361086a;hpb=3488f495321a01f808eebf87e90b6fb334817d81 diff --git a/includes/diff/DifferenceEngine.php b/includes/diff/DifferenceEngine.php index 6a2837b43a..e76bffcace 100644 --- a/includes/diff/DifferenceEngine.php +++ b/includes/diff/DifferenceEngine.php @@ -23,9 +23,6 @@ use MediaWiki\MediaWikiServices; use MediaWiki\Shell\Shell; -/** @deprecated use class constant instead */ -define( 'MW_DIFF_VERSION', '1.11a' ); - /** * @todo document * @ingroup DifferenceEngine @@ -37,7 +34,7 @@ class DifferenceEngine extends ContextSource { * fixes important bugs or such to force cached diff views to * clear. */ - const DIFF_VERSION = MW_DIFF_VERSION; + const DIFF_VERSION = '1.12'; /** @var int */ public $mOldid; @@ -637,7 +634,10 @@ class DifferenceEngine extends ContextSource { if ( Hooks::run( 'DifferenceEngineRenderRevisionAddParserOutput', [ $this, $out, $parserOutput, $wikiPage ] ) ) { - $out->addParserOutput( $parserOutput ); + $out->addParserOutput( $parserOutput, [ + 'enableSectionEditLinks' => $this->mNewRev->isCurrent() + && $this->mNewRev->getTitle()->quickUserCan( 'edit', $this->getUser() ), + ] ); } } } @@ -650,6 +650,12 @@ class DifferenceEngine extends ContextSource { } } + /** + * @param WikiPage $page + * @param Revision $rev + * + * @return ParserOutput|bool False if the revision was not found + */ protected function getParserOutput( WikiPage $page, Revision $rev ) { $parserOptions = $page->makeParserOptions( $this->getContext() ); @@ -753,14 +759,22 @@ class DifferenceEngine extends ContextSource { $key = false; $cache = ObjectCache::getMainWANInstance(); if ( $this->mOldid && $this->mNewid ) { + // Check if subclass is still using the old way + // for backwards-compatibility $key = $this->getDiffBodyCacheKey(); + if ( $key === null ) { + $key = call_user_func_array( + [ $cache, 'makeKey' ], + $this->getDiffBodyCacheKeyParams() + ); + } // Try cache if ( !$this->mRefreshCache ) { $difftext = $cache->get( $key ); if ( $difftext ) { wfIncrStats( 'diff_cache.hit' ); - $difftext = $this->localiseLineNumbers( $difftext ); + $difftext = $this->localiseDiff( $difftext ); $difftext .= "\n\n"; return $difftext; @@ -788,9 +802,9 @@ class DifferenceEngine extends ContextSource { } else { wfIncrStats( 'diff_cache.uncacheable' ); } - // Replace line numbers with the text in the user's language + // localise line numbers and title attribute text if ( $difftext !== false ) { - $difftext = $this->localiseLineNumbers( $difftext ); + $difftext = $this->localiseDiff( $difftext ); } return $difftext; @@ -799,18 +813,49 @@ class DifferenceEngine extends ContextSource { /** * Returns the cache key for diff body text or content. * + * @deprecated since 1.31, use getDiffBodyCacheKeyParams() instead * @since 1.23 * * @throws MWException - * @return string + * @return string|null */ protected function getDiffBodyCacheKey() { + return null; + } + + /** + * Get the cache key parameters + * + * Subclasses can replace the first element in the array to something + * more specific to the type of diff (e.g. "inline-diff"), or append + * if the cache should vary on more things. Overriding entirely should + * be avoided. + * + * @since 1.31 + * + * @return array + * @throws MWException + */ + protected function getDiffBodyCacheKeyParams() { if ( !$this->mOldid || !$this->mNewid ) { throw new MWException( 'mOldid and mNewid must be set to get diff cache key.' ); } - return wfMemcKey( 'diff', 'version', self::DIFF_VERSION, - 'oldid', $this->mOldid, 'newid', $this->mNewid ); + $engine = $this->getEngine(); + $params = [ + 'diff', + $engine, + self::DIFF_VERSION, + "old-{$this->mOldid}", + "rev-{$this->mNewid}" + ]; + + if ( $engine === 'wikidiff2' ) { + $params[] = phpversion( 'wikidiff2' ); + $params[] = $this->getConfig()->get( 'WikiDiff2MovedParagraphDetectionCutoff' ); + } + + return $params; } /** @@ -897,18 +942,14 @@ class DifferenceEngine extends ContextSource { } /** - * Generates diff, to be wrapped internally in a logging/instrumentation + * Process $wgExternalDiffEngine and get a sane, usable engine * - * @param string $otext Old text, must be already segmented - * @param string $ntext New text, must be already segmented - * @return bool|string + * @return bool|string 'wikidiff2', path to an executable, or false */ - protected function textDiff( $otext, $ntext ) { - global $wgExternalDiffEngine, $wgContLang; - - $otext = str_replace( "\r\n", "\n", $otext ); - $ntext = str_replace( "\r\n", "\n", $ntext ); - + private function getEngine() { + global $wgExternalDiffEngine; + // We use the global here instead of Config because we write to the value, + // and Config is not mutable. if ( $wgExternalDiffEngine == 'wikidiff' || $wgExternalDiffEngine == 'wikidiff3' ) { wfDeprecated( "\$wgExternalDiffEngine = '{$wgExternalDiffEngine}'", '1.27' ); $wgExternalDiffEngine = false; @@ -921,13 +962,38 @@ class DifferenceEngine extends ContextSource { $wgExternalDiffEngine = false; } + if ( is_string( $wgExternalDiffEngine ) && is_executable( $wgExternalDiffEngine ) ) { + return $wgExternalDiffEngine; + } elseif ( $wgExternalDiffEngine === false && function_exists( 'wikidiff2_do_diff' ) ) { + return 'wikidiff2'; + } else { + // Native PHP + return false; + } + } + + /** + * Generates diff, to be wrapped internally in a logging/instrumentation + * + * @param string $otext Old text, must be already segmented + * @param string $ntext New text, must be already segmented + * @return bool|string + */ + protected function textDiff( $otext, $ntext ) { + global $wgContLang; + + $otext = str_replace( "\r\n", "\n", $otext ); + $ntext = str_replace( "\r\n", "\n", $ntext ); + + $engine = $this->getEngine(); + // Better external diff engine, the 2 may some day be dropped // This one does the escaping and segmenting itself - if ( function_exists( 'wikidiff2_do_diff' ) && $wgExternalDiffEngine === false ) { + if ( $engine === 'wikidiff2' ) { $wikidiff2Version = phpversion( 'wikidiff2' ); if ( $wikidiff2Version !== false && - version_compare( $wikidiff2Version, '0.3', '>=' ) + version_compare( $wikidiff2Version, '1.5.0', '>=' ) ) { $text = wikidiff2_do_diff( $otext, @@ -953,7 +1019,7 @@ class DifferenceEngine extends ContextSource { $text .= $this->debug( 'wikidiff2' ); return $text; - } elseif ( $wgExternalDiffEngine !== false && is_executable( $wgExternalDiffEngine ) ) { + } elseif ( $engine !== false ) { # Diff via the shell $tmpDir = wfTempDir(); $tempName1 = tempnam( $tmpDir, 'diff_' ); @@ -971,7 +1037,7 @@ class DifferenceEngine extends ContextSource { fwrite( $tempFile2, $ntext ); fclose( $tempFile1 ); fclose( $tempFile2 ); - $cmd = [ $wgExternalDiffEngine, $tempName1, $tempName2 ]; + $cmd = [ $engine, $tempName1, $tempName2 ]; $result = Shell::command( $cmd ) ->execute(); $exitCode = $result->getExitCode(); @@ -981,7 +1047,7 @@ class DifferenceEngine extends ContextSource { ); } $difftext = $result->getStdout(); - $difftext .= $this->debug( "external $wgExternalDiffEngine" ); + $difftext .= $this->debug( "external $engine" ); unlink( $tempName1 ); unlink( $tempName2 ); @@ -994,6 +1060,7 @@ class DifferenceEngine extends ContextSource { $diffs = new Diff( $ota, $nta ); $formatter = new TableDiffFormatter(); $difftext = $wgContLang->unsegmentForDiff( $formatter->format( $diffs ) ); + $difftext .= $this->debug( 'native PHP' ); return $difftext; } @@ -1022,6 +1089,22 @@ class DifferenceEngine extends ContextSource { " -->\n"; } + /** + * Localise diff output + * + * @param string $text + * @return string + */ + private function localiseDiff( $text ) { + $text = $this->localiseLineNumbers( $text ); + if ( $this->getEngine() === 'wikidiff2' && + version_compare( phpversion( 'wikidiff2' ), '1.5.1', '>=' ) + ) { + $text = $this->addLocalisedTitleTooltips( $text ); + } + return $text; + } + /** * Replace line numbers with the text in the user's language * @@ -1045,6 +1128,31 @@ class DifferenceEngine extends ContextSource { return $this->msg( 'lineno' )->numParams( $matches[1] )->escaped(); } + /** + * Add title attributes for tooltips on moved paragraph indicators + * + * @param string $text + * @return string + */ + private function addLocalisedTitleTooltips( $text ) { + return preg_replace_callback( + '/class="mw-diff-movedpara-(left|right)"/', + [ $this, 'addLocalisedTitleTooltipsCb' ], + $text + ); + } + + /** + * @param array $matches + * @return string + */ + private function addLocalisedTitleTooltipsCb( array $matches ) { + $key = $matches[1] === 'right' ? + 'diff-paragraph-moved-toold' : + 'diff-paragraph-moved-tonew'; + return $matches[0] . ' title="' . $this->msg( $key )->escaped() . '"'; + } + /** * If there are revisions between the ones being compared, return a note saying so. *