Overview

Packages

  • Kolab
    • Storage

Classes

  • Horde_Kolab_Storage_Base
  • Horde_Kolab_Storage_Cache
  • Horde_Kolab_Storage_Cache_Data
  • Horde_Kolab_Storage_Cache_List
  • Horde_Kolab_Storage_Cached
  • Horde_Kolab_Storage_Data_Base
  • Horde_Kolab_Storage_Data_Cached
  • Horde_Kolab_Storage_Data_Decorator_Log
  • Horde_Kolab_Storage_Data_Format_Mime
  • Horde_Kolab_Storage_Data_Modifiable
  • Horde_Kolab_Storage_Data_Old
  • Horde_Kolab_Storage_Data_Parser_Structure
  • Horde_Kolab_Storage_Data_Query_History_Base
  • Horde_Kolab_Storage_Data_Query_History_Cache
  • Horde_Kolab_Storage_Data_Query_Preferences_Base
  • Horde_Kolab_Storage_Data_Query_Preferences_Cache
  • Horde_Kolab_Storage_Decorator_Synchronization
  • Horde_Kolab_Storage_Driver_Base
  • Horde_Kolab_Storage_Driver_Cclient
  • Horde_Kolab_Storage_Driver_Decorator_Base
  • Horde_Kolab_Storage_Driver_Decorator_Log
  • Horde_Kolab_Storage_Driver_Decorator_Timer
  • Horde_Kolab_Storage_Driver_Imap
  • Horde_Kolab_Storage_Driver_Mock
  • Horde_Kolab_Storage_Driver_Mock_Data
  • Horde_Kolab_Storage_Driver_Pear
  • Horde_Kolab_Storage_Driver_Rcube
  • Horde_Kolab_Storage_Exception
  • Horde_Kolab_Storage_Exception_Pear
  • Horde_Kolab_Storage_Factory
  • Horde_Kolab_Storage_Folder_Base
  • Horde_Kolab_Storage_Folder_Decorator_Base
  • Horde_Kolab_Storage_Folder_Decorator_Trigger
  • Horde_Kolab_Storage_Folder_Namespace
  • Horde_Kolab_Storage_Folder_Namespace_Config
  • Horde_Kolab_Storage_Folder_Namespace_Element
  • Horde_Kolab_Storage_Folder_Namespace_Element_Other
  • Horde_Kolab_Storage_Folder_Namespace_Element_Personal
  • Horde_Kolab_Storage_Folder_Namespace_Element_Shared
  • Horde_Kolab_Storage_Folder_Namespace_Element_SharedWithPrefix
  • Horde_Kolab_Storage_Folder_Namespace_Fixed
  • Horde_Kolab_Storage_Folder_Namespace_Imap
  • Horde_Kolab_Storage_Folder_Stamp_Uids
  • Horde_Kolab_Storage_Folder_Type
  • Horde_Kolab_Storage_List_Base
  • Horde_Kolab_Storage_List_Decorator_Cache
  • Horde_Kolab_Storage_List_Decorator_Log
  • Horde_Kolab_Storage_List_Query_Acl_Base
  • Horde_Kolab_Storage_List_Query_Acl_Cache
  • Horde_Kolab_Storage_List_Query_ActiveSync_Base
  • Horde_Kolab_Storage_List_Query_ActiveSync_Cache
  • Horde_Kolab_Storage_List_Query_List_Base
  • Horde_Kolab_Storage_List_Query_List_Cache
  • Horde_Kolab_Storage_List_Query_Share_Base
  • Horde_Kolab_Storage_List_Query_Share_Cache
  • Horde_Kolab_Storage_QuerySet_Base
  • Horde_Kolab_Storage_QuerySet_Cached
  • Horde_Kolab_Storage_QuerySet_Uncached
  • Horde_Kolab_Storage_Synchronization
  • Horde_Kolab_Storage_Translation
  • Horde_Kolab_Storage_Uncached

Interfaces

  • Horde_Kolab_Storage
  • Horde_Kolab_Storage_Data
  • Horde_Kolab_Storage_Data_Format
  • Horde_Kolab_Storage_Data_Parser
  • Horde_Kolab_Storage_Data_Query
  • Horde_Kolab_Storage_Data_Query_History
  • Horde_Kolab_Storage_Data_Query_Preferences
  • Horde_Kolab_Storage_Driver
  • Horde_Kolab_Storage_Folder
  • Horde_Kolab_Storage_Folder_Stamp
  • Horde_Kolab_Storage_List
  • Horde_Kolab_Storage_List_Query
  • Horde_Kolab_Storage_List_Query_Acl
  • Horde_Kolab_Storage_List_Query_ActiveSync
  • Horde_Kolab_Storage_List_Query_List
  • Horde_Kolab_Storage_List_Query_Share
  • Horde_Kolab_Storage_Queriable
  • Horde_Kolab_Storage_Query
  • Horde_Kolab_Storage_QuerySet
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * The basic handler for data objects in a Kolab storage folder.
  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 basic handler for data objects in a Kolab storage folder.
 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_Base
 29: implements Horde_Kolab_Storage_Data, Horde_Kolab_Storage_Data_Query
 30: {
 31:     /**
 32:      * The link to the parent folder object.
 33:      *
 34:      * @var Horde_Kolab_Folder
 35:      */
 36:     private $_folder;
 37: 
 38:     /**
 39:      * The driver for accessing the Kolab storage system.
 40:      *
 41:      * @var Horde_Kolab_Storage_Driver
 42:      */
 43:     private $_driver;
 44: 
 45:     /**
 46:      * The factory for generating additional resources.
 47:      *
 48:      * @var Horde_Kolab_Storage_Factory
 49:      */
 50:     private $_factory;
 51: 
 52:     /**
 53:      * The folder type.
 54:      *
 55:      * @var string
 56:      */
 57:     private $_type;
 58: 
 59:     /**
 60:      * The version of the data.
 61:      *
 62:      * @var int
 63:      */
 64:     private $_version;
 65: 
 66:     /**
 67:      * The list of registered queries.
 68:      *
 69:      * @var array
 70:      */
 71:     private $_queries = array();
 72: 
 73:     /**
 74:      * Constructor.
 75:      *
 76:      * @param Horde_Kolab_Storage_Folder  $folder  The folder to retrieve the
 77:      *                                             data from.
 78:      * @param Horde_Kolab_Storage_Driver  $driver  The primary connection driver.
 79:      * @param Horde_Kolab_Storage_Factory $factory The factory.
 80:      * @param string                      $type     The type of data we want to
 81:      *                                              access in the folder.
 82:      * @param int                         $version Format version of the object
 83:      *                                             data.
 84:      */
 85:     public function __construct(Horde_Kolab_Storage_Folder $folder,
 86:                                 Horde_Kolab_Storage_Driver $driver,
 87:                                 Horde_Kolab_Storage_Factory $factory,
 88:                                 $type = null,
 89:                                 $version = 1)
 90:     {
 91:         $this->_folder  = $folder;
 92:         $this->_driver  = $driver;
 93:         $this->_factory = $factory;
 94:         $this->_type    = $type;
 95:         $this->_version = $version;
 96:     }
 97: 
 98:     /**
 99:      * Return the folder path for this data handler.
100:      *
101:      * @since Horde_Kolab_Storage 1.1.0
102:      *
103:      * @return string The folder path.
104:      */
105:     public function getPath()
106:     {
107:         return $this->_folder->getPath();
108:     }
109: 
110:     /**
111:      * Return the ID of the current user.
112:      *
113:      * @since Horde_Kolab_Storage 1.1.0
114:      *
115:      * @return string The current user.
116:      */
117:     public function getAuth()
118:     {
119:         return $this->_driver->getAuth();
120:     }
121: 
122:     /**
123:      * Return the ID of this data handler.
124:      *
125:      * @return string The ID.
126:      */
127:     public function getId()
128:     {
129:         $id = $this->_driver->getParameters();
130:         unset($id['user']);
131:         $id['owner'] = $this->_folder->getOwner();
132:         $id['prefix'] = $this->_folder->getPrefix();
133:         $id['folder'] = $this->_folder->getSubpath();
134:         $id['type'] = $this->getType();
135:         ksort($id);
136:         return md5(serialize($id));
137:     }
138: 
139:     /**
140:      * Return the ID parameters for this data handler.
141:      *
142:      * @return array The ID parameters.
143:      */
144:     public function getIdParameters()
145:     {
146:         $id = $this->_driver->getParameters();
147:         unset($id['user']);
148:         $id['owner'] = $this->_folder->getOwner();
149:         $id['prefix'] = $this->_folder->getPrefix();
150:         $id['folder'] = $this->_folder->getSubpath();
151:         $id['type'] = $this->getType();
152:         return $id;
153:     }
154: 
155:     /**
156:      * Return the data type represented by this object.
157:      *
158:      * @return string The type of data this instance handles.
159:      */
160:     public function getType()
161:     {
162:         if ($this->_type === null) {
163:             $this->_type = $this->_folder->getType();
164:         }
165:         return $this->_type;
166:     }
167: 
168:     /**
169:      * Return the data version.
170:      *
171:      * @return string The data version.
172:      */
173:     public function getVersion()
174:     {
175:         return $this->_version;
176:     }
177: 
178:     /**
179:      * Report the status of this folder.
180:      *
181:      * @return Horde_Kolab_Storage_Folder_Stamp The stamp that can be used for
182:      *                                          detecting folder changes.
183:      */
184:     public function getStamp()
185:     {
186:         return $this->_driver->getStamp($this->_folder->getPath());
187:     }
188: 
189:     /**
190:      * Create a new object.
191:      *
192:      * @param array   &$object The array that holds the object data.
193:      * @param boolean $raw     True if the data to be stored has been provided in
194:      *                         raw format.
195:      *
196:      * @return string The ID of the new object or true in case the backend does
197:      *                not support this return value.
198:      *
199:      * @throws Horde_Kolab_Storage_Exception In case an error occured while
200:      *                                       saving the data.
201:      */
202:     public function create(&$object, $raw = false)
203:     {
204:         if (!isset($object['uid'])) {
205:             $object['uid'] = $this->generateUid();
206:         }
207:         $result = $this->_driver->getParser()
208:             ->create(
209:                 $this->_folder->getPath(),
210:                 $object,
211:                 array(
212:                     'type' => $this->getType(),
213:                     'version' => $this->_version,
214:                     'raw' => $raw
215:                 )
216:             );
217:         if ($result === true) {
218:             $params = array();
219:         } else {
220:             $params = array(
221:                 'changes' => array(
222:                     Horde_Kolab_Storage_Folder_Stamp::ADDED => array(
223:                         $result => $object
224:                     ),
225:                     Horde_Kolab_Storage_Folder_Stamp::DELETED => array()
226:                 )
227:             );
228:         }
229:         $this->synchronize($params);
230:         return $result;
231:     }
232: 
233:     /**
234:      * Modify an existing object.
235:      *
236:      * @param array   $object The array that holds the updated object data.
237:      * @param boolean $raw    True if the data to be stored has been provided in
238:      *                        raw format.
239:      *
240:      * @return string The new backend ID of the modified object or true in case
241:      *                the backend does not support this return value.
242:      *
243:      * @throws Horde_Kolab_Storage_Exception In case an error occured while
244:      *                                       saving the data.
245:      */
246:     public function modify($object, $raw = false)
247:     {
248:         if (!isset($object['uid'])) {
249:             throw new Horde_Kolab_Storage_Exception(
250:                 'The provided object data contains no ID value!'
251:             );
252:         }
253:         try {
254:             $obid = $this->getBackendId($object['uid']);
255:         } catch (Horde_Kolab_Storage_Exception $e) {
256:             throw new Horde_Kolab_Storage_Exception(
257:                 sprintf(
258:                     Horde_Kolab_Storage_Translation::t(
259:                         'The message with ID %s does not exist. This probably means that the Kolab object has been modified by somebody else since you retrieved the object from the backend. Original error: %s'
260:                     ),
261:                     $object['uid'],
262:                     0,
263:                     $e
264:                 )
265:             );
266:         }
267:         $result = $this->_driver->getParser()
268:             ->modify(
269:                 $this->_folder->getPath(),
270:                 $object,
271:                 $obid,
272:                 array(
273:                     'type' => $this->getType(),
274:                     'version' => $this->_version,
275:                     'raw' => $raw
276:                 )
277:             );
278:         if ($result === true) {
279:             $params = array();
280:         } else {
281:             $params = array(
282:                 'changes' => array(
283:                     Horde_Kolab_Storage_Folder_Stamp::ADDED => array(
284:                         $result => $object
285:                     ),
286:                     Horde_Kolab_Storage_Folder_Stamp::DELETED => array()
287:                 )
288:             );
289:         }
290:         $this->synchronize($params);
291:         return $result;
292:     }
293: 
294:     /**
295:      * Retrieves the complete message for the given UID.
296:      *
297:      * @param string $uid The message UID.
298:      *
299:      * @return array The message encapsuled as an array that contains a
300:      *               Horde_Mime_Headers and a Horde_Mime_Part object.
301:      */
302:     public function fetchComplete($uid)
303:     {
304:         return $this->_driver->fetchComplete($this->_folder->getPath(), $uid);
305:     }
306: 
307:     /**
308:      * Retrieves the body part for the given UID and mime part ID.
309:      *
310:      * @param string $uid The message UID.
311:      * @param string $id  The mime part ID.
312:      *
313:      * @return resource The message part as stream resource.
314:      */
315:     public function fetchPart($uid, $id)
316:     {
317:         return $this->_driver->fetchBodypart(
318:             $this->_folder->getPath(), $uid, $id
319:         );
320:     }
321: 
322:     /**
323:      * Retrieves the objects for the given UIDs.
324:      *
325:      * @param array   $uids The message UIDs.
326:      * @param boolean $raw  True if the raw format should be returned rather than
327:      *                      the parsed data.
328:      *
329:      * @return array An array of objects.
330:      */
331:     public function fetch($uids, $raw = false)
332:     {
333:         if (!empty($uids)) {
334:             return $this->_driver->fetch(
335:                 $this->_folder->getPath(),
336:                 $uids,
337:                 array(
338:                     'type' => $this->getType(),
339:                     'version' => $this->_version,
340:                     'raw' => $raw
341:                 )
342:             );
343:         } else {
344:             return array();
345:         }
346:     }
347: 
348:     /**
349:      * Return the backend ID for the given object ID.
350:      *
351:      * @param string $object_uid The object ID.
352:      *
353:      * @return string The backend ID for the object.
354:      */
355:     public function getBackendId($object_id)
356:     {
357:         $by_obid = $this->fetch($this->getStamp()->ids());
358:         foreach ($by_obid as $obid => $object) {
359:             if ($object['uid'] == $object_id) {
360:                 return $obid;
361:             }
362:         }
363:         throw new Horde_Kolab_Storage_Exception(
364:             sprintf('Object ID %s does not exist!', $object_id)
365:         );
366:     }
367: 
368:     /**
369:      * Generate a unique object ID.
370:      *
371:      * @return string  The unique ID.
372:      */
373:     public function generateUid()
374:     {
375:         return strval(new Horde_Support_Uuid());
376:     }
377: 
378:     /**
379:      * Check if the given object ID exists.
380:      *
381:      * @param string $object_id The object ID.
382:      *
383:      * @return boolean True if the ID was found, false otherwise.
384:      */
385:     public function objectIdExists($object_id)
386:     {
387:         return array_key_exists(
388:             $object_id, $this->getObjects()
389:         );
390:     }
391: 
392:     /**
393:      * Return the specified object.
394:      *
395:      * @param string $object_id The object id.
396:      *
397:      * @return array The object data as an array.
398:      */
399:     public function getObject($object_id)
400:     {
401:         $objects = $this->getObjects();
402:         if (isset($objects[$object_id])) {
403:             return $objects[$object_id];
404:         } else {
405:             throw new Horde_Kolab_Storage_Exception(
406:                 sprintf('Object ID %s does not exist!', $object_id)
407:             );
408:         }
409:     }
410: 
411:     /**
412:      * Return the specified attachment.
413:      *
414:      * @param string $attachment_id The attachment id.
415:      *
416:      * @return resource An open stream to the attachment data.
417:      */
418:     public function getAttachment($attachment_id)
419:     {
420:         //@todo: implement
421:     }
422: 
423:     /**
424:      * Retrieve all object ids in the current folder.
425:      *
426:      * @return array The object ids.
427:      */
428:     public function getObjectIds()
429:     {
430:         return array_keys($this->getObjects());
431:     }
432: 
433:     /**
434:      * Retrieve all objects in the current folder.
435:      *
436:      * @return array An array of all objects.
437:      */
438:     public function getObjects()
439:     {
440:         $by_oid  = array();
441:         $by_obid = $this->fetch($this->getStamp()->ids());
442:         foreach ($by_obid as $obid => $object) {
443:             $by_oid[$object['uid']] = $object;
444:         }
445:         return $by_oid;
446:     }
447: 
448:     /**
449:      * Retrieve all objects in the current folder by backend id.
450:      *
451:      * @since Horde_Kolab_Storage 1.1.0
452:      *
453:      * @return array An array of all objects.
454:      */
455:     public function getObjectsByBackendId()
456:     {
457:         return $this->fetch($this->getStamp()->ids());
458:     }
459: 
460:     /**
461:      * Retrieve an object in the current folder by backend id.
462:      *
463:      * @since Horde_Kolab_Storage 1.1.0
464:      *
465:      * @param string $uid Backend id of the object to be returned.
466:      *
467:      * @return array An array of all objects.
468:      */
469:     public function getObjectByBackendId($uid)
470:     {
471:         $fetched = $this->fetch(array($uid));
472:         return array_pop($fetched);
473:     }
474: 
475:     /**
476:      * Return the mapping of object IDs to backend IDs.
477:      *
478:      * @since Horde_Kolab_Storage 1.1.0
479:      *
480:      * @return array The object to backend mapping.
481:      */
482:     public function getObjectToBackend()
483:     {
484:         $bid  = array();
485:         $by_obid = $this->fetch($this->getStamp()->ids());
486:         foreach ($by_obid as $obid => $object) {
487:             $bid[$object['uid']] = $obid;
488:         }
489:         return $bid;
490:     }
491: 
492:     /**
493:      * Retrieve the list of object duplicates.
494:      *
495:      * @since Horde_Kolab_Storage 1.1.0
496:      *
497:      * @return array The list of duplicates.
498:      */
499:     public function getDuplicates()
500:     {
501:         $existing = array();
502:         $duplicates = array();
503:         $by_obid = $this->fetch($this->getStamp()->ids());
504:         foreach ($by_obid as $obid => $object) {
505:             if (isset($existing[$object['uid']])) {
506:                 if (!isset($duplicates[$object['uid']])) {
507:                     $duplicates[$object['uid']][] = $existing[$object['uid']];
508:                 }
509:                 $duplicates[$object['uid']][] = $obid;
510:             } else {
511:                 $existing[$object['uid']] = $obid;
512:             }
513:         }
514:         return $duplicates;
515:     }
516: 
517:     /**
518:      * Retrieve the list of object errors.
519:      *
520:      * @since Horde_Kolab_Storage 1.1.0
521:      *
522:      * @return array The list of errors.
523:      */
524:     public function getErrors()
525:     {
526:         $errors = array();
527:         $by_obid = $this->fetch($this->getStamp()->ids());
528:         foreach ($by_obid as $obid => $object) {
529:             if ($object === false) {
530:                 $errors[] = $obid;
531:             }
532:         }
533:         return $errors;
534:     }
535: 
536:     /**
537:      * Move the specified message from the current folder into a new
538:      * folder.
539:      *
540:      * @param string $object_id  ID of the message to be moved.
541:      * @param string $new_folder Target folder.
542:      *
543:      * @return NULL
544:      */
545:     public function move($object_id, $new_folder)
546:     {
547:         if ($this->objectIdExists($object_id)) {
548:             $uid = $this->getBackendId($object_id);
549:         } else {
550:             throw new Horde_Kolab_Storage_Exception(
551:                 sprintf('No such object %s!', $id)
552:             );
553:         }
554:         $this->_driver->moveMessage(
555:             $uid, $this->_folder->getPath(), $new_folder
556:         );
557:     }
558: 
559:     /**
560:      * Delete the specified objects from this data set.
561:      *
562:      * @param array|string $object_ids Id(s) of the object to be deleted.
563:      *
564:      * @return NULL
565:      */
566:     public function delete($object_ids)
567:     {
568:         if (!is_array($object_ids)) {
569:             $object_ids = array($object_ids);
570:         }
571: 
572:         $uids = array();
573:         foreach ($object_ids as $id) {
574:             if ($this->objectIdExists($id)) {
575:                 $uids[$this->getBackendId($id)] = $id;
576:             } else {
577:                 throw new Horde_Kolab_Storage_Exception(
578:                     sprintf('No such object %s!', $id)
579:                 );
580:             }
581:         }
582:         $this->deleteBackendIds(array_keys($uids));
583:         $this->synchronize(
584:             array(
585:                 'changes' => array(
586:                     Horde_Kolab_Storage_Folder_Stamp::ADDED => array(),
587:                     Horde_Kolab_Storage_Folder_Stamp::DELETED => $uids
588:                 )
589:             )
590:         );
591:     }
592: 
593:     /**
594:      * Delete all objects from this data set.
595:      *
596:      * @return NULL
597:      */
598:     public function deleteAll()
599:     {
600:         $this->delete($this->getObjectIds());
601:     }
602: 
603:     /**
604:      * Delete the specified messages from this folder.
605:      *
606:      * @since Horde_Kolab_Storage 1.1.0
607:      *
608:      * @param array|string $uids Backend id(s) of the message to be deleted.
609:      *
610:      * @return NULL
611:      */
612:     public function deleteBackendIds($uids)
613:     {
614:         if (!is_array($uids)) {
615:             $uids = array($uids);
616:         }
617:         $this->_driver->deleteMessages($this->_folder->getPath(), $uids);
618:         $this->_driver->expunge($this->_folder->getPath());
619:     }
620: 
621:     /**
622:      * Register a query to be updated if the underlying data changes.
623:      *
624:      * @param string                    $name  The query name.
625:      * @param Horde_Kolab_Storage_Query $query The query to register.
626:      *
627:      * @return NULL
628:      */
629:     public function registerQuery($name, Horde_Kolab_Storage_Query $query)
630:     {
631:         if (!$query instanceOf Horde_Kolab_Storage_Data_Query) {
632:             throw new Horde_Kolab_Storage_Exception(
633:                 'The provided query is no data query.'
634:             );
635:         }
636:         $this->_queries[$name] = $query;
637:     }
638: 
639:     /**
640:      * Synchronize the data information with the information from the backend.
641:      *
642:      * @param array $params Additional parameters.
643:      *
644:      * @return NULL
645:      */
646:     public function synchronize($params = array())
647:     {
648:         foreach ($this->_queries as $name => $query) {
649:             $query->synchronize($params);
650:         }
651:     }
652: 
653:     /**
654:      * Return a registered query.
655:      *
656:      * @param string $name The query name.
657:      *
658:      * @return Horde_Kolab_Storage_Query The requested query.
659:      *
660:      * @throws Horde_Kolab_Storage_Exception In case the requested query does
661:      *                                       not exist.
662:      */
663:     public function getQuery($name = null)
664:     {
665:         if (isset($this->_queries[$name])) {
666:             return $this->_queries[$name];
667:         } else {
668:             throw new Horde_Kolab_Storage_Exception('No such query!');
669:         }
670:     }
671: }
672: 
API documentation generated by ApiGen