CacheData::checkClash()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Cachearium;
4
5
/**
6
 * Class used to store cache data in start()/get();
7
 *
8
 */
9
class CacheData {
10
	const CACHEDATA_TYPE_CALLBACK = 'callback';
11
	const CACHEDATA_TYPE_RECURSION = 'recursion';
12
	const CACHEDATA_TYPE_RECURSION_DATA = 'recursiondata';
13
	const CACHEDATA_TYPE_DATA = 'data';
14
15
	/**
16
	 *
17
	 * @var CacheKey
18
	 */
19
	public $key;
20
21
	/**
22
	 * Lifetime: how long this cache should live. It's up to the storage implementation
23
	 * the details of how this will be obeyed, if at all.
24
	 * @var integer
25
	 */
26
	public $lifetime;
27
28
	/**
29
	 * This is a storage of dependencies for this cache. This is stored here as
30
	 * the russian doll model will automatically push up dependencies. In the end
31
	 * this will probably be used by the storage for easy invalidation.
32
	 *
33
	 * @var array:CacheKey
34
	 */
35
	public $dependencies = array();
36
37
	/**
38
	 * The actual cached data
39
	 * @var array
40
	 */
41
	public $data = array();
42
43
	private $dependenciesHash = '';
44
45
	public function __construct(CacheKey $ck, $data = null) {
46
		$this->setKey($ck);
47
48
		if ($data) {
49
			$this->appendData($data);
50
		}
51
	}
52
53
	/**
54
	 *
55
	 * @param CacheKey $ck
56
	 * @return CacheData
57
	 */
58
	public function setKey(CacheKey $ck) {
59
		$this->key = $ck;
60
		return $this;
61
	}
62
63
	/**
64
	 *
65
	 * @param unknown $callback
66
	 * @return CacheData
67
	 */
68
	public function appendCallback(callable $callback) {
69
		$this->data[] = array('type' => self::CACHEDATA_TYPE_CALLBACK, 'data' => $callback);
70
		return $this;
71
	}
72
73
	/**
74
	 *
75
	 * @param CacheData $cd
76
	 * @return CacheData
77
	 */
78
	public function mergeDependencies(CacheData $cd) {
79
		$this->dependencies = array_unique(array_merge($this->dependencies, $cd->dependencies));
80
		return $this;
81
	}
82
83
	public function clearDependenciesHash() {
84
		$this->dependenciesHash = '';
85
	}
86
87
	/**
88
	 * Checks if dependencies are still fresh.
89
	 * @param CacheAbstract $cache
90
	 * @return boolean
91
	 */
92
	public function checkUpdateToDate(CacheAbstract $cache) {
93
		// no deps? bail out
94
		if (!count($this->dependencies)) {
95
			return true;
96
		}
97
		if ($this->generateDependenciesHash($cache) == $this->dependenciesHash) {
98
			return true;
99
		}
100
		return false;
101
	}
102
103
	/**
104
	 * Init dependencies. If increment is not supported by backend return 0.
105
	 *
106
	 * @param CacheAbstract $cache
107
	 * @param CacheKey $k
108
	 * @return integer
109
	 */
110
	public function dependencyInit(CacheAbstract $cache, CacheKey $k) {
111
		try {
112
			return $cache->increment(0, $k, 0);
113
		}
114
		catch (\Cachearium\Exceptions\CacheUnsupportedOperation $e) {
115
			return 0;
116
		}
117
	}
118
119
	/**
120
	 * Get a fresh hash based on dependencies. Does not update the current hash.
121
	 * @param CacheAbstract $cache
122
	 * @return string
123
	 */
124
	public function generateDependenciesHash(CacheAbstract $cache) {
125
		if (!count($this->dependencies)) {
126
			return '';
127
		}
128
		$values = $cache->getMulti($this->dependencies, array($this, 'dependencyInit'));
129
		return md5(implode($values));
130
	}
131
132
	public function updateDependenciesHash(CacheAbstract $cache) {
133
		$this->dependenciesHash = $this->generateDependenciesHash($cache);
134
		return $this;
135
	}
136
137
	public function updateDependenciesHashIfNull(CacheAbstract $cache) {
138
		if (!$this->dependenciesHash) {
139
			$this->dependenciesHash = $this->generateDependenciesHash($cache);
140
		}
141
		return $this;
142
	}
143
144
	public function getKey() {
145
		return $this->key;
146
	}
147
148
	public function getDependenciesHash() {
149
		return $this->dependenciesHash;
150
	}
151
152
	public function getDependencies() {
153
		return $this->dependencies;
154
	}
155
156
	/**
157
	 *
158
	 * @param mixed $data Any kind of data you want to store. usually strings.
159
	 * @return CacheData
160
	 */
161
	public function appendData($data) {
162
		if ($data) {
163
			$this->data[] = array('type' => self::CACHEDATA_TYPE_DATA, 'data' => $data);
164
		}
165
		return $this;
166
	}
167
168
	/**
169
	 * Convenience function. Returns the first data self::CACHEDATA_TYPE_DATA that you
170
	 * stored. Returns null if there is none.
171
	 *
172
	 * @return any|NULL
173
	 */
174
	public function getFirstData() {
175
		foreach ($this->data as $d) {
176
			if ($d['type'] == self::CACHEDATA_TYPE_DATA) {
177
				return $d['data'];
178
			}
179
		}
180
		return null;
181
	}
182
183
	public function appendRecursion(CacheKey $k) {
184
		$this->addDependency($k);
185
		$this->data[] = array(
186
			'type' => self::CACHEDATA_TYPE_RECURSION,
187
			'data' => $k
188
		);
189
		return $this;
190
	}
191
192
	public function appendRecursionData(CacheData $d) {
193
		if (!$d->getKey()) {
194
			throw new Exceptions\CacheInvalidDataException();
195
		}
196
		$this->addDependency($d->getKey());
197
		$this->data[] = array(
198
			'type' => self::CACHEDATA_TYPE_RECURSION_DATA,
199
			'data' => $d->getKey()
200
		);
201
		return $this;
202
	}
203
204
	/**
205
	 * Adds a dependency
206
	 * @param CacheKey $k
207
	 * @return CacheData This
208
	 */
209
	public function addDependency(CacheKey $k) {
210
		$this->dependencies[] = $k;
211
		$this->clearDependenciesHash();
212
		return $this;
213
	}
214
215
	/**
216
	 * Adds a dependency
217
	 * @param array<CacheKey> $k
218
	 * @return CacheData This
219
	 */
220
	public function addDependencies(array $deps) {
221
		foreach ($deps as $k) {
222
			$this->addDependency($k);
223
		}
224
		return $this;
225
	}
226
227
	/**
228
	 * Sets the list of dependencies and updates the dependency hash
229
	 *
230
	 * @param array<CacheKey> $deps
231
	 * @param CacheAbstract $cache
232
	 * @return CacheData
233
	 */
234
	public function setDependencies(array $deps, CacheAbstract $cache) {
235
		$this->dependencies = [];
236
		foreach ($deps as $k) {
237
			$this->addDependency($k);
238
		}
239
		$this->generateDependenciesHash($cache);
240
		return $this;
241
	}
242
243
	/**
244
	 *
245
	 * @param integer $lifetime
246
	 * @return CacheData
247
	 */
248
	public function setLifetime($lifetime) {
249
		$this->lifetime = $lifetime;
250
		return $this;
251
	}
252
253
	/**
254
	 * Checks if a set of keys clashes with the ones used here.
255
	 * @param CacheKey $k
256
	 * @return boolean True if they match and there is a clash
257
	 */
258
	public function checkClash(CacheKey $k) {
259
		return ($this->key == $k);
260
	}
261
262
	/**
263
	 * Converts this data to a string that can output. This is not a hash
264
	 * key or a serialization, but an actual render for humans.
265
	 *
266
	 * @throws Exceptions\NotCachedException
267
	 */
268
	public function stringify(CacheAbstract $c, $recurse = true) {
269
		$retval = [];
270
		foreach ($this->data as $item) {
271
			if ($item['type'] == self::CACHEDATA_TYPE_CALLBACK) {
272
				$callback = $item['data'];
273
				if (is_callable($callback)) {
274
					$retval[] = call_user_func($callback);
275
				}
276
				else {
277
					// throw?
278
				}
279
			}
280
			else if ($item['type'] == self::CACHEDATA_TYPE_RECURSION) {
281
				if ($recurse) {
282
					$retval[] = $c->get($item['data']);
283
				}
284
			}
285
			else if ($item['type'] == self::CACHEDATA_TYPE_RECURSION_DATA) {
286
				if ($recurse) {
287
					$data = $c->getData($item['data']);
288
					$retval[] = $data->stringify($c);
289
				}
290
			}
291
			else {
292
				$retval[] = $item['data'];
293
			}
294
		}
295
296
		return implode('', $retval);
297
	}
298
299
	/**
300
	 * Serialize this object to a string so we can easily store.
301
	 *
302
	 * @return string
303
	 */
304
	public function serialize() {
305
		return serialize($this);
306
	}
307
308
	/**
309
	 * Unserializes data and returns a new CacheData. This is what you
310
	 * should use to get the object data from the storage.
311
	 *
312
	 * @param string $data
313
	 * @return CacheData
314
	 */
315
	static public function unserialize($data) {
316
		return unserialize($data);
317
	}
318
}
319