diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php --- a/plugins/calendar/calendar.php +++ b/plugins/calendar/calendar.php @@ -2505,17 +2505,37 @@ /**** Event invitation plugin hooks ****/ /** + * Find an event in user calendars + */ + protected function find_event($event) + { + $this->load_driver(); + + // We search for writeable calendars in personal namespace by default + $result = $this->driver->get_event($event, calendar_driver::FILTER_WRITEABLE | calendar_driver::FILTER_PERSONAL); + + // Some plugins may search in other users calendars, e.g. where delegation is involved + $plugin = $this->rc->plugins->exec_hook('calendar_event_find', array( + 'search' => $event, + 'result' => $result, + 'calendar' => $this, + )); + + return $plugin['result']; + } + + /** * Handler for calendar/itip-status requests */ function event_itip_status() { $data = rcube_utils::get_input_value('data', rcube_utils::INPUT_POST, true); - // find local copy of the referenced event $this->load_driver(); - $existing = $this->driver->get_event($data, calendar_driver::FILTER_WRITEABLE | calendar_driver::FILTER_PERSONAL); - $itip = $this->load_itip(); + // find local copy of the referenced event + $existing = $this->find_event($data); + $itip = $this->load_itip(); $response = $itip->get_itip_status($data, $existing); // get a list of writeable calendars to save new events to @@ -2914,7 +2934,7 @@ // save to calendar if ($calendar && $calendar['editable']) { // check for existing event with the same UID - $existing = $this->driver->get_event($event, calendar_driver::FILTER_WRITEABLE | calendar_driver::FILTER_PERSONAL); + $existing = $this->find_event($event); if ($existing) { // forward savemode for correct updates of recurring events diff --git a/plugins/kolab_delegation/kolab_delegation.php b/plugins/kolab_delegation/kolab_delegation.php --- a/plugins/kolab_delegation/kolab_delegation.php +++ b/plugins/kolab_delegation/kolab_delegation.php @@ -54,6 +54,7 @@ $this->add_hook('calendar_user_emails', array($this, 'calendar_user_emails')); $this->add_hook('calendar_list_filter', array($this, 'calendar_list_filter')); $this->add_hook('calendar_load_itip', array($this, 'calendar_load_itip')); + $this->add_hook('calendar_event_find', array($this, 'calendar_event_find')); // delegation support in kolab_auth plugin $this->add_hook('kolab_auth_emails', array($this, 'kolab_auth_emails')); @@ -260,6 +261,22 @@ } /** + * calendar::find_event() handler + */ + public function calendar_event_find($args) + { + // If the event can't be found in user personal folders, we'll + // look in delegators' folders (T1264) + + if (!empty($_SESSION['delegators']) && empty($args['result'])) { + $engine = $this->engine(); + $engine->delegator_find_event($args); + } + + return $args; + } + + /** * Delegation support in Calendar plugin UI */ public function calendar_ui() diff --git a/plugins/kolab_delegation/kolab_delegation_engine.php b/plugins/kolab_delegation/kolab_delegation_engine.php --- a/plugins/kolab_delegation/kolab_delegation_engine.php +++ b/plugins/kolab_delegation/kolab_delegation_engine.php @@ -864,6 +864,39 @@ } /** + * Finds an event in delegators' folders. Calendar looks only in + * personal namespace, we "extend" this to delegators' folders. + * + * @param array $args Reference to plugin hook arguments + */ + public function delegator_find_event(&$args) + { + // The event wasn't found and current user has delegators + if (!empty($_SESSION['delegators']) && empty($args['result'])) { + $event = $args['search']; + $ns_root = kolab_storage::namespace_root('other'); + $storage = $this->rc->get_storage(); + $delimiter = $storage->get_hierarchy_delimiter(); + $folders = $storage->list_folders_subscribed($ns_root, '*', 'event', 'w'); + + // search in all delegators' calendars + foreach ($folders as $folder) { + list($uid, $path) = explode($delimiter, substr($folder, strlen($ns_root)), 2); + + if (!empty($_SESSION['delegators'][$uid])) { + $event['calendar'] = kolab_storage::folder_id($folder, true); + $result = $args['calendar']->driver->get_event($event, calendar_driver::FILTER_WRITEABLE); + + if ($result) { + $args['result'] = $result; + return; + } + } + } + } + } + + /** * Compares two ACLs (according to supported rights) * * @param array $acl1 ACL rights array (or string)