Total Complexity | 273 |
Total Lines | 1100 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like addressbook_vcal often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use addressbook_vcal, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | class addressbook_vcal extends addressbook_bo |
||
22 | { |
||
23 | /** |
||
24 | * product manufacturer from setSupportedFields (lowercase!) |
||
25 | * |
||
26 | * @var string |
||
27 | */ |
||
28 | var $productManufacturer = 'file'; |
||
29 | /** |
||
30 | * product name from setSupportedFields (lowercase!) |
||
31 | * |
||
32 | * @var string |
||
33 | */ |
||
34 | var $productName; |
||
35 | /** |
||
36 | * supported fields for vCard file and CardDAV import/export |
||
37 | * |
||
38 | * @var array |
||
39 | */ |
||
40 | var $databaseFields = array( // all entries e.g. for CardDAV |
||
41 | 'ADR;WORK' => array('','adr_one_street2','adr_one_street','adr_one_locality','adr_one_region', |
||
42 | 'adr_one_postalcode','adr_one_countryname'), |
||
43 | 'ADR;HOME' => array('','adr_two_street2','adr_two_street','adr_two_locality','adr_two_region', |
||
44 | 'adr_two_postalcode','adr_two_countryname'), |
||
45 | 'BDAY' => array('bday'), |
||
46 | 'CLASS' => array('private'), |
||
47 | 'CATEGORIES' => array('cat_id'), |
||
48 | 'EMAIL;WORK' => array('email'), |
||
49 | 'EMAIL;HOME' => array('email_home'), |
||
50 | 'N' => array('n_family','n_given','n_middle', |
||
51 | 'n_prefix','n_suffix'), |
||
52 | 'FN' => array('n_fn'), |
||
53 | 'NOTE' => array('note'), |
||
54 | 'ORG' => array('org_name','org_unit','room'), |
||
55 | 'TEL;CELL;WORK' => array('tel_cell'), |
||
56 | 'TEL;CELL;HOME' => array('tel_cell_private'), |
||
57 | 'TEL;CAR' => array('tel_car'), |
||
58 | 'TEL;OTHER' => array('tel_other'), |
||
59 | 'TEL;VOICE;WORK' => array('tel_work'), |
||
60 | 'TEL;FAX;WORK' => array('tel_fax'), |
||
61 | 'TEL;HOME;VOICE' => array('tel_home'), |
||
62 | 'TEL;FAX;HOME' => array('tel_fax_home'), |
||
63 | 'TEL;PAGER' => array('tel_pager'), |
||
64 | 'TITLE' => array('title'), |
||
65 | 'URL;WORK' => array('url'), |
||
66 | 'URL;HOME' => array('url_home'), |
||
67 | 'ROLE' => array('role'), |
||
68 | 'NICKNAME' => array('label'), |
||
69 | 'FBURL' => array('freebusy_uri'), |
||
70 | 'PHOTO' => array('jpegphoto'), |
||
71 | 'X-ASSISTANT' => array('assistent'), |
||
72 | 'X-ASSISTANT-TEL' => array('tel_assistent'), |
||
73 | 'UID' => array('uid'), |
||
74 | 'REV' => array('modified'), |
||
75 | //'KEY' multivalued with mime-type to export PGP and S/Mime public keys |
||
76 | 'KEY' => array('pubkey'), |
||
77 | //set for Apple: 'X-ABSHOWAS' => array('fileas_type'), // Horde vCard class uses uppercase prop-names! |
||
78 | ); |
||
79 | |||
80 | var $supportedFields; |
||
81 | |||
82 | /** |
||
83 | * VCard version |
||
84 | * |
||
85 | * @var string |
||
86 | */ |
||
87 | var $version; |
||
88 | /** |
||
89 | * Client CTCap Properties |
||
90 | * |
||
91 | * @var array |
||
92 | */ |
||
93 | var $clientProperties; |
||
94 | /** |
||
95 | * Set Logging |
||
96 | * |
||
97 | * @var string |
||
98 | * off = false; |
||
99 | */ |
||
100 | var $log = false; |
||
101 | var $logfile="/tmp/log-vcard"; |
||
102 | /** |
||
103 | * Constructor |
||
104 | * |
||
105 | * @param string $contact_app the current application |
||
106 | * @param string $_contentType the content type (version) |
||
107 | * @param array $_clientProperties client properties |
||
108 | */ |
||
109 | function __construct($contact_app='addressbook', $_contentType='text/x-vcard', &$_clientProperties = array()) |
||
110 | { |
||
111 | parent::__construct($contact_app); |
||
112 | if ($this->log) |
||
113 | { |
||
114 | $this->logfile = $GLOBALS['egw_info']['server']['temp_dir']."/log-vcard"; |
||
115 | error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" . |
||
116 | array2string($_contentType)."\n",3,$this->logfile); |
||
117 | } |
||
118 | switch($_contentType) |
||
119 | { |
||
120 | case 'text/vcard': |
||
121 | $this->version = '3.0'; |
||
122 | break; |
||
123 | default: |
||
124 | $this->version = '2.1'; |
||
125 | break; |
||
126 | } |
||
127 | $this->clientProperties = $_clientProperties; |
||
128 | $this->supportedFields = $this->databaseFields; |
||
129 | } |
||
130 | /** |
||
131 | * import a vard into addressbook |
||
132 | * |
||
133 | * @param string $_vcard the vcard |
||
134 | * @param int/string $_abID =null the internal addressbook id or !$_abID for a new enty |
||
|
|||
135 | * @param boolean $merge =false merge data with existing entry |
||
136 | * @param string $charset The encoding charset for $text. Defaults to |
||
137 | * utf-8 for new format, iso-8859-1 for old format. |
||
138 | * @return int contact id |
||
139 | */ |
||
140 | function addVCard($_vcard, $_abID=null, $merge=false, $charset=null) |
||
141 | { |
||
142 | if (!($contact = $this->vcardtoegw($_vcard, $charset))) return false; |
||
143 | |||
144 | if ($_abID) |
||
145 | { |
||
146 | if (($old_contact = $this->read($_abID))) |
||
147 | { |
||
148 | $contact['photo_unchanged'] = $old_contact['jpegphoto'] === $contact['jpegphoto']; |
||
149 | if ($merge) |
||
150 | { |
||
151 | foreach (array_keys($contact) as $key) |
||
152 | { |
||
153 | if (!empty($old_contact[$key])) |
||
154 | { |
||
155 | $contact[$key] = $old_contact[$key]; |
||
156 | } |
||
157 | } |
||
158 | } |
||
159 | else |
||
160 | { |
||
161 | if (isset($old_contact['account_id'])) |
||
162 | { |
||
163 | $contact['account_id'] = $old_contact['account_id']; |
||
164 | } |
||
165 | if (is_array($contact['cat_id'])) |
||
166 | { |
||
167 | $contact['cat_id'] = implode(',',$this->find_or_add_categories($contact['cat_id'], $_abID)); |
||
168 | } |
||
169 | else |
||
170 | { |
||
171 | // restore from orignal |
||
172 | $contact['cat_id'] = $old_contact['cat_id']; |
||
173 | } |
||
174 | } |
||
175 | } |
||
176 | // update entry |
||
177 | $contact['id'] = $_abID; |
||
178 | } |
||
179 | else |
||
180 | { |
||
181 | // If photo is set, we want to update it |
||
182 | $contact['photo_unchanged'] = false; |
||
183 | if (is_array($contact['cat_id'])) |
||
184 | { |
||
185 | $contact['cat_id'] = implode(',',$this->find_or_add_categories($contact['cat_id'], -1)); |
||
186 | } |
||
187 | } |
||
188 | if (isset($contact['owner']) && $contact['owner'] != $this->user) |
||
189 | { |
||
190 | $contact['private'] = 0; // foreign contacts are never private! |
||
191 | } |
||
192 | if ($this->log) |
||
193 | { |
||
194 | error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" . |
||
195 | array2string($contact)."\n",3,$this->logfile); |
||
196 | } |
||
197 | return $this->save($contact); |
||
198 | } |
||
199 | |||
200 | /** |
||
201 | * return a vcard |
||
202 | * |
||
203 | * @param int/string $_id the id of the contact |
||
204 | * @param string $_charset ='UTF-8' encoding of the vcard, default UTF-8 |
||
205 | * @param boolean $extra_charset_attribute =true GroupDAV/CalDAV dont need the charset attribute and some clients have problems with it |
||
206 | * @return string containing the vcard |
||
207 | */ |
||
208 | function getVCard($_id,$_charset='UTF-8',$extra_charset_attribute=true) |
||
209 | { |
||
210 | $vCard = new Horde_Icalendar_Vcard($this->version); |
||
211 | $vCard->setAttribute('PRODID','-//EGroupware//NONSGML EGroupware Addressbook '.$GLOBALS['egw_info']['apps']['api']['version'].'//'. |
||
212 | strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang'])); |
||
213 | |||
214 | $sysCharSet = Api\Translation::charset(); |
||
215 | |||
216 | // KAddressbook and Funambol4BlackBerry always requires non-ascii chars to be qprint encoded. |
||
217 | if ($this->productName == 'kde' || |
||
218 | ($this->productManufacturer == 'funambol' && $this->productName == 'blackberry plug-in')) |
||
219 | { |
||
220 | $extra_charset_attribute = true; |
||
221 | } |
||
222 | |||
223 | if (!($entry = $this->read($_id))) |
||
224 | { |
||
225 | return false; |
||
226 | } |
||
227 | |||
228 | $this->fixup_contact($entry); |
||
229 | |||
230 | foreach ($this->supportedFields as $vcardField => $databaseFields) |
||
231 | { |
||
232 | $values = array(); |
||
233 | $options = array(); |
||
234 | $hasdata = 0; |
||
235 | // seperate fields from their options/attributes |
||
236 | $vcardFields = explode(';', $vcardField); |
||
237 | $vcardField = $vcardFields[0]; |
||
238 | $i = 1; |
||
239 | while (isset($vcardFields[$i])) |
||
240 | { |
||
241 | list($oname, $oval) = explode('=', $vcardFields[$i]); |
||
242 | if (!$oval && ($this->version == '3.0')) |
||
243 | { |
||
244 | // declare OPTION as TYPE=OPTION |
||
245 | $options['TYPE'][] = $oname ; |
||
246 | } |
||
247 | else |
||
248 | { |
||
249 | $options[$oname] = $oval; |
||
250 | } |
||
251 | $i++; |
||
252 | } |
||
253 | if (is_array($options['TYPE'])) |
||
254 | { |
||
255 | $oval = implode(",", $options['TYPE']); |
||
256 | unset($options['TYPE']); |
||
257 | $options['TYPE'] = $oval; |
||
258 | } |
||
259 | if (isset($this->clientProperties[$vcardField]['Size'])) |
||
260 | { |
||
261 | $size = $this->clientProperties[$vcardField]['Size']; |
||
262 | $noTruncate = $this->clientProperties[$vcardField]['NoTruncate']; |
||
263 | if ($this->log && $size > 0) |
||
264 | { |
||
265 | error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ . |
||
266 | "() $vcardField Size: $size, NoTruncate: " . |
||
267 | ($noTruncate ? 'TRUE' : 'FALSE') . "\n",3,$this->logfile); |
||
268 | } |
||
269 | //Horde::logMessage("vCalAddressbook $vcardField Size: $size, NoTruncate: " . |
||
270 | // ($noTruncate ? 'TRUE' : 'FALSE'), __FILE__, __LINE__, PEAR_LOG_DEBUG); |
||
271 | } |
||
272 | else |
||
273 | { |
||
274 | $size = -1; |
||
275 | $noTruncate = false; |
||
276 | } |
||
277 | foreach ($databaseFields as $databaseField) |
||
278 | { |
||
279 | $value = ''; |
||
280 | |||
281 | if (!empty($databaseField)) |
||
282 | { |
||
283 | $value = trim($entry[$databaseField]); |
||
284 | } |
||
285 | |||
286 | switch ($databaseField) |
||
287 | { |
||
288 | case 'modified': |
||
289 | $value = gmdate("Y-m-d\TH:i:s\Z",Api\DateTime::user2server($value)); |
||
290 | $hasdata++; |
||
291 | break; |
||
292 | |||
293 | case 'private': |
||
294 | $value = $value ? 'PRIVATE' : 'PUBLIC'; |
||
295 | $hasdata++; |
||
296 | break; |
||
297 | |||
298 | case 'bday': |
||
299 | if (!empty($value)) |
||
300 | { |
||
301 | if ($size == 8) |
||
302 | { |
||
303 | $value = str_replace('-','',$value); |
||
304 | } |
||
305 | elseif (isset($options['TYPE']) && ( |
||
306 | $options['TYPE'] == 'BASIC')) |
||
307 | { |
||
308 | unset($options['TYPE']); |
||
309 | // used by old SyncML implementations |
||
310 | $value = str_replace('-','',$value).'T000000Z'; |
||
311 | } |
||
312 | $hasdata++; |
||
313 | } |
||
314 | break; |
||
315 | |||
316 | case 'jpegphoto': |
||
317 | if (empty($value) && ($entry['files'] & Api\Contacts::FILES_BIT_PHOTO)) |
||
318 | { |
||
319 | $value = file_get_contents(Api\Link::vfs_path('addressbook', $entry['id'], Api\Contacts::FILES_PHOTO)); |
||
320 | } |
||
321 | if (!empty($value) && |
||
322 | (($size < 0) || (strlen($value) < $size))) |
||
323 | { |
||
324 | if (!isset($options['TYPE'])) |
||
325 | { |
||
326 | $options['TYPE'] = 'JPEG'; |
||
327 | } |
||
328 | if (!isset($options['ENCODING'])) |
||
329 | { |
||
330 | $options['ENCODING'] = 'BASE64'; |
||
331 | } |
||
332 | $hasdata++; |
||
333 | // need to encode binary image, not done in Horde Icalendar |
||
334 | $value = base64_encode($value); |
||
335 | } |
||
336 | else |
||
337 | { |
||
338 | $value = ''; |
||
339 | } |
||
340 | break; |
||
341 | |||
342 | case 'pubkey': // for now we only export S/Mime publik key, as no device supports PGP |
||
343 | // https://en.wikipedia.org/wiki/VCard (search for "KEY") |
||
344 | if (($value = $this->get_key($entry, false))) |
||
345 | { |
||
346 | $options['TYPE'] = 'SMIME'; |
||
347 | $options['MEDIATYPE'] = 'application/x-x509-user-cert'; |
||
348 | $options['ENCODING'] = $this->version == '3.0' ? 'b' : 'BASE64'; |
||
349 | $value = base64_encode($value); |
||
350 | $hasdata++; |
||
351 | } |
||
352 | break; |
||
353 | |||
354 | case 'cat_id': |
||
355 | if (!empty($value) && ($values = /*str_replace(',','\\,',*/$this->get_categories($value)))//) |
||
356 | { |
||
357 | $values = (array) Api\Translation::convert($values, $sysCharSet, $_charset); |
||
358 | $value = implode(',', $values); // just for the CHARSET recognition |
||
359 | if (($size > 0) && strlen($value) > $size) |
||
360 | { |
||
361 | // let us try with only the first category |
||
362 | $value = $values[0]; |
||
363 | if (strlen($value) > $size) |
||
364 | { |
||
365 | if ($this->log) |
||
366 | { |
||
367 | error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ . |
||
368 | "() $vcardField omitted due to maximum size $size\n",3,$this->logfile); |
||
369 | } |
||
370 | // Horde::logMessage("vCalAddressbook $vcardField omitted due to maximum size $size", |
||
371 | // __FILE__, __LINE__, PEAR_LOG_WARNING); |
||
372 | continue; |
||
373 | } |
||
374 | $values = array(); |
||
375 | } |
||
376 | if (preg_match('/[^\x20-\x7F]/', $value)) |
||
377 | { |
||
378 | if ($extra_charset_attribute || $this->productName == 'kde') |
||
379 | { |
||
380 | $options['CHARSET'] = $_charset; |
||
381 | } |
||
382 | // KAddressbook requires non-ascii chars to be qprint encoded, other clients eg. nokia phones have trouble with that |
||
383 | if ($this->productName == 'kde') |
||
384 | { |
||
385 | $options['ENCODING'] = 'QUOTED-PRINTABLE'; |
||
386 | } |
||
387 | elseif ($this->productManufacturer == 'funambol') |
||
388 | { |
||
389 | $options['ENCODING'] = 'FUNAMBOL-QP'; |
||
390 | } |
||
391 | elseif (preg_match(Api\CalDAV\Handler::REQUIRE_QUOTED_PRINTABLE_ENCODING, $value)) |
||
392 | { |
||
393 | $options['ENCODING'] = 'QUOTED-PRINTABLE'; |
||
394 | } |
||
395 | elseif (!$extra_charset_attribute) |
||
396 | { |
||
397 | unset($options['ENCODING']); |
||
398 | } |
||
399 | } |
||
400 | $hasdata++; |
||
401 | } |
||
402 | break; |
||
403 | |||
404 | case 'n_fn': |
||
405 | case 'fileas_type': |
||
406 | // mark entries with fileas_type == 'org_name' as X-ABSHOWAS:COMPANY (Apple AB specific) |
||
407 | if (isset($this->supportedFields['X-ABSHOWAS']) && |
||
408 | $entry['org_name'] == $entry['n_fileas'] && $entry['fileas_type'] == 'org_name') |
||
409 | { |
||
410 | if ($vcardField == 'X-ABSHOWAS') $value = 'COMPANY'; |
||
411 | if ($databaseField == 'n_fn') $value = $entry['org_name']; |
||
412 | } |
||
413 | //error_log("vcardField='$vcardField', databaseField='$databaseField', this->supportedFields['X-ABSHOWAS']=".array2string($this->supportedFields['X-ABSHOWAS'])." --> value='$value'"); |
||
414 | // fall-through |
||
415 | |||
416 | default: |
||
417 | if (($size > 0) && strlen(implode(',', $values) . $value) > $size) |
||
418 | { |
||
419 | if ($noTruncate) |
||
420 | { |
||
421 | if ($this->log) |
||
422 | { |
||
423 | error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ . |
||
424 | "() $vcardField omitted due to maximum size $size\n",3,$this->logfile); |
||
425 | } |
||
426 | // Horde::logMessage("vCalAddressbook $vcardField omitted due to maximum size $size", |
||
427 | // __FILE__, __LINE__, PEAR_LOG_WARNING); |
||
428 | continue; |
||
429 | } |
||
430 | // truncate the value to size |
||
431 | $cursize = strlen(implode('', $values)); |
||
432 | $left = $size - $cursize - count($databaseFields) + 1; |
||
433 | if ($left > 0) |
||
434 | { |
||
435 | $value = substr($value, 0, $left); |
||
436 | } |
||
437 | else |
||
438 | { |
||
439 | $value = ''; |
||
440 | } |
||
441 | if ($this->log) |
||
442 | { |
||
443 | error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ . |
||
444 | "() $vcardField truncated to maximum size $size\n",3,$this->logfile); |
||
445 | } |
||
446 | //Horde::logMessage("vCalAddressbook $vcardField truncated to maximum size $size", |
||
447 | // __FILE__, __LINE__, PEAR_LOG_INFO); |
||
448 | } |
||
449 | if (!empty($value) // required field |
||
450 | || in_array($vcardField,array('FN','ORG','N')) |
||
451 | || ($size >= 0 && !$noTruncate)) |
||
452 | { |
||
453 | $value = Api\Translation::convert(trim($value), $sysCharSet, $_charset); |
||
454 | $values[] = $value; |
||
455 | if ($this->version == '2.1' && preg_match('/[^\x20-\x7F]/', $value)) |
||
456 | { |
||
457 | if ($extra_charset_attribute || $this->productName == 'kde') |
||
458 | { |
||
459 | $options['CHARSET'] = $_charset; |
||
460 | } |
||
461 | // KAddressbook requires non-ascii chars to be qprint encoded, other clients eg. nokia phones have trouble with that |
||
462 | if ($this->productName == 'kde') |
||
463 | { |
||
464 | $options['ENCODING'] = 'QUOTED-PRINTABLE'; |
||
465 | } |
||
466 | elseif ($this->productManufacturer == 'funambol') |
||
467 | { |
||
468 | $options['ENCODING'] = 'FUNAMBOL-QP'; |
||
469 | } |
||
470 | elseif (preg_match(Api\CalDAV\Handler::REQUIRE_QUOTED_PRINTABLE_ENCODING, $value)) |
||
471 | { |
||
472 | $options['ENCODING'] = 'QUOTED-PRINTABLE'; |
||
473 | } |
||
474 | elseif (!$extra_charset_attribute) |
||
475 | { |
||
476 | unset($options['ENCODING']); |
||
477 | } |
||
478 | } |
||
479 | if ($vcardField == 'TEL' && $entry['tel_prefer'] && |
||
480 | ($databaseField == $entry['tel_prefer'])) |
||
481 | { |
||
482 | if ($options['TYPE']) |
||
483 | { |
||
484 | $options['TYPE'] .= ','; |
||
485 | } |
||
486 | $options['TYPE'] .= 'PREF'; |
||
487 | } |
||
488 | $hasdata++; |
||
489 | } |
||
490 | else |
||
491 | { |
||
492 | $values[] = ''; |
||
493 | } |
||
494 | break; |
||
495 | } |
||
496 | } |
||
497 | |||
498 | if ($hasdata <= 0) |
||
499 | { |
||
500 | // don't add the entry if there is no data for this field, |
||
501 | // except it's a mendatory field |
||
502 | continue; |
||
503 | } |
||
504 | |||
505 | $vCard->setAttribute($vcardField, $value, $options, true, $values); |
||
506 | } |
||
507 | |||
508 | // current iOS 8.4 shows TEL;TYPE="WORK,VOICE":+49 123 4567890 as '"WORK' |
||
509 | // old (patched) Horde iCalendar, did not enclosed parameter in quotes |
||
510 | $result = preg_replace('/^TEL;TYPE="([^"]+)":/m', 'TEL;TYPE=$1:', |
||
511 | $vCard->exportvCalendar($_charset)); |
||
512 | |||
513 | if ($this->log) |
||
514 | { |
||
515 | error_log(__FILE__.'['.__LINE__.'] '.__METHOD__ . |
||
516 | "() '$this->productManufacturer','$this->productName'\n",3,$this->logfile); |
||
517 | error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n" . |
||
518 | array2string($result)."\n",3,$this->logfile); |
||
519 | } |
||
520 | return $result; |
||
521 | } |
||
522 | |||
523 | function search($_vcard, $contentID=null, $relax=false, $charset=null) |
||
524 | { |
||
525 | $result = array(); |
||
526 | |||
527 | if (($contact = $this->vcardtoegw($_vcard, $charset))) |
||
528 | { |
||
529 | if (is_array($contact['category'])) |
||
530 | { |
||
531 | $contact['category'] = implode(',',$this->find_or_add_categories($contact['category'], |
||
532 | $contentID ? $contentID : -1)); |
||
533 | } |
||
534 | if ($contentID) |
||
535 | { |
||
536 | $contact['id'] = $contentID; |
||
537 | } |
||
538 | $result = $this->find_contact($contact, $relax); |
||
539 | } |
||
540 | return $result; |
||
541 | } |
||
542 | |||
543 | function setSupportedFields($_productManufacturer='file', $_productName='', $_supportedFields = null) |
||
549 | } |
||
550 | |||
551 | function setDatabaseFields($_databaseFields) |
||
552 | { |
||
553 | if (is_array($_databaseFields)) $this->databaseFields = $_databaseFields; |
||
554 | } |
||
555 | |||
556 | /** |
||
557 | * Parses a string containing vCard data. |
||
558 | * |
||
559 | * @param string $_vcard The data to parse. |
||
560 | * @param string $charset The encoding charset for $text. Defaults to |
||
561 | * utf-8 for new format, iso-8859-1 for old format. |
||
562 | * |
||
563 | * @return array|boolean The contact data or false on errors. |
||
564 | */ |
||
565 | function vcardtoegw($_vcard, $charset=null) |
||
1056 | } |
||
1057 | |||
1058 | /** |
||
1059 | * Exports some contacts: download or write to a file |
||
1060 | * |
||
1061 | * @param array $ids contact-ids |
||
1062 | * @param string $file filename or null for download |
||
1063 | */ |
||
1064 | function export($ids, $file=null) |
||
1065 | { |
||
1066 | if (!$file) |
||
1067 | { |
||
1068 | $filename = count($ids) == 1 ? Link::title('addressbook',$ids[0]): 'egw_addressbook_'.date('Y-m-d'); |
||
1069 | Api\Header\Content::type(($filename ? $filename : 'addressbook').'.vcf','text/x-vcard'); |
||
1070 | } |
||
1071 | if (!($fp = fopen($file ? $file : 'php://output','w'))) |
||
1072 | { |
||
1073 | return false; |
||
1074 | } |
||
1075 | if (isset($GLOBALS['egw_info']['user']['preferences']['addressbook']['vcard_charset'])) |
||
1076 | { |
||
1077 | $charset = $GLOBALS['egw_info']['user']['preferences']['addressbook']['vcard_charset']; |
||
1078 | } |
||
1079 | else |
||
1080 | { |
||
1081 | $charset = 'utf-8'; |
||
1082 | } |
||
1083 | foreach ($ids as $id) |
||
1084 | { |
||
1085 | fwrite($fp,$this->getVCard($id, $charset)); |
||
1086 | } |
||
1087 | fclose($fp); |
||
1088 | |||
1089 | if (!$file) |
||
1090 | { |
||
1091 | exit(); |
||
1092 | } |
||
1093 | return true; |
||
1094 | } |
||
1095 | |||
1096 | /** |
||
1097 | * return a groupVCard |
||
1098 | * |
||
1099 | * @param array $list values for 'list_uid', 'list_name', 'list_modified', 'members' |
||
1100 | * @param string $version ='3.0' vcard version |
||
1101 | * @return string containing the vcard |
||
1102 | */ |
||
1103 | function getGroupVCard(array $list,$version='3.0') |
||
1121 | } |
||
1122 | } |
||
1123 |