Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 37 additions & 9 deletions banner_ics.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public function process_attachment(&$content, &$message, &$a)
$date_format = $rcmail->config->get('date_format', 'D M d, Y');
$time_format = $rcmail->config->get('time_format', 'h:ia');
$combined_format = $date_format . ' ' . $time_format;
$ymd = 'Y-m-d';

// Parse event
$ics = $message->get_part_body($a->mime_id);
Expand All @@ -63,20 +64,47 @@ public function process_attachment(&$content, &$message, &$a)
// Make sure we have events
if (!$ical->hasEvents()) return;

// Crete timezone objects for calendar timezone and RoundCube UI timezone
try {
$ui_tz = new DateTimeZone($rcmail->config->get('timezone'));
} catch (Exception $e) {
$ui_tz = new DateTimeZone(DateTimeZone::UTC);
}
try {
$ical_tz = new DateTimeZone($ical->calendarTimeZone(true));
} catch (Exception $e) {
// Use UI timezone if the calendar have no timezone specified
$ical_tz = $ui_tz;
}
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These try-catch blocks are ugly. Can't we use null coalescing instead?


// Get first event
foreach ($ical->events() as &$event) {
$dtstart = $event->dtstart_array[2];
$dtend = $event->dtend_array[2];
$dtstr = $rcmail->format_date($dtstart, $combined_format) . ' - ';

// Dont double date if same
$df = 'Y-m-d';
if (date($df, $dtstart) === date($df, $dtend)) {
$dtstr .= $rcmail->format_date($dtend, $time_format);
$is_all_day = isset($event->dtstart_array[0]['VALUE']) && $event->dtstart_array[0]['VALUE'] === 'DATE';

if ($is_all_day) {
// All day events should use UI timezone to avoid turning dates
$dtstart = new DateTime($event->dtstart, $ui_tz);
$dtend = new DateTime($event->dtend, $ui_tz);
// All day events ends at next day midnight, we should fix the day
$dtend->modify('-1 day');
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is right. From RFC 5545 (https://tools.ietf.org/html/rfc5545#page-54)

  The "VEVENT" is also the calendar component used to specify an
  anniversary or daily reminder within a calendar.  These events
  have a DATE value type for the "DTSTART" property instead of the
  default value type of DATE-TIME.  If such a "VEVENT" has a "DTEND"
  property, it MUST be specified as a DATE value also.  The
  anniversary type of "VEVENT" can span more than one date (i.e.,
  "DTEND" property value is set to a calendar date after the
  "DTSTART" property value).  If such a "VEVENT" has a "DURATION"
  property, it MUST be specified as a "dur-day" or "dur-week" value.

From what I understand, DTEND would be absent in a single day event, so we need to check for that instead. Also see the examples on Pg. 55

} else {
$dtstr .= $rcmail->format_date($dtend, $combined_format);
// Events with proper time should use calendar timezone.
// Note that if DTSTART/DTEND ends with "Z", UTC is used instead of the given timezone automatically
$dtstart = new DateTime($event->dtstart, $ical_tz);
$dtend = new DateTime($event->dtend, $ical_tz);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should really be checking if the dates have timezone information instead ... correct me if I'm wrong, but I think it is possible that the event date and the DTSTART/DTEND may be in different timezones. In that sense, we should fall back to the event timezone only if the the date timezone is missing.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you can do probably is check if dtstart_array[0] and dtend_array[0] respectively have the key TZID. If yes, directly use dtstart_array[2] in format_date, otherwise create a new DateTime object using the timezone from calendarTimeZone if any.

}

$is_oneday = $dtstart->format($ymd) === $dtend->format($ymd);

// Concatenate event date string
if ($is_all_day) {
// All day events shouldn't display time
$dtstr = $rcmail->format_date($dtstart, $date_format)
. (!$is_oneday ? ' – ' . $rcmail->format_date($dtend, $date_format) : '');
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hyphen instead of dash please.

} else {
$dtstr = $rcmail->format_date($dtstart, $combined_format) . ' – '
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

. ($is_oneday ? $rcmail->format_date($dtend, $time_format) : $rcmail->format_date($dtend, $combined_format));
}
// Put timezone in date string
$dtstr .= ' (' . $rcmail->format_date($dtstart, 'T') . ')';

Expand Down