diff --git a/.gitignore b/.gitignore index 1377554..207784c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ *.swp +._* +.DS_Store diff --git a/Timecard/Timecard.API.php b/Timecard/Timecard.API.php index 32d54f5..a11ac53 100644 --- a/Timecard/Timecard.API.php +++ b/Timecard/Timecard.API.php @@ -22,6 +22,7 @@ class TimecardBug { public $timecard; public $estimate; public $timestamp; + public $timestamp_updates; public $updates; public $spent; @@ -30,7 +31,7 @@ class TimecardBug { * Create a new TimecardBug object. * @param int Bug ID * @param string Timecard string - * @param int Estimate of hours required + * @param float Estimate of hours required */ function __construct( $p_bug_id, $p_timecard='', $p_estimate=-1 ) { $this->bug_id = $p_bug_id < 0 ? 0 : $p_bug_id; @@ -143,27 +144,31 @@ function save() { } if ( $this->timecard != $this->__timecard ) { - if ( $this->__timecard && $this->timecard ) { - plugin_history_log( $this->bug_id, 'timecard_updated', $this->__timecard, $this->timecard, null, 'Timecard' ); + if ( plugin_config_get( 'track_history' ) ) { + if ( $this->__timecard && $this->timecard ) { + plugin_history_log( $this->bug_id, 'timecard_updated', $this->__timecard, $this->timecard, null, 'Timecard' ); - } else if ( $this->timecard ) { - plugin_history_log( $this->bug_id, 'timecard_added', $this->timecard, '', null, 'Timecard' ); + } else if ( $this->timecard ) { + plugin_history_log( $this->bug_id, 'timecard_added', $this->timecard, '', null, 'Timecard' ); - } else if ( $this->__timecard ) { - plugin_history_log( $this->bug_id, 'timecard_removed', $this->__timecard, ' ', null, 'Timecard' ); + } else if ( $this->__timecard ) { + plugin_history_log( $this->bug_id, 'timecard_removed', $this->__timecard, ' ', null, 'Timecard' ); + } } $this->__timecard = $this->timecard; } if ( $this->estimate != $this->__estimate ) { - if ( $this->estimate >= 0 && $this->__estimate >= 0 ) { - plugin_history_log( $this->bug_id, 'estimate_updated', $this->__estimate, $this->estimate, null, 'Timecard' ); + if ( plugin_config_get( 'track_history' ) ) { + if ( $this->estimate >= 0 && $this->__estimate >= 0 ) { + plugin_history_log( $this->bug_id, 'estimate_updated', $this->__estimate, $this->estimate, null, 'Timecard' ); - } else if ( $this->estimate >= 0 ) { - plugin_history_log( $this->bug_id, 'estimate_added', $this->estimate, '', null, 'Timecard' ); + } else if ( $this->estimate >= 0 ) { + plugin_history_log( $this->bug_id, 'estimate_added', $this->estimate, '', null, 'Timecard' ); - } else if ( $this->__estimate >= 0 ) { - plugin_history_log( $this->bug_id, 'estimate_removed', $this->__estimate, ' ', null, 'Timecard' ); + } else if ( $this->__estimate >= 0 ) { + plugin_history_log( $this->bug_id, 'estimate_removed', $this->__estimate, ' ', null, 'Timecard' ); + } } $this->__estimate = $this->estimate; } @@ -187,6 +192,28 @@ function calculate() { } } + /** + * Calculate last timestamp of updates. + */ + function calculateTimestampUpdates() { + $this->load_updates(); + + $this->timestamp_updates = $this->timestamp; + foreach ( $this->updates as $t_update ) { + if ($t_update->timestamp > $this->timestamp_updates) + $this->timestamp_updates = $t_update->timestamp; + } + } + + /** + * Get last timestamp of updates. + */ + function getTimestampUpdates() { + if (is_null($this->timestamp_updates)) + $this->calculateTimestampUpdates(); + return $this->timestamp_updates; + } + } /** @@ -340,13 +367,15 @@ function save() { $this->bug_id, $this->bugnote_id, $this->user_id, - $this->timestamp, + $this->timestamp = db_now(), $this->spent, ) ); $this->id = db_insert_id( $t_update_table ); - plugin_history_log( $this->bug_id, 'time_spent_added', $this->spent . $t_hours, '', null, 'Timecard' ); + if ( plugin_config_get( 'track_history' ) ) { + plugin_history_log( $this->bug_id, 'time_spent_added', $this->spent . $t_hours, '', null, 'Timecard' ); + } } else { #existing $t_query = "UPDATE $t_update_table SET @@ -367,7 +396,9 @@ function save() { ) ); if ( $this->spent != $this->__spent ) { - plugin_history_log( $this->bug_id, 'time_spent_updated', $this->__spent . $t_hours, $this->spent . $t_hours, null, 'Timecard' ); + if ( plugin_config_get( 'track_history' ) ) { + plugin_history_log( $this->bug_id, 'time_spent_updated', $this->__spent . $t_hours, $this->spent . $t_hours, null, 'Timecard' ); + } $this->__spent = $this->spent; } } @@ -380,7 +411,9 @@ function delete() { $t_query = "DELETE FROM $t_update_table WHERE id=" . db_param(); db_query_bound( $t_query, array( $this->id ) ); - plugin_history_log( $this->bug_id, 'time_spent_removed', $this->__spent . $t_hours, '', null, 'Timecard' ); + if ( plugin_config_get( 'track_history' ) ) { + plugin_history_log( $this->bug_id, 'time_spent_removed', $this->__spent . $t_hours, '', null, 'Timecard' ); + } $this->id = 0; } } diff --git a/Timecard/Timecard.php b/Timecard/Timecard.php index fcbec62..0b197df 100644 --- a/Timecard/Timecard.php +++ b/Timecard/Timecard.php @@ -48,6 +48,7 @@ function config() { 'use_estimates' => OFF, 'use_updates' => ON, 'use_timecard' => OFF, + 'track_history' => ON, ); } @@ -126,7 +127,7 @@ function report_bug( $p_event, $p_data, $p_bug_id ) { if ( is_blank( $t_estimate ) ) { $t_bug->estimate = -1; } else { - $t_bug->estimate = gpc_get_int( 'plugin_timecard_estimate', 0 ); + $t_bug->estimate = gpc_get_float( 'plugin_timecard_estimate', 0 ); } } @@ -193,12 +194,14 @@ function update_bug( $p_event, $p_bug_data, $p_bug_id ) { $t_bug = TimecardBug::load( $p_bug_id, true ); if ( $t_use_estimates ) { - $t_estimate = gpc_get_string( 'plugin_timecard_estimate', '' ); + $t_estimate = gpc_get_float( 'plugin_timecard_estimate', '' ); - if ( !is_numeric( $t_estimate ) ) { - $t_bug->estimate = -1; + if ( !is_float( $t_estimate ) ) { + if (gpc_isset($t_estimate)) { + $t_bug->estimate = -1; + } } else { - $t_bug->estimate = gpc_get_int( 'plugin_timecard_estimate', 0 ); + $t_bug->estimate = gpc_get_float( 'plugin_timecard_estimate', 0 ); } } @@ -349,7 +352,7 @@ function bugnote_add( $p_event, $p_bug_id, $p_bugnote_id ) { return; } - $f_spent = gpc_get_int( 'plugin_timecard_spent', 0 ); + $f_spent = gpc_get_float( 'plugin_timecard_spent', 0 ); if ( $f_spent > 0 ) { $t_update = new TimecardUpdate( $p_bug_id, $p_bugnote_id, auth_get_current_user_id(), $f_spent ); $t_update->save(); @@ -389,7 +392,7 @@ function bugnote_edit( $p_event, $p_bug_id, $p_bugnote_id ) { } $f_update_id = gpc_get_int( 'plugin_timecard_id', 0 ); - $f_spent = gpc_get_int( 'plugin_timecard_spent', 0 ); + $f_spent = gpc_get_float( 'plugin_timecard_spent', 0 ); if ( $f_update_id > 0 ) { $t_update = TimecardUpdate::load( $f_update_id ); @@ -469,6 +472,15 @@ function schema() { array( 'AddColumnSQL', array( plugin_table( 'estimate' ), " timestamp I NOTNULL DEFAULT '0' " ) ), + array( 'AlterColumnSQL', array( plugin_table( 'estimate' ), " + estimate F(15,2) NOTNULL DEFAULT '0' + " ) ), + array( 'AlterColumnSQL', array( plugin_table( 'update' ), " + spent F(15,2) NOTNULL DEFAULT '0' + " ) ), + array( 'AlterColumnSQL', array( plugin_table( 'update' ), " + timestamp I NOTNULL DEFAULT '0' + " ) ), ); } @@ -486,3 +498,36 @@ function add_columns() { } } +/** + * Retrieve an integer GPC variable. Uses gpc_get(). + * If you pass in *no* default, an error will be triggered if + * the variable does not exist + * @param string $p_var_name + * @param float $p_default (optional) + * @return float|null + */ +function gpc_get_float( $p_var_name, $p_default = null ) { + # Don't pass along a default unless one was given to us + # otherwise we prevent an error being triggered + $args = func_get_args(); + $t_result = call_user_func_array( 'gpc_get', $args ); + + if( is_array( $t_result ) ) { + error_parameters( $p_var_name ); + trigger_error( ERROR_GPC_ARRAY_UNEXPECTED, ERROR ); + } + $t_val = str_replace( ' ', '', trim( $t_result ) ); + $t_val = str_replace( ',', '.', trim( $t_result ) ); + + if ($t_val != (string)(float)$t_val) { + if (!is_null($p_default) && $p_default === $t_val) + { + return $t_val; + } + error_parameters( $p_var_name ); + trigger_error( ERROR_GPC_NOT_NUMBER, ERROR ); + } + + return (float) $t_val; +} + diff --git a/Timecard/lang/strings_english.txt b/Timecard/lang/strings_english.txt index 97582ab..7d3fb3b 100644 --- a/Timecard/lang/strings_english.txt +++ b/Timecard/lang/strings_english.txt @@ -20,8 +20,8 @@ $s_plugin_Timecard_default_timecard = 'Default Timecard'; $s_plugin_Timecard_timecard = 'Timecard'; $s_plugin_Timecard_estimate = 'Time Estimate'; $s_plugin_Timecard_estimate_zero = 'No estimate'; -$s_plugin_Timecard_estimate_display = '%d hours total (%d hours remaining)'; -$s_plugin_Timecard_estimate_over = '%d hours total (%d hours overrun)'; +$s_plugin_Timecard_estimate_display = '%01.2f hours total (%01.2f hours remaining)'; +$s_plugin_Timecard_estimate_over = '%01.2f hours total (%01.2f hours overrun)'; $s_plugin_Timecard_time_spent = 'Time Spent'; $s_plugin_Timecard_hours_remaining = 'Hours Remaining'; $s_plugin_Timecard_total_remaining = 'Total Hours Remaining'; @@ -40,6 +40,7 @@ $s_plugin_Timecard_enabled_features = 'Enabled Features'; $s_plugin_Timecard_use_estimates = 'Time Estimation'; $s_plugin_Timecard_use_updates = 'Time Spent Updates'; $s_plugin_Timecard_use_timecard = 'Timecard Strings'; +$s_plugin_Timecard_track_history = 'Track History'; $s_plugin_Timecard_timecard_added = 'Timecard Added'; $s_plugin_Timecard_timecard_updated = 'Timecard Updated'; @@ -50,4 +51,5 @@ $s_plugin_Timecard_estimate_removed = 'Time Estimate Removed'; $s_plugin_Timecard_time_spent_added = 'Time Spent Added'; $s_plugin_Timecard_time_spent_updated = 'Time Spent Updated'; $s_plugin_Timecard_time_spent_removed = 'Time Spent Removed'; +$s_plugin_Timecard_unknown = 'Unknown'; diff --git a/Timecard/lang/strings_german.txt b/Timecard/lang/strings_german.txt index 8511a2d..8295d9d 100644 --- a/Timecard/lang/strings_german.txt +++ b/Timecard/lang/strings_german.txt @@ -21,8 +21,8 @@ $s_plugin_Timecard_default_timecard = 'Default Timecard'; $s_plugin_Timecard_timecard = 'Timecard'; $s_plugin_Timecard_estimate = 'Zeitschätzung'; $s_plugin_Timecard_estimate_zero = 'Keine Zeitschätzung'; -$s_plugin_Timecard_estimate_display = '%d Stunden total (%d Stunden verbleiben)'; -$s_plugin_Timecard_estimate_over = '%d Stunden total (%d Stunden überschritten)'; +$s_plugin_Timecard_estimate_display = '%01.2f Stunden total ((%01.2f Stunden verbleiben)'; +$s_plugin_Timecard_estimate_over = '%01.2f Stunden total (%01.2f Stunden überschritten)'; $s_plugin_Timecard_time_spent = 'Verbrauchte Zeit'; $s_plugin_Timecard_hours_remaining = 'Verbleibende Stunden'; $s_plugin_Timecard_total_remaining = 'Gesamte verbleibende Stunden'; @@ -41,6 +41,7 @@ $s_plugin_Timecard_enabled_features = 'Aktivierte Funktionen'; $s_plugin_Timecard_use_estimates = 'Zeitschätzung'; $s_plugin_Timecard_use_updates = 'Verbrauchte Zeit Updates'; $s_plugin_Timecard_use_timecard = 'Timecard Strings'; +$s_plugin_Timecard_track_history = 'Trackaufzeichnung'; $s_plugin_Timecard_timecard_added = 'Timecard Added'; $s_plugin_Timecard_timecard_updated = 'Timecard Updated'; @@ -51,4 +52,4 @@ $s_plugin_Timecard_estimate_removed = 'Zeitschätzung entfernt'; $s_plugin_Timecard_time_spent_added = 'Verbrauchte Zeit hinzugefügt'; $s_plugin_Timecard_time_spent_updated = 'Verbrauchte Zeit aktualisiert'; $s_plugin_Timecard_time_spent_removed = 'Verbrauchte Zeit entfernt'; - +$s_plugin_Timecard_unknown = 'Unbekannt'; diff --git a/Timecard/pages/config_page.php b/Timecard/pages/config_page.php index 87ec959..1f8d726 100644 --- a/Timecard/pages/config_page.php +++ b/Timecard/pages/config_page.php @@ -61,6 +61,8 @@

+
diff --git a/Timecard/pages/config_update.php b/Timecard/pages/config_update.php index 9c5e26c..e94df8b 100644 --- a/Timecard/pages/config_update.php +++ b/Timecard/pages/config_update.php @@ -30,6 +30,7 @@ function maybe_set_option( $name, $value ) { maybe_set_option( 'use_estimates', gpc_get_bool( 'use_estimates', OFF ) ); maybe_set_option( 'use_updates', gpc_get_bool( 'use_updates', OFF ) ); maybe_set_option( 'use_timecard', gpc_get_bool( 'use_timecard', OFF ) ); +maybe_set_option( 'track_history', gpc_get_bool( 'track_history', OFF ) ); form_security_purge( 'plugin_Timecard_config_update' ); print_successful_redirect( plugin_page( 'config_page', true ) ); diff --git a/Timecard/pages/log_time.php b/Timecard/pages/log_time.php index b585760..41ef7ce 100644 --- a/Timecard/pages/log_time.php +++ b/Timecard/pages/log_time.php @@ -14,12 +14,12 @@ form_security_validate( 'plugin_Timecard_log_time' ); $f_bug_id = gpc_get_int( 'bug_id' ); -$f_spent = gpc_get_int( 'spent', 0 ); +$f_spent = gpc_get_float( 'spent', 0 ); access_ensure_bug_level( plugin_config_get( 'update_threshold' ), $f_bug_id ); if ( $f_spent > 0 ) { - $t_update = new TimecardUpdate( $f_bug_id, 0, auth_get_current_user_cookie(), $f_spent ); + $t_update = new TimecardUpdate( $f_bug_id, 0, auth_get_current_user_id(), $f_spent ); $t_update->save(); } else { trigger_error( ERROR_GENERIC, ERROR ); diff --git a/Timecard/pages/view_timecard.php b/Timecard/pages/view_timecard.php index 61d94a1..ab38f5e 100644 --- a/Timecard/pages/view_timecard.php +++ b/Timecard/pages/view_timecard.php @@ -105,7 +105,14 @@ } $t_timecard->status = MantisEnum::getLabel( config_get( 'status_enum_string' ), $t_row['status'] ); - $t_timecard->diff = time_get_diff( $t_timecard->timestamp ); + $timestamp = $t_timecard->getTimestampUpdates(); + if (!empty($timestamp)) { + $t_timecard->diff = time_get_diff( $timestamp ); + } + else + { + $t_timecard->diff = plugin_lang_get('unknown'); + } if( $t_timecard->estimate < 0 ){ $t_timecard->estimate = plugin_lang_get( 'estimate_zero' );