Merge branch 'master' of ssh://git.kolabsys.com/git/roundcube

This commit is contained in:
Thomas 2011-07-19 17:50:34 +02:00
commit 01cf039bcc
6 changed files with 95 additions and 38 deletions

View file

@ -91,11 +91,13 @@ class calendar extends rcube_plugin
}
if ($this->rc->task == 'calendar' && $this->rc->action != 'save-pref') {
if ($this->rc->action != 'upload') {
$this->load_driver();
// load iCalendar functions
require($this->home . '/lib/calendar_ical.php');
$this->ical = new calendar_ical($this->rc, $this->driver);
}
// register calendar actions
$this->register_action('index', array($this, 'calendar_view'));
@ -580,7 +582,7 @@ class calendar extends rcube_plugin
}
/**
*
* Construct the ics file for exporting events to iCalendar format;
*/
function export_events()
{
@ -588,7 +590,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);
$events = $this->driver->load_events($start, $end, get_input_value('source', RCUBE_INPUT_GET));
$events = $this->driver->load_events($start, $end, null, get_input_value('source', RCUBE_INPUT_GET), 0);
header("Content-Type: text/calendar");
header("Content-Disposition: inline; filename=calendar.ics");

View file

@ -256,7 +256,7 @@ function rcube_calendar_ui(settings)
}
}
else if (calendar.attachments) {
// fetch attachments, some drivers doesn't set 'attachments' popr of the event
// fetch attachments, some drivers doesn't set 'attachments' prop of the event?
}
// list event attendees
@ -474,7 +474,7 @@ function rcube_calendar_ui(settings)
}
else {
$('#edit-attachments > ul').empty();
// fetch attachments, some drivers doesn't set 'attachments' array for event
// fetch attachments, some drivers doesn't set 'attachments' array for event?
}
}
@ -507,7 +507,8 @@ function rcube_calendar_ui(settings)
recurrence: '',
alarms: '',
attendees: event_attendees,
deleted_attachments: rcmail.env.deleted_attachments
deleted_attachments: rcmail.env.deleted_attachments,
attachments: []
};
// serialize alarm settings
@ -522,11 +523,9 @@ function rcube_calendar_ui(settings)
}
// uploaded attachments list
var attachments = [];
for (var i in rcmail.env.attachments)
if (i.match(/^rcmfile([0-9a-z]+)/))
attachments.push(RegExp.$1);
data.attachments = attachments;
if (i.match(/^rcmfile(.+)/))
data.attachments.push(RegExp.$1);
// read attendee roles
$('select.edit-attendee-role').each(function(i, elem){

View file

@ -191,9 +191,10 @@ class kolab_calendar
* @param integer Event's new start (unix timestamp)
* @param integer Event's new end (unix timestamp)
* @param string Search query (optional)
* @param boolean Strip virtual events (optional)
* @return array A list of event records
*/
public function list_events($start, $end, $search = null)
public function list_events($start, $end, $search = null, $virtual = 1)
{
$this->_fetch_events();
@ -224,7 +225,7 @@ class kolab_calendar
}
// resolve recurring events
if ($event['recurrence']) {
if ($event['recurrence'] && $virtual == 1) {
$events = array_merge($events, $this->_get_recurring_events($event, $start, $end));
}
}

View file

@ -505,9 +505,10 @@ class kolab_driver extends calendar_driver
* @param integer Event's new end (unix timestamp)
* @param string Search query (optional)
* @param mixed List of calendar IDs to load events from (either as array or comma-separated string)
* @param boolean Strip virtual events (optional)
* @return array A list of event records
*/
public function load_events($start, $end, $search = null, $calendars = null)
public function load_events($start, $end, $search = null, $calendars = null, $virtual = 1)
{
if ($calendars && is_string($calendars))
$calendars = explode(',', $calendars);
@ -517,7 +518,7 @@ class kolab_driver extends calendar_driver
if ($calendars && !in_array($cid, $calendars))
continue;
$events = array_merge($events, $this->calendars[$cid]->list_events($start, $end, $search));
$events = array_merge($events, $this->calendars[$cid]->list_events($start, $end, $search, $virtual));
}
return $events;

View file

@ -19,6 +19,7 @@
| |
+-------------------------------------------------------------------------+
| Author: Lazlo Westerhof <hello@lazlo.me> |
| Bogomil "Bogo" Shopov <shopov@kolabsys.com> |
+-------------------------------------------------------------------------+
*/
@ -55,26 +56,32 @@ class calendar_ical
public function export($events)
{
if (!empty($this->rc->user->ID)) {
$ical = "BEGIN:VCALENDAR\n";
$ical .= "VERSION:2.0\n";
$ical .= "PRODID:-//Roundcube Webmail " . RCMAIL_VERSION . "//NONSGML Calendar//EN\n";
$ical .= "CALSCALE:GREGORIAN\n";
$ical = "BEGIN:VCALENDAR\r\n";
$ical .= "VERSION:2.0\r\n";
$ical .= "PRODID:-//Roundcube Webmail " . RCMAIL_VERSION . "//NONSGML Calendar//EN\r\n";
$ical .= "CALSCALE:GREGORIAN\r\n";
foreach ($events as $event) {
$ical .= "BEGIN:VEVENT\n";
$ical .= "UID:" . self::escpape($event['uid']) . "\n";
$ical .= "DTSTART:" . gmdate('Ymd\THis\Z', $event['start']) . "\n";
$ical .= "DTEND:" . gmdate('Ymd\THis\Z', $event['end']) . "\n";
$ical .= "SUMMARY:" . self::escpape($event['title']) . "\n";
$ical .= "DESCRIPTION:" . self::escpape($event['description']) . "\n";
$ical .= "BEGIN:VEVENT\r\n";
$ical .= "UID:" . self::escpape($event['uid']) . "\r\n";
$ical .= "DTSTART:" . gmdate('Ymd\THis\Z', $event['start']) . "\r\n";
$ical .= "DTEND:" . gmdate('Ymd\THis\Z', $event['end']) . "\r\n";
$ical .= "SUMMARY:" . self::escpape($event['title']) . "\r\n";
$ical .= "DESCRIPTION:" . wordwrap(self::escpape($event['description']),75,'\r\n ') . "\r\n";
if (!empty($event['attendees'])){
$ical .= $this->_get_attendees($event['attendees']);
}
if (!empty($event['location'])) {
$ical .= "LOCATION:" . self::escpape($event['location']) . "\n";
$ical .= "LOCATION:" . self::escpape($event['location']) . "\r\n";
}
if ($event['recurrence']) {
$ical .= "RRULE:" . calendar::to_rrule($event['recurrence']) . "\n";
$ical .= "RRULE:" . calendar::to_rrule($event['recurrence']) . "\r\n";
}
if(!empty($event['categories'])) {
$ical .= "CATEGORIES:" . self::escpape(strtoupper($event['categories'])) . "\n";
$ical .= "CATEGORIES:" . self::escpape(strtoupper($event['categories'])) . "\r\n";
}
if ($event['sensitivity'] > 0) {
$ical .= "X-CALENDARSERVER-ACCESS:CONFIDENTIAL";
@ -84,16 +91,16 @@ class calendar_ical
$val = calendar::parse_alaram_value($trigger);
$ical .= "BEGIN:VALARM\n";
if ($val[1]) $ical .= "TRIGGER:" . preg_replace('/^([-+])(.+)/', '\\1PT\\2', $trigger) . "\n";
else $ical .= "TRIGGER;VALUE=DATE-TIME:" . gmdate('Ymd\THis\Z', $val[0]) . "\n";
if ($action) $ical .= "ACTION:" . self::escpape(strtoupper($action)) . "\n";
if ($val[1]) $ical .= "TRIGGER:" . preg_replace('/^([-+])(.+)/', '\\1PT\\2', $trigger) . "\r\n";
else $ical .= "TRIGGER;VALUE=DATE-TIME:" . gmdate('Ymd\THis\Z', $val[0]) . "\r\n";
if ($action) $ical .= "ACTION:" . self::escpape(strtoupper($action)) . "\r\n";
$ical .= "END:VALARM\n";
}
$ical .= "TRANSP:" . ($event['free_busy'] == 'free' ? 'TRANSPARENT' : 'OPAQUE') . "\n";
$ical .= "TRANSP:" . ($event['free_busy'] == 'free' ? 'TRANSPARENT' : 'OPAQUE') . "\r\n";
// TODO: export attachments
$ical .= "END:VEVENT\n";
$ical .= "END:VEVENT\r\n";
}
$ical .= "END:VCALENDAR";
@ -106,4 +113,45 @@ class calendar_ical
{
return preg_replace('/(?<!\\\\)([\:\;\,\\n\\r])/', '\\\$1', $str);
}
/**
* Construct the orginizer of the event.
* @param Array Attendees and roles
*
*/
private function _get_attendees($ats)
{
$organizer = "";
$attendees = "";
foreach ($ats as $at){
if ($at['role']=="ORGANIZER"){
//I am an orginizer
$organizer .= "ORGANIZER;";
if (!empty($at['name']))
$organizer .="CN=".$at['name'].":";
//handling limitations according to rfc2445#section-4.1
$organizer .="MAILTO:"."\r\n ".$at['email'];
}else{
//I am an attendee
$attendees .= "ATTENDEE;ROLE=".$at['role'].";PARTSTAT=".$at['status'];
$attendees .= "\r\n "; ////handling limitations according to rfc2445#section-4.1
if (!empty($at['name']))
$attendees .=";CN=".$at['name'].":";
$attendees .="MAILTO:".$at['email']."\r\n";
}
}
return $organizer."\r\n".$attendees;
}
}

View file

@ -160,7 +160,8 @@ pre {
width: 100%;
}
#agendalist td, th {
#agendalist td,
#agendalist th {
border-right: 1px solid #C1DAD7;
border-bottom: 1px solid #C1DAD7;
background: #fff;
@ -672,6 +673,11 @@ a.alarm-action-snooze:after {
padding-right: 0.5em;
}
.ui-datepicker th {
padding: 0.3em 0;
font-size: 10px;
}
.ui-datepicker td span,
.ui-datepicker td a {
padding-left: 0.1em;