Committing patch for bug 10931, which also fixes bug 13651. For a detailed explanatio...
authorRoan Kattouw <catrope@users.mediawiki.org>
Fri, 11 Apr 2008 15:20:45 +0000 (15:20 +0000)
committerRoan Kattouw <catrope@users.mediawiki.org>
Fri, 11 Apr 2008 15:20:45 +0000 (15:20 +0000)
12 files changed:
RELEASE-NOTES
includes/Article.php
includes/api/ApiBlock.php
includes/api/ApiDelete.php
includes/api/ApiEditPage.php
includes/api/ApiMain.php
includes/api/ApiMove.php
includes/api/ApiPageSet.php
includes/api/ApiProtect.php
includes/api/ApiRollback.php
includes/api/ApiUnblock.php
includes/api/ApiUndelete.php

index 2b8b7ca..f244425 100644 (file)
@@ -69,6 +69,7 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
   to message 'sidebar'
 ** (bug 6332) Lacking entry Mainpage-url
 ** (bug 8617) Separate main page url and name
+* Automatically add old redirects to the redirect table when needed
 
 === Bug fixes in 1.13 ===
 
index 57e4887..78387da 100644 (file)
@@ -34,6 +34,7 @@ class Article {
        var $mTouched;                  //!<
        var $mUser;                             //!<
        var $mUserText;                 //!<
+       var $mRedirectTarget;           //!<
        /**@}}*/
 
        /**
@@ -56,12 +57,58 @@ class Article {
                $this->mRedirectedFrom = $from;
        }
 
+       /**
+        * If this page is a redirect, get its target
+        *
+        * The target will be fetched from the redirect table if possible.
+        * If this page doesn't have an entry there, call insertRedirect()
+        * @return mixed Title object, or null if this page is not a redirect
+        */
+       public function getRedirectTarget() {
+               if(!$this->mTitle || !$this->mTitle->isRedirect())
+                       return null;
+               if(!is_null($this->mRedirectTarget))
+                       return $this->mRedirectTarget;
+
+               # Query the redirect table
+               $dbr = wfGetDb(DB_SLAVE);
+               $res = $dbr->select('redirect',
+                               array('rd_namespace', 'rd_title'),
+                               array('rd_from' => $this->getID()),
+                               __METHOD__
+               );
+               $row = $dbr->fetchObject($res);
+               if($row)
+                       return $this->mRedirectTarget = Title::makeTitle($row->rd_namespace, $row->rd_title);
+
+               # This page doesn't have an entry in the redirect table
+               return $this->mRedirectTarget = $this->insertRedirect();
+       }
+
+       /**
+        * Insert an entry for this page into the redirect table.
+        *
+        * Don't call this function directly unless you know what you're doing.
+        * @return Title object
+        */
+       public function insertRedirect() {
+               $retval = Title::newFromRedirect($this->getContent());
+               if(!$retval)
+                       return null;
+               $dbw = wfGetDb(DB_MASTER);
+               $dbw->insert('redirect', array(
+                               'rd_from' => $this->getID(),
+                               'rd_namespace' => $retval->getNamespace(),
+                               'rd_title' => $retval->getDBKey()
+               ));
+               return $retval;
+       }
+
        /**
         * @return mixed false, Title of in-wiki target, or string with URL
         */
        function followRedirect() {
-               $text = $this->getContent();
-               $rt = Title::newFromRedirect( $text );
+               $rt = $this->getRedirectTarget();
 
                # process if title object is valid and not special:userlogout
                if( $rt ) {
@@ -114,6 +161,7 @@ class Article {
 
                $this->mCurID = $this->mUser = $this->mCounter = -1; # Not loaded
                $this->mRedirectedFrom = null; # Title object if set
+               $this->mRedirectTarget = null; # Title object if set
                $this->mUserText =
                $this->mTimestamp = $this->mComment = '';
                $this->mGoodAdjustment = $this->mTotalAdjustment = 0;
@@ -801,7 +849,7 @@ class Article {
                        
                        }
                        
-                       elseif ( $rt = Title::newFromRedirect( $text ) ) {
+                       elseif ( $rt = $this->getRedirectTarget() ) {
                                # Display redirect
                                $imageDir = $wgContLang->isRTL() ? 'rtl' : 'ltr';
                                $imageUrl = $wgStylePath.'/common/images/redirect' . $imageDir . '.png';
index 5d6b161..f2b72f2 100644 (file)
@@ -87,14 +87,12 @@ class ApiBlock extends ApiBase {
                $form->BlockEmail = $params['noemail'];
                $form->BlockHideName = $params['hidename'];
 
-               $dbw = wfGetDb(DB_MASTER);
-               $dbw->begin();
                $retval = $form->doBlock($userID, $expiry);
                if(!empty($retval))
                        // We don't care about multiple errors, just report one of them
                        $this->dieUsageMsg($retval);
+               $this->getMain()->scheduleCommit();
 
-               $dbw->commit();
                $res['user'] = $params['user'];
                $res['userID'] = $userID;
                $res['expiry'] = ($expiry == Block::infinity() ? 'infinite' : $expiry);
index edfe672..b5411c4 100644 (file)
@@ -66,8 +66,6 @@ class ApiDelete extends ApiBase {
 
                $articleObj = new Article($titleObj);
                $reason = (isset($params['reason']) ? $params['reason'] : NULL);
-               $dbw = wfGetDb(DB_MASTER);
-               $dbw->begin();
                $retval = self::delete($articleObj, $params['token'], $reason);
                
                if(!empty($retval))
@@ -78,7 +76,7 @@ class ApiDelete extends ApiBase {
                        $articleObj->doWatch();
                else if($params['unwatch'])
                        $articleObj->doUnwatch();
-               $dbw->commit();
+               $this->getMain()->scheduleCommit();
                $r = array('title' => $titleObj->getPrefixedText(), 'reason' => $reason);
                $this->getResult()->addValue(null, $this->getModuleName(), $r);
        }
index b05f6c7..03e9e21 100644 (file)
@@ -146,10 +146,8 @@ class ApiEditPage extends ApiBase {
                # but that breaks API mode detection through is_null($wgTitle)
                global $wgTitle;
                $wgTitle = null;
-               $dbw = wfGetDb(DB_MASTER);
-               $dbw->begin();
                $retval = $ep->internalAttemptSave($result, $wgUser->isAllowed('bot') && $params['bot']);
-               $dbw->commit();
+               $this->getMain()->scheduleCommit();
                switch($retval)
                {
                        case EditPage::AS_HOOK_ERROR:
index 5c2c53d..5765c97 100644 (file)
@@ -95,7 +95,7 @@ class ApiMain extends ApiBase {
                'dbgfm' => 'ApiFormatDbg'
        );
 
-       private $mPrinter, $mModules, $mModuleNames, $mFormats, $mFormatNames;
+       private $mPrinter, $mModules, $mModuleNames, $mFormats, $mFormatNames, $mCommit;
        private $mResult, $mAction, $mShowVersions, $mEnableWrite, $mRequest, $mInternalMode, $mSquidMaxage;
 
        /**
@@ -150,6 +150,7 @@ class ApiMain extends ApiBase {
                $this->mRequest = & $request;
 
                $this->mSquidMaxage = 0;
+               $this->mCommit = false;
        }
 
        /**
@@ -195,6 +196,13 @@ class ApiMain extends ApiBase {
        public function createPrinterByName($format) {
                return new $this->mFormats[$format] ($this, $format);
        }
+       
+       /**
+        * Schedule a database commit
+        */
+       public function scheduleCommit() {
+               $this->mCommit = true;
+       }
 
        /**
         * Execute api request. Any errors will be handled if the API was called by the remote client. 
@@ -205,6 +213,11 @@ class ApiMain extends ApiBase {
                        $this->executeAction();
                else
                        $this->executeActionWithErrorHandling();
+               if($this->mCommit)
+               {
+                       $dbw = wfGetDb(DB_MASTER);
+                       $dbw->immediateCommit();
+               }
                $this->profileOut();
        }
 
@@ -617,3 +630,4 @@ class UsageException extends Exception {
 }
 
 
+
index 919b7bc..9653d0b 100644 (file)
@@ -79,8 +79,6 @@ class ApiMove extends ApiBase {
                        // We don't care about multiple errors, just report one of them
                        $this->dieUsageMsg(current($errors));
 
-               $dbw = wfGetDB(DB_MASTER);
-               $dbw->begin();          
                $retval = $fromTitle->moveTo($toTitle, true, $params['reason'], !$params['noredirect']);
                if($retval !== true)
                        $this->dieUsageMsg(array($retval));
@@ -118,7 +116,7 @@ class ApiMove extends ApiBase {
                        $wgUser->removeWatch($fromTitle);
                        $wgUser->removeWatch($toTitle);
                }
-               $dbw->commit(); // Make sure all changes are really written to the DB
+               $this->getMain()->scheduleCommit();
                $this->getResult()->addValue(null, $this->getModuleName(), $r);
        }
        
index 1acfb2b..3383b25 100644 (file)
@@ -528,7 +528,7 @@ class ApiPageSet extends ApiQueryBase {
                while($row = $db->fetchObject($res))
                {
                        $rdfrom = intval($row->rd_from);
-                       $from = Title::newFromId($row->rd_from)->getPrefixedText();
+                       $from = $this->mPendingRedirectIDs[$rdfrom]->getPrefixedText();
                        $to = Title::makeTitle($row->rd_namespace, $row->rd_title)->getPrefixedText();
                        unset($this->mPendingRedirectIDs[$rdfrom]);
                        if(!isset($this->mAllPages[$row->rd_namespace][$row->rd_title]))
@@ -537,7 +537,22 @@ class ApiPageSet extends ApiQueryBase {
                }
                $db->freeResult($res);
                if(!empty($this->mPendingRedirectIDs))
-                       ApiBase :: dieDebug(__METHOD__, 'Invalid redirect IDs were found');
+               {
+                       # We found pages that aren't in the redirect table
+                       # Add them
+                       foreach($this->mPendingRedirectIDs as $id => $title)
+                       {
+                               $article = new Article($title);
+                               $rt = $article->insertRedirect();
+                               if(!$rt)
+                                       # What the hell. Let's just ignore this
+                                       continue;
+                               $lb->addObj($rt);
+                               $this->mRedirectTitles[$title->getPrefixedText()] = $rt->getPrefixedText();
+                               unset($this->mPendingRedirectIDs[$id]);
+                       }
+                       $this->getMain()->scheduleCommit();
+               }
                return $lb;
        }
 
@@ -617,3 +632,4 @@ class ApiPageSet extends ApiQueryBase {
        }
 }
 
+
index bd7fa90..e64a6be 100644 (file)
@@ -85,8 +85,6 @@ class ApiProtect extends ApiBase {
                                $this->dieUsageMsg(array('missingtitles-createonly'));
                }
 
-               $dbw = wfGetDb(DB_MASTER);
-               $dbw->begin();
                if($titleObj->exists()) {
                        $articleObj = new Article($titleObj);
                        $ok = $articleObj->updateRestrictions($protections, $params['reason'], $params['cascade'], $expiry);
@@ -96,7 +94,7 @@ class ApiProtect extends ApiBase {
                        // This is very weird. Maybe the article was deleted or the user was blocked/desysopped in the meantime?
                        // Just throw an unknown error in this case, as it's very likely to be a race condition
                        $this->dieUsageMsg(array());
-               $dbw->commit();
+               $this->getMain()->scheduleCommit();
                $res = array('title' => $titleObj->getPrefixedText(), 'reason' => $params['reason']);
                if($expiry == Block::infinity())
                        $res['expiry'] = 'infinity';
index 5e21789..6ccc438 100644 (file)
@@ -62,15 +62,13 @@ class ApiRollback extends ApiBase {
                $articleObj = new Article($titleObj);
                $summary = (isset($params['summary']) ? $params['summary'] : "");
                $details = null;
-               $dbw = wfGetDb(DB_MASTER);
-               $dbw->begin();
                $retval = $articleObj->doRollback($username, $summary, $params['token'], $params['markbot'], $details);
 
                if(!empty($retval))
                        // We don't care about multiple errors, just report one of them
                        $this->dieUsageMsg(current($retval));
 
-               $dbw->commit();
+               $this->getMain()->scheduleCommit();
                $current = $target = $summary = NULL;
                extract($details);
 
index f1d8753..1a30c64 100644 (file)
@@ -70,13 +70,11 @@ class ApiUnblock extends ApiBase {
                $id = $params['id'];
                $user = $params['user'];
                $reason = (is_null($params['reason']) ? '' : $params['reason']);
-               $dbw = wfGetDb(DB_MASTER);
-               $dbw->begin();
                $retval = IPUnblockForm::doUnblock($id, $user, $reason, $range);
                if(!empty($retval))
                        $this->dieUsageMsg($retval);
 
-               $dbw->commit();
+               $this->getMain()->scheduleCommit();
                $res['id'] = $id;
                $res['user'] = $user;
                $res['reason'] = $reason;
index 04ba074..6dd1b2c 100644 (file)
@@ -73,7 +73,7 @@ class ApiUndelete extends ApiBase {
                if(!is_array($retval))
                        $this->dieUsageMsg(array('cannotundelete'));
 
-               $dbw->commit();
+               $this->getMain()->scheduleCommit();
                $info['title'] = $titleObj->getPrefixedText();
                $info['revisions'] = $retval[0];
                $info['fileversions'] = $retval[1];