Merge "Slight improvements to FormSpecialPage behavior."
[lhc/web/wiklou.git] / includes / WikiPage.php
index 5aba23c..b8f4911 100644 (file)
@@ -187,7 +187,7 @@ class WikiPage implements Page, IDBAccessObject {
         * (and only when) $wgActions[$action] === true. This allows subclasses
         * to override the default behavior.
         *
-        * @todo: move this UI stuff somewhere else
+        * @todo Move this UI stuff somewhere else
         *
         * @return Array
         */
@@ -305,7 +305,7 @@ class WikiPage implements Page, IDBAccessObject {
        public function pageDataFromTitle( $dbr, $title, $options = array() ) {
                return $this->pageData( $dbr, array(
                        'page_namespace' => $title->getNamespace(),
-                       'page_title'     => $title->getDBkey() ), $options );
+                       'page_title' => $title->getDBkey() ), $options );
        }
 
        /**
@@ -462,7 +462,9 @@ class WikiPage implements Page, IDBAccessObject {
         */
        public function isRedirect() {
                $content = $this->getContent();
-               if ( !$content ) return false;
+               if ( !$content ) {
+                       return false;
+               }
 
                return $content->isRedirect();
        }
@@ -646,7 +648,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @return String|false The text of the current revision
         * @deprecated as of 1.21, getContent() should be used instead.
         */
-       public function getText( $audience = Revision::FOR_PUBLIC, User $user = null ) { // @todo: deprecated, replace usage!
+       public function getText( $audience = Revision::FOR_PUBLIC, User $user = null ) { // @todo deprecated, replace usage!
                ContentHandler::deprecated( __METHOD__, '1.21' );
 
                $this->loadLastEdit();
@@ -906,10 +908,10 @@ class WikiPage implements Page, IDBAccessObject {
                $dbw = wfGetDB( DB_MASTER );
                $dbw->replace( 'redirect', array( 'rd_from' ),
                        array(
-                               'rd_from'      => $this->getId(),
+                               'rd_from' => $this->getId(),
                                'rd_namespace' => $rt->getNamespace(),
-                               'rd_title'     => $rt->getDBkey(),
-                               'rd_fragment'  => $rt->getFragment(),
+                               'rd_title' => $rt->getDBkey(),
+                               'rd_fragment' => $rt->getFragment(),
                                'rd_interwiki' => $rt->getInterwiki(),
                        ),
                        __METHOD__
@@ -944,7 +946,7 @@ class WikiPage implements Page, IDBAccessObject {
                                // This can be hard to reverse and may produce loops,
                                // so they may be disabled in the site configuration.
                                $source = $this->mTitle->getFullURL( 'redirect=no' );
-                               return $rt->getFullURL( 'rdfrom=' . urlencode( $source ) );
+                               return $rt->getFullURL( array( 'rdfrom' => $source ) );
                        } else {
                                // External pages pages without "local" bit set are not valid
                                // redirect targets
@@ -1155,7 +1157,7 @@ class WikiPage implements Page, IDBAccessObject {
        public function doPurge() {
                global $wgUseSquid;
 
-               if( !wfRunHooks( 'ArticlePurge', array( &$this ) ) ) {
+               if ( !wfRunHooks( 'ArticlePurge', array( &$this ) ) ) {
                        return false;
                }
 
@@ -1173,7 +1175,7 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
-                       // @todo: move this logic to MessageCache
+                       // @todo move this logic to MessageCache
 
                        if ( $this->exists() ) {
                                // NOTE: use transclusion text for messages.
@@ -1182,7 +1184,9 @@ class WikiPage implements Page, IDBAccessObject {
                                $content = $this->getContent();
                                $text = $content === null ? null : $content->getWikitextForTransclusion();
 
-                               if ( $text === null ) $text = false;
+                               if ( $text === null ) {
+                                       $text = false;
+                               }
                        } else {
                                $text = false;
                        }
@@ -1455,8 +1459,8 @@ class WikiPage implements Page, IDBAccessObject {
         *
         * @return boolean whether sections are supported.
         *
-        * @todo: the skin should check this and not offer section functionality if sections are not supported.
-        * @todo: the EditPage should check this and not offer section functionality if sections are not supported.
+        * @todo The skin should check this and not offer section functionality if sections are not supported.
+        * @todo The EditPage should check this and not offer section functionality if sections are not supported.
         */
        public function supportsSections() {
                return $this->getContentHandler()->supportsSections();
@@ -1698,7 +1702,9 @@ class WikiPage implements Page, IDBAccessObject {
 
                // Provide autosummaries if one is not provided and autosummaries are enabled.
                if ( $wgUseAutomaticEditSummaries && $flags & EDIT_AUTOSUMMARY && $summary == '' ) {
-                       if ( !$old_content ) $old_content = null;
+                       if ( !$old_content ) {
+                               $old_content = null;
+                       }
                        $summary = $handler->getAutosummary( $old_content, $content, $flags );
                }
 
@@ -1950,7 +1956,7 @@ class WikiPage implements Page, IDBAccessObject {
                $options = $this->getContentHandler()->makeParserOptions( $context );
 
                if ( $this->getTitle()->isConversionTable() ) {
-                       //@todo: ConversionTable should become a separate content model, so we don't need special cases like this one.
+                       // @todo ConversionTable should become a separate content model, so we don't need special cases like this one.
                        $options->disableContentConversion();
                }
 
@@ -2047,7 +2053,8 @@ class WikiPage implements Page, IDBAccessObject {
                $content = $revision->getContent();
 
                // Parse the text
-               // Be careful not to double-PST: $text is usually already PST-ed once
+               // Be careful not to do pre-save transform twice: $text is usually
+               // already pre-save transformed once.
                if ( !$this->mPreparedEdit || $this->mPreparedEdit->output->getFlag( 'vary-revision' ) ) {
                        wfDebug( __METHOD__ . ": No prepared edit or vary-revision is set...\n" );
                        $editInfo = $this->prepareContentForEdit( $content, $revision->getId(), $user );
@@ -2074,15 +2081,7 @@ class WikiPage implements Page, IDBAccessObject {
                        if ( 0 == mt_rand( 0, 99 ) ) {
                                // Flush old entries from the `recentchanges` table; we do this on
                                // random requests so as to avoid an increase in writes for no good reason
-                               global $wgRCMaxAge;
-
-                               $dbw = wfGetDB( DB_MASTER );
-                               $cutoff = $dbw->timestamp( time() - $wgRCMaxAge );
-                               $dbw->delete(
-                                       'recentchanges',
-                                       array( 'rc_timestamp < ' . $dbw->addQuotes( $cutoff ) ),
-                                       __METHOD__
-                               );
+                               RecentChange::purgeExpiredChanges();
                        }
                }
 
@@ -2111,7 +2110,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 1, $good, $total ) );
                DeferredUpdates::addUpdate( new SearchUpdate( $id, $title, $content->getTextForSearchIndex() ) );
-               // @TODO: let the search engine decide what to do with the content object
+               // @todo let the search engine decide what to do with the content object
 
                // If this is another user's talk page, update newtalk.
                // Don't do this if $options['changed'] = false (null-edits) nor if
@@ -2121,17 +2120,20 @@ class WikiPage implements Page, IDBAccessObject {
                        && $shortTitle != $user->getTitleKey()
                        && !( $revision->isMinor() && $user->isAllowed( 'nominornewtalk' ) )
                ) {
-                       if ( wfRunHooks( 'ArticleEditUpdateNewTalk', array( &$this ) ) ) {
-                               $other = User::newFromName( $shortTitle, false );
-                               if ( !$other ) {
-                                       wfDebug( __METHOD__ . ": invalid username\n" );
-                               } elseif ( User::isIP( $shortTitle ) ) {
-                                       // An anonymous user
-                                       $other->setNewtalk( true, $revision );
-                               } elseif ( $other->isLoggedIn() ) {
-                                       $other->setNewtalk( true, $revision );
-                               } else {
-                                       wfDebug( __METHOD__ . ": don't need to notify a nonexistent user\n" );
+                       $recipient = User::newFromName( $shortTitle, false );
+                       if ( !$recipient ) {
+                               wfDebug( __METHOD__ . ": invalid username\n" );
+                       } else {
+                               // Allow extensions to prevent user notification when a new message is added to their talk page
+                               if ( wfRunHooks( 'ArticleEditUpdateNewTalk', array( &$this, $recipient ) ) ) {
+                                       if ( User::isIP( $shortTitle ) ) {
+                                               // An anonymous user
+                                               $recipient->setNewtalk( true, $revision );
+                                       } elseif ( $recipient->isLoggedIn() ) {
+                                               $recipient->setNewtalk( true, $revision );
+                                       } else {
+                                               wfDebug( __METHOD__ . ": don't need to notify a nonexistent user\n" );
+                                       }
                                }
                        }
                }
@@ -2139,12 +2141,14 @@ class WikiPage implements Page, IDBAccessObject {
                if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
                        // XXX: could skip pseudo-messages like js/css here, based on content model.
                        $msgtext = $content ? $content->getWikitextForTransclusion() : null;
-                       if ( $msgtext === false || $msgtext === null ) $msgtext = '';
+                       if ( $msgtext === false || $msgtext === null ) {
+                               $msgtext = '';
+                       }
 
                        MessageCache::singleton()->replace( $shortTitle, $msgtext );
                }
 
-               if( $options['created'] ) {
+               if ( $options['created'] ) {
                        self::onArticleCreate( $this->mTitle );
                } else {
                        self::onArticleEdit( $this->mTitle );
@@ -2217,7 +2221,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @return Status
         */
        public function doUpdateRestrictions( array $limit, array $expiry, &$cascade, $reason, User $user ) {
-               global $wgContLang;
+               global $wgContLang, $wgCascadingRestrictionLevels;
 
                if ( wfReadOnly() ) {
                        return Status::newFatal( 'readonlytext', wfReadOnlyReason() );
@@ -2340,12 +2344,17 @@ class WikiPage implements Page, IDBAccessObject {
                                return Status::newGood();
                        }
 
-                       // Only restrictions with the 'protect' right can cascade...
-                       // Otherwise, people who cannot normally protect can "protect" pages via transclusion
+                       // Only certain restrictions can cascade... Otherwise, users who cannot normally protect pages
+                       // could "protect" them by transcluding them on protected pages they are allowed to edit.
                        $editrestriction = isset( $limit['edit'] ) ? array( $limit['edit'] ) : $this->mTitle->getRestrictions( 'edit' );
 
+                       $cascadingRestrictionLevels = $wgCascadingRestrictionLevels;
+                       if ( in_array( 'sysop', $cascadingRestrictionLevels ) ) {
+                               $cascadingRestrictionLevels[] = 'protect'; // backwards compatibility
+                       }
+
                        // The schema allows multiple restrictions
-                       if ( !in_array( 'protect', $editrestriction ) && !in_array( 'sysop', $editrestriction ) ) {
+                       if ( !array_intersect( $editrestriction, $cascadingRestrictionLevels ) ) {
                                $cascade = false;
                        }
 
@@ -2664,7 +2673,7 @@ class WikiPage implements Page, IDBAccessObject {
         * performs permissions checks on $user, then calls commitRollback()
         * to do the dirty work
         *
-        * @todo: separate the business/permission stuff out from backend code
+        * @todo Separate the business/permission stuff out from backend code
         *
         * @param string $fromP Name of the user whose edits to rollback.
         * @param string $summary Custom summary. Set to default summary if empty.
@@ -2808,7 +2817,7 @@ class WikiPage implements Page, IDBAccessObject {
                        $wgContLang->timeanddate( wfTimestamp( TS_MW, $s->rev_timestamp ) ),
                        $current->getId(), $wgContLang->timeanddate( $current->getTimestamp() )
                );
-               if( $summary instanceof Message ) {
+               if ( $summary instanceof Message ) {
                        $summary = $summary->params( $args )->inContentLanguage()->text();
                } else {
                        $summary = wfMsgReplaceArgs( $summary, $args );
@@ -2849,8 +2858,8 @@ class WikiPage implements Page, IDBAccessObject {
                $resultDetails = array(
                        'summary' => $summary,
                        'current' => $current,
-                       'target'  => $target,
-                       'newid'   => $revId
+                       'target' => $target,
+                       'newid' => $revId
                );
 
                return array();
@@ -2932,7 +2941,7 @@ class WikiPage implements Page, IDBAccessObject {
         * Purge caches on page update etc
         *
         * @param $title Title object
-        * @todo:  verify that $title is always a Title object (and never false or null), add Title hint to parameter $title
+        * @todo Verify that $title is always a Title object (and never false or null), add Title hint to parameter $title
         */
        public static function onArticleEdit( $title ) {
                // Invalidate caches of articles which include this page
@@ -3079,11 +3088,11 @@ class WikiPage implements Page, IDBAccessObject {
                                        );
                                }
 
-                               foreach( $added as $catName ) {
+                               foreach ( $added as $catName ) {
                                        $cat = Category::newFromName( $catName );
                                        wfRunHooks( 'CategoryAfterPageAdded', array( $cat, $that ) );
                                }
-                               foreach( $deleted as $catName ) {
+                               foreach ( $deleted as $catName ) {
                                        $cat = Category::newFromName( $catName );
                                        wfRunHooks( 'CategoryAfterPageRemoved', array( $cat, $that ) );
                                }
@@ -3394,7 +3403,7 @@ class PoolWorkArticleView extends PoolCounterWork {
        function doWork() {
                global $wgUseFileCache;
 
-               // @todo: several of the methods called on $this->page are not declared in Page, but present
+               // @todo several of the methods called on $this->page are not declared in Page, but present
                //        in WikiPage and delegated by Article.
 
                $isCurrent = $this->revid === $this->page->getLatest();