summaryrefslogtreecommitdiff
path: root/app/Model/Timetable.php
diff options
context:
space:
mode:
authorFrederic Guillot <fred@kanboard.net>2015-09-20 18:24:15 -0400
committerFrederic Guillot <fred@kanboard.net>2015-09-20 18:24:15 -0400
commite6f547abcfe684658a7498391db72d13b6aa7d9a (patch)
tree75b709c12fb03e11d7cb85558558f89f19abb284 /app/Model/Timetable.php
parent2021dccc5a444f60c5ba1673d94b39999912cd26 (diff)
Move timetable to a plugin
Plugin repository: https://github.com/kanboard/plugin-timetable
Diffstat (limited to 'app/Model/Timetable.php')
-rw-r--r--app/Model/Timetable.php356
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();
- }
-}