Refactoring - white space.
[timetracker.git] / WEB-INF / lib / ttTimeHelper.class.php
index 1333894..d183f1d 100644 (file)
@@ -31,12 +31,6 @@ import('DateAndTime');
 // The ttTimeHelper is a class to help with time-related values.
 class ttTimeHelper {
        
-  /* // isWeekend determines if $date falls on weekend.
-  static function isWeekend($date) {
-       $weekDay = date('w', strtotime($date));
-    return ($weekDay == WEEKEND_START_DAY || $weekDay == (WEEKEND_START_DAY + 1) % 7);
-  }*/
-
   // isValidTime validates a value as a time string.
   static function isValidTime($value) {
     if (strlen($value)==0 || !isset($value)) return false;
@@ -89,6 +83,7 @@ class ttTimeHelper {
         return false;
       return true;
     }
+
     return false;
   }
   
@@ -146,13 +141,11 @@ class ttTimeHelper {
     return (int)@$time_a[1] + ((int)@$time_a[0]) * 60;
   }
   
-  // toDuration - calculates duration between start and finish times in 00:00 format.
-  static function toDuration($start, $finish) {
-    $duration_minutes = ttTimeHelper::toMinutes($finish) - ttTimeHelper::toMinutes($start);
-    if ($duration_minutes <= 0) return false;
-    
-    $hours = (string)((int)($duration_minutes / 60));
-    $mins = (string)($duration_minutes % 60);
+  // toAbsDuration - converts a number of minutes to format 00:00
+  // even if $minutes is negative.
+  static function toAbsDuration($minutes){
+    $hours = (string)((int)abs($minutes / 60));
+    $mins = (string)(abs($minutes % 60));
     if (strlen($hours) == 1)
       $hours = '0'.$hours;
     if (strlen($mins) == 1)
@@ -160,16 +153,24 @@ class ttTimeHelper {
     return $hours.':'.$mins;
   }
   
+  // toDuration - calculates duration between start and finish times in 00:00 format.
+  static function toDuration($start, $finish) {
+    $duration_minutes = ttTimeHelper::toMinutes($finish) - ttTimeHelper::toMinutes($start);
+    if ($duration_minutes <= 0) return false;
+    
+    return ttTimeHelper::toAbsDuration($duration_minutes);
+  }
+  
   // The to12HourFormat function converts a 24-hour time value (such as 15:23) to 12 hour format (03:23 PM).
   static function to12HourFormat($value) {
-       if ('24:00' == $value) return '12:00 AM';
+    if ('24:00' == $value) return '12:00 AM';
        
     $time_a = explode(':', $value);
     if ($time_a[0] > 12)
       $res = (string)((int)$time_a[0] - 12).':'.$time_a[1].' PM';
-    else if ($time_a[0] == 12)
+    elseif ($time_a[0] == 12)
       $res = $value.' PM';
-    else if ($time_a[0] == 0)
+    elseif ($time_a[0] == 0)
       $res = '12:'.$time_a[1].' AM';
     else
       $res = $value.' AM';
@@ -179,51 +180,51 @@ class ttTimeHelper {
   // The to24HourFormat function attempts to convert a string value (human readable notation of time of day)
   // to a 24-hour time format HH:MM.
   static function to24HourFormat($value) {
-       $res = null;
-       
-       // Algorithm: use regular expressions to find a matching pattern, starting with most popular patterns first.
-       $tmp_val = trim($value);
-
-       // 24 hour patterns.
-       if (preg_match('/^([01][0-9]|2[0-3]):[0-5][0-9]$/', $tmp_val)) { // 00:00 - 23:59
-         // We already have a 24-hour format. Just return it. 
-         $res = $tmp_val; 
-         return $res;
-       }
-       if (preg_match('/^[0-9]:[0-5][0-9]$/', $tmp_val)) { // 0:00 - 9:59
-         // This is a 24-hour format without a leading zero. Add 0 and return.
-         $res = '0'.$tmp_val; 
-         return $res;
-       }
+    $res = null;
+
+    // Algorithm: use regular expressions to find a matching pattern, starting with most popular patterns first.
+    $tmp_val = trim($value);
+
+    // 24 hour patterns.
+    if (preg_match('/^([01][0-9]|2[0-3]):[0-5][0-9]$/', $tmp_val)) { // 00:00 - 23:59
+      // We already have a 24-hour format. Just return it.
+      $res = $tmp_val;
+      return $res;
+    }
+    if (preg_match('/^[0-9]:[0-5][0-9]$/', $tmp_val)) { // 0:00 - 9:59
+      // This is a 24-hour format without a leading zero. Add 0 and return.
+      $res = '0'.$tmp_val;
+      return $res;
+    }
     if (preg_match('/^[0-9]$/', $tmp_val)) { // 0 - 9
-         // Single digit. Assuming hour number.
-         $res = '0'.$tmp_val.':00'; 
-         return $res;
-       }
+      // Single digit. Assuming hour number.
+      $res = '0'.$tmp_val.':00';
+      return $res;
+    }
     if (preg_match('/^([01][0-9]|2[0-4])$/', $tmp_val)) { // 00 - 24
-         // Two digit hour number.
-         $res = $tmp_val.':00'; 
-         return $res;
-       }
+      // Two digit hour number.
+      $res = $tmp_val.':00';
+      return $res;
+    }
     if (preg_match('/^[0-9][0-5][0-9]$/', $tmp_val)) { // 000 - 959
-         // Missing colon. We'll assume the first digit is the hour, the rest is minutes.
-         $tmp_arr = str_split($tmp_val);
-         $res = '0'.$tmp_arr[0].':'.$tmp_arr[1].$tmp_arr[2]; 
-         return $res;
-       }       
+      // Missing colon. We'll assume the first digit is the hour, the rest is minutes.
+      $tmp_arr = str_split($tmp_val);
+      $res = '0'.$tmp_arr[0].':'.$tmp_arr[1].$tmp_arr[2];
+      return $res;
+    }
     if (preg_match('/^([01][0-9]|2[0-3])[0-5][0-9]$/', $tmp_val)) { // 0000 - 2359
-         // Missing colon. We'll assume the first 2 digits are the hour, the rest is minutes.
-         $tmp_arr = str_split($tmp_val);
-         $res = $tmp_arr[0].$tmp_arr[1].':'.$tmp_arr[2].$tmp_arr[3]; 
-         return $res;
-       }
-       // Special handling for midnight.
+      // Missing colon. We'll assume the first 2 digits are the hour, the rest is minutes.
+      $tmp_arr = str_split($tmp_val);
+      $res = $tmp_arr[0].$tmp_arr[1].':'.$tmp_arr[2].$tmp_arr[3];
+      return $res;
+    }
+    // Special handling for midnight.
     if ($tmp_val == '24:00' || $tmp_val == '2400')
-      return '24:00';  
-       
+      return '24:00';
+
     // 12 hour AM patterns.
     if (preg_match('/.(am|AM)$/', $tmp_val)) {
-       
+
       // The $value ends in am or AM. Strip it.
       $tmp_val = rtrim(substr($tmp_val, 0, -2));
       
@@ -233,37 +234,37 @@ class ttTimeHelper {
         
       // We are ready to convert AM time.
       if (preg_match('/^(0[0-9]|1[0-1]):[0-5][0-9]$/', $tmp_val)) { // 00:00 - 11:59
-           // We already have a 24-hour format. Just return it. 
-           $res = $tmp_val; 
+        // We already have a 24-hour format. Just return it.
+        $res = $tmp_val;
         return $res;
-         }
-         if (preg_match('/^[1-9]:[0-5][0-9]$/', $tmp_val)) { // 1:00 - 9:59
-           // This is a 24-hour format without a leading zero. Add 0 and return.
-           $res = '0'.$tmp_val; 
-           return $res;
-         }
+      }
+      if (preg_match('/^[1-9]:[0-5][0-9]$/', $tmp_val)) { // 1:00 - 9:59
+        // This is a 24-hour format without a leading zero. Add 0 and return.
+        $res = '0'.$tmp_val;
+        return $res;
+      }
       if (preg_match('/^[1-9]$/', $tmp_val)) { // 1 - 9
        // Single digit. Assuming hour number.
-        $res = '0'.$tmp_val.':00'; 
-           return $res;
-         }
-         if (preg_match('/^(0[0-9]|1[0-1])$/', $tmp_val)) { // 00 - 11
-           // Two digit hour number.
-           $res = $tmp_val.':00'; 
-           return $res;
-         }
+        $res = '0'.$tmp_val.':00';
+        return $res;
+      }
+      if (preg_match('/^(0[0-9]|1[0-1])$/', $tmp_val)) { // 00 - 11
+        // Two digit hour number.
+        $res = $tmp_val.':00';
+        return $res;
+      }
       if (preg_match('/^[1-9][0-5][0-9]$/', $tmp_val)) { // 100 - 959
         // Missing colon. Assume the first digit is the hour, the rest is minutes.
-           $tmp_arr = str_split($tmp_val);
-           $res = '0'.$tmp_arr[0].':'.$tmp_arr[1].$tmp_arr[2]; 
-           return $res;
-         }     
+        $tmp_arr = str_split($tmp_val);
+        $res = '0'.$tmp_arr[0].':'.$tmp_arr[1].$tmp_arr[2];
+        return $res;
+      }
       if (preg_match('/^(0[0-9]|1[0-1])[0-5][0-9]$/', $tmp_val)) { // 0000 - 1159
         // Missing colon. We'll assume the first 2 digits are the hour, the rest is minutes.
-           $tmp_arr = str_split($tmp_val);
-           $res = $tmp_arr[0].$tmp_arr[1].':'.$tmp_arr[2].$tmp_arr[3]; 
-           return $res;
-         }  
+        $tmp_arr = str_split($tmp_val);
+        $res = $tmp_arr[0].$tmp_arr[1].':'.$tmp_arr[2].$tmp_arr[3];
+        return $res;
+      }
     } // AM cases handling.
 
     // 12 hour PM patterns.
@@ -284,38 +285,38 @@ class ttTimeHelper {
           $tmp_val = (string)(12 + (int)$tmp_val);
         $res = $tmp_val.':00';
         return $res;
-      }        
+      }
       if (preg_match('/^[1-9][0-5][0-9]$/', $tmp_val)) { // 100 - 959
         // Missing colon. We'll assume the first digit is the hour, the rest is minutes.
-           $tmp_arr = str_split($tmp_val);
-           $hour = (string)(12 + (int)$tmp_arr[0]);
-           $res = $hour.':'.$tmp_arr[1].$tmp_arr[2]; 
-           return $res;
-         }
-         if (preg_match('/^(0[1-9]|1[0-2])[0-5][0-9]$/', $tmp_val)) { // 0100 - 1259
+        $tmp_arr = str_split($tmp_val);
+        $hour = (string)(12 + (int)$tmp_arr[0]);
+        $res = $hour.':'.$tmp_arr[1].$tmp_arr[2];
+        return $res;
+      }
+      if (preg_match('/^(0[1-9]|1[0-2])[0-5][0-9]$/', $tmp_val)) { // 0100 - 1259
         // Missing colon. We'll assume the first 2 digits are the hour, the rest is minutes.
         $hour = substr($tmp_val, 0, -2);
         $min = substr($tmp_val, 2);
         if ('12' != $hour)
           $hour = (string)(12 + (int)$hour); 
-        $res = $hour.':'.$min; 
-           return $res;
-         }  
+        $res = $hour.':'.$min;
+        return $res;
+      }
       if (preg_match('/^[1-9]:[0-5][0-9]$/', $tmp_val)) { // 1:00 - 9:59
-           $hour = substr($tmp_val, 0, -3);
+        $hour = substr($tmp_val, 0, -3);
         $min = substr($tmp_val, 2);
         $hour = (string)(12 + (int)$hour);
-        $res = $hour.':'.$min;         
-           return $res;
-         }
+        $res = $hour.':'.$min;
+        return $res;
+      }
       if (preg_match('/^(0[1-9]|1[0-2]):[0-5][0-9]$/', $tmp_val)) { // 01:00 - 12:59
-           $hour = substr($tmp_val, 0, -3);
+        $hour = substr($tmp_val, 0, -3);
         $min = substr($tmp_val, 3);
         if ('12' != $hour)
           $hour = (string)(12 + (int)$hour);
-           $res = $hour.':'.$min;
+        $res = $hour.':'.$min;
         return $res;
-         }    
+      }
     } // PM cases handling.
 
     return $res;
@@ -365,7 +366,10 @@ class ttTimeHelper {
     $duration = ttTimeHelper::normalizeDuration($duration);
 
     if (!$timestamp) {
-      $timestamp = date('YmdHis');//yyyymmddhhmmss
+      $timestamp = date('YmdHis'); //yyyymmddhhmmss
+      // TODO: this timestamp could be illegal if we hit inside DST switch deadzone, such as '2016-03-13 02:30:00'
+      // Anything between 2am and 3am on DST introduction date will not work if we run on a system with DST on.
+      // We need to address this properly to avoid potential complications.
     }
         
     if (!$billable) $billable = 0;
@@ -485,11 +489,26 @@ class ttTimeHelper {
     return 0;
   }
   
+  // getTimeForMonth - gets total time for a user for a given month.
+  static function getTimeForMonth($user_id, $date){
+    import('Period');
+    $mdb2 = getConnection();
+    
+    $period = new Period(INTERVAL_THIS_MONTH, $date);
+    $sql = "select sum(time_to_sec(duration)) as sm from tt_log where user_id = $user_id and date >= '".$period->getBeginDate(DB_DATEFORMAT)."' and date <= '".$period->getEndDate(DB_DATEFORMAT)."' and status = 1";
+    $res = $mdb2->query($sql);
+    if (!is_a($res, 'PEAR_Error')) {
+      $val = $res->fetchRow();
+      return sec_to_time_fmt_hm($val['sm']);
+    }
+    return 0;
+  }
+  
   // getUncompleted - retrieves an uncompleted record for user, if one exists.
   static function getUncompleted($user_id) {
     $mdb2 = getConnection();
 
-    $sql = "select id from tt_log  
+    $sql = "select id, start from tt_log  
       where user_id = $user_id and start is not null and time_to_sec(duration) = 0 and status = 1";
     $res = $mdb2->query($sql);
     if (!is_a($res, 'PEAR_Error')) {
@@ -512,6 +531,10 @@ class ttTimeHelper {
   //   $finish - new record finish time, may be null
   //   $record_id - optional record id we may be editing, excluded from overlap set
   static function overlaps($user_id, $date, $start, $finish, $record_id = null) {
+    // Do not bother checking if we allow overlaps.
+    if (defined('ALLOW_OVERLAP') && ALLOW_OVERLAP == true)
+      return false;
+      
     $mdb2 = getConnection();
     
     $start = ttTimeHelper::to24HourFormat($start);
@@ -608,12 +631,12 @@ class ttTimeHelper {
     $mdb2 = getConnection();
 
     $client_field = null;
-    if (in_array('cl', explode(',', $user->plugins)))
+    if ($user->isPluginEnabled('cl'))
       $client_field = ", c.name as client";
     
     $left_joins = " left join tt_projects p on (l.project_id = p.id)".
       " left join tt_tasks t on (l.task_id = t.id)";
-    if (in_array('cl', explode(',', $user->plugins)))
+    if ($user->isPluginEnabled('cl'))
       $left_joins .= " left join tt_clients c on (l.client_id = c.id)";
 
     $sql = "select l.id as id, TIME_FORMAT(l.start, $sql_time_format) as start,