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 @@
- project_id, 'name' ) . "] ";
- } ?>
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 @@
|
- project_id, 'name' ) . "] ";
- } ?>
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 "";
+ foreach( $cat_arr as $t_category_row ) {
+ $t_category_id = $t_category_row['id'];
+ echo "';
}
}
# --------------------
@@ -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 @@
|
+
+ |
+
+ |
+
+
+ |
+
+
+
+ |
+
+ |
+
+
+ |
+
+
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 @@
+
+>
+ |
+
+ |
+
+ />
+ |
+
+
>
|
@@ -179,7 +189,10 @@ if ( access_has_global_level ( config_get( 'delete_project_threshold' ) ) ) { ?>
|
+