Add support for Number grouping(commafy) based on CLDR number grouping patterns like...
[lhc/web/wiklou.git] / includes / Article.php
index 8f141e6..a91ad26 100644 (file)
@@ -23,7 +23,7 @@ class Article extends Page {
         */
 
        /**
-        * @var RequestContext
+        * @var IContextSource
         */
        protected $mContext;
 
@@ -88,10 +88,10 @@ class Article extends Page {
         * Create an Article object of the appropriate class for the given page.
         *
         * @param $title Title
-        * @param $context RequestContext
+        * @param $context IContextSource
         * @return Article object
         */
-       public static function newFromTitle( $title, RequestContext $context ) {
+       public static function newFromTitle( $title, IContextSource $context ) {
                if ( NS_MEDIA == $title->getNamespace() ) {
                        // FIXME: where should this go?
                        $title = Title::makeTitle( NS_FILE, $title->getDBkey() );
@@ -364,7 +364,6 @@ class Article extends Page {
                        return;
                }
 
-               $wgOut->setArticleFlag( true );
                # Set page title (may be overridden by DISPLAYTITLE)
                $wgOut->setPageTitle( $this->getTitle()->getPrefixedText() );
 
@@ -377,6 +376,7 @@ class Article extends Page {
                        return;
                }
 
+               $wgOut->setArticleFlag( true );
                # Allow frames by default
                $wgOut->allowClickjacking();
 
@@ -510,6 +510,9 @@ class Article extends Page {
                                                wfDebug( __METHOD__ . ": showing CSS/JS source\n" );
                                                $this->showCssOrJsPage();
                                                $outputDone = true;
+                                       } elseif( !wfRunHooks( 'ArticleViewCustom', array( $this->mContent, $this->getTitle(), $wgOut ) ) ) {
+                                               # Allow extensions do their own custom view for certain pages
+                                               $outputDone = true;
                                        } else {
                                                $rt = Title::newFromRedirectArray( $text );
                                                if ( $rt ) {
@@ -558,7 +561,7 @@ class Article extends Page {
                # tents of 'pagetitle-view-mainpage' instead of the default (if
                # that's not empty).
                # This message always exists because it is in the i18n files
-               if ( $this->getTitle()->equals( Title::newMainPage() ) ) {
+               if ( $this->getTitle()->isMainPage() ) {
                        $msg = wfMessage( 'pagetitle-view-mainpage' )->inContentLanguage();
                        if ( !$msg->isDisabled() ) {
                                $wgOut->setHTMLTitle( $msg->title( $this->getTitle() )->text() );
@@ -611,7 +614,11 @@ class Article extends Page {
        protected function showCssOrJsPage() {
                global $wgOut;
 
-               $wgOut->wrapWikiMsg( "<div id='mw-clearyourcache'>\n$1\n</div>", 'clearyourcache' );
+               $dir = $this->getContext()->getLang()->getDir();
+               $lang = $this->getContext()->getLang()->getCode();
+
+               $wgOut->wrapWikiMsg( "<div id='mw-clearyourcache' lang='$lang' dir='$dir' class='mw-content-$dir'>\n$1\n</div>",
+                       'clearyourcache' );
 
                // Give hooks a chance to customise the output
                if ( wfRunHooks( 'ShowRawCssJs', array( $this->mContent, $this->getTitle(), $wgOut ) ) ) {
@@ -1049,7 +1056,8 @@ class Article extends Page {
                        $target = array( $target );
                }
 
-               $imageDir = wfUILang()->getDir();
+               $lang = $this->getTitle()->getPageLanguage();
+               $imageDir = $lang->getDir();
 
                if ( $appendSubtitle ) {
                        $wgOut->appendSubtitle( wfMsgHtml( 'redirectpagesub' ) );
@@ -1065,7 +1073,7 @@ class Article extends Page {
                }
 
                $nextRedirect = $wgStylePath . '/common/images/nextredirect' . $imageDir . '.png';
-               $alt = wfUILang()->isRTL() ? '←' : '→';
+               $alt = $lang->isRTL() ? '←' : '→';
                // Automatically append redirect=no to each link, since most of them are redirect pages themselves.
                foreach ( $target as $rt ) {
                        $link .= Html::element( 'img', array( 'src' => $nextRedirect, 'alt' => $alt ) );
@@ -1124,7 +1132,7 @@ class Article extends Page {
 
        /**
         * Removes trackback record for current article from trackbacks table
-        * @deprecated since 1.19
+        * @deprecated since 1.18
         */
        public function deletetrackback() {
                return Action::factory( 'deletetrackback', $this )->show();
@@ -1150,7 +1158,7 @@ class Article extends Page {
 
        /**
         * Mark this particular edit/page as patrolled
-        * @deprecated since 1.19
+        * @deprecated since 1.18
         */
        public function markpatrolled() {
                Action::factory( 'markpatrolled', $this )->show();
@@ -1158,7 +1166,7 @@ class Article extends Page {
 
        /**
         * User-interface handler for the "watch" action.
-        * Requires Request to pass a token as of 1.19.
+        * Requires Request to pass a token as of 1.18.
         * @deprecated since 1.18
         */
        public function watch() {
@@ -1180,7 +1188,7 @@ class Article extends Page {
 
        /**
         * User interface handler for the "unwatch" action.
-        * Requires Request to pass a token as of 1.19.
+        * Requires Request to pass a token as of 1.18.
         * @deprecated since 1.18
         */
        public function unwatch() {
@@ -1239,7 +1247,7 @@ class Article extends Page {
         * Output a redirect back to the article.
         * This is typically used after an edit.
         *
-        * @deprecated in 1.19; call $wgOut->redirect() directly
+        * @deprecated in 1.18; call $wgOut->redirect() directly
         * @param $noRedir Boolean: add redirect=no
         * @param $sectionAnchor String: section to redirect to, including "#"
         * @param $extraQuery String: extra query params
@@ -1259,101 +1267,6 @@ class Article extends Page {
                $wgOut->redirect( $this->getTitle()->getFullURL( $query ) . $sectionAnchor );
        }
 
-       /**
-        * Auto-generates a deletion reason
-        *
-        * @param &$hasHistory Boolean: whether the page has a history
-        * @return mixed String containing deletion reason or empty string, or boolean false
-        *    if no revision occurred
-        */
-       public function generateReason( &$hasHistory ) {
-               global $wgContLang;
-
-               $dbw = wfGetDB( DB_MASTER );
-               // Get the last revision
-               $rev = Revision::newFromTitle( $this->getTitle() );
-
-               if ( is_null( $rev ) ) {
-                       return false;
-               }
-
-               // Get the article's contents
-               $contents = $rev->getText();
-               $blank = false;
-
-               // If the page is blank, use the text from the previous revision,
-               // which can only be blank if there's a move/import/protect dummy revision involved
-               if ( $contents == '' ) {
-                       $prev = $rev->getPrevious();
-
-                       if ( $prev )    {
-                               $contents = $prev->getText();
-                               $blank = true;
-                       }
-               }
-
-               // Find out if there was only one contributor
-               // Only scan the last 20 revisions
-               $res = $dbw->select( 'revision', 'rev_user_text',
-                       array( 'rev_page' => $this->mPage->getID(), $dbw->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0' ),
-                       __METHOD__,
-                       array( 'LIMIT' => 20 )
-               );
-
-               if ( $res === false ) {
-                       // This page has no revisions, which is very weird
-                       return false;
-               }
-
-               $hasHistory = ( $res->numRows() > 1 );
-               $row = $dbw->fetchObject( $res );
-
-               if ( $row ) { // $row is false if the only contributor is hidden
-                       $onlyAuthor = $row->rev_user_text;
-                       // Try to find a second contributor
-                       foreach ( $res as $row ) {
-                               if ( $row->rev_user_text != $onlyAuthor ) { // Bug 22999
-                                       $onlyAuthor = false;
-                                       break;
-                               }
-                       }
-               } else {
-                       $onlyAuthor = false;
-               }
-
-               // Generate the summary with a '$1' placeholder
-               if ( $blank ) {
-                       // The current revision is blank and the one before is also
-                       // blank. It's just not our lucky day
-                       $reason = wfMsgForContent( 'exbeforeblank', '$1' );
-               } else {
-                       if ( $onlyAuthor ) {
-                               $reason = wfMsgForContent( 'excontentauthor', '$1', $onlyAuthor );
-                       } else {
-                               $reason = wfMsgForContent( 'excontent', '$1' );
-                       }
-               }
-
-               if ( $reason == '-' ) {
-                       // Allow these UI messages to be blanked out cleanly
-                       return '';
-               }
-
-               // Replace newlines with spaces to prevent uglyness
-               $contents = preg_replace( "/[\n\r]/", ' ', $contents );
-               // Calculate the maximum amount of chars to get
-               // Max content length = max comment length - length of the comment (excl. $1)
-               $maxLength = 255 - ( strlen( $reason ) - 2 );
-               $contents = $wgContLang->truncate( $contents, $maxLength );
-               // Remove possible unfinished links
-               $contents = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $contents );
-               // Now replace the '$1' placeholder
-               $reason = str_replace( '$1', $contents, $reason );
-
-               return $reason;
-       }
-
-
        /**
         * UI entry point for page deletion
         */
@@ -1764,7 +1677,7 @@ class Article extends Page {
                        "\n\t\t\t\t<div id=\"mw-revision-nav\">" . $cdel . wfMsgExt( 'revision-nav', array( 'escapenoentities', 'parsemag', 'replaceafter' ),
                        $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff ) . "</div>\n\t\t\t";
 
-               $wgOut->addHTML( $r );
+               $wgOut->setSubtitle( $r );
        }
 
        /* Caching functions */
@@ -1856,6 +1769,7 @@ class Article extends Page {
                global $wgEnableParserCache, $wgUser;
                $user = is_null( $user ) ? $wgUser : $user;
 
+               wfProfileIn( __METHOD__ );
                // Should the parser cache be used?
                $useParserCache = $wgEnableParserCache &&
                        $user->getStubThreshold() == 0 &&
@@ -1871,6 +1785,7 @@ class Article extends Page {
                if ( $useParserCache ) {
                        $parserOutput = ParserCache::singleton()->get( $this, $this->mPage->getParserOptions() );
                        if ( $parserOutput !== false ) {
+                               wfProfileOut( __METHOD__ );
                                return $parserOutput;
                        }
                }
@@ -1881,12 +1796,15 @@ class Article extends Page {
                } else {
                        $rev = Revision::newFromTitle( $this->getTitle(), $oldid );
                        if ( $rev === null ) {
+                               wfProfileOut( __METHOD__ );
                                return false;
                        }
                        $text = $rev->getText();
                }
 
-               return $this->getOutputFromWikitext( $text, $useParserCache );
+               $output = $this->getOutputFromWikitext( $text, $useParserCache );
+               wfProfileOut( __METHOD__ );
+               return $output;
        }
 
        /**
@@ -1897,7 +1815,7 @@ class Article extends Page {
         * @param $text string
         * @param $cache boolean
         * @param $parserOptions parsing options, defaults to false
-        * @return string containing parsed output
+        * @return ParserOutput
         */
        public function getOutputFromWikitext( $text, $cache = true, $parserOptions = false ) {
                global $wgParser, $wgEnableParserCache, $wgUseFileCache;
@@ -1929,66 +1847,17 @@ class Article extends Page {
                        $wgUseFileCache = false;
                }
 
-               $this->doCascadeProtectionUpdates( $this->mParserOutput );
-
-               return $this->mParserOutput;
-       }
-
-       /**
-        * Updates cascading protections
-        *
-        * @param $parserOutput ParserOutput object, or boolean false
-        **/
-       protected function doCascadeProtectionUpdates( $parserOutput ) {
-               if ( !$this->isCurrent() || wfReadOnly() || !$this->getTitle()->areRestrictionsCascading() ) {
-                       return;
-               }
-
-               // templatelinks table may have become out of sync,
-               // especially if using variable-based transclusions.
-               // For paranoia, check if things have changed and if
-               // so apply updates to the database. This will ensure
-               // that cascaded protections apply as soon as the changes
-               // are visible.
-
-               # Get templates from templatelinks
-               $id = $this->getTitle()->getArticleID();
-
-               $tlTemplates = array();
-
-               $dbr = wfGetDB( DB_SLAVE );
-               $res = $dbr->select( array( 'templatelinks' ),
-                       array( 'tl_namespace', 'tl_title' ),
-                       array( 'tl_from' => $id ),
-                       __METHOD__
-               );
-
-               foreach ( $res as $row ) {
-                       $tlTemplates["{$row->tl_namespace}:{$row->tl_title}"] = true;
+               if ( $this->isCurrent() ) {
+                       $this->mPage->doCascadeProtectionUpdates( $this->mParserOutput );
                }
 
-               # Get templates from parser output.
-               $poTemplates = array();
-               foreach ( $parserOutput->getTemplates() as $ns => $templates ) {
-                       foreach ( $templates as $dbk => $id ) {
-                               $poTemplates["$ns:$dbk"] = true;
-                       }
-               }
-
-               # Get the diff
-               $templates_diff = array_diff_key( $poTemplates, $tlTemplates );
-
-               if ( count( $templates_diff ) > 0 ) {
-                       # Whee, link updates time.
-                       $u = new LinksUpdate( $this->getTitle(), $parserOutput, false );
-                       $u->doUpdate();
-               }
+               return $this->mParserOutput;
        }
 
        /**
         * Sets the context this Article is executed in
         *
-        * @param $context RequestContext
+        * @param $context IContextSource
         * @since 1.18
         */
        public function setContext( $context ) {
@@ -1998,11 +1867,11 @@ class Article extends Page {
        /**
         * Gets the context this Article is executed in
         *
-        * @return RequestContext
+        * @return IContextSource
         * @since 1.18
         */
        public function getContext() {
-               if ( $this->mContext instanceof RequestContext ) {
+               if ( $this->mContext instanceof IContextSource ) {
                        return $this->mContext;
                } else {
                        wfDebug( __METHOD__ . " called and \$mContext is null. Return RequestContext::getMain(); for sanity\n" );
@@ -2021,7 +1890,7 @@ class Article extends Page {
                        #wfWarn( "Access to raw $fname field " . __CLASS__ );
                        return $this->mPage->$fname;
                }
-        trigger_error( 'Inaccessible property via __get(): ' . $fname, E_USER_NOTICE );
+               trigger_error( 'Inaccessible property via __get(): ' . $fname, E_USER_NOTICE );
        }
 
        /**
@@ -2030,7 +1899,6 @@ class Article extends Page {
         *
         * @param $fname String Field name
         * @param $fvalue mixed New value
-        * @param $args Array Arguments to the method
         */
        public function __set( $fname, $fvalue ) {
                if ( property_exists( $this->mPage, $fname ) ) {
@@ -2040,7 +1908,7 @@ class Article extends Page {
                } elseif ( !in_array( $fname, array( 'mContext', 'mPage' ) ) ) {
                        $this->mPage->$fname = $fvalue;
                } else {
-                       trigger_error( 'Inaccessible property via __get(): ' . $fname, E_USER_NOTICE );
+                       trigger_error( 'Inaccessible property via __set(): ' . $fname, E_USER_NOTICE );
                }
        }
 
@@ -2056,7 +1924,7 @@ class Article extends Page {
                        #wfWarn( "Call to " . __CLASS__ . "::$fname; please use WikiPage instead" );
                        return call_user_func_array( array( $this->mPage, $fname ), $args );
                }
-        trigger_error( 'Inaccessible function via __call(): ' . $fname, E_USER_ERROR );
+               trigger_error( 'Inaccessible function via __call(): ' . $fname, E_USER_ERROR );
        }
 
        // ****** B/C functions to work-around PHP silliness with __call and references ****** //
@@ -2068,12 +1936,20 @@ class Article extends Page {
                return $this->mPage->doDeleteArticle( $reason, $suppress, $id, $commit, $error );
        }
 
-       public function doRollback( $fromP, $summary, $token, $bot, &$resultDetails ) {
-               return $this->mPage->doRollback( $fromP, $summary, $token, $bot, $resultDetails );
+       public function doRollback( $fromP, $summary, $token, $bot, &$resultDetails, User $user = null ) {
+               global $wgUser;
+               $user = is_null( $user ) ? $wgUser : $user;
+               return $this->mPage->doRollback( $fromP, $summary, $token, $bot, $resultDetails, $user );
        }
 
-       public function commitRollback( $fromP, $summary, $bot, &$resultDetails ) {
-               return $this->mPage->commitRollback( $fromP, $summary, $bot, $resultDetails );
+       public function commitRollback( $fromP, $summary, $bot, &$resultDetails, User $guser = null ) {
+               global $wgUser;
+               $guser = is_null( $guser ) ? $wgUser : $guser;
+               return $this->mPage->commitRollback( $fromP, $summary, $bot, $resultDetails, $guser );
+       }
+
+       public function generateReason( &$hasHistory ) {
+               return $this->mPage->getAutoDeleteReason( $hasHistory );
        }
 
        // ****** B/C functions for static methods ( __callStatic is PHP>=5.3 ) ****** //
@@ -2139,7 +2015,7 @@ class PoolWorkArticleView extends PoolCounterWork {
        }
 
        /**
-        * @param  $status Status
+        * @param $status Status
         */
        function error( $status ) {
                global $wgOut;