diff options
author | Frederic Guillot <fred@kanboard.net> | 2015-09-20 18:24:15 -0400 |
---|---|---|
committer | Frederic Guillot <fred@kanboard.net> | 2015-09-20 18:24:15 -0400 |
commit | e6f547abcfe684658a7498391db72d13b6aa7d9a (patch) | |
tree | 75b709c12fb03e11d7cb85558558f89f19abb284 /app/Model | |
parent | 2021dccc5a444f60c5ba1673d94b39999912cd26 (diff) |
Move timetable to a plugin
Plugin repository: https://github.com/kanboard/plugin-timetable
Diffstat (limited to 'app/Model')
-rw-r--r-- | app/Model/SubtaskTimeTracking.php | 38 | ||||
-rw-r--r-- | app/Model/Timetable.php | 356 | ||||
-rw-r--r-- | app/Model/TimetableDay.php | 87 | ||||
-rw-r--r-- | app/Model/TimetableExtra.php | 22 | ||||
-rw-r--r-- | app/Model/TimetableOff.php | 125 | ||||
-rw-r--r-- | app/Model/TimetableWeek.php | 91 |
6 files changed, 28 insertions, 691 deletions
diff --git a/app/Model/SubtaskTimeTracking.php b/app/Model/SubtaskTimeTracking.php index 56998769..d65f2f75 100644 --- a/app/Model/SubtaskTimeTracking.php +++ b/app/Model/SubtaskTimeTracking.php @@ -150,13 +150,14 @@ class SubtaskTimeTracking extends Base * * @access public * @param integer $user_id - * @param integer $start - * @param integer $end + * @param string $start ISO-8601 format + * @param string $end * @return array */ public function getUserCalendarEvents($user_id, $start, $end) { - $result = $this->getUserQuery($user_id) + $hook = 'model:subtask-time-tracking:calendar:events'; + $events = $this->getUserQuery($user_id) ->addCondition($this->getCalendarCondition( $this->dateParser->getTimestampFromIsoFormat($start), $this->dateParser->getTimestampFromIsoFormat($end), @@ -165,9 +166,16 @@ class SubtaskTimeTracking extends Base )) ->findAll(); - $result = $this->timetable->calculateEventsIntersect($user_id, $result, $start, $end); + if ($this->hook->exists($hook)) { + $events = $this->hook->first($hook, array( + 'user_id' => $user_id, + 'events' => $events, + 'start' => $start, + 'end' => $end, + )); + } - return $this->toCalendarEvents($result); + return $this->toCalendarEvents($events); } /** @@ -293,6 +301,7 @@ class SubtaskTimeTracking extends Base */ public function getTimeSpent($subtask_id, $user_id) { + $hook = 'model:subtask-time-tracking:calculate:time-spent'; $start_time = $this->db ->table(self::TABLE) ->eq('subtask_id', $subtask_id) @@ -300,14 +309,23 @@ class SubtaskTimeTracking extends Base ->eq('end', 0) ->findOneColumn('start'); - if ($start_time) { - $start = new DateTime; - $start->setTimestamp($start_time); + if (empty($start_time)) { + return 0; + } + + $end = new DateTime; + $start = new DateTime; + $start->setTimestamp($start_time); - return $this->timetable->calculateEffectiveDuration($user_id, $start, new DateTime); + if ($this->hook->exists($hook)) { + return $this->hook->first($hook, array( + 'user_id' => $user_id, + 'start' => $start, + 'end' => $end, + )); } - return 0; + return $this->dateParser->getHours($start, $end); } /** 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(); - } -} diff --git a/app/Model/TimetableDay.php b/app/Model/TimetableDay.php deleted file mode 100644 index 0c7bf20b..00000000 --- a/app/Model/TimetableDay.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -namespace Model; - -use SimpleValidator\Validator; -use SimpleValidator\Validators; - -/** - * Timetable Workweek - * - * @package model - * @author Frederic Guillot - */ -class TimetableDay extends Base -{ - /** - * SQL table name - * - * @var string - */ - const TABLE = 'timetable_day'; - - /** - * Get the timetable for a given user - * - * @access public - * @param integer $user_id User id - * @return array - */ - public function getByUser($user_id) - { - return $this->db->table(self::TABLE)->eq('user_id', $user_id)->asc('start')->findAll(); - } - - /** - * Add a new time slot in the database - * - * @access public - * @param integer $user_id User id - * @param string $start Start hour (24h format) - * @param string $end End hour (24h format) - * @return boolean|integer - */ - public function create($user_id, $start, $end) - { - $values = array( - 'user_id' => $user_id, - 'start' => $start, - 'end' => $end, - ); - - return $this->persist(self::TABLE, $values); - } - - /** - * Remove a specific time slot - * - * @access public - * @param integer $slot_id - * @return boolean - */ - public function remove($slot_id) - { - return $this->db->table(self::TABLE)->eq('id', $slot_id)->remove(); - } - - /** - * Validate creation - * - * @access public - * @param array $values Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateCreation(array $values) - { - $v = new Validator($values, array( - new Validators\Required('user_id', t('Field required')), - new Validators\Required('start', t('Field required')), - new Validators\Required('end', t('Field required')), - )); - - return array( - $v->execute(), - $v->getErrors() - ); - } -} diff --git a/app/Model/TimetableExtra.php b/app/Model/TimetableExtra.php deleted file mode 100644 index 48db662d..00000000 --- a/app/Model/TimetableExtra.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -namespace Model; - -use SimpleValidator\Validator; -use SimpleValidator\Validators; - -/** - * Timetable over-time - * - * @package model - * @author Frederic Guillot - */ -class TimetableExtra extends TimetableOff -{ - /** - * SQL table name - * - * @var string - */ - const TABLE = 'timetable_extra'; -} diff --git a/app/Model/TimetableOff.php b/app/Model/TimetableOff.php deleted file mode 100644 index e4fe32d2..00000000 --- a/app/Model/TimetableOff.php +++ /dev/null @@ -1,125 +0,0 @@ -<?php - -namespace Model; - -use SimpleValidator\Validator; -use SimpleValidator\Validators; - -/** - * Timetable time off - * - * @package model - * @author Frederic Guillot - */ -class TimetableOff extends Base -{ - /** - * SQL table name - * - * @var string - */ - const TABLE = 'timetable_off'; - - /** - * Get query to fetch everything (pagination) - * - * @access public - * @param integer $user_id User id - * @return \PicoDb\Table - */ - public function getUserQuery($user_id) - { - return $this->db->table(static::TABLE)->eq('user_id', $user_id); - } - - /** - * Get the timetable for a given user - * - * @access public - * @param integer $user_id User id - * @return array - */ - public function getByUser($user_id) - { - return $this->db->table(static::TABLE)->eq('user_id', $user_id)->desc('date')->asc('start')->findAll(); - } - - /** - * Get the timetable for a given user - * - * @access public - * @param integer $user_id User id - * @param string $start_date - * @param string $end_date - * @return array - */ - public function getByUserAndDate($user_id, $start_date, $end_date) - { - return $this->db->table(static::TABLE) - ->eq('user_id', $user_id) - ->gte('date', $start_date) - ->lte('date', $end_date) - ->desc('date') - ->asc('start') - ->findAll(); - } - - /** - * Add a new time slot in the database - * - * @access public - * @param integer $user_id User id - * @param string $date Day (ISO8601 format) - * @param boolean $all_day All day flag - * @param float $start Start hour (24h format) - * @param float $end End hour (24h format) - * @param string $comment - * @return boolean|integer - */ - public function create($user_id, $date, $all_day, $start = '', $end = '', $comment = '') - { - $values = array( - 'user_id' => $user_id, - 'date' => $date, - 'all_day' => (int) $all_day, // Postgres fix - 'start' => $all_day ? '' : $start, - 'end' => $all_day ? '' : $end, - 'comment' => $comment, - ); - - return $this->persist(static::TABLE, $values); - } - - /** - * Remove a specific time slot - * - * @access public - * @param integer $slot_id - * @return boolean - */ - public function remove($slot_id) - { - return $this->db->table(static::TABLE)->eq('id', $slot_id)->remove(); - } - - /** - * Validate creation - * - * @access public - * @param array $values Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateCreation(array $values) - { - $v = new Validator($values, array( - new Validators\Required('user_id', t('Field required')), - new Validators\Required('date', t('Field required')), - new Validators\Numeric('all_day', t('This value must be numeric')), - )); - - return array( - $v->execute(), - $v->getErrors() - ); - } -} diff --git a/app/Model/TimetableWeek.php b/app/Model/TimetableWeek.php deleted file mode 100644 index b22b3b7e..00000000 --- a/app/Model/TimetableWeek.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -namespace Model; - -use SimpleValidator\Validator; -use SimpleValidator\Validators; - -/** - * Timetable Workweek - * - * @package model - * @author Frederic Guillot - */ -class TimetableWeek extends Base -{ - /** - * SQL table name - * - * @var string - */ - const TABLE = 'timetable_week'; - - /** - * Get the timetable for a given user - * - * @access public - * @param integer $user_id User id - * @return array - */ - public function getByUser($user_id) - { - return $this->db->table(self::TABLE)->eq('user_id', $user_id)->asc('day')->asc('start')->findAll(); - } - - /** - * Add a new time slot in the database - * - * @access public - * @param integer $user_id User id - * @param string $day Day of the week (ISO-8601) - * @param string $start Start hour (24h format) - * @param string $end End hour (24h format) - * @return boolean|integer - */ - public function create($user_id, $day, $start, $end) - { - $values = array( - 'user_id' => $user_id, - 'day' => $day, - 'start' => $start, - 'end' => $end, - ); - - return $this->persist(self::TABLE, $values); - } - - /** - * Remove a specific time slot - * - * @access public - * @param integer $slot_id - * @return boolean - */ - public function remove($slot_id) - { - return $this->db->table(self::TABLE)->eq('id', $slot_id)->remove(); - } - - /** - * Validate creation - * - * @access public - * @param array $values Form values - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateCreation(array $values) - { - $v = new Validator($values, array( - new Validators\Required('user_id', t('Field required')), - new Validators\Required('day', t('Field required')), - new Validators\Numeric('day', t('This value must be numeric')), - new Validators\Required('start', t('Field required')), - new Validators\Required('end', t('Field required')), - )); - - return array( - $v->execute(), - $v->getErrors() - ); - } -} |