diff options
Diffstat (limited to 'app/Model/Timetable.php')
-rw-r--r-- | app/Model/Timetable.php | 356 |
1 files changed, 0 insertions, 356 deletions
diff --git a/app/Model/Timetable.php b/app/Model/Timetable.php deleted file mode 100644 index 6ddf826b..00000000 --- a/app/Model/Timetable.php +++ /dev/null @@ -1,356 +0,0 @@ -<?php - -namespace Model; - -use DateTime; -use DateInterval; - -/** - * Timetable - * - * @package model - * @author Frederic Guillot - */ -class Timetable extends Base -{ - /** - * User time slots - * - * @access private - * @var array - */ - private $day; - private $week; - private $overtime; - private $timeoff; - - /** - * Get a set of events by using the intersection between the timetable and the time tracking data - * - * @access public - * @param integer $user_id - * @param array $events Time tracking data - * @param string $start ISO8601 date - * @param string $end ISO8601 date - * @return array - */ - public function calculateEventsIntersect($user_id, array $events, $start, $end) - { - $start_dt = new DateTime($start); - $start_dt->setTime(0, 0); - - $end_dt = new DateTime($end); - $end_dt->setTime(23, 59); - - $timetable = $this->calculate($user_id, $start_dt, $end_dt); - - // The user has no timetable - if (empty($this->week)) { - return $events; - } - - $results = array(); - - foreach ($events as $event) { - $results = array_merge($results, $this->calculateEventIntersect($event, $timetable)); - } - - return $results; - } - - /** - * Get a serie of events based on the timetable and the provided event - * - * @access public - * @param array $event - * @param array $timetable - * @return array - */ - public function calculateEventIntersect(array $event, array $timetable) - { - $events = array(); - - foreach ($timetable as $slot) { - - $start_ts = $slot[0]->getTimestamp(); - $end_ts = $slot[1]->getTimestamp(); - - if ($start_ts > $event['end']) { - break; - } - - if ($event['start'] <= $start_ts) { - $event['start'] = $start_ts; - } - - if ($event['start'] >= $start_ts && $event['start'] <= $end_ts) { - - if ($event['end'] >= $end_ts) { - $events[] = array_merge($event, array('end' => $end_ts)); - } - else { - $events[] = $event; - break; - } - } - } - - return $events; - } - - /** - * Calculate effective worked hours by taking into consideration the timetable - * - * @access public - * @param integer $user_id - * @param \DateTime $start - * @param \DateTime $end - * @return float - */ - public function calculateEffectiveDuration($user_id, DateTime $start, DateTime $end) - { - $end_timetable = clone($end); - $end_timetable->setTime(23, 59); - - $timetable = $this->calculate($user_id, $start, $end_timetable); - $found_start = false; - $hours = 0; - - // The user has no timetable - if (empty($this->week)) { - return $this->dateParser->getHours($start, $end); - } - - foreach ($timetable as $slot) { - - $isStartSlot = $this->dateParser->withinDateRange($start, $slot[0], $slot[1]); - $isEndSlot = $this->dateParser->withinDateRange($end, $slot[0], $slot[1]); - - // Start and end are within the same time slot - if ($isStartSlot && $isEndSlot) { - return $this->dateParser->getHours($start, $end); - } - - // We found the start slot - if (! $found_start && $isStartSlot) { - $found_start = true; - $hours = $this->dateParser->getHours($start, $slot[1]); - } - else if ($found_start) { - - // We found the end slot - if ($isEndSlot) { - $hours += $this->dateParser->getHours($slot[0], $end); - break; - } - else { - - // Sum hours of the intermediate time slots - $hours += $this->dateParser->getHours($slot[0], $slot[1]); - } - } - } - - // The start date was not found in regular hours so we get the nearest time slot - if (! empty($timetable) && ! $found_start) { - $slot = $this->findClosestTimeSlot($start, $timetable); - - if ($start < $slot[0]) { - return $this->calculateEffectiveDuration($user_id, $slot[0], $end); - } - } - - return $hours; - } - - /** - * Find the nearest time slot - * - * @access public - * @param DateTime $date - * @param array $timetable - * @return array - */ - public function findClosestTimeSlot(DateTime $date, array $timetable) - { - $values = array(); - - foreach ($timetable as $slot) { - $t1 = abs($slot[0]->getTimestamp() - $date->getTimestamp()); - $t2 = abs($slot[1]->getTimestamp() - $date->getTimestamp()); - - $values[] = min($t1, $t2); - } - - asort($values); - return $timetable[key($values)]; - } - - /** - * Get the timetable for a user for a given date range - * - * @access public - * @param integer $user_id - * @param \DateTime $start - * @param \DateTime $end - * @return array - */ - public function calculate($user_id, DateTime $start, DateTime $end) - { - $timetable = array(); - - $this->day = $this->timetableDay->getByUser($user_id); - $this->week = $this->timetableWeek->getByUser($user_id); - $this->overtime = $this->timetableExtra->getByUserAndDate($user_id, $start->format('Y-m-d'), $end->format('Y-m-d')); - $this->timeoff = $this->timetableOff->getByUserAndDate($user_id, $start->format('Y-m-d'), $end->format('Y-m-d')); - - for ($today = clone($start); $today <= $end; $today->add(new DateInterval('P1D'))) { - $week_day = $today->format('N'); - $timetable = array_merge($timetable, $this->getWeekSlots($today, $week_day)); - $timetable = array_merge($timetable, $this->getOvertimeSlots($today, $week_day)); - } - - return $timetable; - } - - /** - * Return worked time slots for the given day - * - * @access public - * @param \DateTime $today - * @param string $week_day - * @return array - */ - public function getWeekSlots(DateTime $today, $week_day) - { - $slots = array(); - $dayoff = $this->getDayOff($today); - - if (! empty($dayoff) && $dayoff['all_day'] == 1) { - return array(); - } - - foreach ($this->week as $slot) { - if ($week_day == $slot['day']) { - $slots = array_merge($slots, $this->getDayWorkSlots($slot, $dayoff, $today)); - } - } - - return $slots; - } - - /** - * Get the overtime time slots for the given day - * - * @access public - * @param \DateTime $today - * @param string $week_day - * @return array - */ - public function getOvertimeSlots(DateTime $today, $week_day) - { - $slots = array(); - - foreach ($this->overtime as $slot) { - - $day = new DateTime($slot['date']); - - if ($week_day == $day->format('N')) { - - if ($slot['all_day'] == 1) { - $slots = array_merge($slots, $this->getDaySlots($today)); - } - else { - $slots[] = $this->getTimeSlot($slot, $day); - } - } - } - - return $slots; - } - - /** - * Get worked time slots and remove time off - * - * @access public - * @param array $slot - * @param array $dayoff - * @param \DateTime $today - * @return array - */ - public function getDayWorkSlots(array $slot, array $dayoff, DateTime $today) - { - $slots = array(); - - if (! empty($dayoff) && $dayoff['start'] < $slot['end']) { - - if ($dayoff['start'] > $slot['start']) { - $slots[] = $this->getTimeSlot(array('end' => $dayoff['start']) + $slot, $today); - } - - if ($dayoff['end'] < $slot['end']) { - $slots[] = $this->getTimeSlot(array('start' => $dayoff['end']) + $slot, $today); - } - } - else { - $slots[] = $this->getTimeSlot($slot, $today); - } - - return $slots; - } - - /** - * Get regular day work time slots - * - * @access public - * @param \DateTime $today - * @return array - */ - public function getDaySlots(DateTime $today) - { - $slots = array(); - - foreach ($this->day as $day) { - $slots[] = $this->getTimeSlot($day, $today); - } - - return $slots; - } - - /** - * Get the start and end time slot for a given day - * - * @access public - * @param array $slot - * @param \DateTime $today - * @return array - */ - public function getTimeSlot(array $slot, DateTime $today) - { - $date = $today->format('Y-m-d'); - - return array( - new DateTime($date.' '.$slot['start']), - new DateTime($date.' '.$slot['end']), - ); - } - - /** - * Return day off time slot - * - * @access public - * @param \DateTime $today - * @return array - */ - public function getDayOff(DateTime $today) - { - foreach ($this->timeoff as $day) { - - if ($day['date'] === $today->format('Y-m-d')) { - return $day; - } - } - - return array(); - } -} |