New feature: Recent Changes Patrol. All edits and new pages are now highlighted on
authorArne Heizmann <timwi@users.mediawiki.org>
Mon, 9 Aug 2004 05:38:11 +0000 (05:38 +0000)
committerArne Heizmann <timwi@users.mediawiki.org>
Mon, 9 Aug 2004 05:38:11 +0000 (05:38 +0000)
Special:Recentchanges and Special:Newpages until someone "marks" them as
"patrolled" using a special link. For new pages, this link appears at the bottom
of the article if the link in Recent Changes or New Pages is followed. For all
other edits, this link appears only in the diff and only if the diff link is
followed from Recent Changes. (Might need to add this functionality to Watchlist
too; haven't done that yet.)

includes/Article.php
includes/DifferenceEngine.php
includes/QueryPage.php
includes/RecentChange.php
includes/Skin.php
includes/SpecialNewpages.php
includes/SpecialRecentchanges.php
languages/Language.php
maintenance/archives/patch-rc-patrol.sql [new file with mode: 0755]
maintenance/tables.sql
stylesheets/monobook/main.css

index 319166c..d56a000 100644 (file)
@@ -224,7 +224,7 @@ class Article {
                          $action=='view'
                        ) {
                                wfProfileOut( $fname );
-                               return $this->mContent . "\n" .wfMsg('anontalkpagetext'); 
+                               return $this->mContent . "\n" .wfMsg('anontalkpagetext');
                        } else {
                                if($action=='edit') {
                                        if($section!='') {
@@ -324,12 +324,12 @@ class Article {
        function &getOldContentFields() {
                global $wgArticleOldContentFields;
                if ( !$wgArticleOldContentFields ) {
-                       $wgArticleOldContentFields = array( 'old_namespace','old_title','old_text','old_timestamp', 
+                       $wgArticleOldContentFields = array( 'old_namespace','old_title','old_text','old_timestamp',
                          'old_user','old_user_text','old_comment','old_flags' );
                }
                return $wgArticleOldContentFields;
        }
-                               
+
        # Load the revision (including cur_text) into this object
        function loadContent( $noredir = false )
        {
@@ -362,7 +362,7 @@ class Article {
                        if ( 0 == $id ) return;
 
                        $s = $dbr->getArray( 'cur', $this->getCurContentFields(), array( 'cur_id' => $id ), $fname );
-                       if ( $s === false ) { 
+                       if ( $s === false ) {
                                return;
                        }
 
@@ -448,7 +448,7 @@ class Article {
                        }
 
                        $s = $dbr->getArray( 'cur', $this->getCurContentFields(), array( 'cur_id' => $id ), $fname );
-                       if ( $s === false ) { 
+                       if ( $s === false ) {
                                return false;
                        }
 
@@ -481,7 +481,7 @@ class Article {
                        $this->mTitle->mRestrictionsLoaded = true;
                } else { # oldid set, retrieve historical version
                        $s = $dbr->getArray( 'old', $this->getOldContentFields(), array( 'old_id' => $oldid ) );
-                       if ( $s === false ) { 
+                       if ( $s === false ) {
                                return false;
                        }
                        $this->mContent = Article::getRevisionText( $s );
@@ -534,11 +534,11 @@ class Article {
        {
                global $wgOut;
                if ( -1 != $this->mUser ) return;
-               
+
                $fname = 'Article::loadLastEdit';
 
                $dbr =& wfGetDB( DB_SLAVE );
-               $s = $dbr->getArray( 'cur', 
+               $s = $dbr->getArray( 'cur',
                  array( 'cur_user','cur_user_text','cur_timestamp', 'cur_comment','cur_minor_edit' ),
                  array( 'cur_id' => $this->getID() ), $fname );
 
@@ -597,11 +597,11 @@ class Article {
                $user = $this->getUser();
 
                $sql = "SELECT old_user, old_user_text, user_real_name, MAX(old_timestamp) as timestamp
-                       FROM $oldTable LEFT JOIN $userTable ON old_user = user_id 
+                       FROM $oldTable LEFT JOIN $userTable ON old_user = user_id
                        WHERE old_namespace = $user
                        AND old_title = $encDBkey
                        AND old_user != $user
-                       GROUP BY old_user 
+                       GROUP BY old_user
                        ORDER BY timestamp DESC";
 
                 if ($limit > 0) {
@@ -624,15 +624,17 @@ class Article {
 
        function view()
        {
-               global $wgUser, $wgOut, $wgLang, $wgRequest, $wgMwRedir;
+               global $wgUser, $wgOut, $wgLang, $wgRequest, $wgMwRedir, $wgOnlySysopsCanPatrol;
                global $wgLinkCache, $IP, $wgEnableParserCache, $wgStylePath;
+               $sk = $wgUser->getSkin();
 
                $fname = 'Article::view';
                wfProfileIn( $fname );
 
-               # Get variables from query string :P
+               # Get variables from query string
                $oldid = $wgRequest->getVal( 'oldid' );
                $diff = $wgRequest->getVal( 'diff' );
+               $rcid = $wgRequest->getVal( 'rcid' );
 
                $wgOut->setArticleFlag( true );
                $wgOut->setRobotpolicy( 'index,follow' );
@@ -642,7 +644,7 @@ class Article {
 
                if ( !is_null( $diff ) ) {
                        $wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
-                       $de = new DifferenceEngine( intval($oldid), intval($diff) );
+                       $de = new DifferenceEngine( intval($oldid), intval($diff), intval($rcid) );
                        $de->showDiffPage();
                        wfProfileOut( $fname );
                        if( $diff == 0 ) {
@@ -715,7 +717,6 @@ class Article {
                                $wgOut->addHTML( '<pre>'.htmlspecialchars($this->mContent)."\n</pre>" );
                        } else if ( $rt = Title::newFromRedirect( $text ) ) {
                                # Display redirect
-                               $sk = $wgUser->getSkin();
                                $imageUrl = "$wgStylePath/images/redirect.png";
                                $targetUrl = $rt->escapeLocalURL();
                                $titleText = htmlspecialchars( $rt->getPrefixedText() );
@@ -732,6 +733,17 @@ class Article {
                }
                $wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
 
+               # If we have been passed an &rcid= parameter, we want to give the user a
+               # chance to mark this new article as patrolled.
+               if ( !is_null ( $rcid ) && $rcid != 0 && $wgUser->getID() != 0 &&
+                    ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
+               {
+                       $wgOut->addHTML( wfMsg ( 'markaspatrolledlink',
+                               $sk->makeKnownLinkObj ( $this->mTitle, wfMsg ( 'markaspatrolledtext' ),
+                                       "action=markpatrolled&rcid={$rcid}" )
+                        ) );
+               }
+
                # Add link titles as META keywords
                $wgOut->addMetaTags() ;
 
@@ -765,7 +777,7 @@ class Article {
                $rand = number_format( mt_rand() / mt_getrandmax(), 12, '.', '' );
                $dbw =& wfGetDB( DB_MASTER );
 
-               $cur_id = $dbw->nextSequenceValue( 'cur_cur_id_seq' ); 
+               $cur_id = $dbw->nextSequenceValue( 'cur_cur_id_seq' );
 
                $isminor = ( $isminor && $wgUser->getID() ) ? 1 : 0;
 
@@ -894,10 +906,10 @@ class Article {
                global $wgOut, $wgUser;
                global $wgDBtransactions, $wgMwRedir;
                global $wgUseSquid, $wgInternalServer;
-               
+
                $fname = 'Article::updateArticle';
                $good = true;
-               
+
                if ( $this->mMinorEdit ) { $me1 = 1; } else { $me1 = 0; }
                if ( $minor && $wgUser->getID() ) { $me2 = 1; } else { $me2 = 0; }
                if ( preg_match( "/^((" . $wgMwRedir->getBaseRegex() . ')[^\\n]+)/i', $text, $m ) ) {
@@ -911,15 +923,15 @@ class Article {
 
                # Update article, but only if changed.
 
-               # It's important that we either rollback or complete, otherwise an attacker could 
-               # overwrite cur entries by sending precisely timed user aborts. Random bored users 
+               # It's important that we either rollback or complete, otherwise an attacker could
+               # overwrite cur entries by sending precisely timed user aborts. Random bored users
                # could conceivably have the same effect, especially if cur is locked for long periods.
                if( $wgDBtransactions ) {
                        $dbw->query( 'BEGIN', $fname );
                } else {
                        $userAbort = ignore_user_abort( true );
                }
-               
+
                $oldtext = $this->getContent( true );
 
                if ( 0 != strcmp( $text, $oldtext ) ) {
@@ -929,24 +941,24 @@ class Article {
                        $won = wfInvertTimestamp( $now );
 
                        # First update the cur row
-                       $dbw->updateArray( 'cur', 
-                               array( /* SET */ 
+                       $dbw->updateArray( 'cur',
+                               array( /* SET */
                                        'cur_text' => $text,
                                        'cur_comment' => $summary,
-                                       'cur_minor_edit' => $me2, 
+                                       'cur_minor_edit' => $me2,
                                        'cur_user' => $wgUser->getID(),
                                        'cur_timestamp' => $now,
                                        'cur_user_text' => $wgUser->getName(),
-                                       'cur_is_redirect' => $redir, 
+                                       'cur_is_redirect' => $redir,
                                        'cur_is_new' => 0,
-                                       'cur_touched' => $now, 
+                                       'cur_touched' => $now,
                                        'inverse_timestamp' => $won
                                ), array( /* WHERE */
-                                       'cur_id' => $this->getID(), 
-                                       'cur_timestamp' => $this->getTimestamp() 
-                               ), $fname 
+                                       'cur_id' => $this->getID(),
+                                       'cur_timestamp' => $this->getTimestamp()
+                               ), $fname
                        );
-                       
+
                        if( $dbw->affectedRows() == 0 ) {
                                /* Belated edit conflict! Run away!! */
                                $good = false;
@@ -955,8 +967,8 @@ class Article {
 
                                # This overwrites $oldtext if revision compression is on
                                $flags = Article::compressRevisionText( $oldtext );
-                               
-                               $dbw->insertArray( 'old', 
+
+                               $dbw->insertArray( 'old',
                                        array(
                                                'old_id' => $dbw->nextSequenceValue( 'old_old_id_seq' ),
                                                'old_namespace' => $this->mTitle->getNamespace(),
@@ -969,13 +981,13 @@ class Article {
                                                'old_minor_edit' => $me1,
                                                'inverse_timestamp' => wfInvertTimestamp( $this->getTimestamp() ),
                                                'old_flags' => $flags,
-                                       ), $fname 
+                                       ), $fname
                                );
-                               
+
                                $oldid = $dbw->insertId();
 
                                $bot = (int)($wgUser->isBot() || $forceBot);
-                               RecentChange::notifyEdit( $now, $this->mTitle, $me2, $wgUser, $summary, 
+                               RecentChange::notifyEdit( $now, $this->mTitle, $me2, $wgUser, $summary,
                                        $oldid, $this->getTimestamp(), $bot );
                                Article::onArticleEdit( $this->mTitle );
                        }
@@ -1035,15 +1047,15 @@ class Article {
                $wgLinkCache = new LinkCache();
                # Select for update
                $wgLinkCache->forUpdate( true );
-               
+
                # Get old version of link table to allow incremental link updates
                $wgLinkCache->preFill( $this->mTitle );
                $wgLinkCache->clear();
-               
+
                # Switch on use of link cache in the skin
                $sk =& $wgUser->getSkin();
                $sk->postParseLinkColour( false );
-               
+
                # Now update the link cache by parsing the text
                $wgOut = new OutputPage();
                $wgOut->addWikiText( $text );
@@ -1056,7 +1068,7 @@ class Article {
        }
 
        # Validate article
-       
+
        function validate ()
        {
                global $wgOut ;
@@ -1068,11 +1080,35 @@ class Article {
                        return ;
                        }
                $v = new Validation ;
-               $v->validate_form ( $this->mTitle->getDBkey() ) ;               
+               $v->validate_form ( $this->mTitle->getDBkey() ) ;
        }
 
-       # Add this page to my watchlist
+       # Mark this particular edit as patrolled
+       function markpatrolled()
+       {
+               global $wgOut, $wgRequest, $wgOnlySysopsCanPatrol;
+               $wgOut->setRobotpolicy( 'noindex,follow' );
+               if( $wgOnlySysopsCanPatrol && !$wgUser->isSysop() )
+               {
+                       $wgOut->sysopRequired();
+                       return;
+               }
+               $rcid = $wgRequest->getVal( 'rcid' );
+               if ( !is_null ( $rcid ) )
+               {
+                       RecentChange::markPatrolled( $rcid );
+                       $wgOut->setPagetitle( wfMsg( 'markedaspatrolled' ) );
+                       $wgOut->addWikiText( wfMsg( 'markedaspatrolledtext' ) );
+                       $wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
+               }
+               else
+               {
+                       $wgOut->errorpage( 'markedaspatrollederror', 'markedaspatrollederrortext' );
+               }
+       }
 
+
+       # Add this page to my watchlist
        function watch( $add = true )
        {
                global $wgUser, $wgOut, $wgLang;
@@ -1137,13 +1173,13 @@ class Article {
 
                if ( $confirm ) {
                        $dbw =& wfGetDB( DB_MASTER );
-                       $dbw->updateArray( 'cur', 
+                       $dbw->updateArray( 'cur',
                                array( /* SET */
                                        'cur_touched' => wfTimestampNow(),
                                        'cur_restrictions' => (string)$limit
                                ), array( /* WHERE */
-                                       'cur_id' => $id 
-                               ), 'Article::protect' 
+                                       'cur_id' => $id
+                               ), 'Article::protect'
                        );
 
                        $log = new LogPage( wfMsg( 'protectlogpage' ), wfMsg( 'protectlogtext' ) );
@@ -1269,29 +1305,29 @@ class Article {
                $dbr =& wfGetDB( DB_SLAVE );
                $ns = $this->mTitle->getNamespace();
                $title = $this->mTitle->getDBkey();
-               $old = $dbr->getArray( 'old', 
-                       array( 'old_text', 'old_flags' ), 
+               $old = $dbr->getArray( 'old',
+                       array( 'old_text', 'old_flags' ),
                        array(
                                'old_namespace' => $ns,
                                'old_title' => $title,
-                       ), $fname, array( 'ORDER BY' => 'inverse_timestamp' ) 
+                       ), $fname, array( 'ORDER BY' => 'inverse_timestamp' )
                );
-               
+
                if( $old !== false && !$confirm ) {
                        $skin=$wgUser->getSkin();
                        $wgOut->addHTML('<b>'.wfMsg('historywarning'));
                        $wgOut->addHTML( $skin->historyLink() .'</b>');
                }
-               
+
                # Fetch cur_text
-               $s = $dbr->getArray( 'cur', 
-                       array( 'cur_text' ), 
-                       array( 
-                               'cur_namespace' => $ns, 
+               $s = $dbr->getArray( 'cur',
+                       array( 'cur_text' ),
+                       array(
+                               'cur_namespace' => $ns,
                                'cur_title' => $title,
                        ), $fname
                );
-               
+
                if( $s !== false ) {
                        # if this is a mini-text, we can paste part of it into the deletion reason
 
@@ -1426,7 +1462,7 @@ class Article {
 
                $fname = 'Article::doDeleteArticle';
                wfDebug( $fname."\n" );
-               
+
                $dbw =& wfGetDB( DB_MASTER );
                $ns = $this->mTitle->getNamespace();
                $t = $this->mTitle->getDBkey();
@@ -1466,8 +1502,8 @@ class Article {
                $recentchangesTable = $dbw->tableName( 'recentchanges' );
                $linksTable = $dbw->tableName( 'links' );
                $brokenlinksTable = $dbw->tableName( 'brokenlinks' );
-               
-               $dbw->insertSelect( 'archive', 'cur', 
+
+               $dbw->insertSelect( 'archive', 'cur',
                        array(
                                'ar_namespace' => 'cur_namespace',
                                'ar_title' => 'cur_title',
@@ -1481,9 +1517,9 @@ class Article {
                        ), array(
                                'cur_namespace' => $ns,
                                'cur_title' => $t,
-                       ), $fname 
+                       ), $fname
                );
-               
+
                $dbw->insertSelect( 'archive', 'old',
                        array(
                                'ar_namespace' => 'old_namespace',
@@ -1500,7 +1536,7 @@ class Article {
                                'old_title' => $t,
                        ), $fname
                );
-               
+
                # Now that it's safely backed up, delete it
 
                $dbw->delete( 'cur', array( 'cur_namespace' => $ns, 'cur_title' => $t ), $fname );
@@ -1520,7 +1556,7 @@ class Article {
                        $brokenLinks[] = array( 'bl_from' => $linkID, 'bl_to' => $t );
                }
                $dbw->insert( 'brokenlinks', $brokenLinks, $fname, 'IGNORE' );
-               
+
                # Delete live links
                $dbw->delete( 'links', array( 'l_to' => $id ) );
                $dbw->delete( 'links', array( 'l_from' => $id ) );
@@ -1543,7 +1579,7 @@ class Article {
        {
                global $wgUser, $wgLang, $wgOut, $wgRequest;
                $fname = "Article::rollback";
-               
+
                if ( ! $wgUser->isSysop() ) {
                        $wgOut->sysopRequired();
                        return;
@@ -1562,7 +1598,7 @@ class Article {
                $n = $this->mTitle->getNamespace();
 
                # Get the last editor, lock table exclusively
-               $s = $dbw->getArray( 'cur', 
+               $s = $dbw->getArray( 'cur',
                        array( 'cur_id','cur_user','cur_user_text','cur_comment' ),
                        array( 'cur_title' => $tt, 'cur_namespace' => $n ),
                        $fname, 'FOR UPDATE'
@@ -1592,10 +1628,10 @@ class Article {
                }
 
                # Get the last edit not by this guy
-               $s = $dbw->getArray( 'old', 
+               $s = $dbw->getArray( 'old',
                        array( 'old_text','old_user','old_user_text','old_timestamp','old_flags' ),
-                       array( 
-                               'old_namespace' => $n, 
+                       array(
+                               'old_namespace' => $n,
                                'old_title' => $tt,
                                "old_user <> {$uid} OR old_user_text <> '{$ut}'"
                        ), $fname, array( 'FOR UPDATE', 'USE INDEX' => 'name_title_timestamp' )
@@ -1609,13 +1645,13 @@ class Article {
 
                if ( $bot ) {
                        # Mark all reverted edits as bot
-                       $dbw->updateArray( 'recentchanges', 
-                               array( /* SET */ 
-                                       'rc_bot' => 1 
+                       $dbw->updateArray( 'recentchanges',
+                               array( /* SET */
+                                       'rc_bot' => 1
                                ), array( /* WHERE */
                                        'rc_user' => $uid,
                                        "rc_timestamp > '{$s->old_timestamp}'",
-                               ), $fname 
+                               ), $fname
                        );
                }
 
@@ -1655,7 +1691,7 @@ class Article {
        {
                global $wgDeferredUpdateList, $wgDBname, $wgMemc;
                global $wgMessageCache;
-               
+
                wfSeedRandom();
                if ( 0 == mt_rand( 0, 999 ) ) {
                        $dbw =& wfGetDB( DB_MASTER );
@@ -1762,7 +1798,7 @@ class Article {
 
                $id = $this->getID();
                $dbr =& wfGetDB( DB_SLAVE );
-               $s = $dbr->getArray( 'cur', array( 'cur_touched', 'cur_is_redirect' ), 
+               $s = $dbr->getArray( 'cur', array( 'cur_touched', 'cur_is_redirect' ),
                        array( 'cur_id' => $id ), $fname );
                if( $s !== false ) {
                        $this->mTouched = $s->cur_touched;
@@ -1798,7 +1834,7 @@ class Article {
                        ), array(
                                'cur_namespace' => $ns,
                                'cur_title' => $dbkey,
-                       ), $fname 
+                       ), $fname
                );
 
                # Use the affected row count to determine if the article is new
@@ -1841,14 +1877,14 @@ class Article {
                $curTable = $dbw->tableName( 'cur' );
                $hitcounterTable = $dbw->tableName( 'hitcounter' );
                $acchitsTable = $dbw->tableName( 'acchits' );
-               
+
                if( $wgHitcounterUpdateFreq <= 1 ){ //
                        $dbw->query( "UPDATE $curTable SET cur_counter = cur_counter + 1 WHERE cur_id = $id" );
                        return;
                }
 
                # Not important enough to warrant an error page in case of failure
-               $oldignore = $dbw->ignoreErrors( true ); 
+               $oldignore = $dbw->ignoreErrors( true );
 
                $dbw->query( "INSERT INTO $hitcounterTable (hc_id) VALUES ({$id})" );
 
@@ -1922,12 +1958,12 @@ class Article {
        {
                global $wgUser, $wgTitle, $wgOut, $wgLang, $wgAllowPageInfo;
                $fname = 'Article::info';
-       
+
                if ( !$wgAllowPageInfo ) {
                        $wgOut->errorpage( "nosuchaction", "nosuchactiontext" );
                        return;
                }
-               
+
                $dbr =& wfGetDB( DB_SLAVE );
 
                $basenamespace = $wgTitle->getNamespace() & (~1);
@@ -1957,7 +1993,7 @@ class Article {
                        $cur_author = $dbr->selectField( 'cur', 'cur_user_text', $cur_clause, $fname );
 
                        # find number of 'old' authors excluding 'cur' author
-                       $authors = $dbr->selectField( 'old', 'COUNT(DISTINCT old_user_text)', 
+                       $authors = $dbr->selectField( 'old', 'COUNT(DISTINCT old_user_text)',
                                $old_clause + array( 'old_user_text<>' . $dbr->addQuotes( $cur_author ) ), $fname ) + 1;
 
                        # now for the Talk page ...
@@ -1977,7 +2013,7 @@ class Article {
                        # number of authors
                        if ($exists > 0) {
                                $cur_author = $dbr->selectField( 'cur', 'cur_user_text', $cur_clause, $fname );
-                               $authors = $dbr->selectField( 'cur', 'COUNT(DISTINCT old_user_text)', 
+                               $authors = $dbr->selectField( 'cur', 'COUNT(DISTINCT old_user_text)',
                                        $old_clause + array( 'old_user_text<>' . $dbr->addQuotes( $cur_author ) ), $fname );
 
                                $wgOut->addHTML( "<li>" . wfMsg("numtalkauthors", $authors) . "</li></ul>" );
index 8b80c27..c2c3884 100644 (file)
@@ -8,19 +8,21 @@ class DifferenceEngine {
        /* private */ var $mOldUser, $mNewUser;
        /* private */ var $mOldComment, $mNewComment;
        /* private */ var $mOldPage, $mNewPage;
-       
-       function DifferenceEngine( $old, $new )
+       /* private */ var $mRcidMarkPatrolled;
+
+       function DifferenceEngine( $old, $new, $rcid = 0 )
        {
                $this->mOldid = $old;
                $this->mNewid = $new;
+               $this->mRcidMarkPatrolled = intval($rcid);  # force it to be an integer
        }
 
        function showDiffPage()
        {
-               global $wgUser, $wgTitle, $wgOut, $wgLang;
+               global $wgUser, $wgTitle, $wgOut, $wgLang, $wgOnlySysopsCanPatrol;
                $fname = "DifferenceEngine::showDiffPage";
                wfProfileIn( $fname );
-               
+
                $t = $wgTitle->getPrefixedText() . " (Diff: {$this->mOldid}, " .
                  "{$this->mNewid})";
                $mtext = wfMsg( "missingarticle", $t );
@@ -33,7 +35,7 @@ class DifferenceEngine {
                        return;
                }
                $wgOut->suppressQuickbar();
-               
+
                $oldTitle = $this->mOldPage->getPrefixedText();
                $newTitle = $this->mNewPage->getPrefixedText();
                if( $oldTitle == $newTitle ) {
@@ -43,7 +45,7 @@ class DifferenceEngine {
                }
                $wgOut->setSubtitle( wfMsg( "difference" ) );
                $wgOut->setRobotpolicy( "noindex,follow" );
-               
+
                if ( !( $this->mOldPage->userCanRead() && $this->mNewPage->userCanRead() ) ) {
                        $wgOut->loginToUse();
                        $wgOut->output();
@@ -55,11 +57,9 @@ class DifferenceEngine {
                $talk = $wgLang->getNsText( NS_TALK );
                $contribs = wfMsg( "contribslink" );
 
-
                $this->mOldComment = $sk->formatComment($this->mOldComment);
                $this->mNewComment = $sk->formatComment($this->mNewComment);
 
-
                $oldUserLink = $sk->makeLinkObj( Title::makeTitle( NS_USER, $this->mOldUser ), $this->mOldUser );
                $newUserLink = $sk->makeLinkObj( Title::makeTitle( NS_USER, $this->mNewUser ), $this->mNewUser );
                $oldUTLink = $sk->makeLinkObj( Title::makeTitle( NS_USER_TALK, $this->mOldUser ), $talk );
@@ -74,17 +74,25 @@ class DifferenceEngine {
                } else {
                        $rollback = "";
                }
+               if ( $this->mRcidMarkPatrolled != 0 && $wgUser->getID() != 0 &&
+                    ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
+               {
+                       $patrol = " [" . $sk->makeKnownLinkObj( $wgTitle, wfMsg( 'markaspatrolleddiff' ),
+                               "action=markpatrolled&rcid={$this->mRcidMarkPatrolled}" ) . "]";
+               } else {
+                       $patrol = "";
+               }
 
-               $oldHeader = "<strong>{$this->mOldtitle}</strong><br />$oldUserLink ($oldUTLink | $oldContribs)<br />". 
-                 $this->mOldComment;
-               $newHeader = "<strong>{$this->mNewtitle}</strong><br />$newUserLink ($newUTLink | $newContribs) $rollback<br />".
-                 $this->mNewComment;
+               $oldHeader = "<strong>{$this->mOldtitle}</strong><br />$oldUserLink " .
+                       "($oldUTLink | $oldContribs)<br />" . $this->mOldComment;
+               $newHeader = "<strong>{$this->mNewtitle}</strong><br />$newUserLink .
+                       "($newUTLink | $newContribs) $rollback<br />" . $this->mNewComment . $patrol;
 
                DifferenceEngine::showDiff( $this->mOldtext, $this->mNewtext,
                  $oldHeader, $newHeader );
                $wgOut->addHTML( "<hr /><h2>{$this->mNewtitle}</h2>\n" );
                $wgOut->addWikiText( $this->mNewtext );
-               
+
                wfProfileOut( $fname );
        }
 
@@ -125,17 +133,17 @@ cellpadding='0' cellspacing='4px' class='diff'><tr>
        {
                global $wgTitle, $wgOut, $wgLang;
                $fname = "DifferenceEngine::loadText";
-               
+
                $dbr =& wfGetDB( DB_SLAVE );
                if ( 0 == $this->mNewid || 0 == $this->mOldid ) {
                        $wgOut->setArticleFlag( true );
                        $this->mNewtitle = wfMsg( "currentrev" );
                        $id = $wgTitle->getArticleID();
-                       
-                       $s = $dbr->getArray( 'cur', array( 'cur_text', 'cur_user_text', 'cur_comment' ), 
+
+                       $s = $dbr->getArray( 'cur', array( 'cur_text', 'cur_user_text', 'cur_comment' ),
                                array( 'cur_id' => $id ), $fname );
-                       if ( $s === false ) { 
-                               return false; 
+                       if ( $s === false ) {
+                               return false;
                        }
 
                        $this->mNewPage = &$wgTitle;
@@ -146,8 +154,8 @@ cellpadding='0' cellspacing='4px' class='diff'><tr>
                        $s = $dbr->getArray( 'old', array( 'old_namespace','old_title','old_timestamp', 'old_text',
                                'old_flags','old_user_text','old_comment' ), array( 'old_id' => $this->mNewid ), $fname );
 
-                       if ( $s === false ) { 
-                               return false; 
+                       if ( $s === false ) {
+                               return false;
                        }
 
                        $this->mNewtext = Article::getRevisionText( $s );
@@ -159,22 +167,22 @@ cellpadding='0' cellspacing='4px' class='diff'><tr>
                        $this->mNewComment = $s->old_comment;
                }
                if ( 0 == $this->mOldid ) {
-                       $s = $dbr->getArray( 'old', 
-                               array( 'old_namespace','old_title','old_timestamp','old_text', 'old_flags','old_user_text','old_comment' ), 
+                       $s = $dbr->getArray( 'old',
+                               array( 'old_namespace','old_title','old_timestamp','old_text', 'old_flags','old_user_text','old_comment' ),
                                array( /* WHERE */
-                                       'old_namespace' => $this->mNewPage->getNamespace(), 
-                                       'old_title' => $this->mNewPage->getDBkey() 
+                                       'old_namespace' => $this->mNewPage->getNamespace(),
+                                       'old_title' => $this->mNewPage->getDBkey()
                                ), $fname, array( 'ORDER BY' => 'inverse_timestamp', 'USE INDEX' => 'name_title_timestamp' )
                        );
                } else {
-                       $s = $dbr->getArray( 'old', 
+                       $s = $dbr->getArray( 'old',
                                array( 'old_namespace','old_title','old_timestamp','old_text','old_flags','old_user_text','old_comment'),
-                               array( 'old_id' => $this->mOldid ), 
+                               array( 'old_id' => $this->mOldid ),
                                $fname
                        );
                }
-               if ( $s === false ) { 
-                       return false; 
+               if ( $s === false ) {
+                       return false;
                }
                $this->mOldPage = Title::MakeTitle( $s->old_namespace, $s->old_title );
                $this->mOldtext = Article::getRevisionText( $s );
@@ -183,7 +191,7 @@ cellpadding='0' cellspacing='4px' class='diff'><tr>
                $this->mOldtitle = wfMsg( "revisionasof", $t );
                $this->mOldUser = $s->old_user_text;
                $this->mOldComment = $s->old_comment;
-               
+
                return true;
        }
 }
@@ -200,7 +208,7 @@ class _DiffOp {
        var $type;
        var $orig;
        var $closing;
-       
+
        function reverse() {
                trigger_error("pure virtual", E_USER_ERROR);
        }
@@ -216,7 +224,7 @@ class _DiffOp {
 
 class _DiffOp_Copy extends _DiffOp {
        var $type = 'copy';
-       
+
        function _DiffOp_Copy ($orig, $closing = false) {
                if (!is_array($closing))
                        $closing = $orig;
@@ -231,7 +239,7 @@ class _DiffOp_Copy extends _DiffOp {
 
 class _DiffOp_Delete extends _DiffOp {
        var $type = 'delete';
-       
+
        function _DiffOp_Delete ($lines) {
                $this->orig = $lines;
                $this->closing = false;
@@ -244,7 +252,7 @@ class _DiffOp_Delete extends _DiffOp {
 
 class _DiffOp_Add extends _DiffOp {
        var $type = 'add';
-       
+
        function _DiffOp_Add ($lines) {
                $this->closing = $lines;
                $this->orig = false;
@@ -257,7 +265,7 @@ class _DiffOp_Add extends _DiffOp {
 
 class _DiffOp_Change extends _DiffOp {
        var $type = 'change';
-       
+
        function _DiffOp_Change ($orig, $closing) {
                $this->orig = $orig;
                $this->closing = $closing;
@@ -267,8 +275,8 @@ class _DiffOp_Change extends _DiffOp {
                return new _DiffOp_Change($this->closing, $this->orig);
        }
 }
-               
-         
+
+
 /**
  * Class used internally by Diff to actually compute the diffs.
  *
@@ -301,7 +309,7 @@ class _DiffEngine
                unset($this->seq);
                unset($this->in_seq);
                unset($this->lcs);
-                
+
                // Skip leading common lines.
                for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) {
                        if ($from_lines[$skip] != $to_lines[$skip])
@@ -315,7 +323,7 @@ class _DiffEngine
                                break;
                        $this->xchanged[$xi] = $this->ychanged[$yi] = false;
                }
-               
+
                // Ignore lines which do not exist in both files.
                for ($xi = $skip; $xi < $n_from - $endskip; $xi++)
                        $xhash[$from_lines[$xi]] = 1;
@@ -367,7 +375,7 @@ class _DiffEngine
                        $add = array();
                        while ($yi < $n_to && $this->ychanged[$yi])
                                $add[] = $to_lines[$yi++];
-                       
+
                        if ($delete && $add)
                                $edits[] = new _DiffOp_Change($delete, $add);
                        elseif ($delete)
@@ -377,7 +385,7 @@ class _DiffEngine
                }
                return $edits;
        }
-       
+
 
        /* Divide the Largest Common Subsequence (LCS) of the sequences
         * [XOFF, XLIM) and [YOFF, YLIM) into NCHUNKS approximately equally
@@ -397,7 +405,7 @@ class _DiffEngine
         */
        function _diag ($xoff, $xlim, $yoff, $ylim, $nchunks) {
        $flip = false;
-       
+
        if ($xlim - $xoff > $ylim - $yoff) {
                // Things seems faster (I'm not sure I understand why)
                        // when the shortest sequence in X.
@@ -417,7 +425,7 @@ class _DiffEngine
        $this->seq[0]= $yoff - 1;
        $this->in_seq = array();
        $ymids[0] = array();
-       
+
        $numer = $xlim - $xoff + $nchunks - 1;
        $x = $xoff;
        for ($chunk = 0; $chunk < $nchunks; $chunk++) {
@@ -584,14 +592,14 @@ class _DiffEngine
                 */
                while ($j < $other_len && $other_changed[$j])
                $j++;
-               
+
                while ($i < $len && ! $changed[$i]) {
                USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]');
                $i++; $j++;
                while ($j < $other_len && $other_changed[$j])
                        $j++;
                        }
-                       
+
                if ($i == $len)
                break;
 
@@ -673,7 +681,7 @@ class _DiffEngine
 /**
  * Class representing a 'diff' between two sequences of strings.
  */
-class Diff 
+class Diff
 {
        var $edits;
 
@@ -722,7 +730,7 @@ class Diff
                }
                return true;
        }
-  
+
        /**
         * Compute the length of the Longest Common Subsequence (LCS).
         *
@@ -749,7 +757,7 @@ class Diff
         */
        function orig() {
                $lines = array();
-               
+
                foreach ($this->edits as $edit) {
                        if ($edit->orig)
                                array_splice($lines, sizeof($lines), 0, $edit->orig);
@@ -767,7 +775,7 @@ class Diff
         */
        function closing() {
                $lines = array();
-               
+
                foreach ($this->edits as $edit) {
                        if ($edit->closing)
                                array_splice($lines, sizeof($lines), 0, $edit->closing);
@@ -776,7 +784,7 @@ class Diff
        }
 
        /**
-        * Check a Diff for validity. 
+        * Check a Diff for validity.
         *
         * This is here only for debugging purposes.
         */
@@ -804,7 +812,7 @@ class Diff
                trigger_error("Diff okay: LCS = $lcs", E_USER_NOTICE);
        }
 }
-                       
+
 /**
  * FIXME: bad name.
  */
@@ -839,7 +847,7 @@ extends Diff
 
                assert(sizeof($from_lines) == sizeof($mapped_from_lines));
                assert(sizeof($to_lines) == sizeof($mapped_to_lines));
-               
+
                $this->Diff($mapped_from_lines, $mapped_to_lines);
 
                $xi = $yi = 0;
@@ -849,7 +857,7 @@ extends Diff
                                $orig = array_slice($from_lines, $xi, sizeof($orig));
                                $xi += sizeof($orig);
                        }
-                       
+
                        $closing = &$this->edits[$i]->closing;
                        if (is_array($closing)) {
                                $closing = array_slice($to_lines, $yi, sizeof($closing));
@@ -981,11 +989,11 @@ class DiffFormatter
 
                return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
        }
-       
+
        function _start_block($header) {
                echo $header;
        }
-       
+
        function _end_block() {
        }
 
@@ -993,7 +1001,7 @@ class DiffFormatter
                foreach ($lines as $line)
                        echo "$prefix $line\n";
        }
-       
+
        function _context($lines) {
                $this->_lines($lines);
        }
@@ -1015,7 +1023,7 @@ class DiffFormatter
 
 /**
  *     Additions by Axel Boldt follow, partly taken from diff.php, phpwiki-1.3.3
- * 
+ *
  */
 
 define('NBSP', '&#160;');                      // iso-8859-x non-breaking space.
@@ -1030,7 +1038,7 @@ class _HWLDF_WordAccumulator {
 
        function _flushGroup ($new_tag) {
                if ($this->_group !== '') {
-         if ($this->_tag == 'mark') 
+         if ($this->_tag == 'mark')
                        $this->_line .= '<span class="diffchange">'.$this->_group.'</span>';
          else
                $this->_line .= $this->_group;
@@ -1038,14 +1046,14 @@ class _HWLDF_WordAccumulator {
                $this->_group = '';
                $this->_tag = $new_tag;
        }
-       
+
        function _flushLine ($new_tag) {
                $this->_flushGroup($new_tag);
                if ($this->_line != '')
                        $this->_lines[] = $this->_line;
                $this->_line = '';
        }
-                               
+
        function addWords ($words, $tag = '') {
                if ($tag != $this->_tag)
                        $this->_flushGroup($tag);
@@ -1076,7 +1084,7 @@ class WordLevelDiff extends MappedDiff
                list ($orig_words, $orig_stripped) = $this->_split($orig_lines);
                list ($closing_words, $closing_stripped) = $this->_split($closing_lines);
 
-               
+
                $this->MappedDiff($orig_words, $closing_words,
                                                  $orig_stripped, $closing_stripped);
        }
@@ -1094,7 +1102,7 @@ class WordLevelDiff extends MappedDiff
 
        function orig () {
                $orig = new _HWLDF_WordAccumulator;
-               
+
                foreach ($this->edits as $edit) {
                        if ($edit->type == 'copy')
                                $orig->addWords($edit->orig);
@@ -1106,7 +1114,7 @@ class WordLevelDiff extends MappedDiff
 
        function closing () {
                $closing = new _HWLDF_WordAccumulator;
-               
+
                foreach ($this->edits as $edit) {
                        if ($edit->type == 'copy')
                                $closing->addWords($edit->closing);
@@ -1119,7 +1127,7 @@ class WordLevelDiff extends MappedDiff
 
 /**
  *     Wikipedia Table style diff formatter.
- * 
+ *
  */
 class TableDiffFormatter extends DiffFormatter
 {
@@ -1127,7 +1135,7 @@ class TableDiffFormatter extends DiffFormatter
                $this->leading_context_lines = 2;
                $this->trailing_context_lines = 2;
        }
-       
+
        function _block_header( $xbeg, $xlen, $ybeg, $ylen ) {
                $l1 = wfMsg( "lineno", $xbeg );
                $l2 = wfMsg( "lineno", $ybeg );
@@ -1165,7 +1173,7 @@ class TableDiffFormatter extends DiffFormatter
        function contextLine( $line ) {
                return '<td> </td><td class="diff-context">'.$line.'</td>';
        }
-       
+
        function _added($lines) {
                global $wgOut;
                foreach ($lines as $line) {
index e6173ad..fb5dea8 100644 (file)
@@ -27,7 +27,7 @@ class QueryPage {
        function getSQL() {
                return "SELECT 'sample' as type, 0 as namespace, 'Sample result' as title, 42 as value";
        }
-       
+
        # Override to sort by increasing values
        function sortDescending() {
                return true;
@@ -55,10 +55,10 @@ class QueryPage {
        function formatResult( $skin, $result ) {
                return "";
        }
-       
+
        # This is the actual workhorse. It does everything needed to make a
        # real, honest-to-gosh query page.
-       
+
        function doQuery( $offset, $limit ) {
                global $wgUser, $wgOut, $wgLang, $wgRequest;
                global $wgMiserMode;
@@ -72,17 +72,17 @@ class QueryPage {
 
                $wgOut->setSyndicated( true );
                $res = false;
-               
+
                if ( $this->isExpensive() ) {
                        $recache = $wgRequest->getBool( "recache" );
                        if( $recache ) {
                                # Clear out any old cached data
                                $dbw->delete( 'querycache', array( 'qc_type' => $sname ), $fname );
-                               
+
                                # Do query on the (possibly out of date) slave server
                                $maxstored = 1000;
                                $res = $dbr->query( $sql . $this->getOrderLimit( 0, $maxstored ), $fname );
-                               
+
                                # Fetch results
                                $insertSql = "INSERT INTO $querycache (qc_type,qc_namespace,qc_title,qc_value) VALUES ";
                                $first = true;
@@ -91,7 +91,7 @@ class QueryPage {
                                                $first = false;
                                        } else {
                                                $insertSql .= ",";
-                                       } 
+                                       }
                                        $insertSql .= "(" .
                                                $dbw->addQuotes( $row->type ) . "," .
                                                $dbw->addQuotes( $row->namespace ) . "," .
@@ -125,8 +125,8 @@ class QueryPage {
                        $res = $dbr->query( $sql . $this->getOrderLimit( $offset, $limit ), $fname );
                        $num = $dbr->numRows($res);
                }
-               
-               
+
+
                $sk = $wgUser->getSkin( );
 
                $top = wfShowingResults( $offset, $num);
@@ -134,22 +134,23 @@ class QueryPage {
 
                # often disable 'next' link when we reach the end
                if($num < $limit) { $atend = true; } else { $atend = false; }
-               
+
                $sl = wfViewPrevNext( $offset, $limit , $wgLang->specialPage( $sname ), "" ,$atend );
                $wgOut->addHTML( "<br />{$sl}</p>\n" );
 
-               $s = "<ol start='" . ( $offset + 1 ) . "'>";
+               $s = "<ol start='" . ( $offset + 1 ) . "' class='special'>";
                # Only read at most $num rows, because $res may contain the whole 1000
                for ( $i = 0; $i < $num && $obj = $dbr->fetchObject( $res ); $i++ ) {
                        $format = $this->formatResult( $sk, $obj );
-                       $s .= "<li>{$format}</li>\n";
+                       $attr = ( $obj->usepatrol && $obj->patrolled == 0 ) ? ' class="not_patrolled"' : '';
+                       $s .= "<li{$attr}>{$format}</li>\n";
                }
                $dbr->freeResult( $res );
                $s .= "</ol>";
                $wgOut->addHTML( $s );
                $wgOut->addHTML( "<p>{$sl}</p>\n" );
        }
-       
+
        # Similar to above, but packaging in a syndicated feed instead of a web page
        function doFeed( $class = "" ) {
                global $wgFeedClasses;
@@ -160,7 +161,7 @@ class QueryPage {
                                $this->feedDesc(),
                                $this->feedUrl() );
                        $feed->outHeader();
-                       
+
                        $dbr =& wfGetDB( DB_SLAVE );
                        $sql = $this->getSQL() . $this->getOrderLimit( 0, 50 );
                        $res = $dbr->query( $sql, "QueryPage::doFeed" );
@@ -189,13 +190,13 @@ class QueryPage {
                        } else {
                                $date = "";
                        }
-                       
+
                        $comments = "";
                        if( $title ) {
                                $talkpage = $title->getTalkPage();
                                $comments = $talkpage->getFullURL();
                        }
-                       
+
                        return new FeedItem(
                                $title->getText(),
                                $this->feedItemDesc( $row ),
@@ -207,7 +208,7 @@ class QueryPage {
                        return NULL;
                }
        }
-       
+
        function feedItemDesc( $row ) {
                $text = "";
                if( isset( $row->comment ) ) {
@@ -215,14 +216,14 @@ class QueryPage {
                } else {
                        $text = "";
                }
-               
+
                if( isset( $row->text ) ) {
                        $text = "<p>" . htmlspecialchars( wfMsg( "summary" ) ) . ": " . $text . "</p>\n<hr />\n<div>" .
                                nl2br( htmlspecialchars( $row->text ) ) . "</div>";;
                }
                return $text;
        }
-       
+
        function feedItemAuthor( $row ) {
                if( isset( $row->user_text ) ) {
                        return $row->user_text;
@@ -230,18 +231,18 @@ class QueryPage {
                        return "";
                }
        }
-       
+
        function feedTitle() {
                global $wgLanguageCode, $wgSitename, $wgLang;
                $page = SpecialPage::getPage( $this->getName() );
                $desc = $page->getDescription();
                return "$wgSitename - $desc [$wgLanguageCode]";
        }
-       
+
        function feedDesc() {
                return wfMsg( "fromwikipedia" );
        }
-       
+
        function feedUrl() {
                global $wgLang;
                $title = Title::MakeTitle( NS_SPECIAL, $this->getName() );
index eb3aeb6..dd0370e 100644 (file)
@@ -10,11 +10,12 @@ define( "RC_MOVE_OVER_REDIRECT", 4);
 
 /*
 mAttributes:
+       rc_id           id of the row in the recentchanges table
        rc_timestamp    time the entry was made
        rc_cur_time     timestamp on the cur row
        rc_namespace    namespace #
        rc_title        non-prefixed db key
-       rc_type          is new entry, used to determine whether updating is necessary
+       rc_type         is new entry, used to determine whether updating is necessary
        rc_minor        is minor
        rc_cur_id       id of associated cur entry
        rc_user         user id who made the entry
@@ -25,6 +26,7 @@ mAttributes:
        rc_bot          is bot, hidden
        rc_ip           IP address of the user in dotted quad notation
        rc_new          obsolete, use rc_type==RC_NEW
+       rc_patrolled    boolean whether or not someone has marked this edit as patrolled
 
 mExtra:
        prefixedDBkey   prefixed db key, used by external app via msg queue
@@ -38,14 +40,14 @@ class RecentChange
        var $mTitle = false, $mMovedToTitle = false;
 
        # Factory methods
-       
-       /* static */ function newFromRow( $row ) 
+
+       /* static */ function newFromRow( $row )
        {
                $rc = new RecentChange;
                $rc->loadFromRow( $row );
                return $rc;
        }
-       
+
        /* static */ function newFromCurRow( $row )
        {
                $rc = new RecentChange;
@@ -54,17 +56,17 @@ class RecentChange
        }
 
        # Accessors
-       
-       function setAttribs( $attribs ) 
+
+       function setAttribs( $attribs )
        {
                $this->mAttribs = $attribs;
        }
-       
+
        function setExtra( $extra )
        {
                $this->mExtra = $extra;
        }
-       
+
        function getTitle()
        {
                if ( $this->mTitle === false ) {
@@ -76,31 +78,31 @@ class RecentChange
        function getMovedToTitle()
        {
                if ( $this->mMovedToTitle === false ) {
-                       $this->mMovedToTitle = Title::makeTitle( $this->mAttribs['rc_moved_to_ns'], 
+                       $this->mMovedToTitle = Title::makeTitle( $this->mAttribs['rc_moved_to_ns'],
                                $this->mAttribs['rc_moved_to_title'] );
                }
                return $this->mMovedToTitle;
        }
 
        # Writes the data in this object to the database
-       function save() 
+       function save()
        {
                global $wgUseRCQueue, $wgRCQueueID, $wgLocalInterwiki, $wgPutIPinRC;
                $fname = "RecentChange::save";
-               
+
                $dbw =& wfGetDB( DB_MASTER );
                if ( !is_array($this->mExtra) ) {
                        $this->mExtra = array();
                }
                $this->mExtra['lang'] = $wgLocalInterwiki;
-               
+
                if ( !$wgPutIPinRC ) {
                        $this->mAttribs['rc_ip'] = '';
                }
-               
+
                # Insert new row
                $dbw->insertArray( "recentchanges", $this->mAttribs, $fname );
-               
+
                # Update old rows, if necessary
                if ( $this->mAttribs['rc_type'] == RC_EDIT ) {
                        $oldid = $this->mAttribs['rc_last_oldid'];
@@ -109,12 +111,12 @@ class RecentChange
                        $lastTime = $this->mExtra['lastTimestamp'];
                        $now = $this->mAttribs['rc_timestamp'];
                        $curId = $this->mAttribs['rc_cur_id'];
-                       
+
                        # Update rc_this_oldid for the entries which were current
-                       $dbw->updateArray( 'recentchanges', 
+                       $dbw->updateArray( 'recentchanges',
                                array( /* SET */
                                        'rc_this_oldid' => $oldid
-                               ), array( /* WHERE */ 
+                               ), array( /* WHERE */
                                        'rc_namespace' => $ns,
                                        'rc_title' => $title,
                                        'rc_timestamp' => $lastTime
@@ -122,24 +124,40 @@ class RecentChange
                        );
 
                        # Update rc_cur_time
-                       $dbw->updateArray( 'recentchanges', array( 'rc_cur_time' => $now ), 
+                       $dbw->updateArray( 'recentchanges', array( 'rc_cur_time' => $now ),
                                array( 'rc_cur_id' => $curId ), $fname );
                }
-               
+
                # Notify external application
                if ( $wgUseRCQueue ) {
                        $queue = msg_get_queue( $wgRCQueueID );
-                       if (!msg_send( $queue, array_merge( $this->mAttribs, 1, $this->mExtra ), 
-                               true, false, $error )) 
+                       if (!msg_send( $queue, array_merge( $this->mAttribs, 1, $this->mExtra ),
+                               true, false, $error ))
                        {
                                wfDebug( "Error sending message to RC queue, code $error\n" );
                        }
                }
        }
-       
+
+       # Marks a certain row as patrolled
+       function markPatrolled( $rcid )
+       {
+               $fname = "RecentChange::markPatrolled";
+
+               $dbw =& wfGetDB( DB_MASTER );
+
+               $dbw->updateArray( 'recentchanges',
+                       array( /* SET */
+                               'rc_patrolled' => 1
+                       ), array( /* WHERE */
+                               'rc_id' => $rcid
+                       ), $fname
+               );
+       }
+
        # Makes an entry in the database corresponding to an edit
-       /*static*/ function notifyEdit( $timestamp, &$title, $minor, &$user, $comment, 
-               $oldId, $lastTimestamp, $bot = "default", $ip = '' ) 
+       /*static*/ function notifyEdit( $timestamp, &$title, $minor, &$user, $comment,
+               $oldId, $lastTimestamp, $bot = "default", $ip = '' )
        {
                if ( $bot == "default " ) {
                        $bot = $user->isBot();
@@ -149,7 +167,7 @@ class RecentChange
                        global $wgIP;
                        $ip = empty( $wgIP ) ? '' : $wgIP;
                }
-               
+
                $rc = new RecentChange;
                $rc->mAttribs = array(
                        'rc_timestamp'  => $timestamp,
@@ -170,14 +188,14 @@ class RecentChange
                        'rc_ip' => $ip,
                        'rc_new'        => 0 # obsolete
                );
-               
+
                $rc->mExtra =  array(
                        'prefixedDBkey' => $title->getPrefixedDBkey(),
                        'lastTimestamp' => $lastTimestamp
                );
                $rc->save();
        }
-       
+
        # Makes an entry in the database corresponding to page creation
        # Note: the title object must be loaded with the new id using resetArticleID()
        /*static*/ function notifyNew( $timestamp, &$title, $minor, &$user, $comment, $bot = "default", $ip='' )
@@ -210,14 +228,14 @@ class RecentChange
                        'rc_ip'             => $ip,
                        'rc_new'        => 1 # obsolete
                );
-               
+
                $rc->mExtra =  array(
                        'prefixedDBkey' => $title->getPrefixedDBkey(),
                        'lastTimestamp' => 0
                );
                $rc->save();
        }
-       
+
        # Makes an entry in the database corresponding to a rename
        /*static*/ function notifyMove( $timestamp, &$oldTitle, &$newTitle, &$user, $comment, $ip='', $overRedir = false )
        {
@@ -243,9 +261,10 @@ class RecentChange
                        'rc_moved_to_ns'        => $newTitle->getNamespace(),
                        'rc_moved_to_title'     => $newTitle->getDBkey(),
                        'rc_ip'         => $ip,
-                       'rc_new'        => 0 # obsolete
+                       'rc_new'        => 0, # obsolete
+                       'rc_patrolled' => 1
                );
-               
+
                $rc->mExtra = array(
                        'prefixedDBkey' => $oldTitle->getPrefixedDBkey(),
                        'lastTimestamp' => 0,
@@ -253,7 +272,7 @@ class RecentChange
                );
                $rc->save();
        }
-       
+
        /* static */ function notifyMoveToNew( $timestamp, &$oldTitle, &$newTitle, &$user, $comment, $ip='' ) {
                RecentChange::notifyMove( $timestamp, $oldTitle, $newTitle, $user, $comment, $ip, false );
        }
@@ -262,7 +281,7 @@ class RecentChange
                RecentChange::notifyMove( $timestamp, $oldTitle, $newTitle, $user, $comment, $ip='', true );
        }
 
-       # A log entry is different to an edit in that previous revisions are 
+       # A log entry is different to an edit in that previous revisions are
        # not kept
        /*static*/ function notifyLog( $timestamp, &$title, &$user, $comment, $ip='' )
        {
@@ -288,6 +307,7 @@ class RecentChange
                        'rc_moved_to_ns'        => 0,
                        'rc_moved_to_title'     => '',
                        'rc_ip' => $ip,
+                       'rc_patrolled' => 1,
                        'rc_new'        => 0 # obsolete
                );
                $rc->mExtra =  array(
@@ -303,7 +323,7 @@ class RecentChange
                $this->mAttribs = get_object_vars( $row );
                $this->mExtra = array();
        }
-       
+
        # Makes a pseudo-RC entry from a cur row, for watchlists and things
        function loadFromCurRow( $row )
        {
index 17ddf6e..fcc82a2 100644 (file)
@@ -439,13 +439,13 @@ class Skin {
                $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
                return $printfooter . $this->doAfterContent();
        }
-       
+
        function printSource() {
                global $wgTitle;
                $url = htmlspecialchars( $wgTitle->getFullURL() );
                return wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" );
        }
-       
+
        function printFooter() {
                return "<p>" .  $this->printSource() .
                        "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
@@ -2265,7 +2265,9 @@ class Skin {
                        $this->lastdate = $date;
                        $this->rclistOpen = true;
                }
-               $s .= '<li> ';
+
+               # If this edit has not yet been patrolled, make it stick out
+               $s .= ( $rc_patrolled ) ? '<li> ' : '<li class="not_patrolled"> ';
 
                if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
                        # Diff
@@ -2275,11 +2277,7 @@ class Skin {
                                ') . . ';
 
                        # "[[x]] moved to [[y]]"
-                       if ( $rc_type == RC_MOVE ) {
-                               $msg = '1movedto2';
-                       } else {
-                               $msg = '1movedto2_redir';
-                       }
+                       $msg = ( $rc_type == RC_MOVE ) ? '1movedto2' : '1movedto2_redir';
                        $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
                                $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
                } else {
@@ -2287,8 +2285,14 @@ class Skin {
                        if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) {
                                $diffLink = wfMsg( 'diff' );
                        } else {
+                               if ( $rc_patrolled == 0 && $wgUser->getID() != 0 &&
+                                    ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
+                                       $rcidparam = "&rcid={$rc_id}";
+                               else
+                                       $rcidparam = "";
                                $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
-                                 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid  ,'' ,'' , ' tabindex="'.$rc->counter.'"');
+                                 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
+                                 '', '', ' tabindex="'.$rc->counter.'"');
                        }
                        $s .= '('.$diffLink.') (';
 
@@ -2303,7 +2307,13 @@ class Skin {
                        if ( $rc_type == RC_NEW ) { $s .= '<strong>'.$N.'</strong>'; }
 
                        # Article link
-                       $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
+                       # If it's a new article, there is no diff link, but if it hasn't been
+                       # patrolled yet, we need to give users a way to do so
+                       if ( $rc_type == RC_NEW && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
+                            ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
+                               $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
+                       else
+                               $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
 
                        if ( $watched ) {
                                $articleLink = '<strong>'.$articleLink.'</strong>';
@@ -2370,7 +2380,7 @@ class Skin {
 
                # If it's a new day, add the headline and flush the cache
                $date = $wgLang->date( $rc_timestamp, true);
-               $ret = '' ;
+               $ret = '';
                if ( $date != $this->lastdate ) {
                        # Process current cache
                        $ret = $this->recentChangesBlock () ;
@@ -2381,11 +2391,7 @@ class Skin {
 
                # Make article link
                if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
-                       if ( $rc_type == RC_MOVE ) {
-                               $msg = "1movedto2";
-                       } else {
-                               $msg = "1movedto2_redir";
-                       }
+                       $msg = ( $rc_type == RC_MOVE ) ? "1movedto2" : "1movedto2_redir";
                        $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
                          $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
                } else {
@@ -2418,7 +2424,7 @@ class Skin {
                }
 
                # Make user link (or user contributions for unregistered users)
-               if ( 0 == $rc_user ) {
+               if ( $rc_user == 0 ) {
                        $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
                        $rc_user_text, 'target=' . $rc_user_text );
                } else {
@@ -2426,12 +2432,11 @@ class Skin {
                          Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
                }
 
-               $rc->userlink = $userLink ;
-               $rc->lastlink = $lastLink ;
-               $rc->curlink = $curLink ;
+               $rc->userlink = $userLink;
+               $rc->lastlink = $lastLink;
+               $rc->curlink  = $curLink;
                $rc->difflink = $diffLink;
 
-
                # Make user talk link
                $utns=$wgLang->getNsText(NS_USER_TALK);
                $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
index 802e9f9..6f5fedb 100644 (file)
@@ -7,7 +7,7 @@ class NewPagesPage extends QueryPage {
        function getName() {
                return "Newpages";
        }
-       
+
        function isExpensive() {
                # Indexed on RC, and will *not* work with querycache yet.
                return false;
@@ -15,6 +15,8 @@ class NewPagesPage extends QueryPage {
        }
 
        function getSQL() {
+               global $wgUser, $wgOnlySysopsCanPatrol;
+               $usepatrol = ( $wgUser->getID() != 0 && ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) ) ? 1 : 0;
                $dbr =& wfGetDB( DB_SLAVE );
                extract( $dbr->tableNames( 'recentchanges', 'cur' ) );
 
@@ -23,11 +25,13 @@ class NewPagesPage extends QueryPage {
                                rc_namespace AS namespace,
                                rc_title AS title,
                                rc_cur_id AS value,
-                               
                                rc_user AS user,
                                rc_user_text AS user_text,
                                rc_comment as comment,
                                rc_timestamp AS timestamp,
+                               '{$usepatrol}' as usepatrol,
+                               rc_patrolled AS patrolled,
+                               rc_id AS rcid,
                                length(cur_text) as length,
                                cur_text as text
                        FROM $recentchanges,$cur
@@ -36,7 +40,7 @@ class NewPagesPage extends QueryPage {
        }
 
        function formatResult( $skin, $result ) {
-               global $wgLang;
+               global $wgLang, $wgUser, $wgOnlySysopsCanPatrol;
                $u = $result->user;
                $ut = $result->user_text;
 
@@ -51,7 +55,15 @@ class NewPagesPage extends QueryPage {
                }
 
                $d = $wgLang->timeanddate( $result->timestamp, true );
-               $link = $skin->makeKnownLink( $result->title, "" );
+
+               # If it's a new article, there is no diff link, but if it hasn't been
+               # patrolled yet, we need to give users a way to do so
+               if ( $result->usepatrol && $result->patrolled == 0 && $wgUser->getID() != 0 &&
+                    ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
+                       $link = $skin->makeKnownLink( $result->title, '', "rcid={$result->rcid}" );
+               else
+                       $link = $skin->makeKnownLink( $result->title, '' );
+
                $s = "{$d} {$link} ({$length}) . . {$ul}";
 
                if ( "" != $c && "*" != $c ) {
@@ -66,7 +78,7 @@ function wfSpecialNewpages()
 {
        global $wgRequest;
     list( $limit, $offset ) = wfCheckLimits();
-    
+
     $npp = new NewPagesPage();
 
     if( !$npp->doFeed( $wgRequest->getVal( 'feed' ) ) ) {
index 2d378b2..414f618 100644 (file)
@@ -16,13 +16,14 @@ function wfSpecialRecentchanges( $par )
        if ( !$defaultDays ) {
                $defaultDays = 3;
        }
-       
+
        $days = $wgRequest->getInt( 'days', $defaultDays );
        $hideminor = $wgRequest->getBool( 'hideminor', $wgUser->getOption( 'hideminor' ) ) ? 1 : 0;
        $from = $wgRequest->getText( 'from' );
        $hidebots = $wgRequest->getBool( 'hidebots', true ) ? 1 : 0;
        $hideliu = $wgRequest->getBool( 'hideliu', false ) ? 1 : 0;
-       
+       $hidepatrolled = $wgRequest->getBool( 'hidepatrolled', false ) ? 1 : 0;
+
        # Get query parameters from path
        if( $par ) {
                $bits = preg_split( '/\s*,\s*/', trim( $par ) );
@@ -31,11 +32,12 @@ function wfSpecialRecentchanges( $par )
                if( in_array( "hideminor", $bits ) ) $hideminor = 1;
                if( in_array( "minor", $bits ) ) $hideminor = 0;
                if( in_array( "hideliu", $bits) ) $hideliu = 1;
+               if( in_array( "hidepatrolled", $bits) ) $hidepatrolled = 1;
        }
-       
+
        $dbr =& wfGetDB( DB_SLAVE );
        extract( $dbr->tableNames( 'recentchanges', 'watchlist' ) );
-       
+
        $lastmod = $dbr->selectField( 'recentchanges', 'MAX(rc_timestamp)', false, $fname );
        # 10 seconds server-side caching max
        $wgOut->setSquidMaxage( 10 );
@@ -45,16 +47,16 @@ function wfSpecialRecentchanges( $par )
        }
 
        # The next few lines can probably be commented out now that wfMsg can get text from the DB
-       $rctext = $dbr->selectField( 'cur', 'cur_text', 
+       $rctext = $dbr->selectField( 'cur', 'cur_text',
                array( 'cur_namespace' => NS_WIKIPEDIA, 'cur_title' => 'Recentchanges' ),
                $fname
        );
        if( !$rctext ) {
                $rctext = wfMsg( "recentchangestext" );
        }
-       
+
        $wgOut->addWikiText( $rctext );
-       
+
        list( $limit, $offset ) = wfCheckLimits( 100, "rclimit" );
        $now = wfTimestampNow();
        $cutoff_unixtime = time() - ( $days * 86400 );
@@ -68,31 +70,24 @@ function wfSpecialRecentchanges( $par )
 
        $sk = $wgUser->getSkin();
        $showhide = array( wfMsg( "show" ), wfMsg( "hide" ));
-       
-       if ( $hideminor ) {
-               $hidem = "AND rc_minor=0";
-       } else {
-               $hidem = "";
-       }
-       
-       if( $hidebots ) {
-               $hidem .= " AND rc_bot=0";
-       }
-       
-       if ( $hideliu ) {
-               $hidem .= " AND rc_user=0";
-       }
-       $hideliu = ($hideliu ? 1 : 0);
-       #$hideparams = "hideminor={$hideminor}&hideliu={$hideliu}&hidebots={$hidebots}";
-       $urlparams = array( "hideminor" => $hideminor, "hideliu" => $hideliu, "hidebots" => $hidebots );
+
+       $hidem  = ( $hideminor )    ? "AND rc_minor=0" : "";
+       $hidem .= ( $hidebots )     ? " AND rc_bot=0" : "";
+       $hidem .= ( $hideliu )      ? " AND rc_user=0" : "";
+       $hidem .= ( $hidepatrolled )? " AND rc_patrolled=0" : "";
+
+       $urlparams = array( "hideminor" => $hideminor,  "hideliu"       => $hideliu,
+                           "hidebots"  => $hidebots,   "hidepatrolled" => $hidepatrolled );
        $hideparams = wfArrayToCGI( $urlparams );
-       
+
        $minorLink = $sk->makeKnownLink( $wgLang->specialPage( "Recentchanges" ),
          $showhide[1-$hideminor], wfArrayToCGI( array( "hideminor" => 1-$hideminor ), $urlparams ) );
        $botLink = $sk->makeKnownLink( $wgLang->specialPage( "Recentchanges" ),
          $showhide[1-$hidebots], wfArrayToCGI( array( "hidebots" => 1-$hidebots ), $urlparams ) );
        $liuLink = $sk->makeKnownLink( $wgLang->specialPage( "Recentchanges" ),
          $showhide[1-$hideliu], wfArrayToCGI( array( "hideliu" => 1-$hideliu ), $urlparams ) );
+       $patrLink = $sk->makeKnownLink( $wgLang->specialPage( "Recentchanges" ),
+         $showhide[1-$hidepatrolled], wfArrayToCGI( array( "hidepatrolled" => 1-$hidepatrolled ), $urlparams ) );
 
        $uid = $wgUser->getID();
        $sql2 = "SELECT $recentchanges.*" . ($uid ? ",wl_user" : "") . " FROM $recentchanges " .
@@ -102,11 +97,11 @@ function wfSpecialRecentchanges( $par )
 
        $res = $dbr->query( $sql2, DB_SLAVE, $fname );
        $rows = array();
-       while( $row = $dbr->fetchObject( $res ) ){ 
-               $rows[] = $row; 
+       while( $row = $dbr->fetchObject( $res ) ){
+               $rows[] = $row;
        }
        $dbr->freeResult( $res );
-       
+
        if(isset($from)) {
                $note = wfMsg( "rcnotefrom", $wgLang->formatNum( $limit ),
                        $wgLang->timeanddate( $from, true ) );
@@ -115,7 +110,7 @@ function wfSpecialRecentchanges( $par )
        }
        $wgOut->addHTML( "\n<hr />\n{$note}\n<br />" );
 
-       $note = rcDayLimitLinks( $days, $limit, "Recentchanges", $hideparams, false, $minorLink, $botLink, $liuLink );
+       $note = rcDayLimitLinks( $days, $limit, "Recentchanges", $hideparams, false, $minorLink, $botLink, $liuLink, $patrLink );
 
        $note .= "<br />\n" . wfMsg( "rclistfrom",
          $sk->makeKnownLink( $wgLang->specialPage( "Recentchanges" ),
@@ -149,10 +144,11 @@ function wfSpecialRecentchanges( $par )
                $counter = 1;
                foreach( $rows as $obj ){
                        if( $limit == 0) {
-                               break; 
+                               break;
                        }
-                       
-                       if ( ! ( $hideminor && $obj->rc_minor ) ) {
+
+                       if ( ! ( $hideminor     && $obj->rc_minor     ) &&
+                            ! ( $hidepatrolled && $obj->rc_patrolled ) ) {
                                $rc = RecentChange::newFromRow( $obj );
                                $rc->counter = $counter++;
                                $s .= $sk->recentChangesLine( $rc, !empty( $obj->wl_user ) );
@@ -184,8 +180,8 @@ function rcDaysLink( $lim, $d, $page="Recentchanges", $more="" )
        return $s;
 }
 
-function rcDayLimitLinks( $days, $limit, $page="Recentchanges", $more="", $doall = false, $minorLink = "", 
-       $botLink = "", $liuLink = "" )
+function rcDayLimitLinks( $days, $limit, $page="Recentchanges", $more="", $doall = false, $minorLink = "",
+       $botLink = "", $liuLink = "", $patrLink = "" )
 {
        if ($more != "") $more .= "&";
        $cl = rcCountLink( 50, $days, $page, $more ) . " | " .
@@ -199,7 +195,7 @@ function rcDayLimitLinks( $days, $limit, $page="Recentchanges", $more="", $doall
          rcDaysLink( $limit, 14, $page, $more  ) . " | " .
          rcDaysLink( $limit, 30, $page, $more  ) .
          ( $doall ? ( " | " . rcDaysLink( $limit, 0, $page, $more ) ) : "" );
-       $shm = wfMsg( "showhideminor", $minorLink, $botLink, $liuLink );
+       $shm = wfMsg( "showhideminor", $minorLink, $botLink, $liuLink, $patrLink );
        $note = wfMsg( "rclinks", $cl, $dl, $shm );
        return $note;
 }
index e72c796..8ff162b 100644 (file)
@@ -1428,12 +1428,19 @@ You might want to check the following regular expression for patterns that are c
 "numtalkauthors" => "Number of distinct authors (discussion page): $1",
 
 # Math options
-       'mw_math_png' => 'Always render PNG',
-       'mw_math_simple' => 'HTML if very simple or else PNG',
-       'mw_math_html' => 'HTML if possible or else PNG',
-       'mw_math_source' => 'Leave it as TeX (for text browsers)',
-       'mw_math_modern' => 'Recommended for modern browsers',
-       'mw_math_mathml' => 'MathML if possible (experimental)',
+'mw_math_png' => 'Always render PNG',
+'mw_math_simple' => 'HTML if very simple or else PNG',
+'mw_math_html' => 'HTML if possible or else PNG',
+'mw_math_source' => 'Leave it as TeX (for text browsers)',
+'mw_math_modern' => 'Recommended for modern browsers',
+'mw_math_mathml' => 'MathML if possible (experimental)',
+
+# Patrolling
+'markaspatrolleddiff'   => "Mark as patrolled",
+'markaspatrolledlink'   => "<div class='patrollink'>[$1]</div>",
+'markaspatrolledtext'   => "Mark this article as patrolled",
+'markedaspatrolled'     => "Marked as patrolled",
+'markedaspatrolledtext' => "The selected revision has been marked as patrolled.",
 
 # Monobook.js: tooltips and access keys for monobook
 'Monobook.js' => '/* tooltips and access keys */
@@ -1870,7 +1877,7 @@ class Language {
                }
                return $s;
        }
-       
+
        # Crop a string from the beginning or end to a certain number of bytes.
        # (Bytes are used because our storage has limited byte lengths for some
        # columns in the database.) Multibyte charsets will need to make sure that
diff --git a/maintenance/archives/patch-rc-patrol.sql b/maintenance/archives/patch-rc-patrol.sql
new file mode 100755 (executable)
index 0000000..51fd3c6
--- /dev/null
@@ -0,0 +1,9 @@
+--
+-- patch-rc-patrol.sql
+-- Adds a row to recentchanges for the patrolling feature
+-- 2004-08-09
+--
+
+ALTER TABLE recentchanges
+       ADD COLUMN rc_patrolled tinyint(3) unsigned NOT NULL default '0';
+
index dc8194f..b726f75 100644 (file)
@@ -12,11 +12,11 @@ CREATE TABLE user (
   user_password tinyblob NOT NULL default '',
   user_newpassword tinyblob NOT NULL default '',
   user_email tinytext NOT NULL default '',
-  user_options blob NOT NULL default '',  
+  user_options blob NOT NULL default '',
   user_touched char(14) binary NOT NULL default '',
   UNIQUE KEY user_id (user_id)
 ) PACK_KEYS=1;
-       
+
 CREATE TABLE user_newtalk (
   user_id int(5) NOT NULL default '0',
   user_ip varchar(40) NOT NULL default ''
@@ -192,6 +192,7 @@ CREATE TABLE recentchanges (
   rc_type tinyint(3) unsigned NOT NULL default '0',
   rc_moved_to_ns tinyint(3) unsigned NOT NULL default '0',
   rc_moved_to_title varchar(255) binary NOT NULL default '',
+  rc_patrolled tinyint(3) unsigned NOT NULL default '0',
   rc_ip char(15) NOT NULL default '',
   PRIMARY KEY rc_id (rc_id)
 ) PACK_KEYS=1;
index b6d3f82..603d2b6 100644 (file)
@@ -906,3 +906,11 @@ fieldset.operaprefsection { margin-left: 15em }
 .printfooter {
         display: none;
 }
+
+ul.special li.not_patrolled, ol.special li.not_patrolled {
+       background-color: #ffa;
+}
+div.patrollink {
+       font-size: 75%;
+       text-align: right;
+}