Page MenuHomePhorge

No OneTemporary

Size
69 KB
Referenced Files
None
Subscribers
None
diff --git a/plugins/kolab_addressbook/kolab_addressbook.php b/plugins/kolab_addressbook/kolab_addressbook.php
index 5a47657d..8abdab6d 100644
--- a/plugins/kolab_addressbook/kolab_addressbook.php
+++ b/plugins/kolab_addressbook/kolab_addressbook.php
@@ -1,590 +1,590 @@
<?php
/**
* Kolab address book
*
* Sample plugin to add a new address book source with data from Kolab storage
* It provides also a possibilities to manage contact folders
* (create/rename/delete/acl) directly in Addressbook UI.
*
* @version @package_version@
* @author Thomas Bruederli <bruederli@kolabsys.com>
* @author Aleksander Machniak <machniak@kolabsys.com>
*
* Copyright (C) 2011, Kolab Systems AG <contact@kolabsys.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class kolab_addressbook extends rcube_plugin
{
public $task = 'mail|settings|addressbook|calendar';
private $folders;
private $sources;
private $rc;
private $ui;
const GLOBAL_FIRST = 0;
const PERSONAL_FIRST = 1;
const GLOBAL_ONLY = 2;
const PERSONAL_ONLY = 3;
/**
* Startup method of a Roundcube plugin
*/
public function init()
{
require_once(dirname(__FILE__) . '/lib/rcube_kolab_contacts.php');
$this->rc = rcmail::get_instance();
// load required plugin
- $this->require_plugin('kolab_core');
+ $this->require_plugin('libkolab');
// register hooks
$this->add_hook('addressbooks_list', array($this, 'address_sources'));
$this->add_hook('addressbook_get', array($this, 'get_address_book'));
$this->add_hook('config_get', array($this, 'config_get'));
if ($this->rc->task == 'addressbook') {
$this->add_texts('localization');
$this->add_hook('contact_form', array($this, 'contact_form'));
// Plugin actions
$this->register_action('plugin.book', array($this, 'book_actions'));
$this->register_action('plugin.book-save', array($this, 'book_save'));
// Load UI elements
if ($this->api->output->type == 'html') {
require_once($this->home . '/lib/kolab_addressbook_ui.php');
$this->ui = new kolab_addressbook_ui($this);
}
}
else if ($this->rc->task == 'settings') {
$this->add_texts('localization');
$this->add_hook('preferences_list', array($this, 'prefs_list'));
$this->add_hook('preferences_save', array($this, 'prefs_save'));
}
}
/**
* Handler for the addressbooks_list hook.
*
* This will add all instances of available Kolab-based address books
* to the list of address sources of Roundcube.
* This will also hide some addressbooks according to kolab_addressbook_prio setting.
*
* @param array $p Hash array with hook parameters
*
* @return array Hash array with modified hook parameters
*/
public function address_sources($p)
{
// Load configuration
$this->load_config();
$abook_prio = (int) $this->rc->config->get('kolab_addressbook_prio');
$undelete = $this->rc->config->get('undo_timeout');
// Disable all global address books
// Assumes that all non-kolab_addressbook sources are global
if ($abook_prio == self::PERSONAL_ONLY) {
$p['sources'] = array();
}
$sources = array();
$names = array();
foreach ($this->_list_sources() as $abook_id => $abook) {
$name = $origname = $abook->get_name();
// find folder prefix to truncate
for ($i = count($names)-1; $i >= 0; $i--) {
if (strpos($name, $names[$i].' &raquo; ') === 0) {
$length = strlen($names[$i].' &raquo; ');
$prefix = substr($name, 0, $length);
$count = count(explode(' &raquo; ', $prefix));
$name = str_repeat('&nbsp;&nbsp;', $count-1) . '&raquo; ' . substr($name, $length);
break;
}
}
$names[] = $origname;
// register this address source
$sources[$abook_id] = array(
'id' => $abook_id,
'name' => $name,
'readonly' => $abook->readonly,
'editable' => $abook->editable,
'groups' => $abook->groups,
'undelete' => $abook->undelete && $undelete,
'realname' => rcube_charset::convert($abook->get_realname(), 'UTF7-IMAP'), // IMAP folder name
'class_name' => $abook->get_namespace(),
'kolab' => true,
);
}
// Add personal address sources to the list
if ($abook_prio == self::PERSONAL_FIRST) {
// $p['sources'] = array_merge($sources, $p['sources']);
// Don't use array_merge(), because if you have folders name
// that resolve to numeric identifier it will break output array keys
foreach ($p['sources'] as $idx => $value)
$sources[$idx] = $value;
$p['sources'] = $sources;
}
else {
// $p['sources'] = array_merge($p['sources'], $sources);
foreach ($sources as $idx => $value)
$p['sources'][$idx] = $value;
}
return $p;
}
/**
* Sets autocomplete_addressbooks option according to
* kolab_addressbook_prio setting extending list of address sources
* to be used for autocompletion.
*/
public function config_get($args)
{
if ($args['name'] != 'autocomplete_addressbooks') {
return $args;
}
// Load configuration
$this->load_config();
$abook_prio = (int) $this->rc->config->get('kolab_addressbook_prio');
// here we cannot use rc->config->get()
$sources = $GLOBALS['CONFIG']['autocomplete_addressbooks'];
// Disable all global address books
// Assumes that all non-kolab_addressbook sources are global
if ($abook_prio == self::PERSONAL_ONLY) {
$sources = array();
}
if (!is_array($sources)) {
$sources = array();
}
$kolab_sources = array();
foreach ($this->_list_sources() as $abook_id => $abook) {
if (!in_array($abook_id, $sources))
$kolab_sources[] = $abook_id;
}
// Add personal address sources to the list
if (!empty($kolab_sources)) {
if ($abook_prio == self::PERSONAL_FIRST) {
$sources = array_merge($kolab_sources, $sources);
}
else {
$sources = array_merge($sources, $kolab_sources);
}
}
$args['result'] = $sources;
return $args;
}
/**
* Getter for the rcube_addressbook instance
*
* @param array $p Hash array with hook parameters
*
* @return array Hash array with modified hook parameters
*/
public function get_address_book($p)
{
if ($p['id']) {
$this->_list_sources();
if ($this->sources[$p['id']]) {
$p['instance'] = $this->sources[$p['id']];
}
}
return $p;
}
private function _list_sources()
{
// already read sources
if (isset($this->sources))
return $this->sources;
$this->sources = array();
// Load configuration
$this->load_config();
$abook_prio = (int) $this->rc->config->get('kolab_addressbook_prio');
// Personal address source(s) disabled?
if ($abook_prio == self::GLOBAL_ONLY) {
return $this->sources;
}
// get all folders that have "contact" type
- $this->folders = rcube_kolab::get_folders('contact');
+ $this->folders = kolab_storage::get_folders('contact');
if (PEAR::isError($this->folders)) {
raise_error(array(
'code' => 600, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Failed to list contact folders from Kolab server:" . $this->folders->getMessage()),
true, false);
}
else {
// convert to UTF8 and sort
$names = array();
foreach ($this->folders as $c_folder)
$names[$c_folder->name] = rcube_charset::convert($c_folder->name, 'UTF7-IMAP');
asort($names, SORT_LOCALE_STRING);
foreach ($names as $utf7name => $name) {
// create instance of rcube_contacts
- $abook_id = rcube_kolab::folder_id($utf7name);
+ $abook_id = kolab_storage::folder_id($utf7name);
$abook = new rcube_kolab_contacts($utf7name);
$this->sources[$abook_id] = $abook;
}
}
return $this->sources;
}
/**
* Plugin hook called before rendering the contact form or detail view
*
* @param array $p Hash array with hook parameters
*
* @return array Hash array with modified hook parameters
*/
public function contact_form($p)
{
// none of our business
if (!is_object($GLOBALS['CONTACTS']) || !is_a($GLOBALS['CONTACTS'], 'rcube_kolab_contacts'))
return $p;
// extend the list of contact fields to be displayed in the 'personal' section
if (is_array($p['form']['personal'])) {
$p['form']['contact']['content']['officelocation'] = array('size' => 40);
$p['form']['personal']['content']['initials'] = array('size' => 6);
$p['form']['personal']['content']['profession'] = array('size' => 40);
$p['form']['personal']['content']['children'] = array('size' => 40);
$p['form']['personal']['content']['pgppublickey'] = array('size' => 40);
$p['form']['personal']['content']['freebusyurl'] = array('size' => 40);
// re-order fields according to the coltypes list
$p['form']['contact']['content'] = $this->_sort_form_fields($p['form']['contact']['content']);
$p['form']['personal']['content'] = $this->_sort_form_fields($p['form']['personal']['content']);
/* define a separate section 'settings'
$p['form']['settings'] = array(
'name' => $this->gettext('settings'),
'content' => array(
'pgppublickey' => array('size' => 40, 'visible' => true),
'freebusyurl' => array('size' => 40, 'visible' => true),
)
);
*/
}
return $p;
}
private function _sort_form_fields($contents)
{
$block = array();
$contacts = reset($this->sources);
foreach ($contacts->coltypes as $col => $prop) {
if (isset($contents[$col]))
$block[$col] = $contents[$col];
}
return $block;
}
/**
* Handler for user preferences form (preferences_list hook)
*
* @param array $args Hash array with hook parameters
*
* @return array Hash array with modified hook parameters
*/
public function prefs_list($args)
{
if ($args['section'] != 'addressbook') {
return $args;
}
// Load configuration
$this->load_config();
// Load localization
$this->add_texts('localization');
// Check that configuration is not disabled
$dont_override = (array) $this->rc->config->get('dont_override', array());
if (!in_array('kolab_addressbook_prio', $dont_override)) {
$field_id = '_kolab_addressbook_prio';
$select = new html_select(array('name' => $field_id, 'id' => $field_id));
$select->add($this->gettext('globalfirst'), self::GLOBAL_FIRST);
$select->add($this->gettext('personalfirst'), self::PERSONAL_FIRST);
$select->add($this->gettext('globalonly'), self::GLOBAL_ONLY);
$select->add($this->gettext('personalonly'), self::PERSONAL_ONLY);
$args['blocks']['main']['options']['kolab_addressbook_prio'] = array(
'title' => html::label($field_id, Q($this->gettext('addressbookprio'))),
'content' => $select->show((int)$this->rc->config->get('kolab_addressbook_prio')),
);
}
return $args;
}
/**
* Handler for user preferences save (preferences_save hook)
*
* @param array $args Hash array with hook parameters
*
* @return array Hash array with modified hook parameters
*/
public function prefs_save($args)
{
if ($args['section'] != 'addressbook') {
return $args;
}
// Load configuration
$this->load_config();
// Check that configuration is not disabled
$dont_override = (array) $this->rc->config->get('dont_override', array());
if (!in_array('kolab_addressbook_prio', $dont_override)) {
$key = 'kolab_addressbook_prio';
$args['prefs'][$key] = (int) get_input_value('_'.$key, RCUBE_INPUT_POST);
}
return $args;
}
/**
* Handler for plugin actions
*/
public function book_actions()
{
$action = trim(get_input_value('_act', RCUBE_INPUT_GPC));
if ($action == 'create') {
$this->ui->book_edit();
}
else if ($action == 'edit') {
$this->ui->book_edit();
}
else if ($action == 'delete') {
$this->book_delete();
}
}
/**
* Handler for address book create/edit form submit
*/
public function book_save()
{
$storage = $this->rc->get_storage();
$folder = trim(get_input_value('_name', RCUBE_INPUT_POST, true, 'UTF7-IMAP'));
$oldfolder = trim(get_input_value('_oldname', RCUBE_INPUT_POST, true)); // UTF7-IMAP
$path = trim(get_input_value('_parent', RCUBE_INPUT_POST, true)); // UTF7-IMAP
$delimiter = $storage->get_hierarchy_delimiter();
if (strlen($oldfolder)) {
$options = $storage->folder_info($oldfolder);
}
if (!empty($options) && ($options['norename'] || $options['protected'])) {
}
// sanity checks (from steps/settings/save_folder.inc)
else if (!strlen($folder)) {
$error = rcube_label('cannotbeempty');
}
else if (strlen($folder) > 128) {
$error = rcube_label('nametoolong');
}
else {
// these characters are problematic e.g. when used in LIST/LSUB
foreach (array($delimiter, '%', '*') as $char) {
if (strpos($folder, $delimiter) !== false) {
$error = rcube_label('forbiddencharacter') . " ($char)";
break;
}
}
}
if (!$error) {
if (!empty($options) && ($options['protected'] || $options['norename'])) {
$folder = $oldfolder;
}
else if (strlen($path)) {
$folder = $path . $delimiter . $folder;
}
else {
// add namespace prefix (when needed)
$folder = $storage->mod_folder($folder, 'in');
}
// Check access rights to the parent folder
if (strlen($path) && (!strlen($oldfolder) || $oldfolder != $folder)) {
$parent_opts = $storage->folder_info($path);
if ($parent_opts['namespace'] != 'personal'
&& (empty($parent_opts['rights']) || !preg_match('/[ck]/', implode($parent_opts)))
) {
$error = rcube_label('parentnotwritable');
}
}
}
if (!$error) {
// update the folder name
if (strlen($oldfolder)) {
$type = 'update';
$plugin = $this->rc->plugins->exec_hook('addressbook_update', array(
'name' => $folder, 'oldname' => $oldfolder));
if (!$plugin['abort']) {
if ($oldfolder != $folder)
- $result = rcube_kolab::folder_rename($oldfolder, $folder);
+ $result = kolab_storage::folder_rename($oldfolder, $folder);
else
$result = true;
}
else {
$result = $plugin['result'];
}
}
// create new folder
else {
$type = 'create';
$plugin = $this->rc->plugins->exec_hook('addressbook_create', array('name' => $folder));
$folder = $plugin['name'];
if (!$plugin['abort']) {
- $result = rcube_kolab::folder_create($folder, 'contact', false);
+ $result = kolab_storage::folder_create($folder, 'contact', false);
}
else {
$result = $plugin['result'];
}
}
}
if ($result) {
$kolab_folder = new rcube_kolab_contacts($folder);
// create display name for the folder (see self::address_sources())
if (strpos($folder, $delimiter)) {
$names = array();
foreach ($this->_list_sources() as $abook_id => $abook) {
$realname = $abook->get_realname();
// The list can be not updated yet, handle old folder name
if ($type == 'update' && $realname == $oldfolder) {
$abook = $kolab_folder;
$realname = $folder;
}
$name = $origname = $abook->get_name();
// find folder prefix to truncate
for ($i = count($names)-1; $i >= 0; $i--) {
if (strpos($name, $names[$i].' &raquo; ') === 0) {
$length = strlen($names[$i].' &raquo; ');
$prefix = substr($name, 0, $length);
$count = count(explode(' &raquo; ', $prefix));
$name = str_repeat('&nbsp;&nbsp;', $count-1) . '&raquo; ' . substr($name, $length);
break;
}
}
$names[] = $origname;
if ($realname == $folder) {
break;
}
}
}
else {
$name = $kolab_folder->get_name();
}
$this->rc->output->show_message('kolab_addressbook.book'.$type.'d', 'confirmation');
$this->rc->output->command('set_env', 'delimiter', $delimiter);
$this->rc->output->command('book_update', array(
- 'id' => rcube_kolab::folder_id($folder),
+ 'id' => kolab_storage::folder_id($folder),
'name' => $name,
'readonly' => false,
'editable' => true,
'groups' => true,
'realname' => rcube_charset::convert($folder, 'UTF7-IMAP'), // IMAP folder name
'class_name' => $kolab_folder->get_namespace(),
'kolab' => true,
- ), rcube_kolab::folder_id($oldfolder));
+ ), kolab_storage::folder_id($oldfolder));
$this->rc->output->send('iframe');
}
if (!$error)
$error = $plugin['message'] ? $plugin['message'] : 'kolab_addressbook.book'.$type.'error';
$this->rc->output->show_message($error, 'error');
// display the form again
$this->ui->book_edit();
}
/**
* Handler for address book delete action (AJAX)
*/
private function book_delete()
{
$folder = trim(get_input_value('_source', RCUBE_INPUT_GPC, true, 'UTF7-IMAP'));
- if (rcube_kolab::folder_delete($folder)) {
+ if (kolab_storage::folder_delete($folder)) {
$this->rc->output->show_message('kolab_addressbook.bookdeleted', 'confirmation');
$this->rc->output->set_env('pagecount', 0);
$this->rc->output->command('set_rowcount', rcmail_get_rowcount_text(new rcube_result_set()));
$this->rc->output->command('list_contacts_clear');
- $this->rc->output->command('book_delete_done', rcube_kolab::folder_id($folder));
+ $this->rc->output->command('book_delete_done', kolab_storage::folder_id($folder));
}
else {
$this->rc->output->show_message('kolab_addressbook.bookdeleteerror', 'error');
}
$this->rc->output->send();
}
}
diff --git a/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php b/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php
index f028f522..08ba20a8 100644
--- a/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php
+++ b/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php
@@ -1,1232 +1,1119 @@
<?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
+ * rcube_addressbook interface with the kolab_storage wrapper from libkolab
*
* @author Thomas Bruederli <bruederli@kolabsys.com>
* @author Aleksander Machniak <machniak@kolabsys.com>
*
* Copyright (C) 2011, Kolab Systems AG <contact@kolabsys.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @see rcube_addressbook
*/
class rcube_kolab_contacts extends rcube_addressbook
{
public $primary_key = 'ID';
public $readonly = true;
public $editable = false;
public $undelete = true;
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),
'email' => array('subtypes' => null),
'phone' => array(),
- 'address' => array('limit' => 2, 'subtypes' => array('home','business')),
+ 'address' => array('subtypes' => array('home','business')),
'officelocation' => array('type' => 'text', 'size' => 40, 'maxlength' => 50, 'limit' => 1,
'label' => 'kolab_addressbook.officelocation', 'category' => 'main'),
- 'website' => array('limit' => 1, 'subtypes' => null),
- 'im' => array('limit' => 1, 'subtypes' => null),
+ 'website' => array('subtypes' => null),
+ 'im' => array('subtypes' => null),
'gender' => array('limit' => 1),
'initials' => array('type' => 'text', 'size' => 6, 'maxlength' => 10, 'limit' => 1,
'label' => 'kolab_addressbook.initials', 'category' => 'personal'),
'birthday' => array('limit' => 1),
'anniversary' => array('limit' => 1),
'profession' => array('type' => 'text', 'size' => 40, 'maxlength' => 80, 'limit' => 1,
'label' => 'kolab_addressbook.profession', 'category' => 'personal'),
'manager' => array('limit' => 1),
'assistant' => array('limit' => 1),
'spouse' => array('limit' => 1),
'children' => array('type' => 'text', 'size' => 40, 'maxlength' => 80, 'limit' => 1,
'label' => 'kolab_addressbook.children', 'category' => 'personal'),
'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
+ // TODO: define more Kolab-specific fields such as: role, language, latitude, longitude
);
/**
* vCard additional fields mapping
*/
public $vcard_map = array(
'profession' => 'X-PROFESSION',
'officelocation' => 'X-OFFICE-LOCATION',
'initials' => 'X-INITIALS',
'children' => 'X-CHILDREN',
'freebusyurl' => 'X-FREEBUSY-URL',
'pgppublickey' => 'KEY',
);
private $gid;
private $storagefolder;
- private $contactstorage;
- private $liststorage;
private $contacts;
private $distlists;
private $groupmembers;
- private $id2uid;
private $filter;
private $result;
private $namespace;
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',
- 'gender' => 'gender',
- );
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;
+ $format = kolab_format::factory('contact');
+ $this->coltypes['phone']['subtypes'] = array_keys($format->phonetypes);
+ $this->coltypes['address']['subtypes'] = array_keys($format->addresstypes);
// 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->storagefolder = rcube_kolab::get_folder($this->imap_folder);
+ $this->storagefolder = kolab_storage::get_folder($this->imap_folder);
$this->ready = !PEAR::isError($this->storagefolder);
// Set readonly and editable flags according to folder permissions
if ($this->ready) {
- if ($this->get_owner() == $_SESSION['username']) {
+ if ($this->storagefolder->get_owner() == $_SESSION['username']) {
$this->editable = true;
$this->readonly = false;
}
else {
- $rights = $this->storagefolder->getMyRights();
+ $rights = $this->storagefolder->get_acl();
if (!PEAR::isError($rights)) {
if (strpos($rights, 'i') !== false)
$this->readonly = false;
if (strpos($rights, 'a') !== false || strpos($rights, 'x') !== false)
$this->editable = true;
}
}
}
}
/**
* Getter for the address book name to be displayed
*
* @return string Name of this address book
*/
public function get_name()
{
- $folder = rcube_kolab::object_name($this->imap_folder, $this->namespace);
+ $folder = kolab_storage::object_name($this->imap_folder, $this->namespace);
return $folder;
}
/**
* Getter for the IMAP folder name
*
* @return string Name of the IMAP folder
*/
public function get_realname()
{
return $this->imap_folder;
}
- /**
- * Getter for the IMAP folder owner
- *
- * @return string Name of the folder owner
- */
- public function get_owner()
- {
- return $this->storagefolder->getOwner();
- }
-
-
/**
* Getter for the name of the namespace to which the IMAP folder belongs
*
* @return string Name of the namespace (personal, other, shared)
*/
public function get_namespace()
{
if ($this->namespace === null) {
- $this->namespace = rcube_kolab::folder_namespace($this->imap_folder);
+ $this->namespace = $this->storagefolder->get_namespace();
}
return $this->namespace;
}
/**
* 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[$group['last-name']] = array('ID' => $group['ID'], 'name' => $group['last-name']);
+ if (!$search || strstr(strtolower($group['name']), strtolower($search)))
+ $groups[$group['name']] = array('ID' => $group['ID'], 'name' => $group['name']);
}
// sort groups
ksort($groups, SORT_LOCALE_STRING);
return array_values($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
+ else {
+ $this->_fetch_contacts();
$ids = is_array($this->filter['ids']) ? $this->filter['ids'] : array_keys($this->contacts);
+ }
// sort data arrays according to desired list sorting
if ($count = count($ids)) {
uasort($this->contacts, array($this, '_sort_contacts_comp'));
// get sorted IDs
if ($count != count($this->contacts))
$ids = array_values(array_intersect(array_keys($this->contacts), $ids));
else
$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);
for ($i = $start_row; $i < $last_row; $i++) {
if ($id = $ids[$i])
$this->result->add($this->contacts[$id]);
}
return $this->result;
}
/**
* Search records
*
* @param mixed $fields The field name of array of field names to search in
* @param mixed $value Search value (or array of values when $fields is array)
* @param int $mode Matching mode:
* 0 - partial (*abc*),
* 1 - strict (=),
* 2 - prefix (abc*)
* @param boolean $select True if results are requested, False if count only
* @param boolean $nocount True to skip the count query (select only)
* @param array $required List of fields that cannot be empty
*
* @return object rcube_result_set List of contact records and 'count' value
*/
public function search($fields, $value, $mode=0, $select=true, $nocount=false, $required=array())
{
$this->_fetch_contacts();
// search by ID
if ($fields == $this->primary_key) {
$ids = !is_array($value) ? explode(',', $value) : $value;
$result = new rcube_result_set();
foreach ($ids as $id) {
if ($rec = $this->get_record($id, true)) {
$result->add($rec);
$result->count++;
}
}
return $result;
}
else if ($fields == '*') {
$fields = array_keys($this->coltypes);
}
if (!is_array($fields))
$fields = array($fields);
if (!is_array($required) && !empty($required))
$required = array($required);
// advanced search
if (is_array($value)) {
$advanced = true;
$value = array_map('mb_strtolower', $value);
}
else
$value = mb_strtolower($value);
$scount = count($fields);
// build key name regexp
$regexp = '/^(' . implode($fields, '|') . ')(?:.*)$/';
// save searching conditions
$this->filter = array('fields' => $fields, 'value' => $value, 'mode' => $mode, '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;
}
$found = array();
foreach (preg_grep($regexp, array_keys($contact)) as $col) {
if ($advanced) {
$pos = strpos($col, ':');
$colname = $pos ? substr($col, 0, $pos) : $col;
$search = $value[array_search($colname, $fields)];
}
else {
$search = $value;
}
foreach ((array)$contact[$col] as $val) {
$val = mb_strtolower($val);
switch ($mode) {
case 1:
$got = ($val == $search);
break;
case 2:
$got = ($search == substr($val, 0, strlen($search)));
break;
default:
$got = (strpos($val, $search) !== false);
break;
}
if ($got) {
if (!$advanced) {
$this->filter['ids'][] = $id;
break 2;
}
else {
$found[$colname] = true;
}
}
}
}
if (count($found) >= $scount) // && $advanced
$this->filter['ids'][] = $id;
}
// 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['mode']);
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));
+ if ($this->gid) {
+ $this->_fetch_groups();
+ $count = count($this->distlists[$this->gid]['member']);
+ }
+ else if (is_array($this->filter['ids'])) {
+ $count = count($this->filter['ids']);
+ }
+ else {
+ $count = $this->storagefolder->count();
+ }
+
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]) {
+ if ($object = $this->storagefolder->get_object($this->_id2uid($id))) {
+ $rec = $this->_to_rcube_contact($object);
$this->result = new rcube_result_set(1);
- $this->result->add($this->contacts[$id]);
- return $assoc ? $this->contacts[$id] : $this->result;
+ $this->result->add($rec);
+ return $assoc ? $rec : $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'];
+ $out[$gid] = $group['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) {
- $this->_connect();
-
// generate new Kolab contact item
$object = $this->_from_rcube_contact($save_data);
- $object['uid'] = $this->contactstorage->generateUID();
+ $object['uid'] = kolab_format::generate_uid();
- $saved = $this->contactstorage->save($object);
+ $saved = $this->storagefolder->save($object, 'contact');
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);
+ if ($old = $this->storagefolder->get_object($this->_id2uid($id))) {
$object = array_merge($old, $this->_from_rcube_contact($save_data));
- $saved = $this->contactstorage->save($object, $uid);
- if (PEAR::isError($saved)) {
+ $saved = $this->storagefolder->save($object, 'contact', $uid);
+ if (!$saved || PEAR::isError($saved)) {
raise_error(array(
'code' => 600, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Error saving contact object to Kolab server:" . $saved->getMessage()),
+ 'message' => "Error saving contact object to Kolab server"),
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
* @param boolean Remove record(s) irreversible (mark as deleted otherwise)
*
* @return int Number of records deleted
*/
public function delete($ids, $force=true)
{
- $this->_fetch_contacts();
$this->_fetch_groups();
if (!is_array($ids))
$ids = explode(',', $ids);
$count = 0;
- $imap_uids = array();
-
foreach ($ids as $id) {
- if ($uid = $this->id2uid[$id]) {
- $imap_uid = $this->contactstorage->_getStorageId($uid);
- $deleted = $this->contactstorage->delete($uid, $force);
+ if ($uid = $this->_id2uid($id)) {
+ $deleted = $this->storagefolder->delete($uid, $force);
- if (PEAR::isError($deleted)) {
+ if (!$deleted) {
raise_error(array(
'code' => 600, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
- 'message' => "Error deleting a contact object from the Kolab server:" . $deleted->getMessage()),
+ 'message' => "Error deleting a contact object from the Kolab server"),
true, false);
}
else {
// remove from distribution lists
foreach ((array)$this->groupmembers[$id] as $gid)
$this->remove_from_group($gid, $id);
- $imap_uids[$id] = $imap_uid;
// clear internal cache
- unset($this->contacts[$id], $this->id2uid[$id], $this->groupmembers[$id]);
+ unset($this->contacts[$id], $this->groupmembers[$id]);
$count++;
}
}
}
- // store IMAP uids for undelete()
- if (!$force) {
- $_SESSION['kolab_delete_uids'] = $imap_uids;
- }
-
return $count;
}
/**
* Undelete one or more contact records.
* Only possible just after delete (see 2nd argument of delete() method).
*
* @param array Record identifiers
*
* @return int Number of records restored
*/
public function undelete($ids)
{
if (!is_array($ids))
$ids = explode(',', $ids);
$count = 0;
$uids = array();
+/*
+ TODO: re-implement this using kolab_storage_folder::undelete();
+
$imap_uids = $_SESSION['kolab_delete_uids'];
// convert contact IDs into IMAP UIDs
foreach ($ids as $id)
if ($uid = $imap_uids[$id])
$uids[] = $uid;
if (!empty($uids)) {
$session = &Horde_Kolab_Session::singleton();
$imap = &$session->getImap();
if (is_object($imap) && is_a($imap, 'PEAR_Error')) {
$error = $imap;
}
else {
$result = $imap->select($this->imap_folder);
if (is_object($result) && is_a($result, 'PEAR_Error')) {
$error = $result;
}
else {
$result = $imap->undeleteMessages(implode(',', $uids));
if (is_object($result) && is_a($result, 'PEAR_Error')) {
$error = $result;
}
else {
$this->_connect();
- $this->contactstorage->synchronize();
+ $this->storagefolder->synchronize();
}
}
}
if ($error) {
raise_error(array(
'code' => 600, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Error undeleting a contact object(s) from the Kolab server:" . $error->getMessage()),
true, false);
}
$rcmail = rcmail::get_instance();
$rcmail->session->remove('kolab_delete_uids');
}
-
+*/
return count($uids);
}
/**
* Remove all records from the database
*/
public function delete_all()
{
- $this->_connect();
-
- if (!PEAR::isError($this->contactstorage->deleteAll())) {
+ if ($this->storagefolder->delete_all()) {
$this->contacts = array();
- $this->id2uid = array();
$this->result = null;
}
}
/**
* Close connection to source
* Called on script shutdown
*/
public function close()
{
}
/**
* 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,
+ 'uid' => kolab_format::generate_uid(),
+ 'name' => $name,
'member' => array(),
);
- $saved = $this->liststorage->save($list);
+ $saved = $this->storagefolder->save($list, 'distribution-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[$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']);
+ $deleted = $this->storagefolder->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 ($newname != $list['name']) {
+ $list['name'] = $newname;
+ $saved = $this->storagefolder->save($list, 'distribution-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]) {
+ 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']);
+ $saved = $this->storagefolder->save($list, 'distribution-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']);
+ $saved = $this->storagefolder->save($list, 'distribution-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;
}
/**
* Check the given data before saving.
* If input not valid, the message to display can be fetched using get_error()
*
* @param array Associative array with contact data to save
*
* @return boolean True if input is valid, False if not.
*/
public function validate($save_data)
{
// validate e-mail addresses
$valid = parent::validate($save_data);
// require at least one e-mail address (syntax check is already done)
if ($valid) {
if (!strlen($save_data['name'])
&& !array_filter($this->get_col_values('email', $save_data, true))
) {
$this->set_error('warning', 'kolab_addressbook.noemailnamewarning');
$valid = false;
}
}
return $valid;
}
- /**
- * Establishes a connection to the Kolab_Data object for accessing contact data
- */
- private function _connect()
- {
- if (!isset($this->contactstorage)) {
- $this->contactstorage = $this->storagefolder->getData(null);
- }
- }
-
- /**
- * Establishes a connection to the Kolab_Data object for accessing groups data
- */
- private function _connect_groups()
- {
- if (!isset($this->liststorage)) {
- $this->liststorage = $this->storagefolder->getData('distributionlist');
- }
- }
-
/**
* Simply fetch all records and store them in private member vars
*/
private function _fetch_contacts()
{
if (!isset($this->contacts)) {
- $this->_connect();
-
- // read contacts
- $this->contacts = $this->id2uid = array();
- foreach ((array)$this->contactstorage->getObjects() as $record) {
+ $this->contacts = array();
+ foreach ((array)$this->storagefolder->get_objects() as $record) {
// Because of a bug, sometimes group records are returned
if ($record['__type'] == 'Group')
continue;
$contact = $this->_to_rcube_contact($record);
$id = $contact['ID'];
$this->contacts[$id] = $contact;
- $this->id2uid[$id] = $record['uid'];
}
}
}
/**
* Callback function for sorting contacts
*/
private function _sort_contacts_comp($a, $b)
{
$a_value = $b_value = '';
switch ($this->sort_col) {
case 'name':
$a_value = $a['name'] . $a['prefix'];
$b_value = $b['name'] . $b['prefix'];
case 'firstname':
$a_value .= $a['firstname'] . $a['middlename'] . $a['surname'];
$b_value .= $b['firstname'] . $b['middlename'] . $b['surname'];
break;
case 'surname':
$a_value = $a['surname'] . $a['firstname'] . $a['middlename'];
$b_value = $b['surname'] . $b['firstname'] . $b['middlename'];
break;
default:
$a_value = $a[$this->sort_col];
$b_value = $b[$this->sort_col];
break;
}
$a_value .= is_array($a['email']) ? $a['email'][0] : $a['email'];
$b_value .= is_array($b['email']) ? $b['email'][0] : $b['email'];
// return strcasecmp($a_value, $b_value);
// make sorting unicode-safe and locale-dependent
if ($a_value == $b_value)
return 0;
$arr = array($a_value, $b_value);
sort($arr, SORT_LOCALE_STRING);
return $a_value == $arr[0] ? -1 : 1;
}
/**
* Read distribution-lists AKA groups from server
*/
private function _fetch_groups()
{
if (!isset($this->distlists)) {
- $this->_connect_groups();
-
$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)$this->storagefolder->get_objects('distribution-list') as $record) {
+ $record['ID'] = $this->_uid2id($record['uid']);
foreach ((array)$record['member'] as $i => $member) {
- $mid = md5($member['uid']);
+ $mid = $this->_uid2id($member['uid']);
$record['member'][$i]['ID'] = $mid;
$this->groupmembers[$mid][] = $record['ID'];
}
$this->distlists[$record['ID']] = $record;
}
}
}
+ /**
+ * Encode object UID into a safe identifier
+ */
+ private function _uid2id($uid)
+ {
+ return rtrim(strtr(base64_encode($uid), '+/', '-_'), '=');
+ }
+
+ /**
+ * Convert Roundcube object identifier back into the original UID
+ */
+ private function _id2uid($id)
+ {
+ return base64_decode(str_pad(strtr($id, '-_', '+/'), strlen($id) % 4, '=', STR_PAD_RIGHT));
+ }
+
/**
* 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];
+ $record['ID'] = $this->_uid2id($record['uid']);
+
+ if (is_array($record['phone'])) {
+ $phones = $record['phone'];
+ unset($record['phone']);
+ foreach ((array)$phones as $i => $phone) {
+ $key = 'phone' . ($phone['type'] ? ':' . $phone['type'] : '');
+ $record[$key][] = $phone['number'];
+ }
}
- 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'],
+ $addresses = $record['address'];
+ unset($record['address']);
+ foreach ($addresses as $i => $adr) {
+ $key = 'address' . ($adr['type'] ? ':' . $adr['type'] : '');
+ $record[$key][] = array(
+ 'street' => $adr['street'],
'locality' => $adr['locality'],
- 'zipcode' => $adr['postal-code'],
- 'region' => $adr['region'],
- 'country' => $adr['country'],
+ 'zipcode' => $adr['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']);
+ if ($record['photo'] && ($att = $record['_attachments'][$record['photo']])) {
+ $out['photo'] = $att['content'] ? $att['content'] : $this->storagefolder->get_attachment($record['uid'], $att['key']);
}
// remove empty fields
- return array_filter($out);
+ return array_filter($record);
}
/**
* Map fields from Roundcube format to internal Kolab_Format
*/
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;
- }
+ if (!$contact['uid'] && $contact['ID'])
+ $contact['uid'] = $this->_id2uid($contact['ID']);
+/*
// 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($object['gender']))
- $object['gender'] = $gendermap[$object['gender']];
-
- $emails = $this->get_col_values('email', $contact, true);
- $object['emails'] = join(', ', array_filter($emails));
- // overwrite 'email' field
- $object['email'] = null;
+*/
+ $contact['email'] = array_filter($this->get_col_values('email', $contact, true));
+ $contact['website'] = array_filter($this->get_col_values('website', $contact, true));
+ $contact['im'] = array_filter($this->get_col_values('im', $contact, true));
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);
+ $contact['phone'][] = array('number' => $phone, 'type' => $type);
}
}
}
- $object['address'] = array();
-
+ $addresses = array();
foreach ($this->get_col_values('address', $contact) as $type => $values) {
- if ($this->addresstypemap[$type])
- $type = $this->addresstypemap[$type];
-
- $updated = false;
- $basekey = 'addr-' . $type . '-';
foreach ((array)$values as $adr) {
// skip empty address
$adr = array_filter($adr);
if (empty($adr))
continue;
- // 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'];
-
- // Update existing address entry of this type
- foreach($object['address'] as $index => $address) {
- if ($address['type'] == $type) {
- $object['address'][$index] = $new_address;
- $updated = true;
- }
- }
- }
- if (!$updated) {
- $object['address'][] = array(
- 'type' => $type,
- 'street' => $adr['street'],
- 'locality' => $adr['locality'],
- 'postal-code' => $adr['zipcode'],
- 'region' => $adr['region'],
- 'country' => $adr['country'],
- );
- }
+ $addresses[] = array(
+ 'type' => $type,
+ 'street' => $adr['street'],
+ 'locality' => $adr['locality'],
+ 'code' => $adr['zipcode'],
+ 'region' => $adr['region'],
+ 'country' => $adr['country'],
+ );
}
+
+ unset($contact['address:'.$type]);
}
+ $contact['address'] = $addresses;
// save new photo as attachment
if ($contact['photo']) {
$attkey = 'photo.attachment';
- $object['_attachments'][$attkey] = array(
+ $contact['_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;
+ $contact['photo'] = $attkey;
}
- return $object;
+ return $contact;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Aug 17, 8:24 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1261601
Default Alt Text
(69 KB)

Event Timeline