MediaWiki REL1_40
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->castFromPageReference( $page );
168
169 if ( $title->canExist() ) {
170 $pageIdentities[] = $title;
171 }
172 }
173
174 if ( !$pageIdentities ) {
175 return;
176 }
177
178 if ( $this->useFileCache ) {
179 // @phan-suppress-next-line PhanTypeMismatchArgument castFrom does not return null here
180 $update = HtmlFileCacheUpdate::newFromPages( $pageIdentities );
181 if ( $this->fieldHasFlag( $flags, self::PURGE_PRESEND ) ) {
182 DeferredUpdates::addUpdate( $update, DeferredUpdates::PRESEND );
183 } else {
184 $update->doUpdate();
185 }
186 }
187
188 $minFreshCacheMtime = $unless[self::UNLESS_CACHE_MTIME_AFTER] ?? null;
189 if ( !$minFreshCacheMtime || time() <= ( $minFreshCacheMtime + $this->cdnMaxAge ) ) {
190 $urls = [];
191 foreach ( $pageIdentities as $pi ) {
193 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable castFrom does not return null here
194 $urls = array_merge( $urls, $this->getUrls( $pi, $flags ) );
195 }
196 $this->purgeUrls( $urls, $flags );
197 }
198 }
199
207 public function getUrls( PageReference $page, int $flags = 0 ): array {
208 $title = $this->titleFactory->castFromPageReference( $page );
209
210 if ( !$title->canExist() ) {
211 return [];
212 }
213
214 // These urls are affected both by direct revisions as well,
215 // as re-rendering of the same content during a LinksUpdate.
216 $urls = [
217 $title->getInternalURL()
218 ];
219 // Language variant page views are currently not cached
220 // and thus not purged (T250511).
221
222 // These urls are only affected by direct revisions, and do not require
223 // purging when a LinksUpdate merely rerenders the same content.
224 // This exists to avoid large amounts of redundant PURGE traffic (T250261).
225 if ( !$this->fieldHasFlag( $flags, self::PURGE_URLS_LINKSUPDATE_ONLY ) ) {
226 $urls[] = $title->getInternalURL( 'action=history' );
227
228 // Canonical action=raw URLs for user and site config pages (T58874, T261371).
229 if ( $title->isUserJsConfigPage() || $title->isSiteJsConfigPage() ) {
230 $urls[] = $title->getInternalURL( 'action=raw&ctype=text/javascript' );
231 } elseif ( $title->isUserJsonConfigPage() || $title->isSiteJsonConfigPage() ) {
232 $urls[] = $title->getInternalURL( 'action=raw&ctype=application/json' );
233 } elseif ( $title->isUserCssConfigPage() || $title->isSiteCssConfigPage() ) {
234 $urls[] = $title->getInternalURL( 'action=raw&ctype=text/css' );
235 }
236 }
237
238 // Extensions may add novel ways to access this content
239 $append = [];
240 $mode = $flags & self::PURGE_URLS_LINKSUPDATE_ONLY;
241 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable castFrom does not return null here
242 $this->hookRunner->onHtmlCacheUpdaterAppendUrls( $title, $mode, $append );
243 $urls = array_merge( $urls, $append );
244
245 // Extensions may add novel ways to access the site overall
246 $append = [];
247 $this->hookRunner->onHtmlCacheUpdaterVaryUrls( $urls, $append );
248 $urls = array_merge( $urls, $append );
249
250 // Legacy. TODO: Deprecate this
251 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable castFrom does not return null here
252 $this->hookRunner->onTitleSquidURLs( $title, $urls );
253
254 return $urls;
255 }
256}
Handles purging the appropriate CDN objects given a list of URLs or Title instances.
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...
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.