From ce628dfba39a649e3184811f8678487412f2613b Mon Sep 17 00:00:00 2001 From: Francisco Mancardi Date: Mon, 5 Mar 2018 21:10:28 +0100 Subject: [PATCH 1/9] label changed from Category to Activity to avoid confusion with MantisBT standard category concept. --- TimeTracking/lang/strings_english.txt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) mode change 100755 => 100644 TimeTracking/lang/strings_english.txt diff --git a/TimeTracking/lang/strings_english.txt b/TimeTracking/lang/strings_english.txt old mode 100755 new mode 100644 index e9ccfd3..e62ac0b --- a/TimeTracking/lang/strings_english.txt +++ b/TimeTracking/lang/strings_english.txt @@ -1,10 +1,10 @@ Date: Mon, 5 Mar 2018 21:11:38 +0100 Subject: [PATCH 2/9] new configuration option enabled_on_bugnote_add_form. config_update.php refactoring. --- TimeTracking/TimeTracking.php | 477 ++++++++++++++------------- TimeTracking/pages/config_page.php | 7 + TimeTracking/pages/config_update.php | 30 +- 3 files changed, 277 insertions(+), 237 deletions(-) diff --git a/TimeTracking/TimeTracking.php b/TimeTracking/TimeTracking.php index 9d1df69..8e86a42 100644 --- a/TimeTracking/TimeTracking.php +++ b/TimeTracking/TimeTracking.php @@ -20,239 +20,266 @@ */ class TimeTrackingPlugin extends MantisPlugin { - function register() { - plugin_require_api( 'core/constants.php' ); - - $this->name = plugin_lang_get( 'plugin_title' ); - $this->description = plugin_lang_get( 'plugin_description' ); - $this->page = 'config_page'; - - $this->version = '3.0-dev'; - $this->requires = array( - 'MantisCore' => '2.0.0' - ); - - $this->author = 'Elmar Schumacher, Michael Baker, Erwann Penet'; - $this->contact = ''; - $this->url = 'https://github.com/mantisbt-plugins/timetracking'; - } - - function hooks() { - return array( - 'EVENT_LAYOUT_RESOURCES' => 'resources', - 'EVENT_VIEW_BUG_EXTRA' => 'ev_view_bug', - 'EVENT_MENU_ISSUE' => 'timerecord_menu', - 'EVENT_MENU_MAIN' => 'showreport_menu', - 'EVENT_VIEW_BUGNOTE' => 'ev_view_bugnote', - 'EVENT_BUGNOTE_ADD_FORM' => 'ev_bugnote_add_form', - 'EVENT_BUGNOTE_DATA' => 'ev_bugnote_add_validate', - 'EVENT_BUGNOTE_ADD' => 'ev_bugnote_added', - 'EVENT_VIEW_BUG_DETAILS' => 'ev_view_bug_details', - 'EVENT_LAYOUT_CONTENT_BEGIN' => 'ev_layout_content_begin', - 'EVENT_FILTER_COLUMNS' => 'ev_register_columns', - ); - } - - function config() { - return array( - # old thresholds - /* - 'admin_own_threshold' => DEVELOPER, - 'view_others_threshold' => MANAGER, - 'admin_threshold' => ADMINISTRATOR, - */ - # new thresholds - 'view_threshold' => DEVELOPER, - 'edit_threshold' => DEVELOPER, - 'reporting_threshold' => MANAGER, - - 'stopwatch_enabled' => ON, - - 'categories' => '' - ); - } - - function init() { - plugin_require_api( 'core/timetracking_api.php' ); - plugin_require_api( 'core/stopwatch_api.php' ); - plugin_require_api( 'core/columns.php' ); - plugin_require_api( 'core/reports.php' ); - } - - function errors() { - return array( - TimeTracking\ERROR_INVALID_TIME_FORMAT => plugin_lang_get( 'ERROR_INVALID_TIME_FORMAT' ), - TimeTracking\ERROR_ID_NOT_EXISTS => plugin_lang_get( 'ERROR_ID_NOT_EXISTS' ), - ); - } - - function resources() { - $res = ''; - $res .= ''; - $res .= ''; - if( \TimeTracking\stopwatch_enabled() ) { - $res .= ''; - } - return $res; - } - - function ev_register_columns( $p_event ) { - return array( - new TimeTracking\ColumnTotalTime(), - new TimeTracking\ColumnMyTime(), - ); - } - - /** - * Show time tracking info within the bugnote activity area - */ - function ev_view_bugnote( $p_event, $p_bug_id, $p_note_id, $p_is_private ) { - $t_record = TimeTracking\get_record_for_bugnote( $p_note_id ); - if( !$t_record ) { - return; - } - if( TimeTracking\user_can_view_record_id( $t_record['id'] ) ) { - TimeTracking\print_bugnote_label_row( $t_record, $p_is_private ); - } - } - - /** - * Prints the time tracking inputs within the bugnote-add form - * @param type $p_event - * @param type $p_bug_id - */ - function ev_bugnote_add_form( $p_event, $p_bug_id ) { - if( TimeTracking\user_can_edit_bug_id( $p_bug_id ) ) { - TimeTracking\print_bugnote_add_form( $p_bug_id ); - } - } - - /** - * Validates time tracking submitted data when adding bugnotes - */ - function ev_bugnote_add_validate( $p_event, $p_bugnote_text, $p_bug_id ) { - $t_time_imput = gpc_get_string( 'plugin_timetracking_time_input', '' ); - if( !is_blank( $t_time_imput ) ) { - if( TimeTracking\user_can_edit_bug_id( $p_bug_id ) ) { - $t_parsed = TimeTracking\parse_gpc_time_record(); - } - } - return $p_bugnote_text; - } - - /** - * Creates a time tracking record from submitted data when adding bugnotes - */ - function ev_bugnote_added( $p_event, $p_bug_id, $p_bugnote_id ) { - $t_time_imput = gpc_get_string( 'plugin_timetracking_time_input', '' ); - if( !is_blank( $t_time_imput ) ) { - if( TimeTracking\user_can_edit_bug_id( $p_bug_id ) ) { - $t_record = TimeTracking\parse_gpc_time_record(); - $t_record['bugnote_id'] = $p_bugnote_id; - $t_record['bug_id'] = $p_bug_id; - TimeTracking\create_record( $t_record ); - } - } - } - - function ev_view_bug_details( $p_event, $p_bug_id ) { - if( TimeTracking\user_can_view_bug_id( $p_bug_id ) ) { - $t_records = TimeTracking\get_records_for_bug( $p_bug_id ); - if( $t_records ) { - TimeTracking\print_bug_details_row( $p_bug_id ); - } - } - } - - function ev_layout_content_begin( $p_event ) { - if( TimeTracking\stopwatch_enabled() && TimeTracking\stopwatch_exists() ) { - TimeTracking\print_stopwatch_header_control(); - } - } - - function ev_view_bug( $p_event, $p_bug_id ) { - if( TimeTracking\user_can_view_bug_id( $p_bug_id ) ) { - TimeTracking\print_bug_timetracking_section( $p_bug_id ); - } - } - - function schema() { - $schema[0] = - array( 'CreateTableSQL', array( plugin_table( 'data' ), " - id I NOTNULL UNSIGNED AUTOINCREMENT PRIMARY, - bug_id I DEFAULT NULL UNSIGNED, - user I DEFAULT NULL UNSIGNED, - expenditure_date T DEFAULT NULL, - hours F(15,3) DEFAULT NULL, - timestamp T DEFAULT NULL, - category C(255) DEFAULT NULL, - info C(255) DEFAULT NULL - " ) - ); - - $schema[1] = - array( - 'AddColumnSQL', - array( plugin_table( 'data' ), - " user_id I UNSIGNED, - date_created I UNSIGNED NOTNULL DEFAULT '1', - time_count I UNSIGNED NOTNULL DEFAULT '0', - time_exp_date I UNSIGNED NOTNULL DEFAULT '1', - bugnote_id I UNSIGNED" - ) - ); - - $schema[2] = array( 'UpdateFunction', 'date_migrate', array( plugin_table( 'data' ), 'id', 'expenditure_date', 'time_exp_date' ) ); - $schema[3] = array( 'UpdateFunction', 'date_migrate', array( plugin_table( 'data' ), 'id', 'timestamp', 'date_created' ) ); - $schema[4] = array( 'UpdateFunction', 'timetracking_update_hours', array() ); - $schema[5] = array( 'UpdateFunction', 'timetracking_update_user_id', array() ); - - $schema[6] = array( 'DropColumnSQL', array( plugin_table( 'data' ), 'user' ) ); - $schema[7] = array( 'DropColumnSQL', array( plugin_table( 'data' ), 'expenditure_date' ) ); - $schema[8] = array( 'DropColumnSQL', array( plugin_table( 'data' ), 'timestamp' ) ); - $schema[9] = array( 'DropColumnSQL', array( plugin_table( 'data' ), 'hours' ) ); - - return $schema; - } - - function timerecord_menu( $p_event, $p_bug_id ) { - if( TimeTracking\user_can_view_bug_id( $p_bug_id ) ) { - $t_href = '#timerecord'; - return array( plugin_lang_get( 'timerecord_menu' ) => $t_href ); - } - else { - return array (); - } - } - - function showreport_menu() { - return array( - array( - 'title' => plugin_lang_get( 'title' ), - 'access_level' => plugin_config_get( 'reporting_threshold' ), - 'url' => plugin_page( 'report_page' ), - 'icon' => 'fa-random' - ) - ); - } + function register() { + plugin_require_api( 'core/constants.php' ); + + $this->name = plugin_lang_get( 'plugin_title' ); + $this->description = plugin_lang_get( 'plugin_description' ); + $this->page = 'config_page'; + + $this->version = '3.0-dev-03-2018'; + $this->requires = array( + 'MantisCore' => '2.0.0' + ); + + $this->author = 'Elmar Schumacher, Michael Baker, Erwann Penet'; + $this->contact = ''; + $this->url = 'https://github.com/mantisbt-plugins/timetracking'; + } + + function hooks() { + return array( + 'EVENT_LAYOUT_RESOURCES' => 'resources', + 'EVENT_VIEW_BUG_EXTRA' => 'ev_view_bug', + 'EVENT_MENU_ISSUE' => 'timerecord_menu', + 'EVENT_MENU_MAIN' => 'showreport_menu', + 'EVENT_VIEW_BUGNOTE' => 'ev_view_bugnote', + 'EVENT_BUGNOTE_ADD_FORM' => 'ev_bugnote_add_form', + 'EVENT_BUGNOTE_DATA' => 'ev_bugnote_add_validate', + 'EVENT_BUGNOTE_ADD' => 'ev_bugnote_added', + 'EVENT_VIEW_BUG_DETAILS' => 'ev_view_bug_details', + 'EVENT_LAYOUT_CONTENT_BEGIN' => 'ev_layout_content_begin', + 'EVENT_FILTER_COLUMNS' => 'ev_register_columns', + ); + } + + /** + * + */ + function config() { + return self::getConfig(); + } + + /** + * + */ + function init() { + plugin_require_api( 'core/timetracking_api.php' ); + plugin_require_api( 'core/stopwatch_api.php' ); + plugin_require_api( 'core/columns.php' ); + plugin_require_api( 'core/reports.php' ); + } + + /** + * + */ + function errors() { + return array( + TimeTracking\ERROR_INVALID_TIME_FORMAT => plugin_lang_get( 'ERROR_INVALID_TIME_FORMAT' ), + TimeTracking\ERROR_ID_NOT_EXISTS => plugin_lang_get( 'ERROR_ID_NOT_EXISTS' ), + ); + } + + /** + * + */ + function resources() { + $res = ''; + $res .= ''; + $res .= ''; + if( \TimeTracking\stopwatch_enabled() ) { + $res .= ''; + } + return $res; + } + + /** + * + */ + function ev_register_columns( $p_event ) { + return array( + new TimeTracking\ColumnTotalTime(), + new TimeTracking\ColumnMyTime(), + ); + } + + /** + * Show time tracking info within the bugnote activity area + */ + function ev_view_bugnote( $p_event, $p_bug_id, $p_note_id, $p_is_private ) { + $t_record = TimeTracking\get_record_for_bugnote( $p_note_id ); + if( !$t_record ) { + return; + } + if( TimeTracking\user_can_view_record_id( $t_record['id'] ) ) { + TimeTracking\print_bugnote_label_row( $t_record, $p_is_private ); + } + } + + /** + * Prints the time tracking inputs within the bugnote-add form + * @param type $p_event + * @param type $p_bug_id + */ + function ev_bugnote_add_form( $p_event, $p_bug_id ) { + $t_enabled_on_bugnote_add_form = plugin_config_get('enabled_on_bugnote_add_form'); + if( $t_enabled_on_bugnote_add_form ) { + if( TimeTracking\user_can_edit_bug_id( $p_bug_id ) ) { + TimeTracking\print_bugnote_add_form( $p_bug_id ); + } + } + } + + /** + * Validates time tracking submitted data when adding bugnotes + */ + function ev_bugnote_add_validate( $p_event, $p_bugnote_text, $p_bug_id ) { + $t_time_imput = gpc_get_string( 'plugin_timetracking_time_input', '' ); + if( !is_blank( $t_time_imput ) ) { + if( TimeTracking\user_can_edit_bug_id( $p_bug_id ) ) { + $t_parsed = TimeTracking\parse_gpc_time_record(); + } + } + return $p_bugnote_text; + } + + /** + * Creates a time tracking record from submitted data when adding bugnotes + */ + function ev_bugnote_added( $p_event, $p_bug_id, $p_bugnote_id ) { + $t_time_imput = gpc_get_string( 'plugin_timetracking_time_input', '' ); + if( !is_blank( $t_time_imput ) ) { + if( TimeTracking\user_can_edit_bug_id( $p_bug_id ) ) { + $t_record = TimeTracking\parse_gpc_time_record(); + $t_record['bugnote_id'] = $p_bugnote_id; + $t_record['bug_id'] = $p_bug_id; + TimeTracking\create_record( $t_record ); + } + } + } + + function ev_view_bug_details( $p_event, $p_bug_id ) { + if( TimeTracking\user_can_view_bug_id( $p_bug_id ) ) { + $t_records = TimeTracking\get_records_for_bug( $p_bug_id ); + if( $t_records ) { + TimeTracking\print_bug_details_row( $p_bug_id ); + } + } + } + + function ev_layout_content_begin( $p_event ) { + if( TimeTracking\stopwatch_enabled() && TimeTracking\stopwatch_exists() ) { + TimeTracking\print_stopwatch_header_control(); + } + } + + function ev_view_bug( $p_event, $p_bug_id ) { + if( TimeTracking\user_can_view_bug_id( $p_bug_id ) ) { + TimeTracking\print_bug_timetracking_section( $p_bug_id ); + } + } + + /** + * + */ + static function getConfig() { + return array( + # old thresholds + /* + 'admin_own_threshold' => DEVELOPER, + 'view_others_threshold' => MANAGER, + 'admin_threshold' => ADMINISTRATOR, + */ + # new thresholds + 'view_threshold' => DEVELOPER, + 'edit_threshold' => DEVELOPER, + 'reporting_threshold' => MANAGER, + + 'stopwatch_enabled' => ON, + + 'categories' => '', + 'enabled_on_bugnote_add_form' => ON + ); + + } + + function schema() { + $schema[0] = + array( 'CreateTableSQL', array( plugin_table( 'data' ), " + id I NOTNULL UNSIGNED AUTOINCREMENT PRIMARY, + bug_id I DEFAULT NULL UNSIGNED, + user I DEFAULT NULL UNSIGNED, + expenditure_date T DEFAULT NULL, + hours F(15,3) DEFAULT NULL, + timestamp T DEFAULT NULL, + category C(255) DEFAULT NULL, + info C(255) DEFAULT NULL + " ) + ); + + $schema[1] = + array( + 'AddColumnSQL', + array( plugin_table( 'data' ), + " user_id I UNSIGNED, + date_created I UNSIGNED NOTNULL DEFAULT '1', + time_count I UNSIGNED NOTNULL DEFAULT '0', + time_exp_date I UNSIGNED NOTNULL DEFAULT '1', + bugnote_id I UNSIGNED" + ) + ); + + $schema[2] = array( 'UpdateFunction', 'date_migrate', array( plugin_table( 'data' ), 'id', 'expenditure_date', 'time_exp_date' ) ); + $schema[3] = array( 'UpdateFunction', 'date_migrate', array( plugin_table( 'data' ), 'id', 'timestamp', 'date_created' ) ); + $schema[4] = array( 'UpdateFunction', 'timetracking_update_hours', array() ); + $schema[5] = array( 'UpdateFunction', 'timetracking_update_user_id', array() ); + + $schema[6] = array( 'DropColumnSQL', array( plugin_table( 'data' ), 'user' ) ); + $schema[7] = array( 'DropColumnSQL', array( plugin_table( 'data' ), 'expenditure_date' ) ); + $schema[8] = array( 'DropColumnSQL', array( plugin_table( 'data' ), 'timestamp' ) ); + $schema[9] = array( 'DropColumnSQL', array( plugin_table( 'data' ), 'hours' ) ); + + return $schema; + } + + function timerecord_menu( $p_event, $p_bug_id ) { + if( TimeTracking\user_can_view_bug_id( $p_bug_id ) ) { + $t_href = '#timerecord'; + return array( plugin_lang_get( 'timerecord_menu' ) => $t_href ); + } + else { + return array (); + } + } + + function showreport_menu() { + return array( + array( + 'title' => plugin_lang_get( 'title' ), + 'access_level' => plugin_config_get( 'reporting_threshold' ), + 'url' => plugin_page( 'report_page' ), + 'icon' => 'fa-random' + ) + ); + } } # class end function install_timetracking_update_hours() { - $t_query = 'UPDATE ' . plugin_table( 'data' ) . ' SET time_count = hours*3600' - . ' WHERE time_count = 0'; - db_query( $t_query ); + $t_query = 'UPDATE ' . plugin_table( 'data' ) . ' SET time_count = hours*3600' + . ' WHERE time_count = 0'; + db_query( $t_query ); - # Return 2 because that's what ADOdb/DataDict does when things happen properly - return 2; + # Return 2 because that's what ADOdb/DataDict does when things happen properly + return 2; } function install_timetracking_update_user_id() { - $t_query = 'UPDATE ' . plugin_table( 'data' ) . ' SET user_id = user' - . ' WHERE user_id IS NULL'; - db_query( $t_query ); + $t_query = 'UPDATE ' . plugin_table( 'data' ) . ' SET user_id = user' + . ' WHERE user_id IS NULL'; + db_query( $t_query ); - # Return 2 because that's what ADOdb/DataDict does when things happen properly - return 2; + # Return 2 because that's what ADOdb/DataDict does when things happen properly + return 2; } diff --git a/TimeTracking/pages/config_page.php b/TimeTracking/pages/config_page.php index a36c73a..3654f94 100644 --- a/TimeTracking/pages/config_page.php +++ b/TimeTracking/pages/config_page.php @@ -76,6 +76,13 @@ + + + + > + + + diff --git a/TimeTracking/pages/config_update.php b/TimeTracking/pages/config_update.php index d1d6c66..34fe524 100644 --- a/TimeTracking/pages/config_update.php +++ b/TimeTracking/pages/config_update.php @@ -21,21 +21,27 @@ http://www.mantisbt.org/forums/viewtopic.php?f=4&t=589 */ -form_security_validate( 'plugin_TimeTracking_config_update' ); +$fid = 'plugin_TimeTracking_config_update'; +form_security_validate( $fid ); access_ensure_global_level( config_get( 'manage_plugin_threshold' ) ); -function maybe_set_option( $name, $value ) { - if ( $value != plugin_config_get( $name ) ) { - plugin_config_set( $name, $value ); - } -} -maybe_set_option( 'edit_threshold', gpc_get_int( 'edit_threshold' ) ); -maybe_set_option( 'view_threshold', gpc_get_int( 'view_threshold' ) ); -maybe_set_option( 'reporting_threshold', gpc_get_int( 'reporting_threshold' ) ); -maybe_set_option( 'categories', gpc_get_string( 'categories' ) ); -maybe_set_option( 'stopwatch_enabled', gpc_get_int( 'stopwatch_enabled', OFF ) ); +$config = \TimeTrackingPlugin::getConfig(); +foreach($config as $opt => $default ) { + + if( is_int($default) ) { + $fn = 'gpc_get_int'; + if( strpos($opt, 'enabled') !== FALSE ) { + // is a bool like 1/0 + $default = OFF; + } + } -form_security_purge( 'plugin_TimeTracking_config_update' ); + if( is_string($default) ) { + $fn = 'gpc_get_string'; + } + plugin_config_set( $opt, $fn( $opt, $default ) ); +} +form_security_purge( $fid ); print_successful_redirect( plugin_page( 'config_page', true ) ); From 35f17d92a93f1bfcf69c150e36af628d44dcc3df Mon Sep 17 00:00:00 2001 From: Francisco Mancardi Date: Mon, 5 Mar 2018 23:06:43 +0100 Subject: [PATCH 3/9] add project_id on to get configuration option --- TimeTracking/TimeTracking.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/TimeTracking/TimeTracking.php b/TimeTracking/TimeTracking.php index 8e86a42..47964a6 100644 --- a/TimeTracking/TimeTracking.php +++ b/TimeTracking/TimeTracking.php @@ -122,7 +122,9 @@ function ev_view_bugnote( $p_event, $p_bug_id, $p_note_id, $p_is_private ) { * @param type $p_bug_id */ function ev_bugnote_add_form( $p_event, $p_bug_id ) { - $t_enabled_on_bugnote_add_form = plugin_config_get('enabled_on_bugnote_add_form'); + + $t_project_id = bug_get_field( $p_bug_id, 'project_id' ); + $t_enabled_on_bugnote_add_form = plugin_config_get('enabled_on_bugnote_add_form',null,false,null,$t_project_id); if( $t_enabled_on_bugnote_add_form ) { if( TimeTracking\user_can_edit_bug_id( $p_bug_id ) ) { TimeTracking\print_bugnote_add_form( $p_bug_id ); From 63c88ca481a062c97db9ee8cd0c9a843a1798a4e Mon Sep 17 00:00:00 2001 From: Francisco Mancardi Date: Mon, 5 Mar 2018 23:15:57 +0100 Subject: [PATCH 4/9] config option renamed --- TimeTracking/TimeTracking.php | 2 +- TimeTracking/lang/strings_english.txt | 2 +- TimeTracking/pages/config_page.php | 148 +++++++++++++------------- TimeTracking/pages/config_update.php | 2 +- 4 files changed, 77 insertions(+), 77 deletions(-) diff --git a/TimeTracking/TimeTracking.php b/TimeTracking/TimeTracking.php index 47964a6..df52a67 100644 --- a/TimeTracking/TimeTracking.php +++ b/TimeTracking/TimeTracking.php @@ -200,7 +200,7 @@ static function getConfig() { 'stopwatch_enabled' => ON, 'categories' => '', - 'enabled_on_bugnote_add_form' => ON + 'on_bugnote_enabled' => ON ); } diff --git a/TimeTracking/lang/strings_english.txt b/TimeTracking/lang/strings_english.txt index e62ac0b..62495ee 100644 --- a/TimeTracking/lang/strings_english.txt +++ b/TimeTracking/lang/strings_english.txt @@ -75,4 +75,4 @@ $s_plugin_TimeTracking_reset = 'Reset'; $s_plugin_TimeTracking_copy_to_time_input = 'Copy to time tracking input'; # -$s_plugin_TimeTracking_config_enabled_on_bugnote_add_form = 'Enabled on Bugnote Form'; +$s_plugin_TimeTracking_config_on_bugnote_enabled = 'Enabled on Bugnote Form'; diff --git a/TimeTracking/pages/config_page.php b/TimeTracking/pages/config_page.php index 3654f94..4604f01 100644 --- a/TimeTracking/pages/config_page.php +++ b/TimeTracking/pages/config_page.php @@ -18,7 +18,7 @@ Notes: Based on the Time Tracking plugin by Elmar: 2005 by Elmar Schumacher - GAMBIT Consulting GmbH - http://www.mantisbt.org/forums/viewtopic.php?f=4&t=589 + http://www.mantisbt.org/forums/viewtopic.php?f=4&t=589 */ @@ -29,80 +29,80 @@ ?>
-
-
-
-
-
-

- - -

-
-
-
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
-
- > - -
- > - -
- -
-
-
-
- -
-
-
+
+
+ +
+
+

+ + +

+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ > + +
+ > + +
+ +
+
+
+
+ +
+
+
- -
+ +
Date: Tue, 6 Mar 2018 10:16:20 +0100 Subject: [PATCH 5/9] Added activity date on report --- TimeTracking/core/reports.php | 10 ++++++---- TimeTracking/core/timetracking_api.php | 2 +- TimeTracking/pages/add_record.php | 1 + 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/TimeTracking/core/reports.php b/TimeTracking/core/reports.php index 14910d7..70224c1 100644 --- a/TimeTracking/core/reports.php +++ b/TimeTracking/core/reports.php @@ -12,7 +12,7 @@ class Report { * @var array */ static $column_keys = array( - 'user', 'issue', 'project', 'time_category', + 'user', 'issue', 'project', 'time_category', 'time_exp_date', ); /** @@ -20,7 +20,7 @@ class Report { * @var array */ static $default_keys = array( - 'user', 'time_category', + 'user', 'time_category', 'time_exp_date', ); /** @@ -36,6 +36,7 @@ class Report { 'time_category' => 'TT.category', 'exp_date' => 'TT.time_exp_date', 'date_created' => 'TT.date_created', + 'time_exp_date' => " FROM_UNIXTIME(TT.time_exp_date,'%d-%m-%Y') ", ); /** @@ -49,6 +50,7 @@ class Report { 'time_category' => 'TT.category', 'exp_date' => 'TT.time_exp_date', 'date_created' => 'TT.date_created', + 'time_exp_date' => 'TT.time_exp_date', ); /** @@ -619,10 +621,10 @@ public function print_inputs_group_by() { class ReportForBug extends Report { # override parent definiiton for keys, only to those that make sens for a singe issue static $column_keys = array( - 'user', 'time_category', + 'user', 'time_category', 'time_exp_date' ); static $default_keys = array( - 'user', 'time_category', + 'user', 'time_category', 'time_exp_date' ); protected $bug_id; diff --git a/TimeTracking/core/timetracking_api.php b/TimeTracking/core/timetracking_api.php index f5f36c1..e91adc6 100644 --- a/TimeTracking/core/timetracking_api.php +++ b/TimeTracking/core/timetracking_api.php @@ -100,7 +100,7 @@ function cache_records_bug_ids( array $p_bug_id ) { for( $i = 0; $i < $t_count; $i++ ) { $t_ids_dbparams[] = db_param(); } - $t_query = 'SELECT T.* FROM {bug} B JOIN ' . plugin_table( 'data' ) . ' T' + $t_query = 'SELECT T.* FROM {bug} B JOIN ' . plugin_table( 'data', __NAMESPACE__ ) . ' T' . ' ON B.id = T.bug_id WHERE T.bug_id IN (' . implode( ',', $t_ids_dbparams ) . ')'; $t_result = db_query( $t_query, array_values( $t_bug_ids_to_search) ); diff --git a/TimeTracking/pages/add_record.php b/TimeTracking/pages/add_record.php index c910bdb..06f3842 100644 --- a/TimeTracking/pages/add_record.php +++ b/TimeTracking/pages/add_record.php @@ -33,6 +33,7 @@ form_security_purge( 'plugin_TimeTracking_add_record' ); +$f_bug_id = gpc_get_int( 'plugin_timetracking_time_input_bug_id', 0 ); $t_url = string_get_bug_view_url( $f_bug_id, auth_get_current_user_id() ); print_successful_redirect( $t_url . "#timerecord" ); From ceb05bd85de5842beec8bdd29a90d1d311aeff4b Mon Sep 17 00:00:00 2001 From: Francisco Mancardi Date: Tue, 6 Mar 2018 10:23:02 +0100 Subject: [PATCH 6/9] missing label --- TimeTracking/lang/strings_english.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/TimeTracking/lang/strings_english.txt b/TimeTracking/lang/strings_english.txt index 62495ee..ce47fef 100644 --- a/TimeTracking/lang/strings_english.txt +++ b/TimeTracking/lang/strings_english.txt @@ -2,6 +2,7 @@ $s_plugin_TimeTracking_title = 'Time Tracking'; $s_plugin_TimeTracking_categories = 'Activity Types'; +$s_plugin_TimeTracking_exp_date = 'Activity Date'; $s_plugin_TimeTracking_expenditure_date = 'Expenditure Date'; $s_plugin_TimeTracking_category = 'Activity Type'; From b27d0bf11806231d16157a970bc6a3c4767327f5 Mon Sep 17 00:00:00 2001 From: Francisco Mancardi Date: Tue, 6 Mar 2018 10:29:46 +0100 Subject: [PATCH 7/9] missing label --- TimeTracking/lang/strings_english.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/TimeTracking/lang/strings_english.txt b/TimeTracking/lang/strings_english.txt index ce47fef..363b32d 100644 --- a/TimeTracking/lang/strings_english.txt +++ b/TimeTracking/lang/strings_english.txt @@ -3,6 +3,7 @@ $s_plugin_TimeTracking_title = 'Time Tracking'; $s_plugin_TimeTracking_categories = 'Activity Types'; $s_plugin_TimeTracking_exp_date = 'Activity Date'; +$s_plugin_TimeTracking_time_exp_date = 'Activity Date'; $s_plugin_TimeTracking_expenditure_date = 'Expenditure Date'; $s_plugin_TimeTracking_category = 'Activity Type'; From 5c7b7089da7659de44f0c2e41fa144b1c8a60bf2 Mon Sep 17 00:00:00 2001 From: foxdog Date: Mon, 3 Sep 2018 16:45:35 +0200 Subject: [PATCH 8/9] tab to spaces --- TimeTracking/core/reports.php | 1381 ++++++++++++++++++--------------- 1 file changed, 742 insertions(+), 639 deletions(-) diff --git a/TimeTracking/core/reports.php b/TimeTracking/core/reports.php index 70224c1..de8b942 100644 --- a/TimeTracking/core/reports.php +++ b/TimeTracking/core/reports.php @@ -5,649 +5,752 @@ * Class that encapsulates logic and presentation for report generation */ class Report { - # these static fields are global definitions for this object and inherited - - /** - * Array of possible column keys - * @var array - */ - static $column_keys = array( - 'user', 'issue', 'project', 'time_category', 'time_exp_date', - ); - - /** - * Default keys to use - * @var array - */ - static $default_keys = array( - 'user', 'time_category', 'time_exp_date', - ); - - /** - * db fields to use in sql query, for each key - * using alias: - * 'TT' as plugin data table - * @var array - */ - static $column_db_fileds = array( - 'user' => '{user}.id', - 'issue' => 'TT.bug_id', - 'project' => '{project}.id', - 'time_category' => 'TT.category', - 'exp_date' => 'TT.time_exp_date', - 'date_created' => 'TT.date_created', - 'time_exp_date' => " FROM_UNIXTIME(TT.time_exp_date,'%d-%m-%Y') ", - ); - - /** - * db fields to sort on, for each key - * @var array - */ - static $column_db_sort_fileds = array( - 'user' => '{user}.username', - 'issue' => 'TT.bug_id', - 'project' => '{project}.name', - 'time_category' => 'TT.category', - 'exp_date' => 'TT.time_exp_date', - 'date_created' => 'TT.date_created', - 'time_exp_date' => 'TT.time_exp_date', - ); - - /** - * Current selection of keys for this object - * @var array - */ - public $selected_keys = array(); - - /** - * pagination: rows per page - * @var integer - */ - public $rows_per_page = 100; - - /** - * pagination, current page - * @var integer - */ - public $page = 1; /* starts at 1 */ - - /** - * Filter array, to filter current bug selection - * @var array - */ - public $bug_filter = null; - - # current values for timetracking filtering - # if any is null, it won't be applied - public $time_filter_from, $time_filter_to; # as integer timestamps - public $time_filter_user_id = null; - public $time_filter_category = null; - - /** - * After the query is executed, total number of rows will be sotred here - * Note: for consistency, use get_rows_count() - * @var integer - */ - protected $all_rows_count; - - /** - * After the query is executed, the raw result will be stored here - * Note: for consistency, use get_result() - * @var iterator - */ - protected $result; - - /** - * Constructor. Initialize defaults - */ - public function __construct() { - $this->selected_keys = static::$default_keys; - } - - /** - * Build a sql select based on the configured filter. - * This query is suitable to be used as IN clause - * Note: this mthod will call db_param_push() - * @param array $p_params db_params array (output) - * @return string SQL query for subselect - */ - protected function build_filter_subselect( array &$p_params ) { - # prepare filter subselect - if( !$this->bug_filter ) { - $t_filter = array(); - $t_filter[FILTER_PROPERTY_HIDE_STATUS] = array( META_FILTER_NONE ); - $t_filter = filter_ensure_valid_filter( $t_filter ); - $this->bug_filter = $t_filter; - } - # Note: filter_get_bug_rows_query_clauses() calls db_param_push(); - $t_query_clauses = filter_get_bug_rows_query_clauses( $this->bug_filter, null, null, null ); - # if the query can't be formed, there are no results - if( empty( $t_query_clauses ) ) { - # reset the db_param stack that was initialized by "filter_get_bug_rows_query_clauses()" - db_param_pop(); - return db_empty_result(); - } - $t_select_string = 'SELECT {bug}.id '; - $t_from_string = ' FROM ' . implode( ', ', $t_query_clauses['from'] ); - $t_join_string = count( $t_query_clauses['join'] ) > 0 ? implode( ' ', $t_query_clauses['join'] ) : ' '; - $t_where_string = ' WHERE '. implode( ' AND ', $t_query_clauses['project_where'] ); - if( count( $t_query_clauses['where'] ) > 0 ) { - $t_where_string .= ' AND ( '; - $t_where_string .= implode( $t_query_clauses['operator'], $t_query_clauses['where'] ); - $t_where_string .= ' ) '; - } - $t_query = $t_select_string . $t_from_string . $t_join_string . $t_where_string; - $p_params = $t_query_clauses['where_values']; - return $t_query; - } - - /** - * Get the row count of the report result. - * If the query has not been executed yet, calls to build an execute it- - * @return type - */ - public function get_rows_count() { - if( !$this->result ) { - $this->fetch_result(); - } - return $this->all_rows_count; - } - - /** - * Get the query result - * If the query has not been executed yet, calls to build an execute it- - * @return iterator - */ - public function get_result() { - if( !$this->result ) { - $this->fetch_result(); - } - return $this->result; - } - - /** - * Builds the query, execute it and stores the result - */ - protected function fetch_result() { - $t_select_columns = array(); - $t_group_columns = array(); - $t_order_columns = array(); - foreach( $this->selected_keys as $key ) { - $t_select_columns[] = static::$column_db_fileds[$key] . ' AS ' . $key; - $t_group_columns[] = static::$column_db_fileds[$key]; - $t_order_columns[] = static::$column_db_sort_fileds[$key]; - } - - $t_where= array(); - $t_params = array(); - - # bug filter - $t_where[] = 'TT.bug_id IN ( ' . $this->build_filter_subselect( $t_params ) . ' )'; - - # timetracking date - if( $this->time_filter_from ) { - $t_where[] = 'TT.time_exp_date >= ' . db_param(); - $t_params[] = (int)$this->time_filter_from; - } - if( $this->time_filter_to ) { - $t_where[] = 'TT.time_exp_date < ' . db_param(); - $t_params[] = (int)$this->time_filter_to; - } - - # timetracking user - if( $this->time_filter_user_id ) { - $t_where[] = 'TT.user_id = ' . db_param(); - $t_params[] = (int)$this->time_filter_user_id; - } - - # timetracking category - if( $this->time_filter_category ) { - $t_where[] = 'TT.category = ' . db_param(); - $t_params[] = $this->time_filter_category; - } - - # main query - $t_cols_select = implode( ', ', $t_select_columns ); - if( !empty( $t_select_columns ) ) { - $t_cols_select .= ', '; - } - $t_cols_group = implode( ', ', $t_group_columns ); - $t_cols_order = implode( ', ', $t_order_columns ); - $t_query = 'SELECT ' . $t_cols_select . 'SUM( TT.time_count ) AS time_count' - . ' FROM {bug} JOIN ' . plugin_table( 'data' ) . ' TT ON {bug}.id = TT.bug_id' - . ' JOIN {user} ON TT.user_id = {user}.id' - . ' JOIN {project} ON {bug}.project_id = {project}.id' - . ' WHERE ' . implode( ' AND ', $t_where ); - if( !empty( $t_select_columns ) ) { - $t_query .= ' GROUP BY ' . $t_cols_group . ' ORDER BY ' . $t_cols_order; - } - - $t_query_count = 'SELECT count(*) FROM ( ' . $t_query . ' ) C'; - - # keeps db_params in the stack, for the next db_query - $this->all_rows_count = db_result( db_query( $t_query_count, $t_params, -1, -1, false ) ); - - # update current page if it is outside range - $t_max_page = 1 + (int)floor( $this->all_rows_count / $this->rows_per_page ); - if( $this->page > $t_max_page ) { - $this->page = $t_max_page; - } - - $this->result = db_query( $t_query, $t_params, $this->rows_per_page, $this->rows_per_page * ( $this->page - 1 ) ); - } - - /** - * Process a result array and cache relevant data in core apis - * @param array $p_result_array The query result in array form - */ - protected function cache_resut_array( array $p_result_array ) { - foreach( $this->selected_keys as $t_key ) { - switch( $t_key ) { - case 'user': - user_cache_array_rows( array_column( $p_result_array, $t_key ) ); - break; - case 'project': - project_cache_array_rows( array_column( $p_result_array, $t_key ) ); - break; - case 'issue': - bug_cache_array_rows( array_column( $p_result_array, $t_key ) ); - } - } - } - - /** - * Formats each column key for proper presentation - * @param string $p_key Column key - * @param mixed $p_value Value to format - * @return mixed Formatted value - */ - public static function format_value( $p_key, $p_value ) { - switch( $p_key ) { - case 'user': - $t_value = string_display_line( user_get_name( $p_value ) ); - break; - case 'project': - $t_value = string_display_line( project_get_name( $p_value ) ); - break; - case 'issue': - $t_value = string_get_bug_view_link( $p_value ) . ':' . lang_get( 'word_separator' ) . string_shorten( bug_get_field( $p_value, 'summary' ), 80 ); - break; - case 'exp_date': - $t_value = string_display_line( date( config_get( 'short_date_format' ), $p_value ) ); - break; - case 'date_created': - $t_value = string_display_line( date( config_get( 'normal_date_format' ), $p_value ) ); - break; - default; - $t_value = string_display_line( $p_value ); - } - return $t_value; - } - - /** - * Outputs the query result into an htm table - */ - public function print_table() { - $t_result = $this->get_result(); - $t_result_array = array(); - while( $t_row = db_fetch_array( $t_result ) ) { - $t_result_array[] = $t_row; - } - $this->cache_resut_array( $t_result_array ); - - echo ''; - echo ''; - echo ''; - foreach( $this->selected_keys as $t_col_name ) { - echo ''; - } - echo ''; - echo ''; - echo ''; - echo ''; - foreach( $t_result_array as $t_row ) { - echo ''; - foreach( $t_row as $t_key => $t_value ) { - echo ''; - echo ''; - } - echo ''; - } - echo ''; - echo '
', plugin_lang_get( $t_col_name ) , '', plugin_lang_get( 'time_count' ) , '
'; - if( 'time_count' == $t_key ) { - echo seconds_to_hours( $t_value ); - echo ''; - echo seconds_to_hms( $t_value ); - } else { - echo static::format_value( $t_key, $t_value ); - } - echo '
'; - } - - /** - * Prints the pagination controls for current report - * @return string Html for pagination div - */ - public function print_report_pagination() { - $t_count = $this->get_rows_count(); - $t_pages = 1 + (int)floor( $t_count / $this->rows_per_page ); - if( $t_pages == 1 ) { - return; - } - - $t_url_page = url_self(); - $t_url_params = $this->get_current_params() + $_GET; - - $t_lang_first = lang_get( 'first' ); - $t_lang_last = lang_get( 'last' ); - $t_lang_prev = lang_get( 'prev' ); - $t_lang_next = lang_get( 'next' ); - $t_show_pages = 10; - $t_show_from = max( 1, floor( $this->page - $t_show_pages / 2 ) ); - $t_show_to = min( $t_pages, 1+ floor( $this->page + $t_show_pages / 2 ) ); - echo '
'; - echo '
    '; - if( $t_show_to < $t_pages ) { - $t_link_params = array( 'ttreport_page' => $t_pages ) + $t_url_params; - echo '
  • ' . $t_lang_last . '
  • '; - } - if( $this->page < $t_show_to ) { - $t_link_params = array( 'ttreport_page' => $this->page + 1 ) + $t_url_params; - echo '
  • ' . $t_lang_next . '
  • '; - } - if( $t_show_to < $t_pages ) { - echo '
  • ...
  • '; - } - for( $i = $t_show_to; $i >= $t_show_from; $i-- ) { - $t_active = ( $i == $this->page ) ? 'active ' : ''; - $t_link_params = array( 'ttreport_page' => $i ) + $t_url_params; - echo '
  • ' . $i . '
  • '; - } - if( $t_show_from > 1 ) { - echo '
  • ...
  • '; - } - if( $this->page > $t_show_from ) { - $t_link_params = array( 'ttreport_page' => $this->page - 1 ) + $t_url_params; - echo '
  • ' . $t_lang_prev . '
  • '; - } - if( $t_show_from > 1 ) { - $t_link_params = array( 'ttreport_page' => 1 ) + $t_url_params; - echo '
  • ' . $t_lang_first . '
  • '; - } - echo '
'; - echo '
'; - } - - /** - * Reads GET and POST parameters to update the status of current filter and properties - */ - public function read_gpc_params() { - $f_page = gpc_get_int( 'ttreport_page', 1 ); - $this->page = $f_page; - - $f_groupby = gpc_get_string_array( 'ttreport_groupby', array() ); - # if empty, no value were submitted, then use defaults - if( empty( $f_groupby ) ) { - $this->selected_keys = static::$default_keys; - } else { - $c_groupby = array(); - foreach( $f_groupby as $t_key ) { - if( in_array( $t_key, static::$column_keys ) ) { - $c_groupby[] = $t_key; - } - } - # here the group fields may be empty, but this was submitted intentionally - $this->selected_keys = $c_groupby; - } - - # Read filter parameters - $f_reset = gpc_isset( 'reset_filter_button' ); - if( $f_reset ) { - $this->time_filter_from = null; - $this->time_filter_to = null; - $this->time_filter_category = null; - $this->time_filter_user_id = null; - } else { - # dates as d/m/Y - $f_date_from_d = gpc_get_int( 'ttreport_date_from_d', 0 ); - $f_date_from_m = gpc_get_int( 'ttreport_date_from_m', 0 ); - $f_date_from_y = gpc_get_int( 'ttreport_date_from_y', 0 ); - $f_date_to_d = gpc_get_int( 'ttreport_date_to_d', 0 ); - $f_date_to_m = gpc_get_int( 'ttreport_date_to_m', 0 ); - $f_date_to_y = gpc_get_int( 'ttreport_date_to_y', 0 ); - if( $f_date_from_d && $f_date_from_m && $f_date_from_y ) { - $this->time_filter_from = parse_date_parts( $f_date_from_y, $f_date_from_m, $f_date_from_d ); - } - if( $f_date_to_d && $f_date_to_m && $f_date_to_y ) { - $this->time_filter_to = parse_date_parts( $f_date_to_y, $f_date_to_m, $f_date_to_d ); - } - - # dates as timestamp - $f_timestamp_from = gpc_get_int( 'ttreport_date_from', 0 ); - if( $f_timestamp_from > 0 ) { - $this->time_filter_from = $f_timestamp_from; - } - $f_timestamp_to = gpc_get_int( 'ttreport_date_to', 0 ); - if( $f_timestamp_to > 0 ) { - $this->time_filter_to = $f_timestamp_to; - } - - # timetracking category - $f_category = gpc_get_string( 'ttreport_category', '' ); - if( !empty( $f_category ) ) { - $this->time_filter_category = string_html_entities( $f_category ); - } - - #timetracking user - $f_user_id = gpc_get_int( 'ttreport_user_id', 0 ); - if( $f_user_id > 0 ) { - $this->time_filter_user_id = $f_user_id; - } - } - } - - /** - * Returns an array of key/value pairs representign the state of current filter and properties, - * suitable to build a query url - * @return type - */ - public function get_current_params() { - $t_params = array(); - $t_params['ttreport_page'] = $this->page; - $t_params['ttreport_groupby'] = $this->selected_keys; - if( $this->time_filter_user_id ) { - $t_params['ttreport_user_id'] = $this->time_filter_user_id; - } - if( $this->time_filter_category ) { - $t_params['ttreport_category'] = $this->time_filter_category; - } - if( $this->time_filter_from ) { - $t_params['ttreport_date_from'] = $this->time_filter_from; - } - if( $this->time_filter_to ) { - $t_params['ttreport_date_to'] = $this->time_filter_to; - } - return $t_params; - } - - /** - * Prints html for current filter properties. - * It will print the inputs and supporting html, but not the main form tags - */ - function print_inputs_time_filter() { - if( $this->time_filter_from ) { - $t_date_enabled = true; - $t_date_from = new \DateTime(); - $t_date_from->settimestamp( $this->time_filter_from ); - } else { - $t_date_enabled = false; - $t_date_from = new \DateTime( 'yesterday' ); - } - if( $this->time_filter_to ) { - $t_date_to = new \DateTime(); - $t_date_to->settimestamp( $this->time_filter_to ); - } else { - $t_date_to = new \DateTime( 'today' ); - } - $t_category_enabled = isset( $this->time_filter_category ); - $t_user_enabled = isset( $this->time_filter_user_id ); - ?> - - - - - - - - - - - - - - - -
- - - - - -
- - - - - - - - - - - - - - -
- - - - - -
- - - - - -
-
-
- - - - - - - -
- '; - echo '' . plugin_lang_get( 'group_by' ) . ':'; - echo ''; - # set a dummy group field to allow for empty group, and avoid applying deafults. - echo ''; - $t_elements = array(); - $t_par_index = 1; - foreach( $this->selected_keys as $t_key ) { - $t_el = ''; - $t_el .= ''; - $t_el .= ''; - $t_el .= plugin_lang_get( $t_key ); - $t_el .= ''; - $t_el .= ''; - $t_el .= ''; - $t_elements[] = $t_el; - } - $t_unused_keys = array_diff( static::$column_keys, $this->selected_keys ); - if( !empty( $t_unused_keys ) ) { - $t_input = ''; - $t_input .= ''; - $t_input .= ''; - $t_elements[] = $t_input; - } - echo implode ( '', $t_elements ); - echo ''; - echo ''; - } + # these static fields are global definitions for this object and inherited + + /** + * Array of possible column keys + * @var array + */ + static $column_keys = array( + 'user', 'issue', 'project', 'time_category', 'time_exp_date', + ); + + /** + * Default keys to use + * @var array + */ + static $default_keys = array( + 'user', 'time_category', 'time_exp_date', + ); + + /** + * db fields to use in sql query, for each key + * using alias: + * 'TT' as plugin data table + * @var array + */ + static $column_db_fields = array( + 'user' => '{user}.id', + 'issue' => 'TT.bug_id', + 'project' => '{project}.id', + 'time_category' => 'TT.category', + 'exp_date' => 'TT.time_exp_date', + 'date_created' => 'TT.date_created', + 'time_exp_date' => " FROM_UNIXTIME(TT.time_exp_date,'%d-%m-%Y') ", + 'user_resource' => '' + ); + + /** + * db fields to sort on, for each key + * @var array + */ + static $column_db_sort_fields = array( + 'user' => '{user}.username', + 'issue' => 'TT.bug_id', + 'project' => '{project}.name', + 'time_category' => 'TT.category', + 'exp_date' => 'TT.time_exp_date', + 'date_created' => 'TT.date_created', + 'time_exp_date' => 'TT.time_exp_date', + ); + + /** + * Current selection of keys for this object + * @var array + */ + public $selected_keys = array(); + + /** + * pagination: rows per page + * @var integer + */ + public $rows_per_page = 100; + + /** + * pagination, current page + * @var integer + */ + public $page = 1; /* starts at 1 */ + + /** + * Filter array, to filter current bug selection + * @var array + */ + public $bug_filter = null; + + # current values for timetracking filtering + # if any is null, it won't be applied + public $time_filter_from, $time_filter_to; # as integer timestamps + public $time_filter_user_id = null; + public $time_filter_category = null; + + /** + * After the query is executed, total number of rows will be sotred here + * Note: for consistency, use get_rows_count() + * @var integer + */ + protected $all_rows_count; + + /** + * After the query is executed, the raw result will be stored here + * Note: for consistency, use get_result() + * @var iterator + */ + protected $result; + + var $userRoleViewExists; + var $userRoleView; + + /** + * Constructor. Initialize defaults + */ + public function __construct() { + global $g_db; + $this->selected_keys = static::$default_keys; + $t_views = $g_db->MetaTables( 'VIEW' ); + + $this->userRoleViewExists = false; + $this->userRoleView = 'v_AccountCustomFields_UserRole'; + if( is_array( $t_views ) ) { + # Can't use in_array() since it is case sensitive + $t_table_view = utf8_strtolower( $this->userRoleView ); + foreach( $t_views as $t_current_view ) { + if( utf8_strtolower( $t_current_view ) == $t_table_view ) { + $this->userRoleViewExists = true; + } + } + } + } + + /** + * Build a sql select based on the configured filter. + * This query is suitable to be used as IN clause + * Note: this mthod will call db_param_push() + * @param array $p_params db_params array (output) + * @return string SQL query for subselect + */ + protected function build_filter_subselect( array &$p_params ) { + # prepare filter subselect + if( !$this->bug_filter ) { + $t_filter = array(); + $t_filter[FILTER_PROPERTY_HIDE_STATUS] = array( META_FILTER_NONE ); + $t_filter = filter_ensure_valid_filter( $t_filter ); + $this->bug_filter = $t_filter; + } + # Note: filter_get_bug_rows_query_clauses() calls db_param_push(); + $t_query_clauses = filter_get_bug_rows_query_clauses( $this->bug_filter, null, null, null ); + # if the query can't be formed, there are no results + if( empty( $t_query_clauses ) ) { + # reset the db_param stack that was initialized by "filter_get_bug_rows_query_clauses()" + db_param_pop(); + return db_empty_result(); + } + $t_select_string = 'SELECT {bug}.id '; + $t_from_string = ' FROM ' . implode( ', ', $t_query_clauses['from'] ); + $t_join_string = count( $t_query_clauses['join'] ) > 0 ? implode( ' ', $t_query_clauses['join'] ) : ' '; + $t_where_string = ' WHERE '. implode( ' AND ', $t_query_clauses['project_where'] ); + if( count( $t_query_clauses['where'] ) > 0 ) { + $t_where_string .= ' AND ( '; + $t_where_string .= implode( $t_query_clauses['operator'], $t_query_clauses['where'] ); + $t_where_string .= ' ) '; + } + $t_query = $t_select_string . $t_from_string . $t_join_string . $t_where_string; + $p_params = $t_query_clauses['where_values']; + return $t_query; + } + + /** + * Get the row count of the report result. + * If the query has not been executed yet, calls to build an execute it- + * @return type + */ + public function get_rows_count() { + if( !$this->result ) { + $this->fetch_result(); + } + return $this->all_rows_count; + } + + /** + * Get the query result + * If the query has not been executed yet, calls to build an execute it- + * @return iterator + */ + public function get_result() { + if( !$this->result ) { + $this->fetch_result(); + } + return $this->result; + } + + /** + * Builds the query, execute it and stores the result + */ + protected function fetch_result() { + $t_select_columns = array(); + $t_group_columns = array(); + $t_order_columns = array(); + foreach( $this->selected_keys as $key ) { + $t_select_columns[] = static::$column_db_fields[$key] . ' AS ' . $key; + $t_group_columns[] = static::$column_db_fields[$key]; + $t_order_columns[] = static::$column_db_sort_fields[$key]; + } + + $t_where= array(); + $t_params = array(); + + # bug filter + $t_where[] = 'TT.bug_id IN ( ' . $this->build_filter_subselect( $t_params ) . ' )'; + + # timetracking date + if( $this->time_filter_from ) { + $t_where[] = 'TT.time_exp_date >= ' . db_param(); + $t_params[] = (int)$this->time_filter_from; + } + if( $this->time_filter_to ) { + $t_where[] = 'TT.time_exp_date < ' . db_param(); + $t_params[] = (int)$this->time_filter_to; + } + + # timetracking user + if( $this->time_filter_user_id ) { + $t_where[] = 'TT.user_id = ' . db_param(); + $t_params[] = (int)$this->time_filter_user_id; + } + + # timetracking category + if( $this->time_filter_category ) { + $t_where[] = 'TT.category = ' . db_param(); + $t_params[] = $this->time_filter_category; + } + + # main query + $t_cols_select = implode( ', ', $t_select_columns ); + if( !empty( $t_select_columns ) ) { + $t_cols_select .= ', '; + } + $t_cols_group = implode( ', ', $t_group_columns ); + $t_cols_order = implode( ', ', $t_order_columns ); + $t_query = 'SELECT ' . $t_cols_select . 'SUM( TT.time_count ) AS time_count' + . ' FROM {bug} JOIN ' . plugin_table( 'data' ) . ' TT ON {bug}.id = TT.bug_id' + . ' JOIN {user} ON TT.user_id = {user}.id' + . ' JOIN {project} ON {bug}.project_id = {project}.id'; + + if( $this->userRoleViewExists ) { + $t_query .= ' JOIN ' . $this->userRoleView . ' AS VUR ' . + ' ON VUR.user_id = TT.user_id '; + } + + $t_query .= ' WHERE ' . implode( ' AND ', $t_where ); + if( !empty( $t_select_columns ) ) { + $t_query .= ' GROUP BY ' . $t_cols_group . ' ORDER BY ' . $t_cols_order; + } + + $t_query_count = 'SELECT count(*) FROM ( ' . $t_query . ' ) C'; + + # keeps db_params in the stack, for the next db_query + $this->all_rows_count = db_result( db_query( $t_query_count, $t_params, -1, -1, false ) ); + + # update current page if it is outside range + $t_max_page = 1 + (int)floor( $this->all_rows_count / $this->rows_per_page ); + if( $this->page > $t_max_page ) { + $this->page = $t_max_page; + } + + $this->result = db_query( $t_query, $t_params, $this->rows_per_page, $this->rows_per_page * ( $this->page - 1 ) ); + } + + /** + * Process a result array and cache relevant data in core apis + * @param array $p_result_array The query result in array form + */ + protected function cache_resut_array( array $p_result_array ) { + foreach( $this->selected_keys as $t_key ) { + switch( $t_key ) { + case 'user': + user_cache_array_rows( array_column( $p_result_array, $t_key ) ); + break; + case 'project': + project_cache_array_rows( array_column( $p_result_array, $t_key ) ); + break; + case 'issue': + bug_cache_array_rows( array_column( $p_result_array, $t_key ) ); + } + } + } + + /** + * Formats each column key for proper presentation + * @param string $p_key Column key + * @param mixed $p_value Value to format + * @return mixed Formatted value + */ + public static function format_value( $p_key, $p_value ) { + switch( $p_key ) { + case 'user': + $t_value = string_display_line( user_get_name( $p_value ) ); + break; + case 'project': + $t_value = string_display_line( project_get_name( $p_value ) ); + break; + case 'issue': + $t_value = string_get_bug_view_link( $p_value ) . ':' . lang_get( 'word_separator' ) . string_shorten( bug_get_field( $p_value, 'summary' ), 80 ); + break; + case 'exp_date': + $t_value = string_display_line( date( config_get( 'short_date_format' ), $p_value ) ); + break; + case 'date_created': + $t_value = string_display_line( date( config_get( 'normal_date_format' ), $p_value ) ); + break; + default; + $t_value = string_display_line( $p_value ); + } + return $t_value; + } + + /** + * Outputs the query result into an htm table + */ + public function print_table() { + $t_result = $this->get_result(); + $t_result_array = array(); + while( $t_row = db_fetch_array( $t_result ) ) { + $t_result_array[] = $t_row; + } + $this->cache_resut_array( $t_result_array ); + + echo ''; + echo ''; + echo ''; + foreach( $this->selected_keys as $t_col_name ) { + echo ''; + } + echo ''; + echo ''; + echo ''; + echo ''; + foreach( $t_result_array as $t_row ) { + echo ''; + foreach( $t_row as $t_key => $t_value ) { + echo ''; + echo ''; + } + echo ''; + } + echo ''; + echo '
', plugin_lang_get( $t_col_name ) , '', plugin_lang_get( 'time_count' ) , '
'; + if( 'time_count' == $t_key ) { + echo seconds_to_hours( $t_value ); + echo ''; + echo seconds_to_hms( $t_value ); + } else { + echo static::format_value( $t_key, $t_value ); + } + echo '
'; + } + + /** + * Prints the pagination controls for current report + * @return string Html for pagination div + */ + public function print_report_pagination() { + $t_count = $this->get_rows_count(); + $t_pages = 1 + (int)floor( $t_count / $this->rows_per_page ); + if( $t_pages == 1 ) { + return; + } + + $t_url_page = url_self(); + $t_url_params = $this->get_current_params() + $_GET; + + $t_lang_first = lang_get( 'first' ); + $t_lang_last = lang_get( 'last' ); + $t_lang_prev = lang_get( 'prev' ); + $t_lang_next = lang_get( 'next' ); + $t_show_pages = 10; + $t_show_from = max( 1, floor( $this->page - $t_show_pages / 2 ) ); + $t_show_to = min( $t_pages, 1+ floor( $this->page + $t_show_pages / 2 ) ); + echo '
'; + echo '
    '; + if( $t_show_to < $t_pages ) { + $t_link_params = array( 'ttreport_page' => $t_pages ) + $t_url_params; + echo '
  • ' . $t_lang_last . '
  • '; + } + if( $this->page < $t_show_to ) { + $t_link_params = array( 'ttreport_page' => $this->page + 1 ) + $t_url_params; + echo '
  • ' . $t_lang_next . '
  • '; + } + if( $t_show_to < $t_pages ) { + echo '
  • ...
  • '; + } + for( $i = $t_show_to; $i >= $t_show_from; $i-- ) { + $t_active = ( $i == $this->page ) ? 'active ' : ''; + $t_link_params = array( 'ttreport_page' => $i ) + $t_url_params; + echo '
  • ' . $i . '
  • '; + } + if( $t_show_from > 1 ) { + echo '
  • ...
  • '; + } + if( $this->page > $t_show_from ) { + $t_link_params = array( 'ttreport_page' => $this->page - 1 ) + $t_url_params; + echo '
  • ' . $t_lang_prev . '
  • '; + } + if( $t_show_from > 1 ) { + $t_link_params = array( 'ttreport_page' => 1 ) + $t_url_params; + echo '
  • ' . $t_lang_first . '
  • '; + } + echo '
'; + echo '
'; + } + + /** + * Reads GET and POST parameters to update the status of current filter and properties + */ + public function read_gpc_params() { + $f_page = gpc_get_int( 'ttreport_page', 1 ); + $this->page = $f_page; + + $f_groupby = gpc_get_string_array( 'ttreport_groupby', array() ); + # if empty, no value were submitted, then use defaults + if( empty( $f_groupby ) ) { + $this->selected_keys = static::$default_keys; + } else { + $c_groupby = array(); + foreach( $f_groupby as $t_key ) { + if( in_array( $t_key, static::$column_keys ) ) { + $c_groupby[] = $t_key; + } + } + # here the group fields may be empty, but this was submitted intentionally + $this->selected_keys = $c_groupby; + } + + # Read filter parameters + $f_reset = gpc_isset( 'reset_filter_button' ); + if( $f_reset ) { + $this->time_filter_from = null; + $this->time_filter_to = null; + $this->time_filter_category = null; + $this->time_filter_user_id = null; + } else { + # dates as d/m/Y + $f_date_from_d = gpc_get_int( 'ttreport_date_from_d', 0 ); + $f_date_from_m = gpc_get_int( 'ttreport_date_from_m', 0 ); + $f_date_from_y = gpc_get_int( 'ttreport_date_from_y', 0 ); + $f_date_to_d = gpc_get_int( 'ttreport_date_to_d', 0 ); + $f_date_to_m = gpc_get_int( 'ttreport_date_to_m', 0 ); + $f_date_to_y = gpc_get_int( 'ttreport_date_to_y', 0 ); + if( $f_date_from_d && $f_date_from_m && $f_date_from_y ) { + $this->time_filter_from = parse_date_parts( $f_date_from_y, $f_date_from_m, $f_date_from_d ); + } + if( $f_date_to_d && $f_date_to_m && $f_date_to_y ) { + $this->time_filter_to = parse_date_parts( $f_date_to_y, $f_date_to_m, $f_date_to_d ); + } + + # dates as timestamp + $f_timestamp_from = gpc_get_int( 'ttreport_date_from', 0 ); + if( $f_timestamp_from > 0 ) { + $this->time_filter_from = $f_timestamp_from; + } + $f_timestamp_to = gpc_get_int( 'ttreport_date_to', 0 ); + if( $f_timestamp_to > 0 ) { + $this->time_filter_to = $f_timestamp_to; + } + + # timetracking category + $f_category = gpc_get_string( 'ttreport_category', '' ); + if( !empty( $f_category ) ) { + $this->time_filter_category = string_html_entities( $f_category ); + } + + #timetracking user + $f_user_id = gpc_get_int( 'ttreport_user_id', 0 ); + if( $f_user_id > 0 ) { + $this->time_filter_user_id = $f_user_id; + } + } + } + + /** + * Returns an array of key/value pairs representign the state of current filter and properties, + * suitable to build a query url + * @return type + */ + public function get_current_params() { + $t_params = array(); + $t_params['ttreport_page'] = $this->page; + $t_params['ttreport_groupby'] = $this->selected_keys; + if( $this->time_filter_user_id ) { + $t_params['ttreport_user_id'] = $this->time_filter_user_id; + } + if( $this->time_filter_category ) { + $t_params['ttreport_category'] = $this->time_filter_category; + } + if( $this->time_filter_from ) { + $t_params['ttreport_date_from'] = $this->time_filter_from; + } + if( $this->time_filter_to ) { + $t_params['ttreport_date_to'] = $this->time_filter_to; + } + return $t_params; + } + + /** + * Prints html for current filter properties. + * It will print the inputs and supporting html, but not the main form tags + */ + function print_inputs_time_filter() { + if( $this->time_filter_from ) { + $t_date_enabled = true; + $t_date_from = new \DateTime(); + $t_date_from->settimestamp( $this->time_filter_from ); + } else { + $t_date_enabled = false; + $t_date_from = new \DateTime( 'yesterday' ); + } + if( $this->time_filter_to ) { + $t_date_to = new \DateTime(); + $t_date_to->settimestamp( $this->time_filter_to ); + } else { + $t_date_to = new \DateTime( 'today' ); + } + $t_category_enabled = isset( $this->time_filter_category ); + $t_user_enabled = isset( $this->time_filter_user_id ); + ?> + + + + + + + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + +
+ + + + + +
+ + + + + +
+
+
+ + + + + + + +
+ '; + echo '' . plugin_lang_get( 'group_by' ) . ':'; + echo ''; + # set a dummy group field to allow for empty group, and avoid applying deafults. + echo ''; + $t_elements = array(); + $t_par_index = 1; + foreach( $this->selected_keys as $t_key ) { + $t_el = ''; + $t_el .= ''; + $t_el .= ''; + $t_el .= plugin_lang_get( $t_key ); + $t_el .= ''; + $t_el .= ''; + $t_el .= ''; + $t_elements[] = $t_el; + } + $t_unused_keys = array_diff( static::$column_keys, $this->selected_keys ); + if( !empty( $t_unused_keys ) ) { + $t_input = ''; + $t_input .= ''; + $t_input .= ''; + $t_elements[] = $t_input; + } + echo implode ( '', $t_elements ); + echo ''; + echo ''; + } } /** * Class for a report suitable for a single issue */ class ReportForBug extends Report { - # override parent definiiton for keys, only to those that make sens for a singe issue - static $column_keys = array( - 'user', 'time_category', 'time_exp_date' - ); - static $default_keys = array( - 'user', 'time_category', 'time_exp_date' - ); - - protected $bug_id; - - /** - * constructor, must be initialized with a bug id - * @param integer $p_bug_id Bug id - */ - public function __construct( $p_bug_id ) { - parent::__construct(); - $this->bug_id = $p_bug_id; - } - - /** - * Overrides parent filter-based selection, to show only specified bug id - * @param array $p_params db_params (output) - * @return string sql string - */ - protected function build_filter_subselect( array &$p_params ) { - db_param_push(); - # use only the bug id, as it will be placed inside a IN () clause - $t_query = db_param(); - $p_params[] = (int)$this->bug_id; - return $t_query; - } + # override parent definiiton for keys, only to those that make sens for a singe issue + static $column_keys = array( + 'user', 'time_category', 'time_exp_date' + ); + static $default_keys = array( + 'user', 'time_category', 'time_exp_date' + ); + + protected $bug_id; + + /** + * constructor, must be initialized with a bug id + * @param integer $p_bug_id Bug id + */ + public function __construct( $p_bug_id ) { + parent::__construct(); + $this->bug_id = $p_bug_id; + } + + /** + * Overrides parent filter-based selection, to show only specified bug id + * @param array $p_params db_params (output) + * @return string sql string + */ + protected function build_filter_subselect( array &$p_params ) { + db_param_push(); + # use only the bug id, as it will be placed inside a IN () clause + $t_query = db_param(); + $p_params[] = (int)$this->bug_id; + return $t_query; + } + + /** + * Will be used ONLY IF Custom Fields AT USER LEVEL + * are enabled. + * + */ + protected function fetchResultWithResourceType() { + $t_select_columns = array(); + $t_group_columns = array(); + $t_order_columns = array(); + + foreach( $this->selected_keys as $key ) { + $t_select_columns[] = static::$column_db_fields[$key] . ' AS ' . $key; + $t_group_columns[] = static::$column_db_fields[$key]; + $t_order_columns[] = static::$column_db_sort_fields[$key]; + } + + $t_where= array(); + $t_params = array(); + + # bug filter + $t_where[] = 'TT.bug_id IN ( ' . $this->build_filter_subselect( $t_params ) . ' )'; + + # timetracking date + if( $this->time_filter_from ) { + $t_where[] = 'TT.time_exp_date >= ' . db_param(); + $t_params[] = (int)$this->time_filter_from; + } + if( $this->time_filter_to ) { + $t_where[] = 'TT.time_exp_date < ' . db_param(); + $t_params[] = (int)$this->time_filter_to; + } + + # timetracking user + if( $this->time_filter_user_id ) { + $t_where[] = 'TT.user_id = ' . db_param(); + $t_params[] = (int)$this->time_filter_user_id; + } + + # timetracking category + if( $this->time_filter_category ) { + $t_where[] = 'TT.category = ' . db_param(); + $t_params[] = $this->time_filter_category; + } + + # main query + $t_cols_select = implode( ', ', $t_select_columns ); + if( !empty( $t_select_columns ) ) { + $t_cols_select .= ', '; + } + $t_cols_group = implode( ', ', $t_group_columns ); + $t_cols_order = implode( ', ', $t_order_columns ); + $t_query = 'SELECT ' . $t_cols_select . + 'SUM( TT.time_count ) AS time_count' . + ' FROM {bug} JOIN ' . plugin_table( 'data' ) . + ' TT ON {bug}.id = TT.bug_id' . + ' JOIN {user} ON TT.user_id = {user}.id' . + ' JOIN {project} ON {bug}.project_id = {project}.id' . + ' WHERE ' . implode( ' AND ', $t_where ); + if( !empty( $t_select_columns ) ) { + $t_query .= ' GROUP BY ' . $t_cols_group . ' ORDER BY ' . $t_cols_order; + } + + $t_query_count = 'SELECT count(*) FROM ( ' . $t_query . ' ) C'; + + # keeps db_params in the stack, for the next db_query + $this->all_rows_count = db_result( db_query( $t_query_count, $t_params, -1, -1, false ) ); + + # update current page if it is outside range + $t_max_page = 1 + (int)floor( $this->all_rows_count / $this->rows_per_page ); + if( $this->page > $t_max_page ) { + $this->page = $t_max_page; + } + + $this->result = db_query( $t_query, $t_params, $this->rows_per_page, $this->rows_per_page * ( $this->page - 1 ) ); + } + + + } \ No newline at end of file From f2d9060442a0203021e28b9a7fb279a2b5edb4cb Mon Sep 17 00:00:00 2001 From: foxdog Date: Mon, 3 Sep 2018 16:46:18 +0200 Subject: [PATCH 9/9] changed default to false to avoid MantisBT Error --- TimeTracking/TimeTracking.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TimeTracking/TimeTracking.php b/TimeTracking/TimeTracking.php index df52a67..f38feb0 100644 --- a/TimeTracking/TimeTracking.php +++ b/TimeTracking/TimeTracking.php @@ -124,7 +124,7 @@ function ev_view_bugnote( $p_event, $p_bug_id, $p_note_id, $p_is_private ) { function ev_bugnote_add_form( $p_event, $p_bug_id ) { $t_project_id = bug_get_field( $p_bug_id, 'project_id' ); - $t_enabled_on_bugnote_add_form = plugin_config_get('enabled_on_bugnote_add_form',null,false,null,$t_project_id); + $t_enabled_on_bugnote_add_form = plugin_config_get('enabled_on_bugnote_add_form',false,false,null,$t_project_id); if( $t_enabled_on_bugnote_add_form ) { if( TimeTracking\user_can_edit_bug_id( $p_bug_id ) ) { TimeTracking\print_bugnote_add_form( $p_bug_id );