ApiQueryBase::addTitleInfo( $r, $title );
$page = WikiPage::factory( $title );
if ( !$user->pingLimiter( 'purge' ) ) {
- $page->doPurge(); // Directly purge and skip the UI part of purge().
+ $flags = WikiPage::PURGE_ALL;
+ if ( !$this->getRequest()->wasPosted() ) {
+ $flags ^= WikiPage::PURGE_GLOBAL_PCACHE; // skip DB_MASTER write
+ }
+ // Directly purge and skip the UI part of purge()
+ $page->doPurge( $flags );
$r['purged'] = true;
} else {
$error = $this->parseMsg( [ 'actionthrottledtext' ] );
* Call to WikiPage function for backwards compatibility.
* @see WikiPage::doPurge
*/
- public function doPurge() {
- return $this->mPage->doPurge();
+ public function doPurge( $flags = WikiPage::PURGE_ALL ) {
+ return $this->mPage->doPurge( $flags );
+ }
+
+ /**
+ * Call to WikiPage function for backwards compatibility.
+ * @see WikiPage::getLastPurgeTimestamp
+ */
+ public function getLastPurgeTimestamp() {
+ return $this->mPage->getLastPurgeTimestamp();
}
/**
return $this->mDupes;
}
- /**
- * Override handling of action=purge
- * @return bool
- */
- public function doPurge() {
+ public function doPurge( $flags = self::PURGE_ALL ) {
$this->loadFile();
+
if ( $this->mFile->exists() ) {
wfDebug( 'ImagePage::doPurge purging ' . $this->mFile->getName() . "\n" );
DeferredUpdates::addUpdate( new HTMLCacheUpdate( $this->mTitle, 'imagelinks' ) );
// Purge redirect cache
$this->mRepo->invalidateImageRedirect( $this->mTitle );
}
- return parent::doPurge();
+
+ return parent::doPurge( $flags );
}
/**
*/
protected $mLinksUpdated = '19700101000000';
+ const PURGE_CDN_CACHE = 1; // purge CDN cache for page variant URLs
+ const PURGE_CLUSTER_PCACHE = 2; // purge parser cache in the local datacenter
+ const PURGE_GLOBAL_PCACHE = 4; // set page_touched to clear parser cache in all datacenters
+ const PURGE_ALL = 7;
+
/**
* Constructor and clear the article
* @param Title $title Reference to a Title object.
/**
* Perform the actions of a page purging
+ * @param integer $flags Bitfield of WikiPage::PURGE_* constants
* @return bool
*/
- public function doPurge() {
+ public function doPurge( $flags = self::PURGE_ALL ) {
if ( !Hooks::run( 'ArticlePurge', [ &$this ] ) ) {
return false;
}
- $this->mTitle->invalidateCache();
+ if ( ( $flags & self::PURGE_GLOBAL_PCACHE ) == self::PURGE_GLOBAL_PCACHE ) {
+ // Set page_touched in the database to invalidate all DC caches
+ $this->mTitle->invalidateCache();
+ } elseif ( ( $flags & self::PURGE_CLUSTER_PCACHE ) == self::PURGE_CLUSTER_PCACHE ) {
+ // Delete the parser options key in the local cluster to invalidate the DC cache
+ ParserCache::singleton()->deleteOptionsKey( $this );
+ // Avoid sending HTTP 304s in ViewAction to the client who just issued the purge
+ $cache = ObjectCache::getLocalClusterInstance();
+ $cache->set(
+ $cache->makeKey( 'page', 'last-dc-purge', $this->getId() ),
+ wfTimestamp( TS_MW ),
+ $cache::TTL_HOUR
+ );
+ }
- // Clear file cache
- HTMLFileCache::clearFileCache( $this->getTitle() );
- // Send purge after above page_touched update was committed
- DeferredUpdates::addUpdate(
- new CdnCacheUpdate( $this->mTitle->getCdnUrls() ),
- DeferredUpdates::PRESEND
- );
+ if ( ( $flags & self::PURGE_CDN_CACHE ) == self::PURGE_CDN_CACHE ) {
+ // Clear any HTML file cache
+ HTMLFileCache::clearFileCache( $this->getTitle() );
+ // Send purge after any page_touched above update was committed
+ DeferredUpdates::addUpdate(
+ new CdnCacheUpdate( $this->mTitle->getCdnUrls() ),
+ DeferredUpdates::PRESEND
+ );
+ }
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
// @todo move this logic to MessageCache
return true;
}
+ /**
+ * Get the last time a user explicitly purged the page via action=purge
+ *
+ * @return string|bool TS_MW timestamp or false
+ * @since 1.28
+ */
+ public function getLastPurgeTimestamp() {
+ $cache = ObjectCache::getLocalClusterInstance();
+
+ return $cache->get( $cache->makeKey( 'page', 'last-dc-purge', $this->getId() ) );
+ }
+
/**
* Insert a new empty page record for this article.
* This *must* be followed up by creating a revision
}
/**
- * @param WikiPage $article
+ * @param WikiPage $page
* @return mixed|string
*/
- protected function getOptionsKey( $article ) {
- $pageid = $article->getId();
- return wfMemcKey( 'pcache', 'idoptions', "{$pageid}" );
+ protected function getOptionsKey( $page ) {
+ return wfMemcKey( 'pcache', 'idoptions', $page->getId() );
+ }
+
+ /**
+ * @param WikiPage $page
+ * @since 1.28
+ */
+ public function deleteOptionsKey( $page ) {
+ $this->mMemc->delete( $this->getOptionsKey( $page ) );
}
/**