8 // Old style constructors are DEPRECATED in PHP 7.0, and will be removed in a future version. You should always use __construct() in new code.
9 function __construct() {
10 $this->db = getConnection();
11 $i18n = $GLOBALS['I18N'];
12 $this->holidays = $i18n->holidays;
14 $this->usersTeamId = $user->team_id;
17 public function update($year, $month, $quota) {
18 $teamId = $this->usersTeamId;
19 $deleteSql = "DELETE FROM tt_monthly_quota WHERE year = $year AND month = $month AND team_id = $teamId";
20 $this->db->exec($deleteSql);
22 $insertSql = "INSERT INTO tt_monthly_quota (team_id, year, month, quota) values ($teamId, $year, $month, $quota)";
23 $affected = $this->db->exec($insertSql);
24 return (!is_a($affected, 'PEAR_Error'));
29 public function get($year, $month) {
31 return $this->getMany($year);
34 return $this->getSingle($year, $month);
37 public function getDailyWorkingHours(){
38 $teamId = $this->usersTeamId;
39 $sql = "SELECT workday_hours FROM tt_teams where id = $teamId";
40 $reader = $this->db->query($sql);
41 if (is_a($reader, 'PEAR_Error')) {
45 $row = $reader->fetchRow();
46 return $row["workday_hours"];
49 private function getSingle($year, $month) {
50 $teamId = $this->usersTeamId;
51 $sql = "SELECT quota FROM tt_monthly_quota WHERE year = $year AND month = $month AND team_id = $teamId";
52 $reader = $this->db->query($sql);
53 if (is_a($reader, 'PEAR_Error')) {
57 $row = $reader->fetchRow();
59 // if we don't find a record, return calculated monthly quota
62 $holidaysWithYear = array();
63 foreach ($this->holidays as $day) {
64 $parts = explode("/", $day);
65 $holiday = "$year-$parts[0]-$parts[1]";
66 array_push($holidaysWithYear, $holiday);
69 $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);
70 return $this->getWorkingDays("$year-$month-01", "$year-$month-$daysInMonth", $holidaysWithYear) * $this->getDailyWorkingHours();
76 private function getMany($year){
77 $teamId = $this->usersTeamId;
78 $sql = "SELECT month, quota FROM tt_monthly_quota WHERE year = $year AND team_id = $teamId";
80 $res = $this->db->query($sql);
81 if (is_a($res, 'PEAR_Error')) {
85 while ($val = $res->fetchRow()) {
86 $result[$val["month"]] = $val["quota"];
93 //The function returns the no. of business days between two dates and it skips the holidays
94 private function getWorkingDays($startDate, $endDate, $holidays) {
95 // do strtotime calculations just once
96 $endDate = strtotime($endDate);
97 $startDate = strtotime($startDate);
99 //The total number of days between the two dates. We compute the no. of seconds and divide it to 60*60*24
100 //We add one to inlude both dates in the interval.
101 $days = ($endDate - $startDate) / 86400 + 1;
103 $noOfFullWeeks = floor($days / 7);
104 $noOfRemainingDays = fmod($days, 7);
106 //It will return 1 if it's Monday,.. ,7 for Sunday
107 $firstDayofWeek = date("N", $startDate);
108 $lastDayofWeek = date("N", $endDate);
110 //---->The two can be equal in leap years when february has 29 days, the equal sign is added here
111 //In the first case the whole interval is within a week, in the second case the interval falls in two weeks.
112 if ($firstDayofWeek <= $lastDayofWeek) {
113 if ($firstDayofWeek <= 6 && 6 <= $lastDayofWeek) {
114 $noOfRemainingDays--;
117 if ($firstDayofWeek <= 7 && 7 <= $lastDayofWeek) {
118 $noOfRemainingDays--;
122 // (edit by Tokes to fix an edge case where the start day was a Sunday
123 // and the end day was NOT a Saturday)
125 // the day of the week for start is later than the day of the week for end
126 if ($firstDayofWeek == 7) {
127 // if the start date is a Sunday, then we definitely subtract 1 day
128 $noOfRemainingDays--;
130 if ($lastDayofWeek == 6) {
131 // if the end date is a Saturday, then we subtract another day
132 $noOfRemainingDays--;
136 // the start date was a Saturday (or earlier), and the end date was (Mon..Fri)
137 // so we skip an entire weekend and subtract 2 days
138 $noOfRemainingDays -= 2;
142 //T he no. of business days is: (number of weeks between the two dates) * (5 working days) + the remainder
143 // ---->february in none leap years gave a remainder of 0 but still calculated weekends between first and last day, this is one way to fix it
144 $workingDays = $noOfFullWeeks * 5;
145 if ($noOfRemainingDays > 0 ) {
146 $workingDays += $noOfRemainingDays;
149 // We subtract the holidays
150 foreach($holidays as $holiday){
151 $timeStamp = strtotime($holiday);
152 // If the holiday doesn't fall in weekend
153 // TODO: add handling for countries where they move non working day to first working day if holiday is on weekends
154 if ($startDate <= $timeStamp && $timeStamp <= $endDate && date("N", $timeStamp) != 6 && date("N", $timeStamp ) != 7)