Implement searching for unsubscribed IMAP folders and temporary/session subscriptions
This commit is contained in:
parent
00b1c7631b
commit
008c5db5d9
11 changed files with 411 additions and 108 deletions
|
@ -725,9 +725,29 @@ class calendar extends rcube_plugin
|
||||||
$this->rc->output->command('plugin.destroy_source', array('id' => $cal['id']));
|
$this->rc->output->command('plugin.destroy_source', array('id' => $cal['id']));
|
||||||
break;
|
break;
|
||||||
case "subscribe":
|
case "subscribe":
|
||||||
if (!$this->driver->subscribe_calendar($cal))
|
if (!$this->driver->subscribe_calendar($cal, intval(get_input_value('perm', RCUBE_INPUT_GPC))))
|
||||||
$this->rc->output->show_message($this->gettext('errorsaving'), 'error');
|
$this->rc->output->show_message($this->gettext('errorsaving'), 'error');
|
||||||
return;
|
return;
|
||||||
|
case "search":
|
||||||
|
$results = array();
|
||||||
|
$color_mode = $this->rc->config->get('calendar_event_coloring', $this->defaults['calendar_event_coloring']);
|
||||||
|
foreach ((array)$this->driver->search_calendars(get_input_value('q', RCUBE_INPUT_GPC), get_input_value('source', RCUBE_INPUT_GPC)) as $id => $prop) {
|
||||||
|
$editname = $prop['editname'];
|
||||||
|
unset($prop['editname']); // force full name to be displayed
|
||||||
|
$prop['active'] = false;
|
||||||
|
|
||||||
|
// let the UI generate HTML and CSS representation for this calendar
|
||||||
|
$html = $this->ui->calendar_list_item($id, $prop, $jsenv);
|
||||||
|
$cal = $jsenv[$id];
|
||||||
|
$cal['editname'] = $editname;
|
||||||
|
$cal['html'] = $html;
|
||||||
|
if (!empty($prop['color']))
|
||||||
|
$cal['css'] = $this->ui->calendar_css_classes($id, $prop, $color_mode);
|
||||||
|
|
||||||
|
$results[] = $cal;
|
||||||
|
}
|
||||||
|
$this->rc->output->command('multi_thread_http_response', $results, get_input_value('_reqid', RCUBE_INPUT_GPC));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($success)
|
if ($success)
|
||||||
|
|
|
@ -39,6 +39,7 @@ function rcube_calendar_ui(settings)
|
||||||
this.selected_calendar = null;
|
this.selected_calendar = null;
|
||||||
this.search_request = null;
|
this.search_request = null;
|
||||||
this.saving_lock;
|
this.saving_lock;
|
||||||
|
this.calendars = {};
|
||||||
|
|
||||||
|
|
||||||
/*** private vars ***/
|
/*** private vars ***/
|
||||||
|
@ -52,6 +53,9 @@ function rcube_calendar_ui(settings)
|
||||||
var event_defaults = { free_busy:'busy', alarms:'' };
|
var event_defaults = { free_busy:'busy', alarms:'' };
|
||||||
var event_attendees = [];
|
var event_attendees = [];
|
||||||
var calendars_list;
|
var calendars_list;
|
||||||
|
var calenders_search_list;
|
||||||
|
var calenders_search_container;
|
||||||
|
var search_calendars = {};
|
||||||
var attendees_list;
|
var attendees_list;
|
||||||
var resources_list;
|
var resources_list;
|
||||||
var resources_treelist;
|
var resources_treelist;
|
||||||
|
@ -2667,16 +2671,79 @@ function rcube_calendar_ui(settings)
|
||||||
this.selected_calendar = id;
|
this.selected_calendar = id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// render the results for calendar list search
|
||||||
|
var calendar_search_results = function(results)
|
||||||
|
{
|
||||||
|
if (results.length) {
|
||||||
|
// create treelist widget to present the search results
|
||||||
|
if (!calenders_search_list) {
|
||||||
|
calenders_search_container = $('<div class="searchresults"></div>')
|
||||||
|
.html('<h2 class="boxtitle">' + rcmail.gettext('calsearchresults','calendar') + '</h2>')
|
||||||
|
.insertAfter(rcmail.gui_objects.calendarslist);
|
||||||
|
|
||||||
/*** startup code ***/
|
calenders_search_list = new rcube_treelist_widget('<ul class="treelist listing"></ul>', {
|
||||||
|
id_prefix: 'rcmlical',
|
||||||
|
selectable: false
|
||||||
|
});
|
||||||
|
|
||||||
// create list of event sources AKA calendars
|
// register click handler on search result's checkboxes to select the given calendar for listing
|
||||||
this.calendars = {};
|
calenders_search_list.container
|
||||||
var id, li, cal, active, color, brightness, event_sources = [];
|
.appendTo(calenders_search_container)
|
||||||
for (id in rcmail.env.calendars) {
|
.on('click', 'input[type=checkbox]', function(e){
|
||||||
cal = rcmail.env.calendars[id];
|
var li = $(this).closest('li'),
|
||||||
this.calendars[id] = $.extend({
|
id = li.attr('id').replace(/^rcmlical/, ''),
|
||||||
url: "./?_task=calendar&_action=load_events&source="+escape(id),
|
prop = search_calendars[id],
|
||||||
|
parent_id = prop.parent || null;
|
||||||
|
|
||||||
|
if (!this.checked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// find parent node and insert at the right place
|
||||||
|
if (parent_id && $('#rcmlical'+parent_id, rcmail.gui_objects.calendarslist).length) {
|
||||||
|
prop.listname = prop.editname;
|
||||||
|
li.children().first().find('.calname').html(Q(prop.listname));
|
||||||
|
}
|
||||||
|
|
||||||
|
// move this calendar to the calendars_list widget
|
||||||
|
calendars_list.insert({
|
||||||
|
id: id,
|
||||||
|
classes: [],
|
||||||
|
html: li.children().first()
|
||||||
|
}, parent_id, parent_id ? true : false);
|
||||||
|
|
||||||
|
search_calendars[id].active = true;
|
||||||
|
add_calendar_source(prop);
|
||||||
|
li.remove();
|
||||||
|
|
||||||
|
// add css classes related to this calendar to document
|
||||||
|
if (cal.css) {
|
||||||
|
$('<style type="text/css"></style>')
|
||||||
|
.html(cal.css)
|
||||||
|
.appendTo('head');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var cal, i=0; i < results.length; i++) {
|
||||||
|
cal = results[i];
|
||||||
|
search_calendars[cal.id] = cal;
|
||||||
|
$('<li>')
|
||||||
|
.attr('id', 'rcmlical' + cal.id)
|
||||||
|
.html(cal.html)
|
||||||
|
.appendTo(calenders_search_list.container);
|
||||||
|
}
|
||||||
|
|
||||||
|
calenders_search_container.show();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// register the given calendar to the current view
|
||||||
|
var add_calendar_source = function(cal)
|
||||||
|
{
|
||||||
|
var color, brightness, select, id = cal.id;
|
||||||
|
|
||||||
|
me.calendars[id] = $.extend({
|
||||||
|
url: rcmail.url('calendar/load_events', { source: id }),
|
||||||
editable: !cal.readonly,
|
editable: !cal.readonly,
|
||||||
className: 'fc-event-cal-'+id,
|
className: 'fc-event-cal-'+id,
|
||||||
id: id
|
id: id
|
||||||
|
@ -2689,18 +2756,40 @@ function rcube_calendar_ui(settings)
|
||||||
// http://javascriptrules.com/2009/08/05/css-color-brightness-contrast-using-javascript/
|
// http://javascriptrules.com/2009/08/05/css-color-brightness-contrast-using-javascript/
|
||||||
brightness = (parseInt(RegExp.$1, 16) * 299 + parseInt(RegExp.$2, 16) * 587 + parseInt(RegExp.$3, 16) * 114) / 1000;
|
brightness = (parseInt(RegExp.$1, 16) * 299 + parseInt(RegExp.$2, 16) * 587 + parseInt(RegExp.$3, 16) * 114) / 1000;
|
||||||
if (brightness > 125)
|
if (brightness > 125)
|
||||||
this.calendars[id].textColor = 'black';
|
me.calendars[id].textColor = 'black';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
me.calendars[id].color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.calendars[id].color = color;
|
if (fc && cal.active) {
|
||||||
|
fc.fullCalendar('addEventSource', me.calendars[id]);
|
||||||
if ((active = cal.active || false)) {
|
rcmail.http_post('calendar', { action:'subscribe', c:{ id:id, active:cal.active?1:0 } });
|
||||||
event_sources.push(this.calendars[id]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// insert to #calendar-select options if writeable
|
||||||
|
select = $('#edit-calendar');
|
||||||
|
if (fc && !cal.readonly && select.length && !select.find('option[value="'+id+'"]').length) {
|
||||||
|
$('<option>').attr('value', id).text(Q(cal.name)).appendTo(select);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*** startup code ***/
|
||||||
|
|
||||||
|
// create list of event sources AKA calendars
|
||||||
|
var id, cal, active, event_sources = [];
|
||||||
|
for (id in rcmail.env.calendars) {
|
||||||
|
cal = rcmail.env.calendars[id];
|
||||||
|
active = cal.active || false;
|
||||||
|
add_calendar_source(cal);
|
||||||
|
|
||||||
// check active calendars
|
// check active calendars
|
||||||
$('#rcmlical'+id+' > .calendar input').data('id', id).get(0).checked = active;
|
$('#rcmlical'+id+' > .calendar input').get(0).checked = active;
|
||||||
|
|
||||||
|
if (active) {
|
||||||
|
event_sources.push(this.calendars[id]);
|
||||||
|
}
|
||||||
|
|
||||||
if (!cal.readonly && !this.selected_calendar) {
|
if (!cal.readonly && !this.selected_calendar) {
|
||||||
this.selected_calendar = id;
|
this.selected_calendar = id;
|
||||||
|
@ -2720,12 +2809,32 @@ function rcube_calendar_ui(settings)
|
||||||
rcmail.enable_command('calendar-remove', !me.calendars[node.id].readonly);
|
rcmail.enable_command('calendar-remove', !me.calendars[node.id].readonly);
|
||||||
});
|
});
|
||||||
calendars_list.addEventListener('search', function(search){
|
calendars_list.addEventListener('search', function(search){
|
||||||
console.log(search);
|
// hide search results
|
||||||
|
if (calenders_search_list) {
|
||||||
|
calenders_search_container.hide();
|
||||||
|
calenders_search_list.reset();
|
||||||
|
}
|
||||||
|
search_calendars = {};
|
||||||
|
|
||||||
|
// send search request(s) to server
|
||||||
|
if (search.query && search.execute) {
|
||||||
|
var sources = [ 'folders' /*, 'users'*/ ];
|
||||||
|
var reqid = rcmail.multi_thread_http_request({
|
||||||
|
items: sources,
|
||||||
|
threads: rcmail.env.autocomplete_threads || 1,
|
||||||
|
action: 'calendar/calendar',
|
||||||
|
postdata: { action:'search', q:search.query, source:'%s' },
|
||||||
|
lock: rcmail.display_message(rcmail.get_label('searching'), 'loading'),
|
||||||
|
onresponse: calendar_search_results
|
||||||
|
});
|
||||||
|
|
||||||
|
listsearch_data = { id:reqid, sources:sources.slice(), num:sources.length };
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// init (delegate) event handler on calendar list checkboxes
|
// init (delegate) event handler on calendar list checkboxes
|
||||||
$(rcmail.gui_objects.calendarslist).on('click', 'input[type=checkbox]', function(e){
|
$(rcmail.gui_objects.calendarslist).on('click', 'input[type=checkbox]', function(e){
|
||||||
var id = $(this).data('id');
|
var id = this.value;
|
||||||
if (me.calendars[id]) { // add or remove event source on click
|
if (me.calendars[id]) { // add or remove event source on click
|
||||||
var action;
|
var action;
|
||||||
if (this.checked) {
|
if (this.checked) {
|
||||||
|
|
|
@ -165,6 +165,15 @@ abstract class calendar_driver
|
||||||
*/
|
*/
|
||||||
abstract function remove_calendar($prop);
|
abstract function remove_calendar($prop);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for shared or otherwise not listed calendars the user has access
|
||||||
|
*
|
||||||
|
* @param string Search string
|
||||||
|
* @param string Section/source to search
|
||||||
|
* @return array List of calendars
|
||||||
|
*/
|
||||||
|
abstract function search_calendars($query, $source);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a single event to the database
|
* Add a single event to the database
|
||||||
*
|
*
|
||||||
|
|
|
@ -247,6 +247,19 @@ class database_driver extends calendar_driver
|
||||||
return $this->rc->db->affected_rows($query);
|
return $this->rc->db->affected_rows($query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for shared or otherwise not listed calendars the user has access
|
||||||
|
*
|
||||||
|
* @param string Search string
|
||||||
|
* @param string Section/source to search
|
||||||
|
* @return array List of calendars
|
||||||
|
*/
|
||||||
|
public function search_calendars($query, $source)
|
||||||
|
{
|
||||||
|
// not implemented
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a single event to the database
|
* Add a single event to the database
|
||||||
*
|
*
|
||||||
|
|
|
@ -52,11 +52,12 @@ class kolab_calendar
|
||||||
$this->imap_folder = $this->name = $imap_folder;
|
$this->imap_folder = $this->name = $imap_folder;
|
||||||
|
|
||||||
// ID is derrived from folder name
|
// ID is derrived from folder name
|
||||||
$this->id = kolab_storage::folder_id($this->imap_folder);
|
$this->id = kolab_storage::folder_id($this->imap_folder, true);
|
||||||
|
$old_id = kolab_storage::folder_id($this->imap_folder, false);
|
||||||
|
|
||||||
// fetch objects from the given IMAP folder
|
// fetch objects from the given IMAP folder
|
||||||
$this->storage = kolab_storage::get_folder($this->imap_folder);
|
$this->storage = kolab_storage::get_folder($this->imap_folder);
|
||||||
$this->ready = $this->storage && !PEAR::isError($this->storage);
|
$this->ready = $this->storage && !PEAR::isError($this->storage) && $this->storage->type !== null;
|
||||||
|
|
||||||
// Set readonly and alarms flags according to folder permissions
|
// Set readonly and alarms flags according to folder permissions
|
||||||
if ($this->ready) {
|
if ($this->ready) {
|
||||||
|
@ -76,6 +77,8 @@ class kolab_calendar
|
||||||
$prefs = $this->cal->rc->config->get('kolab_calendars', array());
|
$prefs = $this->cal->rc->config->get('kolab_calendars', array());
|
||||||
if (isset($prefs[$this->id]['showalarms']))
|
if (isset($prefs[$this->id]['showalarms']))
|
||||||
$this->alarms = $prefs[$this->id]['showalarms'];
|
$this->alarms = $prefs[$this->id]['showalarms'];
|
||||||
|
else if (isset($prefs[$old_id]['showalarms']))
|
||||||
|
$this->alarms = $prefs[$old_id]['showalarms'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,9 @@ class kolab_driver extends calendar_driver
|
||||||
$this->alarm_types = array('DISPLAY');
|
$this->alarm_types = array('DISPLAY');
|
||||||
$this->alarm_absolute = false;
|
$this->alarm_absolute = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calendar uses fully encoded identifiers
|
||||||
|
kolab_storage::$encode_ids = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,6 +120,9 @@ class kolab_driver extends calendar_driver
|
||||||
foreach ($folders as $id => $cal) {
|
foreach ($folders as $id => $cal) {
|
||||||
$fullname = $cal->get_name();
|
$fullname = $cal->get_name();
|
||||||
$listname = kolab_storage::folder_displayname($fullname, $names);
|
$listname = kolab_storage::folder_displayname($fullname, $names);
|
||||||
|
$imap_path = explode('/', $cal->name);
|
||||||
|
$topname = array_pop($imap_path);
|
||||||
|
$parent_id = kolab_storage::folder_id(join('/', $imap_path), true);
|
||||||
|
|
||||||
// special handling for virtual folders
|
// special handling for virtual folders
|
||||||
if ($cal->virtual) {
|
if ($cal->virtual) {
|
||||||
|
@ -143,6 +149,7 @@ class kolab_driver extends calendar_driver
|
||||||
'active' => $cal->storage->is_active(),
|
'active' => $cal->storage->is_active(),
|
||||||
'owner' => $cal->get_owner(),
|
'owner' => $cal->get_owner(),
|
||||||
'children' => true, // TODO: determine if that folder indeed has child folders
|
'children' => true, // TODO: determine if that folder indeed has child folders
|
||||||
|
'parent' => $parent_id,
|
||||||
'caldavurl' => $cal->get_caldav_url(),
|
'caldavurl' => $cal->get_caldav_url(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -212,6 +219,26 @@ class kolab_driver extends calendar_driver
|
||||||
return $calendars;
|
return $calendars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the kolab_calendar instance for the given calendar ID
|
||||||
|
*
|
||||||
|
* @param string Calendar identifier (encoded imap folder name)
|
||||||
|
* @return object kolab_calendar Object nor null if calendar doesn't exist
|
||||||
|
*/
|
||||||
|
protected function get_calendar($id)
|
||||||
|
{
|
||||||
|
// create calendar object if necesary
|
||||||
|
if (!$this->calendars[$id] && $id !== self::BIRTHDAY_CALENDAR_ID) {
|
||||||
|
$foldername = kolab_storage::id_decode($id);
|
||||||
|
$calendar = new kolab_calendar($foldername, $this->cal);
|
||||||
|
if ($calendar->ready)
|
||||||
|
$this->calendars[$calendar->id] = $calendar;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->calendars[$id];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new calendar assigned to the current user
|
* Create a new calendar assigned to the current user
|
||||||
*
|
*
|
||||||
|
@ -257,7 +284,7 @@ class kolab_driver extends calendar_driver
|
||||||
*/
|
*/
|
||||||
public function edit_calendar($prop)
|
public function edit_calendar($prop)
|
||||||
{
|
{
|
||||||
if ($prop['id'] && ($cal = $this->calendars[$prop['id']])) {
|
if ($prop['id'] && ($cal = $this->get_calendar($prop['id']))) {
|
||||||
$prop['oldname'] = $cal->get_realname();
|
$prop['oldname'] = $cal->get_realname();
|
||||||
$newfolder = kolab_storage::folder_update($prop);
|
$newfolder = kolab_storage::folder_update($prop);
|
||||||
|
|
||||||
|
@ -297,9 +324,10 @@ class kolab_driver extends calendar_driver
|
||||||
*
|
*
|
||||||
* @see calendar_driver::subscribe_calendar()
|
* @see calendar_driver::subscribe_calendar()
|
||||||
*/
|
*/
|
||||||
public function subscribe_calendar($prop)
|
public function subscribe_calendar($prop, $permanent = false)
|
||||||
{
|
{
|
||||||
if ($prop['id'] && ($cal = $this->calendars[$prop['id']])) {
|
if ($prop['id'] && ($cal = $this->get_calendar($prop['id']))) {
|
||||||
|
if ($permanent) $cal->storage->subscribe($prop['active']);
|
||||||
return $cal->storage->activate($prop['active']);
|
return $cal->storage->activate($prop['active']);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -321,8 +349,9 @@ class kolab_driver extends calendar_driver
|
||||||
*/
|
*/
|
||||||
public function remove_calendar($prop)
|
public function remove_calendar($prop)
|
||||||
{
|
{
|
||||||
if ($prop['id'] && ($cal = $this->calendars[$prop['id']])) {
|
if ($prop['id'] && ($cal = $this->get_calendar($prop['id']))) {
|
||||||
$folder = $cal->get_realname();
|
$folder = $cal->get_realname();
|
||||||
|
// TODO: unsubscribe if no admin rights
|
||||||
if (kolab_storage::folder_delete($folder)) {
|
if (kolab_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', array());
|
$prefs['kolab_calendars'] = $this->rc->config->get('kolab_calendars', array());
|
||||||
|
@ -339,6 +368,51 @@ class kolab_driver extends calendar_driver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for shared or otherwise not listed calendars the user has access
|
||||||
|
*
|
||||||
|
* @param string Search string
|
||||||
|
* @param string Section/source to search
|
||||||
|
* @return array List of calendars
|
||||||
|
*/
|
||||||
|
public function search_calendars($query, $source)
|
||||||
|
{
|
||||||
|
if (!kolab_storage::setup())
|
||||||
|
return array();
|
||||||
|
|
||||||
|
$this->calendars = array();
|
||||||
|
$imap = $this->rc->get_storage();
|
||||||
|
|
||||||
|
// find unsubscribed IMAP folders that have "event" type
|
||||||
|
if ($source == 'folders') {
|
||||||
|
$folders = array();
|
||||||
|
foreach ((array)kolab_storage::list_folders('', '*', 'event', false, $folderdata) as $foldername) {
|
||||||
|
// FIXME: only consider the last part of the folder path for searching?
|
||||||
|
$realname = strtolower(rcube_charset::convert($foldername, 'UTF7-IMAP'));
|
||||||
|
if (strpos($realname, $query) !== false &&
|
||||||
|
!kolab_storage::folder_is_subscribed($foldername, true) &&
|
||||||
|
$imap->folder_namespace($foldername) != 'other'
|
||||||
|
) {
|
||||||
|
$folders[$foldername] = new kolab_storage_folder($foldername, $folderdata[$foldername]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($folders as $folder) {
|
||||||
|
$calendar = new kolab_calendar($folder->name, $this->cal);
|
||||||
|
$this->calendars[$calendar->id] = $calendar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ($source == 'users') {
|
||||||
|
// TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't list the birthday calendar
|
||||||
|
$this->rc->config->set('calendar_contact_birthdays', false);
|
||||||
|
|
||||||
|
return $this->list_calendars();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a single event
|
* Fetch a single event
|
||||||
*
|
*
|
||||||
|
@ -356,7 +430,7 @@ class kolab_driver extends calendar_driver
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($cal) {
|
if ($cal) {
|
||||||
if ($storage = $this->calendars[$cal]) {
|
if ($storage = $this->get_calendar($cal)) {
|
||||||
return $storage->get_event($id);
|
return $storage->get_event($id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,7 +457,7 @@ class kolab_driver extends calendar_driver
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
$cid = $event['calendar'] ? $event['calendar'] : reset(array_keys($this->calendars));
|
$cid = $event['calendar'] ? $event['calendar'] : reset(array_keys($this->calendars));
|
||||||
if ($storage = $this->calendars[$cid]) {
|
if ($storage = $this->get_calendar($cid)) {
|
||||||
// handle attachments to add
|
// handle attachments to add
|
||||||
if (!empty($event['attachments'])) {
|
if (!empty($event['attachments'])) {
|
||||||
foreach ($event['attachments'] as $idx => $attachment) {
|
foreach ($event['attachments'] as $idx => $attachment) {
|
||||||
|
@ -425,7 +499,7 @@ class kolab_driver extends calendar_driver
|
||||||
*/
|
*/
|
||||||
public function move_event($event)
|
public function move_event($event)
|
||||||
{
|
{
|
||||||
if (($storage = $this->calendars[$event['calendar']]) && ($ev = $storage->get_event($event['id']))) {
|
if (($storage = $this->get_calendar($event['calendar'])) && ($ev = $storage->get_event($event['id']))) {
|
||||||
unset($ev['sequence']);
|
unset($ev['sequence']);
|
||||||
return $this->update_event($event + $ev);
|
return $this->update_event($event + $ev);
|
||||||
}
|
}
|
||||||
|
@ -441,7 +515,7 @@ class kolab_driver extends calendar_driver
|
||||||
*/
|
*/
|
||||||
public function resize_event($event)
|
public function resize_event($event)
|
||||||
{
|
{
|
||||||
if (($storage = $this->calendars[$event['calendar']]) && ($ev = $storage->get_event($event['id']))) {
|
if (($storage = $this->get_calendar($event['calendar'])) && ($ev = $storage->get_event($event['id']))) {
|
||||||
unset($ev['sequence']);
|
unset($ev['sequence']);
|
||||||
return $this->update_event($event + $ev);
|
return $this->update_event($event + $ev);
|
||||||
}
|
}
|
||||||
|
@ -463,7 +537,7 @@ class kolab_driver extends calendar_driver
|
||||||
$success = false;
|
$success = false;
|
||||||
$savemode = $event['_savemode'];
|
$savemode = $event['_savemode'];
|
||||||
|
|
||||||
if (($storage = $this->calendars[$event['calendar']]) && ($event = $storage->get_event($event['id']))) {
|
if (($storage = $this->get_calendar($event['calendar'])) && ($event = $storage->get_event($event['id']))) {
|
||||||
$event['_savemode'] = $savemode;
|
$event['_savemode'] = $savemode;
|
||||||
$savemode = 'all';
|
$savemode = 'all';
|
||||||
$master = $event;
|
$master = $event;
|
||||||
|
@ -566,7 +640,7 @@ class kolab_driver extends calendar_driver
|
||||||
*/
|
*/
|
||||||
public function restore_event($event)
|
public function restore_event($event)
|
||||||
{
|
{
|
||||||
if ($storage = $this->calendars[$event['calendar']]) {
|
if ($storage = $this->get_calendar($event['calendar'])) {
|
||||||
if (!empty($_SESSION['calendar_restore_event_data']))
|
if (!empty($_SESSION['calendar_restore_event_data']))
|
||||||
$success = $storage->update_event($_SESSION['calendar_restore_event_data']);
|
$success = $storage->update_event($_SESSION['calendar_restore_event_data']);
|
||||||
else
|
else
|
||||||
|
@ -586,12 +660,12 @@ class kolab_driver extends calendar_driver
|
||||||
*/
|
*/
|
||||||
private function update_event($event)
|
private function update_event($event)
|
||||||
{
|
{
|
||||||
if (!($storage = $this->calendars[$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 ($event['_fromcalendar'] && $event['_fromcalendar'] != $event['calendar']) {
|
if ($event['_fromcalendar'] && $event['_fromcalendar'] != $event['calendar']) {
|
||||||
if (!($fromcalendar = $this->calendars[$event['_fromcalendar']]))
|
if (!($fromcalendar = $this->get_calendar($event['_fromcalendar'])))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ($event['_savemode'] != 'new') {
|
if ($event['_savemode'] != 'new') {
|
||||||
|
@ -780,18 +854,19 @@ class kolab_driver extends calendar_driver
|
||||||
{
|
{
|
||||||
if ($calendars && is_string($calendars))
|
if ($calendars && is_string($calendars))
|
||||||
$calendars = explode(',', $calendars);
|
$calendars = explode(',', $calendars);
|
||||||
|
else if (!$calendars)
|
||||||
|
$calendars = array_keys($this->calendars);
|
||||||
|
|
||||||
$query = array();
|
$query = array();
|
||||||
if ($modifiedsince)
|
if ($modifiedsince)
|
||||||
$query[] = array('changed', '>=', $modifiedsince);
|
$query[] = array('changed', '>=', $modifiedsince);
|
||||||
|
|
||||||
$events = $categories = array();
|
$events = $categories = array();
|
||||||
foreach (array_keys($this->calendars) as $cid) {
|
foreach ($calendars as $cid) {
|
||||||
if ($calendars && !in_array($cid, $calendars))
|
if ($storage = $this->get_calendar($cid)) {
|
||||||
continue;
|
$events = array_merge($events, $storage->list_events($start, $end, $search, $virtual, $query));
|
||||||
|
$categories += $storage->categories;
|
||||||
$events = array_merge($events, $this->calendars[$cid]->list_events($start, $end, $search, $virtual, $query));
|
}
|
||||||
$categories += $this->calendars[$cid]->categories;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add events from the address books birthday calendar
|
// add events from the address books birthday calendar
|
||||||
|
@ -928,7 +1003,7 @@ class kolab_driver extends calendar_driver
|
||||||
*/
|
*/
|
||||||
public function list_attachments($event)
|
public function list_attachments($event)
|
||||||
{
|
{
|
||||||
if (!($storage = $this->calendars[$event['calendar']]))
|
if (!($storage = $this->get_calendar($event['calendar'])))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
$event = $storage->get_event($event['id']);
|
$event = $storage->get_event($event['id']);
|
||||||
|
@ -941,7 +1016,7 @@ class kolab_driver extends calendar_driver
|
||||||
*/
|
*/
|
||||||
public function get_attachment($id, $event)
|
public function get_attachment($id, $event)
|
||||||
{
|
{
|
||||||
if (!($storage = $this->calendars[$event['calendar']]))
|
if (!($storage = $this->get_calendar($event['calendar'])))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
$event = $storage->get_event($event['id']);
|
$event = $storage->get_event($event['id']);
|
||||||
|
@ -963,7 +1038,7 @@ class kolab_driver extends calendar_driver
|
||||||
*/
|
*/
|
||||||
public function get_attachment_body($id, $event)
|
public function get_attachment_body($id, $event)
|
||||||
{
|
{
|
||||||
if (!($cal = $this->calendars[$event['calendar']]))
|
if (!($cal = $this->get_calendar($event['calendar'])))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return $cal->storage->get_attachment($event['id'], $id);
|
return $cal->storage->get_attachment($event['id'], $id);
|
||||||
|
@ -1080,7 +1155,7 @@ class kolab_driver extends calendar_driver
|
||||||
ignore_user_abort(true);
|
ignore_user_abort(true);
|
||||||
|
|
||||||
$cal = get_input_value('source', RCUBE_INPUT_GPC);
|
$cal = get_input_value('source', RCUBE_INPUT_GPC);
|
||||||
if (!($cal = $this->calendars[$cal]))
|
if (!($cal = $this->get_calendar($cal)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// trigger updates on folder
|
// trigger updates on folder
|
||||||
|
@ -1275,7 +1350,7 @@ class kolab_driver extends calendar_driver
|
||||||
public function calendar_acl_form()
|
public function calendar_acl_form()
|
||||||
{
|
{
|
||||||
$calid = get_input_value('_id', RCUBE_INPUT_GPC);
|
$calid = get_input_value('_id', RCUBE_INPUT_GPC);
|
||||||
if ($calid && ($cal = $this->calendars[$calid])) {
|
if ($calid && ($cal = $this->get_calendar($calid))) {
|
||||||
$folder = $cal->get_realname(); // UTF7
|
$folder = $cal->get_realname(); // UTF7
|
||||||
$color = $cal->get_color();
|
$color = $cal->get_color();
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,31 +157,41 @@ class calendar_ui
|
||||||
foreach ((array)$calendars as $id => $prop) {
|
foreach ((array)$calendars as $id => $prop) {
|
||||||
if (!$prop['color'])
|
if (!$prop['color'])
|
||||||
continue;
|
continue;
|
||||||
$color = $prop['color'];
|
$css .= $this->calendar_css_classes($id, $prop, $mode);
|
||||||
$class = 'cal-' . asciiwords($id, true);
|
|
||||||
$css .= "li.$class, #eventshow .$class { color: #$color }\n";
|
|
||||||
if ($mode != 1) {
|
|
||||||
if ($mode == 3) {
|
|
||||||
$css .= ".fc-event-$class .fc-event-bg {";
|
|
||||||
$css .= " opacity: 0.9;";
|
|
||||||
$css .= " filter: alpha(opacity=90);";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$css .= ".fc-event-$class, ";
|
|
||||||
$css .= ".fc-event-$class .fc-event-inner {";
|
|
||||||
}
|
|
||||||
if (!$attrib['printmode'])
|
|
||||||
$css .= " background-color: #$color;";
|
|
||||||
if ($mode % 2 == 0)
|
|
||||||
$css .= " border-color: #$color;";
|
|
||||||
$css .= "}\n";
|
|
||||||
}
|
|
||||||
$css .= ".$class .handle { background-color: #$color; }";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return html::tag('style', array('type' => 'text/css'), $css);
|
return html::tag('style', array('type' => 'text/css'), $css);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function calendar_css_classes($id, $prop, $mode)
|
||||||
|
{
|
||||||
|
$color = $prop['color'];
|
||||||
|
$class = 'cal-' . asciiwords($id, true);
|
||||||
|
$css .= "li.$class, #eventshow .$class { color: #$color }\n";
|
||||||
|
|
||||||
|
if ($mode != 1) {
|
||||||
|
if ($mode == 3) {
|
||||||
|
$css .= ".fc-event-$class .fc-event-bg {";
|
||||||
|
$css .= " opacity: 0.9;";
|
||||||
|
$css .= " filter: alpha(opacity=90);";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$css .= ".fc-event-$class, ";
|
||||||
|
$css .= ".fc-event-$class .fc-event-inner {";
|
||||||
|
}
|
||||||
|
if (!$attrib['printmode'])
|
||||||
|
$css .= " background-color: #$color;";
|
||||||
|
if ($mode % 2 == 0)
|
||||||
|
$css .= " border-color: #$color;";
|
||||||
|
$css .= "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $css . ".$class .handle { background-color: #$color; }\n";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -224,7 +234,7 @@ class calendar_ui
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return html for a structured list <ul> for the mailbox tree
|
* Return html for a structured list <ul> for the folder tree
|
||||||
*/
|
*/
|
||||||
public function list_tree_html(&$node, &$data, &$jsenv, $attrib)
|
public function list_tree_html(&$node, &$data, &$jsenv, $attrib)
|
||||||
{
|
{
|
||||||
|
@ -255,7 +265,7 @@ class calendar_ui
|
||||||
/**
|
/**
|
||||||
* Helper method to build a calendar list item (HTML content and js data)
|
* Helper method to build a calendar list item (HTML content and js data)
|
||||||
*/
|
*/
|
||||||
protected function calendar_list_item($id, $prop, &$jsenv)
|
public function calendar_list_item($id, $prop, &$jsenv)
|
||||||
{
|
{
|
||||||
unset($prop['user_id']);
|
unset($prop['user_id']);
|
||||||
$prop['alarms'] = $this->cal->driver->alarms;
|
$prop['alarms'] = $this->cal->driver->alarms;
|
||||||
|
@ -283,7 +293,7 @@ class calendar_ui
|
||||||
if (!$attrib['activeonly'] || $prop['active']) {
|
if (!$attrib['activeonly'] || $prop['active']) {
|
||||||
$content = html::div($class,
|
$content = html::div($class,
|
||||||
($prop['virtual'] ? '' : html::tag('input', array('type' => 'checkbox', 'name' => '_cal[]', 'value' => $id, 'checked' => $prop['active']), '') .
|
($prop['virtual'] ? '' : html::tag('input', array('type' => 'checkbox', 'name' => '_cal[]', 'value' => $id, 'checked' => $prop['active']), '') .
|
||||||
html::span('handle', ' ')) .
|
html::span(array('class' => 'handle', 'style' => "background-color: #" . ($prop['color'] ?: 'f00')), ' ')) .
|
||||||
html::span(array('class' => 'calname', 'title' => $title), $prop['editname'] ? Q($prop['editname']) : $prop['listname'])
|
html::span(array('class' => 'calname', 'title' => $title), $prop['editname'] ? Q($prop['editname']) : $prop['listname'])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@ $labels['nmonthsback'] = '$nr months back';
|
||||||
$labels['showurl'] = 'Show calendar URL';
|
$labels['showurl'] = 'Show calendar URL';
|
||||||
$labels['showurldescription'] = 'Use the following address to access (read only) your calendar from other applications. You can copy and paste this into any calendar software that supports the iCal format.';
|
$labels['showurldescription'] = 'Use the following address to access (read only) your calendar from other applications. You can copy and paste this into any calendar software that supports the iCal format.';
|
||||||
$labels['caldavurldescription'] = 'Copy this address to a <a href="http://en.wikipedia.org/wiki/CalDAV" target="_blank">CalDAV</a> client application (e.g. Evolution or Mozilla Thunderbird) to fully synchronize this specific calendar with your computer or mobile device.';
|
$labels['caldavurldescription'] = 'Copy this address to a <a href="http://en.wikipedia.org/wiki/CalDAV" target="_blank">CalDAV</a> client application (e.g. Evolution or Mozilla Thunderbird) to fully synchronize this specific calendar with your computer or mobile device.';
|
||||||
|
$labels['calsearchresults'] = 'Additional Results';
|
||||||
|
|
||||||
// agenda view
|
// agenda view
|
||||||
$labels['listrange'] = 'Range to display:';
|
$labels['listrange'] = 'Range to display:';
|
||||||
|
|
|
@ -168,27 +168,23 @@ pre {
|
||||||
top: 68px;
|
top: 68px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist li {
|
#calendars .treelist li {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist li label {
|
#calendars .treelist li div.folder,
|
||||||
display: block;
|
#calendars .treelist li div.calendar {
|
||||||
}
|
|
||||||
|
|
||||||
#calendarslist li div.folder,
|
|
||||||
#calendarslist li div.calendar {
|
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist li div.virtual {
|
#calendars .treelist li div.virtual {
|
||||||
height: 22px;
|
height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#calendarslist li span.calname {
|
#calendars .treelist li span.calname {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 0px 30px 2px 2px;
|
padding: 0px 30px 2px 2px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -203,17 +199,17 @@ pre {
|
||||||
color: #004458;
|
color: #004458;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist li div.virtual > span.calname {
|
#calendars .treelist li div.virtual > span.calname {
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
top: 4px;
|
top: 4px;
|
||||||
left: 20px;
|
left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist.flat li span.calname {
|
#calendars .treelist.flat li span.calname {
|
||||||
left: 24px;
|
left: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist li span.handle {
|
#calendars .treelist li span.handle {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 8px;
|
top: 8px;
|
||||||
|
@ -229,66 +225,77 @@ pre {
|
||||||
box-shadow: inset 0px 0 1px 1px rgba(0, 0, 0, 0.3);
|
box-shadow: inset 0px 0 1px 1px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist li input {
|
#calendars .treelist li input {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 5px;
|
top: 5px;
|
||||||
left: 18px;
|
left: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist li div.treetoggle {
|
#calendars .treelist li div.treetoggle {
|
||||||
top: 8px;
|
top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist li.virtual div.treetoggle {
|
#calendars .treelist li.virtual div.treetoggle {
|
||||||
top: 6px;
|
top: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist.flat li input {
|
#calendars .treelist.flat li input {
|
||||||
left: 4px;
|
left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist ul li div.folder,
|
#calendars .treelist ul li div.folder,
|
||||||
#calendarslist ul li div.calendar {
|
#calendars .treelist ul li div.calendar {
|
||||||
margin-left: 16px;
|
margin-left: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist ul ul li div.folder,
|
#calendars .treelist ul ul li div.folder,
|
||||||
#calendarslist ul ul li div.calendar {
|
#calendars .treelist ul ul li div.calendar {
|
||||||
margin-left: 32px;
|
margin-left: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist ul ul ul li div.folder,
|
#calendars .treelist ul ul ul li div.folder,
|
||||||
#calendarslist ul ul ul li div.calendar {
|
#calendars .treelist ul ul ul li div.calendar {
|
||||||
margin-left: 48px;
|
margin-left: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist li.selected {
|
#calendars .treelist li.selected {
|
||||||
background-color: #c7e3ef;
|
background-color: #c7e3ef;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist li.selected > span.calname {
|
#calendars .treelist li.selected > span.calname {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist div.readonly span.calname {
|
#calendars .treelist div.readonly span.calname {
|
||||||
background-position: right -20px;
|
background-position: right -20px;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
#calendarslist div.other span.calname {
|
#calendars .treelist div.other span.calname {
|
||||||
background-position: right -38px;
|
background-position: right -38px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist div.other.readonly span.calname {
|
#calendars .treelist div.other.readonly span.calname {
|
||||||
background-position: right -56px;
|
background-position: right -56px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist div.shared span.calname {
|
#calendars .treelist div.shared span.calname {
|
||||||
background-position: right -74px;
|
background-position: right -74px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendarslist div.shared.readonly span.calname {
|
#calendars .treelist div.shared.readonly span.calname {
|
||||||
background-position: right -92px;
|
background-position: right -92px;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#calendars .searchresults {
|
||||||
|
background: #b0ccd7;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calendars .searchresults .boxtitle {
|
||||||
|
background: none;
|
||||||
|
padding: 2px 8px 2px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
#calfeedurl,
|
#calfeedurl,
|
||||||
#caldavurl {
|
#caldavurl {
|
||||||
|
|
|
@ -247,7 +247,7 @@ class kolab_addressbook extends rcube_plugin
|
||||||
$names = array();
|
$names = array();
|
||||||
foreach ($folders as $folder) {
|
foreach ($folders as $folder) {
|
||||||
// create instance of rcube_contacts
|
// create instance of rcube_contacts
|
||||||
$abook_id = kolab_storage::folder_id($folder->name);
|
$abook_id = kolab_storage::folder_id($folder->name, false);
|
||||||
$abook = new rcube_kolab_contacts($folder->name);
|
$abook = new rcube_kolab_contacts($folder->name);
|
||||||
$this->sources[$abook_id] = $abook;
|
$this->sources[$abook_id] = $abook;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* @author Thomas Bruederli <bruederli@kolabsys.com>
|
* @author Thomas Bruederli <bruederli@kolabsys.com>
|
||||||
* @author Aleksander Machniak <machniak@kolabsys.com>
|
* @author Aleksander Machniak <machniak@kolabsys.com>
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012, Kolab Systems AG <contact@kolabsys.com>
|
* Copyright (C) 2012-2014, Kolab Systems AG <contact@kolabsys.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
@ -37,6 +37,7 @@ class kolab_storage
|
||||||
|
|
||||||
public static $version = '3.0';
|
public static $version = '3.0';
|
||||||
public static $last_error;
|
public static $last_error;
|
||||||
|
public static $encode_ids = false;
|
||||||
|
|
||||||
private static $ready = false;
|
private static $ready = false;
|
||||||
private static $subscriptions;
|
private static $subscriptions;
|
||||||
|
@ -226,13 +227,39 @@ class kolab_storage
|
||||||
/**
|
/**
|
||||||
* Creates folder ID from folder name
|
* Creates folder ID from folder name
|
||||||
*
|
*
|
||||||
* @param string $folder Folder name (UTF7-IMAP)
|
* @param string $folder Folder name (UTF7-IMAP)
|
||||||
*
|
* @param boolean $enc Use lossless encoding
|
||||||
* @return string Folder ID string
|
* @return string Folder ID string
|
||||||
*/
|
*/
|
||||||
public static function folder_id($folder)
|
public static function folder_id($folder, $enc = null)
|
||||||
{
|
{
|
||||||
return asciiwords(strtr($folder, '/.-', '___'));
|
return $enc == true || ($enc === null && self::$encode_ids) ?
|
||||||
|
self::id_encode($folder) :
|
||||||
|
asciiwords(strtr($folder, '/.-', '___'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode the given ID to a safe ascii representation
|
||||||
|
*
|
||||||
|
* @param string $id Arbitrary identifier string
|
||||||
|
*
|
||||||
|
* @return string Ascii representation
|
||||||
|
*/
|
||||||
|
public static function id_encode($id)
|
||||||
|
{
|
||||||
|
return rtrim(strtr(base64_encode($id), '+/', '-_'), '=');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given identifier back to it's raw value
|
||||||
|
*
|
||||||
|
* @param string $id Ascii identifier
|
||||||
|
* @return string Raw identifier string
|
||||||
|
*/
|
||||||
|
public static function id_decode($id)
|
||||||
|
{
|
||||||
|
return base64_decode(str_pad(strtr($id, '-_', '+/'), strlen($id) % 4, '=', STR_PAD_RIGHT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -665,11 +692,16 @@ class kolab_storage
|
||||||
if (!$filter) {
|
if (!$filter) {
|
||||||
// Get ALL folders list, standard way
|
// Get ALL folders list, standard way
|
||||||
if ($subscribed) {
|
if ($subscribed) {
|
||||||
return self::$imap->list_folders_subscribed($root, $mbox);
|
$folders = self::$imap->list_folders_subscribed($root, $mbox);
|
||||||
|
// add temporarily subscribed folders
|
||||||
|
if (is_array($_SESSION['kolab_subscribed_folders']))
|
||||||
|
$folders = array_unique(array_merge($folders, $_SESSION['kolab_subscribed_folders']));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return self::$imap->list_folders($root, $mbox);
|
$folders = self::$imap->list_folders($root, $mbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
$prefix = $root . $mbox;
|
$prefix = $root . $mbox;
|
||||||
|
@ -696,6 +728,10 @@ class kolab_storage
|
||||||
// Get folders list
|
// Get folders list
|
||||||
if ($subscribed) {
|
if ($subscribed) {
|
||||||
$folders = self::$imap->list_folders_subscribed($root, $mbox);
|
$folders = self::$imap->list_folders_subscribed($root, $mbox);
|
||||||
|
|
||||||
|
// add temporarily subscribed folders
|
||||||
|
if (is_array($_SESSION['kolab_subscribed_folders']))
|
||||||
|
$folders = array_unique(array_merge($folders, $_SESSION['kolab_subscribed_folders']));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$folders = self::$imap->list_folders($root, $mbox);
|
$folders = self::$imap->list_folders($root, $mbox);
|
||||||
|
@ -903,17 +939,19 @@ class kolab_storage
|
||||||
* Check subscription status of this folder
|
* Check subscription status of this folder
|
||||||
*
|
*
|
||||||
* @param string $folder Folder name
|
* @param string $folder Folder name
|
||||||
|
* @param boolean $temp Include temporary/session subscriptions
|
||||||
*
|
*
|
||||||
* @return boolean True if subscribed, false if not
|
* @return boolean True if subscribed, false if not
|
||||||
*/
|
*/
|
||||||
public static function folder_is_subscribed($folder)
|
public static function folder_is_subscribed($folder, $temp = false)
|
||||||
{
|
{
|
||||||
if (self::$subscriptions === null) {
|
if (self::$subscriptions === null) {
|
||||||
self::setup();
|
self::setup();
|
||||||
self::$subscriptions = self::$imap->list_folders_subscribed();
|
self::$subscriptions = self::$imap->list_folders_subscribed();
|
||||||
}
|
}
|
||||||
|
|
||||||
return in_array($folder, self::$subscriptions);
|
return in_array($folder, self::$subscriptions) ||
|
||||||
|
($temp && in_array($folder, (array)$_SESSION['kolab_subscribed_folders']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -921,14 +959,25 @@ class kolab_storage
|
||||||
* Change subscription status of this folder
|
* Change subscription status of this folder
|
||||||
*
|
*
|
||||||
* @param string $folder Folder name
|
* @param string $folder Folder name
|
||||||
|
* @param boolean $temp Only subscribe temporarily for the current session
|
||||||
*
|
*
|
||||||
* @return True on success, false on error
|
* @return True on success, false on error
|
||||||
*/
|
*/
|
||||||
public static function folder_subscribe($folder)
|
public static function folder_subscribe($folder, $temp = false)
|
||||||
{
|
{
|
||||||
self::setup();
|
self::setup();
|
||||||
|
|
||||||
if (self::$imap->subscribe($folder)) {
|
// temporary/session subscription
|
||||||
|
if ($temp) {
|
||||||
|
if (self::folder_is_subscribed($folder)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (!is_array($_SESSION['kolab_subscribed_folders']) || !in_array($folder, $_SESSION['kolab_subscribed_folders'])) {
|
||||||
|
$_SESSION['kolab_subscribed_folders'][] = $folder;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (self::$imap->subscribe($folder)) {
|
||||||
self::$subscriptions === null;
|
self::$subscriptions === null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -981,6 +1030,8 @@ class kolab_storage
|
||||||
*/
|
*/
|
||||||
public static function folder_activate($folder)
|
public static function folder_activate($folder)
|
||||||
{
|
{
|
||||||
|
// activation implies temporary subscription
|
||||||
|
self::folder_subscribe($folder, true);
|
||||||
return self::set_state($folder, true);
|
return self::set_state($folder, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -994,6 +1045,11 @@ class kolab_storage
|
||||||
*/
|
*/
|
||||||
public static function folder_deactivate($folder)
|
public static function folder_deactivate($folder)
|
||||||
{
|
{
|
||||||
|
// remove from temp subscriptions
|
||||||
|
if (is_array($_SESSION['kolab_subscribed_folders']) && ($i = array_search($folder, $_SESSION['kolab_subscribed_folders'])) !== false) {
|
||||||
|
unset($_SESSION['kolab_subscribed_folders'][$i]);
|
||||||
|
}
|
||||||
|
|
||||||
return self::set_state($folder, false);
|
return self::set_state($folder, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue