/** * get all repeating events/bookings? * TODO: change function name, in a distinct view bookings are events too * use constants for repeat ids (better readable) * * Maybe rewrite function: * look at php date objects like DatePeriod, DateInterval: * $period = new DatePeriod($start, $interval, $recurrences); * foreach ($period as $date) { * echo $date->format('Y-m-d')."\n"; * } * you can use dates like "first tuesday of july 2008", "next Monday 2012-04-01" * http://de1.php.net/manual/de/datetime.formats.relative.php * * @param object $r * @param int $_from; default: -1, days to add to fromDate * @param int $_to; default: 1, days to add to fromDate * @return */ function getAllDatesWithRepeats($r, $_from = -1, $_to = 1, $fromDate = null) { // $dates later will contain all date occurence. $dates = array(); // $max prevents an endless loop on erors $max = 999; if ($fromDate == null) { $fromDate = new DateTime(); } else { $fromDate = new DateTime($fromDate->format('d.m.Y')); } $to = new DateTime($fromDate->format('d.m.Y H:i')); $fromDate->modify("+{$_from} days"); $to->modify("+{$_to} days"); $r->startdate = new DateTime($r->startdate instanceof DateTime ? $r->startdate->format('d.m.Y H:i') : $r->startdate); $d = clone $r->startdate; $r->enddate = new DateTime($r->enddate instanceof DateTime ? $r->enddate->format('d.m.Y H:i') : $r->enddate); $e = clone $r->enddate; if (!isset($r->repeat_until)) { $r->repeat_until = $d->format("d.m.Y H:i"); } $repeat_until = new DateTime($r->repeat_until); $repeat_until = $repeat_until->modify('+1 day'); // include given day! if ($to < $repeat_until) { $repeat_until = $to; } if (!empty($r->additions)) { $additions = $r->additions; } else { $additions = array(); } // Add addition date for Start date, so we only need one foreach loop $my = new stdClass(); $my->add_date = $d->format('d.m.Y H:i'); $my->with_repeat_yn = 1; $additions[0] = $my; // array_unshift($additions, $my); // print_r($additions); foreach ($additions as $key => $add_unkownFormat) { $add = (object) $add_unkownFormat; // Parameter can be Arrays from HTTP Input or Objects from DB $d = new DateTime(substr($add->add_date, 0, 10) . " " . $d->format('H:i:s')); $e = new DateTime(substr($add->add_date, 0, 10) . " " . $e->format('H:i:s')); // Mark exception as used, so datesInConflict() will be called only for new exceptions to save time! if (!empty($r->exceptions)) { foreach ($r->exceptions as $key => $exc) { if (is_array($r->exceptions[$key])) { $r->exceptions[$key] = (object) $r->exceptions[$key]; } $r->exceptions[$key]->used = false; } } do { $exception = false; if (!empty($r->exceptions)) { foreach ($r->exceptions as $exc) { // if exception is not used proof conflict with exception date if (!$exception && !$exc->used && datesInConflict(new DateTime($exc->except_date_start), new DateTime($exc->except_date_end), $d, $e)) { $exception = true; $exc->used = true; } } } if (!$exception) { //why two ifs? if ($d <= $fromDate && $e >= $fromDate || $e >= $fromDate && $e <= $to) { $dates[] = new DateTime($d->format('Y-m-d H:i:s')); } } // f.e. each second week is 7*2 => 14 days if ($r->repeat_id == 1 || $r->repeat_id == 7) { $repeat = $r->repeat_id * $r->repeat_frequence; $d->modify("+{$repeat} days"); $e->modify("+{$repeat} days"); } else { if ($r->repeat_id == 31) { $counter = 0; do { $tester = new DateTime($d->format('Y-m-d H:i:s')); $modify = "+ " . ($counter + 1 * $r->repeat_frequence) . " month"; $tester->modify($modify); if ($tester->format('d') == $d->format('d')) { $d->modify($modify); $e->modify($modify); $counter = 999; //TODO: why not using break here? } $counter = $counter + 1; } while ($counter < 99); } else { if ($r->repeat_id == 32) { // first find last weekday if ($r->repeat_option_id == 6) { // go some days back, so we dont jump into the next month and therefor miss one month $d->modify("- 5 days"); $e->modify("- 5 days"); // add months $d->modify("+ " . (1 + 1 * $r->repeat_frequence) . " month"); // what means 1 + 1 * x? $e->modify("+ " . (1 + 1 * $r->repeat_frequence) . " month"); // first go back to first day of month //TODO: use sort of $d->setDate(2014, 12, 1) and calculate value for $e?; while ($d->format('d') > 1) { $d->modify("-1 day"); $e->modify("-1 day"); } $d->modify("-1 day"); $e->modify("-1 day"); // then search for same weekday while ($d->format('N') != $r->startdate->format('N')) { $d->modify("-1 day"); $e->modify("-1 day"); } } else { $counter = 0; // add months $d->setDate($d->format('Y'), $d->format('m') + 1 * $r->repeat_frequence, 0); $e->setDate($e->format('Y'), $e->format('m') + 1 * $r->repeat_frequence, 0); while ($counter < $r->repeat_option_id) { $m = $d->format("m"); $d->modify("+1 day"); $e->modify("+1 day"); // test if jumped in next month, then the month has to few days and the event is dropped, f.e. on 5th // weekday/month if ($d->format("m") != $m) { $counter = 0; } if ($d->format("N") == $r->startdate->format("N")) { $counter = $counter + 1; } } } } else { if ($r->repeat_id == 365) { $counter = 0; $d->modify("+ " . ($counter + 1 * $r->repeat_frequence) . " year"); $e->modify("+ " . ($counter + 1 * $r->repeat_frequence) . " year"); } } } } $max = $max - 1; if ($max == 0) { addErrorMessage("Zu viele Wiederholungen in getAllDatesWithRepeats! [{$r->id}]"); return false; } } while ($d < $repeat_until && $add->with_repeat_yn == 1 && isset($r->repeat_id) && $r->repeat_id > 0 && isset($r->repeat_frequence) && $r->repeat_frequence > 0); } return $dates; }
function getAllDatesWithRepeats($r, $_von = -1, $_bis = 1) { // $dates later will contain all date occurence. $dates = array(); // $max prevents an endless loop on erors $max = 999; $from = new DateTime(); $from->modify("+{$_von} days"); $to = new DateTime(); $to->modify("+{$_bis} days"); $d = new DateTime($r->startdate->format('d.m.Y H:i')); $e = new DateTime($r->enddate->format('d.m.Y H:i')); $repeat_until = new DateTime($r->repeat_until); $repeat_until = $repeat_until->modify('+1 day'); // Da der Tag ja mit gelten soll! if ($to < $repeat_until) { $repeat_until = $to; } if (isset($r->additions)) { $additions = $r->additions; } else { $additions = array(); } $my = new stdClass(); $my->add_date = $d->format('d.m.Y H:i'); $my->with_repeat_yn = 1; $additions[0] = $my; //array_unshift($additions, $my); foreach ($additions as $key => $add) { $d = new DateTime(substr($add->add_date, 0, 10) . " " . $d->format('H:i:s')); $e = new DateTime(substr($add->add_date, 0, 10) . " " . $e->format('H:i:s')); // Mark exception as used, so the "datesInConflict" will be called only for fresh exceptions to save time! if (isset($r->exceptions)) { foreach ($r->exceptions as $exc) { $exc->used = false; } } do { $exception = false; if (isset($r->exceptions)) { foreach ($r->exceptions as $exc) { // if exception is not used then proof conflict with exception date if (!$exception && !$exc->used && datesInConflict(new DateTime($exc->except_date_start), new DateTime($exc->except_date_end), $d, $e)) { $exception = true; $exc->used = true; } } } if (!$exception) { if ($d <= $from && $e >= $from || $e >= $from && $e <= $to) { $dates[] = new DateTime($d->format('Y-m-d H:i:s')); } } if ($r->repeat_id == 1 || $r->repeat_id == 7) { $repeat = $r->repeat_id * $r->repeat_frequence; // f.e. each second week is 7*2 => 14 days $d->modify("+{$repeat} days"); $e->modify("+{$repeat} days"); } else { if ($r->repeat_id == 31) { $counter = 0; do { $tester = new DateTime($d->format('Y-m-d H:i:s')); $tester->modify("+ " . ($counter + 1 * $r->repeat_frequence) . " month"); if ($tester->format('d') == $d->format('d')) { $d->modify("+ " . ($counter + 1 * $r->repeat_frequence) . " month"); $e->modify("+ " . ($counter + 1 * $r->repeat_frequence) . " month"); $counter = 999; } $counter = $counter + 1; } while ($counter < 99); } else { if ($r->repeat_id == 32) { // first find last weekday if ($r->repeat_option_id == 6) { // go some days back, so we dont jump into the next month and therefor miss one month $d->modify("- 5 days"); $e->modify("- 5 days"); // add months $d->modify("+ " . (1 + 1 * $r->repeat_frequence) . " month"); $e->modify("+ " . (1 + 1 * $r->repeat_frequence) . " month"); // first go back to first day of month while ($d->format('d') > 1) { $d->modify("-1 day"); $e->modify("-1 day"); } $d->modify("-1 day"); $e->modify("-1 day"); // then search for same weekday while ($d->format('N') != $r->startdate->format('N')) { $d->modify("-1 day"); $e->modify("-1 day"); } } else { $counter = 0; // add months $d->setDate($d->format('Y'), $d->format('m') + 1 * $r->repeat_frequence, 0); $e->setDate($e->format('Y'), $e->format('m') + 1 * $r->repeat_frequence, 0); while ($counter < $r->repeat_option_id) { $m = $d->format("m"); $d->modify("+1 day"); $e->modify("+1 day"); // test if jumped in next month, then the month has to few days and the event is dropped, f.e. on 5th weekday/month if ($d->format("m") != $m) { $counter = 0; } if ($d->format("N") == $r->startdate->format("N")) { $counter = $counter + 1; } } } } else { if ($r->repeat_id == 365) { $counter = 0; $d->modify("+ " . ($counter + 1 * $r->repeat_frequence) . " year"); $e->modify("+ " . ($counter + 1 * $r->repeat_frequence) . " year"); } } } } $max = $max - 1; if ($max == 0) { addErrorMessage("Zu viele Wiederholungen in getAllDatesWithRepeats! [{$r->id}]"); return false; } } while ($d < $repeat_until && $add->with_repeat_yn == 1 && isset($r->repeat_id) && $r->repeat_id > 0 && isset($r->repeat_frequence) && $r->repeat_frequence > 0); } return $dates; }