PluginProbe
WebberZone Top 10 — Popular Posts / 4.5.1
WebberZone Top 10 — Popular Posts v4.5.1
4.5.1 4.5.0 4.4.3 4.4.2 4.4.1 4.4.0 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 trunk 1.0 1.0.1 1.1 1.2 1.3 1.4 1.4.1 1.5 1.5.1 1.5.2 1.5.3 1.6 1.6.1 All 117 releases
top-10 / includes / util / class-cache.php

class-cache.php in WebberZone Top 10 — Popular Posts 4.5.1, at includes/util/class-cache.php

399 lines 9.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Cache class.
4 *
5 * @package WebberZone\Top_Ten\Util
6 */
7
8 namespace WebberZone\Top_Ten\Util;
9
10 use WebberZone\Top_Ten\Util\Hook_Registry;
11
12 if ( ! defined( 'WPINC' ) ) {
13 die;
14 }
15
16 /**
17 * Cache class.
18 *
19 * @since 3.3.0
20 */
21 class Cache {
22
23 /**
24 * Constructor class.
25 *
26 * @since 3.3.0
27 */
28 public function __construct() {
29 Hook_Registry::add_action( 'wp_ajax_tptn_clear_cache', array( $this, 'ajax_clearcache' ) );
30 }
31
32 /**
33 * Function to clear the Top 10 Cache with Ajax.
34 *
35 * @since 2.2.0
36 */
37 public function ajax_clearcache() {
38
39 $network_wide = isset( $_POST['network_wide'] ) && '1' === sanitize_key( wp_unslash( $_POST['network_wide'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
40 $capability = $network_wide ? 'manage_network_options' : 'manage_options';
41
42 if ( ! current_user_can( $capability ) ) {
43 wp_die();
44 }
45 check_ajax_referer( 'tptn-admin', 'security' );
46
47 $count = $network_wide ? self::delete_network() : $this->delete();
48
49 wp_send_json_success(
50 array(
51 /* translators: 1: Number of entries cleared. */
52 'message' => sprintf(
53 $network_wide
54 ? _n( '%s cache entry cleared across the network', '%s cache entries cleared across the network', $count, 'top-10' )
55 : _n( '%s entry cleared', '%s entries cleared', $count, 'top-10' ),
56 number_format_i18n( $count )
57 ),
58 )
59 );
60 }
61
62 /**
63 * Delete the Top 10 cache.
64 *
65 * @since 2.3.0
66 *
67 * @param array $transients Array of transients to delete.
68 * @return int Number of transients deleted.
69 */
70 public static function delete( $transients = array() ) {
71 $loop = 0;
72
73 $default_transients = self::get_keys();
74
75 if ( ! empty( $transients ) ) {
76 $transients = array_intersect( $default_transients, (array) $transients );
77 } else {
78 $transients = $default_transients;
79 }
80
81 foreach ( $transients as $transient ) {
82 $del = delete_transient( $transient );
83 if ( $del ) {
84 ++$loop;
85 }
86 }
87 return $loop;
88 }
89
90 /**
91 * Delete the Top 10 cache across all active network sites.
92 *
93 * @since 4.5.0
94 *
95 * @return int Number of transients deleted.
96 */
97 public static function delete_network() {
98 if ( ! is_multisite() ) {
99 return self::delete();
100 }
101
102 $site_ids = wp_list_pluck(
103 get_sites(
104 array(
105 'archived' => 0,
106 'spam' => 0,
107 'deleted' => 0,
108 'number' => 0,
109 )
110 ),
111 'blog_id'
112 );
113 $count = 0;
114 $current_blog_id = get_current_blog_id();
115
116 foreach ( $site_ids as $site_id ) {
117 $site_id = absint( $site_id );
118 $switched = $site_id !== $current_blog_id;
119 if ( $switched ) {
120 switch_to_blog( $site_id );
121 }
122
123 try {
124 $count += self::delete();
125 } finally {
126 if ( $switched ) {
127 restore_current_blog();
128 }
129 }
130 }
131
132 return $count;
133 }
134
135 /**
136 * Get the default meta keys used for the cache
137 *
138 * @return array Transient meta keys
139 */
140 public static function get_keys() {
141
142 $meta_keys = array(
143 'tptn_total',
144 'tptn_daily',
145 'tptn_total_shortcode',
146 'tptn_daily_shortcode',
147 'tptn_total_widget',
148 'tptn_daily_widget',
149 'tptn_total_manual',
150 'tptn_daily_manual',
151 );
152
153 $meta_keys = array_merge( $meta_keys, self::get_widget_keys() );
154
155 /**
156 * Filters the array containing the various cache keys.
157 *
158 * @since 1.9
159 *
160 * @param array $default_meta_keys Array of meta keys
161 */
162 return apply_filters( 'tptn_cache_keys', $meta_keys );
163 }
164
165 /**
166 * Get the cache key based on a list of parameters.
167 *
168 * @since 4.2.0
169 *
170 * @param mixed $attr Array of attributes typically.
171 * @return string Cache meta key
172 */
173 public static function get_key( $attr ): string {
174 $args = (array) $attr;
175
176 static $setting_types = null;
177 if ( null === $setting_types ) {
178 $setting_types = function_exists( 'tptn_get_registered_settings_types' ) ? tptn_get_registered_settings_types() : array();
179 }
180
181 // Remove args that don't affect query results.
182 $exclude_keys = array(
183 'after_list',
184 'after_list_item',
185 'before_list',
186 'before_list_item',
187 'blank_output',
188 'blank_output_text',
189 'cache',
190 'className',
191 'echo',
192 'excerpt_length',
193 'extra_class',
194 'heading',
195 'is_block',
196 'is_manual',
197 'is_shortcode',
198 'is_widget',
199 'link_new_window',
200 'link_nofollow',
201 'more_link_text',
202 'no_found_rows',
203 'other_attributes',
204 'post_types',
205 'post_id',
206 'postid',
207 'same_post_type',
208 'show_author',
209 'show_credit',
210 'show_date',
211 'show_excerpt',
212 'show_metabox',
213 'show_metabox_admins',
214 'suppress_filters',
215 'title',
216 'title_length',
217 );
218
219 foreach ( $exclude_keys as $key ) {
220 unset( $args[ $key ] );
221 }
222
223 // Remove any keys ending in _header or _desc, or with type 'header'.
224 foreach ( $args as $key => $value ) {
225 if ( '_header' === substr( $key, -7 ) || '_desc' === substr( $key, -5 ) ) {
226 unset( $args[ $key ] );
227 continue;
228 }
229
230 if ( isset( $setting_types[ $key ] ) && 'header' === $setting_types[ $key ] ) {
231 unset( $args[ $key ] );
232 }
233 }
234
235 // Define categories of types for normalization.
236 $id_array_types = array( 'postids', 'numbercsv', 'taxonomies' );
237 $string_array_types = array( 'posttypes', 'csv', 'multicheck' );
238 $numeric_types = array( 'number', 'checkbox', 'select', 'radio', 'radiodesc' );
239
240 // Process arguments based on their registered types.
241 foreach ( $args as $key => $value ) {
242 $type = $setting_types[ $key ] ?? '';
243
244 if ( in_array( $type, $numeric_types, true ) && is_numeric( $value ) ) {
245 $args[ $key ] = (int) $value;
246 } elseif ( in_array( $type, $id_array_types, true ) ) {
247 $args[ $key ] = is_array( $value ) ? $value : wp_parse_id_list( $value );
248 $args[ $key ] = array_unique( array_map( 'absint', $args[ $key ] ) );
249 $args[ $key ] = array_filter( $args[ $key ] );
250 sort( $args[ $key ] );
251 if ( empty( $args[ $key ] ) ) {
252 unset( $args[ $key ] );
253 }
254 } elseif ( in_array( $type, $string_array_types, true ) ) {
255 if ( is_string( $value ) && strpos( $value, '=' ) !== false ) {
256 parse_str( $value, $parsed );
257 $value = array_keys( $parsed );
258 } elseif ( is_string( $value ) ) {
259 $value = explode( ',', $value );
260 }
261 $args[ $key ] = is_array( $value ) ? $value : array( $value );
262 $args[ $key ] = array_unique( array_map( 'strval', $args[ $key ] ) );
263 $args[ $key ] = array_filter( $args[ $key ] );
264 sort( $args[ $key ] );
265 if ( empty( $args[ $key ] ) ) {
266 unset( $args[ $key ] );
267 }
268 }
269 }
270
271 // Fallback for known keys that might not be in $setting_types or need specific handling.
272 $id_arrays = array(
273 'author__in',
274 'author__not_in',
275 'category__and',
276 'category__in',
277 'category__not_in',
278 'cornerstone_post_ids',
279 'exclude_categories',
280 'exclude_on_categories',
281 'exclude_on_post_ids',
282 'exclude_post_ids',
283 'include_cat_ids',
284 'include_post_ids',
285 'manual_related',
286 'post__in',
287 'post__not_in',
288 'post_parent__in',
289 'post_parent__not_in',
290 'tag__and',
291 'tag__in',
292 'tag__not_in',
293 'tag_slug__and',
294 'tag_slug__in',
295 );
296
297 foreach ( $id_arrays as $key ) {
298 if ( array_key_exists( $key, $args ) && ! isset( $setting_types[ $key ] ) ) {
299 if ( null !== $args[ $key ] ) {
300 $args[ $key ] = is_array( $args[ $key ] ) ? $args[ $key ] : wp_parse_id_list( $args[ $key ] );
301 $args[ $key ] = array_unique( array_map( 'absint', $args[ $key ] ) );
302 $args[ $key ] = array_filter( $args[ $key ] );
303 sort( $args[ $key ] );
304
305 if ( empty( $args[ $key ] ) ) {
306 unset( $args[ $key ] );
307 }
308 } else {
309 unset( $args[ $key ] );
310 }
311 }
312 }
313
314 $string_arrays = array(
315 'exclude_cat_slugs',
316 'exclude_on_cat_slugs',
317 'exclude_on_post_types',
318 'post_name__in',
319 'post_status',
320 'post_type',
321 'same_taxes',
322 );
323
324 foreach ( $string_arrays as $key ) {
325 if ( array_key_exists( $key, $args ) && ! isset( $setting_types[ $key ] ) ) {
326 if ( null !== $args[ $key ] ) {
327 if ( is_string( $args[ $key ] ) && strpos( $args[ $key ], '=' ) !== false ) {
328 parse_str( $args[ $key ], $parsed );
329 $parsed_value = array_keys( $parsed );
330 } elseif ( is_string( $args[ $key ] ) ) {
331 $parsed_value = explode( ',', $args[ $key ] );
332 } else {
333 $parsed_value = $args[ $key ];
334 }
335 $args[ $key ] = is_array( $parsed_value ) ? $parsed_value : array( $parsed_value );
336 $args[ $key ] = array_unique( array_map( 'strval', $args[ $key ] ) );
337 $args[ $key ] = array_filter( $args[ $key ] );
338 sort( $args[ $key ] );
339
340 if ( empty( $args[ $key ] ) ) {
341 unset( $args[ $key ] );
342 }
343 } else {
344 unset( $args[ $key ] );
345 }
346 }
347 }
348
349 // Sort top-level arguments.
350 ksort( $args );
351
352 // Remove any remaining empty strings or null values.
353 foreach ( $args as $key => $value ) {
354 if ( '' === $value || null === $value ) {
355 unset( $args[ $key ] );
356 }
357 }
358
359 // Keep generated keys discoverable by get_widget_keys() and delete().
360 return 'tptn_cache_' . md5( wp_json_encode( $args ) );
361 }
362
363 /**
364 * Get the transient names for the Top 10 widgets.
365 *
366 * @since 2.3.0
367 *
368 * @return array Top 10 Cache widget keys.
369 */
370 public static function get_widget_keys() {
371 global $wpdb;
372
373 $keys = array();
374
375 $sql = "
376 SELECT option_name
377 FROM {$wpdb->options}
378 WHERE `option_name` LIKE '_transient_tptn_%'
379 ";
380
381 $results = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
382
383 if ( is_array( $results ) ) {
384 foreach ( $results as $result ) {
385 $keys[] = str_replace( '_transient_', '', $result->option_name );
386 }
387 }
388
389 /**
390 * Filters the list of Top 10 cache keys found in the options table.
391 *
392 * @since 2.5.0
393 *
394 * @param string[] $keys Cache keys without the transient prefix.
395 */
396 return apply_filters( 'tptn_cache_get_widget_keys', $keys );
397 }
398 }
399