Changeset View
Changeset View
Standalone View
Standalone View
plugins/calendar/drivers/kolab/kolab_calendar.php
Show First 20 Lines • Show All 182 Lines • ▼ Show 20 Lines | public function update(&$prop) | ||||
return kolab_storage::folder_id($newfolder); | return kolab_storage::folder_id($newfolder); | ||||
} | } | ||||
/** | /** | ||||
* Getter for a single event object | * Getter for a single event object | ||||
*/ | */ | ||||
public function get_event($id) | public function get_event($id) | ||||
{ | { | ||||
// remove our occurrence identifier if it's there | |||||
$master_id = preg_replace('/-\d{8}(T\d{6})?$/', '', $id); | |||||
// directly access storage object | // directly access storage object | ||||
if (!$this->events[$id] && ($record = $this->storage->get_object($id))) | if (!$this->events[$id] && $master_id == $id && ($record = $this->storage->get_object($id))) { | ||||
$this->events[$id] = $this->_to_driver_event($record, true); | $this->events[$id] = $this->_to_driver_event($record, true); | ||||
} | |||||
// event not found, maybe a recurring instance is requested | // maybe a recurring instance is requested | ||||
if (!$this->events[$id]) { | if (!$this->events[$id] && $master_id != $id) { | ||||
$master_id = preg_replace('/-\d+(T\d{6})?$/', '', $id); | |||||
$instance_id = substr($id, strlen($master_id) + 1); | $instance_id = substr($id, strlen($master_id) + 1); | ||||
if ($master_id != $id && ($record = $this->storage->get_object($master_id))) { | if ($record = $this->storage->get_object($master_id)) { | ||||
$master = $this->_to_driver_event($record); | $master = $this->_to_driver_event($record, true); | ||||
$this->events[$master_id] = $master; | |||||
} | } | ||||
if ($master) { | |||||
// check for match in top-level exceptions (aka loose single occurrences) | // check for match in top-level exceptions (aka loose single occurrences) | ||||
if ($master && $master['_formatobj'] && ($instance = $master['_formatobj']->get_instance($instance_id))) { | if ($master['_formatobj'] && ($instance = $master['_formatobj']->get_instance($instance_id))) { | ||||
$this->events[$id] = $this->_to_driver_event($instance); | $this->events[$id] = $this->_to_driver_event($instance); | ||||
} | } | ||||
// check for match on the first instance already | // check for match on the first instance already | ||||
else if ($master['_instance'] && $master['_instance'] == $instance_id) { | else if ($master['_instance'] && $master['_instance'] == $instance_id) { | ||||
$this->events[$id] = $master; | $this->events[$id] = $master; | ||||
} | } | ||||
else if ($master && is_array($master['recurrence'])) { | else if (is_array($master['recurrence'])) { | ||||
$this->get_recurring_events($record, $master['start'], null, $id); | $this->get_recurring_events($record, $master['start'], null, $id); | ||||
} | } | ||||
} | } | ||||
} | |||||
return $this->events[$id]; | return $this->events[$id]; | ||||
} | } | ||||
/** | /** | ||||
* Get attachment body | * Get attachment body | ||||
* @see calendar_driver::get_attachment_body() | * @see calendar_driver::get_attachment_body() | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | if (empty($filter_query) && $this->get_namespace() != 'other') { | ||||
$partstat_exclude = array('NEEDS-ACTION','DECLINED'); | $partstat_exclude = array('NEEDS-ACTION','DECLINED'); | ||||
} | } | ||||
else { | else { | ||||
$partstat_exclude = array(); | $partstat_exclude = array(); | ||||
} | } | ||||
$events = array(); | $events = array(); | ||||
foreach ($this->storage->select($query) as $record) { | foreach ($this->storage->select($query) as $record) { | ||||
$event = $this->_to_driver_event($record, !$virtual); | $event = $this->_to_driver_event($record, !$virtual, false); | ||||
// remember seen categories | // remember seen categories | ||||
if ($event['categories']) { | if ($event['categories']) { | ||||
$cat = is_array($event['categories']) ? $event['categories'][0] : $event['categories']; | $cat = is_array($event['categories']) ? $event['categories'][0] : $event['categories']; | ||||
$this->categories[$cat]++; | $this->categories[$cat]++; | ||||
} | } | ||||
// list events in requested time window | // list events in requested time window | ||||
if ($event['start'] <= $end && $event['end'] >= $start) { | if ($event['start'] <= $end && $event['end'] >= $start) { | ||||
unset($event['_attendees']); | unset($event['_attendees']); | ||||
$add = true; | $add = true; | ||||
// skip the first instance of a recurring event if listed in exdate | // skip the first instance of a recurring event if listed in exdate | ||||
if ($virtual && !empty($event['recurrence']['EXDATE'])) { | if ($virtual && !empty($event['recurrence']['EXDATE'])) { | ||||
Show All 26 Lines | foreach ($this->storage->select($query) as $record) { | ||||
// resolve recurring events | // resolve recurring events | ||||
if ($record['recurrence'] && $virtual == 1) { | if ($record['recurrence'] && $virtual == 1) { | ||||
$events = array_merge($events, $this->get_recurring_events($record, $start, $end)); | $events = array_merge($events, $this->get_recurring_events($record, $start, $end)); | ||||
} | } | ||||
// add top-level exceptions (aka loose single occurrences) | // add top-level exceptions (aka loose single occurrences) | ||||
else if (is_array($record['exceptions'])) { | else if (is_array($record['exceptions'])) { | ||||
foreach ($record['exceptions'] as $ex) { | foreach ($record['exceptions'] as $ex) { | ||||
$component = $this->_to_driver_event($ex); | $component = $this->_to_driver_event($ex, false, false); | ||||
if ($component['start'] <= $end && $component['end'] >= $start) { | if ($component['start'] <= $end && $component['end'] >= $start) { | ||||
$events[] = $component; | $events[] = $component; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// post-filter all events by fulltext search and partstat values | // post-filter all events by fulltext search and partstat values | ||||
Show All 17 Lines | $events = array_filter($events, function($event) use ($words, $partstat_exclude, $user_emails, $me) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
}); | }); | ||||
// Apply event-to-mail relations | |||||
$config = kolab_storage_config::get_instance(); | |||||
$config->apply_links($events); | |||||
// avoid session race conditions that will loose temporary subscriptions | // avoid session race conditions that will loose temporary subscriptions | ||||
$this->cal->rc->session->nowrite = true; | $this->cal->rc->session->nowrite = true; | ||||
return $events; | return $events; | ||||
} | } | ||||
/** | /** | ||||
* | * | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | if (!is_array($event)) | ||||
return false; | return false; | ||||
// email links are stored separately | // email links are stored separately | ||||
$links = $event['links']; | $links = $event['links']; | ||||
unset($event['links']); | unset($event['links']); | ||||
//generate new event from RC input | //generate new event from RC input | ||||
$object = $this->_from_driver_event($event); | $object = $this->_from_driver_event($event); | ||||
$saved = $this->storage->save($object, 'event'); | $saved = $this->storage->save($object, 'event'); | ||||
if (!$saved) { | if (!$saved) { | ||||
rcube::raise_error(array( | rcube::raise_error(array( | ||||
'code' => 600, 'type' => 'php', | 'code' => 600, 'type' => 'php', | ||||
'file' => __FILE__, 'line' => __LINE__, | 'file' => __FILE__, 'line' => __LINE__, | ||||
'message' => "Error saving event object to Kolab server"), | 'message' => "Error saving event object to Kolab server"), | ||||
true, false); | true, false); | ||||
$saved = false; | $saved = false; | ||||
} | } | ||||
else { | else { | ||||
// save links in configuration.relation object | // save links in configuration.relation object | ||||
$this->save_links($event['uid'], $links); | if ($this->save_links($event['uid'], $links)) { | ||||
$object['links'] = $links; | |||||
} | |||||
$this->events = array($event['uid'] => $this->_to_driver_event($object, true)); | $this->events = array($event['uid'] => $this->_to_driver_event($object, true)); | ||||
} | } | ||||
return $saved; | return $saved; | ||||
} | } | ||||
/** | /** | ||||
* Update a specific event record | * Update a specific event record | ||||
* | * | ||||
* @see calendar_driver::new_event() | * @see calendar_driver::new_event() | ||||
* @return boolean True on success, False on error | * @return boolean True on success, False on error | ||||
*/ | */ | ||||
public function update_event($event, $exception_id = null) | public function update_event($event, $exception_id = null) | ||||
{ | { | ||||
$updated = false; | $updated = false; | ||||
$old = $this->storage->get_object($event['uid'] ?: $event['id']); | $old = $this->storage->get_object($event['uid'] ?: $event['id']); | ||||
if (!$old || PEAR::isError($old)) | if (!$old || PEAR::isError($old)) | ||||
return false; | return false; | ||||
// email links are stored separately | // email links are stored separately | ||||
$links = $event['links']; | $links = $event['links']; | ||||
unset($event['links']); | unset($event['links']); | ||||
$object = $this->_from_driver_event($event, $old); | $object = $this->_from_driver_event($event, $old); | ||||
$saved = $this->storage->save($object, 'event', $old['uid']); | $saved = $this->storage->save($object, 'event', $old['uid']); | ||||
if (!$saved) { | if (!$saved) { | ||||
rcube::raise_error(array( | rcube::raise_error(array( | ||||
'code' => 600, 'type' => 'php', | 'code' => 600, 'type' => 'php', | ||||
'file' => __FILE__, 'line' => __LINE__, | 'file' => __FILE__, 'line' => __LINE__, | ||||
'message' => "Error saving event object to Kolab server"), | 'message' => "Error saving event object to Kolab server"), | ||||
true, false); | true, false); | ||||
} | } | ||||
else { | else { | ||||
// save links in configuration.relation object | // save links in configuration.relation object | ||||
$this->save_links($event['uid'], $links); | if ($this->save_links($event['uid'], $links)) { | ||||
$object['links'] = $links; | |||||
} | |||||
$updated = true; | $updated = true; | ||||
$this->events = array($event['uid'] => $this->_to_driver_event($object, true)); | $this->events = array($event['uid'] => $this->_to_driver_event($object, true)); | ||||
// refresh local cache with recurring instances | // refresh local cache with recurring instances | ||||
if ($exception_id) { | if ($exception_id) { | ||||
$this->get_recurring_events($object, $event['start'], $event['end'], $exception_id); | $this->get_recurring_events($object, $event['start'], $event['end'], $exception_id); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | protected function get_links($uid) | ||||
return $storage->get_object_links($uid); | return $storage->get_object_links($uid); | ||||
} | } | ||||
/** | /** | ||||
* | * | ||||
*/ | */ | ||||
protected function save_links($uid, $links) | protected function save_links($uid, $links) | ||||
{ | { | ||||
// make sure we have a valid array | |||||
if (empty($links)) { | |||||
$links = array(); | |||||
} | |||||
$storage = kolab_storage_config::get_instance(); | $storage = kolab_storage_config::get_instance(); | ||||
$remove = array_diff($storage->get_object_links($uid), $links); | return $storage->save_object_links($uid, (array) $links); | ||||
return $storage->save_object_links($uid, $links, $remove); | |||||
} | } | ||||
/** | /** | ||||
* Create instances of a recurring event | * Create instances of a recurring event | ||||
* | * | ||||
* @param array Hash array with event properties | * @param array Hash array with event properties | ||||
* @param object DateTime Start date of the recurrence window | * @param object DateTime Start date of the recurrence window | ||||
* @param object DateTime End date of the recurrence window | * @param object DateTime End date of the recurrence window | ||||
Show All 32 Lines | public function get_recurring_events($event, $start, $end = null, $event_id = null) | ||||
$futuredata = array(); | $futuredata = array(); | ||||
$recurrence_id_format = libcalendaring::recurrence_id_format($event); | $recurrence_id_format = libcalendaring::recurrence_id_format($event); | ||||
if (is_array($event['recurrence']['EXCEPTIONS'])) { | if (is_array($event['recurrence']['EXCEPTIONS'])) { | ||||
foreach ($event['recurrence']['EXCEPTIONS'] as $exception) { | foreach ($event['recurrence']['EXCEPTIONS'] as $exception) { | ||||
if (!$exception['_instance']) | if (!$exception['_instance']) | ||||
$exception['_instance'] = libcalendaring::recurrence_instance_identifier($exception); | $exception['_instance'] = libcalendaring::recurrence_instance_identifier($exception); | ||||
$rec_event = $this->_to_driver_event($exception); | $rec_event = $this->_to_driver_event($exception, false, false); | ||||
$rec_event['id'] = $event['uid'] . '-' . $exception['_instance']; | $rec_event['id'] = $event['uid'] . '-' . $exception['_instance']; | ||||
$rec_event['isexception'] = 1; | $rec_event['isexception'] = 1; | ||||
// found the specifically requested instance: register exception (single occurrence wins) | // found the specifically requested instance: register exception (single occurrence wins) | ||||
if ($rec_event['id'] == $event_id && (!$this->events[$event_id] || $this->events[$event_id]['thisandfuture'])) { | if ($rec_event['id'] == $event_id && (!$this->events[$event_id] || $this->events[$event_id]['thisandfuture'])) { | ||||
$rec_event['recurrence'] = $recurrence_rule; | $rec_event['recurrence'] = $recurrence_rule; | ||||
$rec_event['recurrence_id'] = $event['uid']; | $rec_event['recurrence_id'] = $event['uid']; | ||||
$this->events[$rec_event['id']] = $rec_event; | $this->events[$rec_event['id']] = $rec_event; | ||||
Show All 32 Lines | while ($next_event = $recurrence->next_instance()) { | ||||
// use this event data for future recurring instances | // use this event data for future recurring instances | ||||
if ($futuredata[$datestr]) | if ($futuredata[$datestr]) | ||||
$overlay_data = $futuredata[$datestr]; | $overlay_data = $futuredata[$datestr]; | ||||
// add to output if in range | // add to output if in range | ||||
$rec_id = $event['uid'] . '-' . $instance_id; | $rec_id = $event['uid'] . '-' . $instance_id; | ||||
if (($next_event['start'] <= $end && $next_event['end'] >= $start) || ($event_id && $rec_id == $event_id)) { | if (($next_event['start'] <= $end && $next_event['end'] >= $start) || ($event_id && $rec_id == $event_id)) { | ||||
$rec_event = $this->_to_driver_event($next_event); | $rec_event = $this->_to_driver_event($next_event, false, false); | ||||
$rec_event['_instance'] = $instance_id; | $rec_event['_instance'] = $instance_id; | ||||
$rec_event['_count'] = $i + 1; | $rec_event['_count'] = $i + 1; | ||||
if ($overlay_data || $exdata[$datestr]) // copy data from exception | if ($overlay_data || $exdata[$datestr]) // copy data from exception | ||||
kolab_driver::merge_exception_data($rec_event, $exdata[$datestr] ?: $overlay_data); | kolab_driver::merge_exception_data($rec_event, $exdata[$datestr] ?: $overlay_data); | ||||
$rec_event['id'] = $rec_id; | $rec_event['id'] = $rec_id; | ||||
$rec_event['recurrence_id'] = $event['uid']; | $rec_event['recurrence_id'] = $event['uid']; | ||||
Show All 15 Lines | public function get_recurring_events($event, $start, $end = null, $event_id = null) | ||||
} | } | ||||
return $events; | return $events; | ||||
} | } | ||||
/** | /** | ||||
* Convert from Kolab_Format to internal representation | * Convert from Kolab_Format to internal representation | ||||
*/ | */ | ||||
private function _to_driver_event($record, $noinst = false) | private function _to_driver_event($record, $noinst = false, $links = true) | ||||
{ | { | ||||
$record['calendar'] = $this->id; | $record['calendar'] = $this->id; | ||||
if ($links && !array_key_exists('links', $record)) { | |||||
$record['links'] = $this->get_links($record['uid']); | $record['links'] = $this->get_links($record['uid']); | ||||
} | |||||
if ($this->get_namespace() == 'other') { | if ($this->get_namespace() == 'other') { | ||||
$record['className'] = 'fc-event-ns-other'; | $record['className'] = 'fc-event-ns-other'; | ||||
$record = kolab_driver::add_partstat_class($record, array('NEEDS-ACTION','DECLINED'), $this->get_owner()); | $record = kolab_driver::add_partstat_class($record, array('NEEDS-ACTION','DECLINED'), $this->get_owner()); | ||||
} | } | ||||
// add instance identifier to first occurrence (master event) | // add instance identifier to first occurrence (master event) | ||||
$recurrence_id_format = libcalendaring::recurrence_id_format($record); | $recurrence_id_format = libcalendaring::recurrence_id_format($record); | ||||
▲ Show 20 Lines • Show All 115 Lines • Show Last 20 Lines |