diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php index 822098ea..5c96d82c 100644 --- a/plugins/calendar/calendar.php +++ b/plugins/calendar/calendar.php @@ -466,21 +466,14 @@ class calendar extends rcube_plugin case "new": // create UID for new event $event['uid'] = $this->generate_uid(); - - // set current user as organizer - if (FALSE && !$event['attendees']) { - $identity = $this->rc->user->get_identity(); - $event['attendees'][] = array('role' => 'ORGANIZER', 'name' => $identity['name'], 'email' => $identity['email']); - } - - $this->prepare_event($event); + $this->prepare_event($event, $action); if ($success = $this->driver->new_event($event)) $this->cleanup_event($event); $reload = true; break; case "edit": - $this->prepare_event($event); + $this->prepare_event($event, $action); if ($success = $this->driver->edit_event($event)) $this->cleanup_event($event); $reload = true; @@ -601,7 +594,7 @@ class calendar extends rcube_plugin $end = get_input_value('end', RCUBE_INPUT_GET); if (!$start) $start = mktime(0, 0, 0, 1, date('n'), date('Y')-1); if (!$end) $end = mktime(0, 0, 0, 31, 12, date('Y')+10); - $calendar_name = get_input_value('source', RCUBE_INPUT_GET); + $calendar_name = get_input_value('source', RCUBE_INPUT_GET); $events = $this->driver->load_events($start, $end, null, $calendar_name, 0); header("Content-Type: text/calendar"); @@ -668,8 +661,10 @@ class calendar extends rcube_plugin $settings['hidden_calendars'] = array_filter(explode(',', $this->rc->config->get('hidden_calendars', ''))); // get user identity to create default attendee - $identity = $this->rc->user->get_identity(); - $settings['event_owner'] = array('name' => $identity['name'], 'email' => $identity['email']); + if ($this->ui->screen == 'calendar') { + $identity = $this->rc->user->get_identity(); + $settings['event_owner'] = array('name' => $identity['name'], 'email' => $identity['email']); + } return $settings; } @@ -1149,7 +1144,7 @@ class calendar extends rcube_plugin /** * Prepares new/edited event properties before save */ - private function prepare_event(&$event) + private function prepare_event(&$event, $action) { $eventid = $event['calendar'].':'.$event['id']; @@ -1181,8 +1176,8 @@ class calendar extends rcube_plugin if (!$organizer && $owner !== false) { $event['attendees'][$i]['role'] = 'ORGANIZER'; } - else if (!$organizer && $identity['email']) { - $event['attendees'][] = array('role' => 'ORGANIZER', 'name' => $identity['name'], 'email' => $identity['email'], 'status' => 'ACCEPTED'); + else if (!$organizer && $identity['email'] && $action == 'new') { + array_unshift($event['attendees'], array('role' => 'ORGANIZER', 'name' => $identity['name'], 'email' => $identity['email'], 'status' => 'ACCEPTED')); } } } diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js index 64270cdd..e91b420e 100644 --- a/plugins/calendar/calendar_ui.js +++ b/plugins/calendar/calendar_ui.js @@ -448,6 +448,7 @@ function rcube_calendar_ui(settings) for (var j=0; j < event.attendees.length; j++) add_attendee(event.attendees[j], true); } + $('#edit-attendee-schedule')[(calendar.freebusy?'show':'hide')](); // attachments if (calendar.attachments) { @@ -626,8 +627,8 @@ function rcube_calendar_ui(settings) freebusy_ui.endtime = $('#schedule-endtime').val($.fullCalendar.formatDate(event.end, settings['time_format'])).show(); if (allday.checked) { - starttime.val("00:00").hide(); - endtime.val("23:59").hide(); + freebusy_ui.starttime.val("00:00").hide(); + freebusy_ui.endtime.val("23:59").hide(); event.allDay = true; } @@ -826,12 +827,21 @@ function rcube_calendar_ui(settings) var range_t = freebusy_ui.end.getTime() - freebusy_ui.start.getTime(); var newstart = new Date(freebusy_ui.start.getTime() + px * (range_t / range_p)); newstart.setSeconds(0); newstart.setMilliseconds(0); - // round to 5 minutes - var round = newstart.getMinutes() % 5; - if (round > 2.5) newstart.setTime(newstart.getTime() + (5 - round) * 60000); - else if (round > 0) newstart.setTime(newstart.getTime() - round * 60000); - // update event times + // set time to 00:00 + if (me.selected_event.allDay) { + newstart.setMinutes(0); + newstart.setHours(0); + } + else { + // round to 5 minutes + var round = newstart.getMinutes() % 5; + if (round > 2.5) newstart.setTime(newstart.getTime() + (5 - round) * 60000); + else if (round > 0) newstart.setTime(newstart.getTime() - round * 60000); + } + // update event times and display update_freebusy_dates(newstart, new Date(newstart.getTime() + freebusy_ui.startdate.data('duration') * 1000)); + if (me.selected_event.allDay) + render_freebusy_overlay(); } }).data('isdraggable', true); } @@ -1131,6 +1141,12 @@ function rcube_calendar_ui(settings) // load free-busy status from server and update icon accordingly var check_freebusy_status = function(icon, email, event) { + var calendar = event.calendar && me.calendars[event.calendar] ? me.calendars[event.calendar] : { freebusy:false }; + if (!calendar.freebusy) { + $(icon).removeClass().addClass('availabilityicon unknown'); + return; + } + icon = $(icon).removeClass().addClass('availabilityicon loading'); $.ajax({ diff --git a/plugins/calendar/drivers/calendar_driver.php b/plugins/calendar/drivers/calendar_driver.php index c9ac0c8b..29c202ef 100644 --- a/plugins/calendar/drivers/calendar_driver.php +++ b/plugins/calendar/drivers/calendar_driver.php @@ -75,6 +75,7 @@ abstract class calendar_driver // features supported by backend public $alarms = false; public $attendees = false; + public $freebusy = false; public $attachments = false; public $undelete = false; // event undelete action public $categoriesimmutable = false; @@ -296,7 +297,6 @@ abstract class calendar_driver */ public function get_freebusy_list($email, $start, $end) { - sleep(2); return false; } diff --git a/plugins/calendar/drivers/database/database_driver.php b/plugins/calendar/drivers/database/database_driver.php index 438f270b..6f5e25a6 100644 --- a/plugins/calendar/drivers/database/database_driver.php +++ b/plugins/calendar/drivers/database/database_driver.php @@ -28,6 +28,7 @@ class database_driver extends calendar_driver // features this backend supports public $alarms = true; public $attendees = true; + public $freebusy = false; public $attachments = true; public $alarm_types = array('DISPLAY','EMAIL'); @@ -185,7 +186,7 @@ class database_driver extends calendar_driver $event = $this->_save_preprocess($event); $query = $this->rc->db->query(sprintf( "INSERT INTO " . $this->db_events . " - (calendar_id, created, changed, uid, start, end, all_day, recurrence, title, description, location, categories, free_busy, priority, sensitivity, alarms, notifyat) + (calendar_id, created, changed, uid, start, end, all_day, recurrence, title, description, location, categories, free_busy, priority, sensitivity, attendees, alarms, notifyat) VALUES (?, %s, %s, ?, %s, %s, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $this->rc->db->now(), $this->rc->db->now(), @@ -203,6 +204,7 @@ class database_driver extends calendar_driver intval($event['free_busy']), intval($event['priority']), intval($event['sensitivity']), + $event['attendees'], $event['alarms'], $event['notifyat'] ); @@ -342,6 +344,17 @@ class database_driver extends calendar_driver // compute absolute time to notify the user $event['notifyat'] = $this->_get_notification($event); + // process event attendees + $_attendees = ''; + foreach ((array)$event['attendees'] as $attendee) { + $_attendees .= 'NAME="'.addcslashes($attendee['name'], '"') . '"' . + ';STATUS=' . $attendee['status']. + ';ROLE=' . $attendee['role'] . + ';EMAIL=' . $attendee['email'] . + "\n"; + } + $event['attendees'] = rtrim($_attendees); + return $event; } @@ -387,9 +400,9 @@ class database_driver extends calendar_driver private function _update_event($event, $update_recurring = true) { $event = $this->_save_preprocess($event); - + console($event); $sql_set = array(); - $set_cols = array('all_day', 'recurrence', 'recurrence_id', 'title', 'description', 'location', 'categories', 'free_busy', 'priority', 'sensitivity', 'alarms', 'notifyat'); + $set_cols = array('all_day', 'recurrence', 'recurrence_id', 'title', 'description', 'location', 'categories', 'free_busy', 'priority', 'sensitivity', 'attendees', 'alarms', 'notifyat'); foreach ($set_cols as $col) { if (isset($event[$col])) $sql_set[] = $this->rc->db->quote_identifier($col) . '=' . $this->rc->db->quote($event[$col]); @@ -693,6 +706,20 @@ class database_driver extends calendar_driver if ($event['_attachments'] > 0) $event['attachments'] = (array)$this->list_attachments($event); + // decode serialized event attendees + if ($event['attendees']) { + $attendees = array(); + foreach (explode("\n", $event['attendees']) as $line) { + $att = array(); + foreach (rcube_explode_quoted_string(';', $line) as $prop) { + list($key, $value) = explode("=", $prop); + $att[strtolower($key)] = stripslashes(trim($value, '""')); + } + $attendees[] = $att; + } + $event['attendees'] = $attendees; + } + unset($event['event_id'], $event['calendar_id'], $event['notifyat'], $event['_attachments']); return $event; } diff --git a/plugins/calendar/lib/calendar_ui.php b/plugins/calendar/lib/calendar_ui.php index 9cd9e242..71aeb97d 100644 --- a/plugins/calendar/lib/calendar_ui.php +++ b/plugins/calendar/lib/calendar_ui.php @@ -26,11 +26,13 @@ class calendar_ui { private $rc; private $calendar; + public $screen; function __construct($calendar) { $this->calendar = $calendar; $this->rc = $calendar->rc; + $this->screen = $this->rc->task == 'calendar' ? ($this->rc->action ? $this->rc->action: 'calendar') : 'other'; } /** @@ -129,6 +131,7 @@ class calendar_ui unset($prop['user_id']); $prop['alarms'] = $this->calendar->driver->alarms; $prop['attendees'] = $this->calendar->driver->attendees; + $prop['freebusy'] = $this->calendar->driver->freebusy; $prop['attachments'] = $this->calendar->driver->attachments; $jsenv[$id] = $prop;