Changeset View
Changeset View
Standalone View
Standalone View
plugins/calendar/drivers/kolab/kolab_driver.php
Show All 31 Lines | class kolab_driver extends calendar_driver | ||||
public $alarms = true; | public $alarms = true; | ||||
public $attendees = true; | public $attendees = true; | ||||
public $freebusy = true; | public $freebusy = true; | ||||
public $attachments = true; | public $attachments = true; | ||||
public $undelete = true; | public $undelete = true; | ||||
public $alarm_types = ['DISPLAY', 'AUDIO']; | public $alarm_types = ['DISPLAY', 'AUDIO']; | ||||
public $categoriesimmutable = true; | public $categoriesimmutable = true; | ||||
private $rc; | protected $rc; | ||||
private $cal; | protected $cal; | ||||
private $calendars; | protected $calendars; | ||||
private $has_writeable = false; | protected $storage; | ||||
private $freebusy_trigger = false; | protected $has_writeable = false; | ||||
private $bonnie_api = false; | protected $freebusy_trigger = false; | ||||
protected $bonnie_api = false; | |||||
/** | /** | ||||
* Default constructor | * Default constructor | ||||
*/ | */ | ||||
public function __construct($cal) | public function __construct($cal) | ||||
{ | { | ||||
$cal->require_plugin('libkolab'); | $cal->require_plugin('libkolab'); | ||||
// load helper classes *after* libkolab has been loaded (#3248) | // load helper classes *after* libkolab has been loaded (#3248) | ||||
require_once(__DIR__ . '/kolab_calendar.php'); | require_once(__DIR__ . '/kolab_calendar.php'); | ||||
require_once(__DIR__ . '/kolab_user_calendar.php'); | require_once(__DIR__ . '/kolab_user_calendar.php'); | ||||
require_once(__DIR__ . '/kolab_invitation_calendar.php'); | require_once(__DIR__ . '/kolab_invitation_calendar.php'); | ||||
$this->cal = $cal; | $this->cal = $cal; | ||||
$this->rc = $cal->rc; | $this->rc = $cal->rc; | ||||
$this->storage = new kolab_storage(); | |||||
$this->cal->register_action('push-freebusy', [$this, 'push_freebusy']); | $this->cal->register_action('push-freebusy', [$this, 'push_freebusy']); | ||||
$this->cal->register_action('calendar-acl', [$this, 'calendar_acl']); | $this->cal->register_action('calendar-acl', [$this, 'calendar_acl']); | ||||
$this->freebusy_trigger = $this->rc->config->get('calendar_freebusy_trigger', false); | $this->freebusy_trigger = $this->rc->config->get('calendar_freebusy_trigger', false); | ||||
if (kolab_storage::$version == '2.0') { | if (kolab_storage::$version == '2.0') { | ||||
$this->alarm_types = ['DISPLAY']; | $this->alarm_types = ['DISPLAY']; | ||||
$this->alarm_absolute = false; | $this->alarm_absolute = false; | ||||
} | } | ||||
// get configuration for the Bonnie API | // get configuration for the Bonnie API | ||||
$this->bonnie_api = libkolab::get_bonnie_api(); | $this->bonnie_api = libkolab::get_bonnie_api(); | ||||
// calendar uses fully encoded identifiers | // calendar uses fully encoded identifiers | ||||
kolab_storage::$encode_ids = true; | kolab_storage::$encode_ids = true; | ||||
} | } | ||||
/** | /** | ||||
* Read available calendars from server | * Read available calendars from server | ||||
*/ | */ | ||||
private function _read_calendars() | protected function _read_calendars() | ||||
{ | { | ||||
// already read sources | // already read sources | ||||
if (isset($this->calendars)) { | if (isset($this->calendars)) { | ||||
return $this->calendars; | return $this->calendars; | ||||
} | } | ||||
// get all folders that have "event" type, sorted by namespace/name | // get all folders that have "event" type, sorted by namespace/name | ||||
$folders = kolab_storage::sort_folders( | $folders = $this->storage->sort_folders( | ||||
kolab_storage::get_folders('event') + kolab_storage::get_user_folders('event', true) | $this->storage->get_folders('event') + kolab_storage::get_user_folders('event', true) | ||||
); | ); | ||||
$this->calendars = []; | $this->calendars = []; | ||||
foreach ($folders as $folder) { | foreach ($folders as $folder) { | ||||
$calendar = $this->_to_calendar($folder); | $calendar = $this->_to_calendar($folder); | ||||
if ($calendar->ready) { | if ($calendar->ready) { | ||||
$this->calendars[$calendar->id] = $calendar; | $this->calendars[$calendar->id] = $calendar; | ||||
if ($calendar->editable) { | if ($calendar->editable) { | ||||
$this->has_writeable = true; | $this->has_writeable = true; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return $this->calendars; | return $this->calendars; | ||||
} | } | ||||
/** | /** | ||||
* Convert kolab_storage_folder into kolab_calendar | * Convert kolab_storage_folder into kolab_calendar | ||||
*/ | */ | ||||
private function _to_calendar($folder) | protected function _to_calendar($folder) | ||||
{ | { | ||||
if ($folder instanceof kolab_calendar) { | if ($folder instanceof kolab_calendar) { | ||||
return $folder; | return $folder; | ||||
} | } | ||||
if ($folder instanceof kolab_storage_folder_user) { | if ($folder instanceof kolab_storage_folder_user) { | ||||
$calendar = new kolab_user_calendar($folder, $this->cal); | $calendar = new kolab_user_calendar($folder, $this->cal); | ||||
$calendar->subscriptions = count($folder->children) > 0; | $calendar->subscriptions = count($folder->children) > 0; | ||||
Show All 26 Lines | public function list_calendars($filter = 0, &$tree = null) | ||||
} | } | ||||
$delim = $this->rc->get_storage()->get_hierarchy_delimiter(); | $delim = $this->rc->get_storage()->get_hierarchy_delimiter(); | ||||
$folders = $this->filter_calendars($filter); | $folders = $this->filter_calendars($filter); | ||||
$calendars = []; | $calendars = []; | ||||
// include virtual folders for a full folder tree | // include virtual folders for a full folder tree | ||||
if (!is_null($tree)) { | if (!is_null($tree)) { | ||||
$folders = kolab_storage::folder_hierarchy($folders, $tree); | $folders = $this->storage->folder_hierarchy($folders, $tree); | ||||
} | } | ||||
$parents = array_keys($this->calendars); | $parents = array_keys($this->calendars); | ||||
foreach ($folders as $id => $cal) { | foreach ($folders as $id => $cal) { | ||||
$imap_path = explode($delim, $cal->name); | $imap_path = explode($delim, $cal->name); | ||||
// find parent | // find parent | ||||
do { | do { | ||||
array_pop($imap_path); | array_pop($imap_path); | ||||
$parent_id = kolab_storage::folder_id(join($delim, $imap_path)); | $parent_id = $this->storage->folder_id(join($delim, $imap_path)); | ||||
} | } | ||||
while (count($imap_path) > 1 && !in_array($parent_id, $parents)); | while (count($imap_path) > 1 && !in_array($parent_id, $parents)); | ||||
// restore "real" parent ID | // restore "real" parent ID | ||||
if ($parent_id && !in_array($parent_id, $parents)) { | if ($parent_id && !in_array($parent_id, $parents)) { | ||||
$parent_id = kolab_storage::folder_id($cal->get_parent()); | $parent_id = $this->storage->folder_id($cal->get_parent()); | ||||
} | } | ||||
$parents[] = $cal->id; | $parents[] = $cal->id; | ||||
if ($cal->virtual) { | if ($cal->virtual) { | ||||
$calendars[$cal->id] = [ | $calendars[$cal->id] = [ | ||||
'id' => $cal->id, | 'id' => $cal->id, | ||||
'name' => $cal->get_name(), | 'name' => $cal->get_name(), | ||||
▲ Show 20 Lines • Show All 199 Lines • ▼ Show 20 Lines | class kolab_driver extends calendar_driver | ||||
* @return mixed ID of the calendar on success, False on error | * @return mixed ID of the calendar on success, False on error | ||||
*/ | */ | ||||
public function create_calendar($prop) | public function create_calendar($prop) | ||||
{ | { | ||||
$prop['type'] = 'event'; | $prop['type'] = 'event'; | ||||
$prop['active'] = true; | $prop['active'] = true; | ||||
$prop['subscribed'] = true; | $prop['subscribed'] = true; | ||||
$folder = kolab_storage::folder_update($prop); | $folder = $this->storage->folder_update($prop); | ||||
if ($folder === false) { | if ($folder === false) { | ||||
$this->last_error = $this->cal->gettext(kolab_storage::$last_error); | $this->last_error = $this->cal->gettext($this->storage->last_error); | ||||
return false; | return false; | ||||
} | } | ||||
// create ID | // create ID | ||||
$id = kolab_storage::folder_id($folder); | $id = $this->storage->folder_id($folder); | ||||
// save color in user prefs (temp. solution) | // save color in user prefs (temp. solution) | ||||
$prefs['kolab_calendars'] = $this->rc->config->get('kolab_calendars', []); | $prefs['kolab_calendars'] = $this->rc->config->get('kolab_calendars', []); | ||||
if (isset($prop['color'])) { | if (isset($prop['color'])) { | ||||
$prefs['kolab_calendars'][$id]['color'] = $prop['color']; | $prefs['kolab_calendars'][$id]['color'] = $prop['color']; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | public function subscribe_calendar($prop) | ||||
$ret |= $cal->storage->subscribe(intval($prop['permanent'])); | $ret |= $cal->storage->subscribe(intval($prop['permanent'])); | ||||
} | } | ||||
if (isset($prop['active'])) { | if (isset($prop['active'])) { | ||||
$ret |= $cal->storage->activate(intval($prop['active'])); | $ret |= $cal->storage->activate(intval($prop['active'])); | ||||
} | } | ||||
// apply to child folders, too | // apply to child folders, too | ||||
if (!empty($prop['recursive'])) { | if (!empty($prop['recursive'])) { | ||||
foreach ((array) kolab_storage::list_folders($cal->storage->name, '*', 'event') as $subfolder) { | foreach ((array) $this->storage->list_folders($cal->storage->name, '*', 'event') as $subfolder) { | ||||
if (isset($prop['permanent'])) { | if (isset($prop['permanent'])) { | ||||
if ($prop['permanent']) { | if ($prop['permanent']) { | ||||
kolab_storage::folder_subscribe($subfolder); | $this->storage->folder_subscribe($subfolder); | ||||
} | } | ||||
else { | else { | ||||
kolab_storage::folder_unsubscribe($subfolder); | $this->storage->folder_unsubscribe($subfolder); | ||||
} | } | ||||
} | } | ||||
if (isset($prop['active'])) { | if (isset($prop['active'])) { | ||||
if ($prop['active']) { | if ($prop['active']) { | ||||
kolab_storage::folder_activate($subfolder); | $this->storage->folder_activate($subfolder); | ||||
} | } | ||||
else { | else { | ||||
kolab_storage::folder_deactivate($subfolder); | $this->storage->folder_deactivate($subfolder); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return $ret; | return $ret; | ||||
} | } | ||||
else { | else { | ||||
// save state in local prefs | // save state in local prefs | ||||
Show All 12 Lines | class kolab_driver extends calendar_driver | ||||
* @see calendar_driver::delete_calendar() | * @see calendar_driver::delete_calendar() | ||||
*/ | */ | ||||
public function delete_calendar($prop) | public function delete_calendar($prop) | ||||
{ | { | ||||
if (!empty($prop['id']) && ($cal = $this->get_calendar($prop['id']))) { | if (!empty($prop['id']) && ($cal = $this->get_calendar($prop['id']))) { | ||||
$folder = $cal->get_realname(); | $folder = $cal->get_realname(); | ||||
// TODO: unsubscribe if no admin rights | // TODO: unsubscribe if no admin rights | ||||
if (kolab_storage::folder_delete($folder)) { | if ($this->storage->folder_delete($folder)) { | ||||
// remove color in user prefs (temp. solution) | // remove color in user prefs (temp. solution) | ||||
$prefs['kolab_calendars'] = $this->rc->config->get('kolab_calendars', []); | $prefs['kolab_calendars'] = $this->rc->config->get('kolab_calendars', []); | ||||
unset($prefs['kolab_calendars'][$prop['id']]); | unset($prefs['kolab_calendars'][$prop['id']]); | ||||
$this->rc->user->save_prefs($prefs); | $this->rc->user->save_prefs($prefs); | ||||
return true; | return true; | ||||
} | } | ||||
else { | else { | ||||
$this->last_error = kolab_storage::$last_error; | $this->last_error = $this->storage->last_error; | ||||
} | } | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* Search for shared or otherwise not listed calendars the user has access | * Search for shared or otherwise not listed calendars the user has access | ||||
* | * | ||||
* @param string Search string | * @param string Search string | ||||
* @param string Section/source to search | * @param string Section/source to search | ||||
* | * | ||||
* @return array List of calendars | * @return array List of calendars | ||||
*/ | */ | ||||
public function search_calendars($query, $source) | public function search_calendars($query, $source) | ||||
{ | { | ||||
if (!kolab_storage::setup()) { | if (!$this->storage->setup()) { | ||||
return []; | return []; | ||||
} | } | ||||
$this->calendars = []; | $this->calendars = []; | ||||
$this->search_more_results = false; | $this->search_more_results = false; | ||||
// find unsubscribed IMAP folders that have "event" type | // find unsubscribed IMAP folders that have "event" type | ||||
if ($source == 'folders') { | if ($source == 'folders') { | ||||
foreach ((array) kolab_storage::search_folders('event', $query, ['other']) as $folder) { | foreach ((array) $this->storage->search_folders('event', $query, ['other']) as $folder) { | ||||
$calendar = new kolab_calendar($folder->name, $this->cal); | $calendar = new kolab_calendar($folder->name, $this->cal); | ||||
$this->calendars[$calendar->id] = $calendar; | $this->calendars[$calendar->id] = $calendar; | ||||
} | } | ||||
} | } | ||||
// find other user's virtual calendars | // find other user's virtual calendars | ||||
else if ($source == 'users') { | else if ($source == 'users') { | ||||
// we have slightly more space, so display twice the number | // we have slightly more space, so display twice the number | ||||
$limit = $this->rc->config->get('autocomplete_max', 15) * 2; | $limit = $this->rc->config->get('autocomplete_max', 15) * 2; | ||||
foreach (kolab_storage::search_users($query, 0, [], $limit, $count) as $user) { | foreach ($this->storage->search_users($query, 0, [], $limit, $count) as $user) { | ||||
$calendar = new kolab_user_calendar($user, $this->cal); | $calendar = new kolab_user_calendar($user, $this->cal); | ||||
$this->calendars[$calendar->id] = $calendar; | $this->calendars[$calendar->id] = $calendar; | ||||
// search for calendar folders shared by this user | // search for calendar folders shared by this user | ||||
foreach (kolab_storage::list_user_folders($user, 'event', false) as $foldername) { | foreach ($this->storage->list_user_folders($user, 'event', false) as $foldername) { | ||||
$cal = new kolab_calendar($foldername, $this->cal); | $cal = new kolab_calendar($foldername, $this->cal); | ||||
$this->calendars[$cal->id] = $cal; | $this->calendars[$cal->id] = $cal; | ||||
$calendar->subscriptions = true; | $calendar->subscriptions = true; | ||||
} | } | ||||
} | } | ||||
if ($count > $limit) { | if ($count > $limit) { | ||||
$this->search_more_results = true; | $this->search_more_results = true; | ||||
▲ Show 20 Lines • Show All 423 Lines • ▼ Show 20 Lines | public function restore_event($event) | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* Wrapper to update an event object depending on the given savemode | * Wrapper to update an event object depending on the given savemode | ||||
*/ | */ | ||||
private function update_event($event) | protected function update_event($event) | ||||
{ | { | ||||
if (!($storage = $this->get_calendar($event['calendar']))) { | if (!($storage = $this->get_calendar($event['calendar']))) { | ||||
return false; | return false; | ||||
} | } | ||||
// move event to another folder/calendar | // move event to another folder/calendar | ||||
if (!empty($event['_fromcalendar']) && $event['_fromcalendar'] != $event['calendar']) { | if (!empty($event['_fromcalendar']) && $event['_fromcalendar'] != $event['calendar']) { | ||||
if (!($fromcalendar = $this->get_calendar($event['_fromcalendar']))) { | if (!($fromcalendar = $this->get_calendar($event['_fromcalendar']))) { | ||||
▲ Show 20 Lines • Show All 952 Lines • ▼ Show 20 Lines | public function get_recurring_events($event, $start, $end = null) | ||||
$storage = reset($this->calendars); | $storage = reset($this->calendars); | ||||
return $storage->get_recurring_events($event, $start, $end); | return $storage->get_recurring_events($event, $start, $end); | ||||
} | } | ||||
/** | /** | ||||
* | * | ||||
*/ | */ | ||||
private function get_recurrence_count($event, $dtstart) | protected function get_recurrence_count($event, $dtstart) | ||||
{ | { | ||||
// load the given event data into a libkolabxml container | // load the given event data into a libkolabxml container | ||||
if (empty($event['_formatobj'])) { | if (empty($event['_formatobj'])) { | ||||
$event_xml = new kolab_format_event(); | $event_xml = new kolab_format_event(); | ||||
$event_xml->set($event); | $event_xml->set($event); | ||||
$event['_formatobj'] = $event_xml; | $event['_formatobj'] = $event_xml; | ||||
} | } | ||||
Show All 27 Lines | public function get_freebusy_list($email, $start, $end) | ||||
// ask kolab server first | // ask kolab server first | ||||
try { | try { | ||||
$request_config = [ | $request_config = [ | ||||
'store_body' => true, | 'store_body' => true, | ||||
'follow_redirects' => true, | 'follow_redirects' => true, | ||||
]; | ]; | ||||
$request = libkolab::http_request(kolab_storage::get_freebusy_url($email), 'GET', $request_config); | $request = libkolab::http_request($this->storage->get_freebusy_url($email), 'GET', $request_config); | ||||
$response = $request->send(); | $response = $request->send(); | ||||
// authentication required | // authentication required | ||||
if ($response->getStatus() == 401) { | if ($response->getStatus() == 401) { | ||||
$request->setAuth($this->rc->user->get_username(), $this->rc->decrypt($_SESSION['password'])); | $request->setAuth($this->rc->user->get_username(), $this->rc->decrypt($_SESSION['password'])); | ||||
$response = $request->send(); | $response = $request->send(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 470 Lines • ▼ Show 20 Lines | public function restore_event_revision($event, $rev) | ||||
return $success; | return $success; | ||||
} | } | ||||
/** | /** | ||||
* Helper method to resolved the given event identifier into uid and folder | * Helper method to resolved the given event identifier into uid and folder | ||||
* | * | ||||
* @return array (uid,folder,msguid) tuple | * @return array (uid,folder,msguid) tuple | ||||
*/ | */ | ||||
private function _resolve_event_identity($event) | protected function _resolve_event_identity($event) | ||||
{ | { | ||||
$mailbox = $msguid = null; | $mailbox = $msguid = null; | ||||
if (is_array($event)) { | if (is_array($event)) { | ||||
$uid = !empty($event['uid']) ? $event['uid'] : $event['id']; | $uid = !empty($event['uid']) ? $event['uid'] : $event['id']; | ||||
if (($cal = $this->get_calendar($event['calendar'])) && !($cal instanceof kolab_invitation_calendar)) { | if (($cal = $this->get_calendar($event['calendar'])) && !($cal instanceof kolab_invitation_calendar)) { | ||||
$mailbox = $cal->get_mailbox_id(); | $mailbox = $cal->get_mailbox_id(); | ||||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | public function calendar_form($action, $calendar, $formfields) | ||||
'name' => $this->rc->gettext('properties'), | 'name' => $this->rc->gettext('properties'), | ||||
'fields' => [], | 'fields' => [], | ||||
]; | ]; | ||||
$protected = !empty($options) && (!empty($options['norename']) || !empty($options['protected'])); | $protected = !empty($options) && (!empty($options['norename']) || !empty($options['protected'])); | ||||
// Disable folder name input | // Disable folder name input | ||||
if ($protected) { | if ($protected) { | ||||
$input_name = new html_hiddenfield(['name' => 'name', 'id' => 'calendar-name']); | $input_name = new html_hiddenfield(['name' => 'name', 'id' => 'calendar-name']); | ||||
$formfields['name']['value'] = kolab_storage::object_name($folder) | $formfields['name']['value'] = $this->storage->object_name($folder) | ||||
. $input_name->show($folder); | . $input_name->show($folder); | ||||
} | } | ||||
// calendar name (default field) | // calendar name (default field) | ||||
$form['props']['fields']['location'] = $formfields['name']; | $form['props']['fields']['location'] = $formfields['name']; | ||||
if ($protected) { | if ($protected) { | ||||
// prevent user from moving folder | // prevent user from moving folder | ||||
$hidden_fields[] = ['name' => 'parent', 'value' => $path_imap]; | $hidden_fields[] = ['name' => 'parent', 'value' => $path_imap]; | ||||
} | } | ||||
else { | else { | ||||
$select = kolab_storage::folder_selector('event', ['name' => 'parent', 'id' => 'calendar-parent'], $folder); | $select = $this->storage->folder_selector('event', ['name' => 'parent', 'id' => 'calendar-parent'], $folder); | ||||
$form['props']['fields']['path'] = [ | $form['props']['fields']['path'] = [ | ||||
'id' => 'calendar-parent', | 'id' => 'calendar-parent', | ||||
'label' => $this->cal->gettext('parentcalendar'), | 'label' => $this->cal->gettext('parentcalendar'), | ||||
'value' => $select->show(strlen($folder) ? $path_imap : ''), | 'value' => $select->show(strlen($folder) ? $path_imap : ''), | ||||
]; | ]; | ||||
} | } | ||||
Show All 19 Lines |