/** * Invalidate a set of IDs, right now */ function invalidateIDs(ResultWrapper $res) { global $wgUseFileCache, $wgUseSquid; if ($res->numRows() == 0) { return; } $dbw =& wfGetDB(DB_MASTER); $timestamp = $dbw->timestamp(); $done = false; while (!$done) { # Get all IDs in this query into an array $ids = array(); for ($i = 0; $i < $this->mRowsPerQuery; $i++) { $row = $res->fetchRow(); if ($row) { $ids[] = $row[0]; } else { $done = true; break; } } if (!count($ids)) { break; } # Update page_touched $dbw->update('page', array('page_touched' => $timestamp), array('page_id IN (' . $dbw->makeList($ids) . ')'), __METHOD__); # Update squid if ($wgUseSquid || $wgUseFileCache) { $titles = Title::newFromIDs($ids); if ($wgUseSquid) { $u = SquidUpdate::newFromTitles($titles); $u->doUpdate(); } # Update file cache if ($wgUseFileCache) { foreach ($titles as $title) { $cm = new CacheManager($title); @unlink($cm->fileCacheName()); } } } } }
/** * Change an existing article. Puts the previous version back into the old table, updates RC * and all necessary caches, mostly via the deferred update array. * * It is possible to call this function from a command-line script, but note that you should * first set $wgUser, and clean up $wgDeferredUpdates after each edit. */ function updateArticle($text, $summary, $minor, $watchthis, $forceBot = false, $sectionanchor = '') { global $wgOut, $wgUser; global $wgDBtransactions, $wgMwRedir; global $wgUseSquid, $wgInternalServer, $wgPostCommitUpdateList, $wgUseFileCache; $fname = 'Article::updateArticle'; wfProfileIn($fname); $good = true; $isminor = $minor && $wgUser->isLoggedIn(); if ($this->isRedirect($text)) { # Remove all content but redirect # This could be done by reconstructing the redirect from a title given by # Title::newFromRedirect(), but then we wouldn't know which synonym the user # wants to see if (preg_match("/^((" . $wgMwRedir->getBaseRegex() . ')[^\\n]+)/i', $text, $m)) { $redir = 1; $text = $m[1] . "\n"; } } else { $redir = 0; } $text = $this->preSaveTransform($text); $dbw =& wfGetDB(DB_MASTER); $now = wfTimestampNow(); # Update article, but only if changed. # It's important that we either rollback or complete, otherwise an attacker could # overwrite cur entries by sending precisely timed user aborts. Random bored users # could conceivably have the same effect, especially if cur is locked for long periods. if (!$wgDBtransactions) { $userAbort = ignore_user_abort(true); } $oldtext = $this->getContent(true); $oldsize = strlen($oldtext); $newsize = strlen($text); $lastRevision = 0; if (0 != strcmp($text, $oldtext)) { $empty = false; $this->mGoodAdjustment = $this->isCountable($text) - $this->isCountable($oldtext); $this->mTotalAdjustment = 0; $now = wfTimestampNow(); $lastRevision = $dbw->selectField('page', 'page_latest', array('page_id' => $this->getId())); $revision = new Revision(array('page' => $this->getId(), 'comment' => $summary, 'minor_edit' => $isminor, 'text' => $text)); $dbw->immediateCommit(); $dbw->begin(); $revisionId = $revision->insertOn($dbw); # Update page $ok = $this->updateRevisionOn($dbw, $revision, $lastRevision); if (!$ok) { /* Belated edit conflict! Run away!! */ $good = false; $dbw->rollback(); } else { # Update recentchanges (moved some lines below) and purge cache and whatnot $bot = (int) ($wgUser->isBot() || $forceBot); Article::onArticleEdit($this->mTitle); $dbw->commit(); } } else { $empty = true; } if (!$wgDBtransactions) { ignore_user_abort($userAbort); } if ($good) { if ($watchthis) { if (!$this->mTitle->userIsWatching()) { $this->watch(); } } else { if ($this->mTitle->userIsWatching()) { $this->unwatch(); } } # standard deferred updates $this->editUpdates($text); if (!$empty) { # moved from above to make sure editUpdates were performed: # Is important to call RecentChange::notifyEdit _after_ editUpdates # because a user_newtalk flag and addwatch might be committed in editUpdates # which triggers the sending of an Enotif in RecentChange::notifyEdit just right now RecentChange::notifyEdit($now, $this->mTitle, $isminor, $wgUser, $summary, $lastRevision, $this->getTimestamp(), $bot, '', $oldsize, $newsize, $revisionId); } $urls = array(); # Template namespace # Purge all articles linking here if ($this->mTitle->getNamespace() == NS_TEMPLATE) { $titles = $this->mTitle->getLinksTo(); Title::touchArray($titles); if ($wgUseSquid) { foreach ($titles as $title) { $urls[] = $title->getInternalURL(); } } } # Squid updates if ($wgUseSquid) { $urls = array_merge($urls, $this->mTitle->getSquidURLs()); $u = new SquidUpdate($urls); array_push($wgPostCommitUpdateList, $u); } # File cache if ($wgUseFileCache) { $cm = new CacheManager($this->mTitle); @unlink($cm->fileCacheName()); } $this->showArticle($text, wfMsg('updated'), $sectionanchor); } wfProfileOut($fname); return $good; }
/** * Purge caches on page update etc */ static function onArticleEdit($title) { global $wgDeferredUpdateList, $wgUseFileCache; $urls = array(); // Invalidate caches of articles which include this page $update = new HTMLCacheUpdate($title, 'templatelinks'); $wgDeferredUpdateList[] = $update; # Purge squid for this page only $title->purgeSquid(); # Clear file cache if ($wgUseFileCache) { $cm = new CacheManager($title); @unlink($cm->fileCacheName()); } }
/** * Updates page_touched for this page; called from LinksUpdate.php * @return bool true if the update succeded * @access public */ function invalidateCache($ts = 0) { // WERELATE: add optional ts parameter global $wgUseFileCache; if (wfReadOnly()) { return; } $dbw =& wfGetDB(DB_MASTER); $success = $dbw->update('page', array('page_touched' => $dbw->timestamp($ts)), array('page_namespace' => $this->getNamespace(), 'page_title' => $this->getDBkey()), 'Title::invalidateCache'); if ($wgUseFileCache) { $cache = new CacheManager($this); @unlink($cache->fileCacheName()); } return $success; }