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