TCache   A
last analyzed

Complexity

Total Complexity 26

Size/Duplication

Total Lines 241
Duplicated Lines 0 %

Test Coverage

Coverage 67.31%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 38
c 1
b 0
f 0
dl 0
loc 241
ccs 35
cts 52
cp 0.6731
rs 10
wmc 26

15 Methods

Rating   Name   Duplication   Size   Complexity  
A getKeyPrefix() 0 3 1
A generateUniqueKey() 0 3 1
A setKeyPrefix() 0 3 1
A offsetExists() 0 3 1
A set() 0 7 3
A get() 0 11 5
A setPrimaryCache() 0 3 1
A init() 0 13 4
A offsetUnset() 0 3 1
A delete() 0 3 1
A add() 0 7 3
A getPrimaryCache() 0 3 1
A flush() 0 3 1
A offsetGet() 0 4 1
A offsetSet() 0 3 1
1
<?php
2
3
/**
4
 * TCache and cache dependency classes.
5
 *
6
 * @author Qiang Xue <[email protected]>
7
 * @link https://github.com/pradosoft/prado
8
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
9
 */
10
11
namespace Prado\Caching;
12
13
use Prado\Exceptions\TConfigurationException;
14
use Prado\Exceptions\TNotSupportedException;
15
use Prado\TPropertyValue;
16
17
/**
18
 * TCache class
19
 *
20
 * TCache is the base class for cache classes with different cache storage implementation.
21
 *
22
 * TCache implements the interface {@see \Prado\Caching\ICache} with the following methods,
23
 * - {@see get()} : retrieve the value with a key (if any) from cache
24
 * - {@see set()} : store the value with a key into cache
25
 * - {@see add()} : store the value only if cache does not have this key
26
 * - {@see delete()} : delete the value with the specified key from cache
27
 * - {@see flush()} : delete all values from cache
28
 *
29
 * Each value is associated with an expiration time. The {@see get()} operation
30
 * ensures that any expired value will not be returned. The expiration time by
31
 * the number of seconds. A expiration time 0 represents never expire.
32
 *
33
 * By definition, cache does not ensure the existence of a value
34
 * even if it never expires. Cache is not meant to be an persistent storage.
35
 *
36
 * Child classes must implement the following methods:
37
 * - {@see getValue()}
38
 * - {@see setValue()}
39
 * - {@see addValue()}
40
 * - {@see deleteValue()}
41
 *
42
 * and optionally {@see flush()}
43
 *
44
 * Since version 3.1.2, TCache implements the \ArrayAccess interface such that
45
 * the cache acts as an array.
46
 *
47
 * @author Qiang Xue <[email protected]>
48
 * @since 3.0
49
 */
50
abstract class TCache extends \Prado\TModule implements ICache, \ArrayAccess
51
{
52
	private $_prefix;
53
	private $_primary = true;
54
55
	/**
56
	 * Initializes the cache module.
57
	 * This method initializes the cache key prefix and registers the cache module
58
	 * with the application if the cache is primary.
59
	 * @param \Prado\Xml\TXmlElement $config the module configuration
60
	 */
61 17
	public function init($config)
62
	{
63 17
		if ($this->_prefix === null) {
64 7
			$this->_prefix = $this->getApplication()->getUniqueID();
65
		}
66 17
		if ($this->_primary) {
67 17
			if ($this->getApplication()->getCache() === null) {
68 17
				$this->getApplication()->setCache($this);
69
			} else {
70
				throw new TConfigurationException('cache_primary_duplicated', $this::class);
71
			}
72
		}
73 17
		parent::init($config);
74
	}
75
76
	/**
77
	 * @return bool whether this cache module is used as primary/system cache.
78
	 * A primary cache is used by PRADO core framework to cache data such as
79
	 * parsed templates, themes, etc.
80 1
	 */
81
	public function getPrimaryCache()
82 1
	{
83
		return $this->_primary;
84
	}
85
86
	/**
87
	 * @param bool $value whether this cache module is used as primary/system cache. Defaults to false.
88
	 * @see getPrimaryCache
89 1
	 */
90
	public function setPrimaryCache($value)
91 1
	{
92 1
		$this->_primary = TPropertyValue::ensureBoolean($value);
93
	}
94
95
	/**
96
	 * @return string a unique prefix for the keys of cached values.
97
	 * If it is not explicitly set, it will take the value of {@see \Prado\TApplication::getUniqueID}.
98 1
	 */
99
	public function getKeyPrefix()
100 1
	{
101
		return $this->_prefix;
102
	}
103
104
	/**
105
	 * @param string $value a unique prefix for the keys of cached values
106 11
	 */
107
	public function setKeyPrefix($value)
108 11
	{
109 11
		$this->_prefix = $value;
110
	}
111
112
	/**
113
	 * @param string $key a key identifying a value to be cached
114
	 * @return string a key generated from the provided key which ensures the uniqueness across applications
115 4
	 */
116
	protected function generateUniqueKey($key)
117 4
	{
118
		return md5($this->_prefix . $key);
119
	}
120
121
	/**
122
	 * Retrieves a value from cache with a specified key.
123
	 * @param string $id a key identifying the cached value
124
	 * @return false|mixed the value stored in cache, false if the value is not in the cache or expired.
125 4
	 */
126
	public function get($id)
127 4
	{
128 3
		if (($data = $this->getValue($this->generateUniqueKey($id))) !== false) {
129
			if (!is_array($data)) {
0 ignored issues
show
introduced by
The condition is_array($data) is always false.
Loading history...
130
				return false;
131 3
			}
132 3
			if (!($data[1] instanceof ICacheDependency) || !$data[1]->getHasChanged()) {
133
				return $data[0];
134
			}
135 1
		}
136
		return false;
137
	}
138
139
	/**
140
	 * Stores a value identified by a key into cache.
141
	 * If the cache already contains such a key, the existing value and
142
	 * expiration time will be replaced with the new ones. If the value is
143
	 * empty, the cache key will be deleted.
144
	 *
145
	 * @param string $id the key identifying the value to be cached
146
	 * @param mixed $value the value to be cached
147
	 * @param int $expire the number of seconds in which the cached value will expire. 0 means never expire.
148
	 * @param ICacheDependency $dependency dependency of the cached item. If the dependency changes, the item is labeled invalid.
149
	 * @return bool true if the value is successfully stored into cache, false otherwise
150 2
	 */
151
	public function set($id, $value, $expire = 0, $dependency = null)
152 2
	{
153
		if (empty($value) && $expire === 0) {
154
			return $this->delete($id);
155 2
		} else {
156 2
			$data = [$value, $dependency];
157
			return $this->setValue($this->generateUniqueKey($id), $data, $expire);
0 ignored issues
show
Bug introduced by
$data of type array<integer,Prado\Cach...eDependency|mixed|null> is incompatible with the type string expected by parameter $value of Prado\Caching\TCache::setValue(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

157
			return $this->setValue($this->generateUniqueKey($id), /** @scrutinizer ignore-type */ $data, $expire);
Loading history...
158
		}
159
	}
160
161
	/**
162
	 * Stores a value identified by a key into cache if the cache does not contain this key.
163
	 * Nothing will be done if the cache already contains the key or if value is empty.
164
	 * @param string $id the key identifying the value to be cached
165
	 * @param mixed $value the value to be cached
166
	 * @param int $expire the number of seconds in which the cached value will expire. 0 means never expire.
167
	 * @param ICacheDependency $dependency dependency of the cached item. If the dependency changes, the item is labeled invalid.
168
	 * @return bool true if the value is successfully stored into cache, false otherwise
169 1
	 */
170
	public function add($id, $value, $expire = 0, $dependency = null)
171 1
	{
172
		if (empty($value) && $expire === 0) {
173
			return false;
174 1
		}
175 1
		$data = [$value, $dependency];
176
		return $this->addValue($this->generateUniqueKey($id), $data, $expire);
0 ignored issues
show
Bug introduced by
$data of type array<integer,Prado\Cach...eDependency|mixed|null> is incompatible with the type string expected by parameter $value of Prado\Caching\TCache::addValue(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

176
		return $this->addValue($this->generateUniqueKey($id), /** @scrutinizer ignore-type */ $data, $expire);
Loading history...
177
	}
178
179
	/**
180
	 * Deletes a value with the specified key from cache
181
	 * @param string $id the key of the value to be deleted
182
	 * @return bool if no error happens during deletion
183 1
	 */
184
	public function delete($id)
185 1
	{
186
		return $this->deleteValue($this->generateUniqueKey($id));
187
	}
188
189
	/**
190
	 * Deletes all values from cache.
191
	 * Be careful of performing this operation if the cache is shared by multiple applications.
192
	 * Child classes may implement this method to realize the flush operation.
193
	 * @throws TNotSupportedException if this method is not overridden by child classes
194
	 */
195
	public function flush()
196
	{
197
		throw new TNotSupportedException('cache_flush_unsupported');
198
	}
199
200
	/**
201
	 * Retrieves a value from cache with a specified key.
202
	 * This method should be implemented by child classes to store the data
203
	 * in specific cache storage. The uniqueness and dependency are handled
204
	 * in {@see \Prado\Caching\TCache::get()} already. So only the implementation of data retrieval
205
	 * is needed.
206
	 * @param string $key a unique key identifying the cached value
207
	 * @return false|string the value stored in cache, false if the value is not in the cache or expired.
208
	 */
209
	abstract protected function getValue($key);
210
211
	/**
212
	 * Stores a value identified by a key in cache.
213
	 * This method should be implemented by child classes to store the data
214
	 * in specific cache storage. The uniqueness and dependency are handled
215
	 * in {@see \Prado\Caching\TCache::set()} already. So only the implementation of data storage
216
	 * is needed.
217
	 *
218
	 * @param string $key the key identifying the value to be cached
219
	 * @param string $value the value to be cached
220
	 * @param int $expire the number of seconds in which the cached value will expire. 0 means never expire.
221
	 * @return bool true if the value is successfully stored into cache, false otherwise
222
	 */
223
	abstract protected function setValue($key, $value, $expire);
224
225
	/**
226
	 * Stores a value identified by a key into cache if the cache does not contain this key.
227
	 * This method should be implemented by child classes to store the data
228
	 * in specific cache storage. The uniqueness and dependency are handled
229
	 * in {@see \Prado\Caching\TCache::add()} already. So only the implementation of data storage
230
	 * is needed.
231
	 *
232
	 * @param string $key the key identifying the value to be cached
233
	 * @param string $value the value to be cached
234
	 * @param int $expire the number of seconds in which the cached value will expire. 0 means never expire.
235
	 * @return bool true if the value is successfully stored into cache, false otherwise
236
	 */
237
	abstract protected function addValue($key, $value, $expire);
238
239
	/**
240
	 * Deletes a value with the specified key from cache
241
	 * This method should be implemented by child classes to delete the data from actual cache storage.
242
	 * @param string $key the key of the value to be deleted
243
	 * @return bool if no error happens during deletion
244
	 */
245
	abstract protected function deleteValue($key);
246
247
	/**
248
	 * Returns whether there is a cache entry with a specified key.
249
	 * This method is required by the interface \ArrayAccess.
250
	 * @param string $id a key identifying the cached value
251
	 * @return bool
252
	 */
253
	public function offsetExists($id): bool
254
	{
255
		return $this->get($id) !== false;
256
	}
257
258
	/**
259
	 * Retrieves the value from cache with a specified key.
260
	 * This method is required by the interface \ArrayAccess.
261
	 * @param string $id a key identifying the cached value
262
	 * @return false|mixed the value stored in cache, false if the value is not in the cache or expired.
263
	 */
264
	#[\ReturnTypeWillChange]
265
	public function offsetGet($id)
266
	{
267
		return $this->get($id);
268
	}
269
270
	/**
271
	 * Stores the value identified by a key into cache.
272
	 * If the cache already contains such a key, the existing value will be
273
	 * replaced with the new ones. To add expiration and dependencies, use the set() method.
274
	 * This method is required by the interface \ArrayAccess.
275
	 * @param string $id the key identifying the value to be cached
276
	 * @param mixed $value the value to be cached
277
	 */
278
	public function offsetSet($id, $value): void
279
	{
280
		$this->set($id, $value);
281
	}
282
283
	/**
284
	 * Deletes the value with the specified key from cache
285
	 * This method is required by the interface \ArrayAccess.
286
	 * @param string $id the key of the value to be deleted
287
	 */
288
	public function offsetUnset($id): void
289
	{
290
		$this->delete($id);
291
	}
292
}
293