New hook getOtherBlockLogLink, called in Special:IPBlockList to show links to block...
[lhc/web/wiklou.git] / includes / Article.php
index 7436f60..09bb46d 100644 (file)
@@ -443,7 +443,7 @@ class Article {
                # fails we'll have something telling us what we intended.
                $t = $this->mTitle->getPrefixedText();
                $d = $oldid ? wfMsgExt( 'missingarticle-rev', array( 'escape' ), $oldid ) : '';
-               $this->mContent = wfMsg( 'missing-article', $t, $d ) ;
+               $this->mContent = wfMsgNoTrans( 'missing-article', $t, $d ) ;
 
                if( $oldid ) {
                        $revision = Revision::newFromId( $oldid );
@@ -692,29 +692,35 @@ class Article {
        public function getContributors($limit = 0, $offset = 0) {
                # XXX: this is expensive; cache this info somewhere.
 
-               $contribs = array();
                $dbr = wfGetDB( DB_SLAVE );
                $revTable = $dbr->tableName( 'revision' );
                $userTable = $dbr->tableName( 'user' );
-               $user = $this->getUser();
+
                $pageId = $this->getId();
 
-               $deletedBit = $dbr->bitAnd('rev_deleted', Revision::DELETED_USER); // username hidden?
+               $user = $this->getUser();
+               if ( $user ) {
+                       $excludeCond = "AND rev_user != $user";
+               } else {
+                       $userText = $dbr->addQuotes( $this->getUserText() );
+                       $excludeCond = "AND rev_user_text != $userText";
+               }
+
+               $deletedBit = $dbr->bitAnd( 'rev_deleted', Revision::DELETED_USER ); // username hidden?
 
-               $sql = "SELECT {$userTable}.*, MAX(rev_timestamp) as timestamp
+               $sql = "SELECT {$userTable}.*, rev_user_text as user_name, MAX(rev_timestamp) as timestamp
                        FROM $revTable LEFT JOIN $userTable ON rev_user = user_id
                        WHERE rev_page = $pageId
-                       AND rev_user != $user
+                       $excludeCond
                        AND $deletedBit = 0
-                       GROUP BY rev_user, rev_user_text, user_real_name
+                       GROUP BY rev_user, rev_user_text
                        ORDER BY timestamp DESC";
 
-               if($limit > 0)
-                       $sql = $dbr->limitResult($sql, $limit, $offset);
+               if ( $limit > 0 )
+                       $sql = $dbr->limitResult( $sql, $limit, $offset );
 
-               $sql .= ' '. $this->getSelectOptions();
-
-               $res = $dbr->query($sql, __METHOD__ );
+               $sql .= ' ' . $this->getSelectOptions();
+               $res = $dbr->query( $sql, __METHOD__ );
 
                return new UserArrayFromResult( $res );
        }
@@ -726,7 +732,7 @@ class Article {
        public function view() {
                global $wgUser, $wgOut, $wgRequest, $wgContLang;
                global $wgEnableParserCache, $wgStylePath, $wgParser;
-               global $wgUseTrackbacks;
+               global $wgUseTrackbacks, $wgUseFileCache;
 
                wfProfileIn( __METHOD__ );
 
@@ -752,7 +758,7 @@ class Article {
                                wfProfileOut( __METHOD__ );
                                return;
                        # Try file cache
-                       } else if( $this->tryFileCache() ) {
+                       } else if( $wgUseFileCache && $this->tryFileCache() ) {
                                wfDebug( __METHOD__.": done file cache\n" );
                                # tell wgOut that output is taken care of
                                $wgOut->disable();
@@ -795,9 +801,9 @@ class Article {
                # tents of 'pagetitle-view-mainpage' instead of the default (if
                # that's not empty).
                if( $this->mTitle->equals( Title::newMainPage() )
-                       && wfMsgForContent( 'pagetitle-view-mainpage' ) !== '' )
+                       && ($m=wfMsgForContent( 'pagetitle-view-mainpage' )) !== '' )
                {
-                       $wgOut->setHTMLTitle( wfMsgForContent( 'pagetitle-view-mainpage' ) );
+                       $wgOut->setHTMLTitle( $m );
                }
 
                $wasRedirected = $this->showRedirectedFromHeader();
@@ -809,7 +815,6 @@ class Article {
                $outputDone = false;
                while( !$outputDone && ++$pass ){
                        switch( $pass ){
-
                                case 1:
                                        wfRunHooks( 'ArticleViewHeader', array( &$this, &$outputDone, &$useParserCache ) );
                                        break;
@@ -856,12 +861,13 @@ class Article {
                                                        wfProfileOut( __METHOD__ );
                                                        return;
                                                }
-
+                                               # If this "old" version is the current, then try the parser cache...
                                                if ( $oldid === $this->getLatest() && $this->useParserCache( false ) ) {
                                                        $this->mParserOutput = $parserCache->get( $this, $parserOptions );
                                                        if ( $this->mParserOutput ) {
                                                                wfDebug( __METHOD__.": showing parser cache for current rev permalink\n" );
                                                                $wgOut->addParserOutput( $this->mParserOutput );
+                                                               $wgOut->setRevisionId( $this->mLatest );
                                                                $this->showViewFooter();
                                                                $this->viewUpdates();
                                                                wfProfileOut( __METHOD__ );
@@ -937,7 +943,7 @@ class Article {
                $rcid = $wgRequest->getVal( 'rcid' );
                $diffOnly = $wgRequest->getBool( 'diffonly', $wgUser->getOption( 'diffonly' ) );
                $purge = $wgRequest->getVal( 'action' ) == 'purge';
-               $htmldiff = $wgRequest->getVal( 'htmldiff' , false);
+               $htmldiff = $wgRequest->getBool( 'htmldiff' );
                $unhide = $wgRequest->getInt('unhide') == 1;
                $oldid = $this->getOldID();
 
@@ -1199,9 +1205,27 @@ class Article {
         * namespace, show the default message text. To be called from Article::view().
         */
        public function showMissingArticle() {
-               global $wgOut, $wgRequest;
+               global $wgOut, $wgRequest, $wgUser;
+
+               # Show info in user (talk) namespace. Does the user exist?
+               if ( $this->mTitle->getNamespace() == NS_USER || $this->mTitle->getNamespace() == NS_USER_TALK ) {
+                       $parts = explode( '/', $this->mTitle->getText() );
+                       $rootPart = $parts[0];
+                       $id = User::idFromName( $rootPart );
+                       $ip = User::isIP( $rootPart );
+                       if ( $id == 0 && !$ip ) { # User does not exist
+                               $wgOut->wrapWikiMsg( '<div class="mw-userpage-userdoesnotexist error">$1</div>',
+                                       array( 'userpage-userdoesnotexist-view', $rootPart ) );
+                       }
+               }
+               wfRunHooks( 'ShowMissingArticle', array( $this ) );
                # Show delete and move logs
-               $this->showLogs();
+               LogEventsList::showLogExtract( $wgOut, array( 'delete', 'move' ), $this->mTitle->getPrefixedText(), '',
+                       array(  'lim' => 10,
+                               'conds' => array( "log_action != 'revision'" ),
+                               'showIfEmpty' => false,
+                               'msgKey' => array( 'moveddeleted-notice' ) ) 
+               );
 
                # Show error message
                $oldid = $this->getOldID();
@@ -1213,7 +1237,14 @@ class Article {
                        // Use the default message text
                        $text = $this->getContent();
                } else {
-                       $text = wfMsgNoTrans( 'noarticletext' );
+                       $createErrors = $this->mTitle->getUserPermissionsErrors( 'create', $wgUser );
+                       $editErrors = $this->mTitle->getUserPermissionsErrors( 'edit', $wgUser );
+                       $errors = array_merge( $createErrors, $editErrors );
+                       
+                       if ( !count($errors) )
+                               $text = wfMsgNoTrans( 'noarticletext' );
+                       else
+                               $text = wfMsgNoTrans( 'noarticletext-nopermission' );
                }
                $text = "<div class='noarticletext'>\n$text\n</div>";
                if( !$this->hasViewableContent() ) {
@@ -1259,36 +1290,6 @@ class Article {
                }
        }
 
-       /**
-        * Show an excerpt from the deletion and move logs. To be called from the 
-        * header section on page views of missing pages.
-        */
-       public function showLogs() {
-               global $wgUser, $wgOut;
-               $loglist = new LogEventsList( $wgUser->getSkin(), $wgOut );
-               $pager = new LogPager( $loglist, array('move', 'delete'), false,
-                       $this->mTitle->getPrefixedText(), '', array( "log_action != 'revision'" ) );
-               if( $pager->getNumRows() > 0 ) {
-                       $pager->mLimit = 10;
-                       $wgOut->addHTML( '<div class="mw-warning-with-logexcerpt">' );
-                       $wgOut->addWikiMsg( 'moveddeleted-notice' );
-                       $wgOut->addHTML(
-                               $loglist->beginLogEventsList() .
-                               $pager->getBody() .
-                               $loglist->endLogEventsList()
-                       );
-                       if( $pager->getNumRows() > 10 ) {
-                               $wgOut->addHTML( $wgUser->getSkin()->link(
-                                       SpecialPage::getTitleFor( 'Log' ),
-                                       wfMsgHtml( 'log-fulllog' ),
-                                       array(),
-                                       array( 'page' => $this->mTitle->getPrefixedText() )
-                               ) );
-                       }
-                       $wgOut->addHTML( '</div>' );
-               }
-       }
-
        /*
        * Should the parser cache be used?
        */
@@ -1893,6 +1894,7 @@ class Article {
 
                $dbw = wfGetDB( DB_MASTER );
                $now = wfTimestampNow();
+               $this->mTimestamp=$now;
 
                if( $flags & EDIT_UPDATE ) {
                        # Update article, but only if changed.
@@ -2555,9 +2557,19 @@ class Article {
                $conds = $this->mTitle->pageCond();
                $latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ );
                if( $latest === false ) {
-                       $wgOut->showFatalError( wfMsgExt( 'cannotdelete', array( 'parse' ) ) );
+                       $wgOut->showFatalError(
+                               Html::rawElement(
+                                       'div',
+                                       array( 'class' => 'error mw-error-cannotdelete' ),
+                                       wfMsgExt( 'cannotdelete', array( 'parse' ), $this->mTitle->getPrefixedText() )
+                               )
+                       );
                        $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) );
-                       LogEventsList::showLogExtract( $wgOut, 'delete', $this->mTitle->getPrefixedText() );
+                       LogEventsList::showLogExtract(
+                               $wgOut,
+                               'delete',
+                               $this->mTitle->getPrefixedText()
+                       );
                        return;
                }
 
@@ -2586,10 +2598,16 @@ class Article {
 
                // If the page has a history, insert a warning
                if( $hasHistory && !$confirm ) {
+                       global $wgLang;
                        $skin = $wgUser->getSkin();
-                       $wgOut->addHTML( '<strong>' . wfMsgExt( 'historywarning', array( 'parseinline' ) ) . ' ' . $skin->historyLink() . '</strong>' );
+                       $revisions = $this->estimateRevisionCount();
+                       $wgOut->addHTML( '<strong class="mw-delete-warning-revisions">' .
+                               wfMsgExt( 'historywarning', array( 'parseinline' ), $wgLang->formatNum( $revisions ) ) .' ' .
+                               $skin->historyLink() .
+                               '</strong>'
+                       );
                        if( $bigHistory ) {
-                               global $wgLang, $wgDeleteRevisionsLimit;
+                               global $wgDeleteRevisionsLimit;
                                $wgOut->wrapWikiMsg( "<div class='error'>\n$1</div>\n",
                                        array( 'delete-warning-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) );
                        }
@@ -2765,7 +2783,11 @@ class Article {
 
                $wgOut->addHTML( $form );
                $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) );
-               LogEventsList::showLogExtract( $wgOut, 'delete', $this->mTitle->getPrefixedText() );
+               LogEventsList::showLogExtract(
+                       $wgOut,
+                       'delete',
+                       $this->mTitle->getPrefixedText()
+               );
        }
 
        /**
@@ -2791,9 +2813,19 @@ class Article {
                        }
                } else {
                        if( $error == '' ) {
-                               $wgOut->showFatalError( wfMsgExt( 'cannotdelete', array( 'parse' ) ) );
+                               $wgOut->showFatalError(
+                                       Html::rawElement(
+                                               'div',
+                                               array( 'class' => 'error mw-error-cannotdelete' ),
+                                               wfMsgExt( 'cannotdelete', array( 'parse' ), $this->mTitle->getPrefixedText() )
+                                       )
+                               );
                                $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) );
-                               LogEventsList::showLogExtract( $wgOut, 'delete', $this->mTitle->getPrefixedText() );
+                               LogEventsList::showLogExtract(
+                                       $wgOut,
+                                       'delete',
+                                       $this->mTitle->getPrefixedText()
+                               );
                        } else {
                                $wgOut->showFatalError( $error );
                        }
@@ -3003,6 +3035,8 @@ class Article {
                }
 
                $from = str_replace( '_', ' ', $fromP );
+               # User name given should match up with the top revision.
+               # If the user was deleted then $from should be empty.
                if( $from != $current->getUserText() ) {
                        $resultDetails = array( 'current' => $current );
                        return array(array('alreadyrolled',
@@ -3012,9 +3046,10 @@ class Article {
                        ));
                }
 
-               # Get the last edit not by this guy
-               $user = intval( $current->getUser() );
-               $user_text = $dbw->addQuotes( $current->getUserText() );
+               # Get the last edit not by this guy...
+               # Note: these may not be public values
+               $user = intval( $current->getRawUser() );
+               $user_text = $dbw->addQuotes( $current->getRawUserText() );
                $s = $dbw->selectRow( 'revision',
                        array( 'rev_id', 'rev_timestamp', 'rev_deleted' ),
                        array(  'rev_page' => $current->getPage(),
@@ -3041,20 +3076,24 @@ class Article {
                        $set['rc_patrolled'] = 1;
                }
 
-               if( $set ) {
+               if( count($set) ) {
                        $dbw->update( 'recentchanges', $set,
-                                       array( /* WHERE */
-                                               'rc_cur_id' => $current->getPage(),
-                                               'rc_user_text' => $current->getUserText(),
-                                               "rc_timestamp > '{$s->rev_timestamp}'",
-                                       ), __METHOD__
-                               );
+                               array( /* WHERE */
+                                       'rc_cur_id' => $current->getPage(),
+                                       'rc_user_text' => $current->getUserText(),
+                                       "rc_timestamp > '{$s->rev_timestamp}'",
+                               ), __METHOD__
+                       );
                }
 
                # Generate the edit summary if necessary
                $target = Revision::newFromId( $s->rev_id );
-               if( empty( $summary ) ){
-                       $summary = wfMsgForContent( 'revertpage' );
+               if( empty( $summary ) ) {
+                       if( $from == '' ) { // no public user name
+                               $summary = wfMsgForContent( 'revertpage-nouser' );
+                       } else {
+                               $summary = wfMsgForContent( 'revertpage' );
+                       }
                }
 
                # Allow the custom summary to use the same args as the default message
@@ -3086,8 +3125,8 @@ class Article {
                $resultDetails = array(
                        'summary' => $summary,
                        'current' => $current,
-                       'target' => $target,
-                       'newid' => $revId
+                       'target'  => $target,
+                       'newid'   => $revId
                );
                return array();
        }
@@ -3410,17 +3449,14 @@ class Article {
                        );
 
                $cdel='';
-               if( $wgUser->isAllowed( 'deleterevision' ) ) {
-                       $revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
-                       if( $revision->isCurrent() ) {
-                       // We don't handle top deleted edits too well
-                               $cdel = wfMsgHtml( 'rev-delundel' );
-                       } else if( !$revision->userCan( Revision::DELETED_RESTRICTED ) ) {
+               // Don't show useless link to people who cannot hide revisions
+               if( $wgUser->isAllowed('deleterevision') || ($revision->getVisibility() && $wgUser->isAllowed('deletedhistory')) ) {
+                       if( !$revision->userCan( Revision::DELETED_RESTRICTED ) ) {
                        // If revision was hidden from sysops
                                $cdel = wfMsgHtml( 'rev-delundel' );
                        } else {
                                $cdel = $sk->link(
-                                       $revdel,
+                                       SpecialPage::getTitleFor( 'Revisiondelete' ),
                                        wfMsgHtml('rev-delundel'),
                                        array(),
                                        array(
@@ -3509,8 +3545,7 @@ class Article {
         */
        public function isFileCacheable() {
                $cacheable = false;
-               global $wgUseFileCache;
-               if( $wgUseFileCache and HTMLFileCache::useFileCache() ) {
+               if( HTMLFileCache::useFileCache() ) {
                        $cacheable = $this->getID() && !$this->mRedirectedFrom;
                        // Extension may have reason to disable file caching on some pages.
                        if( $cacheable ) {
@@ -4057,7 +4092,8 @@ class Article {
                }
                $insertRows = array();
                foreach( $insertCats as $cat ) {
-                       $insertRows[] = array( 'cat_title' => $cat );
+                       $insertRows[] = array(  'cat_id' => $dbw->nextSequenceValue( 'category_id_seq' ),
+                                                                                                                       'cat_title' => $cat );
                }
                $dbw->insert( 'category', $insertRows, __METHOD__, 'IGNORE' );