Merge "Add test for Message::params"
[lhc/web/wiklou.git] / includes / diff / DifferenceEngine.php
index b7601e9..414b9f8 100644 (file)
@@ -34,6 +34,7 @@ define( 'MW_DIFF_VERSION', '1.11a' );
  * @ingroup DifferenceEngine
  */
 class DifferenceEngine extends ContextSource {
+
        /** @var int */
        public $mOldid;
 
@@ -88,7 +89,7 @@ class DifferenceEngine extends ContextSource {
         */
        protected $mReducedLineNumbers = false;
 
-       /** @var string Link to action=markpatrolled  */
+       /** @var string Link to action=markpatrolled */
        protected $mMarkPatrolledLink = null;
 
        /** @var bool Show rev_deleted content if allowed */
@@ -97,14 +98,14 @@ class DifferenceEngine extends ContextSource {
 
        /**
         * Constructor
-        * @param $context IContextSource context to use, anything else will be ignored
-        * @param $old Integer old ID we want to show and diff with.
-        * @param $new String|int either revision ID or 'prev' or 'next'. Default: 0.
-        * @param $rcid Integer Deprecated, no longer used!
-        * @param $refreshCache boolean If set, refreshes the diff cache
-        * @param $unhide boolean If set, allow viewing deleted revs
+        * @param IContextSource $context context to use, anything else will be ignored
+        * @param int $old old ID we want to show and diff with.
+        * @param string|int $new either revision ID or 'prev' or 'next'. Default: 0.
+        * @param int $rcid Deprecated, no longer used!
+        * @param bool $refreshCache If set, refreshes the diff cache
+        * @param bool $unhide If set, allow viewing deleted revs
         */
-       function __construct( $context = null, $old = 0, $new = 0, $rcid = 0,
+       public function __construct( $context = null, $old = 0, $new = 0, $rcid = 0,
                $refreshCache = false, $unhide = false
        ) {
                if ( $context instanceof IContextSource ) {
@@ -120,16 +121,16 @@ class DifferenceEngine extends ContextSource {
        }
 
        /**
-        * @param $value bool
+        * @param bool $value
         */
-       function setReducedLineNumbers( $value = true ) {
+       public function setReducedLineNumbers( $value = true ) {
                $this->mReducedLineNumbers = $value;
        }
 
        /**
         * @return Language
         */
-       function getDiffLang() {
+       public function getDiffLang() {
                if ( $this->mDiffLang === null ) {
                        # Default language in which the diff text is written.
                        $this->mDiffLang = $this->getTitle()->getPageLanguage();
@@ -141,23 +142,23 @@ class DifferenceEngine extends ContextSource {
        /**
         * @return bool
         */
-       function wasCacheHit() {
+       public function wasCacheHit() {
                return $this->mCacheHit;
        }
 
        /**
         * @return int
         */
-       function getOldid() {
+       public function getOldid() {
                $this->loadRevisionIds();
 
                return $this->mOldid;
        }
 
        /**
-        * @return Bool|int
+        * @return bool|int
         */
-       function getNewid() {
+       public function getNewid() {
                $this->loadRevisionIds();
 
                return $this->mNewid;
@@ -167,10 +168,11 @@ class DifferenceEngine extends ContextSource {
         * Look up a special:Undelete link to the given deleted revision id,
         * as a workaround for being unable to load deleted diffs in currently.
         *
-        * @param int $id revision ID
+        * @param int $id Revision ID
+        *
         * @return mixed URL or false
         */
-       function deletedLink( $id ) {
+       public function deletedLink( $id ) {
                if ( $this->getUser()->isAllowed( 'deletedhistory' ) ) {
                        $dbr = wfGetDB( DB_SLAVE );
                        $row = $dbr->selectRow( 'archive', '*',
@@ -193,10 +195,11 @@ class DifferenceEngine extends ContextSource {
        /**
         * Build a wikitext link toward a deleted revision, if viewable.
         *
-        * @param int $id revision ID
-        * @return string wikitext fragment
+        * @param int $id Revision ID
+        *
+        * @return string Wikitext fragment
         */
-       function deletedIdMarker( $id ) {
+       public function deletedIdMarker( $id ) {
                $link = $this->deletedLink( $id );
                if ( $link ) {
                        return "[$link $id]";
@@ -225,7 +228,7 @@ class DifferenceEngine extends ContextSource {
                        $this->getLanguage()->listToText( $missing ), count( $missing ) );
        }
 
-       function showDiffPage( $diffOnly = false ) {
+       public function showDiffPage( $diffOnly = false ) {
                wfProfileIn( __METHOD__ );
 
                # Allow frames except in certain special cases
@@ -381,7 +384,7 @@ class DifferenceEngine extends ContextSource {
                $rdel = $this->revisionDeleteLink( $this->mNewRev );
 
                # Allow extensions to define their own revision tools
-               wfRunHooks( 'DiffRevisionTools', array( $this->mNewRev, &$revisionTools ) );
+               wfRunHooks( 'DiffRevisionTools', array( $this->mNewRev, &$revisionTools, $this->mOldRev ) );
                $formattedRevisionTools = array();
                // Put each one in parentheses (poor man's button)
                foreach ( $revisionTools as $tool ) {
@@ -451,7 +454,7 @@ class DifferenceEngine extends ContextSource {
         * Side effect: When the patrol link is build, this method will call
         * OutputPage::preventClickjacking() and load mediawiki.page.patrol.ajax.
         *
-        * @return String
+        * @return string
         */
        protected function markPatrolledLink() {
                global $wgUseRCPatrol, $wgEnableAPI, $wgEnableWriteAPI;
@@ -518,8 +521,9 @@ class DifferenceEngine extends ContextSource {
        }
 
        /**
-        * @param $rev Revision
-        * @return String
+        * @param Revision $rev
+        *
+        * @return string
         */
        protected function revisionDeleteLink( $rev ) {
                $link = Linker::getRevDeleteLink( $this->getUser(), $rev, $rev->getTitle() );
@@ -533,7 +537,7 @@ class DifferenceEngine extends ContextSource {
        /**
         * Show the new revision of the page.
         */
-       function renderNewRevision() {
+       public function renderNewRevision() {
                wfProfileIn( __METHOD__ );
                $out = $this->getOutput();
                $revHeader = $this->getRevisionHeader( $this->mNewRev );
@@ -616,7 +620,7 @@ class DifferenceEngine extends ContextSource {
         *
         * @return bool
         */
-       function showDiff( $otitle, $ntitle, $notice = '' ) {
+       public function showDiff( $otitle, $ntitle, $notice = '' ) {
                $diff = $this->getDiff( $otitle, $ntitle, $notice );
                if ( $diff === false ) {
                        $this->showMissingRevision();
@@ -633,7 +637,7 @@ class DifferenceEngine extends ContextSource {
        /**
         * Add style sheets and supporting JS for diff display.
         */
-       function showDiffStyle() {
+       public function showDiffStyle() {
                $this->getOutput()->addModuleStyles( 'mediawiki.action.history.diff' );
        }
 
@@ -643,9 +647,10 @@ class DifferenceEngine extends ContextSource {
         * @param string|bool $otitle Header for old text or false
         * @param string|bool $ntitle Header for new text or false
         * @param string $notice HTML between diff header and body
+        *
         * @return mixed
         */
-       function getDiff( $otitle, $ntitle, $notice = '' ) {
+       public function getDiff( $otitle, $ntitle, $notice = '' ) {
                $body = $this->getDiffBody();
                if ( $body === false ) {
                        return false;
@@ -747,9 +752,10 @@ class DifferenceEngine extends ContextSource {
        /**
         * Returns the cache key for diff body text or content.
         *
-        * @return string
         * @since 1.23
+        *
         * @throws MWException
+        * @return string
         */
        protected function getDiffBodyCacheKey() {
                if ( !$this->mOldid || !$this->mNewid ) {
@@ -771,14 +777,15 @@ class DifferenceEngine extends ContextSource {
         * perhaps taking advantage of the content's native form. This is required for all content
         * models that are not text based.
         *
-        * @param $old Content: old content
-        * @param $new Content: new content
+        * @since 1.21
+        *
+        * @param Content $old Old content
+        * @param Content $new New content
         *
+        * @throws MWException If old or new content is not an instance of TextContent.
         * @return bool|string
-        * @since 1.21
-        * @throws MWException if $old or $new are not instances of TextContent.
         */
-       function generateContentDiffBody( Content $old, Content $new ) {
+       public function generateContentDiffBody( Content $old, Content $new ) {
                if ( !( $old instanceof TextContent ) ) {
                        throw new MWException( "Diff not implemented for " . get_class( $old ) . "; " .
                                "override generateContentDiffBody to fix this." );
@@ -798,12 +805,13 @@ class DifferenceEngine extends ContextSource {
        /**
         * Generate a diff, no caching
         *
-        * @param string $otext old text, must be already segmented
-        * @param string $ntext new text, must be already segmented
+        * @param string $otext Old text, must be already segmented
+        * @param string $ntext New text, must be already segmented
+        *
         * @return bool|string
         * @deprecated since 1.21, use generateContentDiffBody() instead!
         */
-       function generateDiffBody( $otext, $ntext ) {
+       public function generateDiffBody( $otext, $ntext ) {
                ContentHandler::deprecated( __METHOD__, "1.21" );
 
                return $this->generateTextDiffBody( $otext, $ntext );
@@ -816,9 +824,10 @@ class DifferenceEngine extends ContextSource {
         *
         * @param string $otext old text, must be already segmented
         * @param string $ntext new text, must be already segmented
+        *
         * @return bool|string
         */
-       function generateTextDiffBody( $otext, $ntext ) {
+       public function generateTextDiffBody( $otext, $ntext ) {
                global $wgExternalDiffEngine, $wgContLang;
 
                wfProfileIn( __METHOD__ );
@@ -897,7 +906,7 @@ class DifferenceEngine extends ContextSource {
         * Generate a debug comment indicating diff generating time,
         * server node, and generator backend.
         *
-        * @param String $generator : What diff engine was used
+        * @param string $generator : What diff engine was used
         *
         * @return string
         */
@@ -920,11 +929,11 @@ class DifferenceEngine extends ContextSource {
        /**
         * Replace line numbers with the text in the user's language
         *
-        * @param String $text
+        * @param string $text
         *
         * @return mixed
         */
-       function localiseLineNumbers( $text ) {
+       public function localiseLineNumbers( $text ) {
                return preg_replace_callback(
                        '/<!--LINE (\d+)-->/',
                        array( &$this, 'localiseLineNumbersCb' ),
@@ -932,7 +941,7 @@ class DifferenceEngine extends ContextSource {
                );
        }
 
-       function localiseLineNumbersCb( $matches ) {
+       public function localiseLineNumbersCb( $matches ) {
                if ( $matches[1] === '1' && $this->mReducedLineNumbers ) {
                        return '';
                }
@@ -942,9 +951,10 @@ class DifferenceEngine extends ContextSource {
 
        /**
         * If there are revisions between the ones being compared, return a note saying so.
+        *
         * @return string
         */
-       function getMultiNotice() {
+       public function getMultiNotice() {
                if ( !is_object( $this->mOldRev ) || !is_object( $this->mNewRev ) ) {
                        return '';
                } elseif ( !$this->mOldPage->equals( $this->mNewPage ) ) {
@@ -963,7 +973,12 @@ class DifferenceEngine extends ContextSource {
                $nEdits = $this->mNewPage->countRevisionsBetween( $oldRev, $newRev );
                if ( $nEdits > 0 ) {
                        $limit = 100; // use diff-multi-manyusers if too many users
-                       $numUsers = $this->mNewPage->countAuthorsBetween( $oldRev, $newRev, $limit );
+                       $users = $this->mNewPage->getAuthorsBetween( $oldRev, $newRev, $limit );
+                       $numUsers = count( $users );
+
+                       if ( $numUsers == 1 && $users[0] == $newRev->getRawUserText() ) {
+                               $numUsers = 0; // special case to say "by the same user" instead of "by one other user"
+                       }
 
                        return self::intermediateEditsMsg( $nEdits, $numUsers, $limit );
                }
@@ -973,17 +988,21 @@ class DifferenceEngine extends ContextSource {
 
        /**
         * Get a notice about how many intermediate edits and users there are
-        * @param $numEdits int
-        * @param $numUsers int
-        * @param $limit int
+        *
+        * @param int $numEdits
+        * @param int $numUsers
+        * @param int $limit
+        *
         * @return string
         */
        public static function intermediateEditsMsg( $numEdits, $numUsers, $limit ) {
-               if ( $numUsers > $limit ) {
+               if ( $numUsers === 0 ) {
+                       $msg = 'diff-multi-sameuser';
+               } elseif ( $numUsers > $limit ) {
                        $msg = 'diff-multi-manyusers';
                        $numUsers = $limit;
                } else {
-                       $msg = 'diff-multi';
+                       $msg = 'diff-multi-otherusers';
                }
 
                return wfMessage( $msg )->numParams( $numEdits, $numUsers )->parse();
@@ -992,10 +1011,11 @@ class DifferenceEngine extends ContextSource {
        /**
         * Get a header for a specified revision.
         *
-        * @param $rev Revision
+        * @param Revision $rev
         * @param string $complete 'complete' to get the header wrapped depending
         *        the visibility of the revision and a link to edit the page.
-        * @return String HTML fragment
+        *
+        * @return string HTML fragment
         */
        protected function getRevisionHeader( Revision $rev, $complete = '' ) {
                $lang = $this->getLanguage();
@@ -1057,7 +1077,7 @@ class DifferenceEngine extends ContextSource {
         *
         * @return string
         */
-       function addHeader( $diff, $otitle, $ntitle, $multi = '', $notice = '' ) {
+       public function addHeader( $diff, $otitle, $ntitle, $multi = '', $notice = '' ) {
                // shared.css sets diff in interface language/dir, but the actual content
                // is often in a different language, mostly the page content language/dir
                $tableClass = 'diff diff-contentalign-' . htmlspecialchars( $this->getDiffLang()->alignStart() );
@@ -1106,7 +1126,7 @@ class DifferenceEngine extends ContextSource {
         * Use specified text instead of loading from the database
         * @deprecated since 1.21, use setContent() instead.
         */
-       function setText( $oldText, $newText ) {
+       public function setText( $oldText, $newText ) {
                ContentHandler::deprecated( __METHOD__, "1.21" );
 
                $oldContent = ContentHandler::makeContent( $oldText, $this->getTitle() );
@@ -1119,7 +1139,7 @@ class DifferenceEngine extends ContextSource {
         * Use specified text instead of loading from the database
         * @since 1.21
         */
-       function setContent( Content $oldContent, Content $newContent ) {
+       public function setContent( Content $oldContent, Content $newContent ) {
                $this->mOldContent = $oldContent;
                $this->mNewContent = $newContent;
 
@@ -1132,7 +1152,7 @@ class DifferenceEngine extends ContextSource {
         * (Defaults to page content language).
         * @since 1.19
         */
-       function setTextLanguage( $lang ) {
+       public function setTextLanguage( $lang ) {
                $this->mDiffLang = wfGetLangObj( $lang );
        }
 
@@ -1142,7 +1162,8 @@ class DifferenceEngine extends ContextSource {
         *
         * @param int $old Revision id, e.g. from URL parameter 'oldid'
         * @param int|string $new Revision id or strings 'next' or 'prev', e.g. from URL parameter 'diff'
-        * @return array Array of two revision ids, older first, later second.
+        *
+        * @return int[] List of two revision ids, older first, later second.
         *     Zero signifies invalid argument passed.
         *     false signifies that there is no previous/next revision ($old is the oldest/newest one).
         */
@@ -1201,7 +1222,7 @@ class DifferenceEngine extends ContextSource {
         *
         * @return bool
         */
-       function loadRevisionData() {
+       public function loadRevisionData() {
                if ( $this->mRevisionsLoaded ) {
                        return true;
                }
@@ -1281,7 +1302,7 @@ class DifferenceEngine extends ContextSource {
         *
         * @return bool
         */
-       function loadText() {
+       public function loadText() {
                if ( $this->mTextLoaded == 2 ) {
                        return true;
                }
@@ -1315,7 +1336,7 @@ class DifferenceEngine extends ContextSource {
         *
         * @return bool
         */
-       function loadNewText() {
+       public function loadNewText() {
                if ( $this->mTextLoaded >= 1 ) {
                        return true;
                }
@@ -1330,4 +1351,5 @@ class DifferenceEngine extends ContextSource {
 
                return true;
        }
+
 }