From: Roan Kattouw Date: Fri, 11 Apr 2008 15:20:45 +0000 (+0000) Subject: Committing patch for bug 10931, which also fixes bug 13651. For a detailed explanatio... X-Git-Tag: 1.31.0-rc.0~48444 X-Git-Url: http://git.cyclocoop.org/%28?a=commitdiff_plain;h=68bbfc12c0eec54336bd9cde7386d265099f2685;p=lhc%2Fweb%2Fwiklou.git Committing patch for bug 10931, which also fixes bug 13651. For a detailed explanation of what this commit does, see bug 10931 comment #24 --- diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 2b8b7ca415..f244425da7 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -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 === diff --git a/includes/Article.php b/includes/Article.php index 57e4887ef0..78387dad52 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -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'; diff --git a/includes/api/ApiBlock.php b/includes/api/ApiBlock.php index 5d6b161244..f2b72f2f2c 100644 --- a/includes/api/ApiBlock.php +++ b/includes/api/ApiBlock.php @@ -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); diff --git a/includes/api/ApiDelete.php b/includes/api/ApiDelete.php index edfe672623..b5411c42b4 100644 --- a/includes/api/ApiDelete.php +++ b/includes/api/ApiDelete.php @@ -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); } diff --git a/includes/api/ApiEditPage.php b/includes/api/ApiEditPage.php index b05f6c72b4..03e9e21eea 100644 --- a/includes/api/ApiEditPage.php +++ b/includes/api/ApiEditPage.php @@ -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: diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index 5c2c53d9fe..5765c97aca 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -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 { } + diff --git a/includes/api/ApiMove.php b/includes/api/ApiMove.php index 919b7bc16c..9653d0b21a 100644 --- a/includes/api/ApiMove.php +++ b/includes/api/ApiMove.php @@ -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); } diff --git a/includes/api/ApiPageSet.php b/includes/api/ApiPageSet.php index 1acfb2be75..3383b25573 100644 --- a/includes/api/ApiPageSet.php +++ b/includes/api/ApiPageSet.php @@ -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 { } } + diff --git a/includes/api/ApiProtect.php b/includes/api/ApiProtect.php index bd7fa906eb..e64a6be2b8 100644 --- a/includes/api/ApiProtect.php +++ b/includes/api/ApiProtect.php @@ -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'; diff --git a/includes/api/ApiRollback.php b/includes/api/ApiRollback.php index 5e2178945c..6ccc43874a 100644 --- a/includes/api/ApiRollback.php +++ b/includes/api/ApiRollback.php @@ -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); diff --git a/includes/api/ApiUnblock.php b/includes/api/ApiUnblock.php index f1d8753e05..1a30c646bf 100644 --- a/includes/api/ApiUnblock.php +++ b/includes/api/ApiUnblock.php @@ -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; diff --git a/includes/api/ApiUndelete.php b/includes/api/ApiUndelete.php index 04ba074fc1..6dd1b2c997 100644 --- a/includes/api/ApiUndelete.php +++ b/includes/api/ApiUndelete.php @@ -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];