Simplify a bit by using getRawText() instead of creating a Revision object
[lhc/web/wiklou.git] / includes / Article.php
index 915ee7a..d66795d 100644 (file)
@@ -43,7 +43,7 @@ class Article {
        var $mRedirectTarget = null;
 
        /**
-        * @var Title
+        * @var mixed: boolean false or URL string
         */
        var $mRedirectUrl = false;        // !<
        var $mRevIdFetched = 0;           // !<
@@ -63,7 +63,7 @@ class Article {
        var $mTouched = '19700101000000'; // !<
 
        /**
-        * @var ParserOptions
+        * @var ParserOptions: ParserOptions object for $wgUser articles
         */
        var $mParserOptions;
 
@@ -76,7 +76,7 @@ class Article {
 
        /**
         * Constructor and clear the article
-        * @param $title Reference to a Title object.
+        * @param $title Title Reference to a Title object.
         * @param $oldId Integer revision ID, null to fetch from request, zero for current
         */
        public function __construct( Title $title, $oldId = null ) {
@@ -363,13 +363,12 @@ class Article {
         * @return mixed string on success, false on failure
         */
        public function getUndoText( Revision $undo, Revision $undoafter = null ) {
-               $currentRev = Revision::newFromTitle( $this->mTitle );
-               if ( !$currentRev ) {
+               $cur_text = $this->getRawText();
+               if ( $cur_text === false ) {
                        return false; // no page
                }
                $undo_text = $undo->getText();
                $undoafter_text = $undoafter->getText();
-               $cur_text = $currentRev->getText();
 
                if ( $cur_text == $undo_text ) {
                        # No use doing a merge if it's just a straight revert.
@@ -699,7 +698,7 @@ class Article {
                        if ( $text === false ) {
                                $text = $this->getRawText();
                        }
-                       return in_string( ',', $text );
+                       return strpos( $text,  ',' ) !== false;
                case 'link':
                        if ( $editInfo ) {
                                // ParserOutput::getLinks() is a 2D array of page links, so
@@ -864,7 +863,7 @@ class Article {
        /**
         * Get a list of users who have edited this article, not including the user who made
         * the most recent revision, which you can get from $article->getUser() if you want it
-        * @return UserArray
+        * @return UserArrayFromResult
         */
        public function getContributors() {
                # @todo FIXME: This is expensive; cache this info somewhere.
@@ -907,7 +906,7 @@ class Article {
                        'GROUP BY' => array( 'rev_user', 'rev_user_text' ),
                        'ORDER BY' => 'timestamp DESC',
                );
-               
+
                $res = $dbr->select( $tables, $fields, $conds, __METHOD__, $options, $jconds );
                return new UserArrayFromResult( $res );
        }
@@ -957,7 +956,7 @@ class Article {
                if ( $wgOut->isPrintable() ) {
                        $parserOptions->setIsPrintable( true );
                        $parserOptions->setEditSection( false );
-               } else if ( $wgUseETag && !$this->mTitle->quickUserCan( 'edit' ) ) {
+               } elseif ( $wgUseETag && !$this->mTitle->quickUserCan( 'edit' ) ) {
                        $parserOptions->setEditSection( false );
                }
 
@@ -974,7 +973,7 @@ class Article {
 
                                return;
                        # Try file cache
-                       } else if ( $wgUseFileCache && $this->tryFileCache() ) {
+                       } elseif ( $wgUseFileCache && $this->tryFileCache() ) {
                                wfDebug( __METHOD__ . ": done file cache\n" );
                                # tell wgOut that output is taken care of
                                $wgOut->disable();
@@ -1439,8 +1438,8 @@ class Article {
 
                        if ( !$user->isLoggedIn() && !$ip ) { # User does not exist
                                $wgOut->wrapWikiMsg( "<div class=\"mw-userpage-userdoesnotexist error\">\n\$1\n</div>",
-                                       array( 'userpage-userdoesnotexist-view', $rootPart ) );
-                       } else if ( $user->isBlocked() ) { # Show log extract if the user is currently blocked
+                                       array( 'userpage-userdoesnotexist-view', wfEscapeWikiText( $rootPart ) ) );
+                       } elseif ( $user->isBlocked() ) { # Show log extract if the user is currently blocked
                                LogEventsList::showLogExtract(
                                        $wgOut,
                                        'block',
@@ -1520,7 +1519,7 @@ class Article {
 
                        return false;
                // If the user needs to confirm that they want to see it...
-               } else if ( $wgRequest->getInt( 'unhide' ) != 1 ) {
+               } elseif ( $wgRequest->getInt( 'unhide' ) != 1 ) {
                        # Give explanation and add a link to view the revision...
                        $oldid = intval( $this->getOldID() );
                        $link = $this->mTitle->getFullUrl( "oldid={$oldid}&unhide=1" );
@@ -1706,29 +1705,10 @@ class Article {
 
        /**
         * Removes trackback record for current article from trackbacks table
+        * @deprecated since 1.19
         */
        public function deletetrackback() {
-               global $wgRequest, $wgOut;
-
-               if ( !$wgOut->getUser()->matchEditToken( $wgRequest->getVal( 'token' ) ) ) {
-                       $wgOut->addWikiMsg( 'sessionfailure' );
-
-                       return;
-               }
-
-               $permission_errors = $this->mTitle->getUserPermissionsErrors( 'delete', $wgOut->getUser() );
-
-               if ( count( $permission_errors ) ) {
-                       $wgOut->showPermissionsErrorPage( $permission_errors );
-
-                       return;
-               }
-
-               $db = wfGetDB( DB_MASTER );
-               $db->delete( 'trackbacks', array( 'tb_id' => $wgRequest->getInt( 'tbid' ) ) );
-
-               $wgOut->addWikiMsg( 'trackbackdeleteok' );
-               $this->mTitle->invalidateCache();
+               return Action::factory( 'deletetrackback', $this )->show();
        }
 
        /**
@@ -1784,6 +1764,78 @@ class Article {
                }
        }
 
+       /**
+        * Mark this particular edit/page as patrolled
+        * @deprecated since 1.19
+        */
+       public function markpatrolled() {
+               Action::factory( 'markpatrolled', $this )->show();
+       }
+
+       /**
+        * User-interface handler for the "watch" action.
+        * Requires Request to pass a token as of 1.19.
+        * @deprecated since 1.18
+        */
+       public function watch() {
+               Action::factory( 'watch', $this )->show();
+       }
+
+       /**
+        * Add this page to $wgUser's watchlist
+        *
+        * This is safe to be called multiple times
+        *
+        * @return bool true on successful watch operation
+        * @deprecated since 1.18
+        */
+       public function doWatch() {
+               global $wgUser;
+               return WatchAction::doWatch( $this->mTitle, $wgUser );
+       }
+
+       /**
+        * User interface handler for the "unwatch" action.
+        * Requires Request to pass a token as of 1.19.
+        * @deprecated since 1.18
+        */
+       public function unwatch() {
+               Action::factory( 'unwatch', $this )->show();
+       }
+
+       /**
+        * Stop watching a page
+        * @return bool true on successful unwatch
+        * @deprecated since 1.18
+        */
+       public function doUnwatch() {
+               global $wgUser;
+               return WatchAction::doUnwatch( $this->mTitle, $wgUser );
+       }
+
+       /**
+        * action=protect handler
+        */
+       public function protect() {
+               $form = new ProtectionForm( $this );
+               $form->execute();
+       }
+
+       /**
+        * action=unprotect handler (alias)
+        */
+       public function unprotect() {
+               $this->protect();
+       }
+
+       /**
+        * Info about this page
+        * Called for ?action=info when $wgAllowPageInfo is on.
+        */
+       public function info() {
+               Action::factory( 'info', $this )->show();
+       }
+
        /**
         * Insert a new empty page record for this article.
         * This *must* be followed up by creating a revision
@@ -2303,11 +2355,13 @@ class Article {
         * Output a redirect back to the article.
         * This is typically used after an edit.
         *
+        * @deprecated in 1.19; call $wgOut->redirect() directly
         * @param $noRedir Boolean: add redirect=no
         * @param $sectionAnchor String: section to redirect to, including "#"
         * @param $extraQuery String: extra query params
         */
        public function doRedirect( $noRedir = false, $sectionAnchor = '', $extraQuery = '' ) {
+               wfDeprecated( __METHOD__ );
                global $wgOut;
 
                if ( $noRedir ) {
@@ -2321,118 +2375,6 @@ class Article {
                $wgOut->redirect( $this->mTitle->getFullURL( $query ) . $sectionAnchor );
        }
 
-       /**
-        * Mark this particular edit/page as patrolled
-        */
-       public function markpatrolled() {
-               global $wgOut, $wgRequest;
-
-               $wgOut->setRobotPolicy( 'noindex,nofollow' );
-
-               # If we haven't been given an rc_id value, we can't do anything
-               $rcid = (int) $wgRequest->getVal( 'rcid' );
-
-               if ( !$wgOut->getUser()->matchEditToken( $wgRequest->getVal( 'token' ), $rcid ) ) {
-                       $wgOut->showErrorPage( 'sessionfailure-title', 'sessionfailure' );
-                       return;
-               }
-
-               $rc = RecentChange::newFromId( $rcid );
-
-               if ( is_null( $rc ) ) {
-                       $wgOut->showErrorPage( 'markedaspatrollederror', 'markedaspatrollederrortext' );
-                       return;
-               }
-
-               # It would be nice to see where the user had actually come from, but for now just guess
-               $returnto = $rc->getAttribute( 'rc_type' ) == RC_NEW ? 'Newpages' : 'Recentchanges';
-               $return = SpecialPage::getTitleFor( $returnto );
-
-               $errors = $rc->doMarkPatrolled();
-
-               if ( in_array( array( 'rcpatroldisabled' ), $errors ) ) {
-                       $wgOut->showErrorPage( 'rcpatroldisabled', 'rcpatroldisabledtext' );
-
-                       return;
-               }
-
-               if ( in_array( array( 'hookaborted' ), $errors ) ) {
-                       // The hook itself has handled any output
-                       return;
-               }
-
-               if ( in_array( array( 'markedaspatrollederror-noautopatrol' ), $errors ) ) {
-                       $wgOut->setPageTitle( wfMsg( 'markedaspatrollederror' ) );
-                       $wgOut->addWikiMsg( 'markedaspatrollederror-noautopatrol' );
-                       $wgOut->returnToMain( null, $return );
-
-                       return;
-               }
-
-               if ( !empty( $errors ) ) {
-                       $wgOut->showPermissionsErrorPage( $errors );
-
-                       return;
-               }
-
-               # Inform the user
-               $wgOut->setPageTitle( wfMsg( 'markedaspatrolled' ) );
-               $wgOut->addWikiMsg( 'markedaspatrolledtext', $rc->getTitle()->getPrefixedText() );
-               $wgOut->returnToMain( null, $return );
-       }
-
-       /**
-        * User-interface handler for the "watch" action
-        * @deprecated since 1.18
-        */
-       public function watch() {
-               Action::factory( 'watch', $this )->show();
-       }
-
-       /**
-        * Add this page to $wgUser's watchlist
-        *
-        * This is safe to be called multiple times
-        *
-        * @return bool true on successful watch operation
-        * @deprecated since 1.18
-        */
-       public function doWatch() {
-               return Action::factory( 'watch', $this )->execute();
-       }
-
-       /**
-        * User interface handler for the "unwatch" action.
-        * @deprecated since 1.18
-        */
-       public function unwatch() {
-               Action::factory( 'unwatch', $this )->show();
-       }
-
-       /**
-        * Stop watching a page
-        * @return bool true on successful unwatch
-        * @deprecated since 1.18
-        */
-       public function doUnwatch() {
-               return Action::factory( 'unwatch', $this )->execute();
-       }
-
-       /**
-        * action=protect handler
-        */
-       public function protect() {
-               $form = new ProtectionForm( $this );
-               $form->execute();
-       }
-
-       /**
-        * action=unprotect handler (alias)
-        */
-       public function unprotect() {
-               $this->protect();
-       }
-
        /**
         * Update the article's restriction field, and leave a log entry.
         *
@@ -2789,7 +2731,8 @@ class Article {
                                Html::rawElement(
                                        'div',
                                        array( 'class' => 'error mw-error-cannotdelete' ),
-                                       wfMsgExt( 'cannotdelete', array( 'parse' ), $this->mTitle->getPrefixedText() )
+                                       wfMsgExt( 'cannotdelete', array( 'parse' ),
+                                               wfEscapeWikiText( $this->mTitle->getPrefixedText() ) )
                                )
                        );
                        $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) );
@@ -3057,7 +3000,7 @@ class Article {
 
                        $loglink = '[[Special:Log/delete|' . wfMsgNoTrans( 'deletionlog' ) . ']]';
 
-                       $wgOut->addWikiMsg( 'deletedtext', $deleted, $loglink );
+                       $wgOut->addWikiMsg( 'deletedtext', wfEscapeWikiText( $deleted ), $loglink );
                        $wgOut->returnToMain( false );
                } else {
                        if ( $error == '' ) {
@@ -3065,7 +3008,8 @@ class Article {
                                        Html::rawElement(
                                                'div',
                                                array( 'class' => 'error mw-error-cannotdelete' ),
-                                               wfMsgExt( 'cannotdelete', array( 'parse' ), $this->mTitle->getPrefixedText() )
+                                               wfMsgExt( 'cannotdelete', array( 'parse' ),
+                                                       wfEscapeWikiText( $this->mTitle->getPrefixedText() ) )
                                        )
                                );
 
@@ -3334,7 +3278,7 @@ class Article {
                if ( $s === false ) {
                        # No one else ever edited this page
                        return array( array( 'cantrollback' ) );
-               } else if ( $s->rev_deleted & Revision::DELETED_TEXT || $s->rev_deleted & Revision::DELETED_USER ) {
+               } elseif ( $s->rev_deleted & Revision::DELETED_TEXT || $s->rev_deleted & Revision::DELETED_USER ) {
                        # Only admins can see this text
                        return array( array( 'notvisiblerev' ) );
                }
@@ -3537,7 +3481,7 @@ class Article {
                $edit->revid = $revid;
                $edit->newText = $text;
                $edit->pst = $this->preSaveTransform( $text, $user, $popts );
-               $edit->popts = $this->getParserOptions();
+               $edit->popts = $this->getParserOptions( true );
                $edit->output = $wgParser->parse( $edit->pst, $this->mTitle, $edit->popts, true, true, $revid );
                $edit->oldText = $this->getRawText();
 
@@ -4065,95 +4009,6 @@ class Article {
                $wgOut->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
        }
 
-       /**
-        * Info about this page
-        * Called for ?action=info when $wgAllowPageInfo is on.
-        */
-       public function info() {
-               global $wgLang, $wgOut, $wgAllowPageInfo, $wgUser;
-
-               if ( !$wgAllowPageInfo ) {
-                       $wgOut->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
-                       return;
-               }
-
-               $page = $this->mTitle->getSubjectPage();
-
-               $wgOut->setPagetitle( $page->getPrefixedText() );
-               $wgOut->setPageTitleActionText( wfMsg( 'info_short' ) );
-               $wgOut->setSubtitle( wfMsgHtml( 'infosubtitle' ) );
-
-               if ( !$this->mTitle->exists() ) {
-                       $wgOut->addHTML( '<div class="noarticletext">' );
-                       $msg = $wgUser->isLoggedIn()
-                               ? 'noarticletext'
-                               : 'noarticletextanon';
-                       $wgOut->addWikiMsg( $msg );
-                       $wgOut->addHTML( '</div>' );
-               } else {
-                       $dbr = wfGetDB( DB_SLAVE );
-                       $wl_clause = array(
-                               'wl_title'     => $page->getDBkey(),
-                               'wl_namespace' => $page->getNamespace() );
-                       $numwatchers = $dbr->selectField(
-                               'watchlist',
-                               'COUNT(*)',
-                               $wl_clause,
-                               __METHOD__ );
-
-                       $pageInfo = $this->pageCountInfo( $page );
-                       $talkInfo = $this->pageCountInfo( $page->getTalkPage() );
-
-                       // @todo FIXME: unescaped messages
-                       $wgOut->addHTML( "<ul><li>" . wfMsg( "numwatchers", $wgLang->formatNum( $numwatchers ) ) . '</li>' );
-                       $wgOut->addHTML( "<li>" . wfMsg( 'numedits', $wgLang->formatNum( $pageInfo['edits'] ) ) . '</li>' );
-
-                       if ( $talkInfo ) {
-                               $wgOut->addHTML( '<li>' . wfMsg( "numtalkedits", $wgLang->formatNum( $talkInfo['edits'] ) ) . '</li>' );
-                       }
-
-                       $wgOut->addHTML( '<li>' . wfMsg( "numauthors", $wgLang->formatNum( $pageInfo['authors'] ) ) . '</li>' );
-
-                       if ( $talkInfo ) {
-                               $wgOut->addHTML( '<li>' . wfMsg( 'numtalkauthors', $wgLang->formatNum( $talkInfo['authors'] ) ) . '</li>' );
-                       }
-
-                       $wgOut->addHTML( '</ul>' );
-               }
-       }
-
-       /**
-        * Return the total number of edits and number of unique editors
-        * on a given page. If page does not exist, returns false.
-        *
-        * @param $title Title object
-        * @return mixed array or boolean false
-        */
-       public function pageCountInfo( $title ) {
-               $id = $title->getArticleId();
-
-               if ( $id == 0 ) {
-                       return false;
-               }
-
-               $dbr = wfGetDB( DB_SLAVE );
-               $rev_clause = array( 'rev_page' => $id );
-               $edits = $dbr->selectField(
-                       'revision',
-                       'COUNT(rev_page)',
-                       $rev_clause,
-                       __METHOD__
-               );
-               $authors = $dbr->selectField(
-                       'revision',
-                       'COUNT(DISTINCT rev_user_text)',
-                       $rev_clause,
-                       __METHOD__
-               );
-
-               return array( 'edits' => $edits, 'authors' => $authors );
-       }
-
        /**
         * Return a list of templates used by this article.
         * Uses the templatelinks table
@@ -4325,12 +4180,23 @@ class Article {
 
        /**
         * Get parser options suitable for rendering the primary article wikitext
-        * @return ParserOptions object
+        * @param $canonical boolean Determines that the generated options must not depend on user preferences (see bug 14404)
+        * @return mixed ParserOptions object or boolean false
         */
-       public function getParserOptions() {
-               global $wgUser;
-               if ( !$this->mParserOptions ) {
-                       $this->mParserOptions = $this->makeParserOptions( $wgUser );
+       public function getParserOptions( $canonical = false ) {
+               global $wgUser, $wgLanguageCode;
+
+               if ( !$this->mParserOptions || $canonical ) {
+                       $user = !$canonical ? $wgUser : new User;
+                       $parserOptions = new ParserOptions( $user );
+                       $parserOptions->setTidy( true );
+                       $parserOptions->enableLimitReport();
+
+                       if ( $canonical ) {
+                               $parserOptions->setUserLang( $wgLanguageCode ); # Must be set explicitely
+                               return $parserOptions;
+                       }
+                       $this->mParserOptions = $parserOptions;
                }
                // Clone to allow modifications of the return value without affecting cache
                return clone $this->mParserOptions;