View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0008435 | mantisbt | feature | public | 2007-10-02 14:22 | 2011-10-04 03:59 |
Reporter | jreese | Assigned To | jreese | ||
Priority | normal | Severity | feature | Reproducibility | N/A |
Status | closed | Resolution | fixed | ||
Target Version | 1.2.0a1 | Fixed in Version | 1.2.0a1 | ||
Summary | 0008435: Implement Global and Inheriting Categories Structure | ||||
Description | Implement a set of features for the Mantis bugtracker that will enable a simple and logical method of reducing and reusing project categories by:
The overall requirements outline for this planned feature has been posted on the wiki: | ||||
Tags | No tags attached. | ||||
Attached Files | mantis-categories-2007-11-10.patch (59,115 bytes)
diff --git a/admin/install.php b/admin/install.php index be2ef6a..a74c593 100644 --- a/admin/install.php +++ b/admin/install.php @@ -28,6 +28,7 @@ $g_skip_open_db = true; # don't open the database in database_api.php define( 'PLUGINS_DISABLED', true ); @require_once( dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'core.php' ); + @require_once( 'install_functions.php' ); $g_error_send_page_header = false; # bypass page headers in error handler define( 'BAD', 0 ); diff --git a/admin/install_functions.php b/admin/install_functions.php new file mode 100644 index 0000000..0612550 --- /dev/null +++ b/admin/install_functions.php @@ -0,0 +1,59 @@ +<?php + # Mantis - a php based bugtracking system + # Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org + # Copyright (C) 2002 - 2007 Mantis Team - mantisbt-dev@lists.sourceforge.net + # This program is distributed under the terms and conditions of the GPL + # See the README and LICENSE files for details + + # -------------------------------------------------------- + # $Id: $ + # -------------------------------------------------------- + + /** + * Update functions for the installation schema's 'UpdateFunction' option. + * All functions must be name install_<function_name> and referenced as just <function_name>. + */ + + /** + * Migrate the legacy category data to the new category_id-based schema. + */ + function install_category_migrate() { + $t_bug_table = config_get( 'mantis_bug_table' ); + $t_category_table = config_get( 'mantis_category_table' ); + $t_project_category_table = config_get( 'mantis_project_category_table' ); + + $query = "SELECT project_id, category FROM $t_project_category_table ORDER BY project_id, category"; + $cresult = db_query( $query ); + + $query = "SELECT id, project_id, category FROM $t_bug_table ORDER BY project_id, category"; + $bresult = db_query( $query ); + + $t_data = Array(); + while ( $row = db_fetch_array( $cresult ) ) { + $t_pid = $row['project_id']; + $t_name = $row['category']; + $t_data[$t_pid][$t_name] = Array(); + } + while ( $row = db_fetch_array( $bresult ) ) { + $t_bid = $row['id']; + $t_pid = $row['project_id']; + $t_name = $row['category']; + + $t_data[$t_pid][$t_name][] = $t_bid; + } + + foreach ( $t_data as $t_pid => $t_categories ) { + foreach ( $t_categories as $t_name => $t_bugs ) { + $query = "INSERT INTO $t_category_table ( name, project_id ) VALUES ( '$t_name', '$t_pid' )"; + db_query( $query ); + $t_category_id = db_insert_id( $t_category_table ); + + $query = "UPDATE $t_bug_table SET category_id='$t_category_id' + WHERE project_id='$t_pid' AND category='$t_name'"; + db_query( $query ); + } + } + + return 2; + } + diff --git a/admin/schema.php b/admin/schema.php index 440504e..63bb06e 100644 --- a/admin/schema.php +++ b/admin/schema.php @@ -370,4 +370,21 @@ $upgrade[] = Array('CreateTableSQL', Array( config_get( 'mantis_plugin_table' ), ", Array( 'mysql' => 'TYPE=MyISAM', 'pgsql' => 'WITHOUT OIDS' ) ) ); $upgrade[] = Array('AlterColumnSQL', Array( config_get_global( 'mantis_user_pref_table' ), "redirect_delay I NOTNULL DEFAULT 0" ) ); + +$upgrade[] = Array( 'CreateTableSQL', Array( config_get( 'mantis_category_table' ), " + id I UNSIGNED NOTNULL PRIMARY AUTOINCREMENT, + project_id I UNSIGNED NOTNULL DEFAULT '0', + user_id I UNSIGNED NOTNULL DEFAULT '0', + name C(100) NOTNULL PRIMARY DEFAULT \" '' \", + status I UNSIGNED NOTNULL DEFAULT '0' + ", Array( 'mysql' => 'TYPE=MyISAM', 'pgsql' => 'WITHOUT OIDS' ) ) ); +$upgrade[] = Array( 'CreateIndexSQL', Array( 'idx_category', config_get( 'mantis_category_table' ), 'project_id, status' ) ); +$upgrade[] = Array( 'InsertData', Array( config_get( 'mantis_category_table' ), " + ( project_id, user_id, name, status ) VALUES + ( '0', '0', 'Unknown', '0' ) " ) ); +$upgrade[] = Array( 'AddColumnSQL', Array( config_get( 'mantis_bug_table' ), "category_id I UNSIGNED NOTNULL DEFAULT '0'" ) ); +$upgrade[] = Array( 'UpdateFunction', "category_migrate" ); +$upgrade[] = Array( 'DropColumnSQL', Array( config_get( 'mantis_bug_table' ), "category" ) ); +$upgrade[] = Array( 'DropTableSQL', Array( config_get( 'mantis_project_category_table' ) ) ); + ?> diff --git a/bug_report.php b/bug_report.php index 58588dc..a41fb29 100644 --- a/bug_report.php +++ b/bug_report.php @@ -44,7 +44,7 @@ $t_bug_data->handler_id = gpc_get_int( 'handler_id', 0 ); $t_bug_data->view_state = gpc_get_int( 'view_state', config_get( 'default_bug_view_status' ) ); - $t_bug_data->category = gpc_get_string( 'category', config_get( 'default_bug_category' ) ); + $t_bug_data->category_id = gpc_get_string( 'category_id', config_get( 'default_bug_category' ) ); $t_bug_data->reproducibility = gpc_get_int( 'reproducibility', config_get( 'default_bug_reproducibility' ) ); $t_bug_data->severity = gpc_get_int( 'severity', config_get( 'default_bug_severity' ) ); $t_bug_data->priority = gpc_get_int( 'priority', config_get( 'default_bug_priority' ) ); @@ -171,7 +171,7 @@ ?> <p> <form method="post" action="<?php echo string_get_bug_report_url() ?>"> - <input type="hidden" name="category" value="<?php echo $t_bug_data->category ?>" /> + <input type="hidden" name="category_id" value="<?php echo $t_bug_data->category_id ?>" /> <input type="hidden" name="severity" value="<?php echo $t_bug_data->severity ?>" /> <input type="hidden" name="reproducibility" value="<?php echo $t_bug_data->reproducibility ?>" /> <input type="hidden" name="profile_id" value="<?php echo $t_bug_data->profile_id ?>" /> diff --git a/bug_report_advanced_page.php b/bug_report_advanced_page.php index ed694e3..85117a7 100644 --- a/bug_report_advanced_page.php +++ b/bug_report_advanced_page.php @@ -82,7 +82,7 @@ $f_profile_id = 0; $f_handler_id = $t_bug->handler_id; - $f_category = $t_bug->category; + $f_category_id = $t_bug->category_id; $f_reproducibility = $t_bug->reproducibility; $f_severity = $t_bug->severity; $f_priority = $t_bug->priority; @@ -105,7 +105,7 @@ $f_profile_id = gpc_get_int( 'profile_id', 0 ); $f_handler_id = gpc_get_int( 'handler_id', 0 ); - $f_category = gpc_get_string( 'category', config_get( 'default_bug_category' ) ); + $f_category_id = gpc_get_string( 'category_id', config_get( 'default_bug_category' ) ); $f_reproducibility = gpc_get_int( 'reproducibility', config_get( 'default_bug_reproducibility' ) ); $f_severity = gpc_get_int( 'severity', config_get( 'default_bug_severity' ) ); $f_priority = gpc_get_int( 'priority', config_get( 'default_bug_priority' ) ); @@ -161,13 +161,13 @@ <?php if ( $t_changed_project ) { echo "[" . project_get_field( $t_bug->project_id, 'name' ) . "] "; } ?> - <select <?php echo helper_get_tab_index() ?> name="category"> + <select <?php echo helper_get_tab_index() ?> name="category_id"> <?php - if ( is_blank( $f_category ) ) { + if ( is_blank( $f_category_id ) ) { echo '<option value="" selected="selected">', string_attribute( lang_get( 'select_option' ) ), '</option>'; } - print_category_option_list( $f_category ); + print_category_option_list( $f_category_id ); ?> </select> </td> @@ -555,7 +555,7 @@ <?php if ( ON == config_get( 'use_javascript' ) ) { ?> <script type="text/javascript" language="JavaScript"> <!-- - window.document.report_bug_form.category.focus(); + window.document.report_bug_form.category_id.focus(); --> </script> <?php } ?> diff --git a/bug_report_page.php b/bug_report_page.php index 4446331..65bb875 100644 --- a/bug_report_page.php +++ b/bug_report_page.php @@ -73,7 +73,7 @@ access_ensure_project_level( config_get( 'report_bug_threshold' ) ); $f_product_version = $t_bug->version; - $f_category = $t_bug->category; + $f_category_id = $t_bug->category_id; $f_reproducibility = $t_bug->reproducibility; $f_severity = $t_bug->severity; $f_priority = $t_bug->priority; @@ -87,7 +87,7 @@ access_ensure_project_level( config_get( 'report_bug_threshold' ) ); $f_product_version = gpc_get_string( 'product_version', '' ); - $f_category = gpc_get_string( 'category', config_get( 'default_bug_category' ) ); + $f_category_id = gpc_get_string( 'category_id', config_get( 'default_bug_category' ) ); $f_reproducibility = gpc_get_int( 'reproducibility', config_get( 'default_bug_reproducibility' ) ); $f_severity = gpc_get_int( 'severity', config_get( 'default_bug_severity' ) ); $f_priority = gpc_get_int( 'priority', config_get( 'default_bug_priority' ) ); @@ -143,13 +143,13 @@ <?php if ( $t_changed_project ) { echo "[" . project_get_field( $t_bug->project_id, 'name' ) . "] "; } ?> - <select <?php echo helper_get_tab_index() ?> name="category"> + <select <?php echo helper_get_tab_index() ?> name="category_id"> <?php - if ( is_blank( $f_category ) ) { + if ( is_blank( $f_category_id ) ) { echo '<option value="" selected="selected">', string_attribute( lang_get( 'select_option' ) ), '</option>'; } - print_category_option_list( $f_category ); + print_category_option_list( $f_category_id ); ?> </select> </td> @@ -385,7 +385,7 @@ <?php if ( ON == config_get( 'use_javascript' ) ) { ?> <script type="text/javascript" language="JavaScript"> <!-- - window.document.report_bug_form.category.focus(); + window.document.report_bug_form.category_id.focus(); --> </script> <?php } ?> diff --git a/bug_update.php b/bug_update.php index dd0a2e6..5b16e80 100644 --- a/bug_update.php +++ b/bug_update.php @@ -67,7 +67,7 @@ $t_bug_data->status = gpc_get_int( 'status', $t_bug_data->status ); $t_bug_data->resolution = gpc_get_int( 'resolution', $t_bug_data->resolution ); $t_bug_data->projection = gpc_get_int( 'projection', $t_bug_data->projection ); - $t_bug_data->category = gpc_get_string( 'category', $t_bug_data->category ); + $t_bug_data->category_id = gpc_get_int( 'category_id', $t_bug_data->category_id ); $t_bug_data->eta = gpc_get_int( 'eta', $t_bug_data->eta ); $t_bug_data->os = gpc_get_string( 'os', $t_bug_data->os ); $t_bug_data->os_build = gpc_get_string( 'os_build', $t_bug_data->os_build ); diff --git a/bug_update_advanced_page.php b/bug_update_advanced_page.php index cf429d3..03ed16d 100644 --- a/bug_update_advanced_page.php +++ b/bug_update_advanced_page.php @@ -118,8 +118,8 @@ <?php if ( $t_changed_project ) { echo "[" . project_get_field( $t_bug->project_id, 'name' ) . "] "; } ?> - <select <?php echo helper_get_tab_index() ?> name="category"> - <?php print_category_option_list( $t_bug->category, $t_bug->project_id ) ?> + <select <?php echo helper_get_tab_index() ?> name="category_id"> + <?php print_category_option_list( $t_bug->category_id, $t_bug->project_id ) ?> </select> </td> diff --git a/bug_update_page.php b/bug_update_page.php index 1af51da..151b1bc 100644 --- a/bug_update_page.php +++ b/bug_update_page.php @@ -121,8 +121,8 @@ <?php if ( $t_changed_project ) { echo "[" . project_get_field( $t_bug->project_id, 'name' ) . "] "; } ?> - <select <?php echo helper_get_tab_index() ?> name="category"> - <?php print_category_option_list( $t_bug->category, $t_bug->project_id ) ?> + <select <?php echo helper_get_tab_index() ?> name="category_id"> + <?php print_category_option_list( $t_bug->category_id, $t_bug->project_id ) ?> </select> </td> diff --git a/bug_view_advanced_page.php b/bug_view_advanced_page.php index d16f69e..b0581e7 100644 --- a/bug_view_advanced_page.php +++ b/bug_view_advanced_page.php @@ -168,8 +168,7 @@ <!-- Category --> <td> <?php - $t_project_name = string_display( project_get_field( $t_bug->project_id, 'name' ) ); - echo "[$t_project_name] $t_bug->category"; + echo string_display( category_full_name( $t_bug->category_id ) ); ?> </td> diff --git a/bug_view_page.php b/bug_view_page.php index 5ff445a..ad82077 100644 --- a/bug_view_page.php +++ b/bug_view_page.php @@ -171,8 +171,7 @@ <!-- Category --> <td> <?php - $t_project_name = string_display( project_get_field( $t_bug->project_id, 'name' ) ); - echo "[$t_project_name] $t_bug->category"; + echo string_display( category_full_name( $t_bug->category_id ) ); ?> </td> diff --git a/config_defaults_inc.php b/config_defaults_inc.php index 185a83e..8d79641 100644 --- a/config_defaults_inc.php +++ b/config_defaults_inc.php @@ -1345,9 +1345,10 @@ $g_mantis_bug_text_table = '%db_table_prefix%_bug_text%db_table_suffix%'; $g_mantis_bugnote_table = '%db_table_prefix%_bugnote%db_table_suffix%'; $g_mantis_bugnote_text_table = '%db_table_prefix%_bugnote_text%db_table_suffix%'; + $g_mantis_category_table = '%db_table_prefix%_category%db_table_suffix%'; $g_mantis_news_table = '%db_table_prefix%_news%db_table_suffix%'; $g_mantis_plugin_table = '%db_table_prefix%_plugin%db_table_suffix%'; - $g_mantis_project_category_table = '%db_table_prefix%_project_category%db_table_suffix%'; + $g_mantis_project_category_table = '%db_table_prefix%_project_category%db_table_suffix%'; # Legacy table $g_mantis_project_file_table = '%db_table_prefix%_project_file%db_table_suffix%'; $g_mantis_project_table = '%db_table_prefix%_project%db_table_suffix%'; $g_mantis_project_user_list_table = '%db_table_prefix%_project_user_list%db_table_suffix%'; diff --git a/core/bug_api.php b/core/bug_api.php index f6fce02..6fd0542 100644 --- a/core/bug_api.php +++ b/core/bug_api.php @@ -52,7 +52,7 @@ var $status = NEW_; var $resolution = OPEN; var $projection = 10; - var $category = ''; + var $category_id = 0; var $date_submitted = ''; var $last_updated = ''; var $eta = 10; @@ -353,7 +353,7 @@ $c_priority = db_prepare_int( $p_bug_data->priority ); $c_severity = db_prepare_int( $p_bug_data->severity ); $c_reproducibility = db_prepare_int( $p_bug_data->reproducibility ); - $c_category = db_prepare_string( $p_bug_data->category ); + $c_category_id = db_prepare_int( $p_bug_data->category_id ); $c_os = db_prepare_string( $p_bug_data->os ); $c_os_build = db_prepare_string( $p_bug_data->os_build ); $c_platform = db_prepare_string( $p_bug_data->platform ); @@ -378,11 +378,6 @@ trigger_error( ERROR_EMPTY_FIELD, ERROR ); } - if ( is_blank( $c_category ) ) { - error_parameters( lang_get( 'category' ) ); - trigger_error( ERROR_EMPTY_FIELD, ERROR ); - } - # Only set target_version if user has access to do so if ( access_has_project_level( config_get( 'roadmap_update_threshold' ) ) ) { $c_target_version = db_prepare_string( $p_bug_data->target_version ); @@ -392,7 +387,7 @@ $t_bug_table = config_get_global( 'mantis_bug_table' ); $t_bug_text_table = config_get_global( 'mantis_bug_text_table' ); - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); + $t_category_table = config_get_global( 'mantis_category_table' ); # Insert text information $query = "INSERT INTO $t_bug_text_table @@ -415,9 +410,9 @@ # if a default user is associated with the category and we know at this point # that that the bug was not assigned to somebody, then assign it automatically. $query = "SELECT user_id - FROM $t_project_category_table - WHERE project_id=" .db_param(0) . " AND category=" . db_param(1); - $result = db_query_bound( $query, Array( $c_project_id, $c_category ) ); + FROM $t_category_table + WHERE project_id='$c_project_id' AND id='$c_category_id'"; + $result = db_query( $query ); if ( db_num_rows( $result ) > 0 ) { $c_handler_id = $p_handler_id = db_result( $result ); @@ -438,7 +433,7 @@ duplicate_id, priority, severity, reproducibility, status, resolution, - projection, category, + projection, category_id, date_submitted, last_updated, eta, bug_text_id, os, os_build, @@ -453,7 +448,7 @@ '0', '$c_priority', '$c_severity', '$c_reproducibility', '$t_status', '$t_resolution', - 10, '$c_category', + 10, '$c_category_id', " . db_now() . "," . db_now() . ", 10, '$t_text_id', '$c_os', '$c_os_build', @@ -817,7 +812,7 @@ status='$c_bug_data->status', resolution='$c_bug_data->resolution', projection='$c_bug_data->projection', - category='$c_bug_data->category', + category_id='$c_bug_data->category_id', eta='$c_bug_data->eta', os='$c_bug_data->os', os_build='$c_bug_data->os_build', @@ -854,7 +849,7 @@ history_log_event_direct( $p_bug_id, 'status', $t_old_data->status, $p_bug_data->status ); history_log_event_direct( $p_bug_id, 'resolution', $t_old_data->resolution, $p_bug_data->resolution ); history_log_event_direct( $p_bug_id, 'projection', $t_old_data->projection, $p_bug_data->projection ); - history_log_event_direct( $p_bug_id, 'category', $t_old_data->category, $p_bug_data->category ); + history_log_event_direct( $p_bug_id, 'category_id', $t_old_data->category_id, $p_bug_data->category_id ); history_log_event_direct( $p_bug_id, 'eta', $t_old_data->eta, $p_bug_data->eta ); history_log_event_direct( $p_bug_id, 'os', $t_old_data->os, $p_bug_data->os ); history_log_event_direct( $p_bug_id, 'os_build', $t_old_data->os_build, $p_bug_data->os_build ); @@ -1429,7 +1424,7 @@ $t_bug_data->status = db_prepare_int( $p_bug_data->status ); $t_bug_data->resolution = db_prepare_int( $p_bug_data->resolution ); $t_bug_data->projection = db_prepare_int( $p_bug_data->projection ); - $t_bug_data->category = db_prepare_string( $p_bug_data->category ); + $t_bug_data->category_id = db_prepare_string( $p_bug_data->category_id ); $t_bug_data->date_submitted = db_prepare_string( $p_bug_data->date_submitted ); $t_bug_data->last_updated = db_prepare_string( $p_bug_data->last_updated ); $t_bug_data->eta = db_prepare_int( $p_bug_data->eta ); @@ -1456,7 +1451,7 @@ # Return a copy of the bug structure with all the instvars prepared for editing # in an HTML form function bug_prepare_edit( $p_bug_data ) { - $p_bug_data->category = string_attribute( $p_bug_data->category ); + $p_bug_data->category_id = string_attribute( $p_bug_data->category_id ); $p_bug_data->date_submitted = string_attribute( $p_bug_data->date_submitted ); $p_bug_data->last_updated = string_attribute( $p_bug_data->last_updated ); $p_bug_data->os = string_attribute( $p_bug_data->os ); @@ -1480,7 +1475,7 @@ # Return a copy of the bug structure with all the instvars prepared for editing # in an HTML form function bug_prepare_display( $p_bug_data ) { - $p_bug_data->category = string_display_line( $p_bug_data->category ); + $p_bug_data->category_id = string_display_line( $p_bug_data->category_id ); $p_bug_data->date_submitted = string_display_line( $p_bug_data->date_submitted ); $p_bug_data->last_updated = string_display_line( $p_bug_data->last_updated ); $p_bug_data->os = string_display_line( $p_bug_data->os ); diff --git a/core/category_api.php b/core/category_api.php index 97c5b8d..64c047a 100644 --- a/core/category_api.php +++ b/core/category_api.php @@ -23,6 +23,9 @@ ### Category API ### + # Category data cache (to prevent excessive db queries) + $g_category_cache = array(); + #=================================== # Boolean queries and ensures #=================================== @@ -30,31 +33,32 @@ # -------------------- # Check whether the category exists in the project # Return true if the category exists, false otherwise - function category_exists( $p_project_id, $p_category ) { - $c_project_id = db_prepare_int( $p_project_id ); - $c_category = db_prepare_string( $p_category ); + function category_exists( $p_category_id ) { + global $g_category_cache; + if ( isset( $g_category_cache[$p_category_id] ) ) { + return true; + } - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); + $c_category_id = db_prepare_int( $p_category_id ); - $query = "SELECT COUNT(*) - FROM $t_project_category_table - WHERE project_id=" . db_param(0) . " AND - category=" . db_param(1); - $result = db_query_bound( $query, Array( $c_project_id, $c_category ) ); - $category_count = db_result( $result ); + $t_category_table = config_get( 'mantis_category_table' ); - if ( 0 < $category_count ) { - return true; + $query = "SELECT COUNT(*) FROM $t_category_table + WHERE id=" . db_param(0); + $count = db_result( db_query_bound( $query, array( $c_category_id ) ) ); + + if ( 0 < $count ) { + return true; } else { - return false; + return false; } } # -------------------- # Check whether the category exists in the project # Trigger an error if it does not - function category_ensure_exists( $p_project_id, $p_category ) { - if ( !category_exists( $p_project_id, $p_category ) ) { + function category_ensure_exists( $p_category_id ) { + if ( !category_exists( $p_category_id ) ) { trigger_error( ERROR_CATEGORY_NOT_FOUND, ERROR ); } } @@ -62,15 +66,28 @@ # -------------------- # Check whether the category is unique within a project # Returns true if the category is unique, false otherwise - function category_is_unique( $p_project_id, $p_category ) { - return !category_exists( $p_project_id, $p_category ); + function category_is_unique( $p_project_id, $p_name ) { + $c_project_id = db_prepare_int( $p_project_id ); + $c_name = db_prepare_string( $p_name ); + + $t_category_table = config_get( 'mantis_category_table' ); + + $query = "SELECT COUNT(*) FROM $t_category_table + WHERE project_id=" . db_param(0) . " AND " . db_helper_like( 'name', db_param(1) ); + $count = db_result( db_query_bound( $query, array( $c_project_id, $c_name ) ) ); + + if ( 0 < $count ) { + return false; + } else { + return true; + } } # -------------------- # Check whether the category is unique within a project # Trigger an error if it is not - function category_ensure_unique( $p_project_id, $p_category ) { - if ( !category_is_unique( $p_project_id, $p_category ) ) { + function category_ensure_unique( $p_project_id, $p_name ) { + if ( !category_is_unique( $p_project_id, $p_name ) ) { trigger_error( ERROR_CATEGORY_DUPLICATE, ERROR ); } } @@ -82,51 +99,41 @@ # -------------------- # Add a new category to the project - function category_add( $p_project_id, $p_category ) { + function category_add( $p_project_id, $p_name ) { $c_project_id = db_prepare_int( $p_project_id ); - $c_category = db_prepare_string( $p_category ); + $c_name = db_prepare_string( $p_name ); - category_ensure_unique( $p_project_id, $p_category ); + category_ensure_unique( $p_project_id, $p_name ); - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); + $t_category_table = config_get( 'mantis_category_table' ); - $query = "INSERT INTO $t_project_category_table - ( project_id, category ) + $query = "INSERT INTO $t_category_table + ( project_id, name ) VALUES - ( " . db_param(0) . ',' . db_param(1) . ')'; - db_query_bound( $query, Array( $c_project_id, $c_category ) ); + ( " . db_param(0) . ', ' . db_param(1) . ' )'; + db_query_bound( $query, array( $c_project_id, $c_name ) ); # db_query errors on failure so: - return true; + return db_insert_id( $t_category_table ); } # -------------------- # Update the name and user associated with the category - function category_update( $p_project_id, $p_category, $p_new_category, $p_assigned_to ) { - $c_project_id = db_prepare_int( $p_project_id ); - $c_category = db_prepare_string( $p_category ); - $c_new_category = db_prepare_string( $p_new_category ); + function category_update( $p_category_id, $p_name, $p_assigned_to ) { + $c_category_id = db_prepare_int( $p_category_id ); + $c_name = db_prepare_string( $p_name ); $c_assigned_to = db_prepare_int( $p_assigned_to ); - category_ensure_exists( $p_project_id, $p_category ); + category_ensure_exists( $p_category_id ); - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); - $t_bug_table = config_get_global( 'mantis_bug_table' ); + $t_category_table = config_get( 'mantis_category_table' ); + $t_bug_table = config_get( 'mantis_bug_table' ); - $query = "UPDATE $t_project_category_table - SET category=" . db_param(0) . ", - user_id=" . db_param(1) . " - WHERE category=" . db_param(2) . " AND - project_id=" . db_param(3); - db_query_bound( $query, Array( $c_new_category, $c_assigned_to, $c_category, $c_project_id ) ); - - if ( $p_category != $p_new_category ) { - $query = "UPDATE $t_bug_table - SET category=" . db_param(0) . " - WHERE category=" . db_param(1) . " AND - project_id=" . db_param(2); - db_query_bound( $query, Array( $c_new_category, $c_category, $c_project_id ) ); - } + $query = "UPDATE $t_category_table + SET name=" . db_param(0) . ', + user_id=' . db_param(1) . ' + WHERE id=' . db_param(2); + db_query_bound( $query, array( $c_name, $c_assigned_to, $c_category_id ) ); # db_query errors on failure so: return true; @@ -134,29 +141,26 @@ # -------------------- # Remove a category from the project - function category_remove( $p_project_id, $p_category, $p_new_category='' ) { - $c_project_id = db_prepare_int( $p_project_id ); - $c_category = db_prepare_string( $p_category ); - $c_new_category = db_prepare_string( $p_new_category ); + function category_remove( $p_category_id, $p_new_category=0 ) { + $c_category_id = db_prepare_int( $p_category_id ); + $c_new_category = db_prepare_int( $p_new_category ); - category_ensure_exists( $p_project_id, $p_category ); - if ( !is_blank( $p_new_category ) ) { - category_ensure_exists( $p_project_id, $p_new_category ); + category_ensure_exists( $p_category_id ); + if ( 0 != $p_new_category ) { + category_ensure_exists( $p_new_category ); } - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); - $t_bug_table = config_get_global( 'mantis_bug_table' ); + $t_category_table = config_get( 'mantis_category_table' ); + $t_bug_table = config_get( 'mantis_bug_table' ); - $query = "DELETE FROM $t_project_category_table - WHERE project_id=" . db_param(0) . " AND - category=" . db_param(1); - db_query_bound( $query, Array( $c_project_id, $c_category ) ); + $query = "DELETE FROM $t_category_table + WHERE id=" . db_param(0); + db_query_bound( $query, array( $c_category_id ) ); $query = "UPDATE $t_bug_table - SET category=" . db_param(0) . " - WHERE category=" . db_param(1) . " AND - project_id=" . db_param(2); - db_query_bound( $query, Array( $c_new_category, $c_category, $c_project_id ) ); + SET category_id=" . db_param(0) . " + WHERE category_id=" . db_param(1); + db_query_bound( $query, array( $c_new_category, $c_category_id ) ); # db_query errors on failure so: return true; @@ -164,22 +168,26 @@ # -------------------- # Remove all categories associated with a project - function category_remove_all( $p_project_id ) { + function category_remove_all( $p_project_id, $p_new_category=0 ) { $c_project_id = db_prepare_int( $p_project_id ); + $c_new_category = db_prepare_int( $p_new_category ); project_ensure_exists( $p_project_id ); + if ( 0 != $p_new_category ) { + category_ensure_exists( $p_new_category ); + } - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); - $t_bug_table = config_get_global( 'mantis_bug_table' ); + $t_category_table = config_get( 'mantis_category_table' ); + $t_bug_table = config_get( 'mantis_bug_table' ); - $query = "DELETE FROM $t_project_category_table - WHERE project_id=" . db_param(0); - db_query_bound( $query, Array( $c_project_id ) ); + $query = "DELETE FROM $t_category_table + WHERE project_id='$c_project_id'"; + db_query_bound( $query, array( $c_project_id ) ); $query = "UPDATE $t_bug_table - SET category='' - WHERE project_id=" . db_param(0); - db_query_bound( $query, Array( $c_project_id ) ); + SET category='$c_new_category' + WHERE project_id='$c_project_id'"; + db_query_bound( $query, array( $c_new_category, $c_project_id ) ); # db_query errors on failure so: return true; @@ -192,45 +200,74 @@ # -------------------- # Return the definition row for the category - function category_get_row( $p_project_id, $p_category ) { - $c_project_id = db_prepare_int( $p_project_id ); - $c_category = db_prepare_string( $p_category ); + function category_get_row( $p_category_id ) { + global $g_category_cache; + if ( isset( $g_category_cache[$p_category_id] ) ) { + return $g_category_cache[$p_category_id]; + } - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); + $c_category_id = db_prepare_int( $p_category_id ); - $query = "SELECT category, user_id - FROM $t_project_category_table - WHERE project_id=" . db_param(0) . " AND - category=" . db_param(1); - $result = db_query_bound( $query, Array( $c_project_id, $c_category ) ); + $t_category_table = config_get( 'mantis_category_table' ); + $t_project_table = config_get( 'mantis_project_table' ); + + $query = "SELECT c.*, p.name AS project_name FROM $t_category_table AS c + JOIN $t_project_table AS p + ON c.project_id=p.id + WHERE c.id=" . db_param(0); + $result = db_query_bound( $query, array( $c_category_id ) ); $count = db_num_rows( $result ); if ( 0 == $count ) { trigger_error( ERROR_CATEGORY_NOT_FOUND, ERROR ); } - return db_fetch_array( $result ); + $row = db_fetch_array( $result ); + $g_category_cache[$p_category_id] = $row; + return $row; } # -------------------- # Return all categories for the specified project id function category_get_all_rows( $p_project_id ) { + global $g_category_cache; + $c_project_id = db_prepare_int( $p_project_id ); - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); + $t_category_table = config_get( 'mantis_category_table' ); + $t_project_table = config_get( 'mantis_project_table' ); - $query = "SELECT category, user_id - FROM $t_project_category_table - WHERE project_id=" . db_param(0) . " - ORDER BY category"; - $result = db_query_bound( $query, Array( $c_project_id ) ); + $t_project_where = helper_project_specific_where( $c_project_id ); + + $query = "SELECT c.*, p.name AS project_name FROM $t_category_table AS c + JOIN $t_project_table AS p + ON c.project_id=p.id + WHERE $t_project_where + ORDER BY c.name "; + $result = db_query_bound( $query, array() ); $count = db_num_rows( $result ); $rows = array(); for ( $i = 0 ; $i < $count ; $i++ ) { $row = db_fetch_array( $result ); $rows[] = $row; + $g_category_cache[$row['id']] = $row; } return $rows; } -?> + + # Helpers + + function category_full_name( $p_category_id, $p_show_project=true ) { + if ( $p_category_id == 0 ) { + return lang_get( 'no_category' ); + } + + $t_row = category_get_row( $p_category_id ); + + if ( $p_show_project ) { + return "[$t_row[project_name]] $t_row[name]"; + } else { + return $t_row['name']; + } + } diff --git a/core/columns_api.php b/core/columns_api.php index 65bc271..8f08254 100644 --- a/core/columns_api.php +++ b/core/columns_api.php @@ -534,7 +534,7 @@ echo ']</small><br />'; } - echo string_display( $p_row['category'] ); + echo string_display( category_full_name( $p_row['category_id'], false ) ); echo '</td>'; } diff --git a/core/filter_api.php b/core/filter_api.php index a7b3cd6..a60033d 100644 --- a/core/filter_api.php +++ b/core/filter_api.php @@ -413,6 +413,7 @@ $t_bug_table = config_get_global( 'mantis_bug_table' ); $t_bug_text_table = config_get_global( 'mantis_bug_text_table' ); $t_bugnote_table = config_get_global( 'mantis_bugnote_table' ); + $t_category_table = config_get_global( 'mantis_category_table' ); $t_custom_field_string_table = config_get_global( 'mantis_custom_field_string_table' ); $t_bugnote_text_table = config_get_global( 'mantis_bugnote_text_table' ); $t_project_table = config_get_global( 'mantis_project_table' ); @@ -696,9 +697,7 @@ $t_clauses = array(); foreach( $t_filter['show_category'] as $t_filter_member ) { - $t_filter_member = stripslashes( $t_filter_member ); if ( META_FILTER_NONE == $t_filter_member ) { - array_push( $t_clauses, "''" ); } else { $c_show_category = db_prepare_string( $t_filter_member ); array_push( $t_clauses, "'$c_show_category'" ); @@ -706,9 +705,9 @@ } if ( 1 < count( $t_clauses ) ) { - array_push( $t_where_clauses, "( $t_bug_table.category in (". implode( ', ', $t_clauses ) .") )" ); + array_push( $t_where_clauses, "( $t_bug_table.category_id in ( SELECT id FROM $t_category_table WHERE name in (". implode( ', ', $t_clauses ) .") ) )" ); } else { - array_push( $t_where_clauses, "( $t_bug_table.category=$t_clauses[0] )" ); + array_push( $t_where_clauses, "( $t_bug_table.category_id in ( SELECT id FROM $t_category_table WHERE name=$t_clauses[0] ) )" ); } } @@ -1765,13 +1764,11 @@ } else { $t_first_flag = true; foreach( $t_filter['show_category'] as $t_current ) { - $t_current = stripslashes( $t_current ); ?> - <input type="hidden" name="show_category[]" value="<?php echo string_display( $t_current );?>" /> + <input type="hidden" name="show_category[]" value="<?php echo $t_current;?>" /> <?php $t_this_string = ''; - if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) ) - || ( is_blank( $t_current ) ) ) { + if ( is_blank( $t_current ) || $t_current === "0" || $t_current === META_FILTER_ANY ) { $t_any_found = true; } else { $t_this_string = string_display( $t_current ); @@ -3334,8 +3331,7 @@ <!-- Category --> <select <?php PRINT $t_select_modifier;?> name="show_category[]"> <option value="<?php echo META_FILTER_ANY ?>" <?php check_selected( $t_filter['show_category'], META_FILTER_ANY ); ?>>[<?php echo lang_get( 'any' ) ?>]</option> - <?php # This shows orphaned categories as well as selectable categories ?> - <?php print_category_complete_option_list( $t_filter['show_category'] ) ?> + <?php print_category_filter_option_list( $t_filter['show_category'] ) ?> </select> <?php } diff --git a/core/graph_api.php b/core/graph_api.php index 2393a11..df60a9a 100644 --- a/core/graph_api.php +++ b/core/graph_api.php @@ -591,30 +591,28 @@ global $category_name, $category_bug_count; $t_project_id = helper_get_current_project(); - $t_cat_table = config_get_global( 'mantis_project_category_table' ); - $t_bug_table = config_get_global( 'mantis_bug_table' ); + $t_cat_table = config_get( 'mantis_category_table' ); + $t_bug_table = config_get( 'mantis_bug_table' ); $t_user_id = auth_get_current_user_id(); $specific_where = helper_project_specific_where( $t_project_id, $t_user_id ); - $query = "SELECT DISTINCT category + $query = "SELECT id, name FROM $t_cat_table WHERE $specific_where - ORDER BY category"; + ORDER BY name"; $result = db_query( $query ); $category_count = db_num_rows( $result ); - if ( 0 == $category_count ) { - return array(); - } + $t_metrics = array(); for ($i=0;$i<$category_count;$i++) { $row = db_fetch_array( $result ); - $t_cat_name = $row['category']; - $c_category_name = addslashes($t_cat_name); + $t_cat_name = $row['name']; + $t_cat_id = $row['id']; $query = "SELECT COUNT(*) FROM $t_bug_table - WHERE category='$c_category_name' AND $specific_where"; + WHERE category_id='$t_cat_id' AND $specific_where"; $result2 = db_query( $query ); - $t_metrics[$t_cat_name] = db_result( $result2, 0, 0 ); + $t_metrics[$t_cat_name] = $t_metrics[$t_cat_name] + db_result( $result2, 0, 0 ); } # end for return $t_metrics; } diff --git a/core/history_api.php b/core/history_api.php index 2a6b003..0f51a76 100644 --- a/core/history_api.php +++ b/core/history_api.php @@ -216,6 +216,11 @@ case 'category': $t_field_localized = lang_get( 'category' ); break; + case 'category_id': + $t_field_localized = lang_get( 'category' ); + $p_old_value = category_full_name( $p_old_value, false ); + $p_new_value = category_full_name( $p_new_value, false ); + break; case 'status': $p_old_value = get_enum_element( 'status', $p_old_value ); $p_new_value = get_enum_element( 'status', $p_new_value ); diff --git a/core/my_view_inc.php b/core/my_view_inc.php index dbc86b3..e46e7ab 100644 --- a/core/my_view_inc.php +++ b/core/my_view_inc.php @@ -279,11 +279,10 @@ # type project name if viewing 'all projects' or bug is in subproject if ( ON == config_get( 'show_bug_project_links' ) && helper_get_current_project() != $v_project_id ) { - echo '['; - print( $project_name ); - echo '] '; + echo string_display( category_full_name( $v_category_id ) ); + } else { + echo string_display( category_full_name( $v_category_id, false ) ); } - echo string_display( $v_category ); if ( $v_last_updated > strtotime( '-'.$t_filter['highlight_changed'].' hours' ) ) { echo ' - <b>' . $t_last_updated . '</b>'; diff --git a/core/print_api.php b/core/print_api.php index 65c4795..34ecb7c 100644 --- a/core/print_api.php +++ b/core/print_api.php @@ -424,7 +424,7 @@ # -------------------- # print a news item given a row in the news table. - function print_news_entry_from_row( $p_news_row ) { + function print_news_entry_from_row( $p_news_row ) { extract( $p_news_row, EXTR_PREFIX_ALL, 'v' ); print_news_entry( $v_headline, $v_body, $v_poster_id, $v_view_state, $v_announcement, $v_date_posted ); } @@ -673,12 +673,14 @@ PRINT ">$v_name</option>"; } # end for } + # -------------------- # Since categories can be orphaned we need to grab all unique instances of category # We check in the project category table and in the bug table # We put them all in one array and make sure the entries are unique - function print_category_option_list( $p_category='', $p_project_id = null ) { - $t_mantis_project_category_table = config_get_global( 'mantis_project_category_table' ); + function print_category_option_list( $p_category_id = 0, $p_project_id = null ) { + $t_category_table = config_get( 'mantis_category_table' ); + $t_project_table = config_get( 'mantis_project_table' ); if ( null === $p_project_id ) { $c_project_id = helper_get_current_project(); @@ -690,81 +692,61 @@ # grab all categories in the project category table $cat_arr = array(); - $query = "SELECT DISTINCT category - FROM $t_mantis_project_category_table + $query = "SELECT id,name FROM $t_category_table WHERE $t_project_where - ORDER BY category"; + ORDER BY name"; $result = db_query( $query ); - $category_count = db_num_rows( $result ); - for ($i=0;$i<$category_count;$i++) { - $row = db_fetch_array( $result ); - $cat_arr[] = string_attribute( $row['category'] ); - } - # Add the default option if not in the list retrieved from DB - # This is useful for default categories and when updating an - # issue with a deleted category. - if ( !is_blank( $p_category ) && !in_array( $p_category, $cat_arr ) ) { - $cat_arr[] = $p_category; + while ( $row = db_fetch_array( $result ) ) { + $cat_arr[$row['id']] = $row['name']; } + asort($cat_arr); - sort( $cat_arr ); - $cat_arr = array_unique( $cat_arr ); - - foreach( $cat_arr as $t_category ) { - PRINT "<option value=\"$t_category\""; - check_selected( $t_category, $p_category ); - PRINT ">$t_category</option>"; + foreach( $cat_arr as $t_category_id => $t_name ) { + PRINT "<option value=\"$t_category_id\""; + check_selected( $p_category_id, $t_category_id ); + PRINT ">$t_name</option>"; } } # -------------------- # Since categories can be orphaned we need to grab all unique instances of category # We check in the project category table and in the bug table # We put them all in one array and make sure the entries are unique - function print_category_complete_option_list( $p_category='', $p_project_id = null ) { - $t_mantis_project_category_table = config_get_global( 'mantis_project_category_table' ); - $t_mantis_bug_table = config_get_global( 'mantis_bug_table' ); + function print_category_complete_option_list( $p_category_id = 0, $p_project_id = null ) { + return print_category_option_list( $p_category_id, $p_project_id ); + } + + # --------- + # Now that categories are identified by numerical ID, we need an old-style name + # based option list to keep existing filter functionality. + function print_category_filter_option_list( $p_category_name = '', $p_project_id = null ) { + $t_category_table = config_get( 'mantis_category_table' ); + $t_project_table = config_get( 'mantis_project_table' ); if ( null === $p_project_id ) { - $t_project_id = helper_get_current_project(); + $c_project_id = helper_get_current_project(); } else { - $t_project_id = $p_project_id; + $c_project_id = db_prepare_int( $p_project_id ); } - $t_project_where = helper_project_specific_where( $t_project_id ); + $t_project_where = helper_project_specific_where( $c_project_id ); # grab all categories in the project category table $cat_arr = array(); - $query = "SELECT DISTINCT category - FROM $t_mantis_project_category_table + $query = "SELECT DISTINCT name FROM $t_category_table WHERE $t_project_where - ORDER BY category"; + ORDER BY name"; $result = db_query( $query ); - $category_count = db_num_rows( $result ); - for ($i=0;$i<$category_count;$i++) { - $row = db_fetch_array( $result ); - $cat_arr[] = string_attribute( $row['category'] ); - } - # grab all categories in the bug table - $query = "SELECT DISTINCT category - FROM $t_mantis_bug_table - WHERE $t_project_where - ORDER BY category"; - $result = db_query( $query ); - $category_count = db_num_rows( $result ); - - for ($i=0;$i<$category_count;$i++) { - $row = db_fetch_array( $result ); - $cat_arr[] = string_attribute( $row['category'] ); + while ( $row = db_fetch_array( $result ) ) { + $cat_arr[] = $row['name']; } - sort( $cat_arr ); - $cat_arr = array_unique( $cat_arr ); + sort($cat_arr); - foreach( $cat_arr as $t_category ) { - PRINT "<option value=\"$t_category\""; - check_selected( $p_category, $t_category ); - PRINT ">$t_category</option>"; + foreach( $cat_arr as $t_name ) { + PRINT "<option value=\"$t_name\""; + check_selected( $p_category_name, $t_name ); + PRINT ">$t_name</option>"; } } @@ -1257,26 +1239,26 @@ } # -------------------- function print_project_category_string( $p_project_id ) { - $t_mantis_project_category_table = config_get_global( 'mantis_project_category_table' ); + $t_mantis_category_table = config_get( 'mantis_category_table' ); $c_project_id = db_prepare_int( $p_project_id ); - $query = "SELECT category - FROM $t_mantis_project_category_table - WHERE project_id=" . db_param(0) . " - ORDER BY category"; - $result = db_query_bound( $query, Array( $c_project_id ) ); + $query = "SELECT name + FROM $t_mantis_category_table + WHERE project_id='$c_project_id' + ORDER BY name"; + $result = db_query( $query ); $category_count = db_num_rows( $result ); $t_string = ''; for ($i=0;$i<$category_count;$i++) { $row = db_fetch_array( $result ); - $t_category = $row['category']; + $t_name = $row['name']; if ( $i+1 < $category_count ) { - $t_string .= $t_category.', '; + $t_string .= $t_name.', '; } else { - $t_string .= $t_category; + $t_string .= $t_name; } } @@ -1500,7 +1482,7 @@ } print_page_link( $p_page, $t_last, $p_end, $p_current, $p_temp_filter_id ); - print( " ]" ); + print( " ]" ); } # -------------------- # print a mailto: href link diff --git a/core/summary_api.php b/core/summary_api.php index e0a8e4f..3d514da 100644 --- a/core/summary_api.php +++ b/core/summary_api.php @@ -536,6 +536,7 @@ # print a bug count per category function summary_print_by_category() { $t_mantis_bug_table = config_get_global( 'mantis_bug_table' ); + $t_mantis_category_table = config_get( 'mantis_category_table' ); $t_mantis_project_table = config_get_global( 'mantis_project_table' ); $t_summary_category_include_project = config_get( 'summary_category_include_project' ); @@ -548,15 +549,17 @@ } $t_project_query = ( ON == $t_summary_category_include_project ) ? 'project_id, ' : ''; - $query = "SELECT COUNT(id) as bugcount, $t_project_query category, status + $query = "SELECT COUNT(id) as bugcount, $t_project_query c.name AS category_name, c.id AS categor_id status FROM $t_mantis_bug_table - WHERE category>'' AND $specific_where - GROUP BY $t_project_query category, status - ORDER BY $t_project_query category, status"; + JOIN $t_mantis_category_table AS c ON category_id=c.id + WHERE $specific_where + GROUP BY $t_project_query category_name, status + ORDER BY $t_project_query category_name, status"; $result = db_query( $query ); - $last_category = -1; + $last_category_name = -1; + $last_category_id = -1; $last_project = -1; $t_bugs_open = 0; $t_bugs_resolved = 0; @@ -569,13 +572,13 @@ while ( $row = db_fetch_array( $result ) ) { extract( $row, EXTR_PREFIX_ALL, 'v' ); - if ( ( $v_category != $last_category ) && ( $last_category != -1 ) ) { - $label = $last_category; + if ( ( $v_category_id != $last_category_id ) && ( $last_category_id != -1 ) ) { + $label = $last_category_name; if ( ( ON == $t_summary_category_include_project ) && ( ALL_PROJECTS == $t_project_id ) ) { $label = sprintf( '[%s] %s', project_get_name( $last_project ), $label ); } - $t_bug_link = '<a class="subtle" href="' . config_get( 'bug_count_hyperlink_prefix' ) . '&show_category=' . urlencode( $last_category ); + $t_bug_link = '<a class="subtle" href="' . config_get( 'bug_count_hyperlink_prefix' ) . '&show_category=' . urlencode( $last_category_id ); if ( 0 < $t_bugs_open ) { $t_bugs_open = $t_bug_link . '&hide_status=' . RESOLVED . '">' . $t_bugs_open . '</a>'; } @@ -606,19 +609,20 @@ $t_bugs_open += $row['bugcount']; } - $last_category = $v_category; + $last_category_id = $v_category_id; + $last_category_name = $v_category_name; if ( ( ON == $t_summary_category_include_project ) && ( ALL_PROJECTS == $t_project_id ) ) { $last_project = $v_project_id; } } if ( 0 < $t_bugs_total ) { - $label = $last_category; + $label = $last_category_name; if ( ( ON == $t_summary_category_include_project ) && ( ALL_PROJECTS == $t_project_id ) ) { $label = sprintf( '[%s] %s', project_get_name( $last_project ), $label ); } - $t_bug_link = '<a class="subtle" href="' . config_get( 'bug_count_hyperlink_prefix' ) . '&show_category=' . urlencode( $last_category ); + $t_bug_link = '<a class="subtle" href="' . config_get( 'bug_count_hyperlink_prefix' ) . '&show_category=' . urlencode( $last_category_id ); if ( !is_blank( $t_bug_link ) ) { if ( 0 < $t_bugs_open ) { $t_bugs_open = $t_bug_link . '&hide_status=' . RESOLVED . '">' . $t_bugs_open . '</a>'; diff --git a/graphs/graph_by_category.php b/graphs/graph_by_category.php index a969d25..8e5f098 100644 --- a/graphs/graph_by_category.php +++ b/graphs/graph_by_category.php @@ -36,12 +36,13 @@ $data_category_arr = array(); $data_count_arr = array(); - $query = "SELECT category, COUNT(category) as count + $query = "SELECT c.name AS name, COUNT(name) as count FROM mantis_bug_table - WHERE project_id=" . db_param(0) . " - GROUP BY category - ORDER BY category"; - $result = db_query_bound( $query, Array( $t_project_id ) ); + JOIN mantis_category_table AS c + WHERE project_id='$t_project_id' + GROUP BY name + ORDER BY name"; + $result = db_query( $query ); $category_count = db_num_rows( $result ); $total = 0; $longest_size = 0; @@ -50,11 +51,11 @@ extract( $row ); $total += $count; - $data_category_arr[] = $category; + $data_category_arr[] = $name; $data_count_arr[] = $count; - if ( strlen( $category ) > $longest_size ) { - $longest_size = strlen( $category ); + if ( strlen( $name ) > $longest_size ) { + $longest_size = strlen( $name ); } } $longest_size++; diff --git a/lang/strings_english.txt b/lang/strings_english.txt index 4d1527d..afc07b0 100644 --- a/lang/strings_english.txt +++ b/lang/strings_english.txt @@ -592,6 +592,7 @@ $s_update_simple_link = 'Update Simple'; $s_updating_bug_advanced_title = 'Updating Issue Information'; $s_id = 'ID'; $s_category = 'Category'; +$s_no_category = 'N/A'; $s_severity = 'Severity'; $s_reproducibility = 'Reproducibility'; $s_date_submitted = 'Date Submitted'; diff --git a/manage_proj_cat_add.php b/manage_proj_cat_add.php index 27717f9..9675b08 100644 --- a/manage_proj_cat_add.php +++ b/manage_proj_cat_add.php @@ -30,25 +30,25 @@ auth_reauthenticate(); $f_project_id = gpc_get_int( 'project_id' ); - $f_category = gpc_get_string( 'category' ); + $f_name = gpc_get_string( 'name' ); access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id ); - if ( is_blank( $f_category ) ) { + if ( is_blank( $f_name ) ) { trigger_error( ERROR_EMPTY_FIELD, ERROR ); } - $t_categories = explode( '|', $f_category ); - $t_category_count = count( $t_categories ); + $t_names = explode( '|', $f_name ); + $t_category_count = count( $t_names ); - foreach ( $t_categories as $t_category ) { - if ( is_blank( $t_category ) ) { + foreach ( $t_names as $t_name ) { + if ( is_blank( $t_name ) ) { continue; } - $t_category = trim( $t_category ); - if ( category_is_unique( $f_project_id, $t_category ) ) { - category_add( $f_project_id, $t_category ); + $t_name = trim( $t_name ); + if ( category_is_unique( $f_project_id, $t_name ) ) { + category_add( $f_project_id, $t_name ); } else if ( 1 == $t_category_count ) { # We only error out on duplicates when a single value was # given. If multiple values were given, we just add the diff --git a/manage_proj_cat_copy.php b/manage_proj_cat_copy.php index d7b7c12..f205c71 100644 --- a/manage_proj_cat_copy.php +++ b/manage_proj_cat_copy.php @@ -50,10 +50,10 @@ $rows = category_get_all_rows( $t_src_project_id ); foreach ( $rows as $row ) { - $t_category = $row['category']; + $t_name = $row['name']; - if ( category_is_unique( $t_dst_project_id, $t_category ) ) { - category_add( $t_dst_project_id, $t_category ); + if ( category_is_unique( $t_dst_project_id, $t_name ) ) { + category_add( $t_dst_project_id, $t_name ); } } diff --git a/manage_proj_cat_delete.php b/manage_proj_cat_delete.php index 6dc7966..934e7bf 100644 --- a/manage_proj_cat_delete.php +++ b/manage_proj_cat_delete.php @@ -29,19 +29,22 @@ auth_reauthenticate(); - $f_project_id = gpc_get_int( 'project_id' ); - $f_category = gpc_get_string( 'category' ); + $f_category_id = gpc_get_string( 'id' ); access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id ); + $t_row = category_get_row( $f_category_id ); + $t_name = category_full_name( $f_category_id ); + $t_project_id = $t_row['project_id']; + # Confirm with the user helper_ensure_confirmed( lang_get( 'category_delete_sure_msg' ) . - '<br/>' . lang_get( 'category' ) . ': ' . $f_category, + '<br/>' . lang_get( 'category' ) . ': ' . $t_name, lang_get( 'delete_category_button' ) ); - category_remove( $f_project_id, $f_category ); + category_remove( $f_category_id ); - $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $f_project_id; + $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $t_project_id; html_page_top1(); html_meta_redirect( $t_redirect_url ); diff --git a/manage_proj_cat_edit_page.php b/manage_proj_cat_edit_page.php index ca00e1b..ed69979 100644 --- a/manage_proj_cat_edit_page.php +++ b/manage_proj_cat_edit_page.php @@ -29,13 +29,14 @@ auth_reauthenticate(); - $f_project_id = gpc_get_int( 'project_id' ); - $f_category = gpc_get_string( 'category' ); + $f_category_id = gpc_get_string( 'id' ); access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id ); - $t_row = category_get_row( $f_project_id, $f_category ); + $t_row = category_get_row( $f_category_id ); $t_assigned_to = $t_row['user_id']; + $t_project_id = $t_row['project_id']; + $t_name = $t_row['name']; html_page_top1(); html_page_top2(); @@ -54,12 +55,11 @@ </tr> <tr <?php echo helper_alternate_class() ?>> <td class="category"> - <input type="hidden" name="project_id" value="<?php echo string_attribute( $f_project_id ) ?>" /> - <input type="hidden" name="category" value="<?php echo string_attribute( $f_category ) ?>" /> + <input type="hidden" name="category_id" value="<?php echo string_attribute( $f_category_id ) ?>" /> <?php echo lang_get( 'category' ) ?> </td> <td> - <input type="text" name="new_category" size="32" maxlength="64" value="<?php echo string_attribute( $f_category ) ?>" /> + <input type="text" name="name" size="32" maxlength="64" value="<?php echo string_attribute( $t_name ) ?>" /> </td> </tr> <tr <?php echo helper_alternate_class() ?>> @@ -69,7 +69,7 @@ <td> <select name="assigned_to"> <option value="0"></option> - <?php print_assign_to_option_list( $t_assigned_to, $f_project_id ) ?> + <?php print_assign_to_option_list( $t_assigned_to, $t_project_id ) ?> </select> </td> </tr> @@ -89,8 +89,7 @@ <div class="border-center"> <form method="post" action="manage_proj_cat_delete.php"> - <input type="hidden" name="project_id" value="<?php echo string_attribute( $f_project_id ) ?>" /> - <input type="hidden" name="category" value="<?php echo string_attribute( $f_category ) ?>" /> + <input type="hidden" name="category_id" value="<?php echo string_attribute( $f_category_id ) ?>" /> <input type="submit" class="button" value="<?php echo lang_get( 'delete_category_button' ) ?>" /> </form> </div> diff --git a/manage_proj_cat_update.php b/manage_proj_cat_update.php index 05afd1e..98610e8 100644 --- a/manage_proj_cat_update.php +++ b/manage_proj_cat_update.php @@ -29,29 +29,28 @@ auth_reauthenticate(); - $f_project_id = gpc_get_int( 'project_id' ); - $f_category = gpc_get_string( 'category' ); - $f_new_category = gpc_get_string( 'new_category' ); + $f_category_id = gpc_get_int( 'category_id' ); + $f_name = trim( gpc_get_string( 'name' ) ); $f_assigned_to = gpc_get_int( 'assigned_to', 0 ); access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id ); - if ( is_blank( $f_new_category ) ) { + if ( is_blank( $f_name ) ) { trigger_error( ERROR_EMPTY_FIELD, ERROR ); } - $f_category = trim( $f_category ); - $f_new_category = trim( $f_new_category ); + $t_row = category_get_row( $f_category_id ); + $t_old_name = $t_row['name']; + $t_project_id = $t_row['project_id']; # check for duplicate - if ( strtolower( $f_category ) == strtolower( $f_new_category ) || - category_is_unique( $f_project_id, $f_new_category ) ) { - category_update( $f_project_id, $f_category, $f_new_category, $f_assigned_to ); - } else { - trigger_error( ERROR_CATEGORY_DUPLICATE, ERROR ); + if ( strtolower( $f_name ) != strtolower( $t_old_name ) ) { + category_ensure_unique( $t_project_id, $f_name ); } + + category_update( $f_category_id, $f_name, $f_assigned_to ); - $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $f_project_id; + $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $t_project_id; html_page_top1(); diff --git a/manage_proj_edit_page.php b/manage_proj_edit_page.php index 41c4304..13c83a2 100644 --- a/manage_proj_edit_page.php +++ b/manage_proj_edit_page.php @@ -302,7 +302,8 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?> } foreach ( $t_categories as $t_category ) { - $t_name = $t_category['category']; + $t_id = $t_category['id']; + $t_name = $t_category['name']; if ( NO_USER != $t_category['user_id'] && user_exists( $t_category['user_id'] )) { $t_user_name = user_get_name( $t_category['user_id'] ); @@ -320,11 +321,11 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?> </td> <td class="center"> <?php - $t_name = urlencode( $t_name ); + $t_id = urlencode( $t_id ); - print_button( 'manage_proj_cat_edit_page.php?project_id=' . $f_project_id . '&category=' . $t_name, lang_get( 'edit_link' ) ); + print_button( 'manage_proj_cat_edit_page.php?id=' . $t_id, lang_get( 'edit_link' ) ); echo ' '; - print_button( 'manage_proj_cat_delete.php?project_id=' . $f_project_id . '&category=' . $t_name, lang_get( 'delete_link' ) ); + print_button( 'manage_proj_cat_delete.php?id=' . $t_id, lang_get( 'delete_link' ) ); ?> </td> </tr> @@ -337,7 +338,7 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?> <td class="left" colspan="3"> <form method="post" action="manage_proj_cat_add.php"> <input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" /> - <input type="text" name="category" size="32" maxlength="64" /> + <input type="text" name="name" size="32" maxlength="64" /> <input type="submit" class="button" value="<?php echo lang_get( 'add_category_button' ) ?>" /> </form> </td> diff --git a/my_view_page.php b/my_view_page.php index febd47b..d286294 100644 --- a/my_view_page.php +++ b/my_view_page.php @@ -34,6 +34,9 @@ $t_current_user_id = auth_get_current_user_id(); + # Improve performance by caching category data in one pass + category_get_all_rows( helper_get_current_project() ); + compress_enable(); html_page_top1( lang_get( 'my_view_link' ) ); diff --git a/view_all_inc.php b/view_all_inc.php index 16e4992..8131b17 100644 --- a/view_all_inc.php +++ b/view_all_inc.php @@ -43,6 +43,9 @@ $t_icon_path = config_get( 'icon_path' ); $t_update_bug_threshold = config_get( 'update_bug_threshold' ); + # Improve performance by caching category data in one pass + category_get_all_rows( helper_get_current_project() ); + $t_columns = helper_get_columns_to_view( COLUMNS_TARGET_VIEW_PAGE ); $col_count = sizeof( $t_columns ); mantis-categories-2007-11-12.patch (60,540 bytes)
diff --git a/admin/install.php b/admin/install.php index be2ef6a..a74c593 100644 --- a/admin/install.php +++ b/admin/install.php @@ -28,6 +28,7 @@ $g_skip_open_db = true; # don't open the database in database_api.php define( 'PLUGINS_DISABLED', true ); @require_once( dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'core.php' ); + @require_once( 'install_functions.php' ); $g_error_send_page_header = false; # bypass page headers in error handler define( 'BAD', 0 ); diff --git a/admin/install_functions.php b/admin/install_functions.php new file mode 100644 index 0000000..ddda15f --- /dev/null +++ b/admin/install_functions.php @@ -0,0 +1,64 @@ +<?php + # Mantis - a php based bugtracking system + # Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org + # Copyright (C) 2002 - 2007 Mantis Team - mantisbt-dev@lists.sourceforge.net + # This program is distributed under the terms and conditions of the GPL + # See the README and LICENSE files for details + + # -------------------------------------------------------- + # $Id: $ + # -------------------------------------------------------- + + /** + * Update functions for the installation schema's 'UpdateFunction' option. + * All functions must be name install_<function_name> and referenced as just <function_name>. + */ + + /** + * Migrate the legacy category data to the new category_id-based schema. + */ + function install_category_migrate() { + $t_bug_table = config_get( 'mantis_bug_table' ); + $t_category_table = config_get( 'mantis_category_table' ); + $t_project_category_table = config_get( 'mantis_project_category_table' ); + + $query = "SELECT project_id, category FROM $t_project_category_table ORDER BY project_id, category"; + $t_category_result = db_query( $query ); + + $query = "SELECT project_id, category FROM $t_bug_table ORDER BY project_id, category"; + $t_bug_result = db_query( $query ); + + $t_data = Array(); + + # Find categories specified by project + while ( $row = db_fetch_array( $t_category_result ) ) { + $t_project_id = $row['project_id']; + $t_name = $row['category']; + $t_data[$t_project_id][$t_name] = true; + } + + # Find orphaned categories from bugs + while ( $row = db_fetch_array( $t_bug_result ) ) { + $t_project_id = $row['project_id']; + $t_name = $row['category']; + + $t_data[$t_project_id][$t_name] = true; + } + + # In every project, go through all the categories found, and create them and update the bug + foreach ( $t_data as $t_project_id => $t_categories ) { + foreach ( $t_categories as $t_name => $t_true ) { + $query = "INSERT INTO $t_category_table ( name, project_id ) VALUES ( " . db_param(0) . ', ' . db_param(1) . ' )'; + db_query_bound( $query, array( $t_name, $t_project_id ) ); + $t_category_id = db_insert_id( $t_category_table ); + + $query = "UPDATE $t_bug_table SET category_id=" . db_param(0) . ' + WHERE project_id=' . db_param(1) . ' AND category=' . db_param(2); + db_query_bound( $query, array( $t_category_id, $t_project_id, $t_name ) ); + } + } + + # return 2 because that's what ADOdb/DataDict does when things happen properly + return 2; + } + diff --git a/admin/schema.php b/admin/schema.php index 440504e..a186339 100644 --- a/admin/schema.php +++ b/admin/schema.php @@ -370,4 +370,22 @@ $upgrade[] = Array('CreateTableSQL', Array( config_get( 'mantis_plugin_table' ), ", Array( 'mysql' => 'TYPE=MyISAM', 'pgsql' => 'WITHOUT OIDS' ) ) ); $upgrade[] = Array('AlterColumnSQL', Array( config_get_global( 'mantis_user_pref_table' ), "redirect_delay I NOTNULL DEFAULT 0" ) ); + +$upgrade[] = Array( 'CreateTableSQL', Array( config_get( 'mantis_category_table' ), " + id I UNSIGNED NOTNULL PRIMARY AUTOINCREMENT, + project_id I UNSIGNED NOTNULL DEFAULT '0', + user_id I UNSIGNED NOTNULL DEFAULT '0', + name C(128) NOTNULL DEFAULT \" '' \", + status I UNSIGNED NOTNULL DEFAULT '0' + ", Array( 'mysql' => 'TYPE=MyISAM', 'pgsql' => 'WITHOUT OIDS' ) ) ); +$upgrade[] = Array( 'CreateIndexSQL', Array( 'idx_project_name', config_get( 'mantis_category_table' ), 'project_id, name', array( 'UNIQUE' ) ) ); +$upgrade[] = Array( 'InsertData', Array( config_get( 'mantis_category_table' ), " + ( project_id, user_id, name, status ) VALUES + ( '0', '0', 'None', '0' ) " ) ); +$upgrade[] = Array( 'AddColumnSQL', Array( config_get( 'mantis_bug_table' ), "category_id I UNSIGNED NOTNULL DEFAULT '0'" ) ); +$upgrade[] = Array( 'UpdateFunction', "category_migrate" ); +$upgrade[] = Array( 'DropColumnSQL', Array( config_get( 'mantis_bug_table' ), "category" ) ); +$upgrade[] = Array( 'DropTableSQL', Array( config_get( 'mantis_project_category_table' ) ) ); +$upgrade[] = Array( 'AddColumnSQL', Array( config_get( 'mantis_project_table' ), "category_id I UNSIGNED NOTNULL DEFAULT '0'" ) ); + ?> diff --git a/bug_report.php b/bug_report.php index 58588dc..81f7a0f 100644 --- a/bug_report.php +++ b/bug_report.php @@ -44,7 +44,7 @@ $t_bug_data->handler_id = gpc_get_int( 'handler_id', 0 ); $t_bug_data->view_state = gpc_get_int( 'view_state', config_get( 'default_bug_view_status' ) ); - $t_bug_data->category = gpc_get_string( 'category', config_get( 'default_bug_category' ) ); + $t_bug_data->category_id = gpc_get_int( 'category_id', 0 ); $t_bug_data->reproducibility = gpc_get_int( 'reproducibility', config_get( 'default_bug_reproducibility' ) ); $t_bug_data->severity = gpc_get_int( 'severity', config_get( 'default_bug_severity' ) ); $t_bug_data->priority = gpc_get_int( 'priority', config_get( 'default_bug_priority' ) ); @@ -171,7 +171,7 @@ ?> <p> <form method="post" action="<?php echo string_get_bug_report_url() ?>"> - <input type="hidden" name="category" value="<?php echo $t_bug_data->category ?>" /> + <input type="hidden" name="category_id" value="<?php echo $t_bug_data->category_id ?>" /> <input type="hidden" name="severity" value="<?php echo $t_bug_data->severity ?>" /> <input type="hidden" name="reproducibility" value="<?php echo $t_bug_data->reproducibility ?>" /> <input type="hidden" name="profile_id" value="<?php echo $t_bug_data->profile_id ?>" /> diff --git a/bug_report_advanced_page.php b/bug_report_advanced_page.php index ed694e3..f6d4c8a 100644 --- a/bug_report_advanced_page.php +++ b/bug_report_advanced_page.php @@ -82,7 +82,7 @@ $f_profile_id = 0; $f_handler_id = $t_bug->handler_id; - $f_category = $t_bug->category; + $f_category_id = $t_bug->category_id; $f_reproducibility = $t_bug->reproducibility; $f_severity = $t_bug->severity; $f_priority = $t_bug->priority; @@ -105,7 +105,7 @@ $f_profile_id = gpc_get_int( 'profile_id', 0 ); $f_handler_id = gpc_get_int( 'handler_id', 0 ); - $f_category = gpc_get_string( 'category', config_get( 'default_bug_category' ) ); + $f_category_id = gpc_get_int( 'category_id', 0 ); $f_reproducibility = gpc_get_int( 'reproducibility', config_get( 'default_bug_reproducibility' ) ); $f_severity = gpc_get_int( 'severity', config_get( 'default_bug_severity' ) ); $f_priority = gpc_get_int( 'priority', config_get( 'default_bug_priority' ) ); @@ -161,13 +161,13 @@ <?php if ( $t_changed_project ) { echo "[" . project_get_field( $t_bug->project_id, 'name' ) . "] "; } ?> - <select <?php echo helper_get_tab_index() ?> name="category"> + <select <?php echo helper_get_tab_index() ?> name="category_id"> <?php - if ( is_blank( $f_category ) ) { + if ( 0 === $f_category_id ) { echo '<option value="" selected="selected">', string_attribute( lang_get( 'select_option' ) ), '</option>'; } - print_category_option_list( $f_category ); + print_category_option_list( $f_category_id ); ?> </select> </td> @@ -555,7 +555,7 @@ <?php if ( ON == config_get( 'use_javascript' ) ) { ?> <script type="text/javascript" language="JavaScript"> <!-- - window.document.report_bug_form.category.focus(); + window.document.report_bug_form.category_id.focus(); --> </script> <?php } ?> diff --git a/bug_report_page.php b/bug_report_page.php index 4446331..7cc53aa 100644 --- a/bug_report_page.php +++ b/bug_report_page.php @@ -73,7 +73,7 @@ access_ensure_project_level( config_get( 'report_bug_threshold' ) ); $f_product_version = $t_bug->version; - $f_category = $t_bug->category; + $f_category_id = $t_bug->category_id; $f_reproducibility = $t_bug->reproducibility; $f_severity = $t_bug->severity; $f_priority = $t_bug->priority; @@ -87,7 +87,7 @@ access_ensure_project_level( config_get( 'report_bug_threshold' ) ); $f_product_version = gpc_get_string( 'product_version', '' ); - $f_category = gpc_get_string( 'category', config_get( 'default_bug_category' ) ); + $f_category_id = gpc_get_int( 'category_id', 0 ); $f_reproducibility = gpc_get_int( 'reproducibility', config_get( 'default_bug_reproducibility' ) ); $f_severity = gpc_get_int( 'severity', config_get( 'default_bug_severity' ) ); $f_priority = gpc_get_int( 'priority', config_get( 'default_bug_priority' ) ); @@ -143,13 +143,13 @@ <?php if ( $t_changed_project ) { echo "[" . project_get_field( $t_bug->project_id, 'name' ) . "] "; } ?> - <select <?php echo helper_get_tab_index() ?> name="category"> + <select <?php echo helper_get_tab_index() ?> name="category_id"> <?php - if ( is_blank( $f_category ) ) { + if ( 0 === $f_category_id ) { echo '<option value="" selected="selected">', string_attribute( lang_get( 'select_option' ) ), '</option>'; } - print_category_option_list( $f_category ); + print_category_option_list( $f_category_id ); ?> </select> </td> @@ -385,7 +385,7 @@ <?php if ( ON == config_get( 'use_javascript' ) ) { ?> <script type="text/javascript" language="JavaScript"> <!-- - window.document.report_bug_form.category.focus(); + window.document.report_bug_form.category_id.focus(); --> </script> <?php } ?> diff --git a/bug_update.php b/bug_update.php index dd0a2e6..5b16e80 100644 --- a/bug_update.php +++ b/bug_update.php @@ -67,7 +67,7 @@ $t_bug_data->status = gpc_get_int( 'status', $t_bug_data->status ); $t_bug_data->resolution = gpc_get_int( 'resolution', $t_bug_data->resolution ); $t_bug_data->projection = gpc_get_int( 'projection', $t_bug_data->projection ); - $t_bug_data->category = gpc_get_string( 'category', $t_bug_data->category ); + $t_bug_data->category_id = gpc_get_int( 'category_id', $t_bug_data->category_id ); $t_bug_data->eta = gpc_get_int( 'eta', $t_bug_data->eta ); $t_bug_data->os = gpc_get_string( 'os', $t_bug_data->os ); $t_bug_data->os_build = gpc_get_string( 'os_build', $t_bug_data->os_build ); diff --git a/bug_update_advanced_page.php b/bug_update_advanced_page.php index cf429d3..03ed16d 100644 --- a/bug_update_advanced_page.php +++ b/bug_update_advanced_page.php @@ -118,8 +118,8 @@ <?php if ( $t_changed_project ) { echo "[" . project_get_field( $t_bug->project_id, 'name' ) . "] "; } ?> - <select <?php echo helper_get_tab_index() ?> name="category"> - <?php print_category_option_list( $t_bug->category, $t_bug->project_id ) ?> + <select <?php echo helper_get_tab_index() ?> name="category_id"> + <?php print_category_option_list( $t_bug->category_id, $t_bug->project_id ) ?> </select> </td> diff --git a/bug_update_page.php b/bug_update_page.php index 1af51da..151b1bc 100644 --- a/bug_update_page.php +++ b/bug_update_page.php @@ -121,8 +121,8 @@ <?php if ( $t_changed_project ) { echo "[" . project_get_field( $t_bug->project_id, 'name' ) . "] "; } ?> - <select <?php echo helper_get_tab_index() ?> name="category"> - <?php print_category_option_list( $t_bug->category, $t_bug->project_id ) ?> + <select <?php echo helper_get_tab_index() ?> name="category_id"> + <?php print_category_option_list( $t_bug->category_id, $t_bug->project_id ) ?> </select> </td> diff --git a/bug_view_advanced_page.php b/bug_view_advanced_page.php index d16f69e..b0581e7 100644 --- a/bug_view_advanced_page.php +++ b/bug_view_advanced_page.php @@ -168,8 +168,7 @@ <!-- Category --> <td> <?php - $t_project_name = string_display( project_get_field( $t_bug->project_id, 'name' ) ); - echo "[$t_project_name] $t_bug->category"; + echo string_display( category_full_name( $t_bug->category_id ) ); ?> </td> diff --git a/bug_view_page.php b/bug_view_page.php index 5ff445a..ad82077 100644 --- a/bug_view_page.php +++ b/bug_view_page.php @@ -171,8 +171,7 @@ <!-- Category --> <td> <?php - $t_project_name = string_display( project_get_field( $t_bug->project_id, 'name' ) ); - echo "[$t_project_name] $t_bug->category"; + echo string_display( category_full_name( $t_bug->category_id ) ); ?> </td> diff --git a/config_defaults_inc.php b/config_defaults_inc.php index d1da3ab..069dd3e 100644 --- a/config_defaults_inc.php +++ b/config_defaults_inc.php @@ -684,9 +684,6 @@ # Default bug reproducibility when reporting a new bug $g_default_bug_reproducibility = REPRODUCIBILITY_HAVENOTTRIED; - # Default bug category when reporting a new bug - $g_default_bug_category = ''; - # --- viewing defaults ------------ # site defaults for viewing preferences $g_default_limit_view = 50; @@ -1370,9 +1367,10 @@ $g_mantis_bug_text_table = '%db_table_prefix%_bug_text%db_table_suffix%'; $g_mantis_bugnote_table = '%db_table_prefix%_bugnote%db_table_suffix%'; $g_mantis_bugnote_text_table = '%db_table_prefix%_bugnote_text%db_table_suffix%'; + $g_mantis_category_table = '%db_table_prefix%_category%db_table_suffix%'; $g_mantis_news_table = '%db_table_prefix%_news%db_table_suffix%'; $g_mantis_plugin_table = '%db_table_prefix%_plugin%db_table_suffix%'; - $g_mantis_project_category_table = '%db_table_prefix%_project_category%db_table_suffix%'; + $g_mantis_project_category_table = '%db_table_prefix%_project_category%db_table_suffix%'; # Legacy table $g_mantis_project_file_table = '%db_table_prefix%_project_file%db_table_suffix%'; $g_mantis_project_table = '%db_table_prefix%_project%db_table_suffix%'; $g_mantis_project_user_list_table = '%db_table_prefix%_project_user_list%db_table_suffix%'; diff --git a/core/bug_api.php b/core/bug_api.php index 082b1d2..5f1a004 100644 --- a/core/bug_api.php +++ b/core/bug_api.php @@ -52,7 +52,7 @@ var $status = NEW_; var $resolution = OPEN; var $projection = 10; - var $category = ''; + var $category_id = 0; var $date_submitted = ''; var $last_updated = ''; var $eta = 10; @@ -381,7 +381,7 @@ $c_priority = db_prepare_int( $p_bug_data->priority ); $c_severity = db_prepare_int( $p_bug_data->severity ); $c_reproducibility = db_prepare_int( $p_bug_data->reproducibility ); - $c_category = db_prepare_string( $p_bug_data->category ); + $c_category_id = db_prepare_int( $p_bug_data->category_id ); $c_os = db_prepare_string( $p_bug_data->os ); $c_os_build = db_prepare_string( $p_bug_data->os_build ); $c_platform = db_prepare_string( $p_bug_data->platform ); @@ -406,11 +406,6 @@ trigger_error( ERROR_EMPTY_FIELD, ERROR ); } - if ( is_blank( $c_category ) ) { - error_parameters( lang_get( 'category' ) ); - trigger_error( ERROR_EMPTY_FIELD, ERROR ); - } - # Only set target_version if user has access to do so if ( access_has_project_level( config_get( 'roadmap_update_threshold' ) ) ) { $c_target_version = db_prepare_string( $p_bug_data->target_version ); @@ -420,7 +415,7 @@ $t_bug_table = config_get_global( 'mantis_bug_table' ); $t_bug_text_table = config_get_global( 'mantis_bug_text_table' ); - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); + $t_category_table = config_get_global( 'mantis_category_table' ); # Insert text information $query = "INSERT INTO $t_bug_text_table @@ -443,9 +438,9 @@ # if a default user is associated with the category and we know at this point # that that the bug was not assigned to somebody, then assign it automatically. $query = "SELECT user_id - FROM $t_project_category_table - WHERE project_id=" .db_param(0) . " AND category=" . db_param(1); - $result = db_query_bound( $query, Array( $c_project_id, $c_category ) ); + FROM $t_category_table + WHERE project_id=" . db_param(0) . ' AND id=' . db_param(1); + $result = db_query_bound( $query, array( $c_project_id, $c_category_id ) ); if ( db_num_rows( $result ) > 0 ) { $c_handler_id = $p_handler_id = db_result( $result ); @@ -466,7 +461,7 @@ duplicate_id, priority, severity, reproducibility, status, resolution, - projection, category, + projection, category_id, date_submitted, last_updated, eta, bug_text_id, os, os_build, @@ -481,7 +476,7 @@ '0', '$c_priority', '$c_severity', '$c_reproducibility', '$t_status', '$t_resolution', - 10, '$c_category', + 10, '$c_category_id', " . db_now() . "," . db_now() . ", 10, '$t_text_id', '$c_os', '$c_os_build', @@ -782,8 +777,8 @@ $query = "SELECT id FROM $t_bug_table - WHERE project_id='$c_project_id'"; - $result = db_query( $query ); + WHERE project_id=" . db_param(0); + $result = db_query_bound( $query, array( $c_project_id ) ); $bug_count = db_num_rows( $result ); @@ -845,7 +840,7 @@ status='$c_bug_data->status', resolution='$c_bug_data->resolution', projection='$c_bug_data->projection', - category='$c_bug_data->category', + category_id='$c_bug_data->category_id', eta='$c_bug_data->eta', os='$c_bug_data->os', os_build='$c_bug_data->os_build', @@ -882,7 +877,7 @@ history_log_event_direct( $p_bug_id, 'status', $t_old_data->status, $p_bug_data->status ); history_log_event_direct( $p_bug_id, 'resolution', $t_old_data->resolution, $p_bug_data->resolution ); history_log_event_direct( $p_bug_id, 'projection', $t_old_data->projection, $p_bug_data->projection ); - history_log_event_direct( $p_bug_id, 'category', $t_old_data->category, $p_bug_data->category ); + history_log_event_direct( $p_bug_id, 'category_id', $t_old_data->category_id, $p_bug_data->category_id ); history_log_event_direct( $p_bug_id, 'eta', $t_old_data->eta, $p_bug_data->eta ); history_log_event_direct( $p_bug_id, 'os', $t_old_data->os, $p_bug_data->os ); history_log_event_direct( $p_bug_id, 'os_build', $t_old_data->os_build, $p_bug_data->os_build ); @@ -1457,7 +1452,7 @@ $t_bug_data->status = db_prepare_int( $p_bug_data->status ); $t_bug_data->resolution = db_prepare_int( $p_bug_data->resolution ); $t_bug_data->projection = db_prepare_int( $p_bug_data->projection ); - $t_bug_data->category = db_prepare_string( $p_bug_data->category ); + $t_bug_data->category_id = db_prepare_int( $p_bug_data->category_id ); $t_bug_data->date_submitted = db_prepare_string( $p_bug_data->date_submitted ); $t_bug_data->last_updated = db_prepare_string( $p_bug_data->last_updated ); $t_bug_data->eta = db_prepare_int( $p_bug_data->eta ); @@ -1484,7 +1479,7 @@ # Return a copy of the bug structure with all the instvars prepared for editing # in an HTML form function bug_prepare_edit( $p_bug_data ) { - $p_bug_data->category = string_attribute( $p_bug_data->category ); + $p_bug_data->category_id = string_attribute( $p_bug_data->category_id ); $p_bug_data->date_submitted = string_attribute( $p_bug_data->date_submitted ); $p_bug_data->last_updated = string_attribute( $p_bug_data->last_updated ); $p_bug_data->os = string_attribute( $p_bug_data->os ); @@ -1508,7 +1503,7 @@ # Return a copy of the bug structure with all the instvars prepared for editing # in an HTML form function bug_prepare_display( $p_bug_data ) { - $p_bug_data->category = string_display_line( $p_bug_data->category ); + $p_bug_data->category_id = string_display_line( $p_bug_data->category_id ); $p_bug_data->date_submitted = string_display_line( $p_bug_data->date_submitted ); $p_bug_data->last_updated = string_display_line( $p_bug_data->last_updated ); $p_bug_data->os = string_display_line( $p_bug_data->os ); diff --git a/core/category_api.php b/core/category_api.php index 97c5b8d..ec0c2c0 100644 --- a/core/category_api.php +++ b/core/category_api.php @@ -23,6 +23,9 @@ ### Category API ### + # Category data cache (to prevent excessive db queries) + $g_category_cache = array(); + #=================================== # Boolean queries and ensures #=================================== @@ -30,31 +33,32 @@ # -------------------- # Check whether the category exists in the project # Return true if the category exists, false otherwise - function category_exists( $p_project_id, $p_category ) { - $c_project_id = db_prepare_int( $p_project_id ); - $c_category = db_prepare_string( $p_category ); + function category_exists( $p_category_id ) { + global $g_category_cache; + if ( isset( $g_category_cache[$p_category_id] ) ) { + return true; + } - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); + $c_category_id = db_prepare_int( $p_category_id ); - $query = "SELECT COUNT(*) - FROM $t_project_category_table - WHERE project_id=" . db_param(0) . " AND - category=" . db_param(1); - $result = db_query_bound( $query, Array( $c_project_id, $c_category ) ); - $category_count = db_result( $result ); + $t_category_table = config_get( 'mantis_category_table' ); - if ( 0 < $category_count ) { - return true; + $query = "SELECT COUNT(*) FROM $t_category_table + WHERE id=" . db_param(0); + $count = db_result( db_query_bound( $query, array( $c_category_id ) ) ); + + if ( 0 < $count ) { + return true; } else { - return false; + return false; } } # -------------------- # Check whether the category exists in the project # Trigger an error if it does not - function category_ensure_exists( $p_project_id, $p_category ) { - if ( !category_exists( $p_project_id, $p_category ) ) { + function category_ensure_exists( $p_category_id ) { + if ( !category_exists( $p_category_id ) ) { trigger_error( ERROR_CATEGORY_NOT_FOUND, ERROR ); } } @@ -62,15 +66,28 @@ # -------------------- # Check whether the category is unique within a project # Returns true if the category is unique, false otherwise - function category_is_unique( $p_project_id, $p_category ) { - return !category_exists( $p_project_id, $p_category ); + function category_is_unique( $p_project_id, $p_name ) { + $c_project_id = db_prepare_int( $p_project_id ); + $c_name = db_prepare_string( $p_name ); + + $t_category_table = config_get( 'mantis_category_table' ); + + $query = "SELECT COUNT(*) FROM $t_category_table + WHERE project_id=" . db_param(0) . " AND " . db_helper_like( 'name', $c_name ); + $count = db_result( db_query_bound( $query, array( $c_project_id ) ) ); + + if ( 0 < $count ) { + return false; + } else { + return true; + } } # -------------------- # Check whether the category is unique within a project # Trigger an error if it is not - function category_ensure_unique( $p_project_id, $p_category ) { - if ( !category_is_unique( $p_project_id, $p_category ) ) { + function category_ensure_unique( $p_project_id, $p_name ) { + if ( !category_is_unique( $p_project_id, $p_name ) ) { trigger_error( ERROR_CATEGORY_DUPLICATE, ERROR ); } } @@ -82,51 +99,41 @@ # -------------------- # Add a new category to the project - function category_add( $p_project_id, $p_category ) { + function category_add( $p_project_id, $p_name ) { $c_project_id = db_prepare_int( $p_project_id ); - $c_category = db_prepare_string( $p_category ); + $c_name = db_prepare_string( $p_name ); - category_ensure_unique( $p_project_id, $p_category ); + category_ensure_unique( $p_project_id, $p_name ); - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); + $t_category_table = config_get( 'mantis_category_table' ); - $query = "INSERT INTO $t_project_category_table - ( project_id, category ) + $query = "INSERT INTO $t_category_table + ( project_id, name ) VALUES - ( " . db_param(0) . ',' . db_param(1) . ')'; - db_query_bound( $query, Array( $c_project_id, $c_category ) ); + ( " . db_param(0) . ', ' . db_param(1) . ' )'; + db_query_bound( $query, array( $c_project_id, $c_name ) ); # db_query errors on failure so: - return true; + return db_insert_id( $t_category_table ); } # -------------------- # Update the name and user associated with the category - function category_update( $p_project_id, $p_category, $p_new_category, $p_assigned_to ) { - $c_project_id = db_prepare_int( $p_project_id ); - $c_category = db_prepare_string( $p_category ); - $c_new_category = db_prepare_string( $p_new_category ); + function category_update( $p_category_id, $p_name, $p_assigned_to ) { + $c_category_id = db_prepare_int( $p_category_id ); + $c_name = db_prepare_string( $p_name ); $c_assigned_to = db_prepare_int( $p_assigned_to ); - category_ensure_exists( $p_project_id, $p_category ); + category_ensure_exists( $p_category_id ); - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); - $t_bug_table = config_get_global( 'mantis_bug_table' ); + $t_category_table = config_get( 'mantis_category_table' ); + $t_bug_table = config_get( 'mantis_bug_table' ); - $query = "UPDATE $t_project_category_table - SET category=" . db_param(0) . ", - user_id=" . db_param(1) . " - WHERE category=" . db_param(2) . " AND - project_id=" . db_param(3); - db_query_bound( $query, Array( $c_new_category, $c_assigned_to, $c_category, $c_project_id ) ); - - if ( $p_category != $p_new_category ) { - $query = "UPDATE $t_bug_table - SET category=" . db_param(0) . " - WHERE category=" . db_param(1) . " AND - project_id=" . db_param(2); - db_query_bound( $query, Array( $c_new_category, $c_category, $c_project_id ) ); - } + $query = "UPDATE $t_category_table + SET name=" . db_param(0) . ', + user_id=' . db_param(1) . ' + WHERE id=' . db_param(2); + db_query_bound( $query, array( $c_name, $c_assigned_to, $c_category_id ) ); # db_query errors on failure so: return true; @@ -134,29 +141,26 @@ # -------------------- # Remove a category from the project - function category_remove( $p_project_id, $p_category, $p_new_category='' ) { - $c_project_id = db_prepare_int( $p_project_id ); - $c_category = db_prepare_string( $p_category ); - $c_new_category = db_prepare_string( $p_new_category ); + function category_remove( $p_category_id, $p_new_category_id = 0 ) { + $c_category_id = db_prepare_int( $p_category_id ); + $c_new_category_id = db_prepare_int( $p_new_category_id ); - category_ensure_exists( $p_project_id, $p_category ); - if ( !is_blank( $p_new_category ) ) { - category_ensure_exists( $p_project_id, $p_new_category ); + category_ensure_exists( $p_category_id ); + if ( 0 != $p_new_category_id ) { + category_ensure_exists( $p_new_category_id ); } - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); - $t_bug_table = config_get_global( 'mantis_bug_table' ); + $t_category_table = config_get( 'mantis_category_table' ); + $t_bug_table = config_get( 'mantis_bug_table' ); - $query = "DELETE FROM $t_project_category_table - WHERE project_id=" . db_param(0) . " AND - category=" . db_param(1); - db_query_bound( $query, Array( $c_project_id, $c_category ) ); + $query = "DELETE FROM $t_category_table + WHERE id=" . db_param(0); + db_query_bound( $query, array( $c_category_id ) ); $query = "UPDATE $t_bug_table - SET category=" . db_param(0) . " - WHERE category=" . db_param(1) . " AND - project_id=" . db_param(2); - db_query_bound( $query, Array( $c_new_category, $c_category, $c_project_id ) ); + SET category_id=" . db_param(0) . " + WHERE category_id=" . db_param(1); + db_query_bound( $query, array( $c_new_category_id, $c_category_id ) ); # db_query errors on failure so: return true; @@ -164,22 +168,26 @@ # -------------------- # Remove all categories associated with a project - function category_remove_all( $p_project_id ) { + function category_remove_all( $p_project_id, $p_new_category_id = 0 ) { $c_project_id = db_prepare_int( $p_project_id ); + $c_new_category_id = db_prepare_int( $p_new_category_id ); project_ensure_exists( $p_project_id ); + if ( 0 != $p_new_category_id ) { + category_ensure_exists( $p_new_category_id ); + } - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); - $t_bug_table = config_get_global( 'mantis_bug_table' ); + $t_category_table = config_get( 'mantis_category_table' ); + $t_bug_table = config_get( 'mantis_bug_table' ); - $query = "DELETE FROM $t_project_category_table + $query = "DELETE FROM $t_category_table WHERE project_id=" . db_param(0); - db_query_bound( $query, Array( $c_project_id ) ); + db_query_bound( $query, array( $c_project_id ) ); $query = "UPDATE $t_bug_table - SET category='' - WHERE project_id=" . db_param(0); - db_query_bound( $query, Array( $c_project_id ) ); + SET category=" . db_param(0) . ' + WHERE project_id=' . db_param(1); + db_query_bound( $query, array( $c_new_category_id, $c_project_id ) ); # db_query errors on failure so: return true; @@ -192,45 +200,74 @@ # -------------------- # Return the definition row for the category - function category_get_row( $p_project_id, $p_category ) { - $c_project_id = db_prepare_int( $p_project_id ); - $c_category = db_prepare_string( $p_category ); + function category_get_row( $p_category_id ) { + global $g_category_cache; + if ( isset( $g_category_cache[$p_category_id] ) ) { + return $g_category_cache[$p_category_id]; + } + + $c_category_id = db_prepare_int( $p_category_id ); - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); + $t_category_table = config_get( 'mantis_category_table' ); + $t_project_table = config_get( 'mantis_project_table' ); - $query = "SELECT category, user_id - FROM $t_project_category_table - WHERE project_id=" . db_param(0) . " AND - category=" . db_param(1); - $result = db_query_bound( $query, Array( $c_project_id, $c_category ) ); + $query = "SELECT c.*, p.name AS project_name FROM $t_category_table AS c + JOIN $t_project_table AS p + ON c.project_id=p.id + WHERE c.id=" . db_param(0); + $result = db_query_bound( $query, array( $c_category_id ) ); $count = db_num_rows( $result ); if ( 0 == $count ) { trigger_error( ERROR_CATEGORY_NOT_FOUND, ERROR ); } - return db_fetch_array( $result ); + $row = db_fetch_array( $result ); + $g_category_cache[$p_category_id] = $row; + return $row; } # -------------------- # Return all categories for the specified project id function category_get_all_rows( $p_project_id ) { + global $g_category_cache; + $c_project_id = db_prepare_int( $p_project_id ); - $t_project_category_table = config_get_global( 'mantis_project_category_table' ); + $t_category_table = config_get( 'mantis_category_table' ); + $t_project_table = config_get( 'mantis_project_table' ); + + $t_project_where = helper_project_specific_where( $c_project_id ); - $query = "SELECT category, user_id - FROM $t_project_category_table - WHERE project_id=" . db_param(0) . " - ORDER BY category"; - $result = db_query_bound( $query, Array( $c_project_id ) ); + $query = "SELECT c.*, p.name AS project_name FROM $t_category_table AS c + JOIN $t_project_table AS p + ON c.project_id=p.id + WHERE $t_project_where + ORDER BY c.name "; + $result = db_query_bound( $query ); $count = db_num_rows( $result ); $rows = array(); for ( $i = 0 ; $i < $count ; $i++ ) { $row = db_fetch_array( $result ); $rows[] = $row; + $g_category_cache[$row['id']] = $row; } return $rows; } -?> + + # Helpers + + function category_full_name( $p_category_id, $p_show_project=true ) { + if ( $p_category_id == 0 ) { + return lang_get( 'no_category' ); + } + + $t_row = category_get_row( $p_category_id ); + + if ( $p_show_project ) { + return '[' . $t_row['project_name'] . '] ' . $t_row['name']; + } else { + return $t_row['name']; + } + } diff --git a/core/columns_api.php b/core/columns_api.php index 65bc271..8f08254 100644 --- a/core/columns_api.php +++ b/core/columns_api.php @@ -534,7 +534,7 @@ echo ']</small><br />'; } - echo string_display( $p_row['category'] ); + echo string_display( category_full_name( $p_row['category_id'], false ) ); echo '</td>'; } diff --git a/core/filter_api.php b/core/filter_api.php index a7b3cd6..a60033d 100644 --- a/core/filter_api.php +++ b/core/filter_api.php @@ -413,6 +413,7 @@ $t_bug_table = config_get_global( 'mantis_bug_table' ); $t_bug_text_table = config_get_global( 'mantis_bug_text_table' ); $t_bugnote_table = config_get_global( 'mantis_bugnote_table' ); + $t_category_table = config_get_global( 'mantis_category_table' ); $t_custom_field_string_table = config_get_global( 'mantis_custom_field_string_table' ); $t_bugnote_text_table = config_get_global( 'mantis_bugnote_text_table' ); $t_project_table = config_get_global( 'mantis_project_table' ); @@ -696,9 +697,7 @@ $t_clauses = array(); foreach( $t_filter['show_category'] as $t_filter_member ) { - $t_filter_member = stripslashes( $t_filter_member ); if ( META_FILTER_NONE == $t_filter_member ) { - array_push( $t_clauses, "''" ); } else { $c_show_category = db_prepare_string( $t_filter_member ); array_push( $t_clauses, "'$c_show_category'" ); @@ -706,9 +705,9 @@ } if ( 1 < count( $t_clauses ) ) { - array_push( $t_where_clauses, "( $t_bug_table.category in (". implode( ', ', $t_clauses ) .") )" ); + array_push( $t_where_clauses, "( $t_bug_table.category_id in ( SELECT id FROM $t_category_table WHERE name in (". implode( ', ', $t_clauses ) .") ) )" ); } else { - array_push( $t_where_clauses, "( $t_bug_table.category=$t_clauses[0] )" ); + array_push( $t_where_clauses, "( $t_bug_table.category_id in ( SELECT id FROM $t_category_table WHERE name=$t_clauses[0] ) )" ); } } @@ -1765,13 +1764,11 @@ } else { $t_first_flag = true; foreach( $t_filter['show_category'] as $t_current ) { - $t_current = stripslashes( $t_current ); ?> - <input type="hidden" name="show_category[]" value="<?php echo string_display( $t_current );?>" /> + <input type="hidden" name="show_category[]" value="<?php echo $t_current;?>" /> <?php $t_this_string = ''; - if ( ( ( $t_current == META_FILTER_ANY ) && ( is_numeric( $t_current ) ) ) - || ( is_blank( $t_current ) ) ) { + if ( is_blank( $t_current ) || $t_current === "0" || $t_current === META_FILTER_ANY ) { $t_any_found = true; } else { $t_this_string = string_display( $t_current ); @@ -3334,8 +3331,7 @@ <!-- Category --> <select <?php PRINT $t_select_modifier;?> name="show_category[]"> <option value="<?php echo META_FILTER_ANY ?>" <?php check_selected( $t_filter['show_category'], META_FILTER_ANY ); ?>>[<?php echo lang_get( 'any' ) ?>]</option> - <?php # This shows orphaned categories as well as selectable categories ?> - <?php print_category_complete_option_list( $t_filter['show_category'] ) ?> + <?php print_category_filter_option_list( $t_filter['show_category'] ) ?> </select> <?php } diff --git a/core/graph_api.php b/core/graph_api.php index 2393a11..df60a9a 100644 --- a/core/graph_api.php +++ b/core/graph_api.php @@ -591,30 +591,28 @@ global $category_name, $category_bug_count; $t_project_id = helper_get_current_project(); - $t_cat_table = config_get_global( 'mantis_project_category_table' ); - $t_bug_table = config_get_global( 'mantis_bug_table' ); + $t_cat_table = config_get( 'mantis_category_table' ); + $t_bug_table = config_get( 'mantis_bug_table' ); $t_user_id = auth_get_current_user_id(); $specific_where = helper_project_specific_where( $t_project_id, $t_user_id ); - $query = "SELECT DISTINCT category + $query = "SELECT id, name FROM $t_cat_table WHERE $specific_where - ORDER BY category"; + ORDER BY name"; $result = db_query( $query ); $category_count = db_num_rows( $result ); - if ( 0 == $category_count ) { - return array(); - } + $t_metrics = array(); for ($i=0;$i<$category_count;$i++) { $row = db_fetch_array( $result ); - $t_cat_name = $row['category']; - $c_category_name = addslashes($t_cat_name); + $t_cat_name = $row['name']; + $t_cat_id = $row['id']; $query = "SELECT COUNT(*) FROM $t_bug_table - WHERE category='$c_category_name' AND $specific_where"; + WHERE category_id='$t_cat_id' AND $specific_where"; $result2 = db_query( $query ); - $t_metrics[$t_cat_name] = db_result( $result2, 0, 0 ); + $t_metrics[$t_cat_name] = $t_metrics[$t_cat_name] + db_result( $result2, 0, 0 ); } # end for return $t_metrics; } diff --git a/core/history_api.php b/core/history_api.php index 2a6b003..0f51a76 100644 --- a/core/history_api.php +++ b/core/history_api.php @@ -216,6 +216,11 @@ case 'category': $t_field_localized = lang_get( 'category' ); break; + case 'category_id': + $t_field_localized = lang_get( 'category' ); + $p_old_value = category_full_name( $p_old_value, false ); + $p_new_value = category_full_name( $p_new_value, false ); + break; case 'status': $p_old_value = get_enum_element( 'status', $p_old_value ); $p_new_value = get_enum_element( 'status', $p_new_value ); diff --git a/core/my_view_inc.php b/core/my_view_inc.php index dbc86b3..e46e7ab 100644 --- a/core/my_view_inc.php +++ b/core/my_view_inc.php @@ -279,11 +279,10 @@ # type project name if viewing 'all projects' or bug is in subproject if ( ON == config_get( 'show_bug_project_links' ) && helper_get_current_project() != $v_project_id ) { - echo '['; - print( $project_name ); - echo '] '; + echo string_display( category_full_name( $v_category_id ) ); + } else { + echo string_display( category_full_name( $v_category_id, false ) ); } - echo string_display( $v_category ); if ( $v_last_updated > strtotime( '-'.$t_filter['highlight_changed'].' hours' ) ) { echo ' - <b>' . $t_last_updated . '</b>'; diff --git a/core/obsolete.php b/core/obsolete.php index 30725c2..899ec87 100644 --- a/core/obsolete.php +++ b/core/obsolete.php @@ -120,4 +120,6 @@ # changes in 1.1.0rc2 config_obsolete( 'wait_time', 'default_redirect_delay' ); + config_obsolete( 'default_bug_category' ); + ?> diff --git a/core/print_api.php b/core/print_api.php index 65c4795..34ecb7c 100644 --- a/core/print_api.php +++ b/core/print_api.php @@ -424,7 +424,7 @@ # -------------------- # print a news item given a row in the news table. - function print_news_entry_from_row( $p_news_row ) { + function print_news_entry_from_row( $p_news_row ) { extract( $p_news_row, EXTR_PREFIX_ALL, 'v' ); print_news_entry( $v_headline, $v_body, $v_poster_id, $v_view_state, $v_announcement, $v_date_posted ); } @@ -673,12 +673,14 @@ PRINT ">$v_name</option>"; } # end for } + # -------------------- # Since categories can be orphaned we need to grab all unique instances of category # We check in the project category table and in the bug table # We put them all in one array and make sure the entries are unique - function print_category_option_list( $p_category='', $p_project_id = null ) { - $t_mantis_project_category_table = config_get_global( 'mantis_project_category_table' ); + function print_category_option_list( $p_category_id = 0, $p_project_id = null ) { + $t_category_table = config_get( 'mantis_category_table' ); + $t_project_table = config_get( 'mantis_project_table' ); if ( null === $p_project_id ) { $c_project_id = helper_get_current_project(); @@ -690,81 +692,61 @@ # grab all categories in the project category table $cat_arr = array(); - $query = "SELECT DISTINCT category - FROM $t_mantis_project_category_table + $query = "SELECT id,name FROM $t_category_table WHERE $t_project_where - ORDER BY category"; + ORDER BY name"; $result = db_query( $query ); - $category_count = db_num_rows( $result ); - for ($i=0;$i<$category_count;$i++) { - $row = db_fetch_array( $result ); - $cat_arr[] = string_attribute( $row['category'] ); - } - # Add the default option if not in the list retrieved from DB - # This is useful for default categories and when updating an - # issue with a deleted category. - if ( !is_blank( $p_category ) && !in_array( $p_category, $cat_arr ) ) { - $cat_arr[] = $p_category; + while ( $row = db_fetch_array( $result ) ) { + $cat_arr[$row['id']] = $row['name']; } + asort($cat_arr); - sort( $cat_arr ); - $cat_arr = array_unique( $cat_arr ); - - foreach( $cat_arr as $t_category ) { - PRINT "<option value=\"$t_category\""; - check_selected( $t_category, $p_category ); - PRINT ">$t_category</option>"; + foreach( $cat_arr as $t_category_id => $t_name ) { + PRINT "<option value=\"$t_category_id\""; + check_selected( $p_category_id, $t_category_id ); + PRINT ">$t_name</option>"; } } # -------------------- # Since categories can be orphaned we need to grab all unique instances of category # We check in the project category table and in the bug table # We put them all in one array and make sure the entries are unique - function print_category_complete_option_list( $p_category='', $p_project_id = null ) { - $t_mantis_project_category_table = config_get_global( 'mantis_project_category_table' ); - $t_mantis_bug_table = config_get_global( 'mantis_bug_table' ); + function print_category_complete_option_list( $p_category_id = 0, $p_project_id = null ) { + return print_category_option_list( $p_category_id, $p_project_id ); + } + + # --------- + # Now that categories are identified by numerical ID, we need an old-style name + # based option list to keep existing filter functionality. + function print_category_filter_option_list( $p_category_name = '', $p_project_id = null ) { + $t_category_table = config_get( 'mantis_category_table' ); + $t_project_table = config_get( 'mantis_project_table' ); if ( null === $p_project_id ) { - $t_project_id = helper_get_current_project(); + $c_project_id = helper_get_current_project(); } else { - $t_project_id = $p_project_id; + $c_project_id = db_prepare_int( $p_project_id ); } - $t_project_where = helper_project_specific_where( $t_project_id ); + $t_project_where = helper_project_specific_where( $c_project_id ); # grab all categories in the project category table $cat_arr = array(); - $query = "SELECT DISTINCT category - FROM $t_mantis_project_category_table + $query = "SELECT DISTINCT name FROM $t_category_table WHERE $t_project_where - ORDER BY category"; + ORDER BY name"; $result = db_query( $query ); - $category_count = db_num_rows( $result ); - for ($i=0;$i<$category_count;$i++) { - $row = db_fetch_array( $result ); - $cat_arr[] = string_attribute( $row['category'] ); - } - # grab all categories in the bug table - $query = "SELECT DISTINCT category - FROM $t_mantis_bug_table - WHERE $t_project_where - ORDER BY category"; - $result = db_query( $query ); - $category_count = db_num_rows( $result ); - - for ($i=0;$i<$category_count;$i++) { - $row = db_fetch_array( $result ); - $cat_arr[] = string_attribute( $row['category'] ); + while ( $row = db_fetch_array( $result ) ) { + $cat_arr[] = $row['name']; } - sort( $cat_arr ); - $cat_arr = array_unique( $cat_arr ); + sort($cat_arr); - foreach( $cat_arr as $t_category ) { - PRINT "<option value=\"$t_category\""; - check_selected( $p_category, $t_category ); - PRINT ">$t_category</option>"; + foreach( $cat_arr as $t_name ) { + PRINT "<option value=\"$t_name\""; + check_selected( $p_category_name, $t_name ); + PRINT ">$t_name</option>"; } } @@ -1257,26 +1239,26 @@ } # -------------------- function print_project_category_string( $p_project_id ) { - $t_mantis_project_category_table = config_get_global( 'mantis_project_category_table' ); + $t_mantis_category_table = config_get( 'mantis_category_table' ); $c_project_id = db_prepare_int( $p_project_id ); - $query = "SELECT category - FROM $t_mantis_project_category_table - WHERE project_id=" . db_param(0) . " - ORDER BY category"; - $result = db_query_bound( $query, Array( $c_project_id ) ); + $query = "SELECT name + FROM $t_mantis_category_table + WHERE project_id='$c_project_id' + ORDER BY name"; + $result = db_query( $query ); $category_count = db_num_rows( $result ); $t_string = ''; for ($i=0;$i<$category_count;$i++) { $row = db_fetch_array( $result ); - $t_category = $row['category']; + $t_name = $row['name']; if ( $i+1 < $category_count ) { - $t_string .= $t_category.', '; + $t_string .= $t_name.', '; } else { - $t_string .= $t_category; + $t_string .= $t_name; } } @@ -1500,7 +1482,7 @@ } print_page_link( $p_page, $t_last, $p_end, $p_current, $p_temp_filter_id ); - print( " ]" ); + print( " ]" ); } # -------------------- # print a mailto: href link diff --git a/core/summary_api.php b/core/summary_api.php index 6241eec..2964af1 100644 --- a/core/summary_api.php +++ b/core/summary_api.php @@ -547,6 +547,7 @@ # print a bug count per category function summary_print_by_category() { $t_mantis_bug_table = config_get_global( 'mantis_bug_table' ); + $t_mantis_category_table = config_get( 'mantis_category_table' ); $t_mantis_project_table = config_get_global( 'mantis_project_table' ); $t_summary_category_include_project = config_get( 'summary_category_include_project' ); @@ -559,15 +560,17 @@ } $t_project_query = ( ON == $t_summary_category_include_project ) ? 'project_id, ' : ''; - $query = "SELECT COUNT(id) as bugcount, $t_project_query category, status + $query = "SELECT COUNT(id) as bugcount, $t_project_query c.name AS category_name, c.id AS category_id, status FROM $t_mantis_bug_table - WHERE category>'' AND $specific_where - GROUP BY $t_project_query category, status - ORDER BY $t_project_query category, status"; + JOIN $t_mantis_category_table AS c ON category_id=c.id + WHERE $specific_where + GROUP BY $t_project_query category_id, category_name, status + ORDER BY $t_project_query category_id, category_name, status"; $result = db_query( $query ); - $last_category = -1; + $last_category_name = -1; + $last_category_id = -1; $last_project = -1; $t_bugs_open = 0; $t_bugs_resolved = 0; @@ -580,13 +583,13 @@ while ( $row = db_fetch_array( $result ) ) { extract( $row, EXTR_PREFIX_ALL, 'v' ); - if ( ( $v_category != $last_category ) && ( $last_category != -1 ) ) { - $label = $last_category; + if ( ( $v_category_id != $last_category_id ) && ( $last_category_id != -1 ) ) { + $label = $last_category_name; if ( ( ON == $t_summary_category_include_project ) && ( ALL_PROJECTS == $t_project_id ) ) { $label = sprintf( '[%s] %s', project_get_name( $last_project ), $label ); } - $t_bug_link = '<a class="subtle" href="' . config_get( 'bug_count_hyperlink_prefix' ) . '&show_category=' . urlencode( $last_category ); + $t_bug_link = '<a class="subtle" href="' . config_get( 'bug_count_hyperlink_prefix' ) . '&show_category=' . urlencode( $last_category_id ); if ( 0 < $t_bugs_open ) { $t_bugs_open = $t_bug_link . '&hide_status=' . RESOLVED . '">' . $t_bugs_open . '</a>'; } @@ -617,19 +620,20 @@ $t_bugs_open += $row['bugcount']; } - $last_category = $v_category; + $last_category_id = $v_category_id; + $last_category_name = $v_category_name; if ( ( ON == $t_summary_category_include_project ) && ( ALL_PROJECTS == $t_project_id ) ) { $last_project = $v_project_id; } } if ( 0 < $t_bugs_total ) { - $label = $last_category; + $label = $last_category_name; if ( ( ON == $t_summary_category_include_project ) && ( ALL_PROJECTS == $t_project_id ) ) { $label = sprintf( '[%s] %s', project_get_name( $last_project ), $label ); } - $t_bug_link = '<a class="subtle" href="' . config_get( 'bug_count_hyperlink_prefix' ) . '&show_category=' . urlencode( $last_category ); + $t_bug_link = '<a class="subtle" href="' . config_get( 'bug_count_hyperlink_prefix' ) . '&show_category=' . urlencode( $last_category_id ); if ( !is_blank( $t_bug_link ) ) { if ( 0 < $t_bugs_open ) { $t_bugs_open = $t_bug_link . '&hide_status=' . RESOLVED . '">' . $t_bugs_open . '</a>'; diff --git a/graphs/graph_by_category.php b/graphs/graph_by_category.php index a969d25..8e5f098 100644 --- a/graphs/graph_by_category.php +++ b/graphs/graph_by_category.php @@ -36,12 +36,13 @@ $data_category_arr = array(); $data_count_arr = array(); - $query = "SELECT category, COUNT(category) as count + $query = "SELECT c.name AS name, COUNT(name) as count FROM mantis_bug_table - WHERE project_id=" . db_param(0) . " - GROUP BY category - ORDER BY category"; - $result = db_query_bound( $query, Array( $t_project_id ) ); + JOIN mantis_category_table AS c + WHERE project_id='$t_project_id' + GROUP BY name + ORDER BY name"; + $result = db_query( $query ); $category_count = db_num_rows( $result ); $total = 0; $longest_size = 0; @@ -50,11 +51,11 @@ extract( $row ); $total += $count; - $data_category_arr[] = $category; + $data_category_arr[] = $name; $data_count_arr[] = $count; - if ( strlen( $category ) > $longest_size ) { - $longest_size = strlen( $category ); + if ( strlen( $name ) > $longest_size ) { + $longest_size = strlen( $name ); } } $longest_size++; diff --git a/lang/strings_english.txt b/lang/strings_english.txt index 4d1527d..afc07b0 100644 --- a/lang/strings_english.txt +++ b/lang/strings_english.txt @@ -592,6 +592,7 @@ $s_update_simple_link = 'Update Simple'; $s_updating_bug_advanced_title = 'Updating Issue Information'; $s_id = 'ID'; $s_category = 'Category'; +$s_no_category = 'N/A'; $s_severity = 'Severity'; $s_reproducibility = 'Reproducibility'; $s_date_submitted = 'Date Submitted'; diff --git a/manage_proj_cat_add.php b/manage_proj_cat_add.php index 27717f9..9675b08 100644 --- a/manage_proj_cat_add.php +++ b/manage_proj_cat_add.php @@ -30,25 +30,25 @@ auth_reauthenticate(); $f_project_id = gpc_get_int( 'project_id' ); - $f_category = gpc_get_string( 'category' ); + $f_name = gpc_get_string( 'name' ); access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id ); - if ( is_blank( $f_category ) ) { + if ( is_blank( $f_name ) ) { trigger_error( ERROR_EMPTY_FIELD, ERROR ); } - $t_categories = explode( '|', $f_category ); - $t_category_count = count( $t_categories ); + $t_names = explode( '|', $f_name ); + $t_category_count = count( $t_names ); - foreach ( $t_categories as $t_category ) { - if ( is_blank( $t_category ) ) { + foreach ( $t_names as $t_name ) { + if ( is_blank( $t_name ) ) { continue; } - $t_category = trim( $t_category ); - if ( category_is_unique( $f_project_id, $t_category ) ) { - category_add( $f_project_id, $t_category ); + $t_name = trim( $t_name ); + if ( category_is_unique( $f_project_id, $t_name ) ) { + category_add( $f_project_id, $t_name ); } else if ( 1 == $t_category_count ) { # We only error out on duplicates when a single value was # given. If multiple values were given, we just add the diff --git a/manage_proj_cat_copy.php b/manage_proj_cat_copy.php index d7b7c12..f205c71 100644 --- a/manage_proj_cat_copy.php +++ b/manage_proj_cat_copy.php @@ -50,10 +50,10 @@ $rows = category_get_all_rows( $t_src_project_id ); foreach ( $rows as $row ) { - $t_category = $row['category']; + $t_name = $row['name']; - if ( category_is_unique( $t_dst_project_id, $t_category ) ) { - category_add( $t_dst_project_id, $t_category ); + if ( category_is_unique( $t_dst_project_id, $t_name ) ) { + category_add( $t_dst_project_id, $t_name ); } } diff --git a/manage_proj_cat_delete.php b/manage_proj_cat_delete.php index 6dc7966..934e7bf 100644 --- a/manage_proj_cat_delete.php +++ b/manage_proj_cat_delete.php @@ -29,19 +29,22 @@ auth_reauthenticate(); - $f_project_id = gpc_get_int( 'project_id' ); - $f_category = gpc_get_string( 'category' ); + $f_category_id = gpc_get_string( 'id' ); access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id ); + $t_row = category_get_row( $f_category_id ); + $t_name = category_full_name( $f_category_id ); + $t_project_id = $t_row['project_id']; + # Confirm with the user helper_ensure_confirmed( lang_get( 'category_delete_sure_msg' ) . - '<br/>' . lang_get( 'category' ) . ': ' . $f_category, + '<br/>' . lang_get( 'category' ) . ': ' . $t_name, lang_get( 'delete_category_button' ) ); - category_remove( $f_project_id, $f_category ); + category_remove( $f_category_id ); - $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $f_project_id; + $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $t_project_id; html_page_top1(); html_meta_redirect( $t_redirect_url ); diff --git a/manage_proj_cat_edit_page.php b/manage_proj_cat_edit_page.php index ca00e1b..781d938 100644 --- a/manage_proj_cat_edit_page.php +++ b/manage_proj_cat_edit_page.php @@ -29,13 +29,14 @@ auth_reauthenticate(); - $f_project_id = gpc_get_int( 'project_id' ); - $f_category = gpc_get_string( 'category' ); + $f_category_id = gpc_get_string( 'id' ); access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id ); - $t_row = category_get_row( $f_project_id, $f_category ); + $t_row = category_get_row( $f_category_id ); $t_assigned_to = $t_row['user_id']; + $t_project_id = $t_row['project_id']; + $t_name = $t_row['name']; html_page_top1(); html_page_top2(); @@ -54,12 +55,11 @@ </tr> <tr <?php echo helper_alternate_class() ?>> <td class="category"> - <input type="hidden" name="project_id" value="<?php echo string_attribute( $f_project_id ) ?>" /> - <input type="hidden" name="category" value="<?php echo string_attribute( $f_category ) ?>" /> + <input type="hidden" name="category_id" value="<?php echo string_attribute( $f_category_id ) ?>" /> <?php echo lang_get( 'category' ) ?> </td> <td> - <input type="text" name="new_category" size="32" maxlength="64" value="<?php echo string_attribute( $f_category ) ?>" /> + <input type="text" name="name" size="32" maxlength="128" value="<?php echo string_attribute( $t_name ) ?>" /> </td> </tr> <tr <?php echo helper_alternate_class() ?>> @@ -69,7 +69,7 @@ <td> <select name="assigned_to"> <option value="0"></option> - <?php print_assign_to_option_list( $t_assigned_to, $f_project_id ) ?> + <?php print_assign_to_option_list( $t_assigned_to, $t_project_id ) ?> </select> </td> </tr> @@ -89,8 +89,7 @@ <div class="border-center"> <form method="post" action="manage_proj_cat_delete.php"> - <input type="hidden" name="project_id" value="<?php echo string_attribute( $f_project_id ) ?>" /> - <input type="hidden" name="category" value="<?php echo string_attribute( $f_category ) ?>" /> + <input type="hidden" name="category_id" value="<?php echo string_attribute( $f_category_id ) ?>" /> <input type="submit" class="button" value="<?php echo lang_get( 'delete_category_button' ) ?>" /> </form> </div> diff --git a/manage_proj_cat_update.php b/manage_proj_cat_update.php index 05afd1e..98610e8 100644 --- a/manage_proj_cat_update.php +++ b/manage_proj_cat_update.php @@ -29,29 +29,28 @@ auth_reauthenticate(); - $f_project_id = gpc_get_int( 'project_id' ); - $f_category = gpc_get_string( 'category' ); - $f_new_category = gpc_get_string( 'new_category' ); + $f_category_id = gpc_get_int( 'category_id' ); + $f_name = trim( gpc_get_string( 'name' ) ); $f_assigned_to = gpc_get_int( 'assigned_to', 0 ); access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id ); - if ( is_blank( $f_new_category ) ) { + if ( is_blank( $f_name ) ) { trigger_error( ERROR_EMPTY_FIELD, ERROR ); } - $f_category = trim( $f_category ); - $f_new_category = trim( $f_new_category ); + $t_row = category_get_row( $f_category_id ); + $t_old_name = $t_row['name']; + $t_project_id = $t_row['project_id']; # check for duplicate - if ( strtolower( $f_category ) == strtolower( $f_new_category ) || - category_is_unique( $f_project_id, $f_new_category ) ) { - category_update( $f_project_id, $f_category, $f_new_category, $f_assigned_to ); - } else { - trigger_error( ERROR_CATEGORY_DUPLICATE, ERROR ); + if ( strtolower( $f_name ) != strtolower( $t_old_name ) ) { + category_ensure_unique( $t_project_id, $f_name ); } + + category_update( $f_category_id, $f_name, $f_assigned_to ); - $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $f_project_id; + $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $t_project_id; html_page_top1(); diff --git a/manage_proj_edit_page.php b/manage_proj_edit_page.php index 41c4304..a2270e6 100644 --- a/manage_proj_edit_page.php +++ b/manage_proj_edit_page.php @@ -302,7 +302,8 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?> } foreach ( $t_categories as $t_category ) { - $t_name = $t_category['category']; + $t_id = $t_category['id']; + $t_name = $t_category['name']; if ( NO_USER != $t_category['user_id'] && user_exists( $t_category['user_id'] )) { $t_user_name = user_get_name( $t_category['user_id'] ); @@ -320,11 +321,11 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?> </td> <td class="center"> <?php - $t_name = urlencode( $t_name ); + $t_id = urlencode( $t_id ); - print_button( 'manage_proj_cat_edit_page.php?project_id=' . $f_project_id . '&category=' . $t_name, lang_get( 'edit_link' ) ); + print_button( 'manage_proj_cat_edit_page.php?id=' . $t_id, lang_get( 'edit_link' ) ); echo ' '; - print_button( 'manage_proj_cat_delete.php?project_id=' . $f_project_id . '&category=' . $t_name, lang_get( 'delete_link' ) ); + print_button( 'manage_proj_cat_delete.php?id=' . $t_id, lang_get( 'delete_link' ) ); ?> </td> </tr> @@ -337,7 +338,7 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?> <td class="left" colspan="3"> <form method="post" action="manage_proj_cat_add.php"> <input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" /> - <input type="text" name="category" size="32" maxlength="64" /> + <input type="text" name="name" size="32" maxlength="128" /> <input type="submit" class="button" value="<?php echo lang_get( 'add_category_button' ) ?>" /> </form> </td> diff --git a/my_view_page.php b/my_view_page.php index febd47b..d286294 100644 --- a/my_view_page.php +++ b/my_view_page.php @@ -34,6 +34,9 @@ $t_current_user_id = auth_get_current_user_id(); + # Improve performance by caching category data in one pass + category_get_all_rows( helper_get_current_project() ); + compress_enable(); html_page_top1( lang_get( 'my_view_link' ) ); diff --git a/view_all_inc.php b/view_all_inc.php index 16e4992..8131b17 100644 --- a/view_all_inc.php +++ b/view_all_inc.php @@ -43,6 +43,9 @@ $t_icon_path = config_get( 'icon_path' ); $t_update_bug_threshold = config_get( 'update_bug_threshold' ); + # Improve performance by caching category data in one pass + category_get_all_rows( helper_get_current_project() ); + $t_columns = helper_get_columns_to_view( COLUMNS_TARGET_VIEW_PAGE ); $col_count = sizeof( $t_columns ); mantis-categories.2008-02-04.patch (30,956 bytes)
diff --git a/admin/schema.php b/admin/schema.php index 6aefc72..c8423ba 100644 --- a/admin/schema.php +++ b/admin/schema.php @@ -382,7 +382,7 @@ $upgrade[] = Array( 'CreateTableSQL', Array( db_get_table( 'mantis_category_tabl $upgrade[] = Array( 'CreateIndexSQL', Array( 'idx_category_project_name', db_get_table( 'mantis_category_table' ), 'project_id, name', array( 'UNIQUE' ) ) ); $upgrade[] = Array( 'InsertData', Array( db_get_table( 'mantis_category_table' ), " ( project_id, user_id, name, status ) VALUES - ( '0', '0', 'None', '0' ) " ) ); + ( '0', '0', 'General', '0' ) " ) ); $upgrade[] = Array( 'AddColumnSQL', Array( db_get_table( 'mantis_bug_table' ), "category_id I UNSIGNED NOTNULL DEFAULT '1'" ) ); $upgrade[] = Array( 'UpdateFunction', "category_migrate" ); $upgrade[] = Array( 'DropColumnSQL', Array( db_get_table( 'mantis_bug_table' ), "category" ) ); diff --git a/bug_update_advanced_page.php b/bug_update_advanced_page.php index 03ed16d..8f7768f 100644 --- a/bug_update_advanced_page.php +++ b/bug_update_advanced_page.php @@ -115,9 +115,6 @@ <!-- Category --> <td> - <?php if ( $t_changed_project ) { - echo "[" . project_get_field( $t_bug->project_id, 'name' ) . "] "; - } ?> <select <?php echo helper_get_tab_index() ?> name="category_id"> <?php print_category_option_list( $t_bug->category_id, $t_bug->project_id ) ?> </select> diff --git a/bug_update_page.php b/bug_update_page.php index 151b1bc..abf3501 100644 --- a/bug_update_page.php +++ b/bug_update_page.php @@ -118,9 +118,6 @@ <!-- Category --> <td> - <?php if ( $t_changed_project ) { - echo "[" . project_get_field( $t_bug->project_id, 'name' ) . "] "; - } ?> <select <?php echo helper_get_tab_index() ?> name="category_id"> <?php print_category_option_list( $t_bug->category_id, $t_bug->project_id ) ?> </select> diff --git a/core/category_api.php b/core/category_api.php index cabde42..a768fae 100644 --- a/core/category_api.php +++ b/core/category_api.php @@ -149,7 +149,7 @@ # -------------------- # Remove a category from the project - function category_remove( $p_category_id, $p_new_category_id = 1 ) { + function category_remove( $p_category_id, $p_new_category_id = 0 ) { $t_category_row = category_get_row( $p_category_id ); $c_category_id = db_prepare_int( $p_category_id ); @@ -172,7 +172,6 @@ $t_result = db_query_bound( $query, array( $c_category_id ) ); while ( $t_bug_row = db_fetch_array( $t_result ) ) { - var_dump( $t_bug_row ); history_log_event_direct( $t_bug_row['id'], 'category', $t_category_row['name'], category_full_name( $p_new_category_id, false ) ); } @@ -188,7 +187,7 @@ # -------------------- # Remove all categories associated with a project - function category_remove_all( $p_project_id, $p_new_category_id = 1 ) { + function category_remove_all( $p_project_id, $p_new_category_id = 0 ) { $c_project_id = db_prepare_int( $p_project_id ); $c_new_category_id = db_prepare_int( $p_new_category_id ); @@ -258,19 +257,55 @@ } # -------------------- - # Return all categories for the specified project id - function category_get_all_rows( $p_project_id ) { + # Sort categories based on what project they're in. + # Call beforehand with a single parameter to set a 'preferred' project. + function category_sort_rows_by_project( $p_category1, $p_category2=null ) { + static $p_project_id=null; + if ( is_null( $p_category2 ) ) { # Set a target project + $p_project_id = $p_category1; + return; + } + + if ( !is_null( $p_project_id ) ) { + if ( $p_category1['project_id'] == $p_project_id && + $p_category2['project_id'] != $p_project_id ) { + return -1; + } + if ( $p_category1['project_id'] != $p_project_id && + $p_category2['project_id'] == $p_project_id ) { + return 1; + } + } + + $t_proj_cmp = strcasecmp( $p_category1['project_name'], $p_category2['project_name'] ); + if ( $t_proj_cmp != 0 ) { + return $t_proj_cmp; + } + + return strcasecmp( $p_category1['name'], $p_category2['name'] ); + } + # -------------------- + # Return all categories for the specified project id. + # Obeys project hierarchies and such. + function category_get_all_rows( $p_project_id, $p_inherit=true, $p_sort_by_project=false ) { global $g_category_cache; + project_hierarchy_cache(); + $c_project_id = db_prepare_int( $p_project_id ); $t_category_table = db_get_table( 'mantis_category_table' ); $t_project_table = db_get_table( 'mantis_project_table' ); - $t_project_where = helper_project_specific_where( $c_project_id ); + if ( $p_inherit ) { + $t_project_ids = project_hierarchy_inheritance( $p_project_id ); + $t_project_where = ' project_id IN ( ' . implode( ', ', $t_project_ids ) . ' ) '; + } else { + $t_project_where = ' project_id=' . $p_project_id . ' '; + } $query = "SELECT c.*, p.name AS project_name FROM $t_category_table AS c - JOIN $t_project_table AS p + LEFT JOIN $t_project_table AS p ON c.project_id=p.id WHERE $t_project_where ORDER BY c.name "; @@ -284,6 +319,12 @@ $g_category_cache[$row['id']] = $row; } + if ( $p_sort_by_project ) { + category_sort_rows_by_project( $p_project_id ); + usort( $rows, 'category_sort_rows_by_project' ); + category_sort_rows_by_project( null ); + } + return $rows; } @@ -311,7 +352,7 @@ $t_row = category_get_row( $p_category_id ); $t_project_id = $t_row['project_id']; - if ( $p_show_project && ALL_PROJECTS != $t_project_id ) { + if ( $p_show_project ) { return '[' . project_get_name( $t_project_id ) . '] ' . $t_row['name']; } diff --git a/core/print_api.php b/core/print_api.php index 536a644..894e9c4 100644 --- a/core/print_api.php +++ b/core/print_api.php @@ -696,29 +696,17 @@ $t_project_table = db_get_table( 'mantis_project_table' ); if ( null === $p_project_id ) { - $c_project_id = helper_get_current_project(); + $t_project_id = helper_get_current_project(); } else { - $c_project_id = db_prepare_int( $p_project_id ); + $t_project_id = $p_project_id; } - $t_project_where = helper_project_specific_where( $c_project_id ); - - # grab all categories in the project category table - $cat_arr = array(); - $query = "SELECT id,name FROM $t_category_table - WHERE $t_project_where - ORDER BY name"; - $result = db_query( $query ); - - while ( $row = db_fetch_array( $result ) ) { - $cat_arr[$row['id']] = $row['name']; - } - asort($cat_arr); + $cat_arr = category_get_all_rows( $t_project_id, true, !is_null( $p_project_id ) ); - foreach( $cat_arr as $t_category_id => $t_name ) { - PRINT "<option value=\"$t_category_id\""; - check_selected( $p_category_id, $t_category_id ); - PRINT ">$t_name</option>"; + foreach( $cat_arr as $t_category_row ) { + $t_category_id = $t_category_row['id']; + echo "<option value=\"$t_category_id\"", check_selected( $p_category_id, $t_category_id ), '>'; + echo category_full_name( $t_category_id, $t_category_row['project_id'] != $p_project_id ), '</option>'; } } # -------------------- @@ -742,7 +730,16 @@ $c_project_id = db_prepare_int( $p_project_id ); } - $t_project_where = helper_project_specific_where( $c_project_id ); + project_hierarchy_cache(); + $t_project_ids = project_hierarchy_inheritance( $c_project_id ); + + $t_subproject_ids = array(); + foreach ( $t_project_ids as $t_project_id ) { + $t_subproject_ids = array_merge( $t_subproject_ids, current_user_get_all_accessible_subprojects( $t_project_id ) ); + } + + $t_project_ids = array_merge( $t_project_ids, $t_subproject_ids ); + $t_project_where = ' project_id IN ( ' . implode( ', ', $t_project_ids ) . ' ) '; # grab all categories in the project category table $cat_arr = array(); diff --git a/core/project_api.php b/core/project_api.php index 66476a8..194ee44 100644 --- a/core/project_api.php +++ b/core/project_api.php @@ -211,7 +211,7 @@ # -------------------- # Create a new project - function project_create( $p_name, $p_description, $p_status, $p_view_state = VS_PUBLIC, $p_file_path = '', $p_enabled = true ) { + function project_create( $p_name, $p_description, $p_status, $p_view_state = VS_PUBLIC, $p_file_path = '', $p_enabled = true, $p_inherit_global = true ) { # Make sure file path has trailing slash $p_file_path = terminate_directory_path( $p_file_path ); @@ -221,6 +221,7 @@ $c_view_state = db_prepare_int( $p_view_state ); $c_file_path = db_prepare_string( $p_file_path ); $c_enabled = db_prepare_bool( $p_enabled ); + $c_inherit_global = db_prepare_bool( $p_inherit_global ); if ( is_blank( $p_name ) ) { trigger_error( ERROR_PROJECT_NAME_INVALID, ERROR ); @@ -235,9 +236,9 @@ $t_project_table = db_get_table( 'mantis_project_table' ); $query = "INSERT INTO $t_project_table - ( name, status, enabled, view_state, file_path, description ) + ( name, status, enabled, view_state, file_path, description, inherit_global ) VALUES - ( '$c_name', '$c_status', '$c_enabled', '$c_view_state', '$c_file_path', '$c_description' )"; + ( '$c_name', '$c_status', '$c_enabled', '$c_view_state', '$c_file_path', '$c_description', '$c_inherit_global' )"; db_query( $query ); @@ -302,7 +303,7 @@ # -------------------- # Update a project - function project_update( $p_project_id, $p_name, $p_description, $p_status, $p_view_state, $p_file_path, $p_enabled ) { + function project_update( $p_project_id, $p_name, $p_description, $p_status, $p_view_state, $p_file_path, $p_enabled, $p_inherit_global ) { # Make sure file path has trailing slash $p_file_path = terminate_directory_path( $p_file_path ); @@ -313,6 +314,7 @@ $c_view_state = db_prepare_int( $p_view_state ); $c_file_path = db_prepare_string( $p_file_path ); $c_enabled = db_prepare_bool( $p_enabled ); + $c_inherit_global = db_prepare_bool( $p_inherit_global ); if ( is_blank( $p_name ) ) { trigger_error( ERROR_PROJECT_NAME_INVALID, ERROR ); @@ -336,7 +338,8 @@ enabled='$c_enabled', view_state='$c_view_state', file_path='$c_file_path', - description='$c_description' + description='$c_description', + inherit_global='$c_inherit_global' WHERE id='$c_project_id'"; db_query( $query ); diff --git a/core/project_hierarchy_api.php b/core/project_hierarchy_api.php index accb345..1be60ac 100644 --- a/core/project_hierarchy_api.php +++ b/core/project_hierarchy_api.php @@ -26,7 +26,7 @@ $t_core_dir = dirname( __FILE__ ).DIRECTORY_SEPARATOR; # -------------------- - function project_hierarchy_add( $p_child_id, $p_parent_id ) { + function project_hierarchy_add( $p_child_id, $p_parent_id, $p_inherit_parent = true ) { if ( in_array( $p_parent_id, project_hierarchy_get_all_subprojects( $p_child_id ) ) ) { trigger_error( ERROR_PROJECT_RECURSIVE_HIERARCHY, ERROR ); } @@ -35,13 +35,28 @@ $c_child_id = db_prepare_int( $p_child_id ); $c_parent_id = db_prepare_int( $p_parent_id ); + $c_inherit_parent = db_prepare_bool( $p_inherit_parent ); $query = "INSERT INTO $t_project_hierarchy_table - ( child_id, parent_id ) + ( child_id, parent_id, inherit_parent ) VALUES - ( " . db_param(0) . ", " . db_param(1) . " )"; + ( " . db_param(0) . ', ' . db_param(1) . ', ' . db_param(2) . ' )'; - db_query_bound($query, Array( $c_child_id, $c_parent_id ) ); + db_query_bound($query, Array( $c_child_id, $c_parent_id, $c_inherit_parent ) ); + } + + function project_hierarchy_update( $p_child_id, $p_parent_id, $p_inherit_parent = true ) { + $t_project_hierarchy_table = db_get_table( 'mantis_project_hierarchy_table' ); + + $c_child_id = db_prepare_int( $p_child_id ); + $c_parent_id = db_prepare_int( $p_parent_id ); + $c_inherit_parent = db_prepare_bool( $p_inherit_parent ); + + $query = "UPDATE $t_project_hierarchy_table + SET inherit_parent=" . db_param(0) . ' + WHERE child_id=' . db_param(1) . ' + AND parent_id=' . db_param(2); + db_query_bound( $query, Array( $c_inherit_parent, $c_child_id, $c_parent_id ) ); } # -------------------- @@ -87,16 +102,21 @@ } $g_cache_project_hierarchy = null; + $g_cache_project_inheritance = null; # -------------------- function project_hierarchy_cache( $p_show_disabled = false ) { - global $g_cache_project_hierarchy; + global $g_cache_project_hierarchy, $g_cache_project_inheritance; + + if ( !is_null( $g_cache_project_hierarchy ) ) { + return; + } $t_project_table = db_get_table( 'mantis_project_table' ); $t_project_hierarchy_table = db_get_table( 'mantis_project_hierarchy_table' ); $t_enabled_clause = $p_show_disabled ? '1=1' : 'p.enabled = ' . db_param(0); - $query = "SELECT DISTINCT p.id, ph.parent_id, p.name + $query = "SELECT DISTINCT p.id, ph.parent_id, p.name, p.inherit_global, ph.inherit_parent FROM $t_project_table p LEFT JOIN $t_project_hierarchy_table ph ON ph.child_id = p.id @@ -107,6 +127,7 @@ $row_count = db_num_rows( $result ); $g_cache_project_hierarchy = array(); + $g_cache_project_inheritance = array(); for ( $i=0 ; $i < $row_count ; $i++ ){ $row = db_fetch_array( $result ); @@ -120,9 +141,57 @@ } else { $g_cache_project_hierarchy[ $row['parent_id'] ] = array( $row['id'] ); } + + if ( !isset( $g_cache_project_inheritance[ $row['id'] ] ) ) { + $g_cache_project_inheritance[ $row['id'] ] = array(); + } + + if ( $row['inherit_global'] && !isset( $g_cache_project_inheritance[ $row['id'] ][ ALL_PROJECTS ] ) ) { + $g_cache_project_inheritance[ $row['id'] ][] = ALL_PROJECTS; + } + if ( $row['inherit_parent'] && !isset( $g_cache_project_inheritance[ $row['id'] ][ $row['parent_id'] ] ) ) { + $g_cache_project_inheritance[ $row['id'] ][] = (int)$row['parent_id']; + } } } + # -------------------- + # Returns true if the child project inherits categories from the parent. + function project_hierarchy_inherit_parent( $p_child_id, $p_parent_id ) { + global $g_cache_project_inheritance; + + return in_array( $p_parent_id, $g_cache_project_inheritance[ $p_child_id ] ); + } + + # -------------------- + # Generate an array of project's the given project inherits from, + # including the original project in the result. + function project_hierarchy_inheritance( $p_project_id ) { + global $g_cache_project_inheritance; + + $t_project_ids = array( (int)$p_project_id ); + $t_lookup_ids = array( (int)$p_project_id ); + + while( count( $t_lookup_ids ) > 0 ) { + $t_project_id = array_shift( $t_lookup_ids ); + + if ( !isset( $g_cache_project_inheritance[ $t_project_id ] ) ) { + continue; + } + + foreach( $g_cache_project_inheritance[ $t_project_id ] as $t_parent_id ) { + if ( !in_array( $t_parent_id, $t_project_ids ) ) { + $t_project_ids[] = $t_parent_id; + + if ( !in_array( $t_lookup_ids, $t_project_ids ) ) { + $t_lookup_ids[] = $t_parent_id; + } + } + } + } + + return $t_project_ids; + } # -------------------- function project_hierarchy_get_subprojects( $p_project_id, $p_show_disabled = false ) { diff --git a/lang/strings_english.txt b/lang/strings_english.txt index 5c1a2dc..f791f53 100644 --- a/lang/strings_english.txt +++ b/lang/strings_english.txt @@ -99,7 +99,13 @@ $s_empty_password_sure_msg = 'The user has an empty password. Are you sure that $s_empty_password_button = 'Use Empty Password'; $s_reauthenticate_title = 'Authenticate'; $s_reauthenticate_message = 'You are visting a secure page, and your secure session has expired. Please authenticate yourself to continue.'; + $s_no_category = 'No Category'; +$s_global_categories = 'Global Categories'; +$s_inherit = 'Inherit Categories'; +$s_inherit_global = 'Inherit Global Categories'; +$s_inherit_parent = 'Inherit Parent Categories'; +$s_update_subproject_inheritance = 'Update Subproject Inheritance'; $s_duplicate_of = "duplicate of"; $s_has_duplicate = "has duplicate"; diff --git a/manage_proj_cat_add.php b/manage_proj_cat_add.php index 9675b08..92764b8 100644 --- a/manage_proj_cat_add.php +++ b/manage_proj_cat_add.php @@ -59,7 +59,11 @@ } } - $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $f_project_id; + if ( $f_project_id == ALL_PROJECTS ) { + $t_redirect_url = 'manage_proj_page.php'; + } else { + $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $f_project_id; + } print_header_redirect( $t_redirect_url ); ?> diff --git a/manage_proj_cat_copy.php b/manage_proj_cat_copy.php index f205c71..43e6b9f 100644 --- a/manage_proj_cat_copy.php +++ b/manage_proj_cat_copy.php @@ -57,5 +57,11 @@ } } - print_header_redirect( 'manage_proj_edit_page.php?project_id=' . $f_project_id ); + if ( $f_project_id == ALL_PROJECTS ) { + $t_redirect_url = 'manage_proj_page.php'; + } else { + $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $f_project_id; + } + + print_header_redirect( $t_redirect_url ); ?> diff --git a/manage_proj_cat_delete.php b/manage_proj_cat_delete.php index 934e7bf..971b8cd 100644 --- a/manage_proj_cat_delete.php +++ b/manage_proj_cat_delete.php @@ -30,6 +30,7 @@ auth_reauthenticate(); $f_category_id = gpc_get_string( 'id' ); + $f_project_id = gpc_get_int( 'project_id' ); access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id ); @@ -44,7 +45,11 @@ category_remove( $f_category_id ); - $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $t_project_id; + if ( $f_project_id == ALL_PROJECTS ) { + $t_redirect_url = 'manage_proj_page.php'; + } else { + $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $f_project_id; + } html_page_top1(); html_meta_redirect( $t_redirect_url ); diff --git a/manage_proj_cat_edit_page.php b/manage_proj_cat_edit_page.php index 781d938..2491518 100644 --- a/manage_proj_cat_edit_page.php +++ b/manage_proj_cat_edit_page.php @@ -30,6 +30,7 @@ auth_reauthenticate(); $f_category_id = gpc_get_string( 'id' ); + $f_project_id = gpc_get_string( 'project_id' ); access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id ); diff --git a/manage_proj_cat_update.php b/manage_proj_cat_update.php index 98610e8..7c736f4 100644 --- a/manage_proj_cat_update.php +++ b/manage_proj_cat_update.php @@ -30,6 +30,7 @@ auth_reauthenticate(); $f_category_id = gpc_get_int( 'category_id' ); + $f_project_id = gpc_get_int( 'project_id' ); $f_name = trim( gpc_get_string( 'name' ) ); $f_assigned_to = gpc_get_int( 'assigned_to', 0 ); @@ -50,7 +51,11 @@ category_update( $f_category_id, $f_name, $f_assigned_to ); - $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $t_project_id; + if ( $f_project_id == ALL_PROJECTS ) { + $t_redirect_url = 'manage_proj_page.php'; + } else { + $t_redirect_url = 'manage_proj_edit_page.php?project_id=' . $f_project_id; + } html_page_top1(); diff --git a/manage_proj_create.php b/manage_proj_create.php index 3dcd7a4..9d7d87b 100644 --- a/manage_proj_create.php +++ b/manage_proj_create.php @@ -36,8 +36,10 @@ $f_view_state = gpc_get_int( 'view_state' ); $f_status = gpc_get_int( 'status' ); $f_file_path = gpc_get_string( 'file_path', '' ); + $f_inherit_global = gpc_get_bool( 'inherit_global', 1 ); + $f_inherit_parent = gpc_get_bool( 'inherit_parent', 1 ); - $t_project_id = project_create( strip_tags( $f_name ), $f_description, $f_status, $f_view_state, $f_file_path ); + $t_project_id = project_create( strip_tags( $f_name ), $f_description, $f_status, $f_view_state, $f_file_path, true, $f_inherit_global ); if ( ( $f_view_state == VS_PRIVATE ) && ( false === current_user_is_administrator() ) ) { $t_access_level = access_get_global_level(); @@ -48,7 +50,7 @@ $f_parent_id = gpc_get_int( 'parent_id', 0 ); if ( 0 != $f_parent_id ) { - project_hierarchy_add( $t_project_id, $f_parent_id ); + project_hierarchy_add( $t_project_id, $f_parent_id, $f_inherit_parent ); } $t_redirect_url = 'manage_proj_page.php'; diff --git a/manage_proj_create_page.php b/manage_proj_create_page.php index bf6f7c2..6714c0c 100644 --- a/manage_proj_create_page.php +++ b/manage_proj_create_page.php @@ -84,6 +84,24 @@ </select> </td> </tr> +<tr class="row-2"> + <td class="category"> + <?php echo lang_get( 'inherit_global' ) ?> + </td> + <td> + <input type="checkbox" name="inherit_global" checked="checked" /> + </td> +</tr> +<?php if ( !is_null( $f_parent_id ) ) { ?> +<tr class="row-1"> + <td class="category"> + <?php echo lang_get( 'inherit_parent' ) ?> + </td> + <td> + <input type="checkbox" name="inherit_parent" checked="checked" /> + </td> +</tr> +<?php } ?> <?php if ( config_get( 'allow_file_upload' ) ) { ?> diff --git a/manage_proj_edit_page.php b/manage_proj_edit_page.php index 5292cdd..c819219 100644 --- a/manage_proj_edit_page.php +++ b/manage_proj_edit_page.php @@ -95,6 +95,16 @@ </td> </tr> +<!-- Category Inheritance --> +<tr <?php echo helper_alternate_class() ?>> + <td class="category"> + <?php echo lang_get( 'inherit_global' ) ?> + </td> + <td> + <input type="checkbox" name="inherit_global" <?php check_checked( $row['inherit_global'], ON ); ?> /> + </td> +</tr> + <!-- View Status (public/private) --> <tr <?php echo helper_alternate_class() ?>> <td class="category"> @@ -179,7 +189,10 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?> </tr> <!-- Subprojects --> +<form name="update_children_form" action="manage_proj_update_children.php" method="post"> +<input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" /> <?php + project_hierarchy_cache(); $t_subproject_ids = current_user_get_accessible_subprojects( $f_project_id, /* show_disabled */ true ); if ( Array() != $t_subproject_ids ) { @@ -195,9 +208,12 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?> <?php echo lang_get( 'enabled' ) ?> </td> <td width="10%"> + <?php echo lang_get( 'inherit' ) ?> + </td> + <td width="10%"> <?php echo lang_get( 'view_status' ) ?> </td> - <td width="30%"> + <td width="20%"> <?php echo lang_get( 'description' ) ?> </td> <td width="20%"> @@ -208,18 +224,22 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?> <?php foreach ( $t_subproject_ids as $t_subproject_id ) { $t_subproject = project_get_row( $t_subproject_id ); + $t_inherit_parent = project_hierarchy_inherit_parent( $t_subproject_id, $f_project_id ); ?> <tr <?php echo helper_alternate_class() ?>> <td> <a href="manage_proj_edit_page.php?project_id=<?php echo $t_subproject['id'] ?>"><?php echo string_display( $t_subproject['name'] ) ?></a> </td> - <td> + <td class="center"> <?php echo get_enum_element( 'project_status', $t_subproject['status'] ) ?> </td> - <td> + <td class="center"> <?php echo trans_bool( $t_subproject['enabled'] ) ?> </td> - <td> + <td class="center"> + <input type="checkbox" name="inherit_child_<?php echo $t_subproject_id ?>" <?php echo ( $t_inherit_parent ? 'checked="checked"' : '' ) ?> /> + </td> + <td class="center"> <?php echo get_enum_element( 'project_view_state', $t_subproject['view_state'] ) ?> </td> <td> @@ -227,9 +247,8 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?> </td> <td class="center"> <?php - print_button( 'manage_proj_edit_page.php?project_id=' . $t_subproject['id'], lang_get( 'edit_link' ) ); - echo ' '; - print_button( 'manage_proj_subproj_delete.php?project_id=' . $f_project_id . '&subproject_id=' . $t_subproject['id'], lang_get( 'unlink_link' ) ); + print_bracket_link( 'manage_proj_edit_page.php?project_id=' . $t_subproject['id'], lang_get( 'edit_link' ) ); + print_bracket_link( 'manage_proj_subproj_delete.php?project_id=' . $f_project_id . '&subproject_id=' . $t_subproject['id'], lang_get( 'unlink_link' ) ); ?> </td> </tr> @@ -238,9 +257,16 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?> } # End of hiding subproject listing if there are no subprojects ?> +<tr> + <td colspan="6"> + <input type="submit" value="<?php echo lang_get( 'update_subproject_inheritance' ) ?>" /> + </form> + </td> +</tr> + <!-- Add subproject --> <tr> - <td class="left" colspan="2"> + <td colspan="7"> <form method="post" action="manage_proj_subproj_add.php"> <input type="hidden" name="project_id" value="<?php echo $f_project_id ?>" /> <select name="subproject_id"> @@ -307,8 +333,14 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?> foreach ( $t_categories as $t_category ) { $t_id = $t_category['id']; - $t_name = $t_category['name']; + if ( $t_category['project_id'] != $f_project_id ) { + $t_inherited = true; + } else { + $t_inherited = false; + } + + $t_name = $t_category['name']; if ( NO_USER != $t_category['user_id'] && user_exists( $t_category['user_id'] )) { $t_user_name = user_get_name( $t_category['user_id'] ); } else { @@ -318,19 +350,20 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?> <!-- Repeated Info Row --> <tr <?php echo helper_alternate_class() ?>> <td> - <?php echo string_display( $t_name ) ?> + <?php echo string_display( category_full_name( $t_category['id'] , $t_inherited ) ) ?> </td> <td> <?php echo $t_user_name ?> </td> <td class="center"> - <?php + <?php if ( !$t_inherited ) { $t_id = urlencode( $t_id ); + $t_project_id = urlencode( $f_project_id ); - print_button( 'manage_proj_cat_edit_page.php?id=' . $t_id, lang_get( 'edit_link' ) ); + print_button( 'manage_proj_cat_edit_page.php?id=' . $t_id . '&project_id=' . $t_project_id, lang_get( 'edit_link' ) ); echo ' '; - print_button( 'manage_proj_cat_delete.php?id=' . $t_id, lang_get( 'delete_link' ) ); - ?> + print_button( 'manage_proj_cat_delete.php?id=' . $t_id . '&project_id=' . $t_project_id, lang_get( 'delete_link' ) ); + } ?> </td> </tr> <?php diff --git a/manage_proj_page.php b/manage_proj_page.php index c0b1b25..fe004b8 100644 --- a/manage_proj_page.php +++ b/manage_proj_page.php @@ -140,5 +140,83 @@ } ?> </table> +<br/> + +<!-- GLOBAL CATEGORIES --> +<a name="categories" /> +<div align="center"> +<table class="width75" cellspacing="1"> + +<!-- Title --> +<tr> + <td class="form-title" colspan="3"> + <?php echo lang_get( 'global_categories' ) ?> + </td> +</tr> +<?php + $t_categories = category_get_all_rows( ALL_PROJECTS, false ); + + if ( count( $t_categories ) > 0 ) { +?> + <tr class="row-category"> + <td> + <?php echo lang_get( 'category' ) ?> + </td> + <td> + <?php echo lang_get( 'assign_to' ) ?> + </td> + <td class="center"> + <?php echo lang_get( 'actions' ) ?> + </td> + </tr> +<?php + } + + foreach ( $t_categories as $t_category ) { + $t_id = $t_category['id']; + + $t_name = $t_category['name']; + if ( NO_USER != $t_category['user_id'] && user_exists( $t_category['user_id'] )) { + $t_user_name = user_get_name( $t_category['user_id'] ); + } else { + $t_user_name = ''; + } +?> +<!-- Repeated Info Row --> + <tr <?php echo helper_alternate_class() ?>> + <td> + <?php echo string_display( category_full_name( $t_category['id'], false ) ) ?> + </td> + <td> + <?php echo $t_user_name ?> + </td> + <td class="center"> + <?php + $t_id = urlencode( $t_id ); + $t_project_id = urlencode( ALL_PROJECTS ); + + print_button( 'manage_proj_cat_edit_page.php?id=' . $t_id . '&project_id=' . $t_project_id, lang_get( 'edit_link' ) ); + echo ' '; + print_button( 'manage_proj_cat_delete.php?id=' . $t_id . '&project_id=' . $t_project_id, lang_get( 'delete_link' ) ); + ?> + </td> + </tr> +<?php + } # end for loop +?> + +<!-- Add Category Form --> +<tr> + <td class="left" colspan="3"> + <form method="post" action="manage_proj_cat_add.php"> + <input type="hidden" name="project_id" value="<?php echo ALL_PROJECTS ?>" /> + <input type="text" name="name" size="32" maxlength="128" /> + <input type="submit" class="button" value="<?php echo lang_get( 'add_category_button' ) ?>" /> + </form> + </td> +</tr> + +</table> +</div> <?php html_page_bottom1( __FILE__ ) ?> diff --git a/manage_proj_update.php b/manage_proj_update.php index 2ddbdd2..3cbd2e6 100644 --- a/manage_proj_update.php +++ b/manage_proj_update.php @@ -32,10 +32,11 @@ $f_view_state = gpc_get_int( 'view_state' ); $f_file_path = gpc_get_string( 'file_path', '' ); $f_enabled = gpc_get_bool( 'enabled' ); + $f_inherit_global = gpc_get_bool( 'inherit_global', 1 ); access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id ); - project_update( $f_project_id, $f_name, $f_description, $f_status, $f_view_state, $f_file_path, $f_enabled ); + project_update( $f_project_id, $f_name, $f_description, $f_status, $f_view_state, $f_file_path, $f_enabled, $f_inherit_global ); print_header_redirect( 'manage_proj_page.php' ); ?> diff --git a/manage_proj_update_children.php b/manage_proj_update_children.php new file mode 100644 index 0000000..3a7cbe6 --- /dev/null +++ b/manage_proj_update_children.php @@ -0,0 +1,39 @@ +<?php +# Mantis - a php based bugtracking system + +# Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org +# Copyright (C) 2002 - 2007 Mantis Team - mantisbt-dev@lists.sourceforge.net + +# Mantis is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# Mantis is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Mantis. If not, see <http://www.gnu.org/licenses/>. + + require_once( 'core.php' ); + + $t_core_path = config_get( 'core_path' ); + + require_once( $t_core_path.'project_hierarchy_api.php' ); + + auth_reauthenticate(); + + $f_project_id = gpc_get_int( 'project_id' ); + + access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id ); + + $t_subproject_ids = current_user_get_accessible_subprojects( $f_project_id, true ); + foreach ( $t_subproject_ids as $t_subproject_id ) { + $f_inherit_child = gpc_get_bool( 'inherit_child_' . $t_subproject_id, false ); + var_dump( $t_subproject_id, $f_project_id, $f_inherit_child ); + project_hierarchy_update( $t_subproject_id, $f_project_id, $f_inherit_child ); + } + + print_successful_redirect( 'manage_proj_edit_page.php?project_id=' . $f_project_id ); | ||||
parent of | 0008771 | closed | jreese | Port 0008738: Allow bugs to have no category |
has duplicate | 0006048 | closed | jreese | mantis_bug_table: 'category' field should have ID of a category |
has duplicate | 0007841 | closed | jreese | Categories for subproject |
has duplicate | 0006039 | closed | giallu | global categories |
related to | 0000946 | closed | jreese | Implementation of sub-categories |
related to | 0003370 | closed | jreese | No category filter in "View Bugs" view, when in "All Projects" mode |
related to | 0008582 | assigned | dregad | Default Category for Project / Global default Category |
I've attached a patch containing the first step in this process. The patch includes:
This patch will require you to upgrade your database to work properly. Make sure you backup data before upgrading so that you can revert when you are done testing. |
|
Partial Review: install_category_migrate()
schema.php
Configuration
bug_report_page.php
bug_api.php
category_api.php
strings_english.txt stopped @ filter_api.php |
|
Latest patch attached with changes suggested by Victor: category_migrate()
schema.php
config
bug_report_page.php
bug_api.php
category_api.php
other
|
|
New version of today's patch uploaded with numerous fixes suggested by Paul and others. Same name, more fixes. |
|
Patch mantis-categories.2008-02-04.patch attached. I've finalized my work and completed implementation of global and inheriting categories. This is a feature-complete patch, but I would like the eyes of everyone to make sure I'm not making any dumb mistakes. Cheers |
|
Fixed in trunk 1.2.x r5032. |
|
MantisBT: master 829889da 2007-11-19 20:09 Details Diff |
First phase of bug 0008435: Implement Global and Inheriting Categories Structure. Implemented category ID behaviors to replicate all existing functionality. git-svn-id: http://mantisbt.svn.sourceforge.net/svnroot/mantisbt/trunk@4770 <a class="text" href="/?p=mantisbt.git;a=object;h=f5dc347c">f5dc347c</a>-c33d-0410-90a0-b07cc1902cb9 |
Affected Issues 0008435 |
|
mod - bug_update_advanced_page.php | Diff File | ||
mod - bug_update_page.php | Diff File | ||
mod - core/print_api.php | Diff File | ||
mod - core/filter_api.php | Diff File | ||
mod - bug_update.php | Diff File | ||
mod - core/category_api.php | Diff File | ||
mod - manage_proj_cat_edit_page.php | Diff File | ||
mod - bug_report_page.php | Diff File | ||
mod - view_all_inc.php | Diff File | ||
mod - bug_report.php | Diff File | ||
mod - config_defaults_inc.php | Diff File | ||
mod - core/obsolete.php | Diff File | ||
mod - graphs/graph_by_category.php | Diff File | ||
mod - core/columns_api.php | Diff File | ||
add - admin/install_functions.php | Diff File | ||
mod - admin/schema.php | Diff File | ||
mod - manage_proj_cat_delete.php | Diff File | ||
mod - manage_proj_cat_add.php | Diff File | ||
mod - manage_proj_cat_update.php | Diff File | ||
mod - core/summary_api.php | Diff File | ||
mod - manage_proj_edit_page.php | Diff File | ||
mod - admin/install.php | Diff File | ||
mod - core/bug_api.php | Diff File | ||
mod - core/graph_api.php | Diff File | ||
mod - bug_view_page.php | Diff File | ||
mod - bug_view_advanced_page.php | Diff File | ||
mod - my_view_page.php | Diff File | ||
mod - core/my_view_inc.php | Diff File | ||
mod - manage_proj_cat_copy.php | Diff File | ||
mod - bug_report_advanced_page.php | Diff File |