Overview

Packages

  • Horde
    • Data
  • None
  • Turba

Classes

  • Turba
  • Turba_Api
  • Turba_Driver
  • Turba_Driver_Facebook
  • Turba_Driver_Favourites
  • Turba_Driver_Group
  • Turba_Driver_Imsp
  • Turba_Driver_Kolab
  • Turba_Driver_Ldap
  • Turba_Driver_Prefs
  • Turba_Driver_Share
  • Turba_Driver_Sql
  • Turba_Driver_Vbook
  • Turba_Exception
  • Turba_Factory_Driver
  • Turba_Form_AddContact
  • Turba_Form_Contact
  • Turba_Form_ContactBase
  • Turba_Form_CreateAddressBook
  • Turba_Form_DeleteAddressBook
  • Turba_Form_EditAddressBook
  • Turba_Form_EditContact
  • Turba_Form_EditContactGroup
  • Turba_List
  • Turba_LoginTasks_SystemTask_Upgrade
  • Turba_Object
  • Turba_Object_Group
  • Turba_Test
  • Turba_View_Browse
  • Turba_View_Contact
  • Turba_View_DeleteContact
  • Turba_View_Duplicates
  • Turba_View_EditContact
  • Turba_View_List
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * The Turba_Object:: class provides a base implementation for Turba
  4:  * objects - people, groups, restaurants, etc.
  5:  *
  6:  * @author  Chuck Hagenbuch <chuck@horde.org>
  7:  * @author  Jon Parise <jon@csh.rit.edu>
  8:  * @package Turba
  9:  */
 10: class Turba_Object
 11: {
 12:     /**
 13:      * Underlying driver.
 14:      *
 15:      * @var Turba_Driver
 16:      */
 17:     public $driver;
 18: 
 19:     /**
 20:      * Hash of attributes for this contact.
 21:      *
 22:      * @var array
 23:      */
 24:     public $attributes;
 25: 
 26:     /**
 27:      * Reference to this object's VFS instance.
 28:      *
 29:      * @var VFS
 30:      */
 31:     protected $_vfs;
 32: 
 33:     /**
 34:      * Keeps the normalized values of sort columns.
 35:      *
 36:      * @var array
 37:      */
 38:     public $sortValue = array();
 39: 
 40:     /**
 41:      * Constructs a new Turba_Object object.
 42:      *
 43:      * @param Turba_Driver $driver  The source that this object came from.
 44:      * @param array $attributes     Hash of attributes for this object.
 45:      */
 46:     public function __construct(Turba_Driver $driver, array $attributes = array())
 47:     {
 48:         $this->driver = $driver;
 49:         $this->attributes = $attributes;
 50:         $this->attributes['__type'] = 'Object';
 51:     }
 52: 
 53:     /**
 54:      * Returns a key-value hash containing all properties of this object.
 55:      *
 56:      * @return array  All properties of this object.
 57:      */
 58:     public function getAttributes()
 59:     {
 60:         return $this->attributes;
 61:     }
 62: 
 63:     /**
 64:      * Returns the name of the address book that this object is from.
 65:      */
 66:     public function getSource()
 67:     {
 68:         return $this->driver->getName();
 69:     }
 70: 
 71:     /**
 72:      * Get a fully qualified key for this contact.
 73:      *
 74:      * @param string $delimiter Delimiter for the parts of the key, defaults to ':'.
 75:      *
 76:      * @return string Fully qualified contact id.
 77:      */
 78:     public function getGuid($delimiter = ':')
 79:     {
 80:         return 'turba' . $delimiter . $this->getSource() . $delimiter . $this->getValue('__uid');
 81:     }
 82: 
 83:     /**
 84:      * Returns the value of the specified attribute.
 85:      *
 86:      * @param string $attribute  The attribute to retrieve.
 87:      *
 88:      * @return mixed  The value of $attribute, an array (for photo type)
 89:      *                or the empty string.
 90:      */
 91:     public function getValue($attribute)
 92:     {
 93:         if (isset($this->attributes[$attribute]) &&
 94:             Horde::hookExists('decode_attribute', 'turba')) {
 95:             try {
 96:                 return Horde::callHook('decode_attribute', array($attribute, $this->attributes[$attribute], $this), 'turba');
 97:             } catch (Turba_Exception $e) {}
 98:         }
 99:         if (isset($this->driver->map[$attribute]) &&
100:             is_array($this->driver->map[$attribute])) {
101:             $args = array();
102:             foreach ($this->driver->map[$attribute]['fields'] as $field) {
103:                 $args[] = $this->getValue($field);
104:             }
105:             return Turba::formatCompositeField($this->driver->map[$attribute]['format'], $args);
106:         } elseif (!isset($this->attributes[$attribute])) {
107:             return null;
108:         } elseif (isset($GLOBALS['attributes'][$attribute]) &&
109:                   ($GLOBALS['attributes'][$attribute]['type'] == 'image')) {
110:             return empty($this->attributes[$attribute])
111:                 ? null
112:                 : array(
113:                       'load' => array(
114:                           'data' => $this->attributes[$attribute],
115:                           'file' => basename(Horde::getTempFile('horde_form_', false, '', false, true))
116:                       )
117:                   );
118:         }
119: 
120:         return $this->attributes[$attribute];
121:     }
122: 
123:     /**
124:      * Sets the value of the specified attribute.
125:      *
126:      * @param string $attribute  The attribute to set.
127:      * @param string $value      The value of $attribute.
128:      */
129:     public function setValue($attribute, $value)
130:     {
131:         if (Horde::hookExists('encode_attribute', 'turba')) {
132:             try {
133:                 $value = Horde::callHook('encode_attribute', array($attribute, $value, isset($this->attributes[$attribute]) ? $this->attributes[$attribute] : null, $this), 'turba');
134:             } catch (Turba_Exception $e) {}
135:         }
136:         if (isset($this->driver->map[$attribute]) &&
137:             is_array($this->driver->map[$attribute]) &&
138:             !isset($this->driver->map[$attribute]['attribute'])) {
139:             return;
140:         }
141: 
142:         $this->attributes[$attribute] = $value;
143:         return;
144:     }
145: 
146:     /**
147:      * Determines whether or not the object has a value for the specified
148:      * attribute.
149:      *
150:      * @param string $attribute  The attribute to check.
151:      *
152:      * @return boolean  Whether or not there is a value for $attribute.
153:      */
154:     public function hasValue($attribute)
155:     {
156:         if (isset($this->driver->map[$attribute]) &&
157:             is_array($this->driver->map[$attribute])) {
158:             foreach ($this->driver->map[$attribute]['fields'] as $field) {
159:                 if ($this->hasValue($field)) {
160:                     return true;
161:                 }
162:             }
163:             return false;
164:         } else {
165:             return !is_null($this->getValue($attribute));
166:         }
167:     }
168: 
169:     /**
170:      * Returns the timestamp of the last modification, whether this was the
171:      * creation or editing of the object and stores it as the attribute
172:      * __modified. The value is cached for the lifetime of the object.
173:      *
174:      * @return integer  The timestamp of the last modification or zero.
175:      */
176:     public function lastModification()
177:     {
178:         $time = $this->getValue('__modified');
179:         if (!is_null($time)) {
180:             return $time;
181:         }
182:         if (!$this->getValue('__uid')) {
183:             $this->setValue('__modified', 0);
184:             return 0;
185:         }
186:         $time = 0;
187:         try {
188:             $log = $GLOBALS['injector']
189:                 ->getInstance('Horde_History')
190:                 ->getHistory($this->getGuid());
191:             foreach ($log as $entry) {
192:                 if ($entry['action'] == 'add' || $entry['action'] == 'modify') {
193: 
194:                     $time = max($time, $entry['ts']);
195:                 }
196:             }
197:         } catch (Exception $e) {}
198:         $this->setValue('__modified', $time);
199: 
200:         return $time;
201:     }
202: 
203:     /**
204:      * Merges another contact into this one by filling empty fields of this
205:      * contact with values from the other.
206:      *
207:      * @param Turba_Object $contact  Another contact.
208:      */
209:     public function merge(Turba_Object $contact)
210:     {
211:         foreach (array_keys($contact->attributes) as $attribute) {
212:             if (!$this->hasValue($attribute) && $contact->hasValue($attribute)) {
213:                 $this->setValue($attribute, $contact->getValue($attribute));
214:             }
215:         }
216:     }
217: 
218:     /**
219:      * Returns history information about this contact.
220:      *
221:      * @return array  A hash with the optional entries 'created' and 'modified'
222:      *                and human readable history information as the values.
223:      */
224:     public function getHistory()
225:     {
226:         if (!$this->getValue('__uid')) {
227:             return array();
228:         }
229:         $history = array();
230:         try {
231:             $log = $GLOBALS['injector']
232:                 ->getInstance('Horde_History')
233:                 ->getHistory($this->getGuid());
234:             foreach ($log as $entry) {
235:                 if ($entry['action'] == 'add' || $entry['action'] == 'modify') {
236:                     if ($GLOBALS['registry']->getAuth() != $entry['who']) {
237:                         $by = sprintf(_("by %s"), Turba::getUserName($entry['who']));
238:                     } else {
239:                         $by = _("by me");
240:                     }
241:                     $history[$entry['action'] == 'add' ? 'created' : 'modified']
242:                         = strftime($GLOBALS['prefs']->getValue('date_format'), $entry['ts'])
243:                         . ' '
244:                         . date($GLOBALS['prefs']->getValue('twentyFour') ? 'G:i' : 'g:i a', $entry['ts'])
245:                         . ' '
246:                         . htmlspecialchars($by);
247:                 }
248:             }
249:         } catch (Exception $e) {
250:             return array();
251:         }
252: 
253:         return $history;
254:     }
255: 
256:     /**
257:      * Returns true if this object is a group of multiple contacts.
258:      *
259:      * @return boolean  True if this object is a group of multiple contacts.
260:      */
261:     public function isGroup()
262:     {
263:         return false;
264:     }
265: 
266:     /**
267:      * Returns true if this object is editable by the current user.
268:      *
269:      * @return boolean  Whether or not the current user can edit this object
270:      */
271:     public function isEditable()
272:     {
273:         return $this->driver->hasPermission(Horde_Perms::EDIT);
274:     }
275: 
276:     /**
277:      * Returns whether or not the current user has the requested permission.
278:      *
279:      * @param integer $perm  The permission to check.
280:      *
281:      * @return boolean True if user has the permission.
282:      */
283:     public function hasPermission($perm)
284:     {
285:         return $this->driver->hasPermission($perm);
286:     }
287: 
288:     /**
289:      * Contact url.
290:      *
291:      * @param string $view   The view for the url
292:      * @param boolean $full  Generate a full url?
293:      *
294:      * @return string
295:      */
296:     public function url($view = null, $full = false)
297:     {
298:         $url = Horde::url('contact.php', $full)->add(array(
299:             'source' => $this->driver->getName(),
300:             'key' => $this->getValue('__key')
301:         ));
302: 
303:         if (!is_null($view)) {
304:             $url->add('view', $view);
305:         }
306: 
307:         return $url;
308:     }
309: 
310:     /**
311:      * Saves a file into the VFS backend associated with this object.
312:      *
313:      * @param array $info  A hash with the file information as returned from a
314:      *                     Horde_Form_Type_file.
315:      * @throws Turba_Exception
316:      */
317:     public function addFile(array $info)
318:     {
319:         if (!$this->getValue('__uid')) {
320:             throw new Turba_Exception('VFS not supported for this object.');
321:         }
322:         $this->_vfsInit();
323:         $dir = Turba::VFS_PATH . '/' . $this->getValue('__uid');
324:         $file = $info['name'];
325:         while ($this->_vfs->exists($dir, $file)) {
326:             if (preg_match('/(.*)\[(\d+)\](\.[^.]*)?$/', $file, $match)) {
327:                 $file = $match[1] . '[' . ++$match[2] . ']' . $match[3];
328:             } else {
329:                 $dot = strrpos($file, '.');
330:                 if ($dot === false) {
331:                     $file .= '[1]';
332:                 } else {
333:                     $file = substr($file, 0, $dot) . '[1]' . substr($file, $dot);
334:                 }
335:             }
336:         }
337:         try {
338:             $this->_vfs->write($dir, $file, $info['tmp_name'], true);
339:         } catch (Horde_Vfs_Exception $e) {
340:             throw new Turba_Exception($e);
341:         }
342:     }
343: 
344:     /**
345:      * Deletes a file from the VFS backend associated with this object.
346:      *
347:      * @param string $file  The file name.
348:      * @throws Turba_Exception
349:      */
350:     public function deleteFile($file)
351:     {
352:         if (!$this->getValue('__uid')) {
353:             throw new Turba_Exception('VFS not supported for this object.');
354:         }
355:         $this->_vfsInit();
356:         try {
357:             $this->_vfs->deleteFile(Turba::VFS_PATH . '/' . $this->getValue('__uid'), $file);
358:         } catch (Horde_Vfs_Exception $e) {
359:             throw new Turba_Exception($e);
360:         }
361:     }
362: 
363:     /**
364:      * Deletes all files from the VFS backend associated with this object.
365:      *
366:      * @throws Turba_Exception
367:      */
368:     public function deleteFiles()
369:     {
370:         if (!$this->getValue('__uid')) {
371:             throw new Turba_Exception('VFS not supported for this object.');
372:         }
373:         $this->_vfsInit();
374:         if ($this->_vfs->exists(Turba::VFS_PATH, $this->getValue('__uid'))) {
375:             try {
376:                 $this->_vfs->deleteFolder(Turba::VFS_PATH, $this->getValue('__uid'), true);
377:             } catch (Horde_Vfs_Exception $e) {
378:                 throw new Turba_Exception($e);
379:             }
380:         }
381:     }
382: 
383:     /**
384:      * Returns all files from the VFS backend associated with this object.
385:      *
386:      * @return array  A list of hashes with file informations.
387:      */
388:     public function listFiles()
389:     {
390:         if (!$this->getValue('__uid')) {
391:             return array();
392:         }
393:         try {
394:             $this->_vfsInit();
395:             if ($this->_vfs->exists(Turba::VFS_PATH, $this->getValue('__uid'))) {
396:                 return $this->_vfs->listFolder(Turba::VFS_PATH . '/' . $this->getValue('__uid'));
397:             }
398:         } catch (Turba_Exception $e) {}
399: 
400:         return array();
401:     }
402: 
403:     /**
404:      * Returns a link to display and download a file from the VFS backend
405:      * associated with this object.
406:      *
407:      * @param string $file  The file name.
408:      *
409:      * @return string  The HTML code of the generated link.
410:      */
411:     public function vfsDisplayUrl($file)
412:     {
413:         global $registry, $mime_drivers_map, $mime_drivers;
414: 
415:         $mime_part = new Horde_Mime_Part();
416:         $mime_part->setType(Horde_Mime_Magic::extToMime($file['type']));
417:         $viewer = $GLOBALS['injector']->getInstance('Horde_Core_Factory_MimeViewer')->create($mime_part);
418: 
419:         // We can always download files.
420:         $url_params = array('actionID' => 'download_file',
421:                             'file' => $file['name'],
422:                             'type' => $file['type'],
423:                             'source' => $this->driver->getName(),
424:                             'key' => $this->getValue('__key'));
425:         $dl = Horde::link(Horde::downloadUrl($file['name'], $url_params), $file['name']) . Horde::img('download.png', _("Download")) . '</a>';
426: 
427:         // Let's see if we can view this one, too.
428:         if ($viewer && !($viewer instanceof Horde_Mime_Viewer_Default)) {
429:             $url = Horde::url('view.php')
430:                 ->add($url_params)
431:                 ->add('actionID', 'view_file');
432:             $link = Horde::link($url, $file['name'], null, '_blank') . $file['name'] . '</a>';
433:         } else {
434:             $link = $file['name'];
435:         }
436: 
437:         return $link . ' ' . $dl;
438:     }
439: 
440:     /**
441:      * Returns a link to display, download, and delete a file from the VFS
442:      * backend associated with this object.
443:      *
444:      * @param string $file  The file name.
445:      *
446:      * @return string  The HTML code of the generated link.
447:      */
448:     public function vfsEditUrl($file)
449:     {
450:         $delform = '<form action="' .
451:             Horde::url('deletefile.php') .
452:             '" style="display:inline" method="post">' .
453:             Horde_Util::formInput() .
454:             '<input type="hidden" name="file" value="' . htmlspecialchars($file['name']) . '" />' .
455:             '<input type="hidden" name="source" value="' . htmlspecialchars($this->driver->getName()) . '" />' .
456:             '<input type="hidden" name="key" value="' . htmlspecialchars($this->getValue('__key')) . '" />' .
457:             '<input type="image" class="img" src="' . Horde_Themes::img('delete.png') . '" />' .
458:             '</form>';
459: 
460:         return $this->vfsDisplayUrl($file) . ' ' . $delform;
461:     }
462: 
463:     /**
464:      * Saves the current state of the object to the storage backend.
465:      *
466:      * @throws Turba_Exception
467:      */
468:     public function store()
469:     {
470:         return $this->setValue('__key', $this->driver->save($this));
471:     }
472: 
473:     /**
474:      * Loads the VFS configuration and initializes the VFS backend.
475:      *
476:      * @throws Turba_Exception
477:      */
478:     protected function _vfsInit()
479:     {
480:         if (!isset($this->_vfs)) {
481:             try {
482:                 $this->_vfs = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Vfs')->create('documents');
483:             } catch (Horde_Exception $e) {
484:                 throw new Turba_Exception($e);
485:             }
486:         }
487:     }
488: 
489: }
490: 
API documentation generated by ApiGen