Transients::delete()   A
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 1
nc 1
nop 2
dl 0
loc 2
ccs 2
cts 2
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of mundschenk-at/wp-data-storage.
4
 *
5
 * Copyright 2017-2019 Peter Putzer.
6
 *
7
 * This program is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU General Public License
9
 * as published by the Free Software Foundation; either version 2
10
 * of the License, or ( at your option ) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
 *
21
 * @package mundschenk-at/wp-data-storage/tests
22
 * @license http://www.gnu.org/licenses/gpl-2.0.html
23
 */
24
25
namespace Mundschenk\Data_Storage;
26
27
/**
28
 * Implements an interface to the WordPress Transients API.
29
 *
30
 * @since 1.0.0
31
 *
32
 * @author Peter Putzer <[email protected]>
33
 */
34
class Transients extends Abstract_Cache {
35
36
	const TRANSIENT_SQL_PREFIX = '_transient_';
37
38
	/**
39
	 * The incrementor transient key.
40
	 *
41
	 * @var string
42
	 */
43
	protected $incrementor_key;
44
45
	/**
46
	 * Create new cache instance.
47
	 *
48
	 * @param string $prefix The prefix automatically added to transient names.
49
	 */
50 2
	public function __construct( $prefix ) {
51 2
		$this->incrementor_key = $prefix . 'transients_incrementor';
52 2
		$this->incrementor     = $this->get( $this->incrementor_key, true );
53
54 2
		parent::__construct( $prefix );
55 2
	}
56
57
	/**
58
	 * Invalidate all cached elements by reseting the incrementor.
59
	 */
60 4
	public function invalidate() {
61
62 4
		if ( ! \wp_using_ext_object_cache() ) {
63
			// Clean up old transients.
64 2
			foreach ( $this->get_keys_from_database() as $old_transient ) {
65 2
				$this->delete( $old_transient, true );
66
			}
67
		}
68
69
		// Update incrementor.
70 4
		$this->incrementor = time();
71 4
		$this->set( $this->incrementor_key, $this->incrementor, 0, true );
72 4
	}
73
74
	/**
75
	 * Retrieves a list of transients set by the plugin from the options table.
76
	 *
77
	 * @return string[]
78
	 */
79 1
	public function get_keys_from_database() {
80
		/**
81
		 * WordPress database handler.
82
		 *
83
		 * @var \wpdb
84
		 */
85 1
		global $wpdb;
86
87 1
		$results = $wpdb->get_results(
88 1
			$wpdb->prepare(
89 1
				"SELECT option_name FROM {$wpdb->options} WHERE option_name like %s",
90 1
				static::TRANSIENT_SQL_PREFIX . "{$this->get_prefix()}%"
91
			),
92 1
			ARRAY_A
93
		); // WPCS: db call ok, cache ok.
94
95 1
		return \str_replace( static::TRANSIENT_SQL_PREFIX, '', \wp_list_pluck( $results, 'option_name' ) );
96
	}
97
98
	/**
99
	 * Retrieves a cached value.
100
	 *
101
	 * @param string $key The cache key.
102
	 * @param bool   $raw Optional. Use the raw key name (i.e. don't call get_key). Default false.
103
	 *
104
	 * @return mixed
105
	 */
106 1
	public function get( $key, $raw = false ) {
107 1
		return \get_transient( $raw ? $key : $this->get_key( $key ) );
108
	}
109
110
	/**
111
	 * Retrieves a cached large object.
112
	 *
113
	 * @param string $key The cache key.
114
	 *
115
	 * @return mixed
116
	 */
117 6
	public function get_large_object( $key ) {
118 6
		$encoded = $this->get( $key );
119 6
		if ( false === $encoded ) {
120 2
			return false;
121
		}
122
123 4
		$uncompressed = @\gzdecode( \base64_decode( $encoded ) ); // @codingStandardsIgnoreLine
124 4
		if ( false === $uncompressed ) {
125 2
			return false;
126
		}
127
128 2
		return $this->maybe_fix_object( \unserialize( $uncompressed ) ); // @codingStandardsIgnoreLine
129
	}
130
131
	/**
132
	 * Sets an entry in the cache and stores the key.
133
	 *
134
	 * @param string $key       The cache key.
135
	 * @param mixed  $value     The value to store.
136
	 * @param int    $duration  Optional. The duration in seconds. Default 0 (no expiration).
137
	 * @param bool   $raw       Optional. Use the raw key name (i.e. don't call get_key). Default false.
138
	 *
139
	 * @return bool True if the cache could be set successfully.
140
	 */
141 1
	public function set( $key, $value, $duration = 0, $raw = false ) {
142 1
		return \set_transient( $raw ? $key : $this->get_key( $key ), $value, $duration );
143
	}
144
145
	/**
146
	 * Sets a transient for a large PHP object. The object will be stored in
147
	 * serialized and gzip encoded form using Base64 encoding to ensure binary safety.
148
	 *
149
	 * @param string $key       The cache key.
150
	 * @param mixed  $value     The value to store.
151
	 * @param int    $duration  Optional. The duration in seconds. Default 0 (no expiration).
152
	 *
153
	 * @return bool True if the cache could be set successfully.
154
	 */
155 2
	public function set_large_object( $key, $value, $duration = 0 ) {
156 2
		$compressed = \gzencode( \serialize( $value ) ); // @codingStandardsIgnoreLine
157
158 2
		if ( false === $compressed ) {
159
			return false; // @codeCoverageIgnore
160
		}
161
162
		// base64_encode() is used to safely store the gzipped serialized object
163
		// in the WordPress database.
164 2
		return $this->set( $key, \base64_encode( $compressed ), $duration ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
165
	}
166
167
	/**
168
	 * Deletes an entry from the cache.
169
	 *
170
	 * @param string $key The cache key root.
171
	 * @param bool   $raw Optional. Use the raw key name (i.e. don't call get_key). Default false.
172
	 *
173
	 * @return bool True on successful removal, false on failure.
174
	 */
175 1
	public function delete( $key, $raw = false ) {
176 1
		return \delete_transient( $raw ? $key : $this->get_key( $key ) );
177
	}
178
179
	/**
180
	 * Tries to fix object cache implementations sometimes returning __PHP_Incomplete_Class.
181
	 *
182
	 * Originally based on http://stackoverflow.com/a/1173769/6646342 and refactored
183
	 * for PHP 7.2 compatibility.
184
	 *
185
	 * @param  object $object An object that should have been unserialized, but may be of __PHP_Incomplete_Class.
186
	 *
187
	 * @return object         The object with its real class.
188
	 */
189 2
	protected function maybe_fix_object( $object ) {
190 2
		if ( '__PHP_Incomplete_Class' === \get_class( $object ) ) {
191 2
			$object = \unserialize( \serialize( $object ) ); // phpcs:disable WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize,WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
192
		}
193
194 2
		return $object;
195
	}
196
}
197