X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FDifferenceEngine.php;h=6dc82d6b1f81900bbe3ae4abffbc1caac9dd1b43;hb=ce7a9631d71a68bab409c0557400808ab28c6909;hp=a69c505c20c68f9e45bd7373e44f1cbf2bb49246;hpb=5185b09395b3b68c6cfe392ad0458c165f690c74;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/DifferenceEngine.php b/includes/DifferenceEngine.php index a69c505c20..6dc82d6b1f 100644 --- a/includes/DifferenceEngine.php +++ b/includes/DifferenceEngine.php @@ -6,26 +6,22 @@ */ /** */ -require_once( 'Revision.php' ); - define( 'MAX_DIFF_LINE', 10000 ); define( 'MAX_DIFF_XREF_LENGTH', 10000 ); /** * @todo document - * @access public + * @public * @package MediaWiki * @subpackage DifferenceEngine */ class DifferenceEngine { /**#@+ - * @access private + * @private */ var $mOldid, $mNewid, $mTitle; var $mOldtitle, $mNewtitle, $mPagetitle; var $mOldtext, $mNewtext; - var $mOldUser, $mNewUser; - var $mOldComment, $mNewComment; var $mOldPage, $mNewPage; var $mRcidMarkPatrolled; var $mOldRev, $mNewRev; @@ -35,16 +31,16 @@ class DifferenceEngine { /** * Constructor - * @param Title $titleObj Title object that the diff is associated with - * @param integer $old Old ID we want to show and diff with. - * @param string $new Either 'prev' or 'next'. - * @param integer $rcid ??? (default 0) + * @param $titleObj Title object that the diff is associated with + * @param $old Integer: old ID we want to show and diff with. + * @param $new String: either 'prev' or 'next'. + * @param $rcid Integer: ??? FIXME (default 0) */ function DifferenceEngine( $titleObj = null, $old = 0, $new = 0, $rcid = 0 ) { $this->mTitle = $titleObj; wfDebug("DifferenceEngine old '$old' new '$new' rcid '$rcid'\n"); - if ( 'prev' == $new ) { + if ( 'prev' === $new ) { # Show diff between revision $old and the previous one. # Get previous one from DB. # @@ -52,7 +48,7 @@ class DifferenceEngine { $this->mOldid = $this->mTitle->getPreviousRevisionID( $this->mNewid ); - } elseif ( 'next' == $new ) { + } elseif ( 'next' === $new ) { # Show diff between revision $old and the previous one. # Get previous one from DB. # @@ -72,8 +68,7 @@ class DifferenceEngine { } function showDiffPage() { - global $wgUser, $wgOut, $wgContLang, $wgOnlySysopsCanPatrol, - $wgUseExternalEditor, $wgUseRCPatrol; + global $wgUser, $wgOut, $wgContLang, $wgUseExternalEditor, $wgUseRCPatrol; $fname = 'DifferenceEngine::showDiffPage'; wfProfileIn( $fname ); @@ -117,6 +112,9 @@ CONTROL; wfProfileOut( $fname ); return; } + + wfRunHooks( 'DiffViewHeader', array( $this, $this->mOldRev, $this->mNewRev ) ); + if ( $this->mNewRev->isCurrent() ) { $wgOut->setArticleFlag( true ); } @@ -140,7 +138,7 @@ CONTROL; $wgOut->setPageTitle( $oldTitle . ', ' . $newTitle ); } $wgOut->setSubtitle( wfMsg( 'difference' ) ); - $wgOut->setRobotpolicy( 'noindex,follow' ); + $wgOut->setRobotpolicy( 'noindex,nofollow' ); if ( !( $this->mOldPage->userCanRead() && $this->mNewPage->userCanRead() ) ) { $wgOut->loginToUse(); @@ -153,30 +151,17 @@ CONTROL; $talk = $wgContLang->getNsText( NS_TALK ); $contribs = wfMsg( 'contribslink' ); - $this->mOldComment = $sk->formatComment($this->mOldComment); - $this->mNewComment = $sk->formatComment($this->mNewComment); - - $oldUserLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER, $this->mOldUser ), $this->mOldUser ); - $newUserLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER, $this->mNewUser ), $this->mNewUser ); - $oldUTLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER_TALK, $this->mOldUser ), $talk ); - $newUTLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER_TALK, $this->mNewUser ), $talk ); - $oldContribs = $sk->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Contributions' ), $contribs, - 'target=' . urlencode($this->mOldUser) ); - $newContribs = $sk->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Contributions' ), $contribs, - 'target=' . urlencode($this->mNewUser) ); if ( $this->mNewRev->isCurrent() && $wgUser->isAllowed('rollback') ) { + $username = $this->mNewRev->getUserText(); $rollback = '   [' . $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'rollbacklink' ), - 'action=rollback&from=' . urlencode($this->mNewUser) . - '&token=' . urlencode( $wgUser->editToken( array( $this->mTitle->getPrefixedText(), $this->mNewUser ) ) ) ) . + 'action=rollback&from=' . urlencode( $username ) . + '&token=' . urlencode( $wgUser->editToken( array( $this->mTitle->getPrefixedText(), $username ) ) ) ) . ']'; } else { $rollback = ''; } - if ( $wgUseRCPatrol && $this->mRcidMarkPatrolled != 0 && $wgUser->isLoggedIn() && - ( $wgUser->isAllowed('rollback') || !$wgOnlySysopsCanPatrol ) ) - { - $patrol = ' [' . $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'markaspatrolleddiff' ), - "action=markpatrolled&rcid={$this->mRcidMarkPatrolled}" ) . ']'; + if( $wgUseRCPatrol && $this->mRcidMarkPatrolled != 0 && $wgUser->isAllowed( 'patrol' ) ) { + $patrol = ' [' . $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'markaspatrolleddiff' ), "action=markpatrolled&rcid={$this->mRcidMarkPatrolled}" ) . ']'; } else { $patrol = ''; } @@ -184,24 +169,26 @@ CONTROL; $prevlink = $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml( 'previousdiff' ), 'diff=prev&oldid='.$this->mOldid, '', '', 'id="differences-prevlink"' ); if ( $this->mNewRev->isCurrent() ) { - $nextlink = ''; + $nextlink = ' '; } else { $nextlink = $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml( 'nextdiff' ), 'diff=next&oldid='.$this->mNewid, '', '', 'id="differences-nextlink"' ); } - $oldHeader = "{$this->mOldtitle}
$oldUserLink " . - "($oldUTLink | $oldContribs)
" . $this->mOldComment . - '
' . $prevlink; - $newHeader = "{$this->mNewtitle}
$newUserLink " . - "($newUTLink | $newContribs) $rollback
" . $this->mNewComment . - '
' . $nextlink . $patrol; + $oldHeader = "{$this->mOldtitle}
" . + $sk->revUserTools( $this->mOldRev ) . "
" . + $sk->revComment( $this->mOldRev ) . "
" . + $prevlink; + $newHeader = "{$this->mNewtitle}
" . + $sk->revUserTools( $this->mNewRev ) . " $rollback
" . + $sk->revComment( $this->mNewRev ) . "
" . + $nextlink . $patrol; $this->showDiff( $oldHeader, $newHeader ); $wgOut->addHTML( "

{$this->mPagetitle}

\n" ); if( !$this->mNewRev->isCurrent() ) { - $oldEditSectionSetting = $wgOut->mParserOptions->setEditSection( false ); + $oldEditSectionSetting = $wgOut->parserOptions()->setEditSection( false ); } $this->loadNewText(); @@ -211,7 +198,7 @@ CONTROL; $wgOut->addSecondaryWikiText( $this->mNewtext ); if( !$this->mNewRev->isCurrent() ) { - $wgOut->mParserOptions->setEditSection( $oldEditSectionSetting ); + $wgOut->parserOptions()->setEditSection( $oldEditSectionSetting ); } wfProfileOut( $fname ); @@ -222,7 +209,7 @@ CONTROL; * contrast to normal "old revision" display style. */ function showFirstRevision() { - global $wgOut, $wgUser, $wgLang; + global $wgOut, $wgUser; $fname = 'DifferenceEngine::showFirstRevision'; wfProfileIn( $fname ); @@ -255,19 +242,16 @@ CONTROL; # $sk = $wgUser->getSkin(); - $uTLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER_TALK, $this->mOldUser ), $wgLang->getNsText( NS_TALK ) ); - $userLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER, $this->mOldUser ), $this->mOldUser ); - $contribs = $sk->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Contributions' ), wfMsg( 'contribslink' ), - 'target=' . urlencode($this->mOldUser) ); $nextlink = $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml( 'nextdiff' ), 'diff=next&oldid='.$this->mNewid, '', '', 'id="differences-nextlink"' ); - $header = "
{$this->mOldtitle}
$userLink " . - "($uTLink | $contribs)
" . $this->mOldComment . - '
' . $nextlink. "
\n"; + $header = "
{$this->mOldtitle}
" . + $sk->revUserTools( $this->mNewRev ) . "
" . + $sk->revComment( $this->mNewRev ) . "
" . + $nextlink . "
\n"; $wgOut->addHTML( $header ); $wgOut->setSubtitle( wfMsg( 'difference' ) ); - $wgOut->setRobotpolicy( 'noindex,follow' ); + $wgOut->setRobotpolicy( 'noindex,nofollow' ); # Show current revision @@ -289,7 +273,7 @@ CONTROL; global $wgOut; $diff = $this->getDiff( $otitle, $ntitle ); if ( $diff === false ) { - $wgOut->addWikitext( wfMsg( 'missingarticle', "$t" ) ); + $wgOut->addWikitext( wfMsg( 'missingarticle', "(fixme, bug)" ) ); return false; } else { $wgOut->addHTML( $diff ); @@ -313,11 +297,14 @@ CONTROL; /** * Get the diff table body, without header + * Results are cached * Returns false on error */ function getDiffBody() { - global $wgUseExternalDiffEngine, $wgContLang, $wgMemc, $wgDBname; - + global $wgMemc, $wgDBname; + $fname = 'DifferenceEngine::getDiffBody'; + wfProfileIn( $fname ); + // Cacheable? $key = false; if ( $this->mOldid && $this->mNewid ) { @@ -326,45 +313,123 @@ CONTROL; $difftext = $wgMemc->get( $key ); if ( $difftext ) { wfIncrStats( 'diff_cache_hit' ); - $difftext .= "\n\n"; + $difftext = $this->localiseLineNumbers( $difftext ); + $difftext .= "\n\n"; + wfProfileOut( $fname ); return $difftext; } } if ( !$this->loadText() ) { + wfProfileOut( $fname ); return false; } - $otext = $wgContLang->segmentForDiff($this->mOldtext); - $ntext = $wgContLang->segmentForDiff($this->mNewtext); - if ( $wgUseExternalDiffEngine ) { - # For historical reasons, external diff engine expects - # input text to be HTML-escaped already - $otext = str_replace( "\r\n", "\n", htmlspecialchars ( $otext ) ); - $ntext = str_replace( "\r\n", "\n", htmlspecialchars ( $ntext ) ); - if( !function_exists( 'wikidiff_do_diff' ) ) { - dl('php_wikidiff.so'); - } - $difftext = wikidiff_do_diff( $otext, $ntext, 2 ); - } else { - $ota = explode( "\n", str_replace( "\r\n", "\n", $otext ) ); - $nta = explode( "\n", str_replace( "\r\n", "\n", $ntext ) ); - $diffs =& new Diff( $ota, $nta ); - $formatter =& new TableDiffFormatter(); - $difftext = $formatter->format( $diffs ); - } - $difftext = $wgContLang->unsegmentForDiff($difftext); - + $difftext = $this->generateDiffBody( $this->mOldtext, $this->mNewtext ); + // Save to cache for 7 days - if ( $key !== false ) { + if ( $key !== false && $difftext !== false ) { wfIncrStats( 'diff_cache_miss' ); $wgMemc->set( $key, $difftext, 7*86400 ); } else { wfIncrStats( 'diff_uncacheable' ); } + // Replace line numbers with the text in the user's language + if ( $difftext !== false ) { + $difftext = $this->localiseLineNumbers( $difftext ); + } + wfProfileOut( $fname ); return $difftext; } + /** + * Generate a diff, no caching + * $otext and $ntext must be already segmented + */ + function generateDiffBody( $otext, $ntext ) { + global $wgExternalDiffEngine, $wgContLang; + $fname = 'DifferenceEngine::generateDiffBody'; + + $otext = str_replace( "\r\n", "\n", $otext ); + $ntext = str_replace( "\r\n", "\n", $ntext ); + + if ( $wgExternalDiffEngine == 'wikidiff' ) { + # For historical reasons, external diff engine expects + # input text to be HTML-escaped already + $otext = htmlspecialchars ( $wgContLang->segmentForDiff( $otext ) ); + $ntext = htmlspecialchars ( $wgContLang->segmentForDiff( $ntext ) ); + if( !function_exists( 'wikidiff_do_diff' ) ) { + dl('php_wikidiff.so'); + } + return $wgContLang->unsegementForDiff( wikidiff_do_diff( $otext, $ntext, 2 ) ); + } + + if ( $wgExternalDiffEngine == 'wikidiff2' ) { + # 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' ) ) { + wfProfileIn( "$fname-dl" ); + @dl('php_wikidiff2.so'); + wfProfileOut( "$fname-dl" ); + } + if ( function_exists( 'wikidiff2_do_diff' ) ) { + wfProfileIn( 'wikidiff2_do_diff' ); + $text = wikidiff2_do_diff( $otext, $ntext, 2 ); + wfProfileOut( 'wikidiff2_do_diff' ); + return $text; + } + } + if ( $wgExternalDiffEngine !== false ) { + # Diff via the shell + global $wgTmpDirectory; + $tempName1 = tempnam( $wgTmpDirectory, 'diff_' ); + $tempName2 = tempnam( $wgTmpDirectory, 'diff_' ); + + $tempFile1 = fopen( $tempName1, "w" ); + if ( !$tempFile1 ) { + wfProfileOut( $fname ); + return false; + } + $tempFile2 = fopen( $tempName2, "w" ); + if ( !$tempFile2 ) { + wfProfileOut( $fname ); + return false; + } + fwrite( $tempFile1, $otext ); + fwrite( $tempFile2, $ntext ); + fclose( $tempFile1 ); + fclose( $tempFile2 ); + $cmd = wfEscapeShellArg( $wgExternalDiffEngine, $tempName1, $tempName2 ); + wfProfileIn( "$fname-shellexec" ); + $difftext = wfShellExec( $cmd ); + wfProfileOut( "$fname-shellexec" ); + unlink( $tempName1 ); + unlink( $tempName2 ); + return $difftext; + } + + # Native PHP diff + $ota = explode( "\n", $wgContLang->segmentForDiff( $otext ) ); + $nta = explode( "\n", $wgContLang->segmentForDiff( $ntext ) ); + $diffs = new Diff( $ota, $nta ); + $formatter = new TableDiffFormatter(); + return $wgContLang->unsegmentForDiff( $formatter->format( $diffs ) ); + } + + + /** + * Replace line numbers with the text in the user's language + */ + function localiseLineNumbers( $text ) { + return preg_replace_callback( '//', + array( &$this, 'localiseLineNumbersCb' ), $text ); + } + + function localiseLineNumbersCb( $matches ) { + global $wgLang; + return wfMsgExt( 'lineno', array('parseinline'), $wgLang->formatNum( $matches[1] ) ); + } + /** * Add the header to a diff body */ @@ -421,22 +486,25 @@ CONTROL; } // Set assorted variables + $timestamp = $wgLang->timeanddate( $this->mNewRev->getTimestamp(), true ); + $this->mNewPage = $this->mNewRev->getTitle(); if( $this->mNewRev->isCurrent() ) { - $this->mPagetitle = htmlspecialchars( wfMsg( 'currentrev' ) ); - $this->mNewPage = $this->mTitle; $newLink = $this->mNewPage->escapeLocalUrl(); - $this->mNewtitle = "{$this->mPagetitle}"; + $this->mPagetitle = htmlspecialchars( wfMsg( 'currentrev' ) ); + $newEdit = $this->mNewPage->escapeLocalUrl( 'action=edit' ); + + $this->mNewtitle = "{$this->mPagetitle} ($timestamp)" + . " (" . htmlspecialchars( wfMsg( 'editold' ) ) . ")"; + } else { - $this->mNewPage = $this->mNewRev->getTitle(); - $newLink = $this->mNewPage->escapeLocalUrl ('oldid=' . $this->mNewid ); - $t = $wgLang->timeanddate( $this->mNewRev->getTimestamp(), true ); - $this->mPagetitle = htmlspecialchars( wfMsg( 'revisionasof', $t ) ); - $this->mNewtitle = "{$this->mPagetitle}"; + $newLink = $this->mNewPage->escapeLocalUrl( 'oldid=' . $this->mNewid ); + $newEdit = $this->mNewPage->escapeLocalUrl( 'action=edit&oldid=' . $this->mNewid ); + $this->mPagetitle = htmlspecialchars( wfMsg( 'revisionasof', $timestamp ) ); + + $this->mNewtitle = "{$this->mPagetitle}" + . " (" . htmlspecialchars( wfMsg( 'editold' ) ) . ")"; } - $this->mNewUser = $this->mNewRev->getUserText(); - $this->mNewComment = $this->mNewRev->getComment(); - // Load the old revision object $this->mOldRev = false; if( $this->mOldid ) { @@ -462,11 +530,9 @@ CONTROL; $t = $wgLang->timeanddate( $this->mOldRev->getTimestamp(), true ); $oldLink = $this->mOldPage->escapeLocalUrl( 'oldid=' . $this->mOldid ); - $this->mOldtitle = "" . htmlspecialchars( wfMsg( 'revisionasof', $t ) ) . ''; - - - $this->mOldUser = $this->mOldRev->getUserText(); - $this->mOldComment = $this->mOldRev->getComment(); + $oldEdit = $this->mOldPage->escapeLocalUrl( 'action=edit&oldid=' . $this->mOldid ); + $this->mOldtitle = "" . htmlspecialchars( wfMsg( 'revisionasof', $t ) ) + . " (" . htmlspecialchars( wfMsg( 'editold' ) ) . ")"; } return true; @@ -487,6 +553,7 @@ CONTROL; return false; } if ( $this->mOldRev ) { + // FIXME: permission tests $this->mOldtext = $this->mOldRev->getText(); if ( $this->mOldtext === false ) { return false; @@ -530,7 +597,7 @@ define('USE_ASSERTS', function_exists('assert')); /** * @todo document - * @access private + * @private * @package MediaWiki * @subpackage DifferenceEngine */ @@ -554,7 +621,7 @@ class _DiffOp { /** * @todo document - * @access private + * @private * @package MediaWiki * @subpackage DifferenceEngine */ @@ -575,7 +642,7 @@ class _DiffOp_Copy extends _DiffOp { /** * @todo document - * @access private + * @private * @package MediaWiki * @subpackage DifferenceEngine */ @@ -594,7 +661,7 @@ class _DiffOp_Delete extends _DiffOp { /** * @todo document - * @access private + * @private * @package MediaWiki * @subpackage DifferenceEngine */ @@ -613,7 +680,7 @@ class _DiffOp_Add extends _DiffOp { /** * @todo document - * @access private + * @private * @package MediaWiki * @subpackage DifferenceEngine */ @@ -651,7 +718,7 @@ class _DiffOp_Change extends _DiffOp { * Line length limits for robustness added by Tim Starling, 2005-08-31 * * @author Geoffrey T. Dairiki, Tim Starling - * @access private + * @private * @package MediaWiki * @subpackage DifferenceEngine */ @@ -1071,7 +1138,7 @@ class _DiffEngine /** * Class representing a 'diff' between two sequences of strings. * @todo document - * @access private + * @private * @package MediaWiki * @subpackage DifferenceEngine */ @@ -1213,7 +1280,7 @@ class Diff /** * FIXME: bad name. * @todo document - * @access private + * @private * @package MediaWiki * @subpackage DifferenceEngine */ @@ -1277,7 +1344,7 @@ class MappedDiff extends Diff * It is intended that this class be customized via inheritance, * to obtain fancier outputs. * @todo document - * @access private + * @private * @package MediaWiki * @subpackage DifferenceEngine */ @@ -1444,7 +1511,7 @@ define('NBSP', ' '); // iso-8859-x non-breaking space. /** * @todo document - * @access private + * @private * @package MediaWiki * @subpackage DifferenceEngine */ @@ -1503,7 +1570,7 @@ class _HWLDF_WordAccumulator { /** * @todo document - * @access private + * @private * @package MediaWiki * @subpackage DifferenceEngine */ @@ -1589,7 +1656,7 @@ class WordLevelDiff extends MappedDiff /** * Wikipedia Table style diff formatter. * @todo document - * @access private + * @private * @package MediaWiki * @subpackage DifferenceEngine */ @@ -1601,16 +1668,12 @@ class TableDiffFormatter extends DiffFormatter } function _block_header( $xbeg, $xlen, $ybeg, $ylen ) { - $l1 = wfMsg( 'lineno', $xbeg ); - $l2 = wfMsg( 'lineno', $ybeg ); - - $r = ''.$l1."\n" . - ''.$l2."\n"; + $r = '\n" . + '\n"; return $r; } function _start_block( $header ) { - global $wgOut; echo $header; }