public static function handleTimesheetRequest()
 {
     if (static::peekPath() == 'html') {
         static::$responseMode = 'html';
     }
     $GLOBALS['Session']->requireAccountLevel('Developer');
     $daysLimit = isset($_REQUEST['daysLimit']) ? $_REQUEST['daysLimit'] : 7;
     $gapLimit = isset($_REQUEST['gapLimit']) ? $_REQUEST['gapLimit'] : 1800;
     $minimumSessionDuration = isset($_REQUEST['minimumSessionDuration']) ? $_REQUEST['minimumSessionDuration'] : 120;
     $dayShift = isset($_REQUEST['dayShift']) ? $_REQUEST['dayShift'] : 18000;
     // 5 hours
     $workDays = array();
     $editResults = DB::query('SELECT UNIX_TIMESTAMP(Timestamp) AS Timestamp, AuthorID' . ' FROM _e_files f' . ' WHERE f.AuthorID IS NOT NULL' . ' ORDER BY ID DESC');
     while ($editRecord = $editResults->fetch_assoc()) {
         $day = date('Y-m-d', $editRecord['Timestamp'] - $dayShift);
         if (!array_key_exists($day, $workDays)) {
             if (count($workDays) == $daysLimit) {
                 break;
             }
             $workDays[$day] = array();
         }
         if (!array_key_exists($editRecord['AuthorID'], $workDays[$day])) {
             $workDays[$day][$editRecord['AuthorID']] = array();
         }
         if (!count($workDays[$day][$editRecord['AuthorID']]) || $workDays[$day][$editRecord['AuthorID']][0]['firstEdit'] - $gapLimit > $editRecord['Timestamp']) {
             array_unshift($workDays[$day][$editRecord['AuthorID']], array('firstEdit' => $editRecord['Timestamp'], 'lastEdit' => $editRecord['Timestamp']));
         } else {
             $workDays[$day][$editRecord['AuthorID']][0]['firstEdit'] = $editRecord['Timestamp'];
         }
     }
     // compile results
     $results = array();
     foreach ($workDays as $day => $authors) {
         #        	print("<h1>$day</h1>");
         $dayResults = array('date' => $day, 'authors' => array());
         foreach ($authors as $authorID => $sessions) {
             $authorResults = array('Person' => Person::getByID($authorID), 'totalDuration' => 0, 'sessions' => array());
             #        		print("<h2>$Author->FullName</h2><pre>");
             foreach ($sessions as $authorSession) {
                 $authorSession['duration'] = $authorSession['lastEdit'] - $authorSession['firstEdit'];
                 $authorResults['sessions'][] = $authorSession;
                 #        			printf("%s\t->\t%s\t:\t%s minutes\n", date('g:i:sa', $authorSession['firstEdit']), date('g:i:sa', $authorSession['lastEdit']), number_format($authorSession['duration']/60,1));
                 $authorResults['totalDuration'] += max($authorSession['duration'], $minimumSessionDuration);
             }
             $dayResults['authors'][] = $authorResults;
             #        		print("</pre><p>".number_format($dayAuthor['duration'] / 60, 1)." minutes estimated total</p>");
         }
         $results[] = $dayResults;
     }
     return static::respond('timesheet', array('data' => $results, 'daysLimit' => $daysLimit, 'gapLimit' => $gapLimit, 'minimumSessionDuration' => $minimumSessionDuration, 'dayShift' => $dayShift));
 }
 protected static function _getRequestedUser()
 {
     if (!empty($_GET['person']) && static::$accountLevelEditOthers && $GLOBALS['Session']->hasAccountLevel(static::$accountLevelEditOthers)) {
         if (!($User = Person::getByID($_GET['person']))) {
             return static::throwNotFoundError('Person not found');
         }
     } else {
         $User = $GLOBALS['Session']->Person;
     }
     return $User;
 }