| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
1 <?php 2 # MantisBT - A PHP based bugtracking system 3 4 # MantisBT is free software: you can redistribute it and/or modify 5 # it under the terms of the GNU General Public License as published by 6 # the Free Software Foundation, either version 2 of the License, or 7 # (at your option) any later version. 8 # 9 # MantisBT is distributed in the hope that it will be useful, 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 # GNU General Public License for more details. 13 # 14 # You should have received a copy of the GNU General Public License 15 # along with MantisBT. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Category API 19 * 20 * @package CoreAPI 21 * @subpackage CategoryAPI 22 * @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org 23 * @copyright Copyright (C) 2002 - 2011 MantisBT Team - mantisbt-dev@lists.sourceforge.net 24 * @link http://www.mantisbt.org 25 * 26 * @uses config_api.php 27 * @uses constant_inc.php 28 * @uses database_api.php 29 * @uses error_api.php 30 * @uses helper_api.php 31 * @uses history_api.php 32 * @uses lang_api.php 33 * @uses project_api.php 34 * @uses project_hierarchy_api.php 35 * @uses utility_api.php 36 */ 37 38 require_api( 'config_api.php' ); 39 require_api( 'constant_inc.php' ); 40 require_api( 'database_api.php' ); 41 require_api( 'error_api.php' ); 42 require_api( 'helper_api.php' ); 43 require_api( 'history_api.php' ); 44 require_api( 'lang_api.php' ); 45 require_api( 'project_api.php' ); 46 require_api( 'project_hierarchy_api.php' ); 47 require_api( 'utility_api.php' ); 48 49 # Category data cache (to prevent excessive db queries) 50 $g_category_cache = array(); 51 52 /** 53 * Check whether the category exists in the project 54 * @param int $p_category_id category id 55 * @return bool Return true if the category exists, false otherwise 56 * @access public 57 */ 58 function category_exists( $p_category_id ) { 59 global $g_category_cache; 60 if( isset( $g_category_cache[(int) $p_category_id] ) ) { 61 return true; 62 } 63 64 $c_category_id = db_prepare_int( $p_category_id ); 65 66 $t_category_table = db_get_table( 'category' ); 67 68 $query = "SELECT COUNT(*) FROM $t_category_table 69 WHERE id=" . db_param(); 70 $count = db_result( db_query_bound( $query, array( $c_category_id ) ) ); 71 72 if( 0 < $count ) { 73 return true; 74 } else { 75 return false; 76 } 77 } 78 79 /** 80 * Check whether the category exists in the project 81 * Trigger an error if it does not 82 * @param int $p_category_id category id 83 * @access public 84 */ 85 function category_ensure_exists( $p_category_id ) { 86 if( !category_exists( $p_category_id ) ) { 87 trigger_error( ERROR_CATEGORY_NOT_FOUND, ERROR ); 88 } 89 } 90 91 /** 92 * Check whether the category is unique within a project 93 * @param int $p_project_id project id 94 * @param string $p_name project name 95 * @return bool Returns true if the category is unique, false otherwise 96 * @access public 97 */ 98 function category_is_unique( $p_project_id, $p_name ) { 99 $c_project_id = db_prepare_int( $p_project_id ); 100 101 $t_category_table = db_get_table( 'category' ); 102 103 $query = "SELECT COUNT(*) FROM $t_category_table 104 WHERE project_id=" . db_param() . " AND " . db_helper_like( 'name' ); 105 $count = db_result( db_query_bound( $query, array( $c_project_id, $p_name ) ) ); 106 107 if( 0 < $count ) { 108 return false; 109 } else { 110 return true; 111 } 112 } 113 114 /** 115 * Check whether the category is unique within a project 116 * Trigger an error if it is not 117 * @param int $p_project_id Project id 118 * @param string $p_name Category Name 119 * @return null 120 * @access public 121 */ 122 function category_ensure_unique( $p_project_id, $p_name ) { 123 if( !category_is_unique( $p_project_id, $p_name ) ) { 124 trigger_error( ERROR_CATEGORY_DUPLICATE, ERROR ); 125 } 126 } 127 128 /** 129 * Add a new category to the project 130 * @param int $p_project_id Project id 131 * @param string $p_name Category Name 132 * @return int Category ID 133 * @access public 134 */ 135 function category_add( $p_project_id, $p_name ) { 136 $c_project_id = db_prepare_int( $p_project_id ); 137 138 if( is_blank( $p_name ) ) { 139 error_parameters( lang_get( 'category' ) ); 140 trigger_error( ERROR_EMPTY_FIELD, ERROR ); 141 } 142 143 category_ensure_unique( $p_project_id, $p_name ); 144 145 $t_category_table = db_get_table( 'category' ); 146 147 $query = "INSERT INTO $t_category_table 148 ( project_id, name ) 149 VALUES 150 ( " . db_param() . ', ' . db_param() . ' )'; 151 db_query_bound( $query, array( $c_project_id, $p_name ) ); 152 153 # db_query errors on failure so: 154 return db_insert_id( $t_category_table ); 155 } 156 157 /** 158 * Update the name and user associated with the category 159 * @param int $p_category_id Category id 160 * @param string $p_name Category Name 161 * @param int $p_assigned_to User ID that category is assigned to 162 * @return bool 163 * @access public 164 */ 165 function category_update( $p_category_id, $p_name, $p_assigned_to ) { 166 if( is_blank( $p_name ) ) { 167 error_parameters( lang_get( 'category' ) ); 168 trigger_error( ERROR_EMPTY_FIELD, ERROR ); 169 } 170 171 $t_old_category = category_get_row( $p_category_id ); 172 173 $c_category_id = db_prepare_int( $p_category_id ); 174 $c_assigned_to = db_prepare_int( $p_assigned_to ); 175 176 $t_category_table = db_get_table( 'category' ); 177 $t_bug_table = db_get_table( 'bug' ); 178 179 $query = "UPDATE $t_category_table 180 SET name=" . db_param() . ', 181 user_id=' . db_param() . ' 182 WHERE id=' . db_param(); 183 db_query_bound( $query, array( $p_name, $c_assigned_to, $c_category_id ) ); 184 185 # Add bug history entries if we update the category's name 186 if( $t_old_category['name'] != $p_name ) { 187 $query = "SELECT id FROM $t_bug_table WHERE category_id=" . db_param(); 188 $t_result = db_query_bound( $query, array( $c_category_id ) ); 189 190 while( $t_bug_row = db_fetch_array( $t_result ) ) { 191 history_log_event_direct( $t_bug_row['id'], 'category', $t_old_category['name'], $p_name ); 192 } 193 } 194 195 # db_query errors on failure so: 196 return true; 197 } 198 199 /** 200 * Remove a category from the project 201 * @param int $p_category_id Category id 202 * @param int $p_new_category_id new category id (to replace existing category) 203 * @return bool 204 * @access public 205 */ 206 function category_remove( $p_category_id, $p_new_category_id = 0 ) { 207 $t_category_row = category_get_row( $p_category_id ); 208 209 $c_category_id = db_prepare_int( $p_category_id ); 210 $c_new_category_id = db_prepare_int( $p_new_category_id ); 211 212 category_ensure_exists( $p_category_id ); 213 if( 0 != $p_new_category_id ) { 214 category_ensure_exists( $p_new_category_id ); 215 } 216 217 $t_category_table = db_get_table( 'category' ); 218 $t_bug_table = db_get_table( 'bug' ); 219 220 $query = "DELETE FROM $t_category_table 221 WHERE id=" . db_param(); 222 db_query_bound( $query, array( $c_category_id ) ); 223 224 # update bug history entries 225 $query = "SELECT id FROM $t_bug_table WHERE category_id=" . db_param(); 226 $t_result = db_query_bound( $query, array( $c_category_id ) ); 227 228 while( $t_bug_row = db_fetch_array( $t_result ) ) { 229 history_log_event_direct( $t_bug_row['id'], 'category', $t_category_row['name'], category_full_name( $p_new_category_id, false ) ); 230 } 231 232 # update bug data 233 $query = "UPDATE $t_bug_table 234 SET category_id=" . db_param() . " 235 WHERE category_id=" . db_param(); 236 db_query_bound( $query, array( $c_new_category_id, $c_category_id ) ); 237 238 # db_query errors on failure so: 239 return true; 240 } 241 242 /** 243 * Remove all categories associated with a project 244 * @param int $p_project_id Project ID 245 * @param int $p_new_category_id new category id (to replace existing category) 246 * @return bool 247 * @access public 248 */ 249 function category_remove_all( $p_project_id, $p_new_category_id = 0 ) { 250 251 project_ensure_exists( $p_project_id ); 252 if( 0 != $p_new_category_id ) { 253 category_ensure_exists( $p_new_category_id ); 254 } 255 256 # cache category names 257 category_get_all_rows( $p_project_id ); 258 259 $t_category_table = db_get_table( 'category' ); 260 $t_bug_table = db_get_table( 'bug' ); 261 262 # get a list of affected categories 263 $t_query = "SELECT id FROM $t_category_table WHERE project_id=" . db_param(); 264 $t_result = db_query_bound( $t_query, array( $p_project_id ) ); 265 266 $t_category_ids = array(); 267 while( $t_row = db_fetch_array( $t_result ) ) { 268 $t_category_ids[] = $t_row['id']; 269 } 270 271 # Handle projects with no categories 272 if( count( $t_category_ids ) < 1 ) { 273 return true; 274 } 275 276 $t_category_ids = join( ',', $t_category_ids ); 277 278 # update bug history entries 279 $t_query = "SELECT id, category_id FROM $t_bug_table WHERE category_id IN ( $t_category_ids )"; 280 $t_result = db_query_bound( $t_query ); 281 282 while( $t_bug_row = db_fetch_array( $t_result ) ) { 283 history_log_event_direct( $t_bug_row['id'], 'category', category_full_name( $t_bug_row['category_id'], false ), category_full_name( $p_new_category_id, false ) ); 284 } 285 286 # update bug data 287 $t_query = "UPDATE $t_bug_table SET category_id=" . db_param() . " WHERE category_id IN ( $t_category_ids )"; 288 db_query_bound( $t_query, array( $p_new_category_id ) ); 289 290 # delete categories 291 $t_query = "DELETE FROM $t_category_table WHERE project_id=" . db_param(); 292 db_query_bound( $t_query, array( $p_project_id ) ); 293 294 return true; 295 } 296 297 /** 298 * Return the definition row for the category 299 * @param int $p_category_id Category id 300 * @return array array containing category details 301 * @access public 302 */ 303 function category_get_row( $p_category_id ) { 304 global $g_category_cache; 305 if( isset( $g_category_cache[$p_category_id] ) ) { 306 return $g_category_cache[$p_category_id]; 307 } 308 309 $c_category_id = db_prepare_int( $p_category_id ); 310 311 $t_category_table = db_get_table( 'category' ); 312 $t_project_table = db_get_table( 'project' ); 313 314 $query = "SELECT * FROM $t_category_table 315 WHERE id=" . db_param(); 316 $result = db_query_bound( $query, array( $c_category_id ) ); 317 $count = db_num_rows( $result ); 318 if( 0 == $count ) { 319 trigger_error( ERROR_CATEGORY_NOT_FOUND, ERROR ); 320 } 321 322 $row = db_fetch_array( $result ); 323 $g_category_cache[$p_category_id] = $row; 324 return $row; 325 } 326 327 /** 328 * Sort categories based on what project they're in. 329 * Call beforehand with a single parameter to set a 'preferred' project. 330 * @param array $p_category1 array containing category details 331 * @param array $p_category2 array containing category details 332 * @return int integer representing sort order 333 * @access public 334 */ 335 function category_sort_rows_by_project( $p_category1, $p_category2 = null ) { 336 static $p_project_id = null; 337 if( is_null( $p_category2 ) ) { 338 339 # Set a target project 340 $p_project_id = $p_category1; 341 return; 342 } 343 344 if( !is_null( $p_project_id ) ) { 345 if( $p_category1['project_id'] == $p_project_id && $p_category2['project_id'] != $p_project_id ) { 346 return -1; 347 } 348 if( $p_category1['project_id'] != $p_project_id && $p_category2['project_id'] == $p_project_id ) { 349 return 1; 350 } 351 } 352 353 $t_proj_cmp = strcasecmp( $p_category1['project_name'], $p_category2['project_name'] ); 354 if( $t_proj_cmp != 0 ) { 355 return $t_proj_cmp; 356 } 357 358 return strcasecmp( $p_category1['name'], $p_category2['name'] ); 359 } 360 361 $g_cache_category_project = null; 362 363 function category_cache_array_rows_by_project( $p_project_id_array ) { 364 global $g_category_cache, $g_cache_category_project; 365 366 $c_project_id_array = array(); 367 368 foreach( $p_project_id_array as $t_project_id ) { 369 if( !isset( $g_cache_category_project[(int) $t_project_id] ) ) { 370 $c_project_id_array[] = (int) $t_project_id; 371 $g_cache_category_project[(int) $t_project_id] = array(); 372 } 373 } 374 375 if( empty( $c_project_id_array ) ) { 376 return; 377 } 378 379 $t_category_table = db_get_table( 'category' ); 380 $t_project_table = db_get_table( 'project' ); 381 382 $query = "SELECT c.*, p.name AS project_name FROM $t_category_table c 383 LEFT JOIN $t_project_table p 384 ON c.project_id=p.id 385 WHERE project_id IN ( " . implode( ', ', $c_project_id_array ) . " ) 386 ORDER BY c.name "; 387 $result = db_query_bound( $query ); 388 389 $rows = array(); 390 while( $row = db_fetch_array( $result ) ) { 391 $g_category_cache[(int) $row['id']] = $row; 392 393 $rows[ (int)$row[ 'project_id' ] ][] = $row['id']; 394 } 395 396 foreach( $rows as $t_project_id => $t_row ) { 397 $g_cache_category_project[ (int)$t_project_id ] = $t_row; 398 } 399 return; 400 } 401 402 /** 403 * Get a distinct array of categories accessible to the current user for 404 * the specified projects. If no project is specified, use the current project. 405 * If the current project is ALL_PROJECTS get all categories for all accessible projects. 406 * For all cases, get global categories and subproject categories according to configured inheritance settings. 407 * @param mixed $p_project_id A specific project or null 408 * @return array A unique array of category names 409 */ 410 function category_get_filter_list( $p_project_id = null ) { 411 if( null === $p_project_id ) { 412 $t_project_id = helper_get_current_project(); 413 } else { 414 $t_project_id = $p_project_id; 415 } 416 417 if( $t_project_id == ALL_PROJECTS ) { 418 $t_project_ids = current_user_get_accessible_projects(); 419 } else { 420 $t_project_ids = array( $t_project_id ); 421 } 422 423 $t_subproject_ids = array(); 424 foreach( $t_project_ids as $t_project_id ) { 425 $t_subproject_ids = array_merge( $t_subproject_ids, current_user_get_all_accessible_subprojects( $t_project_id ) ); 426 } 427 428 $t_project_ids = array_merge( $t_project_ids, $t_subproject_ids ); 429 430 $t_categories = array(); 431 foreach( $t_project_ids AS $t_id ) { 432 $t_categories = array_merge( $t_categories, category_get_all_rows( $t_id ) ); 433 } 434 435 $t_unique = array(); 436 foreach( $t_categories AS $t_category ) { 437 if( !in_array( $t_category['name'], $t_unique ) ) { 438 $t_unique[] = $t_category['name']; 439 } 440 } 441 442 return $t_unique; 443 } 444 445 /** 446 * Return all categories for the specified project id. 447 * Obeys project hierarchies and such. 448 * @param int $p_project_id Project id 449 * @param bool $p_inherit indicates whether to inherit categories from parent projects, or null to use configuration default. 450 * @param bool $p_sort_by_project 451 * @return array array of categories 452 * @access public 453 */ 454 function category_get_all_rows( $p_project_id, $p_inherit = null, $p_sort_by_project = false ) { 455 global $g_category_cache, $g_cache_category_project; 456 457 if( isset( $g_cache_category_project[ (int)$p_project_id ] ) ) { 458 if( !empty( $g_cache_category_project[ (int)$p_project_id ]) ) { 459 foreach( $g_cache_category_project[ (int)$p_project_id ] as $t_id ) { 460 $t_categories[] = category_get_row( $t_id ); 461 } 462 463 if( $p_sort_by_project ) { 464 category_sort_rows_by_project( $p_project_id ); 465 usort( $t_categories, 'category_sort_rows_by_project' ); 466 category_sort_rows_by_project( null ); 467 } 468 return $t_categories; 469 } else { 470 return array(); 471 } 472 } 473 474 $c_project_id = db_prepare_int( $p_project_id ); 475 476 $t_category_table = db_get_table( 'category' ); 477 $t_project_table = db_get_table( 'project' ); 478 479 if ( $c_project_id == ALL_PROJECTS ) { 480 $t_inherit = false; 481 } else { 482 if ( $p_inherit === null ) { 483 $t_inherit = config_get( 'subprojects_inherit_categories' ); 484 } else { 485 $t_inherit = $p_inherit; 486 } 487 } 488 489 if ( $t_inherit ) { 490 $t_project_ids = project_hierarchy_inheritance( $p_project_id ); 491 $t_project_where = ' project_id IN ( ' . implode( ', ', $t_project_ids ) . ' ) '; 492 } else { 493 $t_project_where = ' project_id=' . $p_project_id . ' '; 494 } 495 496 $query = "SELECT c.*, p.name AS project_name FROM $t_category_table c 497 LEFT JOIN $t_project_table p 498 ON c.project_id=p.id 499 WHERE $t_project_where 500 ORDER BY c.name "; 501 $result = db_query_bound( $query ); 502 $count = db_num_rows( $result ); 503 $rows = array(); 504 for( $i = 0;$i < $count;$i++ ) { 505 $row = db_fetch_array( $result ); 506 507 $rows[] = $row; 508 $g_category_cache[(int) $row['id']] = $row; 509 } 510 511 if( $p_sort_by_project ) { 512 category_sort_rows_by_project( $p_project_id ); 513 usort( $rows, 'category_sort_rows_by_project' ); 514 category_sort_rows_by_project( null ); 515 } 516 517 return $rows; 518 } 519 520 /** 521 * 522 * @param array $p_cat_id_array array of category id's 523 * @return null 524 * @access public 525 */ 526 function category_cache_array_rows( $p_cat_id_array ) { 527 global $g_category_cache; 528 $c_cat_id_array = array(); 529 530 foreach( $p_cat_id_array as $t_cat_id ) { 531 if( !isset( $g_category_cache[(int) $t_cat_id] ) ) { 532 $c_cat_id_array[] = (int) $t_cat_id; 533 } 534 } 535 536 if( empty( $c_cat_id_array ) ) { 537 return; 538 } 539 540 $t_category_table = db_get_table( 'category' ); 541 $t_project_table = db_get_table( 'project' ); 542 543 $query = "SELECT c.*, p.name AS project_name FROM $t_category_table c 544 LEFT JOIN $t_project_table p 545 ON c.project_id=p.id 546 WHERE c.id IN (" . implode( ',', $c_cat_id_array ) . ')'; 547 $result = db_query_bound( $query ); 548 549 while( $row = db_fetch_array( $result ) ) { 550 $g_category_cache[(int) $row['id']] = $row; 551 } 552 return; 553 } 554 555 /** 556 * Given a category id and a field name, this function returns the field value. 557 * An error will be triggered for a non-existent category id or category id = 0. 558 * @param int $p_category_id category id 559 * @param string $p_name field name 560 * @return string field value 561 * @access public 562 */ 563 function category_get_field( $p_category_id, $p_field_name ) { 564 $t_row = category_get_row( $p_category_id ); 565 return $t_row[$p_field_name]; 566 } 567 568 /** 569 * Given a category id, this function returns the category name. 570 * An error will be triggered for a non-existent category id or category id = 0. 571 * @param int $p_category_id category id 572 * @return string category name 573 * @access public 574 */ 575 function category_get_name( $p_category_id ) { 576 return category_get_field( $p_category_id, 'name' ); 577 } 578 579 /** 580 * Given a category name and project, this function returns the category id. 581 * An error will be triggered if the specified project does not have a 582 * category with that name. 583 * @param string $p_category_name category name 584 * @param int $p_project_id project id 585 * @param bool $p_trigger_errors trigger error on failure 586 * @return bool 587 * @access public 588 */ 589 function category_get_id_by_name( $p_category_name, $p_project_id, $p_trigger_errors = true ) { 590 $t_category_table = db_get_table( 'category' ); 591 $t_project_name = project_get_name( $p_project_id ); 592 593 $t_query = "SELECT id FROM $t_category_table 594 WHERE name=" . db_param() . " AND project_id=" . db_param(); 595 $t_result = db_query_bound( $t_query, array( $p_category_name, (int) $p_project_id ) ); 596 $t_count = db_num_rows( $t_result ); 597 if( 1 > $t_count ) { 598 if( $p_trigger_errors ) { 599 error_parameters( $p_category_name, $t_project_name ); 600 trigger_error( ERROR_CATEGORY_NOT_FOUND_FOR_PROJECT, ERROR ); 601 } else { 602 return false; 603 } 604 } 605 606 return db_result( $t_result ); 607 } 608 609 /** 610 * Retrieves category name (including project name if required) 611 * @param string $p_category_id category id 612 * @param bool $p_show_project show project details 613 * @param int $p_project_id current project id override 614 * @return string category full name 615 * @access public 616 */ 617 function category_full_name( $p_category_id, $p_show_project = true, $p_current_project = null ) { 618 if( 0 == $p_category_id ) { 619 # No Category 620 return lang_get( 'no_category' ); 621 } else { 622 $t_row = category_get_row( $p_category_id ); 623 $t_project_id = $t_row['project_id']; 624 625 $t_current_project = is_null( $p_current_project ) ? helper_get_current_project() : $p_current_project; 626 627 if( $p_show_project && $t_project_id != $t_current_project ) { 628 return '[' . project_get_name( $t_project_id ) . '] ' . $t_row['name']; 629 } 630 631 return $t_row['name']; 632 } 633 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Jul 28 15:48:31 2011 | Cross-referenced by PHPXref 0.7 |