diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php index 152cc539..365ce9ea 100644 --- a/plugins/calendar/calendar.php +++ b/plugins/calendar/calendar.php @@ -38,6 +38,7 @@ class calendar extends rcube_plugin public $rc; public $lib; public $driver; + public $resources_dir; public $home; // declare public to be used in other classes public $urlbase; public $timezone; @@ -211,16 +212,10 @@ class calendar extends rcube_plugin require_once($this->home . '/drivers/calendar_driver.php'); require_once($this->home . '/drivers/' . $driver_name . '/' . $driver_class . '.php'); - switch ($driver_name) { - case "kolab": - $this->require_plugin('libkolab'); - default: - $this->driver = new $driver_class($this); - break; - } + $this->driver = new $driver_class($this); - if ($this->driver->undelete) - $this->driver->undelete = $this->rc->config->get('undo_timeout', 0) > 0; + if ($this->driver->undelete) + $this->driver->undelete = $this->rc->config->get('undo_timeout', 0) > 0; } /** @@ -297,7 +292,7 @@ class calendar extends rcube_plugin $this->rc->output->set_env('timezone', $this->timezone->getName()); $this->rc->output->set_env('calendar_driver', $this->rc->config->get('calendar_driver'), false); - $this->rc->output->set_env('resources', (bool)$this->driver->resources); + $this->rc->output->set_env('calendar_resources', (bool)$this->rc->config->get('calendar_resources_driver')); $this->rc->output->set_env('mscolors', $this->driver->get_color_values()); $this->rc->output->set_env('identities-selector', $this->ui->identity_select(array('id' => 'edit-identities-list'))); @@ -1936,6 +1931,30 @@ class calendar extends rcube_plugin /**** Resource management functions ****/ + /** + * Getter for the configured implementation of the resource directory interface + */ + private function resources_directory() + { + if (is_object($this->resources_dir)) { + return $this->resources_dir; + } + + if ($driver_name = $this->rc->config->get('calendar_resources_driver')) { + $driver_class = 'resources_driver_' . $driver_name; + + require_once($this->home . '/drivers/resources_driver.php'); + require_once($this->home . '/drivers/' . $driver_name . '/' . $driver_class . '.php'); + + $this->resources_dir = new $driver_class($this); + } + + return $this->resources_dir; + } + + /** + * Handler for resoruce autocompletion requests + */ public function resources_autocomplete() { $search = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GPC, true); @@ -1943,12 +1962,14 @@ class calendar extends rcube_plugin $maxnum = (int)$this->rc->config->get('autocomplete_max', 15); $results = array(); - foreach ($this->driver->load_resources($search, $maxnum) as $rec) { - $results[] = array( - 'name' => $rec['name'], - 'email' => $rec['email'], - 'type' => $rec['_type'], - ); + if ($directory = $this->resources_directory()) { + foreach ($directory->load_resources($search, $maxnum) as $rec) { + $results[] = array( + 'name' => $rec['name'], + 'email' => $rec['email'], + 'type' => $rec['_type'], + ); + } } $this->rc->output->command('ksearch_query_results', $results, $search, $sid); @@ -1961,9 +1982,11 @@ class calendar extends rcube_plugin function resources_list() { $data = array(); - foreach ($this->driver->load_resources() as $rec) { - $rec['dn'] = rcube_ldap::dn_decode($rec['ID']); - $data[] = $rec; + + if ($directory = $this->resources_directory()) { + foreach ($directory->load_resources() as $rec) { + $data[] = $rec; + } } $this->rc->output->command('plugin.resource_data', $data); @@ -1975,8 +1998,10 @@ class calendar extends rcube_plugin */ function resources_owner() { - $id = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC); - $data = $this->driver->get_resource_owner($id); + if ($directory = $this->resources_directory()) { + $id = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC); + $data = $directory->get_resource_owner($id); + } $this->rc->output->command('plugin.resource_owner', $data); $this->rc->output->send(); diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js index f39c4c04..986ea8c3 100644 --- a/plugins/calendar/calendar_ui.js +++ b/plugins/calendar/calendar_ui.js @@ -762,7 +762,7 @@ function rcube_calendar_ui(settings) // show/hide tabs according to calendar's feature support $('#edit-tab-attendees')[(calendar.attendees?'show':'hide')](); - $('#edit-tab-resources')[(calendar.resources?'show':'hide')](); + $('#edit-tab-resources')[(rcmail.env.calendar_resources?'show':'hide')](); $('#edit-tab-attachments')[(calendar.attachments?'show':'hide')](); // activate the first tab @@ -1516,7 +1516,7 @@ function rcube_calendar_ui(settings) '' + Q(data.status || '') + '' + '' + (organizer || readonly ? '' : dellink) + ''; - var table = calendar.resources && data.cutype == 'RESOURCE' ? resources_list : attendees_list; + var table = rcmail.env.calendar_resources && data.cutype == 'RESOURCE' ? resources_list : attendees_list; var tr = $('') .addClass(String(data.role).toLowerCase()) .html(html) @@ -1706,12 +1706,12 @@ function rcube_calendar_ui(settings) // assign parent-relations $.each(data, function(i, rec) { - resources_data[rec.dn] = rec; - resources_index.push(rec.dn); + resources_data[rec.ID] = rec; + resources_index.push(rec.ID); if (rec.members) { $.each(rec.members, function(j, m){ - resources_data[m].parent_id = rec.dn; + resources_data[m].parent_id = rec.ID; }); } }); @@ -1730,10 +1730,10 @@ function rcube_calendar_ui(settings) $.each(index, function(i, dn) { if (rec = resources_data[dn]) { link = $('').attr('href', '#') - .attr('rel', rec.dn) + .attr('rel', rec.ID) .html(Q(rec.name)); - resources_treelist.insert({ id:rec.dn, html:link, classes:[rec._type], collapsed:true }, rec.parent_id, false); + resources_treelist.insert({ id:rec.ID, html:link, classes:[rec._type], collapsed:true }, rec.parent_id, false); } }); }; @@ -1772,7 +1772,7 @@ function rcube_calendar_ui(settings) for (var dn in resources_data) { rec = resources_data[dn]; if (String(rec.name).toLowerCase().indexOf(q) >= 0) { - dataset.push(rec.dn); + dataset.push(rec.ID); } } diff --git a/plugins/calendar/config.inc.php.dist b/plugins/calendar/config.inc.php.dist index 9a472a7a..f09d30f0 100644 --- a/plugins/calendar/config.inc.php.dist +++ b/plugins/calendar/config.inc.php.dist @@ -135,4 +135,11 @@ $rcmail_config['calendar_itip_smtp_pass'] = '123456'; // %i - Calendar UUID // $rcmail_config['calendar_caldav_url'] = 'http://%h/iRony/calendars/%u/%i'; +// Driver to provide a resource directory ('ldap' is the only implementation yet). +// Leave empty or commented to disable resources support. +// $rcmail_config['calendar_resources_driver'] = 'ldap'; + +// LDAP directory configuration to find avilable resources for events +// $rcmail_config['calendar_resources_directory'] = array(/* ldap_public-like address book configuration */) + ?> diff --git a/plugins/calendar/drivers/calendar_driver.php b/plugins/calendar/drivers/calendar_driver.php index 3d8d083a..20f9f164 100644 --- a/plugins/calendar/drivers/calendar_driver.php +++ b/plugins/calendar/drivers/calendar_driver.php @@ -86,7 +86,6 @@ abstract class calendar_driver // features supported by backend public $alarms = false; public $attendees = false; - public $resources = false; public $freebusy = false; public $attachments = false; public $undelete = false; // event undelete action @@ -530,54 +529,4 @@ abstract class calendar_driver return $events; } - /** - * Store alarm dismissal for birtual birthay events - * - * @param string Event identifier - * @param integer Suspend the alarm for this number of seconds - */ - public function dismiss_birthday_alarm($event_id, $snooze = 0) - { - $rcmail = rcmail::get_instance(); - $cache = $rcmail->get_cache('calendar.birthdayalarms', 'db', 86400 * 30); - $cache->remove($event_id); - - // compute new notification time or disable if not snoozed - $notifyat = $snooze > 0 ? time() + $snooze : null; - $cache->set($event_id, array('snooze' => $snooze, 'notifyat' => $notifyat)); - - return true; - } - - - /** - * Fetch resource objects to be displayed for booking - * - * @param string Search query (optional) - * @return array List of resource records available for booking - */ - public function load_resources($query = null) - { - return array(); - } - - /** - * Return properties of a single resource - * - * @param mixed UID string - * @return array Resource object as hash array - */ - public function get_resource($uid) - { - return null; - } - - /** - * - */ - public function get_resource_owner($id) - { - return null; - } - } diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php index 1bf4e17f..0bcab593 100644 --- a/plugins/calendar/drivers/kolab/kolab_driver.php +++ b/plugins/calendar/drivers/kolab/kolab_driver.php @@ -47,6 +47,8 @@ class kolab_driver extends calendar_driver */ public function __construct($cal) { + $cal->require_plugin('libkolab'); + $this->cal = $cal; $this->rc = $cal->rc; $this->_read_calendars(); @@ -60,10 +62,6 @@ class kolab_driver extends calendar_driver $this->alarm_types = array('DISPLAY'); $this->alarm_absolute = false; } - - if ($this->rc->config->get('calendar_resources_directory')) { - $this->resources = true; - } } @@ -1287,105 +1285,4 @@ class kolab_driver extends calendar_driver 'FFDEAD'); } - - private function resurces_ldap() - { - if (!isset($this->resources_dir)) { - $this->resources_dir = new rcube_ldap($this->rc->config->get('calendar_resources_directory'), true); - } - - return $this->resources_dir->ready ? $this->resources_dir : null; - } - - - /** - * Fetch resource objects to be displayed for booking - * - * @param string Search query (optional) - * @return array List of resource records available for booking - */ - public function load_resources($query = null, $num = 5000) - { - if (!($ldap = $this->resurces_ldap())) { - return array(); - } - - // TODO: apply paging - $ldap->set_pagesize($num); - - if (isset($query)) { - $results = $ldap->search('*', $query, 0, true, true); - } - else { - $results = $ldap->list_records(); - } - - if ($results instanceof ArrayAccess) { - foreach ($results as $i => $rec) { - $results[$i] = $this->decode_resource($rec); - } - } - - return $results; - } - - /** - * Return properties of a single resource - * - * @param mixed UID string - * @return array Resource object as hash array - */ - public function get_resource($uid) - { - $rec = null; - - if ($ldap = $this->resurces_ldap()) { - $rec = $ldap->get_record($uid); - - if (!empty($rec)) { - $rec = $this->decode_resource($rec); - } - } - - return $rec; - } - - /** - * - */ - public function get_resource_owner($dn) - { - $owner = null; - - if ($ldap = $this->resurces_ldap()) { - $owner = $ldap->get_record(rcube_ldap::dn_encode($dn), true); - $owner['ID'] = rcube_ldap::dn_decode($owner['ID']); - unset($owner['_raw_attrib'], $owner['_type']); - } - - return $owner; - } - - /** - * Extract JSON-serialized attributes - */ - private function decode_resource($rec) - { - if (is_array($rec['attributes']) && $rec['attributes'][0]) { - $attributes = array(); - - foreach ($rec['attributes'] as $sattr) { - $attr = @json_decode($sattr, true); - $attributes += $attr; - } - - $rec['attributes'] = $attributes; - } - - // remove unused cruft - unset($rec['_raw_attrib']); - - return $rec; - } - } diff --git a/plugins/calendar/drivers/ldap/resources_driver_ldap.php b/plugins/calendar/drivers/ldap/resources_driver_ldap.php new file mode 100644 index 00000000..23439b64 --- /dev/null +++ b/plugins/calendar/drivers/ldap/resources_driver_ldap.php @@ -0,0 +1,146 @@ + + * + * Copyright (C) 2014, Kolab Systems AG + * + * 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 . + */ + +/** + * LDAP-based resource directory implementation + */ +class resources_driver_ldap extends resources_driver +{ + private $rc; + private $cal; + private $ldap; + + /** + * Default constructor + */ + function __construct($cal) + { + $this->cal = $cal; + $this->rc = $cal->rc; + } + + /** + * Fetch resource objects to be displayed for booking + * + * @param string Search query (optional) + * @return array List of resource records available for booking + */ + public function load_resources($query = null, $num = 5000) + { + if (!($ldap = $this->connect())) { + return array(); + } + + // TODO: apply paging + $ldap->set_pagesize($num); + + if (isset($query)) { + $results = $ldap->search('*', $query, 0, true, true); + } + else { + $results = $ldap->list_records(); + } + + if ($results instanceof ArrayAccess) { + foreach ($results as $i => $rec) { + $results[$i] = $this->decode_resource($rec); + } + } + + return $results; + } + + /** + * Return properties of a single resource + * + * @param string Unique resource identifier + * @return array Resource object as hash array + */ + public function get_resource($dn) + { + $rec = null; + + if ($ldap = $this->connect()) { + $rec = $ldap->get_record(rcube_ldap::dn_encode($dn)); + + if (!empty($rec)) { + $rec = $this->decode_resource($rec); + } + } + + return $rec; + } + + /** + * Return properties of a resource owner + * + * @param string Owner identifier + * @return array Resource object as hash array + */ + public function get_resource_owner($dn) + { + $owner = null; + + if ($ldap = $this->connect()) { + $owner = $ldap->get_record(rcube_ldap::dn_encode($dn), true); + $owner['ID'] = rcube_ldap::dn_decode($owner['ID']); + unset($owner['_raw_attrib'], $owner['_type']); + } + + return $owner; + } + + /** + * Extract JSON-serialized attributes + */ + private function decode_resource($rec) + { + $rec['ID'] = rcube_ldap::dn_decode($rec['ID']); + + if (is_array($rec['attributes']) && $rec['attributes'][0]) { + $attributes = array(); + + foreach ($rec['attributes'] as $sattr) { + $attr = @json_decode($sattr, true); + $attributes += $attr; + } + + $rec['attributes'] = $attributes; + } + + // remove unused cruft + unset($rec['_raw_attrib']); + + return $rec; + } + + private function connect() + { + if (!isset($this->ldap)) { + $this->ldap = new rcube_ldap($this->rc->config->get('calendar_resources_directory'), true); + } + + return $this->ldap->ready ? $this->ldap : null; + } + +} \ No newline at end of file diff --git a/plugins/calendar/drivers/resources_driver.php b/plugins/calendar/drivers/resources_driver.php new file mode 100644 index 00000000..b1fed9c8 --- /dev/null +++ b/plugins/calendar/drivers/resources_driver.php @@ -0,0 +1,58 @@ + + * + * Copyright (C) 2014, Kolab Systems AG + * + * 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 . + */ + + +/** + * Interface definition for a resources directory driver classe + */ +abstract class resources_driver +{ + + /** + * Fetch resource objects to be displayed for booking + * + * @param string Search query (optional) + * @return array List of resource records available for booking + */ + abstract public function load_resources($query = null); + + /** + * Return properties of a single resource + * + * @param string Unique resource identifier + * @return array Resource object as hash array + */ + abstract public function get_resource($id); + + /** + * Return properties of a resource owner + * + * @param string Owner identifier + * @return array Resource object as hash array + */ + public function get_resource_owner($id) + { + return null; + } + +} diff --git a/plugins/calendar/lib/calendar_ui.php b/plugins/calendar/lib/calendar_ui.php index 710898f6..14bc422f 100644 --- a/plugins/calendar/lib/calendar_ui.php +++ b/plugins/calendar/lib/calendar_ui.php @@ -196,7 +196,6 @@ class calendar_ui unset($prop['user_id']); $prop['alarms'] = $this->cal->driver->alarms; $prop['attendees'] = $this->cal->driver->attendees; - $prop['resources'] = $this->cal->driver->resources; $prop['freebusy'] = $this->cal->driver->freebusy; $prop['attachments'] = $this->cal->driver->attachments; $prop['undelete'] = $this->cal->driver->undelete; diff --git a/plugins/calendar/skins/larry/templates/calendar.html b/plugins/calendar/skins/larry/templates/calendar.html index 574cded2..96be36ea 100644 --- a/plugins/calendar/skins/larry/templates/calendar.html +++ b/plugins/calendar/skins/larry/templates/calendar.html @@ -126,14 +126,6 @@
-