Calculates recurrences of an event during a certain period.
public static addEvents ( &$results, &$event, $startDate, $endDate, $showRecurrence, $json, $coverDates = true ) |
/** * Lists all events in the time range, optionally restricting results to * only events with alarms. * * @param Horde_Date $startDate The start of range date. * @param Horde_Date $endDate The end of date range. * @param array $options Additional options: * - show_recurrence: (boolean) Return every instance of a recurring * event? * DEFAULT: false (Only return recurring events once * inside $startDate - $endDate range) * - has_alarm: (boolean) Only return events with alarms. * DEFAULT: false (Return all events) * - json: (boolean) Store the results of the event's toJson() * method? * DEFAULT: false * - cover_dates: (boolean) Add the events to all days that they * cover? * DEFAULT: true * - hide_exceptions: (boolean) Hide events that represent exceptions to * a recurring event. * DEFAULT: false (Do not hide exception events) * - fetch_tags: (boolean) Fetch tags for all events. * DEFAULT: false (Do not fetch event tags) * * @throws Kronolith_Exception */ protected function _listEvents(Horde_Date $startDate = null, Horde_Date $endDate = null, array $options = array()) { if (!class_exists('Date_Holidays')) { Horde::log('Support for Date_Holidays has been enabled but the package seems to be missing.', 'ERR'); return array(); } if (is_null($startDate) && !is_null($endDate)) { $startDate = clone $endDate; $startDate->year--; } if (is_null($endDate) && !is_null($startDate)) { $endDate = clone $startDate; $endDate->year++; } if ($options['has_alarm'] || is_null($startDate) || is_null($endDate)) { return array(); } $startDate = clone $startDate; $startDate->hour = $startDate->min = $startDate->sec = 0; $endDate = clone $endDate; $endDate->hour = 23; $endDate->min = $endDate->sec = 59; Date_Holidays::staticSetProperty('DIE_ON_MISSING_LOCALE', false); $results = array(); for ($year = $startDate->year; $year <= $endDate->year; $year++) { $dh = Date_Holidays::factory($this->calendar, $year, $this->_params['language']); if (Date_Holidays::isError($dh)) { Horde::log(sprintf('Factory was unable to produce driver object for driver %s in year %s with locale %s', $this->calendar, $year, $this->_params['language']), 'ERR'); continue; } $dh->addTranslation($this->_params['language']); $events = $this->_getEvents($dh, $startDate, $endDate); foreach ($events as $event) { Kronolith::addEvents($results, $event, $startDate, $endDate, $options['show_recurrence'], $options['json'], $options['cover_dates']); } } return $results; }
/** * Searches a calendar. * * @param object $query An object with the criteria to search for. * @param boolean $json Store the results of the events' toJson() method? * * @return mixed An array of Kronolith_Events. * @throws Kronolith_Exception */ public function search($query, $json = false) { /* Our default implementation first gets <em>all</em> events in a * specific period, and then filters based on the actual values that * are filled in. Drivers can optimize this behavior if they have the * ability. */ $results = array(); $events = $this->listEvents(!empty($query->start) ? $query->start : null, !empty($query->end) ? $query->end : null); foreach ($events as $day_events) { foreach ($day_events as $event) { if (((!isset($query->start) || $event->end->compareDateTime($query->start) > 0) && (!isset($query->end) || $event->end->compareDateTime($query->end) < 0) || $event->recurs() && $event->end->compareDateTime($query->start) >= 0 && $event->start->compareDateTime($query->end) <= 0) && (empty($query->title) || stristr($event->getTitle(), $query->title)) && (empty($query->location) || stristr($event->location, $query->location)) && (empty($query->description) || stristr($event->description, $query->description)) && (empty($query->creator) || stristr($event->creator, $query->creator)) && (!isset($query->status) || $event->status == $query->status) && (empty($query->baseid) || $event->baseid == $query->baseid)) { Kronolith::addEvents($results, $event, $event->start, $event->end, false, $json, false); } } } return $results; }
/** * Saves an event and returns a signed result object including the saved * event. * * @param Kronolith_Event $event An event object. * @param Kronolith_Event $original If $event is an exception, this should * be set to the original event. * @param object $attributes The attributes sent by the client. * Expected to contain cstart and cend. * @param boolean $saveOriginal Commit any changes in $original to * storage also. * * @return object The result object. */ protected function _saveEvent(Kronolith_Event $event, Kronolith_Event $original = null, $attributes = null, $saveOriginal = false) { if ($this->vars->targetcalendar) { $cal = $this->vars->targetcalendar; } elseif ($this->vars->cal) { $cal = $this->vars->cal; } else { $cal = $event->calendarType . '|' . $event->calendar; } $result = $this->_signedResponse($cal); $events = array(); try { $event->save(); if (!$this->vars->view_start || !$this->vars->view_end) { $result->events = array(); return $result; } $end = new Horde_Date($this->vars->view_end); $end->hour = 23; $end->min = $end->sec = 59; Kronolith::addEvents($events, $event, new Horde_Date($this->vars->view_start), $end, true, true); // If this is an exception, we re-add the original event also; // cstart and cend are the cacheStart and cacheEnd dates from the // client. if (!empty($original)) { Kronolith::addEvents($events, $original, new Horde_Date($attributes->cstart), new Horde_Date($attributes->cend), true, true); if ($saveOriginal) { $original->save(); } } // If this event recurs, we must add any bound exceptions to the // results if ($event->recurs()) { $bound = $event->boundExceptions(false); foreach ($bound as $day => &$exceptions) { foreach ($exceptions as &$exception) { $exception = $exception->toJson(); } } Kronolith::mergeEvents($events, $bound); } $result->events = count($events) ? $events : array(); } catch (Exception $e) { $GLOBALS['notification']->push($e, 'horde.error'); } return $result; }
/** * Lists all events in the time range, optionally restricting results to * only events with alarms. * * @param Horde_Date $startDate The start of range date. * @param Horde_Date $endDate The end of date range. * @param array $options Additional options: * - show_recurrence: (boolean) Return every instance of a recurring * event? * DEFAULT: false (Only return recurring events once * inside $startDate - $endDate range) * - has_alarm: (boolean) Only return events with alarms. * DEFAULT: false (Return all events) * - json: (boolean) Store the results of the event's toJson() * method? * DEFAULT: false * - cover_dates: (boolean) Add the events to all days that they * cover? * DEFAULT: true * - hide_exceptions: (boolean) Hide events that represent exceptions to * a recurring event. * DEFAULT: false (Do not hide exception events) * - fetch_tags: (boolean) Fetch tags for all events. * DEFAULT: false (Do not fetch event tags) * * @throws Kronolith_Exception */ protected function _listEvents(Horde_Date $startDate = null, Horde_Date $endDate = null, array $options = array()) { if (!is_null($startDate)) { $startDate = clone $startDate; $startDate->hour = $startDate->min = $startDate->sec = 0; } if (!is_null($endDate)) { $endDate = clone $endDate; $endDate->hour = 23; $endDate->min = $endDate->sec = 59; } $conditions = $options['has_alarm'] ? 'event_alarm > ?' : ''; $values = $options['has_alarm'] ? array(0) : array(); if ($options['hide_exceptions']) { if (!empty($conditions)) { $conditions .= ' AND '; } $conditions .= "event_baseid = ''"; } $events = $this->_listEventsConditional($startDate, $endDate, $conditions, $values); $results = array(); $tags = null; if ($options['fetch_tags'] && count($events)) { $tags = Kronolith::getTagger()->getTags(array_keys($events)); } foreach ($events as $id) { $event = $this->getEvent($id); if (isset($tags) && !empty($tags[$event->uid])) { $event->tags = $tags[$event->uid]; } Kronolith::addEvents($results, $event, $startDate, $endDate, $options['show_recurrence'], $options['json'], $options['cover_dates']); } return $results; }
/** * Lists all events in the time range, optionally restricting results to * only events with alarms. * * @param Horde_Date $startDate The start of range date. * @param Horde_Date $endDate The end of date range. * @param array $options Additional options: * - show_recurrence: (boolean) Return every instance of a recurring * event? * DEFAULT: false (Only return recurring events once * inside $startDate - $endDate range) * - has_alarm: (boolean) Only return events with alarms. * DEFAULT: false (Return all events) * - json: (boolean) Store the results of the event's toJson() * method? * DEFAULT: false * - cover_dates: (boolean) Add the events to all days that they * cover? * DEFAULT: true * - hide_exceptions: (boolean) Hide events that represent exceptions to * a recurring event. * DEFAULT: false (Do not hide exception events) * - fetch_tags: (boolean) Fetch tags for all events. * DEFAULT: false (Do not fetch event tags) * * @throws Kronolith_Exception */ protected function _listEvents(Horde_Date $startDate = null, Horde_Date $endDate = null, array $options = array()) { $this->synchronize(); if (empty($startDate)) { $startDate = new Horde_Date(array('mday' => 1, 'month' => 1, 'year' => 00)); } if (empty($endDate)) { $endDate = new Horde_Date(array('mday' => 31, 'month' => 12, 'year' => 9999)); } if (!$startDate instanceof Horde_Date) { $startDate = new Horde_Date($startDate); } if (!$endDate instanceof Horde_Date) { $endDate = new Horde_Date($endDate); } $startDate = clone $startDate; $startDate->hour = $startDate->min = $startDate->sec = 0; $endDate = clone $endDate; $endDate->hour = 23; $endDate->min = $endDate->sec = 59; $events = array(); foreach ($this->_events_cache as $event) { if ($options['has_alarm'] && !$event->alarm) { continue; } if ($options['hide_exceptions'] && !empty($event->baseid)) { continue; } /* Ignore events out of the period. */ $recurs = $event->recurs(); if ($event->start->compareDateTime($endDate) > 0 || !$recurs && $event->end->compareDateTime($startDate) < 0) { continue; } if ($recurs) { // Fixed end date? Check if end is before start period. if ($event->recurrence->hasRecurEnd() && $event->recurrence->recurEnd->compareDateTime($startDate) < 0) { continue; } else { $next = $event->recurrence->nextRecurrence($startDate); if ($next == false || $next->compareDateTime($endDate) > 0) { continue; } } } Kronolith::addEvents($events, $event, $startDate, $endDate, $options['show_recurrence'], $options['json'], $options['cover_dates']); } return $events; }
/** * Lists all events in the time range, optionally restricting results to * only events with alarms. * * @param Horde_Date $startDate The start of range date. * @param Horde_Date $endDate The end of date range. * @param array $options Additional options: * - show_recurrence: (boolean) Return every instance of a recurring * event? * DEFAULT: false (Only return recurring events once * inside $startDate - $endDate range) * - has_alarm: (boolean) Only return events with alarms. * DEFAULT: false (Return all events) * - json: (boolean) Store the results of the event's toJson() * method? * DEFAULT: false * - cover_dates: (boolean) Add the events to all days that they * cover? * DEFAULT: true * - hide_exceptions: (boolean) Hide events that represent exceptions to * a recurring event. * DEFAULT: false (Do not hide exception events) * - fetch_tags: (boolean) Fetch tags for all events. * DEFAULT: false (Do not fetch event tags) * * @throws Kronolith_Exception */ protected function _listEvents(Horde_Date $startDate = null, Horde_Date $endDate = null, array $options = array()) { list($this->api, $category) = explode('/', $this->calendar, 2); if (!$this->_params['registry']->hasMethod($this->api . '/listTimeObjects')) { return array(); } if (is_null($startDate)) { $startDate = new Horde_Date(array('mday' => 1, 'month' => 1, 'year' => 00)); } if (is_null($endDate)) { $endDate = new Horde_Date(array('mday' => 31, 'month' => 12, 'year' => 9999)); } $startDate = clone $startDate; $startDate->hour = $startDate->min = $startDate->sec = 0; $endDate = clone $endDate; $endDate->hour = 23; $endDate->min = $endDate->sec = 59; try { $eventsList = $this->_params['registry']->call($this->api . '/listTimeObjects', array(array($category), $startDate, $endDate)); } catch (Horde_Exception $e) { throw new Kronolith_Exception($e); } $results = array(); foreach ($eventsList as $eventsListItem) { try { $event = new Kronolith_Event_Horde($this, $eventsListItem); } catch (Kronolith_Exception $e) { Horde::log($e, 'NOTICE'); continue; } // Ignore events out of the period. $recurs = $event->recurs(); if ($event->start->compareDateTime($endDate) > 0 || !$recurs && $event->end->compareDateTime($startDate) < 0) { continue; } if ($recurs) { // Fixed end date? Check if end is before start period. if ($event->recurrence->hasRecurEnd() && $event->recurrence->recurEnd->compareDateTime($startDate) < 0) { continue; } else { $next = $event->recurrence->nextRecurrence($startDate); if ($next == false || $next->compareDateTime($endDate) > 0) { continue; } } } Kronolith::addEvents($results, $event, $startDate, $endDate, $options['show_recurrence'], $options['json'], $options['cover_dates']); } return $results; }
/** * Processes the components of a Horde_Icalendar container into an event * list. * * @param array $results Gets filled with the events in the * given time range. * @param array $events A list of Kronolith_Event_Ical objects. * @param Horde_Date $startInterval Start of range date. * @param Horde_Date $endInterval End of range date. * @param boolean $showRecurrence Return every instance of a recurring * event? If false, will only return * recurring events once inside the * $startDate - $endDate range. * @param boolean $json Store the results of the events' * toJson() method? * @param boolean $coverDates Whether to add the events to all days * that they cover. * @param boolean $hideExceptions Hide events that represent exceptions * to a recurring event. * @param string $id Enforce a certain event id (not UID). * * @throws Kronolith_Exception */ protected function _processComponents(&$results, $events, $startDate, $endDate, $showRecurrence, $json, $coverDates, $hideExceptions, $id = null) { $processed = array(); foreach (array_values($events) as $i => $event) { $event->permission = $this->getPermission(); // Force string so JSON encoding is consistent across drivers. $event->id = $id ? $id : 'ical' . $i; /* Catch RECURRENCE-ID attributes which mark single recurrence * instances. */ if (isset($event->recurrenceid) && isset($event->uid) && isset($event->sequence)) { $exceptions[$event->uid][$event->sequence] = $event->recurrenceid; if ($hideExceptions) { continue; } $event->id .= '/' . $event->recurrenceid; } /* Ignore events out of the period. */ $recurs = $event->recurs(); if ($endDate && $event->start->compareDateTime($endDate) > 0 || $startDate && !$recurs && $event->end->compareDateTime($startDate) < 0) { continue; } if ($recurs && $startDate) { // Fixed end date? Check if end is before start period. if ($event->recurrence->hasRecurEnd() && $event->recurrence->recurEnd->compareDateTime($startDate) < 0) { continue; } elseif ($endDate) { $next = $event->recurrence->nextRecurrence($startDate); if ($next == false || $next->compareDateTime($endDate) > 0) { continue; } } } $processed[] = $event; } /* Loop through all explicitly defined recurrence instances and create * exceptions for those in the event with the matching recurrence. */ foreach ($processed as $key => $event) { if ($event->recurs() && isset($exceptions[$event->uid][$event->sequence])) { $timestamp = $exceptions[$event->uid][$event->sequence]; $processed[$key]->recurrence->addException(date('Y', $timestamp), date('m', $timestamp), date('d', $timestamp)); } Kronolith::addEvents($results, $event, $startDate, $endDate, $showRecurrence, $json, $coverDates); } }
/** * Processes the components of a Horde_Icalendar container into an event * list. * * @param array $results Gets filled with the events in the * given time range. * @param Horde_Icalendar $ical An Horde_Icalendar container. * @param Horde_Date $startInterval Start of range date. * @param Horde_Date $endInterval End of range date. * @param boolean $showRecurrence Return every instance of a recurring * event? If false, will only return * recurring events once inside the * $startDate - $endDate range. * @param boolean $json Store the results of the events' * toJson() method? * @param boolean $coverDates Whether to add the events to all days * that they cover. * $param boolean $hideExceptions Hide events that represent exceptions * to a recurring event. * @param string $id Enforce a certain event id (not UID). * * @throws Kronolith_Exception */ protected function _processComponents(&$results, $ical, $startDate, $endDate, $showRecurrence, $json, $coverDates, $hideExceptions, $id = null) { $components = $ical->getComponents(); $events = array(); $count = count($components); $exceptions = array(); for ($i = 0; $i < $count; $i++) { $component = $components[$i]; if ($component->getType() == 'vEvent') { $event = new Kronolith_Event_Ical($this, $component); $event->permission = $this->getPermission(); // Force string so JSON encoding is consistent across drivers. $event->id = $id ? $id : 'ical' . $i; /* Catch RECURRENCE-ID attributes which mark single recurrence * instances. */ try { $recurrence_id = $component->getAttribute('RECURRENCE-ID'); if (is_int($recurrence_id) && is_string($uid = $component->getAttribute('UID')) && is_int($seq = $component->getAttribute('SEQUENCE'))) { $exceptions[$uid][$seq] = $recurrence_id; if ($hideExceptions) { continue; } $event->id .= '/' . $recurrence_id; } } catch (Horde_Icalendar_Exception $e) { } /* Ignore events out of the period. */ $recurs = $event->recurs(); if ($endDate && $event->start->compareDateTime($endDate) > 0 || $startDate && !$recurs && $event->end->compareDateTime($startDate) < 0) { continue; } if ($recurs && $startDate) { // Fixed end date? Check if end is before start period. if ($event->recurrence->hasRecurEnd() && $event->recurrence->recurEnd->compareDateTime($startDate) < 0) { continue; } elseif ($endDate) { $next = $event->recurrence->nextRecurrence($startDate); if ($next == false || $next->compareDateTime($endDate) > 0) { continue; } } } $events[] = $event; } } /* Loop through all explicitly defined recurrence intances and create * exceptions for those in the event with the matching recurrence. */ foreach ($events as $key => $event) { if ($event->recurs() && isset($exceptions[$event->uid][$event->sequence])) { $timestamp = $exceptions[$event->uid][$event->sequence]; $events[$key]->recurrence->addException(date('Y', $timestamp), date('m', $timestamp), date('d', $timestamp)); } Kronolith::addEvents($results, $event, $startDate, $endDate, $showRecurrence, $json, $coverDates); } }