From 4d4a2fa32edffcca91822fe82363b71372048286 Mon Sep 17 00:00:00 2001 From: alecpl Date: Wed, 3 Aug 2011 09:20:52 +0000 Subject: [PATCH] - Added possibility to extend rcube_vcard's fieldmap - Skip empty values in vCard export --- program/include/rcube_contacts.php | 3 +- program/include/rcube_vcard.php | 58 +++++++++++++++++++++++----- program/steps/addressbook/export.inc | 4 +- program/steps/addressbook/import.inc | 5 ++- 4 files changed, 58 insertions(+), 12 deletions(-) diff --git a/program/include/rcube_contacts.php b/program/include/rcube_contacts.php index 3ad53a6db..cd155aada 100644 --- a/program/include/rcube_contacts.php +++ b/program/include/rcube_contacts.php @@ -581,8 +581,9 @@ class rcube_contacts extends rcube_addressbook $updated = false; $write_sql = array(); $record = $this->get_record($id, true); +console($save_cols); $save_cols = $this->convert_save_data($save_cols, $record); - +console($save_cols); foreach ($save_cols as $col => $value) { $write_sql[] = sprintf("%s=%s", $this->db->quoteIdentifier($col), $this->db->quote($value)); } diff --git a/program/include/rcube_vcard.php b/program/include/rcube_vcard.php index dd62e9ed3..90ee7da66 100644 --- a/program/include/rcube_vcard.php +++ b/program/include/rcube_vcard.php @@ -33,7 +33,7 @@ class rcube_vcard 'FN' => array(), 'N' => array(array('','','','','')), ); - private $fieldmap = array( + static private $fieldmap = array( 'phone' => 'TEL', 'birthday' => 'BDAY', 'website' => 'URL', @@ -69,8 +69,11 @@ class rcube_vcard /** * Constructor */ - public function __construct($vcard = null, $charset = RCMAIL_CHARSET, $detect = false) + public function __construct($vcard = null, $charset = RCMAIL_CHARSET, $detect = false, $fieldmap = array()) { + if (!empty($fielmap)) + $this->extend_fieldmap($fieldmap); + if (!empty($vcard)) $this->load($vcard, $charset, $detect); } @@ -146,15 +149,18 @@ class rcube_vcard $out['suffix'] = $this->raw['N'][0][4]; // convert from raw vcard data into associative data for Roundcube - foreach (array_flip($this->fieldmap) as $tag => $col) { + foreach (array_flip(self::$fieldmap) as $tag => $col) { foreach ((array)$this->raw[$tag] as $i => $raw) { if (is_array($raw)) { $k = -1; $key = $col; + $subtype = ''; - $subtype = $typemap[$raw['type'][++$k]] ? $typemap[$raw['type'][$k]] : strtolower($raw['type'][$k]); - while ($k < count($raw['type']) && ($subtype == 'internet' || $subtype == 'pref')) + if (!empty($raw['type'])) { $subtype = $typemap[$raw['type'][++$k]] ? $typemap[$raw['type'][$k]] : strtolower($raw['type'][$k]); + while ($k < count($raw['type']) && ($subtype == 'internet' || $subtype == 'pref')) + $subtype = $typemap[$raw['type'][++$k]] ? $typemap[$raw['type'][$k]] : strtolower($raw['type'][$k]); + } // read vcard 2.1 subtype if (!$subtype) { @@ -167,7 +173,7 @@ class rcube_vcard } // force subtype if none set - if (preg_match('/^(email|phone|address|website)/', $key) && !$subtype) + if (!$subtype && preg_match('/^(email|phone|address|website)/', $key)) $subtype = 'other'; if ($subtype) @@ -220,7 +226,7 @@ class rcube_vcard public function reset($fields = null) { if (!$fields) - $fields = array_merge(array_values($this->fieldmap), array_keys($this->immap), array('FN','N','ORG','NICKNAME','EMAIL','ADR','BDAY')); + $fields = array_merge(array_values(self::$fieldmap), array_keys($this->immap), array('FN','N','ORG','NICKNAME','EMAIL','ADR','BDAY')); foreach ($fields as $f) unset($this->raw[$f]); @@ -323,7 +329,7 @@ class rcube_vcard if ($field == 'phone' && $this->phonetypemap[$type]) $type = $this->phonetypemap[$type]; - if (($tag = $this->fieldmap[$field]) && (is_array($value) || strlen($value))) { + if (($tag = self::$fieldmap[$field]) && (is_array($value) || strlen($value))) { $index = count($this->raw[$tag]); $this->raw[$tag][$index] = (array)$value; if ($type) @@ -389,6 +395,16 @@ class rcube_vcard } + /** + * Extends fieldmap definition + */ + public function extend_fieldmap($map) + { + if (is_array($map)) + self::$fieldmap = array_merge($map, self::$fieldmap); + } + + /** * Factory method to import a vcard file * @@ -420,7 +436,7 @@ class rcube_vcard if (preg_match('/^END:VCARD$/i', $line)) { // parse vcard - $obj = new rcube_vcard(self::cleanup($vcard_block), $charset, true); + $obj = new rcube_vcard(self::cleanup($vcard_block), $charset, true, self::$fieldmap); if (!empty($obj->displayname) || !empty($obj->email)) $out[] = $obj; @@ -620,6 +636,10 @@ class rcube_vcard $value = $entry; } + // skip empty entries + if (self::is_empty($value)) + continue; + $vcard .= self::vcard_quote($type) . $attr . ':' . self::vcard_quote($value) . "\n"; } } @@ -671,6 +691,26 @@ class rcube_vcard } + /** + * Check if vCard entry is empty: empty string or an array with + * all entries empty. + * + * @param mixed $value Attribute value (string or array) + * + * @return bool True if the value is empty, False otherwise + */ + private static function is_empty($value) + { + foreach ((array)$value as $v) { + if (((string)$v) !== '') { + return false; + } + } + + return true; + } + + /** * Returns UNICODE type based on BOM (Byte Order Mark) * diff --git a/program/steps/addressbook/export.inc b/program/steps/addressbook/export.inc index 04b98a308..f890aca69 100644 --- a/program/steps/addressbook/export.inc +++ b/program/steps/addressbook/export.inc @@ -77,7 +77,9 @@ while ($result && ($row = $result->next())) { } // copy values into vcard object else { - $vcard = new rcube_vcard($row['vcard']); + $vcard = new rcube_vcard(); + $vcard->extend_fieldmap($CONTACTS->vcard_map); + $vcard->load($row['vcard']); $vcard->reset(); foreach ($row as $key => $values) { diff --git a/program/steps/addressbook/import.inc b/program/steps/addressbook/import.inc index 12a8d6b9b..1b9aea18a 100644 --- a/program/steps/addressbook/import.inc +++ b/program/steps/addressbook/import.inc @@ -138,7 +138,10 @@ if ($_FILES['_file']['tmp_name'] && is_uploaded_file($_FILES['_file']['tmp_name' $CONTACTS = $RCMAIL->get_address_book($target, true); // let rcube_vcard do the hard work :-) - $vcards = rcube_vcard::import(file_get_contents($_FILES['_file']['tmp_name'])); + $vcard_o = new rcube_vcard(); + $vcard_o->extend_fieldmap($CONTACTS->vcard_map); + + $vcards = $vcard_o->import(file_get_contents($_FILES['_file']['tmp_name'])); // no vcards detected if (!count($vcards)) {