1: <?php
2: /**
3: * A cache backend for Kolab storage list handlers.
4: *
5: * PHP version 5
6: *
7: * @category Kolab
8: * @package Kolab_Storage
9: * @author Gunnar Wrobel <wrobel@pardus.de>
10: * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
11: * @link http://pear.horde.org/index.php?package=Kolab_Storage
12: */
13:
14: /**
15: * A cache backend for Kolab storage list handlers.
16: *
17: * Copyright 2010-2012 Horde LLC (http://www.horde.org/)
18: *
19: * See the enclosed file COPYING for license information (LGPL). If you
20: * did not receive this file, see http://www.horde.org/licenses/lgpl21.
21: *
22: * @category Kolab
23: * @package Kolab_Storage
24: * @author Gunnar Wrobel <wrobel@pardus.de>
25: * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
26: * @link http://pear.horde.org/index.php?package=Kolab_Storage
27: */
28: class Horde_Kolab_Storage_Cache_List
29: {
30: /** Key for the folder list. */
31: const FOLDERS = 'F';
32:
33: /** Key for the type list. */
34: const TYPES = 'T';
35:
36: /** Key for the namespace data. */
37: const NAME_SPACE = 'N';
38:
39: /** Key for the backend capabilities. */
40: const SUPPORT = 'C';
41:
42: /** Holds query results. */
43: const QUERIES = 'Q';
44:
45: /** Holds long term cache data. */
46: const LONG_TERM = 'L';
47:
48: /** Key for the last time the list was synchronized. */
49: const SYNC = 'S';
50:
51: /** Key for the cache format version. */
52: const VERSION = 'V';
53:
54: /** Key for the connection ID associated with this list cache. */
55: const ID = 'I';
56:
57: /** Holds the version number of the cache format. */
58: const FORMAT_VERSION = '1';
59:
60: /**
61: * The core cache driver.
62: *
63: * @var Horde_Kolab_Storage_Cache
64: */
65: private $_cache;
66:
67: /**
68: * List parameters that will be recorded in the cache.
69: *
70: * @var array
71: */
72: private $_parameters;
73:
74: /**
75: * List ID.
76: *
77: * @var string
78: */
79: private $_list_id;
80:
81: /**
82: * The list data.
83: *
84: * @var array
85: */
86: private $_data = false;
87:
88: /**
89: * Constructor.
90: *
91: * @param Horde_Kolab_Storage_Cache $cache The core cache driver.
92:
93: * @param array $parameters Connection parameters that
94: * are only recorded and have
95: * no further impact.
96: */
97: public function __construct(Horde_Kolab_Storage_Cache $cache,
98: $parameters = null)
99: {
100: $this->_cache = $cache;
101: $this->_parameters = $parameters;
102: }
103:
104: /**
105: * The ID for the list cache.
106: *
107: * @param string $list_id The unique ID for the list used when caching it.
108: *
109: * @return NULL
110: */
111: public function setListId($list_id)
112: {
113: $this->_list_id = $list_id;
114: }
115:
116: /**
117: * Return the ID for the list cache.
118: *
119: * @return string The unique ID for the list used when caching it.
120: */
121: public function getListId()
122: {
123: if ($this->_list_id === null) {
124: throw new Horde_Kolab_Storage_Exception(
125: 'You must set the ID of the list cache!'
126: );
127: }
128: return $this->_list_id;
129: }
130:
131: /**
132: * Retrieve the cached list data.
133: *
134: * @return mixed The data of the object.
135: */
136: private function _load()
137: {
138: if ($this->_data === false) {
139: $this->_data = unserialize($this->_cache->loadList($this->getListId()));
140: if (!is_array($this->_data)
141: || !isset($this->_data[self::SYNC])
142: || !isset($this->_data[self::VERSION])
143: || $this->_data[self::VERSION] != self::FORMAT_VERSION) {
144: $this->_data = array();
145: }
146: }
147: }
148:
149: /**
150: * Cache the list data.
151: *
152: * @return NULL
153: */
154: public function save()
155: {
156: $this->_cache->storeList($this->getListId(), serialize($this->_data));
157: }
158:
159: /**
160: * Check if the cache has been initialized.
161: *
162: * @return boolean True if cache data is available.
163: */
164: public function isInitialized()
165: {
166: $this->_load();
167: return !empty($this->_data);
168: }
169:
170: /**
171: * Returns the last sync stamp.
172: *
173: * @return string The last sync stamp.
174: */
175: public function getStamp()
176: {
177: $this->_load();
178: if (isset($this->_data[self::SYNC])) {
179: return $this->_data[self::SYNC];
180: } else {
181: throw new Horde_Kolab_Storage_Exception(
182: sprintf('Missing cache data (Key: %s). Synchronize first!', self::SYNC)
183: );
184: }
185: }
186:
187: /**
188: * Returns the list of folders from the cache.
189: *
190: * @return array The list of folders, represented as a list of strings.
191: */
192: public function getFolders()
193: {
194: $this->_load();
195: if (isset($this->_data[self::FOLDERS])) {
196: return $this->_data[self::FOLDERS];
197: } else {
198: throw new Horde_Kolab_Storage_Exception(
199: sprintf('Missing cache data (Key: %s). Synchronize first!', self::FOLDERS)
200: );
201: }
202: }
203:
204: /**
205: * Returns if the folder type annotation is stored in the cache.
206: *
207: * @since Horde_Kolab_Storage 1.1.0
208: *
209: * @return boolean True if the type annotation is available.
210: */
211: public function hasFolderTypes()
212: {
213: $this->_load();
214: if (isset($this->_data[self::TYPES])) {
215: return true;
216: }
217: return false;
218: }
219:
220: /**
221: * Returns the folder type annotation from the cache.
222: *
223: * @return array The list folder types with the folder names as key and the
224: * folder type as values.
225: */
226: public function getFolderTypes()
227: {
228: if ($this->hasFolderTypes()) {
229: return $this->_data[self::TYPES];
230: } else {
231: throw new Horde_Kolab_Storage_Exception(
232: sprintf('Missing cache data (Key: %s). Synchronize first!', self::TYPES)
233: );
234: }
235: }
236:
237: /**
238: * Returns if the namespace information is available.
239: *
240: * @return boolean True if the information exists in the cache.
241: */
242: public function hasNamespace()
243: {
244: $this->_load();
245: return isset($this->_data[self::NAME_SPACE]);
246: }
247:
248: /**
249: * Return namespace information.
250: *
251: * @return mixed The namespace data.
252: */
253: public function getNamespace()
254: {
255: if ($this->hasNamespace()) {
256: return $this->_data[self::NAME_SPACE];
257: } else {
258: throw new Horde_Kolab_Storage_Exception(
259: 'Missing namespace data. Synchronize first!'
260: );
261: }
262: }
263:
264: /**
265: * Set namespace information.
266: *
267: * @param mixed $data The namespace data.
268: *
269: * @return NULL
270: */
271: public function setNamespace($data)
272: {
273: $this->_load();
274: $this->_data[self::NAME_SPACE] = $data;
275: }
276:
277: /**
278: * Has the capability support already been cached?
279: *
280: * @return boolean True if the value is already in the cache.
281: */
282: public function issetSupport($capability)
283: {
284: $this->_load();
285: return isset($this->_data[self::SUPPORT][$capability]);
286: }
287:
288: /**
289: * Has the list support for the requested capability?
290: *
291: * @param string $capability The name of the requested capability.
292: *
293: * @return boolean True if the backend supports the requested capability.
294: */
295: public function hasSupport($capability)
296: {
297: if ($this->issetSupport($capability)) {
298: return $this->_data[self::SUPPORT][$capability];
299: } else {
300: throw new Horde_Kolab_Storage_Exception(
301: 'Missing support data. Synchronize first!'
302: );
303: }
304: }
305:
306: /**
307: * Set if the list supports the given capability.
308: *
309: * @param string $capability The name of the requested capability.
310: * @param boolean $flag True if the capability is supported.
311: *
312: * @return NULL
313: */
314: public function setSupport($capability, $flag)
315: {
316: $this->_load();
317: $this->_data[self::SUPPORT][$capability] = $flag;
318: }
319:
320: /**
321: * Is the specified query data available in the cache?
322: *
323: * @param string $key The query key.
324: *
325: * @return boolean True in case cached data is available.
326: */
327: public function hasQuery($key)
328: {
329: $this->_load();
330: return isset($this->_data[self::QUERIES][$key]);
331: }
332:
333: /**
334: * Return query information.
335: *
336: * @param string $key The query key.
337: *
338: * @return mixed The query data.
339: */
340: public function getQuery($key)
341: {
342: if ($this->hasQuery($key)) {
343: return $this->_data[self::QUERIES][$key];
344: } else {
345: throw new Horde_Kolab_Storage_Exception(
346: sprintf('Missing query cache data (Key: %s). Synchronize first!', $key)
347: );
348: }
349: }
350:
351: /**
352: * Set query information.
353: *
354: * @param string $key The query key.
355: * @param mixed $data The query data.
356: *
357: * @return NULL
358: */
359: public function setQuery($key, $data)
360: {
361: $this->_load();
362: $this->_data[self::QUERIES][$key] = $data;
363: }
364:
365: /**
366: * Is the specified long term data available in the cache?
367: *
368: * @param string $key The long term key.
369: *
370: * @return boolean True in case cached data is available.
371: */
372: public function hasLongTerm($key)
373: {
374: $this->_load();
375: return isset($this->_data[self::LONG_TERM][$key]);
376: }
377:
378: /**
379: * Return long term information.
380: *
381: * @param string $key The long term key.
382: *
383: * @return mixed The long term data.
384: */
385: public function getLongTerm($key)
386: {
387: if ($this->hasLongTerm($key)) {
388: return $this->_data[self::LONG_TERM][$key];
389: } else {
390: throw new Horde_Kolab_Storage_Exception(
391: sprintf('Missing long term cache data (Key: %s). Synchronize first!', $key)
392: );
393: }
394: }
395:
396: /**
397: * Set long term information.
398: *
399: * @param string $key The long term key.
400: * @param mixed $data The long term data.
401: *
402: * @return NULL
403: */
404: public function setLongTerm($key, $data)
405: {
406: $this->_load();
407: $this->_data[self::LONG_TERM][$key] = $data;
408: }
409:
410: /**
411: * Store the folder list and folder type annotations in the cache.
412: *
413: * @return NULL
414: */
415: public function store(array $folders = null, array $types = null)
416: {
417: $this->_load();
418: $this->_data[self::QUERIES] = array();
419: $this->_data[self::FOLDERS] = $folders;
420: $this->_data[self::TYPES] = $types;
421: $this->_data[self::VERSION] = self::FORMAT_VERSION;
422: $this->_data[self::ID] = serialize($this->_parameters);
423: $this->_data[self::SYNC] = pack('Nn', time(), mt_rand());
424: }
425: }
426: