1: <?php
2: /**
3: * The cache decorator for Kolab storage data 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: * The cache decorator for Kolab storage data handlers.
16: *
17: * Copyright 2011-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_Data_Cached
29: extends Horde_Kolab_Storage_Data_Base
30: {
31: /**
32: * The data cache.
33: *
34: * @var Horde_Kolab_Storage_Cache_Data
35: */
36: private $_data_cache;
37:
38: /**
39: * Has the cache already been loaded and validated?
40: *
41: * @var boolean
42: */
43: private $_init = false;
44:
45: /**
46: * Constructor.
47: *
48: * @param Horde_Kolab_Storage_Folder $folder The folder to retrieve the
49: * data from.
50: * @param Horde_Kolab_Storage_Driver $driver The primary connection driver.
51: * @param Horde_Kolab_Storage_Factory $factory The factory.
52: * @param Horde_Kolab_Storage_Cache $cache The cache storing data for
53: * this decorator.
54: * @param string $type The type of data we want to
55: * access in the folder.
56: * @param int $version Format version of the object
57: * data.
58: */
59: public function __construct(Horde_Kolab_Storage_Folder $folder,
60: Horde_Kolab_Storage_Driver $driver,
61: Horde_Kolab_Storage_Factory $factory,
62: Horde_Kolab_Storage_Cache $cache,
63: $type = null,
64: $version = 1)
65: {
66: parent::__construct($folder, $driver, $factory, $type, $version);
67: $this->_data_cache = $cache->getDataCache($this->getIdParameters());
68: }
69:
70: /**
71: * Check if the cache has been initialized.
72: *
73: * @return NULL
74: */
75: private function _isInitialized()
76: {
77: return ($this->_init || $this->_data_cache->isInitialized());
78: }
79:
80: /**
81: * Check if the cache has been initialized at all and synchronize it if not.
82: *
83: * @return NULL
84: */
85: private function _init()
86: {
87: if (!$this->_isInitialized()) {
88: $this->synchronize();
89: }
90: }
91:
92: /**
93: * Return the backend ID for the given object ID.
94: *
95: * @param string $object_uid The object ID.
96: *
97: * @return string The backend ID for the object.
98: */
99: public function getBackendId($object_id)
100: {
101: $this->_init();
102: $mapping = $this->_data_cache->getObjectToBackend();
103: if (isset($mapping[$object_id])) {
104: return $mapping[$object_id];
105: } else {
106: throw new Horde_Kolab_Storage_Exception(
107: sprintf('Object ID %s does not exist!', $object_id)
108: );
109: }
110: }
111:
112: /**
113: * Check if the given object ID exists.
114: *
115: * @param string $object_id The object ID.
116: *
117: * @return boolean True if the ID was found, false otherwise.
118: */
119: public function objectIdExists($object_id)
120: {
121: $this->_init();
122: return array_key_exists(
123: $object_id, $this->_data_cache->getObjects()
124: );
125: }
126:
127: /**
128: * Return the specified object.
129: *
130: * @param string $object_id The object id.
131: *
132: * @return array The object data as an array.
133: */
134: public function getObject($object_id)
135: {
136: $this->_init();
137: $objects = $this->_data_cache->getObjects();
138: if (isset($objects[$object_id])) {
139: return $objects[$object_id];
140: } else {
141: throw new Horde_Kolab_Storage_Exception(
142: sprintf('Object ID %s does not exist!', $object_id)
143: );
144: }
145: }
146:
147: /**
148: * Return the specified attachment.
149: *
150: * @param string $attachment_id The attachment id.
151: *
152: * @return resource An open stream to the attachment data.
153: */
154: public function getAttachment($attachment_id)
155: {
156: //@todo
157: }
158:
159: /**
160: * Retrieve all object ids in the current folder.
161: *
162: * @return array The object ids.
163: */
164: public function getObjectIds()
165: {
166: $this->_init();
167: return array_keys($this->_data_cache->getObjects());
168: }
169:
170: /**
171: * Retrieve all objects in the current folder.
172: *
173: * @return array An array of all objects.
174: */
175: public function getObjects()
176: {
177: $this->_init();
178: return $this->_data_cache->getObjects();
179: }
180:
181: /**
182: * Return the mapping of object IDs to backend IDs.
183: *
184: * @since Horde_Kolab_Storage 1.1.0
185: *
186: * @return array The object to backend mapping.
187: */
188: public function getObjectToBackend()
189: {
190: $this->_init();
191: return $this->_data_cache->getObjectToBackend();
192: }
193:
194: /**
195: * Retrieve the list of object duplicates.
196: *
197: * @since Horde_Kolab_Storage 1.1.0
198: *
199: * @return array The list of duplicates.
200: */
201: public function getDuplicates()
202: {
203: $this->_init();
204: return $this->_data_cache->getDuplicates();
205: }
206:
207: /**
208: * Retrieve the list of object errors.
209: *
210: * @since Horde_Kolab_Storage 1.1.0
211: *
212: * @return array The list of errors.
213: */
214: public function getErrors()
215: {
216: $this->_init();
217: return $this->_data_cache->getErrors();
218: }
219:
220: /**
221: * Synchronize the query data with the information from the backend.
222: *
223: * @param array $params Additional parameters.
224: *
225: * @return NULL
226: */
227: public function synchronize($params = array())
228: {
229: $current = $this->getStamp();
230: if (!$this->_data_cache->isInitialized()) {
231: $this->_completeSynchronization($current);
232: return;
233: }
234: $previous = unserialize($this->_data_cache->getStamp());
235: if ($previous === false || $previous->isReset($current)) {
236: $this->_completeSynchronization($current);
237: return;
238: }
239: if (!isset($params['changes'])) {
240: $changes = $previous->getChanges($current);
241: $params['changes'][Horde_Kolab_Storage_Folder_Stamp::ADDED] = $this->fetch(
242: $changes[Horde_Kolab_Storage_Folder_Stamp::ADDED]
243: );
244: $params['changes'][Horde_Kolab_Storage_Folder_Stamp::DELETED] = $this->_data_cache->backendMap(
245: $changes[Horde_Kolab_Storage_Folder_Stamp::DELETED]
246: );
247: }
248: if ($params['changes'] !== false) {
249: $params['last_sync'] = $this->_data_cache->getLastSync();
250: $this->_data_cache->store(
251: $params['changes'][Horde_Kolab_Storage_Folder_Stamp::ADDED],
252: $current,
253: $this->getVersion(),
254: $params['changes'][Horde_Kolab_Storage_Folder_Stamp::DELETED]
255: );
256: $params['current_sync'] = $this->_data_cache->getLastSync();
257: parent::synchronize($params);
258: $this->_data_cache->save();
259: }
260: $this->_init = true;
261: }
262:
263: /**
264: * Perform a complete synchronization.
265: *
266: * @param Horde_Kolab_Storage_Folder_Stamp $stamp The current stamp.
267: * @param array $params Additional parameters.
268: *
269: * @return NULL
270: */
271: private function _completeSynchronization(Horde_Kolab_Storage_Folder_Stamp $stamp,
272: $params = array())
273: {
274: $this->_data_cache->reset();
275: $ids = $stamp->ids();
276: $params['last_sync'] = false;
277: $params['changes'][Horde_Kolab_Storage_Folder_Stamp::ADDED] = empty($ids) ? array() : $this->fetch($ids);
278: $this->_data_cache->store(
279: $params['changes'][Horde_Kolab_Storage_Folder_Stamp::ADDED],
280: $stamp,
281: $this->getVersion()
282: );
283: $params['current_sync'] = $this->_data_cache->getLastSync();
284: parent::synchronize($params);
285: $this->_data_cache->save();
286: }
287: }
288: