PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 18.5
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v18.5
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 18.5, at inc/sitemaps/class-sitemaps-cache.php

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