• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / dd6e866a9e6d253114633104d9e3858d807178ba

19 Jun 2024 10:03AM UTC coverage: 48.628% (-4.3%) from 52.936%
dd6e866a9e6d253114633104d9e3858d807178ba

push

github

web-flow
Merge pull request #21431 from Yoast/21429-update-copy-in-the-introduction-and-consent-modals

Updates the copy for the introduction and consent modals

7441 of 13454 branches covered (55.31%)

Branch coverage included in aggregate %.

0 of 3 new or added lines in 2 files covered. (0.0%)

3718 existing lines in 107 files now uncovered.

25100 of 53464 relevant lines covered (46.95%)

62392.47 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/inc/sitemaps/class-sitemaps-cache-validator.php
1
<?php
2
/**
3
 * WPSEO plugin file.
4
 *
5
 * @package WPSEO\XML_Sitemaps
6
 */
7

8
/**
9
 * Handles storage keys for sitemaps caching and invalidation.
10
 *
11
 * @since 3.2
12
 */
13
class WPSEO_Sitemaps_Cache_Validator {
14

15
        /**
16
         * Prefix of the transient key for sitemap caches.
17
         *
18
         * @var string
19
         */
20
        public const STORAGE_KEY_PREFIX = 'yst_sm_';
21

22
        /**
23
         * Name of the option that holds the global validation value.
24
         *
25
         * @var string
26
         */
27
        public const VALIDATION_GLOBAL_KEY = 'wpseo_sitemap_cache_validator_global';
28

29
        /**
30
         * The format which creates the key of the option that holds the type validation value.
31
         *
32
         * @var string
33
         */
34
        public const VALIDATION_TYPE_KEY_FORMAT = 'wpseo_sitemap_%s_cache_validator';
35

36
        /**
37
         * Get the cache key for a certain type and page.
38
         *
39
         * A type of cache would be something like 'page', 'post' or 'video'.
40
         *
41
         * Example key format for sitemap type "post", page 1: wpseo_sitemap_post_1:akfw3e_23azBa .
42
         *
43
         * @since 3.2
44
         *
45
         * @param string|null $type The type to get the key for. Null or self::SITEMAP_INDEX_TYPE for index cache.
46
         * @param int         $page The page of cache to get the key for.
47
         *
48
         * @return bool|string The key where the cache is stored on. False if the key could not be generated.
49
         */
UNCOV
50
        public static function get_storage_key( $type = null, $page = 1 ) {
×
51

52
                // Using SITEMAP_INDEX_TYPE for sitemap index cache.
UNCOV
53
                $type = is_null( $type ) ? WPSEO_Sitemaps::SITEMAP_INDEX_TYPE : $type;
×
54

UNCOV
55
                $global_cache_validator = self::get_validator();
×
UNCOV
56
                $type_cache_validator   = self::get_validator( $type );
×
57

UNCOV
58
                $prefix  = self::STORAGE_KEY_PREFIX;
×
UNCOV
59
                $postfix = sprintf( '_%d:%s_%s', $page, $global_cache_validator, $type_cache_validator );
×
60

61
                try {
UNCOV
62
                        $type = self::truncate_type( $type, $prefix, $postfix );
×
63
                } catch ( OutOfBoundsException $exception ) {
×
64
                        // Maybe do something with the exception, for now just mark as invalid.
65
                        return false;
×
66
                }
67

68
                // Build key.
UNCOV
69
                $full_key = $prefix . $type . $postfix;
×
70

UNCOV
71
                return $full_key;
×
72
        }
73

74
        /**
75
         * If the type is over length make sure we compact it so we don't have any database problems.
76
         *
77
         * When there are more 'extremely long' post types, changes are they have variations in either the start or ending.
78
         * Because of this, we cut out the excess in the middle which should result in less chance of collision.
79
         *
80
         * @since 3.2
81
         *
82
         * @param string $type    The type of sitemap to be used.
83
         * @param string $prefix  The part before the type in the cache key. Only the length is used.
84
         * @param string $postfix The part after the type in the cache key. Only the length is used.
85
         *
86
         * @return string The type with a safe length to use
87
         *
88
         * @throws OutOfRangeException When there is less than 15 characters of space for a key that is originally longer.
89
         */
90
        public static function truncate_type( $type, $prefix = '', $postfix = '' ) {
×
91
                /*
92
                 * This length has been restricted by the database column length of 64 in the past.
93
                 * The prefix added by WordPress is '_transient_' because we are saving to a transient.
94
                 * We need to use a timeout on the transient, otherwise the values get autoloaded, this adds
95
                 * another restriction to the length.
96
                 */
97
                $max_length  = 45; // 64 - 19 ('_transient_timeout_')
×
98
                $max_length -= strlen( $prefix );
×
99
                $max_length -= strlen( $postfix );
×
100

101
                if ( strlen( $type ) > $max_length ) {
×
102

103
                        if ( $max_length < 15 ) {
×
104
                                /*
105
                                 * If this happens the most likely cause is a page number that is too high.
106
                                 *
107
                                 * So this would not happen unintentionally.
108
                                 * Either by trying to cause a high server load, finding backdoors or misconfiguration.
109
                                 */
110
                                throw new OutOfRangeException(
×
111
                                        __(
×
112
                                                'Trying to build the sitemap cache key, but the postfix and prefix combination leaves too little room to do this. You are probably requesting a page that is way out of the expected range.',
×
113
                                                'wordpress-seo'
×
UNCOV
114
                                        )
×
UNCOV
115
                                );
×
116
                        }
117

118
                        $half = ( $max_length / 2 );
×
119

120
                        $first_part = substr( $type, 0, ( ceil( $half ) - 1 ) );
×
121
                        $last_part  = substr( $type, ( 1 - floor( $half ) ) );
×
122

123
                        $type = $first_part . '..' . $last_part;
×
124
                }
125

126
                return $type;
×
127
        }
128

129
        /**
130
         * Invalidate sitemap cache.
131
         *
132
         * @since 3.2
133
         *
134
         * @param string|null $type The type to get the key for. Null for all caches.
135
         *
136
         * @return void
137
         */
138
        public static function invalidate_storage( $type = null ) {
×
139

140
                // Global validator gets cleared when no type is provided.
141
                $old_validator = null;
×
142

143
                // Get the current type validator.
144
                if ( ! is_null( $type ) ) {
×
145
                        $old_validator = self::get_validator( $type );
×
146
                }
147

148
                // Refresh validator.
149
                self::create_validator( $type );
×
150

151
                if ( ! wp_using_ext_object_cache() ) {
×
152
                        // Clean up current cache from the database.
153
                        self::cleanup_database( $type, $old_validator );
×
154
                }
155

156
                // External object cache pushes old and unretrieved items out by itself so we don't have to do anything for that.
157
        }
158

159
        /**
160
         * Cleanup invalidated database cache.
161
         *
162
         * @since 3.2
163
         *
164
         * @param string|null $type      The type of sitemap to clear cache for.
165
         * @param string|null $validator The validator to clear cache of.
166
         *
167
         * @return void
168
         */
169
        public static function cleanup_database( $type = null, $validator = null ) {
×
170

171
                global $wpdb;
×
172

173
                if ( is_null( $type ) ) {
×
174
                        // Clear all cache if no type is provided.
175
                        $like = sprintf( '%s%%', self::STORAGE_KEY_PREFIX );
×
176
                }
177
                else {
178
                        // Clear type cache for all type keys.
179
                        $like = sprintf( '%1$s%2$s_%%', self::STORAGE_KEY_PREFIX, $type );
×
180
                }
181

182
                /*
183
                 * Add slashes to the LIKE "_" single character wildcard.
184
                 *
185
                 * We can't use `esc_like` here because we need the % in the query.
186
                 */
187
                $where   = [];
×
188
                $where[] = sprintf( "option_name LIKE '%s'", addcslashes( '_transient_' . $like, '_' ) );
×
189
                $where[] = sprintf( "option_name LIKE '%s'", addcslashes( '_transient_timeout_' . $like, '_' ) );
×
190

191
                // Delete transients.
192
                //phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- We need to use a direct query here.
193
                //phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches.
194
                $wpdb->query(
×
195
                        $wpdb->prepare(
×
196
                        //phpcs:disable WordPress.DB.PreparedSQLPlaceholders -- %i placeholder is still not recognized.
197
                                'DELETE FROM %i WHERE ' . implode( ' OR ', array_fill( 0, count( $where ), '%s' ) ),
×
198
                                array_merge( [ $wpdb->options ], $where )
×
UNCOV
199
                        )
×
UNCOV
200
                );
×
201

202
                wp_cache_delete( 'alloptions', 'options' );
×
203
        }
204

205
        /**
206
         * Get the current cache validator.
207
         *
208
         * Without the type the global validator is returned.
209
         * This can invalidate -all- keys in cache at once.
210
         *
211
         * With the type parameter the validator for that specific type can be invalidated.
212
         *
213
         * @since 3.2
214
         *
215
         * @param string $type Provide a type for a specific type validator, empty for global validator.
216
         *
217
         * @return string|null The validator for the supplied type.
218
         */
219
        public static function get_validator( $type = '' ) {
×
220

221
                $key = self::get_validator_key( $type );
×
222

223
                $current = get_option( $key, null );
×
224
                if ( ! is_null( $current ) ) {
×
225
                        return $current;
×
226
                }
227

228
                if ( self::create_validator( $type ) ) {
×
229
                        return self::get_validator( $type );
×
230
                }
231

232
                return null;
×
233
        }
234

235
        /**
236
         * Get the cache validator option key for the specified type.
237
         *
238
         * @since 3.2
239
         *
240
         * @param string $type Provide a type for a specific type validator, empty for global validator.
241
         *
242
         * @return string Validator to be used to generate the cache key.
243
         */
UNCOV
244
        public static function get_validator_key( $type = '' ) {
×
245

UNCOV
246
                if ( empty( $type ) ) {
×
UNCOV
247
                        return self::VALIDATION_GLOBAL_KEY;
×
248
                }
249

UNCOV
250
                return sprintf( self::VALIDATION_TYPE_KEY_FORMAT, $type );
×
251
        }
252

253
        /**
254
         * Refresh the cache validator value.
255
         *
256
         * @since 3.2
257
         *
258
         * @param string $type Provide a type for a specific type validator, empty for global validator.
259
         *
260
         * @return bool True if validator key has been saved as option.
261
         */
262
        public static function create_validator( $type = '' ) {
×
263

264
                $key = self::get_validator_key( $type );
×
265

266
                // Generate new validator.
267
                $microtime = microtime();
×
268

269
                // Remove space.
270
                list( $milliseconds, $seconds ) = explode( ' ', $microtime );
×
271

272
                // Transients are purged every 24h.
273
                $seconds      = ( $seconds % DAY_IN_SECONDS );
×
274
                $milliseconds = intval( substr( $milliseconds, 2, 3 ), 10 );
×
275

276
                // Combine seconds and milliseconds and convert to integer.
277
                $validator = intval( $seconds . '' . $milliseconds, 10 );
×
278

279
                // Apply base 61 encoding.
280
                $compressed = self::convert_base10_to_base61( $validator );
×
281

282
                return update_option( $key, $compressed, false );
×
283
        }
284

285
        /**
286
         * Encode to base61 format.
287
         *
288
         * This is base64 (numeric + alpha + alpha upper case) without the 0.
289
         *
290
         * @since 3.2
291
         *
292
         * @param int $base10 The number that has to be converted to base 61.
293
         *
294
         * @return string Base 61 converted string.
295
         *
296
         * @throws InvalidArgumentException When the input is not an integer.
297
         */
UNCOV
298
        public static function convert_base10_to_base61( $base10 ) {
×
299

UNCOV
300
                if ( ! is_int( $base10 ) ) {
×
UNCOV
301
                        throw new InvalidArgumentException( __( 'Expected an integer as input.', 'wordpress-seo' ) );
×
302
                }
303

304
                // Characters that will be used in the conversion.
UNCOV
305
                $characters = '123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
×
UNCOV
306
                $length     = strlen( $characters );
×
307

UNCOV
308
                $remainder = $base10;
×
UNCOV
309
                $output    = '';
×
310

311
                do {
312
                        // Building from right to left in the result.
UNCOV
313
                        $index = ( $remainder % $length );
×
314

315
                        // Prepend the character to the output.
UNCOV
316
                        $output = $characters[ $index ] . $output;
×
317

318
                        // Determine the remainder after removing the applied number.
UNCOV
319
                        $remainder = floor( $remainder / $length );
×
320

321
                        // Keep doing it until we have no remainder left.
UNCOV
322
                } while ( $remainder );
×
323

UNCOV
324
                return $output;
×
325
        }
326
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc