public function getEventsNormalized(\DateTime $start_date, \DateTime $end_date, $events)
{
$normalized_events = array();
$events_copy = $events;
foreach ($events_copy as $unit_id => $data) {
// Make sure years are sorted
ksort($data[Event::BAT_DAY]);
if (isset($data[Event::BAT_HOUR])) {
ksort($data[Event::BAT_HOUR]);
}
if (isset($data[Event::BAT_MINUTE])) {
ksort($data[Event::BAT_MINUTE]);
}
// Set up variables to keep track of stuff
$current_value = NULL;
$start_event = new \DateTime();
$end_event = new \DateTime();
foreach ($data[Event::BAT_DAY] as $year => $months) {
// Make sure months are in right order
ksort($months);
foreach ($months as $month => $days) {
foreach ($days as $day => $value) {
if ($value == -1) {
// Retrieve hour data
$hour_data = $events[$unit_id][Event::BAT_HOUR][$year][$month][$day];
ksort($hour_data, SORT_NATURAL);
foreach ($hour_data as $hour => $hour_value) {
if ($hour_value == -1) {
// We are going to need minute values
$minute_data = $events[$unit_id][Event::BAT_MINUTE][$year][$month][$day][$hour];
ksort($minute_data, SORT_NATURAL);
foreach ($minute_data as $minute => $minute_value) {
if ($current_value === $minute_value) {
// We are still in minutes and going through so add a minute
$end_event->add(new \DateInterval('PT1M'));
} elseif ($current_value != $minute_value && $current_value !== NULL) {
// Value just switched - let us wrap up with current event and start a new one
$normalized_events[$unit_id][] = new Event($start_event, $end_event, $this->getUnit($unit_id), $current_value);
$start_event = clone $end_event->add(new \DateInterval('PT1M'));
$end_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . substr($hour, 1) . ':' . substr($minute, 1));
$current_value = $minute_value;
}
if ($current_value === NULL) {
// We are down to minutes and haven't created and event yet - do one now
$start_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . substr($hour, 1) . ':' . substr($minute, 1));
$end_event = clone $start_event;
}
$current_value = $minute_value;
}
} elseif ($current_value === $hour_value) {
// We are in hours and can add something
$end_event->add(new \DateInterval('PT1H'));
} elseif ($current_value != $hour_value && $current_value !== NULL) {
// Value just switched - let us wrap up with current event and start a new one
$normalized_events[$unit_id][] = new Event($start_event, $end_event, $this->getUnit($unit_id), $current_value);
// Start event becomes the end event with a minute added
$start_event = clone $end_event->add(new \DateInterval('PT1M'));
// End event comes the current point in time
$end_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . substr($hour, 1) . ':59');
$current_value = $hour_value;
}
if ($current_value === NULL) {
// Got into hours and still haven't created an event so
$start_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . substr($hour, 1) . ':00');
// We will be occupying at least this hour so might as well mark it
$end_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . substr($hour, 1) . ':59');
$current_value = $hour_value;
}
}
} elseif ($current_value === $value) {
// We are adding a whole day so the end event gets moved to the end of the day we are adding
$end_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . '23:59');
} elseif ($current_value !== $value && $current_value !== NULL) {
// Value just switched - let us wrap up with current event and start a new one
$normalized_events[$unit_id][] = new Event($start_event, $end_event, $this->getUnit($unit_id), $current_value);
// Start event becomes the end event with a minute added
$start_event = clone $end_event->add(new \DateInterval('PT1M'));
// End event becomes the current day which we have not account for yet
$end_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . '23:59');
$current_value = $value;
}
if ($current_value === NULL) {
// We have not created an event yet so let's do it now
$start_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . '00:00');
$end_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . '23:59');
$current_value = $value;
}
}
}
}
// Add the last event in for which there is nothing in the loop to catch it
$normalized_events[$unit_id][] = new Event($start_event, $end_event, $this->getUnit($unit_id), $current_value);
}
// Given the database structure we may get events that are not with the date ranges we were looking for
// We get rid of them here so that the user has a clean result.
foreach ($normalized_events as $unit_id => $events) {
foreach ($events as $key => $event) {
if ($event->overlaps($start_date, $end_date)) {
// Adjust start or end dates of events so everything is within range
if ($event->startsEarlier($start_date)) {
$event->setStartDate($start_date);
}
if ($event->endsLater($end_date)) {
$event->setEndDate($end_date);
}
} else {
// Event completely not in range so unset it
unset($normalized_events[$unit_id][$key]);
}
}
}
return $normalized_events;
}