/** * Generate the HTML for a vEvent. */ protected function _vEvent($vevent, $id, $method = 'PUBLISH', $components = array()) { global $injector, $prefs, $registry, $notification; $attendees = null; $desc = ''; $sender = $vevent->organizerName(); $options = array(); try { if (($attendees = $vevent->getAttribute('ATTENDEE')) && !is_array($attendees)) { $attendees = array($attendees); } } catch (Horde_Icalendar_Exception $e) { } switch ($method) { case 'PUBLISH': $desc = _("%s wishes to make you aware of \"%s\"."); if ($registry->hasMethod('calendar/import')) { $options['import'] = _("Add this to my calendar"); } break; case 'REQUEST': // Check if this is an update. try { $calendars = $registry->calendar->listCalendars(true); $registry->call('calendar/export', array($vevent->getAttributeSingle('UID'), 'text/calendar', array(), $calendars)); $desc = _("%s wants to notify you about changes in \"%s\"."); $is_update = true; } catch (Horde_Exception $e) { $desc = _("%s wishes to make you aware of \"%s\"."); $is_update = false; // Check that you are one of the attendees here. if (!empty($attendees)) { $identity = $injector->getInstance('IMP_Identity'); for ($i = 0, $c = count($attendees); $i < $c; ++$i) { $attendee = parse_url($attendees[$i]); if (!empty($attendee['path']) && $identity->hasAddress($attendee['path'])) { $desc = _("%s requests your presence at \"%s\"."); break; } } } } if ($is_update && $registry->hasMethod('calendar/replace')) { $options['accept-import'] = _("Accept and update in my calendar"); $options['import'] = _("Update in my calendar"); } elseif ($registry->hasMethod('calendar/import')) { $options['accept-import'] = _("Accept and add to my calendar"); $options['import'] = _("Add to my calendar"); } $options['accept'] = _("Accept request"); $options['tentative'] = _("Tentatively Accept request"); $options['deny'] = _("Deny request"); // $options['delegate'] = _("Delegate position"); break; case 'ADD': $desc = _("%s wishes to amend \"%s\"."); if ($registry->hasMethod('calendar/import')) { $options['import'] = _("Update this event on my calendar"); } break; case 'REFRESH': $desc = _("%s wishes to receive the latest information about \"%s\"."); $options['send'] = _("Send Latest Information"); break; case 'REPLY': $desc = _("%s has replied to the invitation to \"%s\"."); $from = $this->getConfigParam('imp_contents')->getHeader()->getHeader('from'); $sender = $from ? $from->getAddressList(true)->first()->bare_address : null; if ($registry->hasMethod('calendar/updateAttendee') && $this->_autoUpdateReply(self::AUTO_UPDATE_EVENT_REPLY, $sender)) { try { $registry->call('calendar/updateAttendee', array($vevent, $sender)); $notification->push(_("Respondent Status Updated."), 'horde.success'); } catch (Horde_Exception $e) { $notification->push(sprintf(_("There was an error updating the event: %s"), $e->getMessage()), 'horde.error'); } } else { $options['update'] = _("Update respondent status"); } break; case 'CANCEL': try { $vevent->getAttributeSingle('RECURRENCE-ID'); $params = $vevent->getAttribute('RECURRENCE-ID', true); foreach ($params as $param) { if (array_key_exists('RANGE', $param)) { $desc = _("%s has cancelled multiple instances of the recurring \"%s\"."); } break; } if (empty($desc)) { $desc = _("%s has cancelled an instance of the recurring \"%s\"."); } if ($registry->hasMethod('calendar/replace')) { $options['delete'] = _("Update in my calendar"); } } catch (Horde_Icalendar_Exception $e) { $desc = _("%s has cancelled \"%s\"."); if ($registry->hasMethod('calendar/delete')) { $options['delete'] = _("Delete from my calendar"); } } break; } $view = $this->_getViewOb(); try { $start = $vevent->getAttribute('DTSTART'); $view->start = is_array($start) ? strftime($prefs->getValue('date_format'), mktime(0, 0, 0, $start['month'], $start['mday'], $start['year'])) : strftime($prefs->getValue('date_format'), $start) . ' ' . date($prefs->getValue('twentyFour') ? ' G:i' : ' g:i a', $start); } catch (Horde_Icalendar_Exception $e) { $start = null; } try { $end = $vevent->getAttribute('DTEND'); $view->end = is_array($end) ? strftime($prefs->getValue('date_format'), mktime(0, 0, 0, $end['month'], $end['mday'], $end['year'])) : strftime($prefs->getValue('date_format'), $end) . ' ' . date($prefs->getValue('twentyFour') ? ' G:i' : ' g:i a', $end); } catch (Horde_Icalendar_Exception $e) { $end = null; } try { $summary = $vevent->getAttributeSingle('SUMMARY'); $view->summary = $summary; } catch (Horde_Icalendar_Exception $e) { $summary = _("Unknown Meeting"); $view->summary_error = _("None"); } $view->desc = sprintf($desc, $sender, $summary); try { $view->desc2 = $vevent->getAttributeSingle('DESCRIPTION'); } catch (Horde_Icalendar_Exception $e) { } try { $view->loc = $vevent->getAttributeSingle('LOCATION'); } catch (Horde_Icalendar_Exception $e) { } try { $rrule = $vevent->getAttribute('RRULE'); } catch (Horde_Icalendar_Exception $e) { $rrule = array(); } if (!is_array($rrule)) { $recurrence = new Horde_Date_Recurrence(new Horde_Date($view->start)); if (strpos($rrule, '=') !== false) { $recurrence->fromRRule20($rrule); } else { $recurrence->fromRRule10($rrule); } // Add exceptions try { $exdates = $vevent->getAttributeValues('EXDATE'); if (is_array($exdates)) { foreach ($exdates as $exdate) { if (is_array($exdate)) { $recurrence->addException((int) $exdate['year'], (int) $exdate['month'], (int) $exdate['mday']); } } } } catch (Horde_ICalendar_Exception $e) { } $view->recurrence = $recurrence->toString($prefs->getValue('date_format')); $view->exceptions = array(); foreach ($components as $key => $component) { try { if ($component->getAttribute('RECURRENCE-ID') && $component->getAttributeSingle('UID') == $vevent->getAttributeSingle('UID')) { if ($ex = $this->_vEventException($component, $key, $method)) { $view->exceptions[] = $ex; } } } catch (Horde_Icalendar_Exception $e) { } } } if (!empty($attendees)) { $view->attendees = $this->_parseAttendees($vevent, $attendees); } if (!is_null($start) && !is_null($end) && in_array($method, array('PUBLISH', 'REQUEST', 'ADD')) && $registry->hasMethod('calendar/getFbCalendars') && $registry->hasMethod('calendar/listEvents')) { try { $calendars = $registry->call('calendar/getFbCalendars'); $vevent_start = new Horde_Date($start); $vevent_end = new Horde_Date($end); // Check if it's an all-day event. if (is_array($start)) { $vevent_allDay = true; $vevent_end = $vevent_end->sub(1); } else { $vevent_allDay = false; $time_span_start = $vevent_start->sub($prefs->getValue('conflict_interval') * 60); $time_span_end = $vevent_end->add($prefs->getValue('conflict_interval') * 60); } $events = $registry->call('calendar/listEvents', array($start, $vevent_end, $calendars, false)); // TODO: Check if there are too many events to show. $conflicts = array(); foreach ($events as $calendar) { foreach ($calendar as $event) { // TODO: WTF? Why are we using Kronolith constants // here? if (in_array($event->status, array(Kronolith::STATUS_CANCELLED, Kronolith::STATUS_FREE))) { continue; } if ($vevent_allDay || $event->isAllDay()) { $type = 'collision'; } elseif ($event->end->compareDateTime($time_span_start) <= -1 || $event->start->compareDateTime($time_span_end) >= 1) { continue; } elseif ($event->end->compareDateTime($vevent_start) <= -1 || $event->start->compareDateTime($vevent_end) >= 1) { $type = 'nearcollision'; } else { $type = 'collision'; } $conflicts[] = array('collision' => $type == 'collision', 'range' => $event->getTimeRange(), 'title' => $event->getTitle()); } } if (!empty($conflicts)) { $view->conflicts = $conflicts; } } catch (Horde_Exception $e) { } } if (!empty($options)) { reset($options); $view->options = $options; $view->options_id = $id; } return $view->render('action'); }