From 0cc1dc50345b052d65274c4e686bf3b4cd621c4d Mon Sep 17 00:00:00 2001 From: anuko Date: Sat, 6 Jan 2018 17:12:06 +0000 Subject: [PATCH] Moved week view related functions in ttWeekViewHelper class. --- WEB-INF/lib/ttTimeHelper.class.php | 183 ------------------------ WEB-INF/lib/ttWeekViewHelper.class.php | 187 ++++++++++++++++++++++++- WEB-INF/templates/footer.tpl | 2 +- week.php | 6 +- 4 files changed, 188 insertions(+), 190 deletions(-) diff --git a/WEB-INF/lib/ttTimeHelper.class.php b/WEB-INF/lib/ttTimeHelper.class.php index e7491904..9d3f8bbe 100644 --- a/WEB-INF/lib/ttTimeHelper.class.php +++ b/WEB-INF/lib/ttTimeHelper.class.php @@ -587,56 +587,6 @@ class ttTimeHelper { return false; } - // wvCanModify (weekViewCanModify) - determines if an already existing tt_log record - // can be modified with a new user-provided duration. - static function wvCanModify($tt_log_id, $new_duration, $err) { - global $i18n; - $mdb2 = getConnection(); - - // Determine if we have start time in record, as further checking does not makes sense otherwise. - $sql = "select user_id, date, start, duration from tt_log where id = $tt_log_id"; - $res = $mdb2->query($sql); - if (!is_a($res, 'PEAR_Error')) { - if (!$res->numRows()) { - $err->add($i18n->getKey('error.db')); // This is not expected. - return false; - } - $val = $res->fetchRow(); - $oldDuration = $val['duration']; - if (!$val['start']) - return true; // There is no start time in the record, therefore safe to modify. - } - - // We do have start time. - // Quick test if new duration is less then already existing. - $newMinutes = ttTimeHelper::toMinutes($new_duration); - $oldMinutes = ttTimeHelper::toMinutes($oldDuration); - if ($newMinutes < $oldMinutes) - return true; // Safe to modify. - - // Does the new duration put the record beyond 24:00 boundary? - $startMinutes = ttTimeHelper::toMinutes($val['start']); - $newEndMinutes = $startMinutes + $newMinutes; - if ($newEndMinutes > 1440) { - // Invalid duration, as new duration puts the record beyond current day. - $err->add($i18n->getKey('error.field'), $i18n->getKey('label.duration')); - return false; - } - - // Does the new duration causes the record to overlap with others? - $user_id = $val['user_id']; - $date = $val['date']; - $startMinutes = ttTimeHelper::toMinutes($val['start']); - $start = ttTimeHelper::toAbsDuration($startMinutes); - $finish = ttTimeHelper::toAbsDuration($newEndMinutes); - if (ttTimeHelper::overlaps($user_id, $date, $start, $finish, $tt_log_id)) { - $err->add($i18n->getKey('error.overlap')); - return false; - } - - return true; // There are no conflicts, safe to modify. - } - // getRecord - retrieves a time record identified by its id. static function getRecord($id, $user_id) { global $user; @@ -724,137 +674,4 @@ class ttTimeHelper { return $result; } - - // cellExists is a helper function for getDataForWeekView() to see if a cell with a given label - // and a day header already exists. - static function cellExists($row_id, $day_header, $dataArray) { - foreach($dataArray as $row) { - if ($row['row_id'] == $row_id && !empty($row[$day_header]['duration'])) - return true; - } - return false; - } - - // findRow returns an existing row position in $dataArray, -1 otherwise. - static function findRow($row_id, $dataArray) { - $pos = 0; // Row position in array. - foreach($dataArray as $row) { - if ($row['row_id'] == $row_id) - return $pos; - $pos++; // Increment for search. - } - return -1; // Row not found. - } - - // getDayTotals calculates total durations for each day from the existing data in $dataArray. - static function getDayTotals($dataArray, $dayHeaders) { - $dayTotals = array(); - - // Insert label. - global $i18n; - $dayTotals['label'] = $i18n->getKey('label.day_total'); - - foreach ($dataArray as $row) { - foreach($dayHeaders as $dayHeader) { - if (array_key_exists($dayHeader, $row)) { - $minutes = ttTimeHelper::toMinutes($row[$dayHeader]['duration']); - $dayTotals[$dayHeader] += $minutes; - } - } - } - // Convert minutes to hh:mm for display. - foreach($dayHeaders as $dayHeader) { - $dayTotals[$dayHeader] = ttTimeHelper::toAbsDuration($dayTotals[$dayHeader]); - } - return $dayTotals; - } - - // dateFromDayHeader calculates date from start date and day header in week view. - static function dateFromDayHeader($start_date, $day_header) { - $objDate = new DateAndTime(DB_DATEFORMAT, $start_date); - $currentDayHeader = (string) $objDate->getDate(); // It returns an int on first call. - if (strlen($currentDayHeader) == 1) // Which is an implementation detail of DateAndTime class. - $currentDayHeader = '0'.$currentDayHeader; // Add a 0 for single digit day. - $i = 1; - while ($currentDayHeader != $day_header && $i < 7) { - // Iterate through remaining days to find a match. - $objDate->incDay(); - $currentDayHeader = $objDate->getDate(); // After incDay it returns a string with leading 0, when necessary. - $i++; - } - return $objDate->toString(DB_DATEFORMAT); - } - - // insertDurationFromWeekView - inserts a new record in log tables from a week view post. - static function insertDurationFromWeekView($fields, $custom_fields, $err) { - global $i18n; - global $user; - - // Determine date for a new entry. - $entry_date = ttTimeHelper::dateFromDayHeader($fields['start_date'], $fields['day_header']); - $objEntryDate = new DateAndTime(DB_DATEFORMAT, $entry_date); - - // Prohibit creating entries in future. - if (defined('FUTURE_ENTRIES') && !isTrue(FUTURE_ENTRIES) && $fields['browser_today']) { - $objBrowserToday = new DateAndTime(DB_DATEFORMAT, $fields['browser_today']); - if ($objEntryDate->after($objBrowserToday)) { - $err->add($i18n->getKey('error.future_date')); - return false; - } - } - - // Prepare an array of fields for regular insert function. - $fields4insert = array(); - $fields4insert['user_id'] = $user->getActiveUser(); - $fields4insert['date'] = $entry_date; - $fields4insert['duration'] = $fields['duration']; - $fields4insert['client'] = ttWeekViewHelper::parseFromWeekViewRow($fields['row_id'], 'cl'); - $fields4insert['billable'] = ttWeekViewHelper::parseFromWeekViewRow($fields['row_id'], 'bl'); - $fields4insert['project'] = ttWeekViewHelper::parseFromWeekViewRow($fields['row_id'], 'pr'); - $fields4insert['task'] = ttWeekViewHelper::parseFromWeekViewRow($fields['row_id'], 'ts'); - $fields4insert['note'] = $fields['note']; - - // Try to insert a record. - $id = ttTimeHelper::insert($fields4insert); - if (!$id) return false; // Something failed. - - // Insert custom field if we have it. - $result = true; - $cf_1 = ttWeekViewHelper::parseFromWeekViewRow($fields['row_id'], 'cf_1'); - if ($custom_fields && $cf_1) { - if ($custom_fields->fields[0]['type'] == CustomFields::TYPE_TEXT) - $result = $custom_fields->insert($id, $custom_fields->fields[0]['id'], null, $cf_1); - elseif ($custom_fields->fields[0]['type'] == CustomFields::TYPE_DROPDOWN) - $result = $custom_fields->insert($id, $custom_fields->fields[0]['id'], $cf_1, null); - } - - return $result; - } - - - // modifyFromWeekView - modifies a duration of an existing record from a week view post. - static function modifyDurationFromWeekView($fields, $err) { - global $i18n; - global $user; - - // Possible errors: 1) Overlap if the existing record has start time. 2) Going beyond 24 hour boundary. - // TODO: rename this function. - // Handle different errors with specific error messages. - if (!ttTimeHelper::wvCanModify($fields['tt_log_id'], $fields['duration'], $err)) { - // $err->add($i18n->getKey('error.overlap')); - return false; - } - - $mdb2 = getConnection(); - $duration = $fields['duration']; - $tt_log_id = $fields['tt_log_id']; - $user_id = $user->getActiveUser(); - $sql = "update tt_log set duration = '$duration' where id = $tt_log_id and user_id = $user_id"; - $affected = $mdb2->exec($sql); - if (is_a($affected, 'PEAR_Error')) - return false; - - return true; - } } - diff --git a/WEB-INF/lib/ttWeekViewHelper.class.php b/WEB-INF/lib/ttWeekViewHelper.class.php index 7031dab7..ad21be00 100644 --- a/WEB-INF/lib/ttWeekViewHelper.class.php +++ b/WEB-INF/lib/ttWeekViewHelper.class.php @@ -156,15 +156,15 @@ class ttWeekViewHelper { $suffix = 0; $row_id = $row_id_no_suffix.'_'.$suffix; $day_header = substr($record['date'], 8); // Day number in month. - while (ttTimeHelper::cellExists($row_id, $day_header, $dataArray)) { + while (ttWeekViewHelper::cellExists($row_id, $day_header, $dataArray)) { $suffix++; $row_id = $row_id_no_suffix.'_'.$suffix; } // Find row. - $pos = ttTimeHelper::findRow($row_id, $dataArray); + $pos = ttWeekViewHelper::findRow($row_id, $dataArray); if ($pos < 0) { $dataArray[] = array('row_id' => $row_id,'label' => ttWeekViewHelper::makeRowLabel($record)); // Insert row. - $pos = ttTimeHelper::findRow($row_id, $dataArray); + $pos = ttWeekViewHelper::findRow($row_id, $dataArray); // Insert empty cells with proper control ids. for ($i = 0; $i < 7; $i++) { $control_id = $pos.'_'. $dayHeaders[$i]; @@ -177,6 +177,50 @@ class ttWeekViewHelper { return $dataArray; } + // cellExists is a helper function for getDataForWeekView() to see if a cell with a given label + // and a day header already exists. + static function cellExists($row_id, $day_header, $dataArray) { + foreach($dataArray as $row) { + if ($row['row_id'] == $row_id && !empty($row[$day_header]['duration'])) + return true; + } + return false; + } + + // findRow returns an existing row position in $dataArray, -1 otherwise. + static function findRow($row_id, $dataArray) { + $pos = 0; // Row position in array. + foreach($dataArray as $row) { + if ($row['row_id'] == $row_id) + return $pos; + $pos++; // Increment for search. + } + return -1; // Row not found. + } + + // getDayTotals calculates total durations for each day from the existing data in $dataArray. + static function getDayTotals($dataArray, $dayHeaders) { + $dayTotals = array(); + + // Insert label. + global $i18n; + $dayTotals['label'] = $i18n->getKey('label.day_total'); + + foreach ($dataArray as $row) { + foreach($dayHeaders as $dayHeader) { + if (array_key_exists($dayHeader, $row)) { + $minutes = ttTimeHelper::toMinutes($row[$dayHeader]['duration']); + $dayTotals[$dayHeader] += $minutes; + } + } + } + // Convert minutes to hh:mm for display. + foreach($dayHeaders as $dayHeader) { + $dayTotals[$dayHeader] = ttTimeHelper::toAbsDuration($dayTotals[$dayHeader]); + } + return $dayTotals; + } + // getDayHeadersForWeek - obtains day column headers for week view, which are simply day numbers in month. static function getDayHeadersForWeek($start_date) { $dayHeaders = array(); @@ -290,4 +334,141 @@ class ttWeekViewHelper { // Return value. return substr($remaninder, $posBegin, $posEnd - $posBegin); } + + // dateFromDayHeader calculates date from start date and day header in week view. + static function dateFromDayHeader($start_date, $day_header) { + $objDate = new DateAndTime(DB_DATEFORMAT, $start_date); + $currentDayHeader = (string) $objDate->getDate(); // It returns an int on first call. + if (strlen($currentDayHeader) == 1) // Which is an implementation detail of DateAndTime class. + $currentDayHeader = '0'.$currentDayHeader; // Add a 0 for single digit day. + $i = 1; + while ($currentDayHeader != $day_header && $i < 7) { + // Iterate through remaining days to find a match. + $objDate->incDay(); + $currentDayHeader = $objDate->getDate(); // After incDay it returns a string with leading 0, when necessary. + $i++; + } + return $objDate->toString(DB_DATEFORMAT); + } + + // insertDurationFromWeekView - inserts a new record in log tables from a week view post. + static function insertDurationFromWeekView($fields, $custom_fields, $err) { + global $i18n; + global $user; + + // Determine date for a new entry. + $entry_date = ttWeekViewHelper::dateFromDayHeader($fields['start_date'], $fields['day_header']); + $objEntryDate = new DateAndTime(DB_DATEFORMAT, $entry_date); + + // Prohibit creating entries in future. + if (defined('FUTURE_ENTRIES') && !isTrue(FUTURE_ENTRIES) && $fields['browser_today']) { + $objBrowserToday = new DateAndTime(DB_DATEFORMAT, $fields['browser_today']); + if ($objEntryDate->after($objBrowserToday)) { + $err->add($i18n->getKey('error.future_date')); + return false; + } + } + + // Prepare an array of fields for regular insert function. + $fields4insert = array(); + $fields4insert['user_id'] = $user->getActiveUser(); + $fields4insert['date'] = $entry_date; + $fields4insert['duration'] = $fields['duration']; + $fields4insert['client'] = ttWeekViewHelper::parseFromWeekViewRow($fields['row_id'], 'cl'); + $fields4insert['billable'] = ttWeekViewHelper::parseFromWeekViewRow($fields['row_id'], 'bl'); + $fields4insert['project'] = ttWeekViewHelper::parseFromWeekViewRow($fields['row_id'], 'pr'); + $fields4insert['task'] = ttWeekViewHelper::parseFromWeekViewRow($fields['row_id'], 'ts'); + $fields4insert['note'] = $fields['note']; + + // Try to insert a record. + $id = ttTimeHelper::insert($fields4insert); + if (!$id) return false; // Something failed. + + // Insert custom field if we have it. + $result = true; + $cf_1 = ttWeekViewHelper::parseFromWeekViewRow($fields['row_id'], 'cf_1'); + if ($custom_fields && $cf_1) { + if ($custom_fields->fields[0]['type'] == CustomFields::TYPE_TEXT) + $result = $custom_fields->insert($id, $custom_fields->fields[0]['id'], null, $cf_1); + elseif ($custom_fields->fields[0]['type'] == CustomFields::TYPE_DROPDOWN) + $result = $custom_fields->insert($id, $custom_fields->fields[0]['id'], $cf_1, null); + } + + return $result; + } + + // modifyDurationFromWeekView - modifies a duration of an existing record from a week view post. + static function modifyDurationFromWeekView($fields, $err) { + global $i18n; + global $user; + + // Possible errors: 1) Overlap if the existing record has start time. 2) Going beyond 24 hour boundary. + // TODO: rename this function. + // Handle different errors with specific error messages. + if (!ttWeekViewHelper::canModify($fields['tt_log_id'], $fields['duration'], $err)) { + // $err->add($i18n->getKey('error.overlap')); + return false; + } + + $mdb2 = getConnection(); + $duration = $fields['duration']; + $tt_log_id = $fields['tt_log_id']; + $user_id = $user->getActiveUser(); + $sql = "update tt_log set duration = '$duration' where id = $tt_log_id and user_id = $user_id"; + $affected = $mdb2->exec($sql); + if (is_a($affected, 'PEAR_Error')) + return false; + + return true; + } + + // canModify - determines if an already existing tt_log record + // can be modified with a new user-provided duration. + static function canModify($tt_log_id, $new_duration, $err) { + global $i18n; + $mdb2 = getConnection(); + + // Determine if we have start time in record, as further checking does not makes sense otherwise. + $sql = "select user_id, date, start, duration from tt_log where id = $tt_log_id"; + $res = $mdb2->query($sql); + if (!is_a($res, 'PEAR_Error')) { + if (!$res->numRows()) { + $err->add($i18n->getKey('error.db')); // This is not expected. + return false; + } + $val = $res->fetchRow(); + $oldDuration = $val['duration']; + if (!$val['start']) + return true; // There is no start time in the record, therefore safe to modify. + } + + // We do have start time. + // Quick test if new duration is less then already existing. + $newMinutes = ttTimeHelper::toMinutes($new_duration); + $oldMinutes = ttTimeHelper::toMinutes($oldDuration); + if ($newMinutes < $oldMinutes) + return true; // Safe to modify. + + // Does the new duration put the record beyond 24:00 boundary? + $startMinutes = ttTimeHelper::toMinutes($val['start']); + $newEndMinutes = $startMinutes + $newMinutes; + if ($newEndMinutes > 1440) { + // Invalid duration, as new duration puts the record beyond current day. + $err->add($i18n->getKey('error.field'), $i18n->getKey('label.duration')); + return false; + } + + // Does the new duration causes the record to overlap with others? + $user_id = $val['user_id']; + $date = $val['date']; + $startMinutes = ttTimeHelper::toMinutes($val['start']); + $start = ttTimeHelper::toAbsDuration($startMinutes); + $finish = ttTimeHelper::toAbsDuration($newEndMinutes); + if (ttTimeHelper::overlaps($user_id, $date, $start, $finish, $tt_log_id)) { + $err->add($i18n->getKey('error.overlap')); + return false; + } + + return true; // There are no conflicts, safe to modify. + } } diff --git a/WEB-INF/templates/footer.tpl b/WEB-INF/templates/footer.tpl index cb4b19b3..a18ab1e0 100644 --- a/WEB-INF/templates/footer.tpl +++ b/WEB-INF/templates/footer.tpl @@ -12,7 +12,7 @@
-
 Anuko Time Tracker 1.13.7.3725 | Copyright © Anuko | +  Anuko Time Tracker 1.13.7.3726 | Copyright © Anuko | {$i18n.footer.credits} | {$i18n.footer.license} | {$i18n.footer.improve} diff --git a/week.php b/week.php index f4bde294..7afcb401 100644 --- a/week.php +++ b/week.php @@ -116,7 +116,7 @@ $lockedDays = ttWeekViewHelper::getLockedDaysForWeek($startDate->toString(DB_DAT // Build data array for the table. Format is described in the function.. $dataArray = ttWeekViewHelper::getDataForWeekView($user->getActiveUser(), $startDate->toString(DB_DATEFORMAT), $endDate->toString(DB_DATEFORMAT), $dayHeaders); // Build day totals (total durations for each day in week). -$dayTotals = ttTimeHelper::getDayTotals($dataArray, $dayHeaders); +$dayTotals = ttWeekViewHelper::getDayTotals($dataArray, $dayHeaders); // Define rendering class for a label field to the left of durations. class LabelCellRenderer extends DefaultCellRenderer { @@ -361,7 +361,7 @@ if ($request->isPost()) { $fields['start_date'] = $startDate->toString(DB_DATEFORMAT); // To be able to determine date for the entry using $dayHeader. $fields['duration'] = $postedDuration; $fields['browser_today'] = $request->getParameter('browser_today', null); - $result = ttTimeHelper::insertDurationFromWeekView($fields, $custom_fields, $err); + $result = ttWeekViewHelper::insertDurationFromWeekView($fields, $custom_fields, $err); } elseif ($postedDuration == null || 0 == ttTimeHelper::toMinutes($postedDuration)) { // Delete an already existing record here. $result = ttTimeHelper::delete($dataArray[$rowNumber][$dayHeader]['tt_log_id'], $user->getActiveUser()); @@ -369,7 +369,7 @@ if ($request->isPost()) { $fields = array(); $fields['tt_log_id'] = $dataArray[$rowNumber][$dayHeader]['tt_log_id']; $fields['duration'] = $postedDuration; - $result = ttTimeHelper::modifyDurationFromWeekView($fields, $err); + $result = ttWeekViewHelper::modifyDurationFromWeekView($fields, $err); } if (!$result) break; // Break out of the loop in case of first error. } -- 2.20.1