| [ 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 * Helper API 19 * 20 * @package CoreAPI 21 * @subpackage HelperAPI 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 access_api.php 27 * @uses authentication_api.php 28 * @uses config_api.php 29 * @uses constant_inc.php 30 * @uses current_user_api.php 31 * @uses error_api.php 32 * @uses gpc_api.php 33 * @uses html_api.php 34 * @uses lang_api.php 35 * @uses print_api.php 36 * @uses project_api.php 37 * @uses user_api.php 38 * @uses user_pref_api.php 39 * @uses utility_api.php 40 */ 41 42 require_api( 'access_api.php' ); 43 require_api( 'authentication_api.php' ); 44 require_api( 'config_api.php' ); 45 require_api( 'constant_inc.php' ); 46 require_api( 'current_user_api.php' ); 47 require_api( 'error_api.php' ); 48 require_api( 'gpc_api.php' ); 49 require_api( 'html_api.php' ); 50 require_api( 'lang_api.php' ); 51 require_api( 'print_api.php' ); 52 require_api( 'project_api.php' ); 53 require_api( 'user_api.php' ); 54 require_api( 'user_pref_api.php' ); 55 require_api( 'utility_api.php' ); 56 57 /** 58 * alternate color function 59 * If no index is given, continue alternating based on the last index given 60 * @param int $p_index 61 * @param string $p_odd_color 62 * @param string $p_even_color 63 * @return string 64 */ 65 function helper_alternate_colors( $p_index, $p_odd_color, $p_even_color ) { 66 static $t_index = 1; 67 68 if( null !== $p_index ) { 69 $t_index = $p_index; 70 } 71 72 if( 1 == $t_index++ % 2 ) { 73 return $p_odd_color; 74 } else { 75 return $p_even_color; 76 } 77 } 78 79 /** 80 * alternate classes for table rows 81 * If no index is given, continue alternating based on the last index given 82 * @param int $p_index 83 * @param string $p_odd_class default: row-1 84 * @param string $p_even_class default: row-2 85 * @return string 86 */ 87 function helper_alternate_class( $p_index = null, $p_odd_class = 'row-1', $p_even_class = 'row-2' ) { 88 static $t_index = 1; 89 90 if( null !== $p_index ) { 91 $t_index = $p_index; 92 } 93 94 if( 1 == $t_index++ % 2 ) { 95 return "class=\"$p_odd_class\""; 96 } else { 97 return "class=\"$p_even_class\""; 98 } 99 } 100 101 /** 102 * return alternate classes for rows, no attribute 103 * If no index is given, continue alternating based on the last index given 104 * @param int $p_index 105 * @param string $p_odd_class default: odd 106 * @param string $p_even_class default: even 107 * @return string 108 */ 109 function helper_alternate_class_no_attribute( $p_index = null, $p_odd_class = 'odd', $p_even_class = 'even' ) { 110 static $t_index = 1; 111 112 if( null !== $p_index ) { 113 $t_index = $p_index; 114 } 115 116 if( 1 == $t_index++ % 2 ) { 117 return $p_odd_class; 118 } else { 119 return $p_even_class; 120 } 121 } 122 123 /** 124 * get the color string for the given status 125 * @param int $p_status 126 * @return string 127 */ 128 function get_status_color( $p_status ) { 129 $t_status_label = MantisEnum::getLabel( config_get( 'status_enum_string' ), $p_status ); 130 $t_status_colors = config_get( 'status_colors' ); 131 $t_color = '#ffffff'; 132 133 if ( isset( $t_status_colors[$t_status_label] ) ) { 134 $t_color = $t_status_colors[$t_status_label]; 135 } 136 137 return $t_color; 138 } 139 140 /** 141 * get the status percentages 142 * @return array key is the status value, value is the percentage of bugs for the status 143 */ 144 function get_percentage_by_status() { 145 $t_mantis_bug_table = db_get_table( 'bug' ); 146 $t_project_id = helper_get_current_project(); 147 $t_user_id = auth_get_current_user_id(); 148 149 # checking if it's a per project statistic or all projects 150 $t_specific_where = helper_project_specific_where( $t_project_id, $t_user_id ); 151 152 $query = "SELECT status, COUNT(*) AS number 153 FROM $t_mantis_bug_table 154 WHERE $t_specific_where"; 155 if ( !access_has_project_level( config_get( 'private_bug_threshold' ) ) ) { 156 $query .= ' AND view_state < ' . VS_PRIVATE; 157 } 158 $query .= ' GROUP BY status'; 159 $result = db_query_bound( $query ); 160 161 $t_bug_count = 0; 162 $t_status_count_array = array(); 163 164 while( $row = db_fetch_array( $result ) ) { 165 $t_status_count_array[$row['status']] = $row['number']; 166 } 167 $t_bug_count = array_sum( $t_status_count_array ); 168 foreach( $t_status_count_array AS $t_status=>$t_value ) { 169 $t_status_count_array[$t_status] = round(( $t_value / $t_bug_count ) * 100 ); 170 } 171 172 return $t_status_count_array; 173 } 174 175 /** 176 * Given a enum string and num, return the appropriate string 177 * @param string $p_enum_name 178 * @param int $p_val 179 * @return string 180 */ 181 function get_enum_element( $p_enum_name, $p_val ) { 182 $config_var = config_get( $p_enum_name . '_enum_string' ); 183 $string_var = lang_get( $p_enum_name . '_enum_string' ); 184 185 return MantisEnum::getLocalizedLabel( $config_var, $string_var, $p_val ); 186 } 187 188 /** 189 * If $p_var is not an array and is equal to $p_val then we PRINT SELECTED. 190 * If $p_var is an array, then if any member is equal to $p_val we PRINT SELECTED. 191 * This is used when we want to know if a variable indicated a certain 192 * option element is selected 193 * 194 * If the second parameter is not given, the first parameter is compared 195 * to the boolean value true 196 * @param mixed $p_var 197 * @param mixed $p_val 198 * @return null 199 */ 200 function check_selected( $p_var, $p_val = true ) { 201 if( is_array( $p_var ) ) { 202 foreach( $p_var as $t_this_var ) { 203 204 # catch the case where one entry is 0 and the other is a string. 205 if( is_string( $t_this_var ) && is_string( $p_val ) ) { 206 if( $t_this_var === $p_val ) { 207 echo ' selected="selected"'; 208 return; 209 } 210 } 211 else if( $t_this_var == $p_val ) { 212 echo ' selected="selected"'; 213 return; 214 } 215 } 216 } else { 217 if( is_string( $p_var ) && is_string( $p_val ) ) { 218 if( $p_var === $p_val ) { 219 echo ' selected="selected"'; 220 return; 221 } 222 } 223 else if( $p_var == $p_val ) { 224 echo ' selected="selected"'; 225 return; 226 } 227 } 228 } 229 230 /** 231 * If $p_var is not an array and is equal to $p_val then we PRINT CHECKED. 232 * If $p_var is an array, then if any member is equal to $p_val we PRINT CHECKED. 233 * This is used when we want to know if a variable indicated a certain 234 * option element is selected 235 * 236 * If the second parameter is not given, the first parameter is compared 237 * to the boolean value true 238 * @param mixed $p_var 239 * @param mixed $p_val 240 * @return null 241 */ 242 function check_checked( $p_var, $p_val = true ) { 243 if( is_array( $p_var ) ) { 244 foreach( $p_var as $t_this_var ) { 245 246 # catch the case where one entry is 0 and the other is a string. 247 if( is_string( $t_this_var ) && is_string( $p_val ) ) { 248 if( $t_this_var === $p_val ) { 249 echo ' checked="checked"'; 250 return; 251 } 252 } 253 else if( $t_this_var == $p_val ) { 254 echo ' checked="checked"'; 255 return; 256 } 257 } 258 } else { 259 if( is_string( $p_var ) && is_string( $p_val ) ) { 260 if( $p_var === $p_val ) { 261 echo ' checked="checked"'; 262 return; 263 } 264 } 265 else if( $p_var == $p_val ) { 266 echo ' checked="checked"'; 267 return; 268 } 269 } 270 } 271 272 /** 273 * Set up PHP for a long process execution 274 * The script timeout is set based on the value of the long_process_timeout config option. 275 * $p_ignore_abort specified whether to ignore user aborts by hitting 276 * the Stop button (the default is not to ignore user aborts) 277 * @param bool $p_ignore_abort 278 * @return int 279 */ 280 function helper_begin_long_process( $p_ignore_abort = false ) { 281 $t_timeout = config_get( 'long_process_timeout' ); 282 283 # silent errors or warnings reported when safe_mode is ON. 284 @set_time_limit( $t_timeout ); 285 286 ignore_user_abort( $p_ignore_abort ); 287 return $t_timeout; 288 } 289 290 # this allows pages to override the current project settings. 291 # This typically applies to the view bug pages where the "current" 292 # project as used by the filters, etc, does not match the bug being viewed. 293 $g_project_override = null; 294 $g_cache_current_project = null; 295 296 /** 297 * Return the current project id as stored in a cookie 298 * If no cookie exists, the user's default project is returned 299 * @return int 300 */ 301 function helper_get_current_project() { 302 global $g_project_override, $g_cache_current_project; 303 304 if( $g_project_override !== null ) { 305 return $g_project_override; 306 } 307 308 if( $g_cache_current_project === null ) { 309 $t_cookie_name = config_get( 'project_cookie' ); 310 311 $t_project_id = gpc_get_cookie( $t_cookie_name, null ); 312 313 if( null === $t_project_id ) { 314 $t_pref = user_pref_get( auth_get_current_user_id(), ALL_PROJECTS, false ); 315 $t_project_id = $t_pref->default_project; 316 } else { 317 $t_project_id = explode( ';', $t_project_id ); 318 $t_project_id = $t_project_id[count( $t_project_id ) - 1]; 319 } 320 321 if( !project_exists( $t_project_id ) || ( 0 == project_get_field( $t_project_id, 'enabled' ) ) || !access_has_project_level( VIEWER, $t_project_id ) ) { 322 $t_project_id = ALL_PROJECTS; 323 } 324 $g_cache_current_project = (int) $t_project_id; 325 } 326 return $g_cache_current_project; 327 } 328 329 /** 330 * Return the current project id as stored in a cookie, in an Array 331 * If no cookie exists, the user's default project is returned 332 * If the current project is a subproject, the return value will include 333 * any parent projects 334 * @return array 335 */ 336 function helper_get_current_project_trace() { 337 $t_cookie_name = config_get( 'project_cookie' ); 338 339 $t_project_id = gpc_get_cookie( $t_cookie_name, null ); 340 341 if( null === $t_project_id ) { 342 $t_bottom = current_user_get_pref( 'default_project' ); 343 $t_project_id = Array( 344 $t_bottom, 345 ); 346 } else { 347 $t_project_id = explode( ';', $t_project_id ); 348 $t_bottom = $t_project_id[count( $t_project_id ) - 1]; 349 } 350 351 if( !project_exists( $t_bottom ) || ( 0 == project_get_field( $t_bottom, 'enabled' ) ) || !access_has_project_level( VIEWER, $t_bottom ) ) { 352 $t_project_id = Array( 353 ALL_PROJECTS, 354 ); 355 } 356 357 return $t_project_id; 358 } 359 360 /** 361 * Set the current project id (stored in a cookie) 362 * @param int $p_project_id 363 * @return bool always true 364 */ 365 function helper_set_current_project( $p_project_id ) { 366 $t_project_cookie_name = config_get( 'project_cookie' ); 367 368 gpc_set_cookie( $t_project_cookie_name, $p_project_id, true ); 369 370 return true; 371 } 372 373 /** 374 * Clear all known user preference cookies 375 * @return null 376 */ 377 function helper_clear_pref_cookies() { 378 gpc_clear_cookie( config_get( 'project_cookie' ) ); 379 gpc_clear_cookie( config_get( 'manage_cookie' ) ); 380 } 381 382 /** 383 * Check whether the user has confirmed this action. 384 * 385 * If the user has not confirmed the action, generate a page which asks 386 * the user to confirm and then submits a form back to the current page 387 * with all the GET and POST data and an additional field called _confirmed 388 * to indicate that confirmation has been done. 389 * @param string $p_message 390 * @param string $p_button_label 391 * @return bool 392 * @todo improve this formatting - to only be about 50% of the screen width so that it doesn't become hard to read. 393 */ 394 function helper_ensure_confirmed( $p_message, $p_button_label ) { 395 if( true == gpc_get_bool( '_confirmed' ) ) { 396 return true; 397 } 398 399 html_page_top(); 400 401 echo "<br />\n<div class=\"center\">\n<hr />"; 402 echo "\n$p_message\n"; 403 404 echo '<form method="post" action="">' . "\n"; 405 # CSRF protection not required here - user needs to confirm action 406 # before the form is accepted. 407 print_hidden_inputs( gpc_strip_slashes( $_POST ) ); 408 print_hidden_inputs( gpc_strip_slashes( $_GET ) ); 409 410 echo "<input type=\"hidden\" name=\"_confirmed\" value=\"1\" />\n"; 411 echo '<br /><br /><input type="submit" class="button" value="' . $p_button_label . '" />'; 412 echo "\n</form>\n"; 413 414 echo "<hr /></div>\n"; 415 html_page_bottom(); 416 exit; 417 } 418 419 /** 420 * Call custom function. 421 * 422 * $p_function - Name of function to call (eg: do_stuff). The function will call custom_function_override_do_stuff() 423 * if found, otherwise, will call custom_function_default_do_stuff(). 424 * $p_args_array - Parameters to function as an array 425 * @param string $p_function 426 * @param array $p_args_array 427 * @return mixed 428 */ 429 function helper_call_custom_function( $p_function, $p_args_array ) { 430 $t_function = 'custom_function_override_' . $p_function; 431 432 if( !function_exists( $t_function ) ) { 433 $t_function = 'custom_function_default_' . $p_function; 434 } 435 436 return call_user_func_array( $t_function, $p_args_array ); 437 } 438 439 /** 440 * return string to use in db queries containing projects of given user 441 * @param int $p_project_id 442 * @param int $p_user_id 443 * @return string 444 */ 445 function helper_project_specific_where( $p_project_id, $p_user_id = null ) { 446 if( null === $p_user_id ) { 447 $p_user_id = auth_get_current_user_id(); 448 } 449 450 $t_project_ids = user_get_all_accessible_projects( $p_user_id, $p_project_id ); 451 452 if( 0 == count( $t_project_ids ) ) { 453 $t_project_filter = ' 1<>1'; 454 } else if( 1 == count( $t_project_ids ) ) { 455 $t_project_filter = ' project_id=' . $t_project_ids[0]; 456 } else { 457 $t_project_filter = ' project_id IN (' . join( ',', $t_project_ids ) . ')'; 458 } 459 460 return $t_project_filter; 461 } 462 463 /** 464 * 465 * @param int $p_columns_target 466 * @param bool $p_viewable_only 467 * @param int $p_user_id 468 * @return array 469 */ 470 function helper_get_columns_to_view( $p_columns_target = COLUMNS_TARGET_VIEW_PAGE, $p_viewable_only = true, $p_user_id = null ) { 471 $t_columns = helper_call_custom_function( 'get_columns_to_view', array( $p_columns_target, $p_user_id ) ); 472 473 if( !$p_viewable_only ) { 474 return $t_columns; 475 } 476 477 $t_keys_to_remove = array(); 478 479 if( $p_columns_target == COLUMNS_TARGET_CSV_PAGE || $p_columns_target == COLUMNS_TARGET_EXCEL_PAGE ) { 480 $t_keys_to_remove[] = 'selection'; 481 $t_keys_to_remove[] = 'edit'; 482 $t_keys_to_remove[] = 'bugnotes_count'; 483 $t_keys_to_remove[] = 'attachment_count'; 484 $t_keys_to_remove[] = 'overdue'; 485 } 486 487 if( $p_columns_target == COLUMNS_TARGET_CSV_PAGE || $p_columns_target == COLUMNS_TARGET_EXCEL_PAGE || OFF == config_get( 'show_attachment_indicator' ) ) { 488 $t_keys_to_remove[] = 'attachment'; 489 } 490 491 $t_current_project_id = helper_get_current_project(); 492 493 if( $t_current_project_id != ALL_PROJECTS && !access_has_project_level( config_get( 'view_handler_threshold' ), $t_current_project_id ) ) { 494 $t_keys_to_remove[] = 'handler_id'; 495 } 496 497 if( $t_current_project_id != ALL_PROJECTS && !access_has_project_level( config_get( 'roadmap_view_threshold' ), $t_current_project_id ) ) { 498 $t_keys_to_remove[] = 'target_version'; 499 } 500 501 foreach( $t_keys_to_remove as $t_key_to_remove ) { 502 $t_keys = array_keys( $t_columns, $t_key_to_remove ); 503 504 foreach( $t_keys as $t_key ) { 505 unset( $t_columns[$t_key] ); 506 } 507 } 508 509 # get the array values to remove gaps in the array which causes issue 510 # if the array is accessed using an index. 511 return array_values( $t_columns ); 512 } 513 514 /** 515 * if all projects selected, default to <prefix><username><suffix><extension>, otherwise default to 516 * <prefix><projectname><suffix><extension>. 517 * @param string $p_extension_with_dot 518 * @param string $p_prefix 519 * @param string $p_suffix 520 * @return string 521 */ 522 function helper_get_default_export_filename( $p_extension_with_dot, $p_prefix = '', $p_suffix = '' ) { 523 $t_filename = $p_prefix; 524 525 $t_current_project_id = helper_get_current_project(); 526 527 if( ALL_PROJECTS == $t_current_project_id ) { 528 $t_filename .= user_get_name( auth_get_current_user_id() ); 529 } else { 530 $t_filename .= project_get_field( $t_current_project_id, 'name' ); 531 } 532 533 return $t_filename . $p_suffix . $p_extension_with_dot; 534 } 535 536 /** 537 * returns a tab index value and increments it by one. This is used to give sequential tab index on a form. 538 * @return int 539 */ 540 function helper_get_tab_index_value() { 541 static $tab_index = 0; 542 return ++$tab_index; 543 } 544 545 /** 546 * returns a tab index and increments internal state by 1. This is used to give sequential tab index on 547 * a form. For example, this function returns: tabindex="1" 548 * @return string 549 */ 550 function helper_get_tab_index() { 551 return 'tabindex="' . helper_get_tab_index_value() . '"'; 552 } 553 554 /** 555 * returns a boolean indicating whether SQL queries executed should be shown or not. 556 * @return bool 557 */ 558 function helper_log_to_page() { 559 # Check is authenticated before checking access level, otherwise user gets 560 # redirected to login_page.php. See #8461. 561 return config_get_global( 'log_destination' ) === 'page' && auth_is_user_authenticated() && access_has_global_level( config_get( 'show_log_threshold' ) ); 562 } 563 564 /** 565 * returns a boolean indicating whether SQL queries executed should be shown or not. 566 * @return bool 567 */ 568 function helper_show_query_count() { 569 return ON == config_get( 'show_queries_count' ); 570 } 571 572 /** 573 * Return a URL relative to the web root, compatible with other applications 574 * @param string $p_url 575 * @return string 576 */ 577 function helper_mantis_url( $p_url ) { 578 if( is_blank( $p_url ) ) { 579 return $p_url; 580 } 581 return config_get_global( 'short_path' ) . $p_url; 582 } 583 584 /** 585 * convert a duration string in "[h]h:mm" to an integer (minutes) 586 * @param string $p_hhmm 587 * @return int 588 */ 589 function helper_duration_to_minutes( $p_hhmm ) { 590 if( is_blank( $p_hhmm ) ) { 591 return 0; 592 } 593 594 $t_a = explode( ':', $p_hhmm ); 595 $t_min = 0; 596 597 // time can be composed of max 3 parts (hh:mm:ss) 598 if( count( $t_a ) > 3 ) { 599 error_parameters( 'p_hhmm', $p_hhmm ); 600 trigger_error( ERROR_CONFIG_OPT_INVALID, ERROR ); 601 } 602 603 $t_count = count( $t_a ); 604 for( $i = 0;$i < $t_count;$i++ ) { 605 // all time parts should be integers and non-negative. 606 if( !is_numeric( $t_a[$i] ) || ( (integer) $t_a[$i] < 0 ) ) { 607 error_parameters( 'p_hhmm', $p_hhmm ); 608 trigger_error( ERROR_CONFIG_OPT_INVALID, ERROR ); 609 } 610 611 // minutes and seconds are not allowed to exceed 59. 612 if(( $i > 0 ) && ( $t_a[$i] > 59 ) ) { 613 error_parameters( 'p_hhmm', $p_hhmm ); 614 trigger_error( ERROR_CONFIG_OPT_INVALID, ERROR ); 615 } 616 } 617 618 switch( $t_count ) { 619 case 1: 620 $t_min = (integer) $t_a[0]; 621 break; 622 case 2: 623 $t_min = (integer) $t_a[0] * 60 + (integer) $t_a[1]; 624 break; 625 case 3: 626 // if seconds included, approxiate it to minutes 627 $t_min = (integer) $t_a[0] * 60 + (integer) $t_a[1]; 628 629 if( (integer) $t_a[2] >= 30 ) { 630 $t_min++; 631 } 632 break; 633 } 634 635 return (int) $t_min; 636 }
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 |