1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
18: class Turba_Driver implements Countable
19: {
20: 21: 22: 23: 24:
25: public $title;
26:
27: 28: 29: 30: 31: 32:
33: public $map = array();
34:
35: 36: 37: 38: 39:
40: public $tabs = array();
41:
42: 43: 44: 45: 46: 47:
48: public $fields = array();
49:
50: 51: 52: 53: 54:
55: public $strict = array();
56:
57: 58: 59: 60: 61: 62:
63: public $approximate = array();
64:
65: 66: 67: 68: 69:
70: public $listNameField = null;
71:
72: 73: 74: 75: 76: 77:
78: public $alternativeName = null;
79:
80: 81: 82: 83: 84:
85: protected $_name;
86:
87: 88: 89: 90: 91:
92: protected $_params = array();
93:
94: 95: 96: 97: 98:
99: protected $_capabilities = array();
100:
101: 102: 103: 104: 105:
106: protected $_count = null;
107:
108: 109: 110: 111: 112:
113: protected $_contact_owner = '';
114:
115: 116: 117: 118: 119: 120: 121:
122: public function __construct($name = '', array $params = array())
123: {
124: $this->_name = $name;
125: $this->_params = $params;
126: }
127:
128: 129: 130: 131: 132:
133: public function getParams()
134: {
135: return $this->_params;
136: }
137:
138: 139: 140: 141: 142: 143: 144:
145: public function hasCapability($capability)
146: {
147: return !empty($this->_capabilities[$capability]);
148: }
149:
150: 151: 152: 153: 154:
155: public function getBlobs()
156: {
157: global $attributes;
158:
159: $blobs = array();
160: foreach (array_keys($this->fields) as $attribute) {
161: if (isset($attributes[$attribute]) &&
162: $attributes[$attribute]['type'] == 'image') {
163: $blobs[$attribute] = true;
164: }
165: }
166:
167: return $blobs;
168: }
169:
170: 171: 172: 173: 174: 175: 176: 177: 178:
179: public function toDriverKeys(array $hash)
180: {
181:
182: if (!empty($hash['category'])) {
183: if (is_array($hash['category']) && !empty($hash['category']['new'])) {
184: $cManager = new Horde_Prefs_CategoryManager();
185: $cManager->add($hash['category']['value']);
186: $hash['category'] = $hash['category']['value'];
187: } elseif (is_array($hash['category'])) {
188: $hash['category'] = $hash['category']['value'];
189: }
190: }
191:
192:
193:
194:
195: foreach ($this->map as $key => $val) {
196: if (!is_array($val) ||
197: empty($this->map[$key]['attribute']) ||
198: array_key_exists($key, $hash)) {
199: continue;
200: }
201:
202: foreach ($this->map[$key]['fields'] as $mapfields) {
203: if (isset($hash[$mapfields])) {
204:
205: $hash[$key] = null;
206: break;
207: }
208: }
209: }
210:
211: if (!empty($hash['name']) &&
212: !empty($this->listNameField) &&
213: !empty($hash['__type']) &&
214: is_array($this->map['name']) &&
215: ($hash['__type'] == 'Group')) {
216: $hash[$this->listNameField] = $hash['name'];
217: unset($hash['name']);
218: }
219:
220: $fields = array();
221: foreach ($hash as $key => $val) {
222: if (isset($this->map[$key])) {
223: if (!is_array($this->map[$key])) {
224: $fields[$this->map[$key]] = $val;
225: } elseif (!empty($this->map[$key]['attribute'])) {
226: $fieldarray = array();
227: foreach ($this->map[$key]['fields'] as $mapfields) {
228: $fieldarray[] = isset($hash[$mapfields])
229: ? $hash[$mapfields]
230: : '';
231: }
232: $fields[$this->map[$key]['attribute']] = Turba::formatCompositeField($this->map[$key]['format'], $fieldarray);
233: } else {
234:
235: if (!isset($this->map[$key]['parse'])) {
236: $this->map[$key]['parse'] = array(
237: array(
238: 'format' => $this->map[$key]['format'],
239: 'fields' => $this->map[$key]['fields']
240: )
241: );
242: }
243: foreach ($this->map[$key]['parse'] as $parse) {
244: $splitval = sscanf($val, $parse['format']);
245: $count = 0;
246: $tmp_fields = array();
247: foreach ($parse['fields'] as $mapfield) {
248: if (isset($hash[$mapfield])) {
249:
250:
251: break 2;
252: }
253: $tmp_fields[$this->map[$mapfield]] = $splitval[$count++];
254: }
255:
256: if ($splitval[$count - 1] !== null) {
257: break;
258: }
259: }
260: $fields = array_merge($fields, $tmp_fields);
261: }
262: }
263: }
264:
265: return $fields;
266: }
267:
268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281:
282: public function makeSearch($criteria, $search_type, array $strict,
283: $match_begin = false)
284: {
285: $search = $search_terms = $subsearch = $strict_search = array();
286: $glue = $temp = '';
287: $lastChar = '\"';
288: $blobs = $this->getBlobs();
289:
290: foreach ($criteria as $key => $val) {
291: if (!isset($this->map[$key])) {
292: continue;
293: }
294: if (is_array($this->map[$key])) {
295:
296: $parts = explode(' ', $val);
297: if (count($parts) > 1) {
298: 299:
300: for ($i = 0; $i < count($parts); ++$i) {
301: $term = $parts[$i];
302: $firstChar = substr($term, 0, 1);
303: if ($firstChar == '"') {
304: $temp = substr($term, 1, strlen($term) - 1);
305: $done = false;
306: while (!$done && $i < count($parts) - 1) {
307: $lastChar = substr($parts[$i + 1], -1);
308: if ($lastChar == '"') {
309: $temp .= ' ' . substr($parts[$i + 1], 0, -1);
310: $done = true;
311: } else {
312: $temp .= ' ' . $parts[$i + 1];
313: }
314: ++$i;
315: }
316: $search_terms[] = $temp;
317: } else {
318: $search_terms[] = $term;
319: }
320: }
321: $glue = 'AND';
322: } else {
323: 324: 325:
326: $search_terms[0] = $val;
327: $glue = 'OR';
328: }
329:
330: foreach ($this->map[$key]['fields'] as $field) {
331: if (!empty($blobs[$field])) {
332: continue;
333: }
334: $field = $this->toDriver($field);
335: if (!empty($strict[$field])) {
336: 337:
338: $strict_search[] = array(
339: 'field' => $field,
340: 'op' => '=',
341: 'test' => $val,
342: );
343: } else {
344: 345:
346: if (count($search_terms) > 1) {
347: 348:
349: $atomsearch = array();
350: for ($i = 0; $i < count($search_terms); ++$i) {
351: $atomsearch[] = array(
352: 'field' => $field,
353: 'op' => 'LIKE',
354: 'test' => $search_terms[$i],
355: 'begin' => $match_begin,
356: 'approximate' => !empty($this->approximate[$field]),
357: );
358: }
359: $atomsearch[] = array(
360: 'field' => $field,
361: 'op' => '=',
362: 'test' => '',
363: 'begin' => $match_begin,
364: 'approximate' => !empty($this->approximate[$field])
365: );
366:
367: $subsearch[] = array('OR' => $atomsearch);
368: unset($atomsearch);
369: $glue = 'AND';
370: } else {
371: 372: 373:
374: $subsearch[] = array(
375: 'field' => $field,
376: 'op' => 'LIKE',
377: 'test' => $search_terms[0],
378: 'begin' => $match_begin,
379: 'approximate' => !empty($this->approximate[$field]),
380: );
381: $glue = 'OR';
382: }
383: }
384: }
385: if (count($subsearch)) {
386: $search[] = array($glue => $subsearch);
387: }
388: } else {
389:
390: if (!empty($blobs[$key])) {
391: continue;
392: }
393: if (!empty($strict[$this->map[$key]])) {
394: $strict_search[] = array(
395: 'field' => $this->map[$key],
396: 'op' => '=',
397: 'test' => $val,
398: );
399: } else {
400: $search[] = array(
401: 'field' => $this->map[$key],
402: 'op' => 'LIKE',
403: 'test' => $val,
404: 'begin' => $match_begin,
405: 'approximate' => !empty($this->approximate[$this->map[$key]]),
406: );
407: }
408: }
409: }
410:
411: if (count($strict_search) && count($search)) {
412: return array(
413: 'AND' => array(
414: $search_type => $strict_search,
415: array(
416: $search_type => $search
417: )
418: )
419: );
420: } elseif (count($strict_search)) {
421: return array(
422: 'AND' => $strict_search
423: );
424: } elseif (count($search)) {
425: return array(
426: $search_type => $search
427: );
428: }
429:
430: return array();
431: }
432:
433: 434: 435: 436: 437: 438: 439: 440: 441:
442: public function toDriver($attribute)
443: {
444: if (!isset($this->map[$attribute])) {
445: return null;
446: }
447:
448: return is_array($this->map[$attribute])
449: ? $this->map[$attribute]['fields']
450: : $this->map[$attribute];
451: }
452:
453: 454: 455: 456: 457: 458: 459: 460: 461:
462: public function toTurbaKeys(array $entry)
463: {
464: $new_entry = array();
465: foreach ($this->map as $key => $val) {
466: if (!is_array($val)) {
467: $new_entry[$key] = (isset($entry[$val]) && strlen($entry[$val]))
468: ? trim($entry[$val])
469: : null;
470: }
471: }
472:
473: return $new_entry;
474: }
475:
476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499:
500: public function search(array $search_criteria, $sort_order = null,
501: $search_type = 'AND', array $return_fields = array(),
502: array $custom_strict = array(), $match_begin = false,
503: $count_only = false)
504: {
505: 506:
507: $search_criteria['__owner'] = $this->getContactOwner();
508: $strict_fields = array($this->toDriver('__owner') => true);
509:
510: 511:
512: foreach ($this->strict as $strict_field) {
513: $strict_fields[$strict_field] = true;
514: }
515: foreach ($custom_strict as $strict_field) {
516: $strict_fields[$this->map[$strict_field]] = true;
517: }
518:
519:
520: $fields = $this->makeSearch($search_criteria, $search_type,
521: $strict_fields, $match_begin);
522:
523: if (count($return_fields)) {
524: $return_fields_pre = array_unique(array_merge(array('__key', '__type', '__owner', '__members', 'name'), $return_fields));
525: $return_fields = array();
526: foreach ($return_fields_pre as $field) {
527: $result = $this->toDriver($field);
528: if (is_array($result)) {
529: foreach ($result as $composite_field) {
530: $composite_result = $this->toDriver($composite_field);
531: if ($composite_result) {
532: $return_fields[] = $composite_result;
533: }
534: }
535: } elseif ($result) {
536: $return_fields[] = $result;
537: }
538: }
539: } else {
540: 541: 542:
543: $return_fields = array_values(
544: array_unique(array_values($this->fields)));
545: }
546:
547:
548: $objects = $this->_search($fields, $return_fields, $this->toDriverKeys($this->getBlobs()), $count_only);
549: if ($count_only) {
550: return $objects;
551: }
552: return $this->_toTurbaObjects($objects, $sort_order);
553: }
554:
555: 556: 557: 558: 559: 560: 561: 562: 563: 564: 565: 566:
567: public function searchDuplicates()
568: {
569: return array();
570: }
571:
572: 573: 574: 575: 576: 577: 578: 579: 580: 581: 582: 583: 584: 585:
586: protected function _toTurbaObjects(array $objects, array $sort_order = null)
587: {
588: $list = new Turba_List();
589:
590: foreach ($objects as $object) {
591: 592:
593: $object = $this->toTurbaKeys($object);
594:
595: $done = false;
596: if (!empty($object['__type']) &&
597: ucwords($object['__type']) != 'Object') {
598: $class = 'Turba_Object_' . ucwords($object['__type']);
599: if (class_exists($class)) {
600: $list->insert(new $class($this, $object));
601: $done = true;
602: }
603: }
604: if (!$done) {
605: $list->insert(new Turba_Object($this, $object));
606: }
607: }
608:
609: $list->sort($sort_order);
610:
611:
612: return $list;
613: }
614:
615: 616: 617: 618: 619: 620: 621: 622: 623: 624: 625:
626: public function listTimeObjects(Horde_Date $start, Horde_Date $end, $category)
627: {
628: try {
629: $res = $this->getTimeObjectTurbaList($start, $end, $category);
630: } catch (Turba_Exception $e) {
631:
632: $res = $this->_getTimeObjectTurbaListFallback($start, $end, $category);
633: }
634:
635: $t_objects = array();
636: while ($ob = $res->next()) {
637: $t_object = $ob->getValue($category);
638: if (empty($t_object) ||
639: $t_object == '0000-00-00' ||
640: !preg_match('/(\d{4})-(\d{2})-(\d{2})/', $t_object, $match)) {
641: continue;
642: }
643:
644: $t_object = new Horde_Date(array(
645: 'mday' => $match[3],
646: 'month' => $match[2],
647: 'year' => $match[1]
648: ));
649: if ($t_object->compareDate($end) > 0) {
650: continue;
651: }
652:
653: $t_object_end = new Horde_Date($t_object);
654: ++$t_object_end->mday;
655: $key = $ob->getValue('__key');
656:
657:
658: if ($start->year == $end->year ||
659: $end->year == 9999) {
660: $age = $start->year - $t_object->year;
661: } elseif ($t_object->month <= $end->month) {
662:
663: $age = $end->year - $t_object->year;
664: } else {
665:
666: $age = $start->year - $t_object->year;
667: }
668:
669: $title = sprintf(_("%d. %s of %s"),
670: $age,
671: $GLOBALS['attributes'][$category]['label'],
672: $ob->getValue('name'));
673:
674: $t_objects[] = array(
675: 'id' => $key,
676: 'title' => $title,
677: 'start' => sprintf('%d-%02d-%02dT00:00:00',
678: $t_object->year,
679: $t_object->month,
680: $t_object->mday),
681: 'end' => sprintf('%d-%02d-%02dT00:00:00',
682: $t_object_end->year,
683: $t_object_end->month,
684: $t_object_end->mday),
685: 'category' => $ob->getValue('category'),
686: 'recurrence' => array('type' => Horde_Date_Recurrence::RECUR_YEARLY_DATE,
687: 'interval' => 1),
688: 'params' => array('source' => $this->_name, 'key' => $key),
689: 'link' => Horde::url('contact.php', true)->add(array('source' => $this->_name, 'key' => $key))->setRaw(true));
690: }
691:
692: return $t_objects;
693: }
694:
695: 696: 697: 698: 699: 700: 701: 702: 703: 704: 705: 706: 707:
708: public function getTimeObjectTurbaList(Horde_Date $start, Horde_Date $end, $field)
709: {
710: return $this->_getTimeObjectTurbaListFallback($start, $end, $field);
711: }
712:
713: 714: 715: 716: 717: 718: 719: 720: 721: 722: 723: 724: 725:
726: protected function _getTimeObjectTurbaListFallback(Horde_Date $start, Horde_Date $end, $field)
727: {
728: return $this->search(array(), null, 'AND', array('name', $field, 'category'));
729: }
730:
731: 732: 733: 734: 735: 736: 737: 738:
739: public function getObjects(array $objectIds)
740: {
741: $objects = $this->_read($this->map['__key'], $objectIds,
742: $this->getContactOwner(),
743: array_values($this->fields),
744: $this->toDriverKeys($this->getBlobs()));
745: if (!is_array($objects)) {
746: throw new Turba_Exception(_("Requested object not found."));
747: }
748:
749: $results = array();
750: foreach ($objects as $object) {
751: $object = $this->toTurbaKeys($object);
752: $done = false;
753: if (!empty($object['__type']) &&
754: ucwords($object['__type']) != 'Object') {
755: $class = 'Turba_Object_' . ucwords($object['__type']);
756: if (class_exists($class)) {
757: $results[] = new $class($this, $object);
758: $done = true;
759: }
760: }
761: if (!$done) {
762: $results[] = new Turba_Object($this, $object);
763: }
764: }
765:
766: return $results;
767: }
768:
769: 770: 771: 772: 773: 774: 775: 776:
777: public function getObject($objectId)
778: {
779: $result = $this->getObjects(array($objectId));
780:
781: if (empty($result[0])) {
782: throw new Turba_Exception('No results');
783: }
784:
785: $result = $result[0];
786: if (!isset($this->map['__owner'])) {
787: $result->attributes['__owner'] = $this->getContactOwner();
788: }
789:
790: return $result;
791: }
792:
793: 794: 795: 796: 797: 798: 799: 800:
801: public function add(array $attributes)
802: {
803:
804: if (!isset($attributes['__type'])) {
805: $attributes['__type'] = 'Object';
806: }
807: if (isset($this->map['__owner']) && !isset($attributes['__owner'])) {
808: $attributes['__owner'] = $this->getContactOwner();
809: }
810:
811: if (!isset($attributes['__uid'])) {
812: $attributes['__uid'] = $this->_makeUid();
813: }
814:
815: $key = $attributes['__key'] = $this->_makeKey($this->toDriverKeys($attributes));
816: $uid = $attributes['__uid'];
817:
818: $attributes = $this->toDriverKeys($attributes);
819:
820: $this->_add($attributes, $this->toDriverKeys($this->getBlobs()));
821:
822:
823: try {
824: $GLOBALS['injector']->getInstance('Horde_History')
825: ->log('turba:' . $this->getName() . ':' . $uid,
826: array('action' => 'add'), true);
827: } catch (Exception $e) {
828: Horde::logMessage($e, 'ERR');
829: }
830:
831: return $key;
832: }
833:
834: 835: 836: 837: 838:
839: public function canAdd()
840: {
841: return $this->_canAdd();
842: }
843:
844: 845: 846: 847: 848:
849: protected function _canAdd()
850: {
851: return false;
852: }
853:
854: 855: 856: 857: 858: 859: 860:
861: public function delete($object_id)
862: {
863: $object = $this->getObject($object_id);
864:
865: if (!$object->hasPermission(Horde_Perms::DELETE)) {
866: throw new Turba_Exception(_("Permission denied"));
867: }
868:
869: $this->_delete($this->toDriver('__key'), $object_id);
870:
871: $own_contact = $GLOBALS['prefs']->getValue('own_contact');
872: if (!empty($own_contact)) {
873: @list($source, $id) = explode(';', $own_contact);
874: if ($id == $object_id) {
875: $GLOBALS['prefs']->setValue('own_contact', '');
876: }
877: }
878:
879:
880: if ($object->getValue('__uid')) {
881: try {
882: $GLOBALS['injector']->getInstance('Horde_History')->log($object->getGuid(),
883: array('action' => 'delete'),
884: true);
885: } catch (Exception $e) {
886: Horde::logMessage($e, 'ERR');
887: }
888: }
889:
890: return true;
891: }
892:
893: 894: 895: 896: 897: 898: 899: 900: 901: 902:
903: public function deleteAll($sourceName = null)
904: {
905: if (!$this->hasCapability('delete_all')) {
906: throw new Turba_Exception('Not supported');
907: }
908:
909: $this->_deleteAll($sourceName);
910: }
911:
912: 913: 914:
915: protected function _deleteAll()
916: {
917: }
918:
919: 920: 921: 922: 923: 924: 925: 926:
927: public function save(Turba_Object $object)
928: {
929: $object_id = $this->_save($object);
930:
931:
932: if ($object->getValue('__uid')) {
933: try {
934: $GLOBALS['injector']->getInstance('Horde_History')->log($object->getGuid(),
935: array('action' => 'modify'),
936: true);
937: } catch (Exception $e) {
938: Horde::logMessage($e, 'ERR');
939: }
940: }
941:
942: return $object_id;
943: }
944:
945: 946: 947: 948: 949:
950: public function getCriteria()
951: {
952: $criteria = $this->map;
953: unset($criteria['__key']);
954:
955: return $criteria;
956: }
957:
958: 959: 960: 961: 962: 963:
964: public function getFields()
965: {
966: return array_flip($this->fields);
967: }
968:
969: 970: 971: 972: 973: 974: 975: 976: 977: 978: 979: 980:
981: public function tovCard(Turba_Object $object, $version = '2.1',
982: array $fields = null, $skipEmpty = false)
983: {
984: $hash = $object->getAttributes();
985: $vcard = new Horde_Icalendar_Vcard($version);
986: $formattedname = false;
987: $charset = ($version == '2.1')
988: ? array('CHARSET' => 'UTF-8')
989: : array();
990:
991: $haveDecodeHook = Horde::hookExists('decode_attribute', 'turba');
992: foreach ($hash as $key => $val) {
993: if ($skipEmpty && !strlen($val)) {
994: continue;
995: }
996: if ($haveDecodeHook) {
997: try {
998: $val = Horde::callHook(
999: 'decode_attribute',
1000: array($key, $val, $object),
1001: 'turba');
1002: } catch (Turba_Exception $e) {}
1003: }
1004: switch ($key) {
1005: case 'name':
1006: if ($fields && !isset($fields['FN'])) {
1007: break;
1008: }
1009: $vcard->setAttribute('FN', $val, Horde_Mime::is8bit($val) ? $charset : array());
1010: $formattedname = true;
1011: break;
1012:
1013: case 'nickname':
1014: case 'alias':
1015: $params = Horde_Mime::is8bit($val) ? $charset : array();
1016: if (!$fields || isset($fields['NICKNAME'])) {
1017: $vcard->setAttribute('NICKNAME', $val, $params);
1018: }
1019: if (!$fields || isset($fields['X-EPOCSECONDNAME'])) {
1020: $vcard->setAttribute('X-EPOCSECONDNAME', $val, $params);
1021: }
1022: break;
1023:
1024: case 'homeAddress':
1025: if ($fields &&
1026: (!isset($fields['LABEL']) ||
1027: (isset($fields['LABEL']->Params['TYPE']) &&
1028: !$this->_hasValEnum($fields['LABEL']->Params['TYPE']->ValEnum, 'HOME')))) {
1029: break;
1030: }
1031: if ($version == '2.1') {
1032: $vcard->setAttribute('LABEL', $val, array('HOME' => null));
1033: } else {
1034: $vcard->setAttribute('LABEL', $val, array('TYPE' => 'HOME'));
1035: }
1036: break;
1037:
1038: case 'workAddress':
1039: if ($fields &&
1040: (!isset($fields['LABEL']) ||
1041: (isset($fields['LABEL']->Params['TYPE']) &&
1042: !$this->_hasValEnum($fields['LABEL']->Params['TYPE']->ValEnum, 'WORK')))) {
1043: break;
1044: }
1045: if ($version == '2.1') {
1046: $vcard->setAttribute('LABEL', $val, array('WORK' => null));
1047: } else {
1048: $vcard->setAttribute('LABEL', $val, array('TYPE' => 'WORK'));
1049: }
1050: break;
1051:
1052: case 'otherAddress':
1053: if ($fields && !isset($fields['LABEL'])) {
1054: break;
1055: }
1056: $vcard->setAttribute('LABEL', $val);
1057: break;
1058:
1059: case 'phone':
1060: if ($fields && !isset($fields['TEL'])) {
1061: break;
1062: }
1063: $vcard->setAttribute('TEL', $val);
1064: break;
1065:
1066: case 'homePhone':
1067: if ($fields &&
1068: (!isset($fields['TEL']) ||
1069: (isset($fields['TEL']->Params['TYPE']) &&
1070: !$this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'HOME')))) {
1071: break;
1072: }
1073: if ($version == '2.1') {
1074: $vcard->setAttribute('TEL', $val, array('HOME' => null, 'VOICE' => null));
1075: } else {
1076: $vcard->setAttribute('TEL', $val, array('TYPE' => array('HOME', 'VOICE')));
1077: }
1078: break;
1079:
1080: case 'workPhone':
1081: if ($fields &&
1082: (!isset($fields['TEL']) ||
1083: (isset($fields['TEL']->Params['TYPE']) &&
1084: !$this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'WORK')))) {
1085: break;
1086: }
1087: if ($version == '2.1') {
1088: $vcard->setAttribute('TEL', $val, array('WORK' => null, 'VOICE' => null));
1089: } else {
1090: $vcard->setAttribute('TEL', $val, array('TYPE' => array('WORK', 'VOICE')));
1091: }
1092: break;
1093:
1094: case 'cellPhone':
1095: if ($fields &&
1096: (!isset($fields['TEL']) ||
1097: (isset($fields['TEL']->Params['TYPE']) &&
1098: !$this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'CELL')))) {
1099: break;
1100: }
1101: if ($version == '2.1') {
1102: $vcard->setAttribute('TEL', $val, array('CELL' => null, 'VOICE' => null));
1103: } else {
1104: $vcard->setAttribute('TEL', $val, array('TYPE' => array('CELL', 'VOICE')));
1105: }
1106: break;
1107:
1108: case 'homeCellPhone':
1109: $parameters = array();
1110: if ($fields) {
1111: if (!isset($fields['TEL'])) {
1112: break;
1113: }
1114: if (!isset($fields['TEL']->Params['TYPE']) ||
1115: $this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'CELL')) {
1116: if ($version == '2.1') {
1117: $parameters['CELL'] = null;
1118: $parameters['VOICE'] = null;
1119: } else {
1120: $parameters['TYPE'] = array('CELL', 'VOICE');
1121: }
1122: }
1123: if (!isset($fields['TEL']->Params['TYPE']) ||
1124: $this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'HOME')) {
1125: if ($version == '2.1') {
1126: $parameters['HOME'] = null;
1127: $parameters['VOICE'] = null;
1128: } else {
1129: $parameters['TYPE'] = array('HOME', 'VOICE');
1130: }
1131: }
1132: if (empty($parameters)) {
1133: break;
1134: }
1135: } else {
1136: if ($version == '2.1') {
1137: $parameters = array('CELL' => null, 'HOME' => null, 'VOICE' => null);
1138: } else {
1139: $parameters = array('TYPE' => array('CELL', 'HOME', 'VOICE'));
1140: }
1141: }
1142: $vcard->setAttribute('TEL', $val, $parameters);
1143: break;
1144:
1145: case 'workCellPhone':
1146: $parameters = array();
1147: if ($fields) {
1148: if (!isset($fields['TEL'])) {
1149: break;
1150: }
1151: if (!isset($fields['TEL']->Params['TYPE']) ||
1152: $this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'CELL')) {
1153: if ($version == '2.1') {
1154: $parameters['CELL'] = null;
1155: $parameters['VOICE'] = null;
1156: } else {
1157: $parameters['TYPE'] = array('CELL', 'VOICE');
1158: }
1159: }
1160: if (!isset($fields['TEL']->Params['TYPE']) ||
1161: $this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'WORK')) {
1162: if ($version == '2.1') {
1163: $parameters['WORK'] = null;
1164: $parameters['VOICE'] = null;
1165: } else {
1166: $parameters['TYPE'] = array('WORK', 'VOICE');
1167: }
1168: }
1169: if (empty($parameters)) {
1170: break;
1171: }
1172: } else {
1173: if ($version == '2.1') {
1174: $parameters = array('CELL' => null, 'WORK' => null, 'VOICE' => null);
1175: } else {
1176: $parameters = array('TYPE' => array('CELL', 'WORK', 'VOICE'));
1177: }
1178: }
1179: $vcard->setAttribute('TEL', $val, $parameters);
1180: break;
1181:
1182: case 'videoCall':
1183: if ($fields &&
1184: (!isset($fields['TEL']) ||
1185: (isset($fields['TEL']->Params['TYPE']) &&
1186: !$this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'VIDEO')))) {
1187: break;
1188: }
1189: if ($version == '2.1') {
1190: $vcard->setAttribute('TEL', $val, array('VIDEO' => null));
1191: } else {
1192: $vcard->setAttribute('TEL', $val, array('TYPE' => 'VIDEO'));
1193: }
1194: break;
1195:
1196: case 'homeVideoCall':
1197: $parameters = array();
1198: if ($fields) {
1199: if (!isset($fields['TEL'])) {
1200: break;
1201: }
1202: if (!isset($fields['TEL']->Params['TYPE']) ||
1203: $this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'VIDEO')) {
1204: if ($version == '2.1') {
1205: $parameters['VIDEO'] = null;
1206: } else {
1207: $parameters['TYPE'] = 'VIDEO';
1208: }
1209: }
1210: if (!isset($fields['TEL']->Params['TYPE']) ||
1211: $this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'HOME')) {
1212: if ($version == '2.1') {
1213: $parameters['HOME'] = null;
1214: } else {
1215: $parameters['TYPE'] = 'HOME';
1216: }
1217: }
1218: if (empty($parameters)) {
1219: break;
1220: }
1221: } else {
1222: if ($version == '2.1') {
1223: $parameters = array('VIDEO' => null, 'HOME' => null);
1224: } else {
1225: $parameters = array('TYPE' => array('VIDEO', 'HOME'));
1226: }
1227: }
1228: $vcard->setAttribute('TEL', $val, $parameters);
1229: break;
1230:
1231: case 'workVideoCall':
1232: $parameters = array();
1233: if ($fields) {
1234: if (!isset($fields['TEL'])) {
1235: break;
1236: }
1237: if (!isset($fields['TEL']->Params['TYPE']) ||
1238: $this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'VIDEO')) {
1239: if ($version == '2.1') {
1240: $parameters['VIDEO'] = null;
1241: } else {
1242: $parameters['TYPE'] = 'VIDEO';
1243: }
1244: }
1245: if (!isset($fields['TEL']->Params['TYPE']) ||
1246: $this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'WORK')) {
1247: if ($version == '2.1') {
1248: $parameters['WORK'] = null;
1249: } else {
1250: $parameters['TYPE'] = 'WORK';
1251: }
1252: }
1253: if (empty($parameters)) {
1254: break;
1255: }
1256: } else {
1257: if ($version == '2.1') {
1258: $parameters = array('VIDEO' => null, 'WORK' => null);
1259: } else {
1260: $parameters = array('TYPE' => array('VIDEO', 'WORK'));
1261: }
1262: }
1263: $vcard->setAttribute('TEL', $val, $parameters);
1264: break;
1265:
1266: case 'sip':
1267: if ($fields && !isset($fields['X-SIP'])) {
1268: break;
1269: }
1270: $vcard->setAttribute('X-SIP', $val);
1271: break;
1272: case 'ptt':
1273: if ($fields &&
1274: (!isset($fields['X-SIP']) ||
1275: (isset($fields['X-SIP']->Params['TYPE']) &&
1276: !$this->_hasValEnum($fields['X-SIP']->Params['TYPE']->ValEnum, 'POC')))) {
1277: break;
1278: }
1279: if ($version == '2.1') {
1280: $vcard->setAttribute('X-SIP', $val, array('POC' => null));
1281: } else {
1282: $vcard->setAttribute('X-SIP', $val, array('TYPE' => 'POC'));
1283: }
1284: break;
1285:
1286: case 'voip':
1287: if ($fields &&
1288: (!isset($fields['X-SIP']) ||
1289: (isset($fields['X-SIP']->Params['TYPE']) &&
1290: !$this->_hasValEnum($fields['X-SIP']->Params['TYPE']->ValEnum, 'VOIP')))) {
1291: break;
1292: }
1293: if ($version == '2.1') {
1294: $vcard->setAttribute('X-SIP', $val, array('VOIP' => null));
1295: } else {
1296: $vcard->setAttribute('X-SIP', $val, array('TYPE' => 'VOIP'));
1297: }
1298: break;
1299:
1300: case 'shareView':
1301: if ($fields &&
1302: (!isset($fields['X-SIP']) ||
1303: (isset($fields['X-SIP']->Params['TYPE']) &&
1304: !$this->_hasValEnum($fields['X-SIP']->Params['TYPE']->ValEnum, 'SWIS')))) {
1305: break;
1306: }
1307: if ($version == '2.1') {
1308: $vcard->setAttribute('X-SIP', $val, array('SWIS' => null));
1309: } else {
1310: $vcard->setAttribute('X-SIP', $val, array('TYPE' => 'SWIS'));
1311: }
1312: break;
1313:
1314: case 'instantMessenger':
1315: if ($fields && !isset($fields['X-WV-ID'])) {
1316: break;
1317: }
1318: $vcard->setAttribute('X-WV-ID', $val);
1319: break;
1320:
1321: case 'fax':
1322: if ($fields &&
1323: (!isset($fields['TEL']) ||
1324: (isset($fields['TEL']->Params['TYPE']) &&
1325: !$this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'FAX')))) {
1326: break;
1327: }
1328: if ($version == '2.1') {
1329: $vcard->setAttribute('TEL', $val, array('FAX' => null));
1330: } else {
1331: $vcard->setAttribute('TEL', $val, array('TYPE' => 'FAX'));
1332: }
1333: break;
1334:
1335: case 'homeFax':
1336: $parameters = array();
1337: if ($fields) {
1338: if (!isset($fields['TEL'])) {
1339: break;
1340: }
1341: if (!isset($fields['TEL']->Params['TYPE']) ||
1342: $this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'FAX')) {
1343: if ($version == '2.1') {
1344: $parameters['FAX'] = null;
1345: } else {
1346: $parameters['TYPE'] = 'FAX';
1347: }
1348: }
1349: if (!isset($fields['TEL']->Params['TYPE']) ||
1350: $this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'HOME')) {
1351: if ($version == '2.1') {
1352: $parameters['HOME'] = null;
1353: } else {
1354: $parameters['TYPE'] = 'HOME';
1355: }
1356: }
1357: if (empty($parameters)) {
1358: break;
1359: }
1360: } else {
1361: if ($version == '2.1') {
1362: $parameters = array('FAX' => null, 'HOME' => null);
1363: } else {
1364: $parameters = array('TYPE' => array('FAX', 'HOME'));
1365: }
1366: }
1367: $vcard->setAttribute('TEL', $val, $parameters);
1368: break;
1369:
1370: case 'workFax':
1371: $parameters = array();
1372: if ($fields) {
1373: if (!isset($fields['TEL'])) {
1374: break;
1375: }
1376: if (!isset($fields['TEL']->Params['TYPE']) ||
1377: $this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'FAX')) {
1378: if ($version == '2.1') {
1379: $parameters['FAX'] = null;
1380: } else {
1381: $parameters['TYPE'] = 'FAX';
1382: }
1383: }
1384: if (!isset($fields['TEL']->Params['TYPE']) ||
1385: $this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'WORK')) {
1386: if ($version == '2.1') {
1387: $parameters['WORK'] = null;
1388: } else {
1389: $parameters['TYPE'] = 'WORK';
1390: }
1391: }
1392: if (empty($parameters)) {
1393: break;
1394: }
1395: } else {
1396: if ($version == '2.1') {
1397: $parameters = array('FAX' => null, 'WORK' => null);
1398: } else {
1399: $parameters = array('TYPE' => array('FAX', 'WORK'));
1400: }
1401: }
1402: $vcard->setAttribute('TEL', $val, $parameters);
1403: if ($version == '2.1') {
1404: $vcard->setAttribute('TEL', $val, array('FAX' => null, 'WORK' => null));
1405: } else {
1406: $vcard->setAttribute('TEL', $val, array('TYPE' => array('FAX', 'WORK')));
1407: }
1408: break;
1409:
1410: case 'pager':
1411: if ($fields &&
1412: (!isset($fields['TEL']) ||
1413: (isset($fields['TEL']->Params['TYPE']) &&
1414: !$this->_hasValEnum($fields['TEL']->Params['TYPE']->ValEnum, 'PAGER')))) {
1415: break;
1416: }
1417: if ($version == '2.1') {
1418: $vcard->setAttribute('TEL', $val, array('PAGER' => null));
1419: } else {
1420: $vcard->setAttribute('TEL', $val, array('TYPE' => 'PAGER'));
1421: }
1422: break;
1423:
1424: case 'email':
1425: if ($fields && !isset($fields['EMAIL'])) {
1426: break;
1427: }
1428: if ($version == '2.1') {
1429: $vcard->setAttribute(
1430: 'EMAIL',
1431: Horde_Icalendar_Vcard::getBareEmail($val),
1432: array('INTERNET' => null));
1433: } else {
1434: $vcard->setAttribute(
1435: 'EMAIL',
1436: Horde_Icalendar_Vcard::getBareEmail($val),
1437: array('TYPE' => 'INTERNET'));
1438: }
1439: break;
1440:
1441: case 'homeEmail':
1442: if ($fields &&
1443: (!isset($fields['EMAIL']) ||
1444: (isset($fields['EMAIL']->Params['TYPE']) &&
1445: !$this->_hasValEnum($fields['EMAIL']->Params['TYPE']->ValEnum, 'HOME')))) {
1446: break;
1447: }
1448: if ($version == '2.1') {
1449: $vcard->setAttribute('EMAIL',
1450: Horde_Icalendar_Vcard::getBareEmail($val),
1451: array('HOME' => null));
1452: } else {
1453: $vcard->setAttribute('EMAIL',
1454: Horde_Icalendar_Vcard::getBareEmail($val),
1455: array('TYPE' => 'HOME'));
1456: }
1457: break;
1458:
1459: case 'workEmail':
1460: if ($fields &&
1461: (!isset($fields['EMAIL']) ||
1462: (isset($fields['EMAIL']->Params['TYPE']) &&
1463: !$this->_hasValEnum($fields['EMAIL']->Params['TYPE']->ValEnum, 'WORK')))) {
1464: break;
1465: }
1466: if ($version == '2.1') {
1467: $vcard->setAttribute('EMAIL',
1468: Horde_Icalendar_Vcard::getBareEmail($val),
1469: array('WORK' => null));
1470: } else {
1471: $vcard->setAttribute('EMAIL',
1472: Horde_Icalendar_Vcard::getBareEmail($val),
1473: array('TYPE' => 'WORK'));
1474: }
1475: break;
1476:
1477: case 'emails':
1478: if ($fields && !isset($fields['EMAIL'])) {
1479: break;
1480: }
1481: $emails = explode(',', $val);
1482: foreach ($emails as $email) {
1483: $vcard->setAttribute('EMAIL', Horde_Icalendar_Vcard::getBareEmail($email));
1484: }
1485: break;
1486:
1487: case 'title':
1488: if ($fields && !isset($fields['TITLE'])) {
1489: break;
1490: }
1491: $vcard->setAttribute('TITLE', $val, Horde_Mime::is8bit($val) ? $charset : array());
1492: break;
1493:
1494: case 'role':
1495: if ($fields && !isset($fields['ROLE'])) {
1496: break;
1497: }
1498: $vcard->setAttribute('ROLE', $val, Horde_Mime::is8bit($val) ? $charset : array());
1499: break;
1500:
1501: case 'notes':
1502: if ($fields && !isset($fields['NOTE'])) {
1503: break;
1504: }
1505: $vcard->setAttribute('NOTE', $val, Horde_Mime::is8bit($val) ? $charset : array());
1506: break;
1507:
1508: case 'businessCategory':
1509: case 'category':
1510: if ($fields && !isset($fields['CATEGORIES'])) {
1511: break;
1512: }
1513: $vcard->setAttribute('CATEGORIES', $val);
1514: break;
1515:
1516: case 'anniversary':
1517: if (!$fields || isset($fields['X-ANNIVERSARY'])) {
1518: $vcard->setAttribute('X-ANNIVERSARY', $val);
1519: }
1520: break;
1521:
1522: case 'spouse':
1523: if (!$fields || isset($fields['X-SPOUSE'])) {
1524: $vcard->setAttribute('X-SPOUSE', $val);
1525: }
1526: break;
1527:
1528: case 'children':
1529: if (!$fields || isset($fields['X-CHILDREN'])) {
1530: $vcard->setAttribute('X-CHILDREN', $val);
1531: }
1532: break;
1533:
1534: case 'website':
1535: if ($fields && !isset($fields['URL'])) {
1536: break;
1537: }
1538: $vcard->setAttribute('URL', $val);
1539: break;
1540:
1541: case 'homeWebsite':
1542: if ($fields &&
1543: (!isset($fields['URL']) ||
1544: (isset($fields['URL']->Params['TYPE']) &&
1545: !$this->_hasValEnum($fields['URL']->Params['TYPE']->ValEnum, 'HOME')))) {
1546: break;
1547: }
1548: if ($version == '2.1') {
1549: $vcard->setAttribute('URL', $val, array('HOME' => null));
1550: } else {
1551: $vcard->setAttribute('URL', $val, array('TYPE' => 'HOME'));
1552: }
1553: break;
1554:
1555: case 'workWebsite':
1556: if ($fields &&
1557: (!isset($fields['URL']) ||
1558: (isset($fields['URL']->Params['TYPE']) &&
1559: !$this->_hasValEnum($fields['URL']->Params['TYPE']->ValEnum, 'WORK')))) {
1560: break;
1561: }
1562: if ($version == '2.1') {
1563: $vcard->setAttribute('URL', $val, array('WORK' => null));
1564: } else {
1565: $vcard->setAttribute('URL', $val, array('TYPE' => 'WORK'));
1566: }
1567: break;
1568:
1569: case 'birthday':
1570: if ($fields && !isset($fields['BDAY'])) {
1571: break;
1572: }
1573: $vcard->setAttribute('BDAY', $val);
1574: break;
1575:
1576: case 'timezone':
1577: if ($fields && !isset($fields['TZ'])) {
1578: break;
1579: }
1580: $vcard->setAttribute('TZ', $val, array('VALUE' => 'text'));
1581: break;
1582:
1583: case 'latitude':
1584: if ($fields && !isset($fields['GEO'])) {
1585: break;
1586: }
1587: if (isset($hash['longitude'])) {
1588: $vcard->setAttribute('GEO',
1589: array('latitude' => $val,
1590: 'longitude' => $hash['longitude']));
1591: }
1592: break;
1593:
1594: case 'homeLatitude':
1595: if ($fields &&
1596: (!isset($fields['GEO']) ||
1597: (isset($fields['GEO']->Params['TYPE']) &&
1598: !$this->_hasValEnum($fields['GEO']->Params['TYPE']->ValEnum, 'HOME')))) {
1599: break;
1600: }
1601: if (isset($hash['homeLongitude'])) {
1602: if ($version == '2.1') {
1603: $vcard->setAttribute('GEO',
1604: array('latitude' => $val,
1605: 'longitude' => $hash['homeLongitude']),
1606: array('HOME' => null));
1607: } else {
1608: $vcard->setAttribute('GEO',
1609: array('latitude' => $val,
1610: 'longitude' => $hash['homeLongitude']),
1611: array('TYPE' => 'HOME'));
1612: }
1613: }
1614: break;
1615:
1616: case 'workLatitude':
1617: if ($fields &&
1618: (!isset($fields['GEO']) ||
1619: (isset($fields['GEO']->Params['TYPE']) &&
1620: !$this->_hasValEnum($fields['GEO']->Params['TYPE']->ValEnum, 'HOME')))) {
1621: break;
1622: }
1623: if (isset($hash['workLongitude'])) {
1624: if ($version == '2.1') {
1625: $vcard->setAttribute('GEO',
1626: array('latitude' => $val,
1627: 'longitude' => $hash['workLongitude']),
1628: array('WORK' => null));
1629: } else {
1630: $vcard->setAttribute('GEO',
1631: array('latitude' => $val,
1632: 'longitude' => $hash['workLongitude']),
1633: array('TYPE' => 'WORK'));
1634: }
1635: }
1636: break;
1637:
1638: case 'photo':
1639: case 'logo':
1640: $name = Horde_String::upper($key);
1641: $params = array();
1642: if (strlen($val)) {
1643: $params['ENCODING'] = 'b';
1644: }
1645: if (isset($hash[$key . 'type'])) {
1646: $params['TYPE'] = $hash[$key . 'type'];
1647: }
1648: if ($fields &&
1649: (!isset($fields[$name]) ||
1650: (isset($params['TYPE']) &&
1651: isset($fields[$name]->Params['TYPE']) &&
1652: !$this->_hasValEnum($fields[$name]->Params['TYPE']->ValEnum, $params['TYPE'])))) {
1653: break;
1654: }
1655: $vcard->setAttribute($name,
1656: base64_encode($val),
1657: $params);
1658: break;
1659: }
1660: }
1661:
1662:
1663: if (!isset($hash['lastname']) && isset($hash['name'])) {
1664: $this->_guessName($hash);
1665: }
1666:
1667: $a = array(
1668: Horde_Icalendar_Vcard::N_FAMILY => isset($hash['lastname']) ? $hash['lastname'] : '',
1669: Horde_Icalendar_Vcard::N_GIVEN => isset($hash['firstname']) ? $hash['firstname'] : '',
1670: Horde_Icalendar_Vcard::N_ADDL => isset($hash['middlenames']) ? $hash['middlenames'] : '',
1671: Horde_Icalendar_Vcard::N_PREFIX => isset($hash['namePrefix']) ? $hash['namePrefix'] : '',
1672: Horde_Icalendar_Vcard::N_SUFFIX => isset($hash['nameSuffix']) ? $hash['nameSuffix'] : '',
1673: );
1674: $val = implode(';', $a);
1675: if (!$fields || isset($fields['N'])) {
1676: $vcard->setAttribute('N', $val, Horde_Mime::is8bit($val) ? $charset : array(), false, $a);
1677: }
1678:
1679: if (!$formattedname && (!$fields || isset($fields['FN']))) {
1680: if ($object->getValue('name')) {
1681: $val = $object->getValue('name');
1682: } elseif (!empty($this->alternativeName) &&
1683: isset($hash[$this->alternativeName])) {
1684: $val = $hash[$this->alternativeName];
1685: } else {
1686: $val = '';
1687: }
1688: $vcard->setAttribute('FN', $val, Horde_Mime::is8bit($val) ? $charset : array());
1689: }
1690:
1691: $org = array();
1692: if (!empty($hash['company']) ||
1693: (!$skipEmpty && array_key_exists('company', $hash))) {
1694: $org[] = $hash['company'];
1695: }
1696: if (!empty($hash['department']) ||
1697: (!$skipEmpty && array_key_exists('department', $hash))) {
1698: $org[] = $hash['department'];
1699: }
1700: if (count($org) && (!$fields || isset($fields['ORG']))) {
1701: $val = implode(';', $org);
1702: $vcard->setAttribute('ORG', $val, Horde_Mime::is8bit($val) ? $charset : array(), false, $org);
1703: }
1704:
1705: if ((!$fields || isset($fields['ADR'])) &&
1706: (!empty($hash['commonAddress']) ||
1707: !empty($hash['commonStreet']) ||
1708: !empty($hash['commonPOBox']) ||
1709: !empty($hash['commonExtended']) ||
1710: !empty($hash['commonCity']) ||
1711: !empty($hash['commonProvince']) ||
1712: !empty($hash['commonPostalCode']) ||
1713: !empty($hash['commonCountry']) ||
1714: (!$skipEmpty &&
1715: (array_key_exists('commonAddress', $hash) ||
1716: array_key_exists('commonStreet', $hash) ||
1717: array_key_exists('commonPOBox', $hash) ||
1718: array_key_exists('commonExtended', $hash) ||
1719: array_key_exists('commonCity', $hash) ||
1720: array_key_exists('commonProvince', $hash) ||
1721: array_key_exists('commonPostalCode', $hash) ||
1722: array_key_exists('commonCountry', $hash))))) {
1723: 1724: 1725: 1726:
1727: if (isset($hash['commonAddress']) &&
1728: !isset($hash['commonStreet'])) {
1729: $hash['commonStreet'] = $hash['commonAddress'];
1730: }
1731: $a = array(
1732: Horde_Icalendar_Vcard::ADR_POB => isset($hash['commonPOBox'])
1733: ? $hash['commonPOBox'] : '',
1734: Horde_Icalendar_Vcard::ADR_EXTEND => isset($hash['commonExtended'])
1735: ? $hash['commonExtended'] : '',
1736: Horde_Icalendar_Vcard::ADR_STREET => isset($hash['commonStreet'])
1737: ? $hash['commonStreet'] : '',
1738: Horde_Icalendar_Vcard::ADR_LOCALITY => isset($hash['commonCity'])
1739: ? $hash['commonCity'] : '',
1740: Horde_Icalendar_Vcard::ADR_REGION => isset($hash['commonProvince'])
1741: ? $hash['commonProvince'] : '',
1742: Horde_Icalendar_Vcard::ADR_POSTCODE => isset($hash['commonPostalCode'])
1743: ? $hash['commonPostalCode'] : '',
1744: Horde_Icalendar_Vcard::ADR_COUNTRY => isset($hash['commonCountry'])
1745: ? Horde_Nls::getCountryISO($hash['commonCountry']) : '',
1746: );
1747:
1748: $val = implode(';', $a);
1749: if ($version == '2.1') {
1750: $params = array();
1751: if (Horde_Mime::is8bit($val)) {
1752: $params['CHARSET'] = 'UTF-8';
1753: }
1754: } else {
1755: $params = array('TYPE' => '');
1756: }
1757: $vcard->setAttribute('ADR', $val, $params, true, $a);
1758: }
1759:
1760: if ((!$fields ||
1761: (isset($fields['ADR']) &&
1762: (!isset($fields['ADR']->Params['TYPE']) ||
1763: $this->_hasValEnum($fields['ADR']->Params['TYPE']->ValEnum, 'HOME')))) &&
1764: (!empty($hash['homeAddress']) ||
1765: !empty($hash['homeStreet']) ||
1766: !empty($hash['homePOBox']) ||
1767: !empty($hash['homeExtended']) ||
1768: !empty($hash['homeCity']) ||
1769: !empty($hash['homeProvince']) ||
1770: !empty($hash['homePostalCode']) ||
1771: !empty($hash['homeCountry']) ||
1772: (!$skipEmpty &&
1773: (array_key_exists('homeAddress', $hash) ||
1774: array_key_exists('homeStreet', $hash) ||
1775: array_key_exists('homePOBox', $hash) ||
1776: array_key_exists('homeExtended', $hash) ||
1777: array_key_exists('homeCity', $hash) ||
1778: array_key_exists('homeProvince', $hash) ||
1779: array_key_exists('homePostalCode', $hash) ||
1780: array_key_exists('homeCountry', $hash))))) {
1781: if (isset($hash['homeAddress']) && !isset($hash['homeStreet'])) {
1782: $hash['homeStreet'] = $hash['homeAddress'];
1783: }
1784: $a = array(
1785: Horde_Icalendar_Vcard::ADR_POB => isset($hash['homePOBox'])
1786: ? $hash['homePOBox'] : '',
1787: Horde_Icalendar_Vcard::ADR_EXTEND => isset($hash['homeExtended'])
1788: ? $hash['homeExtended'] : '',
1789: Horde_Icalendar_Vcard::ADR_STREET => isset($hash['homeStreet'])
1790: ? $hash['homeStreet'] : '',
1791: Horde_Icalendar_Vcard::ADR_LOCALITY => isset($hash['homeCity'])
1792: ? $hash['homeCity'] : '',
1793: Horde_Icalendar_Vcard::ADR_REGION => isset($hash['homeProvince'])
1794: ? $hash['homeProvince'] : '',
1795: Horde_Icalendar_Vcard::ADR_POSTCODE => isset($hash['homePostalCode'])
1796: ? $hash['homePostalCode'] : '',
1797: Horde_Icalendar_Vcard::ADR_COUNTRY => isset($hash['homeCountry'])
1798: ? Horde_Nls::getCountryISO($hash['homeCountry']) : '',
1799: );
1800:
1801: $val = implode(';', $a);
1802: if ($version == '2.1') {
1803: $params = array('HOME' => null);
1804: if (Horde_Mime::is8bit($val)) {
1805: $params['CHARSET'] = 'UTF-8';
1806: }
1807: } else {
1808: $params = array('TYPE' => 'HOME');
1809: }
1810: $vcard->setAttribute('ADR', $val, $params, true, $a);
1811: }
1812:
1813: if ((!$fields ||
1814: (isset($fields['ADR']) &&
1815: (!isset($fields['ADR']->Params['TYPE']) ||
1816: $this->_hasValEnum($fields['ADR']->Params['TYPE']->ValEnum, 'WORK')))) &&
1817: (!empty($hash['workAddress']) ||
1818: !empty($hash['workStreet']) ||
1819: !empty($hash['workPOBox']) ||
1820: !empty($hash['workExtended']) ||
1821: !empty($hash['workCity']) ||
1822: !empty($hash['workProvince']) ||
1823: !empty($hash['workPostalCode']) ||
1824: !empty($hash['workCountry']) ||
1825: (!$skipEmpty &&
1826: (array_key_exists('workAddress', $hash) ||
1827: array_key_exists('workStreet', $hash) ||
1828: array_key_exists('workPOBox', $hash) ||
1829: array_key_exists('workExtended', $hash) ||
1830: array_key_exists('workCity', $hash) ||
1831: array_key_exists('workProvince', $hash) ||
1832: array_key_exists('workPostalCode', $hash) ||
1833: array_key_exists('workCountry', $hash))))) {
1834: if (isset($hash['workAddress']) && !isset($hash['workStreet'])) {
1835: $hash['workStreet'] = $hash['workAddress'];
1836: }
1837: $a = array(
1838: Horde_Icalendar_Vcard::ADR_POB => isset($hash['workPOBox'])
1839: ? $hash['workPOBox'] : '',
1840: Horde_Icalendar_Vcard::ADR_EXTEND => isset($hash['workExtended'])
1841: ? $hash['workExtended'] : '',
1842: Horde_Icalendar_Vcard::ADR_STREET => isset($hash['workStreet'])
1843: ? $hash['workStreet'] : '',
1844: Horde_Icalendar_Vcard::ADR_LOCALITY => isset($hash['workCity'])
1845: ? $hash['workCity'] : '',
1846: Horde_Icalendar_Vcard::ADR_REGION => isset($hash['workProvince'])
1847: ? $hash['workProvince'] : '',
1848: Horde_Icalendar_Vcard::ADR_POSTCODE => isset($hash['workPostalCode'])
1849: ? $hash['workPostalCode'] : '',
1850: Horde_Icalendar_Vcard::ADR_COUNTRY => isset($hash['workCountry'])
1851: ? Horde_Nls::getCountryISO($hash['workCountry']) : '',
1852: );
1853:
1854: $val = implode(';', $a);
1855: if ($version == '2.1') {
1856: $params = array('WORK' => null);
1857: if (Horde_Mime::is8bit($val)) {
1858: $params['CHARSET'] = 'UTF-8';
1859: }
1860: } else {
1861: $params = array('TYPE' => 'WORK');
1862: }
1863: $vcard->setAttribute('ADR', $val, $params, true, $a);
1864: }
1865:
1866: return $vcard;
1867: }
1868:
1869: 1870: 1871: 1872: 1873: 1874: 1875: 1876: 1877:
1878: protected function _hasValEnum($valEnum, $type)
1879: {
1880: foreach (array_keys($valEnum) as $key) {
1881: if (in_array($type, explode(',', $key))) {
1882: return true;
1883: }
1884: }
1885: return false;
1886: }
1887:
1888: 1889: 1890: 1891: 1892: 1893: 1894: 1895: 1896: 1897: 1898:
1899: public function toHash(Horde_Icalendar_Vcard $vcard)
1900: {
1901: $hash = array();
1902: $attr = $vcard->getAllAttributes();
1903: foreach ($attr as $item) {
1904: switch ($item['name']) {
1905: case 'FN':
1906: $hash['name'] = $item['value'];
1907: break;
1908:
1909: case 'N':
1910: $name = $item['values'];
1911: if (!empty($name[Horde_Icalendar_Vcard::N_FAMILY])) {
1912: $hash['lastname'] = $name[Horde_Icalendar_Vcard::N_FAMILY];
1913: }
1914: if (!empty($name[Horde_Icalendar_Vcard::N_GIVEN])) {
1915: $hash['firstname'] = $name[Horde_Icalendar_Vcard::N_GIVEN];
1916: }
1917: if (!empty($name[Horde_Icalendar_Vcard::N_ADDL])) {
1918: $hash['middlenames'] = $name[Horde_Icalendar_Vcard::N_ADDL];
1919: }
1920: if (!empty($name[Horde_Icalendar_Vcard::N_PREFIX])) {
1921: $hash['namePrefix'] = $name[Horde_Icalendar_Vcard::N_PREFIX];
1922: }
1923: if (!empty($name[Horde_Icalendar_Vcard::N_SUFFIX])) {
1924: $hash['nameSuffix'] = $name[Horde_Icalendar_Vcard::N_SUFFIX];
1925: }
1926: break;
1927:
1928: case 'NICKNAME':
1929: case 'X-EPOCSECONDNAME':
1930: $hash['nickname'] = $item['value'];
1931: $hash['alias'] = $item['value'];
1932: break;
1933:
1934:
1935: case 'LABEL':
1936: if (isset($item['params']['HOME']) && !isset($hash['homeAddress'])) {
1937: $hash['homeAddress'] = $item['value'];
1938: } elseif (isset($item['params']['WORK']) && !isset($hash['workAddress'])) {
1939: $hash['workAddress'] = $item['value'];
1940: } elseif (!isset($hash['commonAddress'])) {
1941: $hash['commonAddress'] = $item['value'];
1942: }
1943: break;
1944:
1945: case 'ADR':
1946: if (isset($item['params']['TYPE'])) {
1947: if (!is_array($item['params']['TYPE'])) {
1948: $item['params']['TYPE'] = array($item['params']['TYPE']);
1949: }
1950: } else {
1951: $item['params']['TYPE'] = array();
1952: if (isset($item['params']['WORK'])) {
1953: $item['params']['TYPE'][] = 'WORK';
1954: }
1955: if (isset($item['params']['HOME'])) {
1956: $item['params']['TYPE'][] = 'HOME';
1957: }
1958: if (count($item['params']['TYPE']) == 0) {
1959: $item['params']['TYPE'][] = 'COMMON';
1960: }
1961: }
1962:
1963: $address = $item['values'];
1964: foreach ($item['params']['TYPE'] as $adr) {
1965: switch (Horde_String::upper($adr)) {
1966: case 'HOME':
1967: $prefix = 'home';
1968: break;
1969:
1970: case 'WORK':
1971: $prefix = 'work';
1972: break;
1973:
1974: default:
1975: $prefix = 'common';
1976: }
1977:
1978: if (isset($hash[$prefix . 'Address'])) {
1979: continue;
1980: }
1981:
1982: $hash[$prefix . 'Address'] = '';
1983:
1984: if (!empty($address[Horde_Icalendar_Vcard::ADR_STREET])) {
1985: $hash[$prefix . 'Street'] = $address[Horde_Icalendar_Vcard::ADR_STREET];
1986: $hash[$prefix . 'Address'] .= $hash[$prefix . 'Street'] . "\n";
1987: }
1988: if (!empty($address[Horde_Icalendar_Vcard::ADR_EXTEND])) {
1989: $hash[$prefix . 'Extended'] = $address[Horde_Icalendar_Vcard::ADR_EXTEND];
1990: $hash[$prefix . 'Address'] .= $hash[$prefix . 'Extended'] . "\n";
1991: }
1992: if (!empty($address[Horde_Icalendar_Vcard::ADR_POB])) {
1993: $hash[$prefix . 'POBox'] = $address[Horde_Icalendar_Vcard::ADR_POB];
1994: $hash[$prefix . 'Address'] .= $hash[$prefix . 'POBox'] . "\n";
1995: }
1996: if (!empty($address[Horde_Icalendar_Vcard::ADR_LOCALITY])) {
1997: $hash[$prefix . 'City'] = $address[Horde_Icalendar_Vcard::ADR_LOCALITY];
1998: $hash[$prefix . 'Address'] .= $hash[$prefix . 'City'];
1999: }
2000: if (!empty($address[Horde_Icalendar_Vcard::ADR_REGION])) {
2001: $hash[$prefix . 'Province'] = $address[Horde_Icalendar_Vcard::ADR_REGION];
2002: $hash[$prefix . 'Address'] .= ', ' . $hash[$prefix . 'Province'];
2003: }
2004: if (!empty($address[Horde_Icalendar_Vcard::ADR_POSTCODE])) {
2005: $hash[$prefix . 'PostalCode'] = $address[Horde_Icalendar_Vcard::ADR_POSTCODE];
2006: $hash[$prefix . 'Address'] .= ' ' . $hash[$prefix . 'PostalCode'];
2007: }
2008: if (!empty($address[Horde_Icalendar_Vcard::ADR_COUNTRY])) {
2009: include 'Horde/Nls/Countries.php';
2010: $country = array_search($address[Horde_Icalendar_Vcard::ADR_COUNTRY], $countries);
2011: if ($country === false) {
2012: $country = $address[Horde_Icalendar_Vcard::ADR_COUNTRY];
2013: }
2014: $hash[$prefix . 'Country'] = $country;
2015: $hash[$prefix . 'Address'] .= "\n" . $address[Horde_Icalendar_Vcard::ADR_COUNTRY];
2016: }
2017:
2018: $hash[$prefix . 'Address'] = trim($hash[$prefix . 'Address']);
2019: }
2020: break;
2021:
2022: case 'TZ':
2023:
2024: if (!isset($item['params']['VALUE']) ||
2025: Horde_String::lower($item['params']['VALUE']) != 'text') {
2026: break;
2027: }
2028: $timezones = explode(';', $item['value']);
2029: $available_timezones = Horde_Nls::getTimezones();
2030: foreach ($timezones as $timezone) {
2031: $timezone = trim($timezone);
2032: if (isset($available_timezones[$timezone])) {
2033: $hash['timezone'] = $timezone;
2034: break 2;
2035: }
2036: }
2037: break;
2038:
2039: case 'GEO':
2040: if (isset($item['params']['HOME'])) {
2041: $hash['homeLatitude'] = $item['value']['latitude'];
2042: $hash['homeLongitude'] = $item['value']['longitude'];
2043: } elseif (isset($item['params']['WORK'])) {
2044: $hash['workLatitude'] = $item['value']['latitude'];
2045: $hash['workLongitude'] = $item['value']['longitude'];
2046: } else {
2047: $hash['latitude'] = $item['value']['latitude'];
2048: $hash['longitude'] = $item['value']['longitude'];
2049: }
2050: break;
2051:
2052: case 'TEL':
2053: if (isset($item['params']['FAX'])) {
2054: if (isset($item['params']['WORK']) &&
2055: !isset($hash['workFax'])) {
2056: $hash['workFax'] = $item['value'];
2057: } elseif (isset($item['params']['HOME']) &&
2058: !isset($hash['homeFax'])) {
2059: $hash['homeFax'] = $item['value'];
2060: } elseif (!isset($hash['fax'])) {
2061: $hash['fax'] = $item['value'];
2062: }
2063: } elseif (isset($item['params']['PAGER']) &&
2064: !isset($hash['pager'])) {
2065: $hash['pager'] = $item['value'];
2066: } elseif (isset($item['params']['TYPE'])) {
2067: if (!is_array($item['params']['TYPE'])) {
2068: $item['params']['TYPE'] = array($item['params']['TYPE']);
2069: }
2070:
2071: if (in_array('CELL', $item['params']['TYPE'])) {
2072: if (in_array('HOME', $item['params']['TYPE']) &&
2073: !isset($hash['homeCellPhone'])) {
2074: $hash['homeCellPhone'] = $item['value'];
2075: } elseif (in_array('WORK', $item['params']['TYPE']) &&
2076: !isset($hash['workCellPhone'])) {
2077: $hash['workCellPhone'] = $item['value'];
2078: } elseif (!isset($hash['cellPhone'])) {
2079: $hash['cellPhone'] = $item['value'];
2080: }
2081: } elseif (in_array('FAX', $item['params']['TYPE'])) {
2082: if (in_array('HOME', $item['params']['TYPE']) &&
2083: !isset($hash['homeFax'])) {
2084: $hash['homeFax'] = $item['value'];
2085: } elseif (in_array('WORK', $item['params']['TYPE']) &&
2086: !isset($hash['workFax'])) {
2087: $hash['workFax'] = $item['value'];
2088: } elseif (!isset($hash['fax'])) {
2089: $hash['fax'] = $item['value'];
2090: }
2091: } elseif (in_array('VIDEO', $item['params']['TYPE'])) {
2092: if (in_array('HOME', $item['params']['TYPE']) &&
2093: !isset($hash['homeVideoCall'])) {
2094: $hash['homeVideoCall'] = $item['value'];
2095: } elseif (in_array('WORK', $item['params']['TYPE']) &&
2096: !isset($hash['workVideoCall'])) {
2097: $hash['workVideoCall'] = $item['value'];
2098: } elseif (!isset($hash['videoCall'])) {
2099: $hash['videoCall'] = $item['value'];
2100: }
2101: } elseif (in_array('PAGER', $item['params']['TYPE']) &&
2102: !isset($hash['pager'])) {
2103: $hash['pager'] = $item['value'];
2104: } elseif (in_array('WORK', $item['params']['TYPE']) &&
2105: !isset($hash['workPhone'])) {
2106: $hash['workPhone'] = $item['value'];
2107: } elseif (in_array('HOME', $item['params']['TYPE']) &&
2108: !isset($hash['homePhone'])) {
2109: $hash['homePhone'] = $item['value'];
2110: }
2111: } elseif (isset($item['params']['CELL'])) {
2112: if (isset($item['params']['WORK']) &&
2113: !isset($hash['workCellPhone'])) {
2114: $hash['workCellPhone'] = $item['value'];
2115: } elseif (isset($item['params']['HOME']) &&
2116: !isset($hash['homeCellPhone'])) {
2117: $hash['homeCellPhone'] = $item['value'];
2118: } elseif (!isset($hash['cellPhone'])) {
2119: $hash['cellPhone'] = $item['value'];
2120: }
2121: } elseif (isset($item['params']['VIDEO'])) {
2122: if (isset($item['params']['WORK']) &&
2123: !isset($hash['workVideoCall'])) {
2124: $hash['workVideoCall'] = $item['value'];
2125: } elseif (isset($item['params']['HOME']) &&
2126: !isset($hash['homeVideoCall'])) {
2127: $hash['homeVideoCall'] = $item['value'];
2128: } elseif (!isset($hash['homeVideoCall'])) {
2129: $hash['videoCall'] = $item['value'];
2130: }
2131: } elseif (count($item['params']) <= 1 ||
2132: isset($item['params']['VOICE'])) {
2133:
2134:
2135: if (isset($item['params']['WORK']) &&
2136: !isset($hash['workPhone'])) {
2137: $hash['workPhone'] = $item['value'];
2138: } elseif (isset($item['params']['HOME']) &&
2139: !isset($hash['homePhone'])) {
2140: $hash['homePhone'] = $item['value'];
2141: } elseif ((count($item['params']) == 0 ||
2142: (count($item['params']) == 1 &&
2143: isset($item['params']['VOICE']))) &&
2144: !isset($hash['phone'])) {
2145: $hash['phone'] = $item['value'];
2146: }
2147: }
2148: break;
2149:
2150: case 'EMAIL':
2151: $email_set = false;
2152: if (isset($item['params']['HOME']) &&
2153: (!isset($hash['homeEmail']) ||
2154: isset($item['params']['PREF']))) {
2155: $hash['homeEmail'] = Horde_Icalendar_Vcard::getBareEmail($item['value']);
2156: $email_set = true;
2157: } elseif (isset($item['params']['WORK']) &&
2158: (!isset($hash['workEmail']) ||
2159: isset($item['params']['PREF']))) {
2160: $hash['workEmail'] = Horde_Icalendar_Vcard::getBareEmail($item['value']);
2161: $email_set = true;
2162: } elseif (isset($item['params']['TYPE'])) {
2163: if (!is_array($item['params']['TYPE'])) {
2164: $item['params']['TYPE'] = array($item['params']['TYPE']);
2165: }
2166: if (in_array('HOME', $item['params']['TYPE']) &&
2167: (!isset($hash['homeEmail']) ||
2168: in_array('PREF', $item['params']['TYPE']))) {
2169: $hash['homeEmail'] = Horde_Icalendar_Vcard::getBareEmail($item['value']);
2170: $email_set = true;
2171: } elseif (in_array('WORK', $item['params']['TYPE']) &&
2172: (!isset($hash['workEmail']) ||
2173: in_array('PREF', $item['params']['TYPE']))) {
2174: $hash['workEmail'] = Horde_Icalendar_Vcard::getBareEmail($item['value']);
2175: $email_set = true;
2176: }
2177: }
2178: if (!$email_set &&
2179: (!isset($hash['email']) ||
2180: isset($item['params']['PREF']))) {
2181: $hash['email'] = Horde_Icalendar_Vcard::getBareEmail($item['value']);
2182: }
2183:
2184: if (!isset($hash['emails'])) {
2185: $hash['emails'] = Horde_Icalendar_Vcard::getBareEmail($item['value']);
2186: } else {
2187: $hash['emails'] .= ', ' . Horde_Icalendar_Vcard::getBareEmail($item['value']);
2188: }
2189: break;
2190:
2191: case 'TITLE':
2192: $hash['title'] = $item['value'];
2193: break;
2194:
2195: case 'ROLE':
2196: $hash['role'] = $item['value'];
2197: break;
2198:
2199: case 'ORG':
2200:
2201:
2202:
2203: $hash['company'] = !empty($item['values'][0]) ? $item['values'][0] : '';
2204: $hash['department'] = !empty($item['values'][1]) ? $item['values'][1] : '';
2205: break;
2206:
2207: case 'NOTE':
2208: $hash['notes'] = $item['value'];
2209: break;
2210:
2211: case 'CATEGORIES':
2212: $hash['businessCategory'] = $hash['category'] = str_replace('\; ', ';', $item['value']);
2213: break;
2214:
2215: case 'URL':
2216: if (isset($item['params']['HOME']) &&
2217: !isset($hash['homeWebsite'])) {
2218: $hash['homeWebsite'] = $item['value'];
2219: } elseif (isset($item['params']['WORK']) &&
2220: !isset($hash['workWebsite'])) {
2221: $hash['workWebsite'] = $item['value'];
2222: } elseif (!isset($hash['website'])) {
2223: $hash['website'] = $item['value'];
2224: }
2225: break;
2226:
2227: case 'BDAY':
2228: if (empty($item['value'])) {
2229: $hash['birthday'] = '';
2230: } else {
2231: $hash['birthday'] = $item['value']['year'] . '-' . $item['value']['month'] . '-' . $item['value']['mday'];
2232: }
2233: break;
2234:
2235: case 'PHOTO':
2236: case 'LOGO':
2237: if (isset($item['params']['VALUE']) &&
2238: Horde_String::lower($item['params']['VALUE']) == 'uri') {
2239:
2240: break;
2241: }
2242: if (!isset($item['params']['ENCODING']) ||
2243: (Horde_String::lower($item['params']['ENCODING']) != 'b' &&
2244: Horde_String::upper($item['params']['ENCODING']) != 'BASE64')) {
2245:
2246: break;
2247: }
2248: $type = Horde_String::lower($item['name']);
2249: $hash[$type] = base64_decode($item['value']);
2250: if (isset($item['params']['TYPE'])) {
2251: $hash[$type . 'type'] = $item['params']['TYPE'];
2252: }
2253: break;
2254:
2255: case 'X-SIP':
2256: if (isset($item['params']['POC']) &&
2257: !isset($hash['ptt'])) {
2258: $hash['ptt'] = $item['value'];
2259: } elseif (isset($item['params']['VOIP']) &&
2260: !isset($hash['voip'])) {
2261: $hash['voip'] = $item['value'];
2262: } elseif (isset($item['params']['SWIS']) &&
2263: !isset($hash['shareView'])) {
2264: $hash['shareView'] = $item['value'];
2265: } elseif (!isset($hash['sip'])) {
2266: $hash['sip'] = $item['value'];
2267: }
2268: break;
2269:
2270: case 'X-WV-ID':
2271: $hash['instantMessenger'] = $item['value'];
2272: break;
2273:
2274: case 'X-ANNIVERSARY':
2275: if (empty($item['value'])) {
2276: $hash['anniversary'] = '';
2277: } else {
2278: $hash['anniversary'] = $item['value']['year'] . '-' . $item['value']['month'] . '-' . $item['value']['mday'];
2279: }
2280: break;
2281:
2282: case 'X-CHILDREN':
2283: $hash['children'] = $item['value'];
2284: break;
2285:
2286: case 'X-SPOUSE':
2287: $hash['spouse'] = $item['value'];
2288: break;
2289: }
2290: }
2291:
2292:
2293: if (empty($hash['name'])) {
2294: 2295:
2296: if (isset($this->map['name']) &&
2297: is_array($this->map['name']) &&
2298: !empty($this->map['name']['attribute'])) {
2299: $fieldarray = array();
2300: foreach ($this->map['name']['fields'] as $mapfields) {
2301: $fieldarray[] = isset($hash[$mapfields]) ?
2302: $hash[$mapfields] : '';
2303: }
2304: $hash['name'] = Turba::formatCompositeField($this->map['name']['format'], $fieldarray);
2305: } else {
2306: $hash['name'] = isset($hash['firstname']) ? $hash['firstname'] : '';
2307: if (!empty($hash['lastname'])) {
2308: $hash['name'] .= ' ' . $hash['lastname'];
2309: }
2310: $hash['name'] = trim($hash['name']);
2311: }
2312: }
2313:
2314: return $hash;
2315: }
2316:
2317: 2318: 2319: 2320: 2321: 2322: 2323:
2324: public function toASContact(Turba_Object $object)
2325: {
2326: $message = new Horde_ActiveSync_Message_Contact(array('logger' => $GLOBALS['injector']->getInstance('Horde_Log_Logger')));
2327: $hash = $object->getAttributes();
2328: if (!isset($hash['lastname']) && isset($hash['name'])) {
2329: $this->_guessName($hash);
2330: }
2331:
2332:
2333:
2334:
2335:
2336:
2337: if (!empty($hash['commonAddress'])) {
2338: if (!isset($hash['commonStreet'])) {
2339: $hash['commonStreet'] = $hash['commonHome'];
2340: }
2341: foreach (array('Address', 'Street', 'POBox', 'Extended', 'City', 'Province', 'PostalCode', 'Country') as $field) {
2342: $hash['home' . $field] = $hash['common' . $field];
2343: }
2344: } else {
2345: if (isset($hash['homeAddress']) && !isset($hash['homeStreet'])) {
2346: $hash['homeStreet'] = $hash['homeAddress'];
2347: }
2348: if (isset($hash['workAddress']) && !isset($hash['workStreet'])) {
2349: $hash['workStreet'] = $hash['workAddress'];
2350: }
2351: }
2352:
2353: $haveDecodeHook = Horde::hookExists('decode_attribute', 'turba');
2354: foreach ($hash as $field => $value) {
2355: if ($haveDecodeHook) {
2356: try {
2357: $value = Horde::callHook(
2358: 'decode_attribute',
2359: array($attribute, $this->attributes[$attribute], $this),
2360: 'turba');
2361: } catch (Turba_Exception $e) {
2362: Horde::logMessage($e);
2363: }
2364: }
2365: switch ($field) {
2366: case 'name':
2367: $message->fileas = $value;
2368: break;
2369:
2370: case 'lastname':
2371: $message->lastname = $value;
2372: break;
2373:
2374: case 'firstname':
2375: $message->firstname = $value;
2376: break;
2377:
2378: case 'middlenames':
2379: $message->middlename = $value;
2380: break;
2381:
2382: case 'namePrefix':
2383: $message->title = $value;
2384: break;
2385:
2386: case 'alias':
2387: case 'nickname':
2388: try {
2389: $message->nickname = $value;
2390: } catch (InvalidArgumentException $e) {
2391: }
2392: break;
2393:
2394: case 'nameSuffix':
2395: $message->suffix = $value;
2396: break;
2397:
2398: case 'photo':
2399: $message->picture = base64_encode($value);
2400: break;
2401:
2402: case 'homeStreet':
2403: $message->homestreet = $hash['homeStreet'];
2404: break;
2405:
2406: case 'homeCity':
2407: $message->homecity = $hash['homeCity'];
2408: break;
2409:
2410: case 'homeProvince':
2411: $message->homestate = $hash['homeProvince'];
2412: break;
2413:
2414: case 'homePostalCode':
2415: $message->homepostalcode = $hash['homePostalCode'];
2416: break;
2417:
2418: case 'homeCountry':
2419: $message->homecountry = !empty($hash['homeCountry']) ? Horde_Nls::getCountryISO($hash['homeCountry']) : null;
2420: break;
2421:
2422: case 'otherStreet':
2423: $message->otherstreet = $hash['otherStreet'];
2424: break;
2425:
2426: case 'otherCity':
2427: $message->othercity = $hash['otherCity'];
2428: break;
2429:
2430: case 'otherProvince':
2431: $message->otherstate = $hash['otherProvince'];
2432: break;
2433:
2434: case 'otherPostalCode':
2435: $message->otherpostalcode = $hash['otherPostalCode'];
2436: break;
2437:
2438: case 'otherCountry':
2439: $message->othercountry = !empty($hash['otherCountry']) ? Horde_Nls::getCountryISO($hash['otherCountry']) : null;
2440: break;
2441:
2442: case 'workStreet':
2443: $message->businessstreet = $hash['workStreet'];
2444: break;
2445:
2446: case 'workCity':
2447: $message->businesscity = $hash['workCity'];
2448: break;
2449:
2450: case 'workProvince':
2451: $message->businessstate = $hash['workProvince'];
2452: break;
2453:
2454: case 'workPostalCode':
2455: $message->businesspostalcode = $hash['workPostalCode'];
2456: break;
2457:
2458: case 'workCountry':
2459: $message->businesscountry = !empty($hash['workCountry']) ? Horde_Nls::getCountryISO($hash['workCountry']) : null;
2460:
2461: case 'homePhone':
2462:
2463: $message->homephonenumber = $hash['homePhone'];
2464: break;
2465:
2466: case 'homePhone2':
2467: $message->home2phonenumber = $hash['homePhone2'];
2468: break;
2469:
2470: case 'cellPhone':
2471: $message->mobilephonenumber = $hash['cellPhone'];
2472: break;
2473:
2474: case 'carPhone':
2475: $message->carphonenumber = $hash['carPhone'];
2476: break;
2477:
2478: case 'fax':
2479: $message->businessfaxnumber = $hash['fax'];
2480: break;
2481:
2482: case 'homeFax':
2483: $message->homefaxnumber = $hash['homeFax'];
2484: break;
2485:
2486: case 'workPhone':
2487: $message->businessphonenumber = $hash['workPhone'];
2488: break;
2489:
2490: case 'workPhone2':
2491: $message->business2phonenumber = $hash['workPhone2'];
2492: break;
2493:
2494: case 'assistPhone':
2495: $message->assistnamephonenumber = $hash['assistPhone'];
2496: break;
2497:
2498: case 'companyPhone':
2499: $message->companymainphone = $hash['companyPhone'];
2500: break;
2501:
2502: case 'radioPhone':
2503: $message->radiophonenumber = $hash['radioPhone'];
2504: break;
2505:
2506: case 'pager':
2507: $message->pagernumber = $hash['pager'];
2508: break;
2509:
2510: case 'email':
2511: $message->email1address = Horde_Icalendar_Vcard::getBareEmail($value);
2512: break;
2513:
2514: case 'homeEmail':
2515: $message->email2address = Horde_Icalendar_Vcard::getBareEmail($value);
2516: break;
2517:
2518: case 'workEmail':
2519: $message->email3address = Horde_Icalendar_Vcard::getBareEmail($value);
2520: break;
2521:
2522: case 'imaddress':
2523: try {
2524: $message->imaddress = $value;
2525: } catch (InvalidArgumentException $e) {
2526: }
2527: break;
2528:
2529: case 'imaddress2':
2530: try {
2531: $message->imaddress2 = $value;
2532: } catch (InvalidArgumentException $e) {
2533:
2534: }
2535: break;
2536:
2537: case 'imaddress3':
2538: try {
2539: $message->imaddress3 = $value;
2540: } catch (InvalidArgumentException $e) {
2541: }
2542: break;
2543:
2544: case 'title':
2545: $message->jobtitle = $value;
2546: break;
2547:
2548: case 'company':
2549: $message->companyname = $value;
2550: break;
2551:
2552: case 'department':
2553: $message->department = $value;
2554: break;
2555:
2556: case 'category':
2557:
2558: $message->categories = explode(';', $value);
2559: break;
2560:
2561: case 'spouse':
2562: $message->spouse = $value;
2563: break;
2564: case 'notes':
2565:
2566: $message->body = $value;
2567: $message->bodysize = strlen($message->body);
2568: $message->bodytruncated = false;
2569: break;
2570:
2571: case 'website':
2572: $message->webpage = $value;
2573: break;
2574:
2575: case 'birthday':
2576: case 'anniversary':
2577: if (!empty($value)) {
2578: try {
2579: $date = new Horde_Date($value);
2580: $message->{$field} = $date;
2581: } catch (Horde_Date_Exception $e) {
2582: $message->$field = null;
2583: }
2584: } else {
2585: $message->$field = null;
2586: }
2587: break;
2588: }
2589: }
2590:
2591: if (empty($this->fileas)) {
2592: $message->fileas = Turba::formatName($object);
2593: }
2594:
2595: return $message;
2596: }
2597:
2598: 2599: 2600: 2601: 2602: 2603: 2604: 2605: 2606:
2607: public function fromASContact(Horde_ActiveSync_Message_Contact $message)
2608: {
2609: $hash = array();
2610: $formattedname = false;
2611:
2612: $textMap = array(
2613: 'fileas' => 'name',
2614: 'lastname' => 'lastname',
2615: 'firstname' => 'firstname',
2616: 'middlename' => 'middlenames',
2617: 'nickname' => 'nickname',
2618: 'title' => 'namePrefix',
2619: 'suffix' => 'nameSuffix',
2620: 'homestreet' => 'homeStreet',
2621: 'homecity' => 'homeCity',
2622: 'homestate' => 'homeProvince',
2623: 'homepostalcode' => 'homePostalCode',
2624: 'otherstreet' => 'otherStreet',
2625: 'othercity' => 'otherCity',
2626: 'otherstate' => 'otherProvince',
2627: 'otherpostalcode' => 'otherPostalCode',
2628: 'businessstreet' => 'workStreet',
2629: 'businesscity' => 'workCity',
2630: 'businessstate' => 'workProvince',
2631: 'businesspostalcode' => 'workPostalCode',
2632: 'jobtitle' => 'title',
2633: 'companyname' => 'company',
2634: 'department' => 'department',
2635: 'spouse' => 'spouse',
2636: 'body' => 'notes',
2637: 'webpage' => 'website',
2638: 'assistantname' => 'assistant',
2639: 'imaddress' => 'imaddress',
2640: 'imaddress2' => 'imaddress2',
2641: 'imaddress3' => 'imaddress3'
2642: );
2643: foreach ($textMap as $asField => $turbaField) {
2644: if (!$message->isGhosted($asField)) {
2645: try {
2646: $hash[$turbaField] = $message->{$asField};
2647: } catch (InvalidArgumentException $e) {
2648: }
2649: }
2650: }
2651:
2652: $nonTextMap = array(
2653: 'homephonenumber' => 'homePhone',
2654: 'home2phonenumber' => 'homePhone2',
2655: 'businessphonenumber' => 'workPhone',
2656: 'business2phonenumber' => 'workPhone2',
2657: 'businessfaxnumber' => 'fax',
2658: 'homefaxnumber' => 'homeFax',
2659: 'pagernumber' => 'pager',
2660: 'mobilephonenumber' => 'cellPhone',
2661: 'carphonenumber' => 'carPhone',
2662: 'assistnamephonenumber' => 'assistPhone',
2663: 'companymainphone' => 'companyPhone',
2664: 'radiophonenumber' => 'radioPhone'
2665: );
2666: foreach ($nonTextMap as $asField => $turbaField) {
2667: if (!$message->isGhosted($asField)) {
2668: try {
2669: $hash[$turbaField] = $message->{$asField};
2670: } catch (InvalidArgumentException $e) {
2671: }
2672: }
2673: }
2674:
2675:
2676:
2677:
2678: if (!$message->isGhosted('picture')) {
2679: $hash['photo'] = base64_decode($message->picture);
2680: }
2681:
2682:
2683: if (!$message->isGhosted('email1address')) {
2684: $hash['email'] = Horde_Icalendar_Vcard::getBareEmail($message->email1address);
2685: }
2686: if (!$message->isGhosted('email2address')) {
2687: $hash['homeEmail'] = Horde_Icalendar_Vcard::getBareEmail($message->email2address);
2688: }
2689: if (!$message->isGhosted('email3address')) {
2690: $hash['workEmail'] = Horde_Icalendar_Vcard::getBareEmail($message->email3address);
2691: }
2692:
2693: if (count($message->categories)) {
2694: $hash['category'] = implode('|', $message->categories);
2695: } elseif (!$message->isGhosted('categories')) {
2696: $hash['category'] = '';
2697: }
2698:
2699:
2700: if (!empty($message->birthday)) {
2701: $bday = new Horde_Date($message->birthday);
2702: $bday->setTimezone(date_default_timezone_get());
2703: $hash['birthday'] = $bday->format('Y-m-d');
2704: } elseif (!$message->isGhosted('birthday')) {
2705: $hash['birthday'] = null;
2706: }
2707: if (!empty($message->anniversary)) {
2708: $anniversary = new Horde_Date($message->anniversary);
2709: $anniversary->setTimezone(date_default_timezone_get());
2710: $hash['anniversary'] = $anniversary->format('Y-m-d');
2711: } elseif (!$message->isGhosted('anniversary')) {
2712: $hash['anniversary'] = null;
2713: }
2714:
2715:
2716: include 'Horde/Nls/Countries.php';
2717: if (!empty($message->homecountry)) {
2718: $country = array_search($message->homecountry, $countries);
2719: if ($country === false) {
2720: $country = $message->homecountry;
2721: }
2722: $hash['homeCountry'] = $country;
2723: } elseif (!$message->isGhosted('homecountry')) {
2724: $hash['homeCountry'] = null;
2725: }
2726:
2727: if (!empty($message->businesscountry)) {
2728: $country = array_search($message->businesscountry, $countries);
2729: if ($country === false) {
2730: $country = $message->businesscountry;
2731: }
2732: $hash['workCountry'] = $country;
2733: } elseif (!$message->isGhosted('businesscountry')) {
2734: $hash['workCountry'] = null;
2735: }
2736:
2737: if (!empty($message->othercountry)) {
2738: $country = array_search($message->othercountry, $countries);
2739: if ($country === false) {
2740: $country = $message->othercountry;
2741: }
2742: $hash['otherCountry'] = $country;
2743: } elseif (!$message->isGhosted('othercountry')) {
2744: $hash['otherCountry'] = null;
2745: }
2746:
2747: return $hash;
2748: }
2749:
2750: 2751: 2752: 2753: 2754: 2755: 2756: 2757:
2758: public function hasPermission($perm)
2759: {
2760: $perms = $GLOBALS['injector']->getInstance('Horde_Perms');
2761: return $perms->exists('turba:sources:' . $this->_name)
2762: ? $perms->hasPermission('turba:sources:' . $this->_name, $GLOBALS['registry']->getAuth(), $perm)
2763:
2764: : true;
2765: }
2766:
2767: 2768: 2769: 2770: 2771: 2772:
2773: public function getName()
2774: {
2775: return $this->_name;
2776: }
2777:
2778: 2779: 2780: 2781: 2782: 2783:
2784: public function getContactOwner()
2785: {
2786: return empty($this->_contact_owner)
2787: ? $this->_getContactOwner()
2788: : $this->_contact_owner;
2789: }
2790:
2791: 2792: 2793: 2794: 2795:
2796: public function setContactOwner($owner)
2797: {
2798: $this->_contact_owner = $owner;
2799: }
2800:
2801: 2802: 2803: 2804: 2805: 2806:
2807: public function setSourceName($name)
2808: {
2809: $this->_name = $name;
2810: }
2811:
2812: 2813: 2814: 2815: 2816: 2817:
2818: protected function _getContactOwner()
2819: {
2820: return $GLOBALS['registry']->getAuth();
2821: }
2822:
2823: 2824: 2825: 2826: 2827: 2828: 2829: 2830:
2831: public function createShare($share_name, array $params)
2832: {
2833:
2834: if (empty($params['params']['name'])) {
2835: $params['params']['name'] = $share_name;
2836: }
2837:
2838: return Turba::createShare($share_name, $params);
2839: }
2840:
2841: 2842: 2843: 2844: 2845: 2846: 2847: 2848:
2849: protected function _makeKey(array $attributes)
2850: {
2851: return hash('md5', mt_rand());
2852: }
2853:
2854: 2855: 2856: 2857: 2858:
2859: protected function _makeUid()
2860: {
2861: return strval(new Horde_Support_Guid());
2862: }
2863:
2864: 2865: 2866: 2867: 2868:
2869: protected function _init()
2870: {
2871: }
2872:
2873: 2874: 2875: 2876: 2877: 2878: 2879: 2880: 2881: 2882: 2883: 2884: 2885: 2886:
2887: protected function _search(array $criteria, array $fields, array $blobFields = array(), $count_only = false)
2888: {
2889: throw new Turba_Exception(_("Searching is not available."));
2890: }
2891:
2892: 2893: 2894: 2895: 2896: 2897: 2898: 2899: 2900: 2901: 2902: 2903:
2904: protected function _read($key, $ids, $owner, array $fields,
2905: array $blobFields = array())
2906: {
2907: throw new Turba_Exception(_("Reading contacts is not available."));
2908: }
2909:
2910: 2911: 2912: 2913: 2914: 2915: 2916: 2917:
2918: protected function _add(array $attributes, array $blob_fields = array())
2919: {
2920: throw new Turba_Exception(_("Adding contacts is not available."));
2921: }
2922:
2923: 2924: 2925: 2926: 2927: 2928: 2929: 2930:
2931: protected function _delete($object_key, $object_id)
2932: {
2933: throw new Turba_Exception(_("Deleting contacts is not available."));
2934: }
2935:
2936: 2937: 2938: 2939: 2940: 2941: 2942: 2943:
2944: protected function _save(Turba_Object $object)
2945: {
2946: throw new Turba_Exception(_("Saving contacts is not available."));
2947: }
2948:
2949: 2950: 2951: 2952: 2953: 2954: 2955:
2956: public function removeUserData($user)
2957: {
2958: throw new Turba_Exception_NotSupported(_("Removing user data is not supported in the current address book storage driver."));
2959: }
2960:
2961: 2962: 2963: 2964: 2965: 2966: 2967: 2968:
2969: public function checkDefaultShare(Horde_Share_Object $share, array $srcconfig)
2970: {
2971: $params = @unserialize($share->get('params'));
2972: if (!isset($params['default'])) {
2973: $params['default'] = ($params['name'] == $GLOBALS['registry']->getAuth());
2974: $share->set('params', serialize($params));
2975: $share->save();
2976: }
2977:
2978: return $params['default'];
2979: }
2980:
2981:
2982:
2983: 2984: 2985: 2986: 2987: 2988:
2989: public function count()
2990: {
2991: if (is_null($this->_count)) {
2992: $this->_count = count(
2993: $this->_search(array('AND' => array(
2994: array('field' => $this->toDriver('__owner'),
2995: 'op' => '=',
2996: 'test' => $this->getContactOwner()))),
2997: array($this->toDriver('__key')))
2998: );
2999: }
3000:
3001: return $this->_count;
3002: }
3003:
3004: 3005: 3006: 3007: 3008:
3009: protected function _guessName(&$hash)
3010: {
3011: if (($pos = strpos($hash['name'], ',')) !== false) {
3012:
3013: $hash['lastname'] = Horde_String::substr($hash['name'], 0, $pos);
3014: $hash['firstname'] = trim(Horde_String::substr($hash['name'], $pos + 1));
3015: } elseif (($pos = Horde_String::rpos($hash['name'], ' ')) !== false) {
3016:
3017: $hash['lastname'] = trim(Horde_String::substr($hash['name'], $pos + 1));
3018: $hash['firstname'] = Horde_String::substr($hash['name'], 0, $pos);
3019: } else {
3020: $hash['lastname'] = $hash['name'];
3021: $hash['firstname'] = '';
3022: }
3023: }
3024:
3025: }
3026: