Refactor deferrable updates into classes & interfaces, also add helper method for...
authorChad Horohoe <demon@users.mediawiki.org>
Sat, 10 Sep 2011 06:50:30 +0000 (06:50 +0000)
committerChad Horohoe <demon@users.mediawiki.org>
Sat, 10 Sep 2011 06:50:30 +0000 (06:50 +0000)
$wgDeferredUpdateList[] = new HTMLCacheUpdate( $title, "sometable" );

I kept b/c with $wgDeferredUpdateList for now, but seeing as only 3 exts in svn use it (FileSearch, FlaggedRevs and WikiScripts), I'd like to deprecate it pretty soon :)

12 files changed:
includes/AutoLoader.php
includes/DeferredUpdates.php [new file with mode: 0644]
includes/GlobalFunctions.php
includes/SiteStats.php
includes/ViewCountUpdate.php
includes/Wiki.php
includes/WikiPage.php
includes/cache/HTMLCacheUpdate.php
includes/search/SearchUpdate.php
maintenance/importDump.php
tests/parser/parserTest.inc
tests/phpunit/suites/UploadFromUrlTestSuite.php

index 4c8c716..d407ca6 100644 (file)
@@ -49,6 +49,8 @@ $wgAutoloadLocalClasses = array(
        'ContextSource' => 'includes/RequestContext.php',
        'Cookie' => 'includes/Cookie.php',
        'CookieJar' => 'includes/Cookie.php',
+       'DeferrableUpdate' => 'includes/DeferredUpdates.php',
+       'DeferredUpdates' => 'includes/DeferredUpdates.php',
        'DiffHistoryBlob' => 'includes/HistoryBlob.php',
        'DjVuImage' => 'includes/DjVuImage.php',
        'DoubleReplacer' => 'includes/StringUtils.php',
diff --git a/includes/DeferredUpdates.php b/includes/DeferredUpdates.php
new file mode 100644 (file)
index 0000000..28783d2
--- /dev/null
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Interface that deferrable updates should implement. Basically required so we
+ * can validate input on DeferredUpdates::addUpdate()
+ */
+interface DeferrableUpdate {
+       /**
+        * Perform the actual work
+        */
+       function doUpdate();
+}
+
+/**
+ * Class for mananging the deferred updates.
+ */
+class DeferredUpdates {
+       /**
+        * Store of updates to be deferred until the end of the request.
+        */
+       private static $updates = array();
+
+       /**
+        * Add an update to the deferred list
+        * @param $update DeferrableUpdate Some object that implements doUpdate()
+        */
+       public static function addUpdate( DeferrableUpdate $update ) {
+               array_push( self::$updates, $update );
+       }
+
+       /**
+        * HTMLCacheUpdates are the most common deferred update people use. This
+        * is a shortcut method for that.
+        * @see HTMLCacheUpdate::__construct()
+        */
+       public static function addHTMLCacheUpdate( $title, $table ) {
+               self::addUpdate( new HTMLCacheUpdate( $title, $table ) );
+       }
+
+       /**
+        * Do any deferred updates and clear the list
+        *
+        * @param $commit String: set to 'commit' to commit after every update to
+        *                prevent lock contention
+        */
+       public static function doUpdates( $commit = '' ) {
+               global $wgDeferredUpdateList;
+
+               wfProfileIn( __METHOD__ );
+
+               $updates = array_merge( $wgDeferredUpdateList, self::$updates );
+
+               // No need to get master connections in case of empty updates array
+               if ( !count( $updates ) ) {
+                       wfProfileOut( __METHOD__ );
+                       return;
+               }
+
+               $doCommit = $commit == 'commit';
+               if ( $doCommit ) {
+                       $dbw = wfGetDB( DB_MASTER );
+               }
+
+               foreach ( $updates as $update ) {
+                       $update->doUpdate();
+
+                       if ( $doCommit && $dbw->trxLevel() ) {
+                               $dbw->commit();
+                       }
+               }
+
+               self::clearPendingUpdates();
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Clear all pending updates without performing them. Generally, you don't
+        * want or need to call this. Unit tests need it though.
+        */
+       public static function clearPendingUpdates() {
+               global $wgDeferredUpdateList;
+               $wgDeferredUpdateList = self::$updates = array();
+       }
+}
index 9431f9c..6b46c3f 100644 (file)
@@ -2918,35 +2918,11 @@ function wfRelativePath( $path, $from ) {
 /**
  * Do any deferred updates and clear the list
  *
- * @param $commit String: set to 'commit' to commit after every update to
- *                prevent lock contention
+ * @deprecated since 1.19
+ * @see DeferredUpdates::doUpdate()
  */
 function wfDoUpdates( $commit = '' ) {
-       global $wgDeferredUpdateList;
-
-       wfProfileIn( __METHOD__ );
-
-       // No need to get master connections in case of empty updates array
-       if ( !count( $wgDeferredUpdateList ) ) {
-               wfProfileOut( __METHOD__ );
-               return;
-       }
-
-       $doCommit = $commit == 'commit';
-       if ( $doCommit ) {
-               $dbw = wfGetDB( DB_MASTER );
-       }
-
-       foreach ( $wgDeferredUpdateList as $update ) {
-               $update->doUpdate();
-
-               if ( $doCommit && $dbw->trxLevel() ) {
-                       $dbw->commit();
-               }
-       }
-
-       $wgDeferredUpdateList = array();
-       wfProfileOut( __METHOD__ );
+       DeferredUpdates::doUpdates( $commit );
 }
 
 /**
index e3d371c..e9137fe 100644 (file)
@@ -220,9 +220,9 @@ class SiteStats {
 }
 
 /**
- *
+ * Class for handling updates to the site_stats table
  */
-class SiteStatsUpdate {
+class SiteStatsUpdate implements DeferrableUpdate {
 
        var $mViews, $mEdits, $mGood, $mPages, $mUsers;
 
index 0642b63..a30b0f7 100644 (file)
@@ -27,7 +27,7 @@
  * 'page_counter' field or use the 'hitcounter' table and then collect the data
  * from that table to update the 'page_counter' field in a batch operation.
  */
-class ViewCountUpdate {
+class ViewCountUpdate implements DeferrableUpdate {
        protected $id;
 
        /**
index 5113a9d..ca8584b 100644 (file)
@@ -377,7 +377,7 @@ class MediaWiki {
                // Output everything!
                $this->context->getOutput()->output();
                // Do any deferred jobs
-               wfDoUpdates( 'commit' );
+               DeferredUpdates::doUpdates( 'commit' );
                $this->doJobs();
                wfProfileOut( __METHOD__ );
        }
index aca2b0c..88182e9 100644 (file)
@@ -1275,7 +1275,7 @@ class WikiPage extends Page {
 
                # Do updates right now unless deferral was requested
                if ( !( $flags & EDIT_DEFER_UPDATES ) ) {
-                       wfDoUpdates();
+                       DeferredUpdates::doUpdates();
                }
 
                // Return the new revision (or null) to the caller
@@ -1604,7 +1604,7 @@ class WikiPage extends Page {
        public function doDeleteArticle(
                $reason, $suppress = false, $id = 0, $commit = true, &$error = '', User $user = null
        ) {
-               global $wgDeferredUpdateList, $wgUseTrackbacks, $wgEnableInterwikiTemplatesTracking, $wgGlobalDatabase, $wgUser;
+               global $wgUseTrackbacks, $wgEnableInterwikiTemplatesTracking, $wgGlobalDatabase, $wgUser;
                $user = is_null( $user ) ? $wgUser : $user;
 
                wfDebug( __METHOD__ . "\n" );
@@ -1620,8 +1620,9 @@ class WikiPage extends Page {
                        return false;
                }
 
-               $u = new SiteStatsUpdate( 0, 1, - (int)$this->isCountable(), -1 );
-               array_push( $wgDeferredUpdateList, $u );
+               DeferredUpdates::addUpdate(
+                       new SiteStatsUpdate( 0, 1, - (int)$this->isCountable(), -1 )
+               );
 
                // Bitfields to further suppress the content
                if ( $suppress ) {
@@ -1939,15 +1940,15 @@ class WikiPage extends Page {
         * @param $user User The relevant user
         */
        public function doViewUpdates( User $user ) {
-               global $wgDeferredUpdateList, $wgDisableCounters;
+               global $wgDisableCounters;
                if ( wfReadOnly() ) {
                        return;
                }
 
                # Don't update page view counters on views from bot users (bug 14044)
                if ( !$wgDisableCounters && !$user->isAllowed( 'bot' ) && $this->getId() ) {
-                       $wgDeferredUpdateList[] = new ViewCountUpdate( $this->getId() );
-                       $wgDeferredUpdateList[] = new SiteStatsUpdate( 1, 0, 0 );
+                       DeferredUpdates::addUpdate( new ViewCountUpdate( $this->getId() ) );
+                       DeferredUpdates::addUpdate( new SiteStatsUpdate( 1, 0, 0 ) );
                }
 
                # Update newtalk / watchlist notification status
@@ -2004,7 +2005,7 @@ class WikiPage extends Page {
         *   - null: don't change the article count
         */
        public function doEditUpdates( Revision $revision, User $user, array $options = array() ) {
-               global $wgDeferredUpdateList, $wgEnableParserCache;
+               global $wgEnableParserCache;
 
                wfProfileIn( __METHOD__ );
 
@@ -2072,8 +2073,8 @@ class WikiPage extends Page {
                        $total = 0;
                }
 
-               $wgDeferredUpdateList[] = new SiteStatsUpdate( 0, 1, $good, $total );
-               $wgDeferredUpdateList[] = new SearchUpdate( $id, $title, $text );
+               DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 1, $good, $total ) );
+               DeferredUpdates::addUpdate( new SearchUpdate( $id, $title, $text ) );
 
                # If this is another user's talk page, update newtalk.
                # Don't do this if $options['changed'] = false (null-edits) nor if
@@ -2221,8 +2222,6 @@ class WikiPage extends Page {
         * @param $title Title object
         */
        public static function onArticleCreate( $title ) {
-               global $wgDeferredUpdateList;
-
                # Update existence markers on article/talk tabs...
                if ( $title->isTalkPage() ) {
                        $other = $title->getSubjectPage();
@@ -2238,7 +2237,7 @@ class WikiPage extends Page {
                $title->deleteTitleProtection();
 
                # Invalidate caches of distant articles which transclude this page
-               $wgDeferredUpdateList[] = new HTMLCacheUpdate( $title, 'globaltemplatelinks' );
+               DeferredUpdates::addHTMLCacheUpdate( $title, 'globaltemplatelinks' );
        }
 
        /**
@@ -2247,8 +2246,6 @@ class WikiPage extends Page {
         * @param $title Title
         */
        public static function onArticleDelete( $title ) {
-               global $wgDeferredUpdateList;
-
                # Update existence markers on article/talk tabs...
                if ( $title->isTalkPage() ) {
                        $other = $title->getSubjectPage();
@@ -2286,7 +2283,7 @@ class WikiPage extends Page {
                RepoGroup::singleton()->getLocalRepo()->invalidateImageRedirect( $title );
 
                # Invalidate caches of distant articles which transclude this page
-               $wgDeferredUpdateList[] = new HTMLCacheUpdate( $title, 'globaltemplatelinks' );
+               DeferredUpdates::addHTMLCacheUpdate( $title, 'globaltemplatelinks' );
        }
 
        /**
@@ -2296,16 +2293,14 @@ class WikiPage extends Page {
         * @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 ) {
-               global $wgDeferredUpdateList;
-
                // Invalidate caches of articles which include this page
-               $wgDeferredUpdateList[] = new HTMLCacheUpdate( $title, 'templatelinks' );
+               DeferredUpdates::addHTMLCacheUpdate( $title, 'templatelinks' );
 
                // Invalidate caches of distant articles which transclude this page
-               $wgDeferredUpdateList[] = new HTMLCacheUpdate( $title, 'globaltemplatelinks' );
+               DeferredUpdates::addHTMLCacheUpdate( $title, 'globaltemplatelinks' );
 
                // Invalidate the caches of all pages which redirect here
-               $wgDeferredUpdateList[] = new HTMLCacheUpdate( $title, 'redirect' );
+               DeferredUpdates::addHTMLCacheUpdate( $title, 'redirect' );
 
                # Purge squid for this page only
                $title->purgeSquid();
index 4fd6c9a..497ff9e 100644 (file)
@@ -23,8 +23,7 @@
  *
  * @ingroup Cache
  */
-class HTMLCacheUpdate
-{
+class HTMLCacheUpdate implements DeferrableUpdate {
        /**
         * @var Title
         */
index 77146eb..30e6a13 100644 (file)
@@ -13,7 +13,7 @@
  *
  * @ingroup Search
  */
-class SearchUpdate {
+class SearchUpdate implements DeferrableUpdate {
 
        private $mId = 0, $mNamespace, $mTitle, $mText;
        private $mTitleWords;
index ed8d80e..68fb2d8 100644 (file)
@@ -209,7 +209,7 @@ TEXT;
                }
                wfWaitForSlaves();
                // XXX: Don't let deferred jobs array get absurdly large (bug 24375)
-               wfDoUpdates( 'commit' );
+               DeferredUpdates::doUpdates( 'commit' );
        }
 
        function progress( $string ) {
index 6d2b225..fd5ac6b 100644 (file)
@@ -132,7 +132,7 @@ class ParserTest {
        }
 
        static function setUp() {
-               global $wgParser, $wgParserConf, $IP, $messageMemc, $wgMemc, $wgDeferredUpdateList,
+               global $wgParser, $wgParserConf, $IP, $messageMemc, $wgMemc,
                        $wgUser, $wgLang, $wgOut, $wgRequest, $wgStyleDirectory, $wgEnableParserCache,
                        $wgNamespaceAliases, $wgNamespaceProtection, $wgLocalFileRepo,
                        $parserMemc, $wgThumbnailScriptPath, $wgScriptPath,
@@ -160,7 +160,7 @@ class ParserTest {
 
 
                $wgEnableParserCache = false;
-               $wgDeferredUpdateList = array();
+               DeferredUpdates::clearPendingUpdates();
                $wgMemc = wfGetMainCache();
                $messageMemc = wfGetMessageCacheStorage();
                $parserMemc = wfGetParserCacheStorage();
index 0f2fecf..f6f2fbd 100644 (file)
@@ -14,7 +14,7 @@ class UploadFromUrlTestSuite extends PHPUnit_Framework_TestSuite {
        }
 
        function setUp() {
-               global $wgParser, $wgParserConf, $IP, $messageMemc, $wgMemc, $wgDeferredUpdateList,
+               global $wgParser, $wgParserConf, $IP, $messageMemc, $wgMemc,
                                  $wgUser, $wgLang, $wgOut, $wgRequest, $wgStyleDirectory, $wgEnableParserCache,
                                  $wgNamespaceAliases, $wgNamespaceProtection, $wgLocalFileRepo,
                                  $parserMemc, $wgThumbnailScriptPath, $wgScriptPath,
@@ -41,7 +41,7 @@ class UploadFromUrlTestSuite extends PHPUnit_Framework_TestSuite {
 
 
                $wgEnableParserCache = false;
-               $wgDeferredUpdateList = array();
+               DeferredUpdates::clearPendingUpdates();
                $wgMemc = wfGetMainCache();
                $messageMemc = wfGetMessageCacheStorage();
                $parserMemc = wfGetParserCacheStorage();