From a69febd59f5a243e04c82006d6fda05a787aefd4 Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Thu, 23 Jun 2011 10:31:45 +0200 Subject: [PATCH 1/9] Fix folder_list handler. Folders table rows are indexed starting with 1. --- plugins/kolab_folders/kolab_folders.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/kolab_folders/kolab_folders.php b/plugins/kolab_folders/kolab_folders.php index 60f37b12..b5d676cc 100644 --- a/plugins/kolab_folders/kolab_folders.php +++ b/plugins/kolab_folders/kolab_folders.php @@ -137,7 +137,7 @@ class kolab_folders extends rcube_plugin // Add type-based style for table rows // See kolab_folders::folder_class_name() - for ($i=0, $cnt=$table->size(); $i<$cnt; $i++) { + for ($i=1, $cnt=$table->size(); $i<=$cnt; $i++) { $attrib = $table->get_row_attribs($i); $folder = $attrib['foldername']; // UTF7-IMAP $data = $folderdata[$folder]; From 17e5d1b7c3eecfebf0abfd10f790124affcea9e5 Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Fri, 24 Jun 2011 20:13:43 +0200 Subject: [PATCH 2/9] Added addressbook directories list styling with readonly and namespace icons. Improved addressbook folders naming/structure representation on the list. Added addressbook folders management features including (delete/create/rename). --- .../kolab_addressbook/kolab_addressbook.js | 256 ++++++++++++++++ .../lib/kolab_addressbook_ui.php | 273 ++++++++++++++++++ .../{ => lib}/rcube_kolab_contacts.php | 138 ++++++++- .../skins/default/kolab_addressbook.css | 35 +++ .../skins/default/kolab_folders.png | Bin 0 -> 2481 bytes .../skins/default/templates/bookedit.html | 27 ++ 6 files changed, 721 insertions(+), 8 deletions(-) create mode 100644 plugins/kolab_addressbook/kolab_addressbook.js create mode 100644 plugins/kolab_addressbook/lib/kolab_addressbook_ui.php rename plugins/kolab_addressbook/{ => lib}/rcube_kolab_contacts.php (88%) create mode 100644 plugins/kolab_addressbook/skins/default/kolab_addressbook.css create mode 100644 plugins/kolab_addressbook/skins/default/kolab_folders.png create mode 100644 plugins/kolab_addressbook/skins/default/templates/bookedit.html diff --git a/plugins/kolab_addressbook/kolab_addressbook.js b/plugins/kolab_addressbook/kolab_addressbook.js new file mode 100644 index 00000000..dbb35004 --- /dev/null +++ b/plugins/kolab_addressbook/kolab_addressbook.js @@ -0,0 +1,256 @@ +if (window.rcmail) { + rcmail.addEventListener('init', function() { + rcmail.set_book_actions(); + if (rcmail.gui_objects.editform && rcmail.env.action.match(/^plugin\.book/)) { + rcmail.enable_command('book-save', true); + } + }); + rcmail.addEventListener('listupdate', function() { + rcmail.set_book_actions(); + }); +} + +// (De-)activates address book management commands +rcube_webmail.prototype.set_book_actions = function() +{ + var source = this.env.source, + sources = this.env.address_sources; + + this.enable_command('book-create', true); + this.enable_command('book-edit', 'book-delete', source && sources[source] && sources[source].kolab && sources[source].editable); +}; + +rcube_webmail.prototype.book_create = function() +{ + this.book_show_contentframe('create'); +}; + +rcube_webmail.prototype.book_edit = function() +{ + this.book_show_contentframe('edit'); +}; + +rcube_webmail.prototype.book_delete = function() +{ + if (this.env.source != '' && confirm(this.get_label('kolab_addressbook.bookdeleteconfirm'))) { + var lock = this.set_busy(true, 'kolab_addressbook.bookdeleting'); + this.http_request('plugin.book', '_act=delete&_source='+urlencode(this.book_realname()), lock); + } +}; + +// displays page with book edit/create form +rcube_webmail.prototype.book_show_contentframe = function(action, framed) +{ + var add_url = '', target = window; + + // unselect contact + this.contact_list.clear_selection(); + this.enable_command('edit', 'delete', 'compose', false); + + if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) { + add_url = '&_framed=1'; + target = window.frames[this.env.contentframe]; + this.show_contentframe(true); + } + else if (framed) + return false; + + if (action) { + this.set_busy(true); + this.location_href(this.env.comm_path+'&_action=plugin.book&_act='+action + +'&_source='+urlencode(this.book_realname()) + +add_url, target); + } + + return true; +}; + +// submits book create/update form +rcube_webmail.prototype.book_save = function() +{ + var form = this.gui_objects.editform, + input = $("input[name='_name']", form) + + if (input.length && input.val() == '') { + alert(this.get_label('kolab_addressbook.nobooknamewarning')); + input.focus(); + return; + } + + input = this.display_message(this.get_label('kolab_addressbook.booksaving'), 'loading'); + $('').val(input).appendTo(form); + + form.submit(); +}; + +// action executed after book delete +rcube_webmail.prototype.book_delete_done = function(id) +{ + var n, g, li = this.get_folder_li(id), groups = this.env.contactgroups; + + // remove folder and its groups rows + for (n in groups) + if (groups[n].source == id && (g = this.get_folder_li(n))) { + $(g).remove(); + delete this.env.contactgroups[n]; + } + $(li).remove(); + + delete this.env.address_sources[id]; + delete this.env.contactfolders[id]; +}; + +// action executed after book create/update +rcube_webmail.prototype.book_update = function(data, old) +{ + var n, i, id, len, row, refrow, olddata, name = '', realname = '', sources, level, + folders = [], class_name = 'addressbook', + list = this.gui_objects.folderlist, + groups = this.env.contactgroups; + + this.env.contactfolders[data.id] = this.env.address_sources[data.id] = data; + this.show_contentframe(false); + + // update + if (old && old != data.id) { + olddata = this.env.address_sources[old]; + delete this.env.address_sources[old]; + delete this.env.contactfolders[old]; + + // update source ID in groups + for (n in groups) + if (groups[n].source == old) + this.env.contactgroups[n].source = data.id; + + refrow = $('#rcmli'+old); + } + // create + else if (!old) { + refrow = $('li', list).get(0); + + // this shouldn't happen + if (!refrow) + this.redirect(this.get_task_url('addressbook')); + } + + if (!refrow) + return; + + sources = this.env.address_sources; + + // clone a table row if there are existing rows + row = $(refrow).clone(); + + // set row attributes + if (data.readonly) + class_name += ' readonly'; + if (data.class) + class_name += ' '+data.class; + // updated currently selected book + if (this.env.source != '' && this.env.source == old) { + class_name += ' selected'; + this.env.source = data.id; + } + + row.attr({id: 'rcmli'+data.id, 'class': class_name}); + $('a', row).html(data.name).attr({onclick: '', rel: data.id, href: '#'}) + .click({id: data.id}, function(e) { return rcmail.command('list', e.data.id, this); }); + + // sort kolab folders, to put the new one in order + for (n in sources) + if (sources[n].kolab && (name = sources[n].realname)) + folders.push(name); + folders.sort(); + + // find current id + for (n=0, len=folders.length; n 0) { + for (i=level; i>0; i--) + name = name.replace(/^  /, ''); + } + else if (level < 0) { + for (i=level; i<0; i++) + name = '  ' + name; + } + + // update existing row + refrow = $('#rcmli'+n); + refrow.remove().attr({id: 'rcmli'+id}); + $('a', refrow).html(name).attr({onclick: '', rel: id, href: '#'}) + .click({id: id}, function(e) { return rcmail.command('list', e.data.id, this); }); + + // move the row to the new place + refrow.insertAfter(row); + row = refrow; + + // update list data + sources[n].id = id; + sources[n].name = name; + sources[n].realname = realname; + this.env.address_sources[id] = this.env.contactfolders[id] = sources[n]; + delete this.env.address_sources[n]; + delete this.env.contactfolders[n]; + + // update groups + for (i in groups) { + if (groups[i].source == n) { + // update existing row + refrow = $('#rcmli'+i); + refrow.remove().attr({id: 'rcmliG'+id+groups[i].id}); + $('a', refrow).attr('onclick', '') + .click({source: id, id: groups[i].id}, function(e) { + return rcmail.command('listgroup', {'source': e.data.source, 'id': e.data.id}, this); }); + refrow.insertAfter(row); + row = refrow; + + // update group data + groups[i].source = id; + this.env.contactgroups['G'+id+groups[i].id] = groups[i]; + delete this.env.contactgroups[i]; + } + } + } + } + } +}; + +// returns real IMAP folder name +rcube_webmail.prototype.book_realname = function() +{ + var source = this.env.source, sources = this.env.address_sources; + return source != '' && sources[source] && sources[source].realname ? sources[source].realname : ''; +}; diff --git a/plugins/kolab_addressbook/lib/kolab_addressbook_ui.php b/plugins/kolab_addressbook/lib/kolab_addressbook_ui.php new file mode 100644 index 00000000..6bac21b1 --- /dev/null +++ b/plugins/kolab_addressbook/lib/kolab_addressbook_ui.php @@ -0,0 +1,273 @@ + + * + * Copyright (C) 2011, Kolab Systems AG + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +class kolab_addressbook_ui +{ + private $plugin; + private $rc; + + /** + * Class constructor + * + * @param kolab_addressbook $plugin Plugin object + */ + public function __construct($plugin) + { + $this->rc = rcmail::get_instance(); + $this->plugin = $plugin; + + $this->init_ui(); + } + + /** + * Adds folders management functionality to Addressbook UI + */ + private function init_ui() + { + if (!empty($this->rc->action) && !preg_match('/^plugin\.book/', $this->rc->action)) { + return; + } + + // Include script + $this->plugin->include_script('kolab_addressbook.js'); + + if (empty($this->rc->action)) { + // Include stylesheet (for directorylist) + $this->plugin->include_stylesheet($this->plugin->local_skin_path().'/kolab_addressbook.css'); + + // Add actions on address books + $options = array('book-create', 'book-edit', 'book-delete'); + $idx = 0; + + foreach ($options as $command) { + $content = html::tag('li', $idx ? null : array('class' => 'separator_above'), + $this->plugin->api->output->button(array( + 'label' => 'kolab_addressbook.'.str_replace('-', '', $command), + 'domain' => $this->ID, + 'classact' => 'active', + 'command' => $command + ))); + $this->plugin->api->add_content($content, 'groupoptions'); + $idx++; + } + + $this->rc->output->add_label('kolab_addressbook.bookdeleteconfirm', + 'kolab_addressbook.bookdeleting'); + } + // book create/edit form + else { + $this->rc->output->add_label('kolab_addressbook.nobooknamewarning', + 'kolab_addressbook.booksaving'); + } + } + + + /** + * Handler for address book create/edit action + */ + public function book_edit() + { + $this->rc->output->add_handler('bookdetails', array($this, 'book_form')); + $this->rc->output->send('kolab_addressbook.bookedit'); + } + + + /** + * Handler for 'bookdetails' object returning form content for book create/edit + * + * @param array $attr Object attributes + * + * @return string HTML output + */ + public function book_form($attrib) + { + $action = trim(get_input_value('_act', RCUBE_INPUT_GPC)); + $folder = trim(get_input_value('_source', RCUBE_INPUT_GPC, true)); // UTF8 + $name = trim(get_input_value('_name', RCUBE_INPUT_GPC, true)); // UTF8 + $old = trim(get_input_value('_oldname', RCUBE_INPUT_GPC, true)); // UTF7-IMAP + $path_imap = trim(get_input_value('_parent', RCUBE_INPUT_GPC, true)); // UTF7-IMAP + + $hidden_fields[] = array('name' => '_source', 'value' => $folder); + + $folder = rcube_charset_convert($folder, RCMAIL_CHARSET, 'UTF7-IMAP'); + $delim = $_SESSION['imap_delimiter']; + $form = array(); + + if ($this->rc->action == 'plugin.book-save') { + // save error + $path_imap = $folder; + $hidden_fields[] = array('name' => '_oldname', 'value' => $old); + + if (strlen($old)) { + $this->rc->imap_connect(); + $options = $this->rc->imap->mailbox_info($old); + } + } + else if ($action == 'edit') { + $path_imap = explode($delim, $folder); + $name = rcube_charset_convert(array_pop($path_imap), 'UTF7-IMAP'); + $path_imap = implode($path_imap, $delim); + + $this->rc->imap_connect(); + $options = $this->rc->imap->mailbox_info($folder); + + $hidden_fields[] = array('name' => '_oldname', 'value' => $folder); + } + else { + $path_imap = $folder; + $name = ''; + } + + // General tab + $form['props'] = array( + 'name' => $this->rc->gettext('properties'), + ); + + $foldername = new html_inputfield(array('name' => '_name', 'id' => '_name', 'size' => 30)); + $foldername = $foldername->show($name); + + $form['props']['fieldsets']['location'] = array( + 'name' => $this->rc->gettext('location'), + 'content' => array( + 'name' => array( + 'label' => $this->plugin->gettext('bookname'), + 'value' => $foldername, + ), + ), + ); + + if (strlen($path_imap)) { + $path = rcube_charset_convert($path_imap, 'UTF7-IMAP'); + // @TODO: $options + if (!empty($options) && ($options['norename'] || $options['namespace'] != 'personal')) { + // prevent user from moving folder + $hidden_fields[] = array('name' => '_parent', 'value' => $path_imap); + } + else { + $radio1 = new html_radiobutton(array('name' => '_parent', 'value' => '')); + $radio2 = new html_radiobutton(array('name' => '_parent', 'value' => $path_imap)); + + $html_path = str_replace($delim, ' » ', $path); + + $folderpath = $radio1->show($path_imap) . Q(rcube_label('none')) . ' ' + .$radio2->show($path_imap) . Q($html_path); + + $form['props']['fieldsets']['location']['content']['path'] = array( + 'label' => $this->plugin->gettext('parentbook'), + 'value' => $folderpath, + ); + } + } + + // Allow plugins to modify address book form content (e.g. with ACL form) + $plugin = $this->rc->plugins->exec_hook('addressbook_form', + array('form' => $form, 'options' => $options, 'name' => $folder)); + + $form = $plugin['form']; + + // Set form tags and hidden fields + list($form_start, $form_end) = $this->get_form_tags($attrib, 'plugin.book-save', null, $hidden_fields); + + unset($attrib['form']); + + // return the complete edit form as table + $out = "$form_start\n"; + + // Create form output + foreach ($form as $tab) { + if (!empty($tab['fieldsets']) && is_array($tab['fieldsets'])) { + $content = ''; + foreach ($tab['fieldsets'] as $fieldset) { + $subcontent = $this->get_form_part($fieldset); + if ($subcontent) { + $content .= html::tag('fieldset', null, html::tag('legend', null, Q($fieldset['name'])) . $subcontent) ."\n"; + } + } + } + else { + $content = $this->get_form_part($tab); + } + + if ($content) { + $out .= html::tag('fieldset', null, html::tag('legend', null, Q($tab['name'])) . $content) ."\n"; + } + } + + $out .= "\n$form_end"; + + return $out; + } + + + private function get_form_part($form) + { + $content = ''; + + if (is_array($form['content']) && !empty($form['content'])) { + $table = new html_table(array('cols' => 2)); + foreach ($form['content'] as $col => $colprop) { + $colprop['id'] = '_'.$col; + $label = !empty($colprop['label']) ? $colprop['label'] : rcube_label($col); + + $table->add('title', sprintf('', $colprop['id'], Q($label))); + $table->add(null, $colprop['value']); + } + $content = $table->show(); + } + else { + $content = $form['content']; + } + + return $content; + } + + + private function get_form_tags($attrib, $action, $id = null, $hidden = null) + { + $form_start = $form_end = ''; + + $request_key = $action . (isset($id) ? '.'.$id : ''); + $form_start = $this->rc->output->request_form(array( + 'name' => 'form', + 'method' => 'post', + 'task' => $this->rc->task, + 'action' => $action, + 'request' => $request_key, + 'noclose' => true, + ) + $attrib); + + if (is_array($hidden)) { + foreach ($hidden as $field) { + $hiddenfield = new html_hiddenfield($field); + $form_start .= $hiddenfield->show(); + } + } + + $form_end = !strlen($attrib['form']) ? '' : ''; + + $EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form'; + $this->rc->output->add_gui_object('editform', $EDIT_FORM); + + return array($form_start, $form_end); + } + +} diff --git a/plugins/kolab_addressbook/rcube_kolab_contacts.php b/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php similarity index 88% rename from plugins/kolab_addressbook/rcube_kolab_contacts.php rename to plugins/kolab_addressbook/lib/rcube_kolab_contacts.php index af3daa8d..3c578e6d 100644 --- a/plugins/kolab_addressbook/rcube_kolab_contacts.php +++ b/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php @@ -13,8 +13,9 @@ class rcube_kolab_contacts extends rcube_addressbook { public $primary_key = 'ID'; - public $readonly = false; - public $groups = true; + public $readonly = true; + public $editable = false; + public $groups = false; public $coltypes = array( 'name' => array('limit' => 1), 'firstname' => array('limit' => 1), @@ -55,9 +56,6 @@ class rcube_kolab_contacts extends rcube_addressbook ); private $gid; - private $imap; - private $kolab; - private $folder; private $contactstorage; private $liststorage; private $contacts; @@ -66,6 +64,7 @@ class rcube_kolab_contacts extends rcube_addressbook 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'); @@ -120,6 +119,25 @@ class rcube_kolab_contacts extends rcube_addressbook $this->liststorage = rcube_kolab::get_storage($this->imap_folder, 'distributionlist'); $this->ready = !PEAR::isError($this->contactstorage) && !PEAR::isError($this->liststorage); + + // Set readonly and editable flags according to folder permissions + if ($this->ready) { + if ($this->get_owner() == $_SESSION['username']) { + $this->editable = true; + $this->readonly = false; + } + else { + $acl = $this->contactstorage->_folder->getACL(); + $acl = $acl[$_SESSION['username']]; + if (strpos($acl, 'i') !== false) + $this->readonly = false; + if (strpos($acl, 'a') !== false || strpos($acl, 'x') !== false) + $this->editable = true; + } + + if (!$this->readonly) + $this->groups = true; + } } @@ -130,9 +148,113 @@ class rcube_kolab_contacts extends rcube_addressbook */ public function get_name() { - $folder = rcube_charset_convert($this->imap_folder, 'UTF7-IMAP'); - // @TODO: use namespace prefixes - return strtr(preg_replace('!^(INBOX|user)/!i', '', $folder), '/', ':'); + $folder = $this->imap_folder; + $namespace = $_SESSION['imap_namespace']; // from rcube_imap class + $found = false; + + if (!empty($namespace['shared'])) { + foreach ($namespace['shared'] as $ns) { + if (strlen($ns[0]) && strpos($folder, $ns[0]) === 0) { + $prefix = ''; + $folder = substr($folder, strlen($ns[0])); + $delim = $ns[1]; + $found = true; + $this->namespace = 'shared'; + break; + } + } + } + if (!$found && !empty($namespace['other'])) { + foreach ($namespace['other'] as $ns) { + if (strlen($ns[0]) && strpos($folder, $ns[0]) === 0) { + // remove namespace prefix + $folder = substr($folder, strlen($ns[0])); + $delim = $ns[1]; + // get username + $pos = strpos($folder, $delim); + $prefix = '('.substr($folder, 0, $pos).') '; + $found = true; + $this->namespace = 'other'; + break; + } + } + } + if (!$found && !empty($namespace['personal'])) { + foreach ($namespace['personal'] as $ns) { + if (strlen($ns[0]) && strpos($folder, $ns[0]) === 0) { + // remove namespace prefix + $folder = substr($folder, strlen($ns[0])); + $prefix = ''; + $delim = $ns[1]; + $found = true; + $this->namespace = 'personal'; + break; + } + } + } + + if (empty($delim)) + $delim = $_SESSION['imap_delimiter']; // from rcube_imap class + + $folder = rcube_charset_convert($folder, 'UTF7-IMAP'); + $folder = str_replace($delim, ' » ', $folder); + + if ($prefix) + $folder = $prefix . ' ' . $folder; + + 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->contactstorage->_folder->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) { + return $this->namespace; + } + + $folder = $this->imap_folder; + $namespace = $_SESSION['imap_namespace']; // from rcube_imap class + + if (!empty($namespace)) { + foreach ($namespace as $nsname => $nsvalue) { + if (in_array($nsname, array('personal', 'other', 'shared')) && !empty($nsvalue)) { + foreach ($nsvalue as $ns) { + if (strlen($ns[0]) && strpos($folder, $ns[0]) === 0) { + return $this->namespace = $nsname; + } + } + } + } + } + + return $this->namespace = 'personal'; } diff --git a/plugins/kolab_addressbook/skins/default/kolab_addressbook.css b/plugins/kolab_addressbook/skins/default/kolab_addressbook.css new file mode 100644 index 00000000..da3abed2 --- /dev/null +++ b/plugins/kolab_addressbook/skins/default/kolab_addressbook.css @@ -0,0 +1,35 @@ +#directorylist li.addressbook.readonly +{ + /* don't use 'background' to not reset background color */ + background-image: url(kolab_folders.png); + background-position: 5px 0px; + background-repeat: no-repeat; +} + +#directorylist li.addressbook.shared +{ + background-image: url(kolab_folders.png); + background-position: 5px -54px; + background-repeat: no-repeat; +} + +#directorylist li.addressbook.shared.readonly +{ + background-image: url(kolab_folders.png); + background-position: 5px -72px; + background-repeat: no-repeat; +} + +#directorylist li.addressbook.other +{ + background-image: url(kolab_folders.png); + background-position: 5px -18px; + background-repeat: no-repeat; +} + +#directorylist li.addressbook.other.readonly +{ + background-image: url(kolab_folders.png); + background-position: 5px -36px; + background-repeat: no-repeat; +} diff --git a/plugins/kolab_addressbook/skins/default/kolab_folders.png b/plugins/kolab_addressbook/skins/default/kolab_folders.png new file mode 100644 index 0000000000000000000000000000000000000000..cd6228a77aafec51ed9a9fc639ad8b993a2cbe32 GIT binary patch literal 2481 zcmV;i2~PHjP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ipb} z2r>|&egW(N00}WkL_t(o!|j-Ra8%_PhoA49y(HOWlaPA?xse122w1rUf`S()7L=RR z5o@QVj+Lp-*v>ehGo9%u+RL;>lxnrDT1P8lMXgjRf`EVs;UW+&fkepW!Y0}5Zuacu z?4DcyNWcwBbgKQs8Qz)iukW1S%zM6hpLxCmU$X?jx~HGaD=sd6J}WzGPBa>&VSmGB zC8XT_$3HyL^OXYL|6ohA+wC6t?`d}=oW#yDq;318-UVQGvDpCQTD>{dmt4i)^-=NnA(RWN;us!6H`jZvaEpxwbkW}$u8r~liMc(*bX;x|GbqiTj*Pb5%1#a z`aGhMZW6lAQ%`O}A2tWew9qY+gsLKHDiBEx*$^05?ZS%eA|CM&33sD}dJ*<=YDd-3 zXQeS~=1kHvGI{#%uOr!H+_o}gdv*bUO*a6u%|d-s7*QWuR3i~ffNr3wd92^~Dig+! zCoexAS+*m|HeOT=4##Xh0Glb{Ilkv@5m(2dsv%<0Fp+42gq9#Zvw*_F5SC@3>pJmx zf2eREn2%FV^3jO6; zvSdlZ>kD8SIw`3s2w6f1IVr%x)MadT8&RhZGbLJ(98kDn!-n5`JRV-!@D2{A6IphE zkPsGFmW5&HXhOzjcc4w$P27K~i+!I3d@9TG{MreVH!c6^eUugDA|x4EmIt;C4Bf;q z3^YwgIn#mNmC^)=3m?$|OuS*<;(d}NBP0odKn!e~mIattriE!*XbF{F?{At0927}Y z=>STBVn7C@ONP)ISSHW`v;qmf{WSteT;G(RMffLk7W?6E&|p6{y8DXFA( z?AQScSzk`1fvpLvR;{Y`cs%^&r42N-wDupL*&i|#k)(lu7Fm{;&6+)zR98B^-Cn|d zej*`1;gFwjpP#U9TO@oZgOzv5>h+x3ahdVx?zHTZG zo1Fvy{2Ti5ojB#%&xkY-Fy^6$9=g4MoZrBnnt{`4$KTTh%?I%GH4|0B6lA&ap8u3B z=2<=t3x9G8K3SI6&AnwIuJlYK(LV!9^D)MbEJ2n8N>Cvp#pqKM9Hy5sh2HGs0C~lV z6;za!p~h9BY8*||IPviwTuwV@PoJZ7>eb9ya5GocRUh7Sz%Yr2dRe!vOF7@y`Jj|cq&f2!k(QA~ zc~vbXrInatW^t&|S4JjfMY%XEldyd_BS+SfF?tcN2d`znvyNTL1cLq$ zY0e^%Q8{bbWr?IXE0}frFEPzDLScwSEkb=!)M$iAUxl5TiB~U6BxiYj)zx!; z_KVE?(W5LmlXy%c67r+;wp&5(serHTqwU7I&A$;t4txI0ELXaiAQIs*hM}hzx~A%S zqRmu;O~iUSfEZUC>D%B)A;UQ|k%n@lSY#Nq4^5;Y9Z6Ob)Ql`A5{{w-6&%Ct14N24 zrch*md=})_w(`l-FE+Hu88>#m{Xt@inYDy-%48NVeVlz8-=(IkfW{+DRMt=8`q|Ub zjWFliJMs4hZQUVd(-k6JA<{QOq$`f}4LFjN5%Ql*87dJBhNSxbr;#}@Lj_vL5N66&B^+kt^w+aO2! z-O2|Tk?X=HNhm>us2n30QV4gn@y^;`V~_Z;_P@c1+!ma2s_{8TD$hzEjt-G(JAfIDLnkX7o%#^xuXsSwKK_O+O!|u;hdgweKAskYOYL)~X97H53yNX68;)&-{HC@lreIL)6iW+NJ+ua9dsEc zi7wn?#d^2sv zD4IHR5eY#srj%X?Fsl5 z(*FvSHcd)(8K$(vABHalN;pDO^R9T$_LY}7k|SrFBO|+B5~9L1O{ZySnxUyZmNP5O vJ#0j=h2+rUk(e6sH4-@ezJL>78z}z;x + + +<roundcube:object name="pagetitle" /> + + + + + + +
+ +
+ +

+ + +

+
+ + + + From 0b85b713173d2bd4c3db1cca6a60c796007040e3 Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Mon, 27 Jun 2011 13:43:11 +0200 Subject: [PATCH 3/9] Describe remove_calendar() parameters --- plugins/calendar/drivers/calendar_driver.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/calendar/drivers/calendar_driver.php b/plugins/calendar/drivers/calendar_driver.php index d4e732ce..1eed9bfb 100644 --- a/plugins/calendar/drivers/calendar_driver.php +++ b/plugins/calendar/drivers/calendar_driver.php @@ -95,6 +95,8 @@ abstract class calendar_driver /** * Delete the given calendar with all its contents * + * @param array Hash array with calendar properties + * id: Calendar Identifier * @return boolean True on success, Fales on failure */ abstract function remove_calendar($prop); From 726932250a515cb235f3cd54a9264ca71e04d888 Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Mon, 27 Jun 2011 13:44:27 +0200 Subject: [PATCH 4/9] Lost commit --- .../kolab_addressbook/kolab_addressbook.php | 238 +++++++++++++++++- .../kolab_addressbook/localization/en_US.inc | 18 ++ .../kolab_addressbook/localization/pl_PL.inc | 18 ++ 3 files changed, 263 insertions(+), 11 deletions(-) diff --git a/plugins/kolab_addressbook/kolab_addressbook.php b/plugins/kolab_addressbook/kolab_addressbook.php index 7a97e672..1d709e22 100644 --- a/plugins/kolab_addressbook/kolab_addressbook.php +++ b/plugins/kolab_addressbook/kolab_addressbook.php @@ -1,12 +1,11 @@ * @author Aleksander Machniak @@ -28,9 +27,12 @@ require_once(dirname(__FILE__) . '/rcube_kolab_contacts.php'); */ class kolab_addressbook extends rcube_plugin { + public $task = 'mail|settings|addressbook'; + private $folders; private $sources; private $rc; + private $ui; const GLOBAL_FIRST = 0; const PERSONAL_FIRST = 1; @@ -42,6 +44,8 @@ class kolab_addressbook extends rcube_plugin */ public function init() { + require_once(dirname(__FILE__) . '/lib/rcube_kolab_contacts.php'); + $this->rc = rcmail::get_instance(); // load required plugin @@ -54,6 +58,16 @@ class kolab_addressbook extends rcube_plugin 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'); @@ -92,13 +106,33 @@ class kolab_addressbook extends rcube_plugin } $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].' » ') === 0) { + $length = strlen($names[$i].' » '); + $prefix = substr($name, 0, $length); + $count = count(explode(' » ', $prefix)); + $name = str_repeat('  ', $count-1) . '» ' . substr($name, $length); + break; + } + } + $names[] = $origname; + // register this address source $sources[$abook_id] = array( - 'id' => $abook_id, - 'name' => $abook->get_name(), + 'id' => $abook_id, + 'name' => $name, 'readonly' => $abook->readonly, - 'groups' => $abook->groups, + 'editable' => $abook->editable, + 'groups' => $abook->groups, + 'realname' => rcube_charset_convert($abook->get_realname(), 'UTF7-IMAP'), // IMAP folder name + 'class' => $abook->get_namespace(), + 'kolab' => true, ); } @@ -200,10 +234,17 @@ class kolab_addressbook extends rcube_plugin true, false); } else { - foreach ($this->folders as $c_folder) { + // 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($c_folder->name); - $abook = new rcube_kolab_contacts($c_folder->name); + $abook_id = rcube_kolab::folder_id($utf7name); + $abook = new rcube_kolab_contacts($utf7name); $this->sources[$abook_id] = $abook; } } @@ -282,7 +323,7 @@ class kolab_addressbook extends rcube_plugin // Load configuration $this->load_config(); - // Load localization and configuration + // Load localization $this->add_texts('localization'); // Check that configuration is not disabled @@ -333,4 +374,179 @@ class kolab_addressbook extends rcube_plugin 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() + { + $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 = $_SESSION['imap_delimiter']; +console($_REQUEST); + // sanity checks (from steps/settings/save_folder.inc) + if (!strlen($folder)) { + $error = rcube_label('cannotbeempty'); + } + else if (strlen($name) > 128) { + $error = rcube_label('nametoolong'); + } + else { + // these characters are problematic e.g. when used in LIST/LSUB + foreach (array($delimiter, '%', '*') as $char) { + if (strpos($name, $delimiter) !== false) { + $error = rcube_label('forbiddencharacter') . " ($char)"; + break; + } + } + } + + if (!$error) { + // @TODO: $options + $options = array(); + if ($options['protected'] || $options['norename']) { + $folder = $oldfolder; + } + else if (strlen($path)) { + $folder = $path . $delimiter . $folder; + } + else { + // namespace prefix? +// $name_imap = $RCMAIL->imap->mod_mailbox($name, 'in'); + } + + // 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); + 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); + } + 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].' » ') === 0) { + $length = strlen($names[$i].' » '); + $prefix = substr($name, 0, $length); + $count = count(explode(' » ', $prefix)); + $name = str_repeat('  ', $count-1) . '» ' . 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), + 'name' => $name, + 'readonly' => false, + 'editable' => true, + 'groups' => true, + 'realname' => rcube_charset_convert($folder, 'UTF7-IMAP'), // IMAP folder name + 'class' => $kolab_folder->get_namespace(), + 'kolab' => true, + ), rcube_kolab::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)) { + $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)); + } + else { + $this->rc->output->show_message('kolab_addressbook.bookdeleteerror', 'error'); + } + + $this->rc->output->send(); + } } diff --git a/plugins/kolab_addressbook/localization/en_US.inc b/plugins/kolab_addressbook/localization/en_US.inc index 9a2e4fa4..ce90f60a 100644 --- a/plugins/kolab_addressbook/localization/en_US.inc +++ b/plugins/kolab_addressbook/localization/en_US.inc @@ -9,10 +9,28 @@ $labels['pgppublickey'] = 'PGP publickey'; $labels['freebusyurl'] = 'Free-busy URL'; $labels['settings'] = 'Settings'; +$labels['bookcreate'] = 'Create address book'; +$labels['bookedit'] = 'Edit address book'; +$labels['bookdelete'] = 'Delete address book'; +$labels['bookproperties'] = 'Address book properties'; +$labels['bookname'] = 'Book name'; +$labels['parentbook'] = 'Superior book'; + $labels['addressbookprio'] = 'Address book(s) selection/behaviour'; $labels['personalfirst'] = 'Personal address book(s) first'; $labels['globalfirst'] = 'Global address book(s) first'; $labels['personalonly'] = 'Personal address book(s) only'; $labels['globalonly'] = 'Global address book(s) only'; +$messages['bookdeleteconfirm'] = 'Do you really want to delete the selected address book and all contacts in it?'; +$messages['bookdeleting'] = 'Deleting address book...'; +$messages['booksaving'] = 'Saving address book...'; +$messages['bookdeleted'] = 'Address book deleted successfully'; +$messages['bookupdated'] = 'Address book updated successfully'; +$messages['bookcreated'] = 'Address book created successfully'; +$messages['bookdeleteerror'] = 'An error occured while deleting address book'; +$messages['bookupdateerror'] = 'An error occured while updating address book'; +$messages['bookcreateerror'] = 'An error occured while creating address book'; +$messages['nobooknamewarning'] = 'Please, enter address book name'; + ?> diff --git a/plugins/kolab_addressbook/localization/pl_PL.inc b/plugins/kolab_addressbook/localization/pl_PL.inc index bdfc0722..61887231 100644 --- a/plugins/kolab_addressbook/localization/pl_PL.inc +++ b/plugins/kolab_addressbook/localization/pl_PL.inc @@ -15,4 +15,22 @@ $labels['globalfirst'] = 'Najpierw globalne książki adresowe'; $labels['personalonly'] = 'Tylko osobiste książki adresowe'; $labels['globalonly'] = 'Tylko globalne książki adresowe'; +$labels['bookcreate'] = 'Utwórz książkę'; +$labels['bookedit'] = 'Edytuj książkę'; +$labels['bookdelete'] = 'Usuń książkę'; +$labels['bookproperties'] = 'Właściwości książki adresowej'; +$labels['bookname'] = 'Nazwa książki'; +$labels['parentbook'] = 'Książka nadrzędna'; + +$messages['bookdeleteconfirm'] = 'Czy na pewno chcesz usunąć wybraną książkę i wszystkie kontakty w niej zapisane?'; +$messages['bookdeleting'] = 'Usuwanie książki adresowej...'; +$messages['booksaving'] = 'Zapisywanie książki adresowej...'; +$messages['bookdeleted'] = 'Książka adresowa została usunięta'; +$messages['bookupdated'] = 'Książka adresowa została zaktualizowana'; +$messages['bookcreated'] = 'Książka adresowa została utworzona'; +$messages['bookdeleteerror'] = 'Wystąpił błąd podczas usuwania książki adresowej'; +$messages['bookupdateerror'] = 'Wystąpił błąd podczas zmiany książki adresowej'; +$messages['bookcreateerror'] = 'Wystąpił błąd podczas tworzenia książki adresowej'; +$messages['nobooknamewarning'] = 'Proszę podać nazwę książki adresowej'; + ?> From d93b7bf46ca4c69b4e899dd68b5e34f6ee0aec3d Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Mon, 27 Jun 2011 14:09:16 +0200 Subject: [PATCH 5/9] Workaround for Horde bug where groups are listed as contacts --- plugins/kolab_addressbook/lib/rcube_kolab_contacts.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php b/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php index 3c578e6d..16689cdc 100644 --- a/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php +++ b/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php @@ -892,6 +892,10 @@ class rcube_kolab_contacts extends rcube_addressbook // read contacts $this->contacts = $this->id2uid = array(); foreach ((array)$this->contactstorage->getObjects() 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; From f0e1198db35121133072b9735d01fd27a1e31ede Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Mon, 27 Jun 2011 14:10:00 +0200 Subject: [PATCH 6/9] Removed debug code, fixed namespace prefix handling --- plugins/kolab_addressbook/kolab_addressbook.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/kolab_addressbook/kolab_addressbook.php b/plugins/kolab_addressbook/kolab_addressbook.php index 1d709e22..cc677659 100644 --- a/plugins/kolab_addressbook/kolab_addressbook.php +++ b/plugins/kolab_addressbook/kolab_addressbook.php @@ -403,7 +403,7 @@ class kolab_addressbook extends rcube_plugin $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 = $_SESSION['imap_delimiter']; -console($_REQUEST); + // sanity checks (from steps/settings/save_folder.inc) if (!strlen($folder)) { $error = rcube_label('cannotbeempty'); @@ -431,8 +431,9 @@ console($_REQUEST); $folder = $path . $delimiter . $folder; } else { - // namespace prefix? -// $name_imap = $RCMAIL->imap->mod_mailbox($name, 'in'); + // add namespace prefix (when needed) + $this->rc->imap_init(); + $folder = $this->rc->imap->mod_mailbox($folder, 'in'); } // update the folder name From 73ed987bb945e165336d6504264daee149c5d6fd Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Mon, 27 Jun 2011 14:45:45 +0200 Subject: [PATCH 7/9] Added HTTP_Request to the list of required PEAR packages --- plugins/kolab_core/README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/kolab_core/README.txt b/plugins/kolab_core/README.txt index 3b82e898..81ef3d78 100644 --- a/plugins/kolab_core/README.txt +++ b/plugins/kolab_core/README.txt @@ -21,7 +21,7 @@ pear install Net_SMTP pear install Mail_mimeDecode pear install Auth_SASL pear install Date - +pear install HTTP_Request Configuration ------------- From 6f296d0928b5f27ea93e6b52b7bb32e3b3643124 Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Mon, 27 Jun 2011 15:49:51 +0200 Subject: [PATCH 8/9] Basic remove/create/edit calendar methods implementation, with color in user preferences --- .../calendar/drivers/kolab/kolab_calendar.php | 43 +++++++---- .../calendar/drivers/kolab/kolab_driver.php | 72 +++++++++++++++++-- 2 files changed, 94 insertions(+), 21 deletions(-) diff --git a/plugins/calendar/drivers/kolab/kolab_calendar.php b/plugins/calendar/drivers/kolab/kolab_calendar.php index eb75bac7..816bf699 100644 --- a/plugins/calendar/drivers/kolab/kolab_calendar.php +++ b/plugins/calendar/drivers/kolab/kolab_calendar.php @@ -12,6 +12,7 @@ | | +-------------------------------------------------------------------------+ | Author: Thomas Bruederli | + | Author: Aleksander Machniak | +-------------------------------------------------------------------------+ */ @@ -20,7 +21,7 @@ class kolab_calendar public $id; public $ready = false; public $readonly = true; - + private $cal; private $storage; private $events; @@ -29,7 +30,7 @@ class kolab_calendar private $sensitivity_map = array('public', 'private', 'confidential'); private $priority_map = array('low', 'normal', 'high'); - + private $fieldmap = array( // kolab => roundcube 'summary' => 'title', @@ -42,14 +43,14 @@ class kolab_calendar 'show-time-as' => 'free_busy', 'alarm','alarms' ); - + /** * Default constructor */ public function __construct($imap_folder, $calendar) { $this->cal = $calendar; - + if (strlen($imap_folder)) $this->imap_folder = $imap_folder; @@ -75,7 +76,19 @@ class kolab_calendar $dispname = preg_replace(array('!INBOX/Calendar/!', '!^INBOX/!', '!^shared/!', '!^user/([^/]+)/!'), array('','','','(\\1) '), $this->imap_folder); return rcube_charset_convert(strlen($dispname) ? $dispname : $this->imap_folder, "UTF7-IMAP"); } - + + + /** + * Getter for the IMAP folder name + * + * @return string Name of the IMAP folder + */ + public function get_realname() + { + return $this->imap_folder; + } + + /** * Getter for the top-end calendar folder name (not the entire path) * @@ -84,22 +97,24 @@ class kolab_calendar public function get_foldername() { $parts = explode('/', $this->imap_folder); - return end($parts); + return rcube_charset_convert(end($parts), 'UTF7-IMAP'); } /** * Return color to display this calendar */ - public function get_color($owner) + public function get_color() { - // TODO: read color from backend (not yet supported) - //temporary color deffirence between own calendars and the rest - if ($owner == $_SESSION['username']) - return 'd63355'; - return '1f9ebe'; + // Store temporarily calendar color in user prefs (will be changed) + $prefs = $this->cal->rc->config->get('kolab_calendars', array()); + + if (!empty($prefs[$this->id]) && !empty($prefs[$this->id]['color'])) + return $prefs[$this->id]['color']; + + return 'cc0000'; } - - + + /** * Getter for a single event object */ diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php index 74d34d89..e81fe5df 100644 --- a/plugins/calendar/drivers/kolab/kolab_driver.php +++ b/plugins/calendar/drivers/kolab/kolab_driver.php @@ -71,7 +71,7 @@ class kolab_driver extends calendar_driver 'id' => $calendar->id, 'name' => $calendar->get_name(), 'editname' => $calendar->get_foldername(), - 'color' => $calendar->get_color($c_folder->_owner), + 'color' => $calendar->get_color(), 'readonly' => $c_folder->_owner != $_SESSION['username'], ); } @@ -102,7 +102,7 @@ class kolab_driver extends calendar_driver if ($this->create_calendar(array('name' => 'Default', 'color' => 'cc0000'))) $this->_read_calendars(); } - + return $this->calendars; } @@ -117,10 +117,30 @@ class kolab_driver extends calendar_driver */ public function create_calendar($prop) { - + $folder = rcube_charset_convert($prop['name'], RCMAIL_CHARSET, 'UTF7-IMAP'); + + // add namespace prefix (when needed) + $this->rc->imap_init(); + $folder = $this->rc->imap->mod_mailbox($folder, 'in'); + + // create ID + $id = rcube_kolab::folder_id($folder); + + // create IMAP folder + if (rcube_kolab::folder_create($folder, 'event')) { + // save color in user prefs (temp. solution) + $prefs['kolab_calendars'] = $this->rc->config->get('kolab_calendars', array()); + $prefs['kolab_calendars'][$id]['color'] = $prop['color']; + + $this->rc->user->save_prefs($prefs); + + return $id; + } + return false; } + /** * Update properties of an existing calendar * @@ -128,9 +148,36 @@ class kolab_driver extends calendar_driver */ public function edit_calendar($prop) { + if ($prop['id'] && ($cal = $this->folders[$prop['id']])) { + $newfolder = rcube_charset_convert($prop['name'], RCMAIL_CHARSET, 'UTF7-IMAP'); + $oldfolder = $cal->get_realname(); + // add namespace prefix (when needed) + $this->rc->imap_init(); + $newfolder = $this->rc->imap->mod_mailbox($newfolder, 'in'); + + if ($newfolder != $oldfolder) + $result = rcube_kolab::folder_rename($oldfolder, $newfolder); + else + $result = true; + + if ($result) { + // create ID + $id = rcube_kolab::folder_id($newfolder); + // save color in user prefs (temp. solution) + $prefs['kolab_calendars'] = $this->rc->config->get('kolab_calendars', array()); + $prefs['kolab_calendars'][$id]['color'] = $prop['color']; + unset($prefs['kolab_calendars'][$prop['id']]); + + $this->rc->user->save_prefs($prefs); + + return true; + } + } + return false; } + /** * Delete the given calendar with all its contents * @@ -138,7 +185,18 @@ class kolab_driver extends calendar_driver */ public function remove_calendar($prop) { - + if ($prop['id'] && ($cal = $this->folders[$prop['id']])) { + $folder = $cal->get_realname(); + if (rcube_kolab::folder_delete($folder)) { + // remove color in user prefs (temp. solution) + $prefs['kolab_calendars'] = $this->rc->config->get('kolab_calendars', array()); + unset($prefs['kolab_calendars'][$prop['id']]); + + $this->rc->user->save_prefs($prefs); + return true; + } + } + return false; } @@ -153,7 +211,7 @@ class kolab_driver extends calendar_driver $cid = $event['calendar'] ? $event['calendar'] : reset(array_keys($this->calendars)); if ($storage = $this->_get_storage($cid)) return $storage->insert_event($event); - + return false; } @@ -167,7 +225,7 @@ class kolab_driver extends calendar_driver { if ($storage = $this->_get_storage($event['calendar'])) return $storage->update_event($event); - + return false; } @@ -181,7 +239,7 @@ class kolab_driver extends calendar_driver { if (($storage = $this->_get_storage($event['calendar'])) && ($ev = $storage->get_event($event['id']))) return $storage->update_event($event + $ev); - + return false; } From 924aaba1eb2bef5d0ec70ee647dd836807b09a4f Mon Sep 17 00:00:00 2001 From: "Aleksander Machniak (Kolab Systems)" Date: Mon, 27 Jun 2011 17:53:10 +0200 Subject: [PATCH 9/9] DOn't use reserver word 'class' --- plugins/kolab_addressbook/kolab_addressbook.js | 4 ++-- plugins/kolab_addressbook/kolab_addressbook.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/kolab_addressbook/kolab_addressbook.js b/plugins/kolab_addressbook/kolab_addressbook.js index dbb35004..cdb525d1 100644 --- a/plugins/kolab_addressbook/kolab_addressbook.js +++ b/plugins/kolab_addressbook/kolab_addressbook.js @@ -144,8 +144,8 @@ rcube_webmail.prototype.book_update = function(data, old) // set row attributes if (data.readonly) class_name += ' readonly'; - if (data.class) - class_name += ' '+data.class; + if (data.class_name) + class_name += ' '+data.class_name; // updated currently selected book if (this.env.source != '' && this.env.source == old) { class_name += ' selected'; diff --git a/plugins/kolab_addressbook/kolab_addressbook.php b/plugins/kolab_addressbook/kolab_addressbook.php index cc677659..5432ffac 100644 --- a/plugins/kolab_addressbook/kolab_addressbook.php +++ b/plugins/kolab_addressbook/kolab_addressbook.php @@ -131,7 +131,7 @@ class kolab_addressbook extends rcube_plugin 'editable' => $abook->editable, 'groups' => $abook->groups, 'realname' => rcube_charset_convert($abook->get_realname(), 'UTF7-IMAP'), // IMAP folder name - 'class' => $abook->get_namespace(), + 'class_name' => $abook->get_namespace(), 'kolab' => true, ); } @@ -514,7 +514,7 @@ class kolab_addressbook extends rcube_plugin 'editable' => true, 'groups' => true, 'realname' => rcube_charset_convert($folder, 'UTF7-IMAP'), // IMAP folder name - 'class' => $kolab_folder->get_namespace(), + 'class_name' => $kolab_folder->get_namespace(), 'kolab' => true, ), rcube_kolab::folder_id($oldfolder));