/** * takes care of the recurrence of events */ static function generate_events($table, $exdates = false, $holidays = false) { # include route require_once JPATH_COMPONENT_SITE . '/helpers/route.php'; $jemsettings = JemHelper::config(); $weekstart = $jemsettings->weekdaystart; $anticipation = $jemsettings->recurrence_anticipation; ##################### ## Reference table ## ##################### # this is the events-table and will be used as base # define variables $id = $table->id; $times = $table->times; $endtimes = $table->endtimes; $dates = $table->dates; $enddates = $table->enddates; $recurrence_count = $table->recurrence_count; $recurrence_freq = $table->recurrence_freq; $recurrence_interval = $table->recurrence_interval; $recurrence_until = $table->recurrence_until; $recurrence_weekday = $table->recurrence_weekday; $recurrence_group = $table->recurrence_group; # select all the data from the event and make an array of it # this info will be used for the generated events. $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select('*'); $query->from($db->quoteName('#__jem_events')); $query->where('id = ' . $table->id); $db->setQuery($query); $reference = $db->loadAssoc(); $rruledatetime1 = new DateTime($dates); $rruledatetime2 = new DateTime($recurrence_until); $rruleinterval = $rruledatetime1->diff($rruledatetime2); $rruleDiff = $rruleinterval->format('%a'); if ($anticipation <= $rruleDiff) { $jdate2 = new JDate($dates); $var9 = '+' . $anticipation . ' days'; $anticipationDate = $jdate2->modify($var9); $rruleUntilLimit = $anticipationDate; } else { $rruleUntilLimit = $recurrence_until; } # Check if startdate is before limitdate if (strtotime($dates) <= strtotime($rruleUntilLimit)) { # combine startdate + time if (empty($times)) { $times = '00:00:00'; } $startDateTime = $dates . ' ' . $times; if (empty($enddates)) { $enddates = $dates; } # combine enddate + time if (empty($endtimes)) { $endtimes = '00:00:00'; } $endDateTime = $enddates . ' ' . $endtimes; # Calculate time difference, for enddate $datetime1 = new DateTime($startDateTime); $datetime2 = new DateTime($endDateTime); $interval = $datetime1->diff($datetime2); $diffYear = $interval->format('%y'); $diffMonth = $interval->format('%m'); $diffDay = $interval->format('%d'); $diffHour = $interval->format('%h'); $diffMinutes = $interval->format('%i'); $diffSeconds = $interval->format('%s'); $diffDays = $interval->format('days'); $formatDifference = 'P' . $diffYear . 'Y' . $diffMonth . 'M' . $diffDay . 'DT' . $diffHour . 'H' . $diffMinutes . 'M' . $diffSeconds . 'S'; $jdate1 = new JDate($rruleUntilLimit); $year1 = $jdate1->format('Y'); $month1 = $jdate1->format('m'); $day1 = $jdate1->format('d'); $hour1 = $jdate1->format('H'); $minutes1 = $jdate1->format('i'); $seconds1 = $jdate1->format('s'); $limit_date2 = $year1 . $month1 . $day1 . 'T235959Z'; # Define FREQ switch ($recurrence_freq) { case "1": $freq = 'DAILY'; break; case "2": $freq = 'WEEKLY'; break; case "3": $freq = 'MONTHLY'; break; case "4": $freq = 'YEARLY'; break; default: $freq = ''; } # let's check if the user did select a weekday if ($recurrence_weekday) { $rrule = 'FREQ=' . $freq . ';INTERVAL=' . $recurrence_interval . ';UNTIL=' . $limit_date2 . ';BYDAY=' . $recurrence_weekday; } else { $rrule = 'FREQ=' . $freq . ';INTERVAL=' . $recurrence_interval . ';UNTIL=' . $limit_date2; } # Get new dates $timezone = JemHelper::getTimeZoneName(); $startDate = new DateTime($startDateTime, new DateTimeZone($timezone)); #################### ## RECURR - CLASS ## #################### $rule = new RecurrenceRule($rrule, $startDate, $timezone); $transformer = new RecurrenceRuleTransformer($rule); # here we've the new dates $newEventArray = $transformer->getComputedArray(); # output is like: # # array # - public 'Date' # - public 'timezone_type' # - public 'timezone' ######### ## END ## ######### $newArray = array(); foreach ($newEventArray as $newEvent) { $date = $newEvent->format('Y-m-d'); $enddate = new DateTime($date); $enddate->add(new DateInterval($formatDifference)); $var2 = $enddate->format('Y-m-d'); if ($date != $dates) { $item = array('startDate' => $date, 'endDate' => $var2); $newArray[] = $item; } } $newArray2 = array(); foreach ($newEventArray as $newEvent2) { $date2 = $newEvent2->format('Y-m-d'); $enddate2 = new DateTime($date2); $enddate2->add(new DateInterval($formatDifference)); $var22 = $enddate2->format('Y-m-d'); if ($date2 != $dates) { $newArray2[] = $date2; } } # retrieve first+last startdate of the array $date_first_calculated_occurrence = reset($newArray2); $date_last_calculated_occurrence = end($newArray2); ########################### ## IGNORE DATES: HOLIDAY ## ########################### /* $currenttime = new JDate(); $year = $currenttime->format('Y'); */ if ($holidays) { $currenttime = new JDate(); $year = $currenttime->format('Y'); $format = 'd-m-Y'; $holiday_array = array(); foreach ($holidays as $holiday) { $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select('*'); $query->from($db->quoteName('#__jem_dates')); $query->where(array('id = ' . $holiday, 'holiday =' . $db->quote('1'))); $db->setQuery($query); $reference2 = $db->loadAssoc(); if ($reference2['date_startdate_range']) { # If we're dealing with a range we've to calculate things $start_range_input = $reference2['date_startdate_range']; $end_range_input = $reference2['date_enddate_range']; $start_range_parsed = date_parse($start_range_input); $end_range_parsed = date_parse($end_range_input); if (checkdate($start_range_parsed["month"], $start_range_parsed["day"], $start_range_parsed["year"]) && !$start_range_parsed["errors"] && checkdate($end_range_parsed["month"], $end_range_parsed["day"], $end_range_parsed["year"]) && !$end_range_parsed["errors"]) { # at this point we made sure we're dealing with valid start+enddates # now we're making a DateTimeperiod $begin2 = new DateTime($start_range_input); $end2 = new DateTime($end_range_input); $end2 = $end2->modify('+1 day'); $interval2 = new DateInterval('P1D'); $daterange2 = new DatePeriod($begin2, $interval2, $end2); foreach ($daterange2 as $exdate2) { $holiday_array[] = $exdate2->format("Y-m-d"); } } } else { # If we're dealing with a single_date we can use the date supplied $holiday_array[] = $reference2['date']; } } // end foreach # it's possible to have duplicates so we've to make the array Unique $holiday_array = array_unique($holiday_array); } // end holiday-check #################################################### ## IGNORE DATES: FORM FIELD (exdates), NO HOLIDAY ## #################################################### # basically we add all occurrences of the set to the database but the unneeded ones will # get a 1 in the ignore field. Those events will get an exdate in the iCal RRULE output # dates provided in the exdate field if ($exdates) { # remove white space $exdates = preg_replace('/\\s+/', '', $exdates); # put the dates into an array $form_exdates_array = explode(",", $exdates); $form_exdate_output = array(); foreach ($form_exdates_array as $form_exdate) { $form_exdate_splits = explode(":", $form_exdate); $form_exdate_splits2 = array(); foreach ($form_exdate_splits as $ignoredate) { $form_exdate_splits2[] = date("Y-m-d", strtotime($ignoredate)); } foreach ($form_exdate_splits2 as $form_exdate_split) { $date = date_parse($form_exdate_split); if (checkdate($date["month"], $date["day"], $date["year"]) && !$date["errors"]) { # retrieve first+last value of the created array $first_form_exdate = reset($form_exdate_splits2); $last_form_exdate = end($form_exdate_splits2); # now we're making a DateTimeperiod $begin = new DateTime($first_form_exdate); $end = new DateTime($last_form_exdate); $end = $end->modify('+1 day'); $interval = new DateInterval('P1D'); $daterange = new DatePeriod($begin, $interval, $end); foreach ($daterange as $exdate) { $form_exdate_output[] = $exdate->format("Y-m-d"); } } } } # check for duplicates $form_exdate_output = array_unique($form_exdate_output); } // end check exdates ##################################### ## IGNORE-DATES: TABLE, NO HOLIDAY ## ##################################### ## select dates from the date-table, within the calculated range $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select('date'); $query->from($db->quoteName('#__jem_dates')); $query->where(array('enabled = 1', 'holiday <> 1', 'date >= ' . $db->Quote($date_first_calculated_occurrence), 'date <= ' . $db->Quote($date_last_calculated_occurrence))); $db->setQuery($query); $dateTable = $db->loadColumn(); if ($dateTable) { $excluded_dates = $dateTable; } else { $excluded_dates = array(); } ########################################### ## IGNORE-DATES: CREATE ARRAY, INTERSECT ## ########################################### ## $newArray2 = generated values // Y-m-d ## $excluded_dates = single-dates from table, no holiday # we will be making an array that contains the values that are present in exluded_dates + generated_dates # this makes sure that the excluded dates are actually in the range of the generating part $exclude_date_array = array_intersect($newArray2, $excluded_dates); # if the exdate form is field we will do a second round if ($exdates) { $exclude_exdate_form = array_intersect($newArray2, $form_exdate_output); } else { $exclude_exdate_form = false; } # If a holiday has been selected we will even do a third round if ($holidays) { $exclude_exdate_holiday = array_intersect($newArray2, $holiday_array); } else { $exclude_exdate_holiday = false; } ###################################### ## IGNORE-DATES: CREATE ARRAY, DIFF ## ###################################### # create array with only the dates we want to have $array_input = $newArray2; $array_to_remove = $exclude_date_array; $array_output = array_diff($array_input, $array_to_remove); if ($exdates && !$holidays) { # exdate field has been filled $array_input_form = $array_output; $array_to_remove_form = $exclude_exdate_form; $generating_array = array_diff($array_input_form, $array_to_remove_form); } if (!$exdates && $holidays) { # holiday field has been filled $array_input_form = $array_output; $array_to_remove_form = $exclude_exdate_holiday; $generating_array = array_diff($array_input_form, $array_to_remove_form); } if ($exdates && $holidays) { # both fields have been filled # in this case we've to merge both arrays and check for duplicates $exdates_holidays_combined = array_merge($exclude_exdate_holiday, $exclude_exdate_form); $exdates_holidays_combined_unique = array_unique($exdates_holidays_combined); $array_input_form = $array_output; $array_to_remove_form = $exdates_holidays_combined_unique; $generating_array = array_diff($array_input_form, $array_to_remove_form); } if (!$exdates && !$holidays) { # no fields have been filled $generating_array = $array_output; } $new_generating_array = array(); foreach ($generating_array as $generated) { $generated_enddate = new DateTime($generated); $generated_enddate->add(new DateInterval($formatDifference)); $var2a = $generated_enddate->format('Y-m-d'); $item2 = array('startDate' => $generated, 'endDate' => $var2a); $new_generating_array[] = $item2; } ############# ## EXDATES ## ############# # do we have an array with dates to ignore? # if yes we need to input the dates as exdate value in the master-table if ($exclude_date_array) { $exdate_date_array = $exclude_date_array; } else { $exdate_date_array = array(); } if ($exclude_exdate_form) { $exdate_exdate_form = $exclude_exdate_form; } else { $exdate_exdate_form = array(); } if ($exclude_exdate_holiday) { $exdate_exdate_holiday = $exclude_exdate_holiday; } else { $exdate_exdate_holiday = array(); } $exdates_input = array_merge($exdate_date_array, $exdate_exdate_form, $exdate_exdate_holiday); $exdates_unique = array_unique($exdates_input); if ($exdates_unique) { $exdates = json_encode($exdates_unique); } else { $exdates = ''; } ####################################################### ## Store the first occurence to the Recurrence table ## ####################################################### $first_event_recurrence = JTable::getInstance('Recurrence', 'JEMTable'); $first_event_recurrence->itemid = $table->id; $first_event_recurrence->groupid = $table->recurrence_group; $first_event_recurrence->groupid_ref = $table->recurrence_group; $first_event_recurrence->interval = $table->recurrence_interval; $first_event_recurrence->freq = $freq; $first_event_recurrence->startdate_org = $startDateTime; $first_event_recurrence->enddate_org = $endDateTime; $first_event_recurrence->wholeday = $table->wholeday; $var2 = $first_event_recurrence->startdate_org; $var3 = new JDate($var2); $var4 = $var3->format('Ymd\\THis\\Z'); $first_event_recurrence->recurrence_id = $var4; $first_event_recurrence->store(); ############################################################## ## Store the first occurence to the Recurrence-Master table ## ############################################################## # define link $master_link = JRoute::_(JURI::root() . JemHelperRoute::getEventRoute($table->id . ':' . $table->alias)); # Retrieve venue + countryname $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select('l.venue, l.city, l.state, l.url, l.street,ct.name AS countryname'); $query->from($db->quoteName('#__jem_events', 'a')); $query->join('LEFT', '#__jem_venues AS l ON l.id = a.locid'); $query->join('LEFT', '#__jem_countries AS ct ON ct.iso2 = l.country'); $query->join('LEFT', '#__jem_cats_event_relations AS rel ON rel.itemid = a.id'); $query->join('LEFT', '#__jem_categories AS c ON c.id = rel.catid'); $query->where(array('a.id =' . $table->id)); $db->setQuery($query); $event_venuecountry = $db->loadObject(); # define location array $location = array(); if (isset($event_venuecountry->venue) && !empty($event_venuecountry->venue)) { $location[] = $event_venuecountry->venue; } if (isset($event_venuecountry->city) && !empty($event_venuecountry->city)) { $location[] = $event_venuecountry->city; } if (isset($event_venuecountry->state) && !empty($event_venuecountry->state)) { $location[] = $event_venuecountry->state; } if (isset($event_venuecountry->url) && !empty($event_venuecountry->url)) { $location[] = $event_venuecountry->url; } if (isset($event_venuecountry->street) && !empty($event_venuecountry->street)) { $location[] = $event_venuecountry->street; } if (isset($event_venuecountry->countryname) && !empty($event_venuecountry->countryname)) { $exp = explode(",", $event_venuecountry->countryname); $location[] = $exp[0]; } $location = implode(",", $location); # retrieve categories $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select('c.id,c.catname'); $query->from($db->quoteName('#__jem_events', 'a')); $query->join('LEFT', '#__jem_venues AS l ON l.id = a.locid'); $query->join('LEFT', '#__jem_countries AS ct ON ct.iso2 = l.country'); $query->join('LEFT', '#__jem_cats_event_relations AS rel ON rel.itemid = a.id'); $query->join('LEFT', '#__jem_categories AS c ON c.id = rel.catid'); $query->where(array('a.id =' . $table->id)); $db->setQuery($query); $event_categories = $db->loadObjectList(); # create array with category id's $categories = array(); foreach ($event_categories as $c) { $categories[] = $c->id; } # define fields $rec_master = JTable::getInstance('Recurrence_master', 'JEMTable'); $rec_master->itemid = $table->id; $rec_master->groupid = $table->recurrence_group; $rec_master->groupid_ref = $table->recurrence_group; $rec_master->interval = $table->recurrence_interval; $rec_master->freq = $freq; $rec_master->startdate_org = $startDateTime; $rec_master->enddate_org = $endDateTime; $rec_master->exdates = $exdates; $rec_master->store(); ####################################### ## Bind & Store the generated values ## ####################################### foreach ($new_generating_array as $value) { # load tables $new_event = JTable::getInstance('Events', 'JEMTable'); $new_event_recurrence = JTable::getInstance('Recurrence', 'JEMTable'); # bind reference-values + strip out individual fields $new_event->bind($reference, array('id', 'hits', 'dates', 'enddates', 'checked_out_time', 'checked_out')); # define new startdate + enddate $new_event->dates = $value['startDate']; $new_event->enddates = $value['endDate']; # define ical settings $new_event->recurrence_until = $rruleUntilLimit; $new_event->recurrence_count = $recurrence_count; $new_event->recurrence_interval = $recurrence_interval; $new_event->recurrence_freq = $freq; if ($recurrence_weekday) { $new_event->recurrence_weekday = $recurrence_weekday; } # store event if ($new_event->store()) { # combine startdate+time if (empty($new_event->times)) { $new_event->times = '00:00:00'; } $newevent_startDateTime = $new_event->dates . ' ' . $new_event->times; if (empty($new_event->enddates)) { $new_event->enddates = $new_event->dates; } # combine enddate + time if (empty($new_event->endtimes)) { $new_event->endtimes = '00:00:00'; } $newevent_endDateTime = $new_event->enddates . ' ' . $new_event->endtimes; # store generated event-info into recurrence_table $new_event_recurrence->itemid = $new_event->id; $new_event_recurrence->groupid = $recurrence_group; $new_event_recurrence->groupid_ref = $recurrence_group; $new_event_recurrence->interval = $recurrence_interval; $new_event_recurrence->startdate_org = $newevent_startDateTime; $new_event_recurrence->enddate_org = $newevent_endDateTime; $new_event_recurrence->freq = $freq; $new_event_recurrence->wholeday = $new_event->wholeday; $var5 = $new_event_recurrence->startdate_org; $var6 = new JDate($var5); $var7 = $var3->format('Ymd\\THis\\Z'); $new_event_recurrence->recurrence_id = $var7; $new_event_recurrence->store(); $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select(array('catid')); $query->from($db->quoteName('#__jem_cats_event_relations')); $query->where('itemid = ' . $table->id); $db->setQuery($query); $cats = $db->loadColumn(0); foreach ($cats as $cat) { $db = JFactory::getDbo(); $query = $db->getQuery(true); // Insert columns. $columns = array('catid', 'itemid'); // Insert values. $values = array($cat, $new_event->id); // Prepare the insert query. $query->insert($db->quoteName('#__jem_cats_event_relations'))->columns($db->quoteName($columns))->values(implode(',', $values)); // Reset the query using our newly populated query object. $db->setQuery($query); $db->execute(); } } } } // end adding new Events }
/** * processEntity * This function is responsible for taking a ScheduleEntity object * and generating up to $maxInstances ScheduleInstance objects from it. * * @param ScheduleEntity $scheduleEntity * @param mixed $maxInstances * @access public * @return void */ public function processEntity(ScheduleEntity $scheduleEntity, $maxInstances = null) { if (is_null($maxInstances)) { $maxInstances = $this->maxInstances; } if ($maxInstances > $this->maxInstances) { $maxInstances = $this->maxInstances; } // get rrule $timezone = 'America/New_York'; $today = new \DateTime(); $dateTimeZone = new \DateTimeZone($timezone); if ($scheduleEntity->getRrule()) { // Handling a recurring event $rrule = new RecurrenceRule($scheduleEntity->getRrule(), $scheduleEntity->getStartAt(), $timezone); $transformer = new RecurrenceRuleTransformer($rrule); $instances = $transformer->getComputedArray($scheduleEntity->getStartAt(), $dateTimeZone, $today->add(new \DateInterval('P6M')), $dateTimeZone); $options = $scheduleEntity->getOptions(); // generate instances if (count($instances)) { $count = 0; foreach ($instances as $startDateTime) { if ($count < $maxInstances) { // compute endDateTime based on duration $endDateTime = clone $startDateTime; $endDateTime->add(new \DateInterval($scheduleEntity->getDuration())); $si = new ScheduleInstance(); $si->setScheduleEntity($scheduleEntity); $si->setUser($scheduleEntity->getUser()); $si->setSchool($scheduleEntity->getSchool()); $si->setTitle($scheduleEntity->getTitle()); $si->setStart($startDateTime); $si->setEnd($endDateTime); $si->setIsAllDay(in_array('all_day', $scheduleEntity->getOptions())); $lastEnd = $endDateTime; $this->em->persist($si); $count++; } } } else { $instances = array(null); } $lastInstance = array_pop($instances); } else { // Handling a non-recurring event $si = new ScheduleInstance(); $si->setScheduleEntity($scheduleEntity); $si->setUser($scheduleEntity->getUser()); $si->setSchool($scheduleEntity->getSchool()); $si->setTitle($scheduleEntity->getTitle()); $si->setStart($scheduleEntity->getStartAt()); $si->setEnd($scheduleEntity->getEndAt()); $si->setIsAllDay(in_array('all_day', $scheduleEntity->getOptions())); $this->em->persist($si); // $lastEnd = $lastInstance = $scheduleEntity->getStartAt()->add(new \DateInterval($scheduleEntity->getDuration())); } // update last_processed // $scheduleEntity->setLastProcessedAt(new \DateTime()); // update expireAt // $scheduleEntity->setExpiresAt($lastEnd); // update maxDateAt // $scheduleEntity->setMaxDateAt($lastInstance); // $this->em->persist($scheduleEntity); $this->em->flush(); }
private function generateDates($rrule, $id, $repeats, $start, $end) { $finalDates = array(); $start = DateTime::createFromString($start, craft()->getTimeZone()); if (!is_null($end)) { $end = DateTime::createFromString($end, craft()->getTimeZone()); } if ($repeats) { $rule = new Recurr\RecurrenceRule($rrule); $ruleTransformer = new Recurr\RecurrenceRuleTransformer($rule, 300); $dates = $ruleTransformer->getComputedArray(); if (!is_null($end)) { $durationInterval = $start->diff($end); } else { $durationInterval = $start->diff($start); } $fullDates = array(); foreach ($dates as $date) { $end = clone $date; $end = $end->add($durationInterval); $startDateString = $date->format('Ymd\\THis'); $endDateString = $end->format('Ymd\\THis'); $datesValues['start'] = DateTime::createFromFormat('Ymd\\THis', $startDateString, craft()->getTimeZone()); if (!empty($end)) { $datesValues['end'] = DateTime::createFromFormat('Ymd\\THis', $endDateString, craft()->getTimeZone()); } $fullDates[] = $datesValues; } $finalDates = $fullDates; } else { $finalDates = array(array('start' => $start, 'end' => $end)); } foreach ($finalDates as $index => $date) { $dateRecord = new RecurringDate_DateRecord(); $dateRecord->setAttributes(array('ruleId' => $id, 'start' => $date['start'], 'end' => $date['end']), false); $dateRecord->save(); } }