Test Failed
Push — issues/1944 ( 0c6474...cfd8d8 )
by Ravinder
05:01
created

Give_Cache::get_group()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 21
Code Lines 12

Duplication

Lines 21
Ratio 100 %

Importance

Changes 0
Metric Value
cc 6
eloc 12
nc 3
nop 3
dl 21
loc 21
rs 8.7624
c 0
b 0
f 0
1
<?php
2
/**
3
 * Class for managing cache
4
 * Note: only use for internal purpose.
5
 *
6
 * @package     Give
7
 * @subpackage  Classes/Give_Cache
8
 * @copyright   Copyright (c) 2017, WordImpress
9
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
10
 * @since       1.8.7
11
 */
12
13
// Exit if accessed directly.
14
if ( ! defined( 'ABSPATH' ) ) {
15
	exit;
16
}
17
18
class Give_Cache {
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
19
	/**
20
	 * Instance.
21
	 *
22
	 * @since  1.8.7
23
	 * @access static
24
	 * @var
25
	 */
26
	static private $instance;
27
28
	/**
29
	 * Singleton pattern.
30
	 *
31
	 * @since  1.8.7
32
	 * @access private
33
	 * Give_Cache constructor.
34
	 */
35
	private function __construct() {
36
	}
37
38
39
	/**
40
	 * Get instance.
41
	 *
42
	 * @since  1.8.7
43
	 * @access public
44
	 * @return static
45
	 */
46
	public static function get_instance() {
47
		if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Give_Cache ) ) {
48
			self::$instance = new Give_Cache();
49
		}
50
51
		return self::$instance;
52
	}
53
54
	/**
55
	 * Setup hooks.
56
	 *
57
	 * @since  1.8.7
58
	 * @access public
59
	 */
60
	public function setup_hooks() {
61
		// weekly delete all expired cache.
62
		Give_Cron::add_weekly_event( array( $this, 'delete_all_expired' ) );
63
	}
64
65
	/**
66
	 * Get cache key.
67
	 *
68
	 * @since  1.8.7
69
	 *
70
	 * @param  string $action     Cache key prefix.
71
	 * @param  array  $query_args (optional) Query array.
72
	 *
73
	 * @return string
74
	 */
75
76
	public static function get_key( $action, $query_args = null ) {
77
		$cache_key = "give_cache_{$action}";
78
79
		// Bailout.
80
		if ( ! empty( $query_args ) ) {
81
			$cache_key = "{$cache_key}_" . substr( md5( serialize( $query_args ) ), 0, 15 );
82
		}
83
84
		return $cache_key;
85
	}
86
87
	/**
88
	 * Get cache.
89
	 *
90
	 * @since  1.8.7
91
	 *
92
	 * @param  string $cache_key
93
	 * @param  bool   $custom_key
94
	 * @param  mixed  $query_args
95
	 *
96
	 * @return mixed
97
	 */
98
99
	public static function get( $cache_key, $custom_key = false, $query_args = array() ) {
100 View Code Duplication
		if ( ! self::is_valid_cache_key( $cache_key ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
101
			if ( ! $custom_key ) {
102
				return new WP_Error( 'give_invalid_cache_key', __( 'Cache key format should be give_cache_*', 'give' ) );
103
			}
104
105
			$cache_key = self::get_key( $cache_key, $query_args );
106
		}
107
108
		$option = get_option( $cache_key );
109
110
		// Backward compatibility (<1.8.7).
111
		if ( ! is_array( $option ) || empty( $option ) || ! array_key_exists( 'expiration', $option ) ) {
112
			return $option;
113
		}
114
115
		// Get current time.
116
		$current_time = current_time( 'timestamp', 1 );
117
118
		if ( empty( $option['expiration'] ) || ( $current_time < $option['expiration'] ) ) {
119
			$option = $option['data'];
120
		} else {
121
			$option = false;
122
		}
123
124
		return $option;
125
	}
126
127
	/**
128
	 * Set cache.
129
	 *
130
	 * @since  1.8.7
131
	 *
132
	 * @param  string   $cache_key
133
	 * @param  mixed    $data
134
	 * @param  int|null $expiration Timestamp should be in GMT format.
135
	 * @param  bool     $custom_key
136
	 * @param  mixed    $query_args
137
	 *
138
	 * @return mixed
139
	 */
140
141
	public static function set( $cache_key, $data, $expiration = null, $custom_key = false, $query_args = array() ) {
142 View Code Duplication
		if ( ! self::is_valid_cache_key( $cache_key ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
143
			if ( ! $custom_key ) {
144
				return new WP_Error( 'give_invalid_cache_key', __( 'Cache key format should be give_cache_*', 'give' ) );
145
			}
146
147
			$cache_key = self::get_key( $cache_key, $query_args );
148
		}
149
150
		$option_value = array(
151
			'data'       => $data,
152
			'expiration' => ! is_null( $expiration )
153
				? ( $expiration + current_time( 'timestamp', 1 ) )
154
				: null,
155
		);
156
157
		$result = update_option( $cache_key, $option_value, 'no' );
158
159
		return $result;
160
	}
161
162
	/**
163
	 * Delete cache.
164
	 *
165
	 * @since  1.8.7
166
	 *
167
	 * @param  string|array $cache_keys
168
	 *
169
	 * @return bool|WP_Error
170
	 */
171
172
	public static function delete( $cache_keys ) {
173
		$result       = true;
174
		$invalid_keys = array();
175
176
		if ( ! empty( $cache_keys ) ) {
177
			$cache_keys = is_array( $cache_keys ) ? $cache_keys : array( $cache_keys );
178
179
			foreach ( $cache_keys as $cache_key ) {
180
				if ( ! self::is_valid_cache_key( $cache_key ) ) {
181
					$invalid_keys[] = $cache_key;
182
					$result         = false;
183
				}
184
185
				delete_option( $cache_key );
186
			}
187
		}
188
189
		if ( ! $result ) {
190
			$result = new WP_Error(
191
				'give_invalid_cache_key',
192
				__( 'Cache key format should be give_cache_*', 'give' ),
193
				$invalid_keys
194
			);
195
		}
196
197
		return $result;
198
	}
199
200
	/**
201
	 * Delete all logging cache.
202
	 *
203
	 * @since  1.8.7
204
	 * @access public
205
	 * @global wpdb $wpdb
206
	 *
207
	 * @param bool  $force If set to true then all cached values will be delete instead of only expired
208
	 *
209
	 * @return bool
210
	 */
211
	public static function delete_all_expired( $force = false ) {
212
		global $wpdb;
213
		$options = $wpdb->get_results(
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
214
			$wpdb->prepare(
215
				"SELECT option_name, option_value
216
						FROM {$wpdb->options}
217
						Where option_name
218
						LIKE '%%%s%%'",
219
				'give_cache'
220
			),
221
			ARRAY_A
222
		);
223
224
		// Bailout.
225
		if ( empty( $options ) ) {
226
			return false;
227
		}
228
229
		$current_time = current_time( 'timestamp', 1 );
230
231
		// Delete log cache.
232
		foreach ( $options as $option ) {
233
			$option['option_value'] = maybe_unserialize( $option['option_value'] );
234
235
			if (
236
				(
237
					! self::is_valid_cache_key( $option['option_name'] )
238
					|| ! is_array( $option['option_value'] ) // Backward compatibility (<1.8.7).
239
					|| ! array_key_exists( 'expiration', $option['option_value'] ) // Backward compatibility (<1.8.7).
240
					|| empty( $option['option_value']['expiration'] )
241
					|| ( $current_time < $option['option_value']['expiration'] )
242
				)
243
				&& ! $force
244
			) {
245
				continue;
246
			}
247
248
			self::delete( $option['option_name'] );
249
		}
250
	}
251
252
253
	/**
254
	 * Get list of options like.
255
	 *
256
	 * @since  1.8.7
257
	 * @access public
258
	 *
259
	 * @param string $option_name
260
	 * @param bool   $fields
261
	 *
262
	 * @return array
263
	 */
264
	public static function get_options_like( $option_name, $fields = false ) {
265
		global $wpdb;
266
267
		if ( empty( $option_name ) ) {
268
			return array();
269
		}
270
271
		$field_names = $fields ? 'option_name, option_value' : 'option_name';
272
273
		if ( $fields ) {
274
			$options = $wpdb->get_results(
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
275
				$wpdb->prepare(
276
					"SELECT {$field_names }
277
						FROM {$wpdb->options}
278
						Where option_name
279
						LIKE '%%%s%%'",
280
					"give_cache_{$option_name}"
281
				),
282
				ARRAY_A
283
			);
284
		} else {
285
			$options = $wpdb->get_col(
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
286
				$wpdb->prepare(
287
					"SELECT *
288
						FROM {$wpdb->options}
289
						Where option_name
290
						LIKE '%%%s%%'",
291
					"give_cache_{$option_name}"
292
				),
293
				1
294
			);
295
		}
296
297
		if ( ! empty( $options ) && $fields ) {
298
			foreach ( $options as $index => $option ) {
299
				$option['option_value'] = maybe_unserialize( $option['option_value'] );
300
				$options[ $index ]      = $option;
301
			}
302
		}
303
304
		return $options;
305
	}
306
307
	/**
308
	 * Check cache key validity.
309
	 *
310
	 * @since  1.8.7
311
	 * @access public
312
	 *
313
	 * @param $cache_key
314
	 *
315
	 * @return bool|int
316
	 */
317
	public static function is_valid_cache_key( $cache_key ) {
318
		return ( false !== strpos( $cache_key, 'give_cache_' ) );
319
	}
320
321
322
	/**
323
	 * Get cache from group
324
	 *
325
	 * @since  2.0
326
	 * @access public
327
	 *
328
	 * @param int    $id
329
	 * @param string $group
330
	 * @param string $cache_type
331
	 *
332
	 * @return mixed
333
	 */
334 View Code Duplication
	public static function get_group( $id, $group = '', $cache_type = 'persistent' ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
335
		$cached_data = false;
336
337
		// Bailout.
338
		if (
339
			// We can disable cache by setting GIVE_CACHE false.
340
			( defined( 'GIVE_CACHE' ) && ! GIVE_CACHE ) ||
341
			empty( $id ) ||
342
			empty( $cache_type )
343
		) {
344
			return $cached_data;
345
		}
346
347
		switch ( $cache_type ) {
348
			case 'persistent':
349
				$cached_data = wp_cache_get( $id, $group );
350
				break;
351
		}
352
353
		return $cached_data;
354
	}
355
356
	/**
357
	 * Cache small chunks inside group
358
	 *
359
	 * @since  2.0
360
	 * @access public
361
	 *
362
	 * @param int    $id
363
	 * @param mixed  $data
364
	 * @param string $group
365
	 * @param int    $expire
366
	 * @param string $cache_type
367
	 *
368
	 * @return bool
369
	 */
370 View Code Duplication
	public static function set_group( $id, $data, $group = '', $expire = 0, $cache_type = 'persistent' ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
371
		$status = false;
372
373
		// Bailout.
374
		if (
375
			// We can disable cache by setting GIVE_CACHE false.
376
			( defined( 'GIVE_CACHE' ) && ! GIVE_CACHE ) ||
377
			empty( $id ) ||
378
			empty( $cache_type )
379
		) {
380
			return $status;
381
		}
382
383
		switch ( $cache_type ) {
384
			case 'persistent':
385
				$status = wp_cache_set( $id, $data, $group, $expire );
386
				break;
387
		}
388
389
		return $status;
390
	}
391
392
	/**
393
	 * Delete group cache
394
	 *
395
	 * @since  2.0
396
	 * @access public
397
	 *
398
	 * @param int    $id
399
	 * @param string $group
400
	 * @param int    $expire
401
	 * @param string $cache_type
402
	 *
403
	 * @return bool
404
	 */
405 View Code Duplication
	public static function delete_group( $id, $group = '', $expire = 0, $cache_type = 'persistent' ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
406
		$status = false;
407
408
		// Bailout.
409
		if (
410
			// We can disable cache by setting GIVE_CACHE false.
411
			( defined( 'GIVE_CACHE' ) && ! GIVE_CACHE ) ||
412
			empty( $id ) ||
413
			empty( $cache_type )
414
		) {
415
			return $status;
416
		}
417
418
		switch ( $cache_type ) {
419
			case 'persistent':
420
				$status = wp_cache_delete( $id, $group, $expire );
421
				break;
422
		}
423
424
		return $status;
425
	}
426
}
427
428
// Initialize
429
Give_Cache::get_instance()->setup_hooks();
430
431
// @todo Check if we can implement GIVE_CACHE for persistent and non-persistent cache.
432