diff options
author | thomascube <thomas@roundcube.net> | 2011-01-12 15:54:35 +0000 |
---|---|---|
committer | thomascube <thomas@roundcube.net> | 2011-01-12 15:54:35 +0000 |
commit | a32679e69f7d6c265f85015677743272740dcc8e (patch) | |
tree | 69059a5afa49d4c21f18bf8b4533f4e510286d73 /plugins/kolab_addressbook/rcube_kolab_contacts.php | |
parent | 62a83b3bd5813885d964d9fd1509d52bb9c4f12c (diff) |
Unlinked externals, removed development stuff and updated versionsv0.5@4408
Diffstat (limited to 'plugins/kolab_addressbook/rcube_kolab_contacts.php')
-rw-r--r-- | plugins/kolab_addressbook/rcube_kolab_contacts.php | 876 |
1 files changed, 0 insertions, 876 deletions
diff --git a/plugins/kolab_addressbook/rcube_kolab_contacts.php b/plugins/kolab_addressbook/rcube_kolab_contacts.php deleted file mode 100644 index 8eb1f7856..000000000 --- a/plugins/kolab_addressbook/rcube_kolab_contacts.php +++ /dev/null @@ -1,876 +0,0 @@ -<?php - - -/** - * Backend class for a custom address book - * - * This part of the Roundcube+Kolab integration and connects the - * rcube_addressbook interface with the rcube_kolab wrapper for Kolab_Storage - * - * @author Thomas Bruederli - * @see rcube_addressbook - */ -class rcube_kolab_contacts extends rcube_addressbook -{ - public $primary_key = 'ID'; - public $readonly = false; - public $groups = true; - public $coltypes = array( - 'name' => array('limit' => 1), - 'firstname' => array('limit' => 1), - 'surname' => array('limit' => 1), - 'middlename' => array('limit' => 1), - 'prefix' => array('limit' => 1), - 'suffix' => array('limit' => 1), - 'nickname' => array('limit' => 1), - 'jobtitle' => array('limit' => 1), - 'organization' => array('limit' => 1), - 'department' => array('limit' => 1), - 'gender' => array('limit' => 1), - 'initials' => array('type' => 'text', 'size' => 6, 'limit' => 1, 'label' => 'kolab_addressbook.initials'), - 'email' => array('subtypes' => null), - 'phone' => array(), - 'im' => array('limit' => 1, 'subtypes' => null), - 'website' => array('limit' => 1, 'subtypes' => null), - 'address' => array('limit' => 2, 'subtypes' => array('home','business')), - 'birthday' => array('limit' => 1), - 'anniversary' => array('limit' => 1), - 'officelocation' => array('type' => 'text', 'size' => 40, 'limit' => 1, 'label' => 'kolab_addressbook.officelocation'), - 'profession' => array('type' => 'text', 'size' => 40, 'limit' => 1, 'label' => 'kolab_addressbook.profession'), - 'manager' => array('limit' => 1), - 'assistant' => array('limit' => 1), - 'spouse' => array('limit' => 1), - 'children' => array('type' => 'text', 'size' => 40, 'limit' => 1, 'label' => 'kolab_addressbook.children'), - 'pgppublickey' => array('type' => 'text', 'size' => 40, 'limit' => 1, 'label' => 'kolab_addressbook.pgppublickey'), - 'freebusyurl' => array('type' => 'text', 'size' => 40, 'limit' => 1, 'label' => 'kolab_addressbook.freebusyurl'), - 'notes' => array(), - 'photo' => array(), - // TODO: define more Kolab-specific fields such as: language, latitude, longitude - ); - - private $gid; - private $imap; - private $kolab; - private $folder; - private $contactstorage; - private $liststorage; - private $contacts; - private $distlists; - private $groupmembers; - private $id2uid; - private $filter; - private $result; - private $imap_folder = 'INBOX/Contacts'; - private $gender_map = array(0 => 'male', 1 => 'female'); - private $phonetypemap = array('home' => 'home1', 'work' => 'business1', 'work2' => 'business2', 'workfax' => 'businessfax'); - private $addresstypemap = array('work' => 'business'); - private $fieldmap = array( - // kolab => roundcube - 'full-name' => 'name', - 'given-name' => 'firstname', - 'middle-names' => 'middlename', - 'last-name' => 'surname', - 'prefix' => 'prefix', - 'suffix' => 'suffix', - 'nick-name' => 'nickname', - 'organization' => 'organization', - 'department' => 'department', - 'job-title' => 'jobtitle', - 'initials' => 'initials', - 'birthday' => 'birthday', - 'anniversary' => 'anniversary', - 'im-address' => 'im', - 'web-page' => 'website', - 'office-location' => 'officelocation', - 'profession' => 'profession', - 'manager-name' => 'manager', - 'assistant' => 'assistant', - 'spouse-name' => 'spouse', - 'children' => 'children', - 'body' => 'notes', - 'pgp-publickey' => 'pgppublickey', - 'free-busy-url' => 'freebusyurl', - ); - - - public function __construct($imap_folder = null) - { - if ($imap_folder) - $this->imap_folder = $imap_folder; - - // extend coltypes configuration - $format = rcube_kolab::get_format('contact'); - $this->coltypes['phone']['subtypes'] = $format->_phone_types; - $this->coltypes['address']['subtypes'] = $format->_address_types; - - // set localized labels for proprietary cols - foreach ($this->coltypes as $col => $prop) { - if (is_string($prop['label'])) - $this->coltypes[$col]['label'] = rcube_label($prop['label']); - } - - // fetch objects from the given IMAP folder - $this->contactstorage = rcube_kolab::get_storage($this->imap_folder); - $this->liststorage = rcube_kolab::get_storage($this->imap_folder, 'distributionlist'); - - $this->ready = !PEAR::isError($this->contactstorage) && !PEAR::isError($this->liststorage); - } - - - /** - * Getter for the address book name to be displayed - * - * @return string Name of this address book - */ - public function get_name() - { - return strtr(preg_replace('!^(INBOX|user)/!i', '', $this->imap_folder), '/', ':'); - } - - - /** - * Setter for the current group - */ - public function set_group($gid) - { - $this->gid = $gid; - } - - - /** - * Save a search string for future listings - * - * @param mixed Search params to use in listing method, obtained by get_search_set() - */ - public function set_search_set($filter) - { - $this->filter = $filter; - } - - - /** - * Getter for saved search properties - * - * @return mixed Search properties used by this class - */ - public function get_search_set() - { - return $this->filter; - } - - - /** - * Reset saved results and search parameters - */ - public function reset() - { - $this->result = null; - $this->filter = null; - } - - - /** - * List all active contact groups of this source - * - * @param string Optional search string to match group name - * @return array Indexed list of contact groups, each a hash array - */ - function list_groups($search = null) - { - $this->_fetch_groups(); - $groups = array(); - foreach ((array)$this->distlists as $group) { - if (!$search || strstr(strtolower($group['last-name']), strtolower($search))) - $groups[] = array('ID' => $group['ID'], 'name' => $group['last-name']); - } - return $groups; - } - - /** - * List the current set of contact records - * - * @param array List of cols to show - * @param int Only return this number of records, use negative values for tail - * @return array Indexed list of contact records, each a hash array - */ - public function list_records($cols=null, $subset=0) - { - $this->result = $this->count(); - - // list member of the selected group - if ($this->gid) { - $seen = array(); - $this->result->count = 0; - foreach ((array)$this->distlists[$this->gid]['member'] as $member) { - // skip member that don't match the search filter - if (is_array($this->filter['ids']) && array_search($member['ID'], $this->filter['ids']) === false) - continue; - if ($this->contacts[$member['ID']] && !$seen[$member['ID']]++) - $this->result->count++; - } - $ids = array_keys($seen); - } - else - $ids = is_array($this->filter['ids']) ? $this->filter['ids'] : array_keys($this->contacts); - - // fill contact data into the current result set - $start_row = $subset < 0 ? $this->result->first + $this->page_size + $subset : $this->result->first; - $last_row = min($subset != 0 ? $start_row + abs($subset) : $this->result->first + $this->page_size, count($ids)); - - for ($i = $start_row; $i < $last_row; $i++) { - if ($id = $ids[$i]) - $this->result->add($this->contacts[$id]); - } - - return $this->result; - } - - - /** - * Search records - * - * @param array List of fields to search in - * @param string Search value - * @param boolean True if results are requested, False if count only - * @param boolean True to skip the count query (select only) - * @param array List of fields that cannot be empty - * @return object rcube_result_set List of contact records and 'count' value - */ - public function search($fields, $value, $strict=false, $select=true, $nocount=false, $required=array()) - { - $this->_fetch_contacts(); - - // search by ID - if ($fields == $this->primary_key) { - return $this->get_record($value); - } - - $value = strtolower($value); - if (!is_array($fields)) - $fields = array($fields); - if (!is_array($required) && !empty($required)) - $required = array($required); - - $this->filter = array('fields' => $fields, 'value' => $value, 'strict' => $strict, 'ids' => array()); - - // search be iterating over all records in memory - foreach ($this->contacts as $id => $contact) { - // check if current contact has required values, otherwise skip it - if ($required) { - foreach ($required as $f) - if (empty($contact[$f])) - continue 2; - } - foreach ($fields as $f) { - foreach ((array)$contact[$f] as $val) { - $val = strtolower($val); - if (($strict && $val == $value) || (!$strict && strstr($val, $value))) { - $this->filter['ids'][] = $id; - break 2; - } - } - } - } - - // list records (now limited by $this->filter) - return $this->list_records(); - } - - - /** - * Refresh saved search results after data has changed - */ - public function refresh_search() - { - if ($this->filter) - $this->search($this->filter['fields'], $this->filter['value'], $this->filter['strict']); - - return $this->get_search_set(); - } - - - /** - * Count number of available contacts in database - * - * @return rcube_result_set Result set with values for 'count' and 'first' - */ - public function count() - { - $this->_fetch_contacts(); - $this->_fetch_groups(); - $count = $this->gid ? count($this->distlists[$this->gid]['member']) : (is_array($this->filter['ids']) ? count($this->filter['ids']) : count($this->contacts)); - return new rcube_result_set($count, ($this->list_page-1) * $this->page_size); - } - - - /** - * Return the last result set - * - * @return rcube_result_set Current result set or NULL if nothing selected yet - */ - public function get_result() - { - return $this->result; - } - - /** - * Get a specific contact record - * - * @param mixed record identifier(s) - * @param boolean True to return record as associative array, otherwise a result set is returned - * @return mixed Result object with all record fields or False if not found - */ - public function get_record($id, $assoc=false) - { - $this->_fetch_contacts(); - if ($this->contacts[$id]) { - $this->result = new rcube_result_set(1); - $this->result->add($this->contacts[$id]); - return $assoc ? $this->contacts[$id] : $this->result; - } - - return false; - } - - - /** - * Get group assignments of a specific contact record - * - * @param mixed Record identifier - * @return array List of assigned groups as ID=>Name pairs - */ - public function get_record_groups($id) - { - $out = array(); - $this->_fetch_groups(); - - foreach ((array)$this->groupmembers[$id] as $gid) { - if ($group = $this->distlists[$gid]) - $out[$gid] = $group['last-name']; - } - - return $out; - } - - - /** - * Create a new contact record - * - * @param array Assoziative array with save data - * Keys: Field name with optional section in the form FIELD:SECTION - * Values: Field value. Can be either a string or an array of strings for multiple values - * @param boolean True to check for duplicates first - * @return mixed The created record ID on success, False on error - */ - public function insert($save_data, $check=false) - { - if (!is_array($save_data)) - return false; - - $insert_id = $existing = false; - - // check for existing records by e-mail comparison - if ($check) { - foreach ($this->get_col_values('email', $save_data, true) as $email) { - if (($res = $this->search('email', $email, true, false)) && $res->count) { - $existing = true; - break; - } - } - } - - if (!$existing) { - // generate new Kolab contact item - $object = $this->_from_rcube_contact($save_data); - $object['uid'] = $this->contactstorage->generateUID(); - - $saved = $this->contactstorage->save($object); - - if (PEAR::isError($saved)) { - raise_error(array( - 'code' => 600, 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Error saving contact object to Kolab server:" . $saved->getMessage()), - true, false); - } - else { - $contact = $this->_to_rcube_contact($object); - $id = $contact['ID']; - $this->contacts[$id] = $contact; - $this->id2uid[$id] = $object['uid']; - $insert_id = $id; - } - } - - return $insert_id; - } - - - /** - * Update a specific contact record - * - * @param mixed Record identifier - * @param array Assoziative array with save data - * Keys: Field name with optional section in the form FIELD:SECTION - * Values: Field value. Can be either a string or an array of strings for multiple values - * @return boolean True on success, False on error - */ - public function update($id, $save_data) - { - $updated = false; - $this->_fetch_contacts(); - if ($this->contacts[$id] && ($uid = $this->id2uid[$id])) { - $old = $this->contactstorage->getObject($uid); - $object = array_merge($old, $this->_from_rcube_contact($save_data)); - - $saved = $this->contactstorage->save($object, $uid); - if (PEAR::isError($saved)) { - raise_error(array( - 'code' => 600, 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Error saving contact object to Kolab server:" . $saved->getMessage()), - true, false); - } - else { - $this->contacts[$id] = $this->_to_rcube_contact($object); - $updated = true; - } - } - - return $updated; - } - - /** - * Mark one or more contact records as deleted - * - * @param array Record identifiers - */ - public function delete($ids) - { - $this->_fetch_contacts(); - $this->_fetch_groups(); - - if (!is_array($ids)) - $ids = explode(',', $ids); - - $count = 0; - foreach ($ids as $id) { - if ($uid = $this->id2uid[$id]) { - $deleted = $this->contactstorage->delete($uid); - - if (PEAR::isError($deleted)) { - raise_error(array( - 'code' => 600, 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Error deleting a contact object from the Kolab server:" . $deleted->getMessage()), - true, false); - } - else { - // remove from distribution lists - foreach ((array)$this->groupmembers[$id] as $gid) - $this->remove_from_group($gid, $id); - - // clear internal cache - unset($this->contacts[$id], $this->id2uid[$id], $this->groupmembers[$id]); - $count++; - } - } - } - - return $count; - } - - /** - * Remove all records from the database - */ - public function delete_all() - { - if (!PEAR::isError($this->contactstorage->deleteAll())) { - $this->contacts = array(); - $this->id2uid = array(); - $this->result = null; - } - } - - - /** - * Close connection to source - * Called on script shutdown - */ - public function close() - { - rcube_kolab::shutdown(); - } - - - /** - * Create a contact group with the given name - * - * @param string The group name - * @return mixed False on error, array with record props in success - */ - function create_group($name) - { - $this->_fetch_groups(); - $result = false; - - $list = array( - 'uid' => $this->liststorage->generateUID(), - 'last-name' => $name, - 'member' => array(), - ); - $saved = $this->liststorage->save($list); - - if (PEAR::isError($saved)) { - raise_error(array( - 'code' => 600, 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Error saving distribution-list object to Kolab server:" . $saved->getMessage()), - true, false); - return false; - } - else { - $id = md5($list['uid']); - $this->distlists[$record['ID']] = $list; - $result = array('id' => $id, 'name' => $name); - } - - return $result; - } - - /** - * Delete the given group and all linked group members - * - * @param string Group identifier - * @return boolean True on success, false if no data was changed - */ - function delete_group($gid) - { - $this->_fetch_groups(); - $result = false; - - if ($list = $this->distlists[$gid]) - $deleted = $this->liststorage->delete($list['uid']); - - if (PEAR::isError($deleted)) { - raise_error(array( - 'code' => 600, 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Error deleting distribution-list object from the Kolab server:" . $deleted->getMessage()), - true, false); - } - else - $result = true; - - return $result; - } - - /** - * Rename a specific contact group - * - * @param string Group identifier - * @param string New name to set for this group - * @return boolean New name on success, false if no data was changed - */ - function rename_group($gid, $newname) - { - $this->_fetch_groups(); - $list = $this->distlists[$gid]; - - if ($newname != $list['last-name']) { - $list['last-name'] = $newname; - $saved = $this->liststorage->save($list, $list['uid']); - } - - if (PEAR::isError($saved)) { - raise_error(array( - 'code' => 600, 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Error saving distribution-list object to Kolab server:" . $saved->getMessage()), - true, false); - return false; - } - - return $newname; - } - - /** - * Add the given contact records the a certain group - * - * @param string Group identifier - * @param array List of contact identifiers to be added - * @return int Number of contacts added - */ - function add_to_group($gid, $ids) - { - if (!is_array($ids)) - $ids = explode(',', $ids); - - $added = 0; - $exists = array(); - - $this->_fetch_groups(); - $this->_fetch_contacts(); - $list = $this->distlists[$gid]; - - foreach ((array)$list['member'] as $i => $member) - $exists[] = $member['ID']; - - // substract existing assignments from list - $ids = array_diff($ids, $exists); - - foreach ($ids as $contact_id) { - if ($uid = $this->id2uid[$contact_id]) { - $contact = $this->contacts[$contact_id]; - foreach ($this->get_col_values('email', $contact, true) as $email) { - $list['member'][] = array( - 'uid' => $uid, - 'display-name' => $contact['name'], - 'smtp-address' => $email, - ); - } - $this->groupmembers[$contact_id][] = $gid; - $added++; - } - } - - if ($added) - $saved = $this->liststorage->save($list, $list['uid']); - - if (PEAR::isError($saved)) { - raise_error(array( - 'code' => 600, 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Error saving distribution-list to Kolab server:" . $saved->getMessage()), - true, false); - $added = false; - } - else { - $this->distlists[$gid] = $list; - } - - return $added; - } - - /** - * Remove the given contact records from a certain group - * - * @param string Group identifier - * @param array List of contact identifiers to be removed - * @return int Number of deleted group members - */ - function remove_from_group($gid, $ids) - { - if (!is_array($ids)) - $ids = explode(',', $ids); - - $this->_fetch_groups(); - if (!($list = $this->distlists[$gid])) - return false; - - $new_member = array(); - foreach ((array)$list['member'] as $member) { - if (!in_array($member['ID'], $ids)) - $new_member[] = $member; - } - - // write distribution list back to server - $list['member'] = $new_member; - $saved = $this->liststorage->save($list, $list['uid']); - - if (PEAR::isError($saved)) { - raise_error(array( - 'code' => 600, 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Error saving distribution-list object to Kolab server:" . $saved->getMessage()), - true, false); - } - else { - // remove group assigments in local cache - foreach ($ids as $id) { - $j = array_search($gid, $this->groupmembers[$id]); - unset($this->groupmembers[$id][$j]); - } - $this->distlists[$gid] = $list; - return true; - } - - return false; - } - - - /** - * Simply fetch all records and store them in private member vars - */ - private function _fetch_contacts() - { - if (!isset($this->contacts)) { - // read contacts - $this->contacts = $this->id2uid = array(); - foreach ((array)$this->contactstorage->getObjects() as $record) { - $contact = $this->_to_rcube_contact($record); - $id = $contact['ID']; - $this->contacts[$id] = $contact; - $this->id2uid[$id] = $record['uid']; - } - - // TODO: sort data arrays according to desired list sorting - } - } - - - /** - * Read distribution-lists AKA groups from server - */ - private function _fetch_groups() - { - if (!isset($this->distlists)) { - $this->distlists = $this->groupmembers = array(); - foreach ((array)$this->liststorage->getObjects() as $record) { - // FIXME: folders without any distribution-list objects return contacts instead ?! - if ($record['__type'] != 'Group') - continue; - $record['ID'] = md5($record['uid']); - foreach ((array)$record['member'] as $i => $member) { - $mid = md5($member['uid']); - $record['member'][$i]['ID'] = $mid; - $this->groupmembers[$mid][] = $record['ID']; - } - $this->distlists[$record['ID']] = $record; - } - } - } - - - /** - * Map fields from internal Kolab_Format to Roundcube contact format - */ - private function _to_rcube_contact($record) - { - $out = array( - 'ID' => md5($record['uid']), - 'email' => array(), - 'phone' => array(), - ); - - foreach ($this->fieldmap as $kolab => $rcube) { - if (strlen($record[$kolab])) - $out[$rcube] = $record[$kolab]; - } - - if (isset($record['gender'])) - $out['gender'] = $this->gender_map[$record['gender']]; - - foreach ((array)$record['email'] as $i => $email) - $out['email'][] = $email['smtp-address']; - - if (!$record['email'] && $record['emails']) - $out['email'] = preg_split('/,\s*/', $record['emails']); - - foreach ((array)$record['phone'] as $i => $phone) - $out['phone:'.$phone['type']][] = $phone['number']; - - if (is_array($record['address'])) { - foreach ($record['address'] as $i => $adr) { - $key = 'address:' . $adr['type']; - $out[$key][] = array( - 'street' => $adr['street'], - 'locality' => $adr['locality'], - 'zipcode' => $adr['postal-code'], - 'region' => $adr['region'], - 'country' => $adr['country'], - ); - } - } - - // photo is stored as separate attachment - if ($record['picture'] && ($att = $record['_attachments'][$record['picture']])) { - $out['photo'] = $att['content'] ? $att['content'] : $this->contactstorage->getAttachment($att['key']); - } - - // remove empty fields - return array_filter($out); - } - - private function _from_rcube_contact($contact) - { - $object = array(); - - foreach (array_flip($this->fieldmap) as $rcube => $kolab) { - if (isset($contact[$rcube])) - $object[$kolab] = is_array($contact[$rcube]) ? $contact[$rcube][0] : $contact[$rcube]; - else if ($values = $this->get_col_values($rcube, $contact, true)) - $object[$kolab] = is_array($values) ? $values[0] : $values; - } - - // format dates - if ($object['birthday'] && ($date = @strtotime($object['birthday']))) - $object['birthday'] = date('Y-m-d', $date); - if ($object['anniversary'] && ($date = @strtotime($object['anniversary']))) - $object['anniversary'] = date('Y-m-d', $date); - - $gendermap = array_flip($this->gender_map); - if (isset($contact['gender'])) - $object['gender'] = $gendermap[$contact['gender']]; - - $emails = $this->get_col_values('email', $contact, true); - $object['emails'] = join(', ', array_filter($emails)); - - foreach ($this->get_col_values('phone', $contact) as $type => $values) { - if ($this->phonetypemap[$type]) - $type = $this->phonetypemap[$type]; - foreach ((array)$values as $phone) { - if (!empty($phone)) { - $object['phone-' . $type] = $phone; - $object['phone'][] = array('number' => $phone, 'type' => $type); - } - } - } - - foreach ($this->get_col_values('address', $contact) as $type => $values) { - if ($this->addresstypemap[$type]) - $type = $this->addresstypemap[$type]; - - $basekey = 'addr-' . $type . '-'; - foreach ((array)$values as $adr) { - // switch type if slot is already taken - if (isset($object[$basekey . 'type'])) { - $type = $type == 'home' ? 'business' : 'home'; - $basekey = 'addr-' . $type . '-'; - } - - if (!isset($object[$basekey . 'type'])) { - $object[$basekey . 'type'] = $type; - $object[$basekey . 'street'] = $adr['street']; - $object[$basekey . 'locality'] = $adr['locality']; - $object[$basekey . 'postal-code'] = $adr['zipcode']; - $object[$basekey . 'region'] = $adr['region']; - $object[$basekey . 'country'] = $adr['country']; - } - else { - $object['address'][] = array( - 'type' => $type, - 'street' => $adr['street'], - 'locality' => $adr['locality'], - 'postal-code' => $adr['zipcode'], - 'region' => $adr['region'], - 'country' => $adr['country'], - ); - } - } - } - - // save new photo as attachment - if ($contact['photo']) { - $attkey = 'photo.attachment'; - $object['_attachments'][$attkey] = array( - 'type' => rc_image_content_type($contact['photo']), - 'content' => preg_match('![^a-z0-9/=+-]!i', $contact['photo']) ? $contact['photo'] : base64_decode($contact['photo']), - ); - $object['picture'] = $attkey; - } - - return $object; - } - -} |