PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 27.9
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v27.9
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
wordpress-seo / inc / sitemaps / class-sitemaps-cache.php

class-sitemaps-cache.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 27.9, at inc/sitemaps/class-sitemaps-cache.php

360 lines 8.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WPSEO plugin file.
4 *
5 * @package WPSEO\XML_Sitemaps
6 */
7
8 /**
9 * Handles sitemaps caching and invalidation.
10 *
11 * @since 3.2
12 */
13 class WPSEO_Sitemaps_Cache {
14
15 /**
16 * Holds the options that, when updated, should cause the cache to clear.
17 *
18 * @var array
19 */
20 protected static $cache_clear = [];
21
22 /**
23 * Mirror of enabled status for static calls.
24 *
25 * @var bool
26 */
27 protected static $is_enabled = false;
28
29 /**
30 * Holds the flag to clear all cache.
31 *
32 * @var bool
33 */
34 protected static $clear_all = false;
35
36 /**
37 * Holds the array of types to clear.
38 *
39 * @var array
40 */
41 protected static $clear_types = [];
42
43 /**
44 * Hook methods for invalidation on necessary events.
45 */
46 public function __construct() {
47
48 add_action( 'init', [ $this, 'init' ] );
49
50 add_action( 'deleted_term_relationships', [ self::class, 'invalidate' ] );
51
52 add_action( 'update_option', [ self::class, 'clear_on_option_update' ] );
53
54 add_action( 'edited_terms', [ self::class, 'invalidate_helper' ], 10, 2 );
55 add_action( 'clean_term_cache', [ self::class, 'invalidate_helper' ], 10, 2 );
56 add_action( 'clean_object_term_cache', [ self::class, 'invalidate_helper' ], 10, 2 );
57
58 add_action( 'user_register', [ self::class, 'invalidate_author' ] );
59 add_action( 'delete_user', [ self::class, 'invalidate_author' ] );
60
61 add_action( 'shutdown', [ self::class, 'clear_queued' ] );
62 }
63
64 /**
65 * Setup context for static calls.
66 *
67 * @return void
68 */
69 public function init() {
70
71 self::$is_enabled = $this->is_enabled();
72 }
73
74 /**
75 * If cache is enabled.
76 *
77 * @since 3.2
78 *
79 * @return bool
80 */
81 public function is_enabled() {
82
83 /**
84 * Filter if XML sitemap transient cache is enabled.
85 *
86 * @param bool $unsigned Enable cache or not, defaults to true.
87 */
88 return apply_filters( 'wpseo_enable_xml_sitemap_transient_caching', false );
89 }
90
91 /**
92 * Retrieve the sitemap page from cache.
93 *
94 * @since 3.2
95 *
96 * @param string $type Sitemap type.
97 * @param int $page Page number to retrieve.
98 *
99 * @return string|bool
100 */
101 public function get_sitemap( $type, $page ) {
102
103 $transient_key = WPSEO_Sitemaps_Cache_Validator::get_storage_key( $type, $page );
104 if ( $transient_key === false ) {
105 return false;
106 }
107
108 return get_transient( $transient_key );
109 }
110
111 /**
112 * Get the sitemap that is cached.
113 *
114 * @param string $type Sitemap type.
115 * @param int $page Page number to retrieve.
116 *
117 * @return WPSEO_Sitemap_Cache_Data|null Null on no cache found otherwise object containing sitemap and meta data.
118 */
119 public function get_sitemap_data( $type, $page ) {
120
121 $sitemap = $this->get_sitemap( $type, $page );
122
123 if ( empty( $sitemap ) ) {
124 return null;
125 }
126
127 /*
128 * Unserialize Cache Data object as is_serialized() doesn't recognize classes in C format.
129 * This work-around should no longer be needed once the minimum PHP version has gone up to PHP 7.4,
130 * as the `WPSEO_Sitemap_Cache_Data` class uses O format serialization in PHP 7.4 and higher.
131 *
132 * @link https://wiki.php.net/rfc/custom_object_serialization
133 */
134 if ( is_string( $sitemap ) && strpos( $sitemap, 'C:24:"WPSEO_Sitemap_Cache_Data"' ) === 0 ) {
135 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize -- Can't be avoided due to how WP stores options.
136 $sitemap = unserialize( $sitemap );
137 }
138
139 // What we expect it to be if it is set.
140 if ( $sitemap instanceof WPSEO_Sitemap_Cache_Data_Interface ) {
141 return $sitemap;
142 }
143
144 return null;
145 }
146
147 /**
148 * Store the sitemap page from cache.
149 *
150 * @since 3.2
151 *
152 * @param string $type Sitemap type.
153 * @param int $page Page number to store.
154 * @param string $sitemap Sitemap body to store.
155 * @param bool $usable Is this a valid sitemap or a cache of an invalid sitemap.
156 *
157 * @return bool
158 */
159 public function store_sitemap( $type, $page, $sitemap, $usable = true ) {
160
161 $transient_key = WPSEO_Sitemaps_Cache_Validator::get_storage_key( $type, $page );
162
163 if ( $transient_key === false ) {
164 return false;
165 }
166
167 $status = ( $usable ) ? WPSEO_Sitemap_Cache_Data::OK : WPSEO_Sitemap_Cache_Data::ERROR;
168
169 $sitemap_data = new WPSEO_Sitemap_Cache_Data();
170 $sitemap_data->set_sitemap( $sitemap );
171 $sitemap_data->set_status( $status );
172
173 return set_transient( $transient_key, $sitemap_data, DAY_IN_SECONDS );
174 }
175
176 /**
177 * Delete cache transients for index and specific type.
178 *
179 * Always deletes the main index sitemaps cache, as that's always invalidated by any other change.
180 *
181 * @since 1.5.4
182 * @since 3.2 Changed from function wpseo_invalidate_sitemap_cache() to method in this class.
183 *
184 * @param string $type Sitemap type to invalidate.
185 *
186 * @return void
187 */
188 public static function invalidate( $type ) {
189
190 self::clear( [ $type ] );
191 }
192
193 /**
194 * Helper to invalidate in hooks where type is passed as second argument.
195 *
196 * @since 3.2
197 *
198 * @param int $unused Unused term ID value.
199 * @param string $type Taxonomy to invalidate.
200 *
201 * @return void
202 */
203 public static function invalidate_helper( $unused, $type ) {
204
205 if (
206 WPSEO_Options::get( 'noindex-' . $type ) === false
207 || WPSEO_Options::get( 'noindex-tax-' . $type ) === false
208 ) {
209 self::invalidate( $type );
210 }
211 }
212
213 /**
214 * Invalidate sitemap cache for authors.
215 *
216 * @param int $user_id User ID.
217 *
218 * @return bool True if the sitemap was properly invalidated. False otherwise.
219 */
220 public static function invalidate_author( $user_id ) {
221
222 $user = get_user_by( 'id', $user_id );
223
224 if ( $user === false ) {
225 return false;
226 }
227
228 if ( current_action() === 'user_register' ) {
229 update_user_meta( $user_id, '_yoast_wpseo_profile_updated', time() );
230 }
231
232 if ( empty( $user->roles ) || in_array( 'subscriber', $user->roles, true ) ) {
233 return false;
234 }
235
236 self::invalidate( 'author' );
237
238 return true;
239 }
240
241 /**
242 * Invalidate sitemap cache for the post type of a post.
243 *
244 * Don't invalidate for revisions.
245 *
246 * @since 1.5.4
247 * @since 3.2 Changed from function wpseo_invalidate_sitemap_cache_on_save_post() to method in this class.
248 *
249 * @param int $post_id Post ID to invalidate type for.
250 *
251 * @return void
252 */
253 public static function invalidate_post( $post_id ) {
254
255 if ( wp_is_post_revision( $post_id ) ) {
256 return;
257 }
258
259 self::invalidate( get_post_type( $post_id ) );
260 }
261
262 /**
263 * Delete cache transients for given sitemaps types or all by default.
264 *
265 * @since 1.8.0
266 * @since 3.2 Moved from WPSEO_Utils to this class.
267 *
268 * @param array $types Set of sitemap types to delete cache transients for.
269 *
270 * @return void
271 */
272 public static function clear( $types = [] ) {
273
274 if ( ! self::$is_enabled ) {
275 return;
276 }
277
278 // No types provided, clear all.
279 if ( empty( $types ) ) {
280 self::$clear_all = true;
281
282 return;
283 }
284
285 // Always invalidate the index sitemap as well.
286 if ( ! in_array( WPSEO_Sitemaps::SITEMAP_INDEX_TYPE, $types, true ) ) {
287 array_unshift( $types, WPSEO_Sitemaps::SITEMAP_INDEX_TYPE );
288 }
289
290 foreach ( $types as $type ) {
291 if ( ! in_array( $type, self::$clear_types, true ) ) {
292 self::$clear_types[] = $type;
293 }
294 }
295 }
296
297 /**
298 * Invalidate storage for cache types queued to clear.
299 *
300 * @return void
301 */
302 public static function clear_queued() {
303
304 if ( self::$clear_all ) {
305
306 WPSEO_Sitemaps_Cache_Validator::invalidate_storage();
307 self::$clear_all = false;
308 self::$clear_types = [];
309
310 return;
311 }
312
313 foreach ( self::$clear_types as $type ) {
314 WPSEO_Sitemaps_Cache_Validator::invalidate_storage( $type );
315 }
316
317 self::$clear_types = [];
318 }
319
320 /**
321 * Adds a hook that when given option is updated, the cache is cleared.
322 *
323 * @since 3.2
324 *
325 * @param string $option Option name.
326 * @param string $type Sitemap type.
327 *
328 * @return void
329 */
330 public static function register_clear_on_option_update( $option, $type = '' ) {
331
332 self::$cache_clear[ $option ] = $type;
333 }
334
335 /**
336 * Clears the transient cache when a given option is updated, if that option has been registered before.
337 *
338 * @since 3.2
339 *
340 * @param string $option The option name that's being updated.
341 *
342 * @return void
343 */
344 public static function clear_on_option_update( $option ) {
345
346 if ( array_key_exists( $option, self::$cache_clear ) ) {
347
348 if ( empty( self::$cache_clear[ $option ] ) ) {
349 // Clear all caches.
350 self::clear();
351 }
352 else {
353 // Clear specific provided type(s).
354 $types = (array) self::$cache_clear[ $option ];
355 self::clear( $types );
356 }
357 }
358 }
359 }
360