diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php index f08d8f8e..f3e8b3c6 100644 --- a/plugins/calendar/calendar.php +++ b/plugins/calendar/calendar.php @@ -2115,22 +2115,24 @@ $("#rcmfd_new_category").keypress(function(event) { // check for organizer in attendees list $organizer = null; - foreach ((array) $event['attendees'] as $i => $attendee) { - if (!empty($attendee['role']) && $attendee['role'] == 'ORGANIZER') { - $organizer = $attendee; - } - if (!empty($attendee['status']) && $attendee['status'] == 'DELEGATED' && empty($attendee['rsvp'])) { - $event['attendees'][$i]['noreply'] = true; - } - else { - unset($event['attendees'][$i]['noreply']); + if (!empty($event['attendees'])) { + foreach ((array) $event['attendees'] as $i => $attendee) { + if (!empty($attendee['role']) && $attendee['role'] == 'ORGANIZER') { + $organizer = $attendee; + } + if (!empty($attendee['status']) && $attendee['status'] == 'DELEGATED' && empty($attendee['rsvp'])) { + $event['attendees'][$i]['noreply'] = true; + } + else { + unset($event['attendees'][$i]['noreply']); + } } } if ($organizer === null && !empty($event['organizer'])) { $organizer = $event['organizer']; $organizer['role'] = 'ORGANIZER'; - if (!is_array($event['attendees'])) { + if (!isset($event['attendees']) || !is_array($event['attendees'])) { $event['attendees'] = [$organizer]; } } diff --git a/plugins/calendar/drivers/calendar_driver.php b/plugins/calendar/drivers/calendar_driver.php index 8bcd6903..49c79579 100644 --- a/plugins/calendar/drivers/calendar_driver.php +++ b/plugins/calendar/drivers/calendar_driver.php @@ -507,7 +507,7 @@ abstract class calendar_driver // add to output if in range if (($next_event['start'] <= $end && $next_event['end'] >= $start)) { $next_event['_instance'] = $next_event['start']->format($recurrence_id_format); - $next_event['id'] = $next_event['uid'] . '-' . $exception['_instance']; + $next_event['id'] = $next_event['uid'] . '-' . $next_event['_instance']; $next_event['recurrence_id'] = $event['uid']; $events[] = $next_event; } @@ -647,7 +647,7 @@ abstract class calendar_driver $year2 = $end->format('Y'); $events = []; - $search = mb_strtolower($search); + $search = mb_strtolower((string) $search); $rcmail = rcmail::get_instance(); $cache = $rcmail->get_cache('calendar.birthdays', 'db', 3600); $cache->expunge(); @@ -786,18 +786,14 @@ abstract class calendar_driver } try { - $bday = $contact['birthday']; - if (!$bday instanceof DateTimeInterface) { - $bday = new DateTime($bday, new DateTimeZone('UTC')); - } - $bday->_dateonly = true; + $bday = libcalendaring_datetime::createFromAny($contact['birthday'], true); } catch (Exception $e) { rcube::raise_error([ 'code' => 600, 'file' => __FILE__, 'line' => __LINE__, - 'message' => 'BIRTHDAY PARSE ERROR: ' . $e->getMessage() + 'message' => 'Failed to parse contact birthday: ' . $e->getMessage() ], true, false ); diff --git a/plugins/libcalendaring/lib/libcalendaring_datetime.php b/plugins/libcalendaring/lib/libcalendaring_datetime.php index 95bdb94e..9f548988 100644 --- a/plugins/libcalendaring/lib/libcalendaring_datetime.php +++ b/plugins/libcalendaring/lib/libcalendaring_datetime.php @@ -26,4 +26,30 @@ class libcalendaring_datetime extends DateTime { public $_dateonly = false; + + /** + * Create an instance from a date string or object + * + * @param DateTimeInterface|string $date Date + * @param bool $dateonly Date only (ignore time) + */ + public static function createFromAny($date, bool $dateonly = false) + { + if (!$date instanceof DateTimeInterface) { + $date = new DateTime($date, new DateTimeZone('UTC')); + } + + // Note: On PHP8 we have DateTime::createFromInterface(), but not on PHP7 + + $result = self::createFromFormat( + 'Y-m-d\\TH:i:s', + $date->format('Y-m-d\\TH:i:s'), + // Sabre will loose timezone on all-day events, use the event start's timezone + $date->getTimezone() + ); + + $result->_dateonly = $dateonly; + + return $result; + } } diff --git a/plugins/libcalendaring/libcalendaring.php b/plugins/libcalendaring/libcalendaring.php index 291aa270..e2de7f2f 100644 --- a/plugins/libcalendaring/libcalendaring.php +++ b/plugins/libcalendaring/libcalendaring.php @@ -853,7 +853,7 @@ class libcalendaring extends rcube_plugin return $this->gettext('ondate') . ' ' . join(', ', $rdates) . ($more ? '...' : ''); } - $output = sprintf('%s %d ', $this->gettext('every'), $rrule['INTERVAL'] ?: 1); + $output = sprintf('%s %d ', $this->gettext('every'), !empty($rrule['INTERVAL']) ? $rrule['INTERVAL'] : 1); switch ($rrule['FREQ']) { case 'DAILY':