| 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 |