docs: Remove odd colons after @todo
[lhc/web/wiklou.git] / includes / WikiPage.php
index c016b18..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();
@@ -797,7 +799,7 @@ class WikiPage implements Page, IDBAccessObject {
        public function setCachedLastEditTime( $timestamp ) {
                global $wgMemc;
                $key = wfMemcKey( 'page-lastedit', md5( $this->mTitle->getPrefixedDBkey() ) );
-               $wgMemc->set( $key, wfTimestamp( TS_MW, $timestamp ), 60*15 );
+               $wgMemc->set( $key, wfTimestamp( TS_MW, $timestamp ), 60 * 15 );
        }
 
        /**
@@ -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
@@ -3019,69 +3028,76 @@ class WikiPage implements Page, IDBAccessObject {
         * @param array $added   The names of categories that were added
         * @param array $deleted The names of categories that were deleted
         */
-       public function updateCategoryCounts( $added, $deleted ) {
-               $ns = $this->mTitle->getNamespace();
+       public function updateCategoryCounts( array $added, array $deleted ) {
+               $that = $this;
+               $method = __METHOD__;
                $dbw = wfGetDB( DB_MASTER );
 
-               // First make sure the rows exist.  If one of the "deleted" ones didn't
-               // exist, we might legitimately not create it, but it's simpler to just
-               // create it and then give it a negative value, since the value is bogus
-               // anyway.
-               //
-               // Sometimes I wish we had INSERT ... ON DUPLICATE KEY UPDATE.
-               $insertCats = array_merge( $added, $deleted );
-               if ( !$insertCats ) {
-                       // Okay, nothing to do
-                       return;
-               }
+               // Do this at the end of the commit to reduce lock wait timeouts
+               $dbw->onTransactionPreCommitOrIdle(
+                       function() use ( $dbw, $that, $method, $added, $deleted ) {
+                               $ns = $that->getTitle()->getNamespace();
 
-               $insertRows = array();
+                               // First make sure the rows exist.  If one of the "deleted" ones didn't
+                               // exist, we might legitimately not create it, but it's simpler to just
+                               // create it and then give it a negative value, since the value is bogus
+                               // anyway.
+                               //
+                               // Sometimes I wish we had INSERT ... ON DUPLICATE KEY UPDATE.
+                               $insertCats = array_merge( $added, $deleted );
+                               if ( !$insertCats ) {
+                                       // Okay, nothing to do
+                                       return;
+                               }
 
-               foreach ( $insertCats as $cat ) {
-                       $insertRows[] = array(
-                               'cat_id' => $dbw->nextSequenceValue( 'category_cat_id_seq' ),
-                               'cat_title' => $cat
-                       );
-               }
-               $dbw->insert( 'category', $insertRows, __METHOD__, 'IGNORE' );
+                               $insertRows = array();
+                               foreach ( $insertCats as $cat ) {
+                                       $insertRows[] = array(
+                                               'cat_id' => $dbw->nextSequenceValue( 'category_cat_id_seq' ),
+                                               'cat_title' => $cat
+                                       );
+                               }
+                               $dbw->insert( 'category', $insertRows, $method, 'IGNORE' );
 
-               $addFields = array( 'cat_pages = cat_pages + 1' );
-               $removeFields = array( 'cat_pages = cat_pages - 1' );
+                               $addFields = array( 'cat_pages = cat_pages + 1' );
+                               $removeFields = array( 'cat_pages = cat_pages - 1' );
 
-               if ( $ns == NS_CATEGORY ) {
-                       $addFields[] = 'cat_subcats = cat_subcats + 1';
-                       $removeFields[] = 'cat_subcats = cat_subcats - 1';
-               } elseif ( $ns == NS_FILE ) {
-                       $addFields[] = 'cat_files = cat_files + 1';
-                       $removeFields[] = 'cat_files = cat_files - 1';
-               }
+                               if ( $ns == NS_CATEGORY ) {
+                                       $addFields[] = 'cat_subcats = cat_subcats + 1';
+                                       $removeFields[] = 'cat_subcats = cat_subcats - 1';
+                               } elseif ( $ns == NS_FILE ) {
+                                       $addFields[] = 'cat_files = cat_files + 1';
+                                       $removeFields[] = 'cat_files = cat_files - 1';
+                               }
 
-               if ( $added ) {
-                       $dbw->update(
-                               'category',
-                               $addFields,
-                               array( 'cat_title' => $added ),
-                               __METHOD__
-                       );
-               }
+                               if ( $added ) {
+                                       $dbw->update(
+                                               'category',
+                                               $addFields,
+                                               array( 'cat_title' => $added ),
+                                               $method
+                                       );
+                               }
 
-               if ( $deleted ) {
-                       $dbw->update(
-                               'category',
-                               $removeFields,
-                               array( 'cat_title' => $deleted ),
-                               __METHOD__
-                       );
-               }
+                               if ( $deleted ) {
+                                       $dbw->update(
+                                               'category',
+                                               $removeFields,
+                                               array( 'cat_title' => $deleted ),
+                                               $method
+                                       );
+                               }
 
-               foreach( $added as $catName ) {
-                       $cat = Category::newFromName( $catName );
-                       wfRunHooks( 'CategoryAfterPageAdded', array( $cat, $this ) );
-               }
-               foreach( $deleted as $catName ) {
-                       $cat = Category::newFromName( $catName );
-                       wfRunHooks( 'CategoryAfterPageRemoved', array( $cat, $this ) );
-               }
+                               foreach ( $added as $catName ) {
+                                       $cat = Category::newFromName( $catName );
+                                       wfRunHooks( 'CategoryAfterPageAdded', array( $cat, $that ) );
+                               }
+                               foreach ( $deleted as $catName ) {
+                                       $cat = Category::newFromName( $catName );
+                                       wfRunHooks( 'CategoryAfterPageRemoved', array( $cat, $that ) );
+                               }
+                       }
+               );
        }
 
        /**
@@ -3387,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();