/** * Returns all event occurrences (one-time and recurring) in a given time range * To prevent memory leaks, the return is a sorted array formatted as: * <code> * array( * 0 => array( * 'id' => $guid, * 'start' => $start_time, * 'end' => $end_time, * 'title' => $title, * 'description' => $description, * 'url' => $url, * ... * ), * ); * </code> * * @param int $starttime Range start timestamp * @param int $endtime Range end timestamp * @param bool $export Export EventInstance objects to array * @param string $consumer Consumer name (passed to the export hook, so plugins can decide on exportable values) * @return EventsInstance[]|array */ public function getAllEventInstances($starttime = null, $endtime = null, $export = true, $consumer = '', $tz = null) { $instances = array(); if (!Util::isValidTimezone($tz)) { if (elgg_is_logged_in()) { // if logged in use the timezone settings of the current user $tz = Util::getClientTimezone(); } else { // use timezone of calendar owner $tz = Util::getClientTimezone($this->getOwnerEntity()); } } $events = $this->getAllEvents($starttime, $endtime); foreach ($events as $event) { /* @var $event Event */ if (!$event instanceof Event) { continue; } $start_times = $event->getStartTimes($starttime, $endtime, $tz); foreach ($start_times as $start_time) { $instance = new EventInstance($event, $start_time); $instance->setCalendar($this); $instances[] = $instance; } } usort($instances, array($this, 'compareInstancesByStartTime')); if ($export) { foreach ($instances as $key => $instance) { $instances[$key] = $instance->export($consumer); } } return $instances; }
/** * Checks if two timestamps fall on the same week day of the month (e.g. 3rd Monday) * * @param int $ts1 First timestamp * @param int $ts2 Second timestamp * @return bool */ public static function isOnSameWeekDayOfMonth($ts1 = 0, $ts2 = 0, $tz = null) { if (!Util::isValidTimezone($tz)) { $tz = Util::getClientTimezone(); } if (!self::isOnSameDayOfWeek($ts1, $ts2, $tz)) { return false; } return self::getWeekDayNthInMonth($ts1, $tz) == self::getWeekDayNthInMonth($ts2, $tz); }
/** * Returns an array of start times for an event within a given timestamp range * Note - assumes timestamp range is in increments of days * * @param int $startime Range start UNIX timestamp * @param int $endtime Range end UNIX timestamp * @return array */ public function getStartTimes($starttime = 0, $endtime = 0, $tz = null) { if (!Util::isValidTimezone($tz)) { $tz = Util::getClientTimezone(); } if (!$this->isRecurring()) { return array($this->getStartTimestamp()); } $start_times = array(); $test_day = $this->getStartTimestamp() > $starttime ? $this->getStartTimestamp() : $starttime; // iterate through each day of our range and see if this event shows up on any of those days while ($test_day < $endtime) { $shows = false; $offset_on_test_day = Util::getOffset($test_day, Util::UTC, $this->getTimezone()); // next increment $next_test_day = $test_day + Util::SECONDS_IN_A_DAY; // event has no more occurrences after this day if ($this->repeat_end_timestamp && $this->repeat_end_timestamp < $test_day) { break; } switch ($this->repeat_frequency) { case Util::FREQUENCY_DAILY: $shows = true; break; case Util::FREQUENCY_WEEKDAY: $repeat_weekly_days = array(Util::SATURDAY, Util::SUNDAY); foreach ($repeat_weekly_days as $key => $day) { $repeat_weekly_days[$key] = Util::getDayOfWeek(strtotime($day, $test_day) - $offset_on_test_day); } $D = Util::getDayOfWeek($test_day); $shows = !in_array($D, $repeat_weekly_days); break; case Util::FREQUENCY_WEEKDAY_ODD: $repeat_weekly_days = array(Util::MONDAY, Util::WEDNESDAY, Util::FRIDAY); foreach ($repeat_weekly_days as $key => $day) { $repeat_weekly_days[$key] = Util::getDayOfWeek(strtotime($day, $test_day) - $offset_on_test_day); } $D = Util::getDayOfWeek($test_day); $shows = in_array($D, $repeat_weekly_days); break; case Util::FREQUENCY_WEEKDAY_EVEN: $repeat_weekly_days = array(Util::TUESDAY, Util::THURSDAY); foreach ($repeat_weekly_days as $key => $day) { $repeat_weekly_days[$key] = Util::getDayOfWeek(strtotime($day, $test_day) - $offset_on_test_day); } $D = Util::getDayOfWeek($test_day); $shows = in_array($D, $repeat_weekly_days); break; case Util::FREQUENCY_WEEKLY: $repeat_weekly_days = $this->repeat_weekly_days; if (!$repeat_weekly_days) { $repeat_weekly_days = Util::getDayOfWeek($this->getStartTimestamp()); } if (!is_array($repeat_weekly_days)) { $repeat_weekly_days = array($repeat_weekly_days); } $D = Util::getDayOfWeek($test_day); foreach ($repeat_weekly_days as $key => $day) { // Monday in Sydney can still be Sunday at UTC $repeat_weekly_days[$key] = Util::getDayOfWeek(strtotime($day, $test_day) - $offset_on_test_day); } $shows = in_array($D, $repeat_weekly_days); break; case Util::FREQUENCY_MONTHLY: if ($this->repeat_monthly_by == Util::REPEAT_MONTHLY_BY_DAY_OF_WEEK) { $shows = Util::isOnSameWeekDayOfMonth($test_day, $this->getStartTimestamp()); if ($shows) { // we can skip 4 weeks $next_test_day = strtotime('+28 days', $test_day); } } else { $shows = Util::isOnSameDayOfMonth($test_day, $this->getStartTimestamp()); if ($shows) { // we can skip a month $next_test_day = strtotime('+1 month', $test_day); } } break; case Util::FREQUENCY_YEARLY: $shows = Util::isOnSameDayOfYear($test_day, $this->getStartTimestamp()); if ($shows) { // we can skip a year $next_test_day = strtotime('+1 year', $test_day); } break; } if ($shows) { $occurrence = (int) Util::getTimeOfDay($this->getStartTimestamp(), $test_day); if ($occurrence >= $starttime && $occurrence <= $endtime) { // events may show on a start or end day, but not fall in the time range array_push($start_times, $occurrence); } } $test_day = $next_test_day; } $cancelled = $this->cancelled_instance; if (!$cancelled) { $cancelled = array(); } if (!is_array($cancelled)) { $cancelled = array($cancelled); } return array_diff($start_times, $cancelled); }