MediaWiki  master
HtmlCacheUpdater.php
Go to the documentation of this file.
1 <?php
25 
34  private $reboundDelay;
36  private $useFileCache;
38  private $cdnMaxAge;
39 
41  private $hookRunner;
42 
44  public const PURGE_NAIVE = 0;
50  public const PURGE_PRESEND = 1;
55  public const PURGE_REBOUND = 2;
56 
65  public const PURGE_INTENT_TXROUND_REFLECTED = self::PURGE_PRESEND | self::PURGE_REBOUND;
66 
75  public const PURGE_URLS_LINKSUPDATE_ONLY = 4;
76 
83  public const UNLESS_CACHE_MTIME_AFTER = 'unless-timestamp-exceeds';
84 
86  private $titleFactory;
87 
97  public function __construct(
98  HookContainer $hookContainer,
102  $cdnMaxAge
103  ) {
104  $this->hookRunner = new HookRunner( $hookContainer );
105  $this->titleFactory = $titleFactory;
106  $this->reboundDelay = $reboundDelay;
107  $this->useFileCache = $useFileCache;
108  $this->cdnMaxAge = $cdnMaxAge;
109  }
110 
116  private function fieldHasFlag( $flags, $flag ) {
117  return ( ( $flags & $flag ) === $flag );
118  }
119 
128  public function purgeUrls( $urls, $flags = self::PURGE_PRESEND, array $unless = [] ) {
129  $minFreshCacheMtime = $unless[self::UNLESS_CACHE_MTIME_AFTER] ?? null;
130  if ( $minFreshCacheMtime && time() > ( $minFreshCacheMtime + $this->cdnMaxAge ) ) {
131  return;
132  }
133 
134  $urls = is_string( $urls ) ? [ $urls ] : $urls;
135 
136  $reboundDelay = $this->fieldHasFlag( $flags, self::PURGE_REBOUND )
137  ? $this->reboundDelay
138  : 0; // no second purge
139 
140  $update = new CdnCacheUpdate( $urls, [ 'reboundDelay' => $reboundDelay ] );
141  if ( $this->fieldHasFlag( $flags, self::PURGE_PRESEND ) ) {
142  DeferredUpdates::addUpdate( $update, DeferredUpdates::PRESEND );
143  } else {
144  $update->doUpdate();
145  }
146  }
147 
160  public function purgeTitleUrls( $pages, $flags = self::PURGE_PRESEND, array $unless = [] ) {
161  $pages = is_iterable( $pages ) ? $pages : [ $pages ];
162  $pageIdentities = [];
163 
164  foreach ( $pages as $page ) {
165  // TODO: We really only need to cast to PageIdentity. We could use a LinkBatch for that.
166  $title = $this->titleFactory->castFromPageReference( $page );
167 
168  if ( $title->canExist() ) {
169  $pageIdentities[] = $title;
170  }
171  }
172 
173  if ( !$pageIdentities ) {
174  return;
175  }
176 
177  if ( $this->useFileCache ) {
178  $update = HtmlFileCacheUpdate::newFromPages( $pageIdentities );
179  if ( $this->fieldHasFlag( $flags, self::PURGE_PRESEND ) ) {
180  DeferredUpdates::addUpdate( $update, DeferredUpdates::PRESEND );
181  } else {
182  $update->doUpdate();
183  }
184  }
185 
186  $minFreshCacheMtime = $unless[self::UNLESS_CACHE_MTIME_AFTER] ?? null;
187  if ( !$minFreshCacheMtime || time() <= ( $minFreshCacheMtime + $this->cdnMaxAge ) ) {
188  $urls = [];
189  foreach ( $pageIdentities as $pi ) {
191  $urls = array_merge( $urls, $this->getUrls( $pi, $flags ) );
192  }
193  $this->purgeUrls( $urls, $flags );
194  }
195  }
196 
204  public function getUrls( PageReference $page, int $flags = 0 ): array {
205  $title = $this->titleFactory->castFromPageReference( $page );
206 
207  if ( !$title->canExist() ) {
208  return [];
209  }
210 
211  // These urls are affected both by direct revisions as well,
212  // as re-rendering of the same content during a LinksUpdate.
213  $urls = [
214  $title->getInternalURL()
215  ];
216  // Language variant page views are currently not cached
217  // and thus not purged (T250511).
218 
219  // These urls are only affected by direct revisions, and do not require
220  // purging when a LinksUpdate merely rerenders the same content.
221  // This exists to avoid large amounts of redundant PURGE traffic (T250261).
222  if ( !$this->fieldHasFlag( $flags, self::PURGE_URLS_LINKSUPDATE_ONLY ) ) {
223  $urls[] = $title->getInternalURL( 'action=history' );
224 
225  // Canonical action=raw URLs for user and site config pages (T58874, T261371).
226  if ( $title->isUserJsConfigPage() || $title->isSiteJsConfigPage() ) {
227  $urls[] = $title->getInternalURL( 'action=raw&ctype=text/javascript' );
228  } elseif ( $title->isUserJsonConfigPage() || $title->isSiteJsonConfigPage() ) {
229  $urls[] = $title->getInternalURL( 'action=raw&ctype=application/json' );
230  } elseif ( $title->isUserCssConfigPage() || $title->isSiteCssConfigPage() ) {
231  $urls[] = $title->getInternalURL( 'action=raw&ctype=text/css' );
232  }
233  }
234 
235  // Extensions may add novel ways to access this content
236  $append = [];
237  $mode = $flags & self::PURGE_URLS_LINKSUPDATE_ONLY;
238  $this->hookRunner->onHtmlCacheUpdaterAppendUrls( $title, $mode, $append );
239  $urls = array_merge( $urls, $append );
240 
241  // Extensions may add novel ways to access the site overall
242  $append = [];
243  $this->hookRunner->onHtmlCacheUpdaterVaryUrls( $urls, $append );
244  $urls = array_merge( $urls, $append );
245 
246  // Legacy. TODO: Deprecate this
247  $this->hookRunner->onTitleSquidURLs( $title, $urls );
248 
249  return $urls;
250  }
251 }
Page\PageIdentity
Interface for objects (potentially) representing an editable wiki page.
Definition: PageIdentity.php:64
HtmlCacheUpdater\$hookRunner
HookRunner $hookRunner
Definition: HtmlCacheUpdater.php:41
HtmlFileCacheUpdate\newFromPages
static newFromPages( $pages)
Definition: HtmlFileCacheUpdate.php:67
HtmlCacheUpdater\purgeTitleUrls
purgeTitleUrls( $pages, $flags=self::PURGE_PRESEND, array $unless=[])
Purge the CDN/HTMLFileCache for a title or the titles yielded by an iterator.
Definition: HtmlCacheUpdater.php:160
DeferredUpdates\addUpdate
static addUpdate(DeferrableUpdate $update, $stage=self::POSTSEND)
Add an update to the pending update queue for execution at the appropriate time.
Definition: DeferredUpdates.php:119
HtmlCacheUpdater\fieldHasFlag
fieldHasFlag( $flags, $flag)
Definition: HtmlCacheUpdater.php:116
Page\PageReference
Interface for objects (potentially) representing a page that can be viewable and linked to on a wiki.
Definition: PageReference.php:49
HtmlCacheUpdater\getUrls
getUrls(PageReference $page, int $flags=0)
Get a list of URLs to purge from the CDN cache when this page changes.
Definition: HtmlCacheUpdater.php:204
HtmlCacheUpdater\__construct
__construct(HookContainer $hookContainer, TitleFactory $titleFactory, $reboundDelay, $useFileCache, $cdnMaxAge)
Definition: HtmlCacheUpdater.php:97
$title
$title
Definition: testCompression.php:38
HtmlCacheUpdater\$titleFactory
TitleFactory $titleFactory
Definition: HtmlCacheUpdater.php:77
HtmlCacheUpdater\purgeUrls
purgeUrls( $urls, $flags=self::PURGE_PRESEND, array $unless=[])
Purge the CDN for a URL or list of URLs.
Definition: HtmlCacheUpdater.php:128
HtmlCacheUpdater\$cdnMaxAge
int $cdnMaxAge
Max seconds for CDN to served cached objects without revalidation.
Definition: HtmlCacheUpdater.php:38
HtmlCacheUpdater\$reboundDelay
int $reboundDelay
Seconds between initial and rebound purges; 0 if disabled.
Definition: HtmlCacheUpdater.php:34
CdnCacheUpdate
Handles purging the appropriate CDN objects given a list of URLs or Title instances.
Definition: CdnCacheUpdate.php:29
HtmlCacheUpdater
Class to invalidate the CDN and HTMLFileCache entries associated with URLs/titles.
Definition: HtmlCacheUpdater.php:32
HtmlCacheUpdater\$useFileCache
int $useFileCache
Whether filesystem-based HTML output caching is enabled.
Definition: HtmlCacheUpdater.php:36
TitleFactory
Creates Title objects.
Definition: TitleFactory.php:35
MediaWiki\HookContainer\HookContainer
HookContainer class.
Definition: HookContainer.php:45
MediaWiki\HookContainer\HookRunner
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Definition: HookRunner.php:555