| [ 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 * Print API 19 * 20 * @package CoreAPI 21 * @subpackage PrintAPI 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 bug_group_action_api.php 29 * @uses category_api.php 30 * @uses config_api.php 31 * @uses collapse_api.php 32 * @uses constant_inc.php 33 * @uses current_user_api.php 34 * @uses custom_field_api.php 35 * @uses database_api.php 36 * @uses email_api.php 37 * @uses error_api.php 38 * @uses file_api.php 39 * @uses form_api.php 40 * @uses helper_api.php 41 * @uses html_api.php 42 * @uses lang_api.php 43 * @uses last_visited_api.php 44 * @uses news_api.php 45 * @uses prepare_api.php 46 * @uses profile_api.php 47 * @uses project_api.php 48 * @uses project_hierarchy_api.php 49 * @uses string_api.php 50 * @uses tag_api.php 51 * @uses user_api.php 52 * @uses utility_api.php 53 * @uses version_api.php 54 */ 55 56 require_api( 'access_api.php' ); 57 require_api( 'authentication_api.php' ); 58 require_api( 'bug_group_action_api.php' ); 59 require_api( 'category_api.php' ); 60 require_api( 'config_api.php' ); 61 require_api( 'collapse_api.php' ); 62 require_api( 'constant_inc.php' ); 63 require_api( 'current_user_api.php' ); 64 require_api( 'custom_field_api.php' ); 65 require_api( 'database_api.php' ); 66 require_api( 'email_api.php' ); 67 require_api( 'error_api.php' ); 68 require_api( 'file_api.php' ); 69 require_api( 'form_api.php' ); 70 require_api( 'helper_api.php' ); 71 require_api( 'html_api.php' ); 72 require_api( 'lang_api.php' ); 73 require_api( 'last_visited_api.php' ); 74 require_api( 'news_api.php' ); 75 require_api( 'prepare_api.php' ); 76 require_api( 'profile_api.php' ); 77 require_api( 'project_api.php' ); 78 require_api( 'project_hierarchy_api.php' ); 79 require_api( 'string_api.php' ); 80 require_api( 'tag_api.php' ); 81 require_api( 'user_api.php' ); 82 require_api( 'utility_api.php' ); 83 require_api( 'version_api.php' ); 84 85 # -------------------- 86 # Print the headers to cause the page to redirect to $p_url 87 # If $p_die is true (default), terminate the execution of the script 88 # immediately 89 # If we have handled any errors on this page and the 'stop_on_errors' config 90 # option is turned on, return false and don't redirect. 91 # $p_sanitize - true/false - true in the case where the URL is extracted from GET/POST or untrusted source. 92 # This would be false if the URL is trusted (e.g. read from config_inc.php). 93 # 94 # @param string The page to redirect: has to be a relative path 95 # @param boolean if true, stop the script after redirecting 96 # @param boolean apply string_sanitize_url to passed url 97 # @return boolean 98 function print_header_redirect( $p_url, $p_die = true, $p_sanitize = false, $p_absolute = false ) { 99 if( ON == config_get_global( 'stop_on_errors' ) && error_handled() ) { 100 return false; 101 } 102 103 # validate the url as part of this site before continuing 104 if( $p_absolute ) { 105 if( $p_sanitize ) { 106 $t_url = string_sanitize_url( $p_url ); 107 } else { 108 $t_url = $p_url; 109 } 110 } else { 111 if( $p_sanitize ) { 112 $t_url = string_sanitize_url( $p_url, true ); 113 } else { 114 $t_url = config_get( 'path' ) . $p_url; 115 } 116 } 117 118 $t_url = string_prepare_header( $t_url ); 119 120 # don't send more headers if they have already been sent (guideweb) 121 if( !headers_sent() ) { 122 header( 'Content-Type: text/html; charset=utf-8' ); 123 header( "Location: $t_url" ); 124 } else { 125 trigger_error( ERROR_PAGE_REDIRECTION, ERROR ); 126 return false; 127 } 128 129 if( $p_die ) { 130 die; 131 132 # additional output can cause problems so let's just stop output here 133 } 134 135 return true; 136 } 137 138 # -------------------- 139 # Print a redirect header to view a bug 140 function print_header_redirect_view( $p_bug_id ) { 141 print_header_redirect( string_get_bug_view_url( $p_bug_id ) ); 142 } 143 144 # -------------------- 145 # Get a view URL for the bug id based on the user's preference and 146 # call print_successful_redirect() with that URL 147 function print_successful_redirect_to_bug( $p_bug_id ) { 148 $t_url = string_get_bug_view_url( $p_bug_id, auth_get_current_user_id() ); 149 150 print_successful_redirect( $t_url ); 151 } 152 153 # -------------------- 154 # If the show query count is ON, print success and redirect after the 155 # configured system wait time. 156 # If the show query count is OFF, redirect right away. 157 function print_successful_redirect( $p_redirect_to ) { 158 if( helper_log_to_page() ) { 159 html_page_top( null, $p_redirect_to ); 160 echo '<br /><div class="center">'; 161 echo lang_get( 'operation_successful' ) . '<br />'; 162 print_bracket_link( $p_redirect_to, lang_get( 'proceed' ) ); 163 echo '</div>'; 164 html_page_bottom(); 165 } else { 166 print_header_redirect( $p_redirect_to ); 167 } 168 } 169 170 # Print avatar image for the given user ID 171 function print_avatar( $p_user_id, $p_size = 80 ) { 172 if( !user_exists( $p_user_id ) ) { 173 return; 174 } 175 176 if( access_has_project_level( config_get( 'show_avatar_threshold' ), null, $p_user_id ) ) { 177 $t_avatar = user_get_avatar( $p_user_id, $p_size ); 178 if( false !== $t_avatar ) { 179 $t_avatar_url = htmlspecialchars( $t_avatar[0] ); 180 $t_width = $t_avatar[1]; 181 $t_height = $t_avatar[2]; 182 echo '<a rel="nofollow" href="http://site.gravatar.com"><img class="avatar" src="' . $t_avatar_url . '" alt="User avatar" width="' . $t_width . '" height="' . $t_height . '" /></a>'; 183 } 184 } 185 } 186 187 # -------------------- 188 # prints the name of the user given the id. also makes it an email link. 189 function print_user( $p_user_id ) { 190 echo prepare_user_name( $p_user_id ); 191 } 192 193 # -------------------- 194 # same as print_user() but fills in the subject with the bug summary 195 function print_user_with_subject( $p_user_id, $p_bug_id ) { 196 $c_user_id = db_prepare_int( $p_user_id ); 197 198 if( NO_USER == $p_user_id ) { 199 return; 200 } 201 202 $t_username = user_get_name( $p_user_id ); 203 if( user_exists( $p_user_id ) && user_get_field( $p_user_id, 'enabled' ) ) { 204 $t_email = user_get_email( $p_user_id ); 205 print_email_link_with_subject( $t_email, $t_username, $p_bug_id ); 206 } else { 207 echo '<span style="text-decoration: line-through">'; 208 echo $t_username; 209 echo '</span>'; 210 } 211 } 212 213 # -------------------- 214 # print out an email editing input 215 function print_email_input( $p_field_name, $p_email ) { 216 $t_limit_email_domain = config_get( 'limit_email_domain' ); 217 if( $t_limit_email_domain ) { 218 219 # remove the domain part 220 $p_email = preg_replace( '/@' . preg_quote( $t_limit_email_domain, '/' ) . '$/i', '', $p_email ); 221 echo '<input id="email-field" type="text" name="' . string_attribute( $p_field_name ) . '" size="20" maxlength="64" value="' . string_attribute( $p_email ) . '" />@' . string_display_line( $t_limit_email_domain ); 222 } else { 223 echo '<input id="email-field" type="text" name="' . string_attribute( $p_field_name ) . '" size="32" maxlength="64" value="' . string_attribute( $p_email ) . '" />'; 224 } 225 } 226 227 # -------------------- 228 # print out an email editing input 229 function print_captcha_input( $p_field_name ) { 230 echo '<input id="captcha-field" type="text" name="' . $p_field_name . '" size="5" maxlength="5" value="" />'; 231 } 232 233 # ########################################################################## 234 # Option List Printing API 235 # ########################################################################## 236 237 238 # -------------------- 239 # This populates an option list with the appropriate users by access level 240 # 241 # @todo from print_reporter_option_list 242 function print_user_option_list( $p_user_id, $p_project_id = null, $p_access = ANYBODY ) { 243 $t_users = array(); 244 245 if( null === $p_project_id ) { 246 $p_project_id = helper_get_current_project(); 247 } 248 249 $t_users = project_get_all_user_rows( $p_project_id, $p_access ); 250 251 # handles ALL_PROJECTS case 252 253 $t_display = array(); 254 $t_sort = array(); 255 $t_show_realname = ( ON == config_get( 'show_realname' ) ); 256 $t_sort_by_last_name = ( ON == config_get( 'sort_by_last_name' ) ); 257 foreach( $t_users as $t_user ) { 258 $t_user_name = string_attribute( $t_user['username'] ); 259 $t_sort_name = utf8_strtolower( $t_user_name ); 260 if( $t_show_realname && ( $t_user['realname'] <> '' ) ) { 261 $t_user_name = string_attribute( $t_user['realname'] ); 262 if( $t_sort_by_last_name ) { 263 $t_sort_name_bits = explode( ' ', utf8_strtolower( $t_user_name ), 2 ); 264 $t_sort_name = ( isset( $t_sort_name_bits[1] ) ? $t_sort_name_bits[1] . ', ' : '' ) . $t_sort_name_bits[0]; 265 } else { 266 $t_sort_name = utf8_strtolower( $t_user_name ); 267 } 268 } 269 $t_display[] = $t_user_name; 270 $t_sort[] = $t_sort_name; 271 } 272 array_multisort( $t_sort, SORT_ASC, SORT_STRING, $t_users, $t_display ); 273 $t_count = count( $t_sort ); 274 for( $i = 0;$i < $t_count;$i++ ) { 275 $t_row = $t_users[$i]; 276 echo '<option value="' . $t_row['id'] . '" '; 277 check_selected( $p_user_id, $t_row['id'] ); 278 echo '>' . $t_display[$i] . '</option>'; 279 } 280 } 281 282 # -------------------- 283 # ugly functions need to be refactored 284 # This populates the reporter option list with the appropriate users 285 # 286 # @todo This function really ought to print out all the users, I think. 287 # I just encountered a situation where a project used to be public and 288 # was made private, so now I can't filter on any of the reporters who 289 # actually reported the bugs at the time. Maybe we could get all user 290 # who are listed as the reporter in any bug? It would probably be a 291 # faster query actually. 292 function print_reporter_option_list( $p_user_id, $p_project_id = null ) { 293 print_user_option_list( $p_user_id, $p_project_id, config_get( 'report_bug_threshold' ) ); 294 } 295 296 /** 297 * Print the entire form for attaching a tag to a bug. 298 * @param integer Bug ID 299 * @param string Default contents of the input box 300 */ 301 function print_tag_attach_form( $p_bug_id, $p_string = '' ) { 302 ?> 303 <small><?php echo sprintf( lang_get( 'tag_separate_by' ), config_get( 'tag_separator' ) )?></small> 304 <form method="post" action="tag_attach.php"> 305 <?php echo form_security_field( 'tag_attach' )?> 306 <input type="hidden" name="bug_id" value="<?php echo $p_bug_id?>" /> 307 <?php 308 print_tag_input( $p_bug_id, $p_string ); 309 ?> 310 <input type="submit" value="<?php echo lang_get( 'tag_attach' )?>" class="button" /> 311 </form> 312 <?php 313 return true; 314 } 315 316 /** 317 * Print the separator comment, input box, and existing tag dropdown menu. 318 * @param integer Bug ID 319 * @param string Default contents of the input box 320 */ 321 function print_tag_input( $p_bug_id = 0, $p_string = '' ) { 322 ?> 323 <input type="hidden" id="tag_separator" value="<?php echo config_get( 'tag_separator' )?>" /> 324 <input type="text" name="tag_string" id="tag_string" size="40" value="<?php echo string_attribute( $p_string )?>" /> 325 <select <?php echo helper_get_tab_index()?> name="tag_select" id="tag_select"> 326 <?php print_tag_option_list( $p_bug_id );?> 327 </select> 328 <?php 329 330 return true; 331 } 332 333 /** 334 * Print the dropdown combo-box of existing tags. 335 * When passed a bug ID, the option list will not contain any tags attached to the given bug. 336 * @param integer Bug ID 337 */ 338 function print_tag_option_list( $p_bug_id = 0 ) { 339 $t_rows = tag_get_candidates_for_bug( $p_bug_id ); 340 341 echo '<option value="0">', string_html_specialchars( lang_get( 'tag_existing' ) ), '</option>'; 342 foreach ( $t_rows as $row ) { 343 $t_string = $row['name']; 344 if ( !empty( $row['description'] ) ) { 345 $t_string .= ' - ' . utf8_substr( $row['description'], 0, 20 ); 346 } 347 echo '<option value="', $row['id'], '" title="', string_attribute( $row['name'] ), '">', string_attribute( $t_string ), '</option>'; 348 } 349 } 350 351 # -------------------- 352 # Get current headlines and id prefix with v_ 353 function print_news_item_option_list() { 354 $t_mantis_news_table = db_get_table( 'news' ); 355 356 $t_project_id = helper_get_current_project(); 357 358 $t_global = access_has_global_level( config_get_global( 'admin_site_threshold' ) ); 359 if( $t_global ) { 360 $query = "SELECT id, headline, announcement, view_state 361 FROM $t_mantis_news_table 362 ORDER BY date_posted DESC"; 363 } else { 364 $query = "SELECT id, headline, announcement, view_state 365 FROM $t_mantis_news_table 366 WHERE project_id=" . db_param() . " 367 ORDER BY date_posted DESC"; 368 } 369 $result = db_query_bound( $query, ($t_global == true ? Array() : Array( $t_project_id ) ) ); 370 $news_count = db_num_rows( $result ); 371 372 for( $i = 0;$i < $news_count;$i++ ) { 373 $row = db_fetch_array( $result ); 374 375 $t_headline = string_display( $row['headline'] ); 376 $t_announcement = $row['announcement']; 377 $t_view_state = $row['view_state']; 378 $t_id = $row['id']; 379 380 $t_notes = array(); 381 $t_note_string = ''; 382 383 if ( 1 == $t_announcement ) { 384 array_push( $t_notes, lang_get( 'announcement' ) ); 385 } 386 387 if ( VS_PRIVATE == $t_view_state ) { 388 array_push( $t_notes, lang_get( 'private' ) ); 389 } 390 391 if ( count( $t_notes ) > 0 ) { 392 $t_note_string = ' [' . implode( ' ', $t_notes ) . ']'; 393 } 394 395 echo "<option value=\"$t_id\">$t_headline$t_note_string</option>"; 396 } 397 } 398 399 # --------------- 400 # Constructs the string for one news entry given the row retrieved from the news table. 401 function print_news_entry( $p_headline, $p_body, $p_poster_id, $p_view_state, $p_announcement, $p_date_posted ) { 402 $t_headline = string_display_links( $p_headline ); 403 $t_body = string_display_links( $p_body ); 404 $t_date_posted = date( config_get( 'normal_date_format' ), $p_date_posted ); 405 406 if( VS_PRIVATE == $p_view_state ) { 407 $t_news_css = 'news-heading-private'; 408 } else { 409 $t_news_css = 'news-heading-public'; 410 } ?> 411 412 <div class="news-item"> 413 <h3 class="<?php echo $t_news_css; ?>"> 414 <span class="news-title"><?php echo $t_headline; ?></span> 415 <span class="news-date-posted"><?php echo $t_date_posted; ?></span> 416 <span class="news-author"><?php echo prepare_user_name( $p_poster_id ); ?></span><?php 417 418 if( 1 == $p_announcement ) { ?> 419 <span class="news-announcement"><?php echo lang_get( 'announcement' ); ?></span><?php 420 } 421 if( VS_PRIVATE == $p_view_state ) { ?> 422 <span class="news-private"><?php echo lang_get( 'private' ); ?></span><?php 423 } ?> 424 </h3> 425 <p class="news-body"><?php echo $t_body; ?></p> 426 </div><?php 427 } 428 429 # -------------------- 430 # print a news item given a row in the news table. 431 function print_news_entry_from_row( $p_news_row ) { 432 $t_headline = $p_news_row['headline']; 433 $t_body = $p_news_row['body']; 434 $t_poster_id = $p_news_row['poster_id']; 435 $t_view_state = $p_news_row['view_state']; 436 $t_announcement = $p_news_row['announcement']; 437 $t_date_posted = $p_news_row['date_posted']; 438 439 print_news_entry( $t_headline, $t_body, $t_poster_id, $t_view_state, $t_announcement, $t_date_posted ); 440 } 441 442 # -------------------- 443 # print a news item 444 function print_news_string_by_news_id( $p_news_id ) { 445 $row = news_get_row( $p_news_id ); 446 447 # only show VS_PRIVATE posts to configured threshold and above 448 if(( VS_PRIVATE == $row['view_state'] ) && !access_has_project_level( config_get( 'private_news_threshold' ) ) ) { 449 return; 450 } 451 452 print_news_entry_from_row( $row ); 453 } 454 455 # -------------------- 456 function print_assign_to_option_list( $p_user_id = '', $p_project_id = null, $p_threshold = null ) { 457 458 if( null === $p_threshold ) { 459 $p_threshold = config_get( 'handle_bug_threshold' ); 460 } 461 462 print_user_option_list( $p_user_id, $p_project_id, $p_threshold ); 463 } 464 465 /** 466 * List projects that the current user has access to. 467 * 468 * @param integer $p_project_id The current project id or null to use cookie. 469 * @param bool $p_include_all_projects true: include "All Projects", otherwise false. 470 * @param mixed $p_filter_project_id The id of a project to exclude or null. 471 * @param string $p_trace The current project trace, identifies the sub-project via a path from top to bottom. 472 * @return void 473 */ 474 function print_project_option_list( $p_project_id = null, $p_include_all_projects = true, $p_filter_project_id = null, $p_trace = false ) { 475 $t_project_ids = current_user_get_accessible_projects(); 476 project_cache_array_rows( $t_project_ids ); 477 478 if( $p_include_all_projects ) { 479 echo '<option value="' . ALL_PROJECTS . '"'; 480 check_selected( $p_project_id, ALL_PROJECTS ); 481 echo '>' . lang_get( 'all_projects' ) . '</option>' . "\n"; 482 } 483 484 $t_project_count = count( $t_project_ids ); 485 for( $i = 0;$i < $t_project_count;$i++ ) { 486 $t_id = $t_project_ids[$i]; 487 if( $t_id != $p_filter_project_id ) { 488 echo '<option value="' . $t_id . '"'; 489 check_selected( $p_project_id, $t_id ); 490 echo '>' . string_attribute( project_get_field( $t_id, 'name' ) ) . '</option>' . "\n"; 491 print_subproject_option_list( $t_id, $p_project_id, $p_filter_project_id, $p_trace, Array() ); 492 } 493 } 494 } 495 496 # -------------------- 497 # List projects that the current user has access to 498 function print_subproject_option_list( $p_parent_id, $p_project_id = null, $p_filter_project_id = null, $p_trace = false, $p_parents = Array() ) { 499 array_push( $p_parents, $p_parent_id ); 500 $t_project_ids = current_user_get_accessible_subprojects( $p_parent_id ); 501 $t_project_count = count( $t_project_ids ); 502 for( $i = 0;$i < $t_project_count;$i++ ) { 503 $t_full_id = $t_id = $t_project_ids[$i]; 504 if( $t_id != $p_filter_project_id ) { 505 echo "<option value=\""; 506 if( $p_trace ) { 507 $t_full_id = join( $p_parents, ";" ) . ';' . $t_id; 508 } 509 echo $t_full_id . '"'; 510 check_selected( $p_project_id, $t_full_id ); 511 echo '>' . str_repeat( ' ', count( $p_parents ) ) . str_repeat( '»', count( $p_parents ) ) . ' ' . string_attribute( project_get_field( $t_id, 'name' ) ) . '</option>' . "\n"; 512 print_subproject_option_list( $t_id, $p_project_id, $p_filter_project_id, $p_trace, $p_parents ); 513 } 514 } 515 } 516 517 # -------------------- 518 # prints the profiles given the user id 519 function print_profile_option_list( $p_user_id, $p_select_id = '', $p_profiles = null ) { 520 if( '' === $p_select_id ) { 521 $p_select_id = profile_get_default( $p_user_id ); 522 } 523 if( $p_profiles != null ) { 524 $t_profiles = $p_profiles; 525 } else { 526 $t_profiles = profile_get_all_for_user( $p_user_id ); 527 } 528 print_profile_option_list_from_profiles( $t_profiles, $p_select_id ); 529 } 530 531 # -------------------- 532 # prints the profiles used in a certain project 533 function print_profile_option_list_for_project( $p_project_id, $p_select_id = '', $p_profiles = null ) { 534 if( '' === $p_select_id ) { 535 $p_select_id = profile_get_default( auth_get_current_user_id() ); 536 } 537 if( $p_profiles != null ) { 538 $t_profiles = $p_profiles; 539 } else { 540 $t_profiles = profile_get_all_for_project( $p_project_id ); 541 } 542 print_profile_option_list_from_profiles( $t_profiles, $p_select_id ); 543 } 544 545 # -------------------- 546 # print the profile option list from profiles array 547 function print_profile_option_list_from_profiles( $p_profiles, $p_select_id ) { 548 echo '<option value=""></option>'; 549 foreach( $p_profiles as $t_profile ) { 550 extract( $t_profile, EXTR_PREFIX_ALL, 'v' ); 551 552 $t_platform = string_attribute( $t_profile['platform'] ); 553 $t_os = string_attribute( $t_profile['os'] ); 554 $t_os_build = string_attribute( $t_profile['os_build'] ); 555 556 echo '<option value="' . $t_profile['id'] . '"'; 557 check_selected( $p_select_id, $t_profile['id'] ); 558 echo '>' . $t_platform . ' ' . $t_os . ' ' . $t_os_build . '</option>'; 559 } 560 } 561 562 # -------------------- 563 # Since categories can be orphaned we need to grab all unique instances of category 564 # We check in the project category table and in the bug table 565 # We put them all in one array and make sure the entries are unique 566 function print_category_option_list( $p_category_id = 0, $p_project_id = null ) { 567 $t_category_table = db_get_table( 'category' ); 568 $t_project_table = db_get_table( 'project' ); 569 570 if( null === $p_project_id ) { 571 $t_project_id = helper_get_current_project(); 572 } else { 573 $t_project_id = $p_project_id; 574 } 575 576 if( config_get( 'allow_no_category' ) ) { 577 echo "<option value=\"0\"", check_selected( $p_category_id, 0 ), '>'; 578 echo category_full_name( 0, /* show project */ false ), '</option>'; 579 } else { 580 if( 0 == $p_category_id ) { 581 echo "<option value=\"0\"", check_selected( $p_category_id, 0 ), '>'; 582 echo string_attribute( lang_get( 'select_option' ) ), '</option>'; 583 } 584 } 585 586 $cat_arr = category_get_all_rows( $t_project_id, /* inherit */ null, /* sortByProject */ true ); 587 588 foreach( $cat_arr as $t_category_row ) { 589 $t_category_id = $t_category_row['id']; 590 echo "<option value=\"$t_category_id\""; 591 check_selected( $p_category_id, $t_category_id ); 592 echo '>' . string_attribute( category_full_name( $t_category_id, $t_category_row['project_id'] != $t_project_id ) ) . '</option>'; 593 } 594 } 595 596 /** 597 * Now that categories are identified by numerical ID, we need an old-style name 598 * based option list to keep existing filter functionality. 599 * @param string $p_category_name The selected category 600 * @param mixed $p_project_id A specific project or null 601 */ 602 function print_category_filter_option_list( $p_category_name = '', $p_project_id = null ) { 603 $t_cat_arr = category_get_filter_list( $p_project_id ); 604 605 natcasesort( $t_cat_arr ); 606 foreach( $t_cat_arr as $t_cat ) { 607 $t_name = string_attribute( $t_cat ); 608 echo '<option value="' . $t_name . '"'; 609 check_selected( string_attribute( $p_category_name ), $t_name ); 610 echo '>' . $t_name . '</option>'; 611 } 612 } 613 614 # -------------------- 615 # Print the option list for platforms accessible for the specified user. 616 function print_platform_option_list( $p_platform, $p_user_id = null ) { 617 $t_platforms_array = profile_get_field_all_for_user( 'platform', $p_user_id ); 618 619 foreach( $t_platforms_array as $t_platform ) { 620 $t_platform = string_attribute( $t_platform ); 621 echo '<option value="' . $t_platform . '"'; 622 check_selected( string_attribute( $p_platform ), $t_platform ); 623 echo '>' . $t_platform . '</option>'; 624 } 625 } 626 627 # -------------------- 628 # Print the option list for OSes accessible for the specified user. 629 function print_os_option_list( $p_os, $p_user_id = null ) { 630 $t_os_array = profile_get_field_all_for_user( 'os', $p_user_id ); 631 632 foreach( $t_os_array as $t_os ) { 633 $t_os = string_attribute( $t_os ); 634 echo '<option value="' . $t_os . '"'; 635 check_selected( string_attribute( $p_os ), $t_os ); 636 echo '>' . $t_os . '</option>'; 637 } 638 } 639 640 # Print the option list for os_build accessible for the specified user. 641 function print_os_build_option_list( $p_os_build, $p_user_id = null ) { 642 $t_os_build_array = profile_get_field_all_for_user( 'os_build', $p_user_id ); 643 644 foreach( $t_os_build_array as $t_os_build ) { 645 $t_os_build = string_attribute( $t_os_build ); 646 echo '<option value="' . $t_os_build . '"'; 647 check_selected( string_attribute( $p_os_build ), $t_os_build ); 648 echo '>' . $t_os_build . '</option>'; 649 } 650 } 651 652 # Print the option list for versions 653 # $p_version = currently selected version. 654 # $p_project_id = project id, otherwise current project will be used. 655 # $p_released = null to get all, 1: only released, 0: only future versions 656 # $p_leading_black = allow selection of no version 657 # $p_with_subs = include subprojects 658 function print_version_option_list( $p_version = '', $p_project_id = null, $p_released = null, $p_leading_blank = true, $p_with_subs = false ) { 659 if( null === $p_project_id ) { 660 $c_project_id = helper_get_current_project(); 661 } else { 662 $c_project_id = db_prepare_int( $p_project_id ); 663 } 664 665 if( $p_with_subs ) { 666 $versions = version_get_all_rows_with_subs( $c_project_id, $p_released, 667 /* obsolete */ 668 null ); 669 } else { 670 $versions = version_get_all_rows( $c_project_id, $p_released, 671 /* obsolete */ 672 null ); 673 } 674 675 if( $p_leading_blank ) { 676 echo '<option value=""></option>'; 677 } 678 679 $t_listed = array(); 680 $t_max_length = config_get( 'max_dropdown_length' ); 681 $t_show_version_dates = access_has_project_level( config_get( 'show_version_dates_threshold' ) ); 682 $t_short_date_format = config_get( 'short_date_format' ); 683 684 foreach( $versions as $version ) { 685 # If the current version is obsolete, and current version not equal to $p_version, 686 # then skip it. 687 if(( (int) $version['obsolete'] ) == 1 ) { 688 if( $version['version'] != $p_version ) { 689 continue; 690 } 691 } 692 693 $t_version = string_attribute( $version['version'] ); 694 695 if ( !in_array( $t_version, $t_listed ) ) { 696 $t_listed[] = $t_version; 697 echo '<option value="' . $t_version . '"'; 698 check_selected( string_attribute( $p_version ), $t_version ); 699 700 $t_version_string = string_attribute( prepare_version_string( $c_project_id, $version['id'] ) ); 701 702 echo '>', string_shorten( $t_version_string , $t_max_length ), '</option>'; 703 } 704 } 705 } 706 707 function print_build_option_list( $p_build = '' ) { 708 $t_bug_table = db_get_table( 'bug' ); 709 $t_overall_build_arr = array(); 710 711 $t_project_id = helper_get_current_project(); 712 713 $t_project_where = helper_project_specific_where( $t_project_id ); 714 715 # Get the "found in" build list 716 $query = "SELECT DISTINCT build 717 FROM $t_bug_table 718 WHERE $t_project_where 719 ORDER BY build DESC"; 720 $result = db_query_bound( $query ); 721 $option_count = db_num_rows( $result ); 722 723 for( $i = 0;$i < $option_count;$i++ ) { 724 $row = db_fetch_array( $result ); 725 $t_overall_build_arr[] = $row['build']; 726 } 727 728 $t_max_length = config_get( 'max_dropdown_length' ); 729 730 foreach( $t_overall_build_arr as $t_build ) { 731 $t_build = string_attribute( $t_build ); 732 echo "<option value=\"$t_build\""; 733 check_selected( string_attribute( $p_build ), $t_build ); 734 echo ">" . string_shorten( $t_build, $t_max_length ) . "</option>"; 735 } 736 } 737 738 # select the proper enum values based on the input parameter 739 # $p_enum_name - name of enumeration (eg: status) 740 # $p_val: current value 741 function print_enum_string_option_list( $p_enum_name, $p_val = 0 ) { 742 $t_config_var_name = $p_enum_name . '_enum_string'; 743 $t_config_var_value = config_get( $t_config_var_name ); 744 745 $t_enum_values = MantisEnum::getValues( $t_config_var_value ); 746 747 foreach ( $t_enum_values as $t_key ) { 748 $t_elem2 = get_enum_element( $p_enum_name, $t_key ); 749 750 echo '<option value="' . $t_key . '"'; 751 check_selected( $p_val, $t_key ); 752 echo '>' . string_html_specialchars( $t_elem2 ) . '</option>'; 753 } 754 } 755 756 # Select the proper enum values for status based on workflow 757 # or the input parameter if workflows are not used 758 # $p_enum_name : name of enumeration (eg: status) 759 # $p_current_value : current value 760 function get_status_option_list( $p_user_auth = 0, $p_current_value = 0, $p_show_current = true, $p_add_close = false, $p_project_id = ALL_PROJECTS ) { 761 $t_config_var_value = config_get( 'status_enum_string', null, null, $p_project_id ); 762 $t_enum_workflow = config_get( 'status_enum_workflow', null, null, $p_project_id ); 763 764 if( count( $t_enum_workflow ) < 1 ) { 765 # workflow not defined, use default enum 766 $t_enum_values = MantisEnum::getValues( $t_config_var_value ); 767 } else { 768 # workflow defined - find allowed states 769 if( isset( $t_enum_workflow[$p_current_value] ) ) { 770 $t_enum_values = MantisEnum::getValues( $t_enum_workflow[$p_current_value] ); 771 } else { 772 # workflow was not set for this status, this shouldn't happen 773 $t_enum_values = MantisEnum::getValues( $t_config_var_value ); 774 } 775 } 776 777 $t_enum_list = array(); 778 779 foreach ( $t_enum_values as $t_enum_value ) { 780 if ( ( access_compare_level( $p_user_auth, access_get_status_threshold( $t_enum_value, $p_project_id ) ) ) 781 && ( !(( false == $p_show_current ) && ( $p_current_value == $t_enum_value ) ) ) ) { 782 $t_enum_list[$t_enum_value] = get_enum_element( 'status', $t_enum_value ); 783 } 784 } 785 786 if ( $p_show_current ) { 787 $t_enum_list[$p_current_value] = get_enum_element( 'status', $p_current_value ); 788 } 789 790 if ( $p_add_close && access_compare_level( $p_current_value, config_get( 'bug_resolved_status_threshold', null, null, $p_project_id ) ) ) { 791 $t_closed = config_get( 'bug_closed_status_threshold', null, null, $p_project_id ); 792 $t_enum_list[$t_closed] = get_enum_element( 'status', $t_closed ); 793 } 794 795 return $t_enum_list; 796 } 797 798 # print the status option list for the bug_update pages 799 function print_status_option_list( $p_select_label, $p_current_value = 0, $p_allow_close = false, $p_project_id = ALL_PROJECTS ) { 800 $t_current_auth = access_get_project_level( $p_project_id ); 801 802 $t_enum_list = get_status_option_list( $t_current_auth, $p_current_value, true, $p_allow_close, $p_project_id ); 803 804 if( count( $t_enum_list ) > 1 ) { 805 806 # resort the list into ascending order 807 ksort( $t_enum_list ); 808 reset( $t_enum_list ); 809 echo '<select ' . helper_get_tab_index() . ' id="' . $p_select_label . '" name="' . $p_select_label . '">'; 810 foreach( $t_enum_list as $key => $val ) { 811 echo '<option value="' . $key . '"'; 812 check_selected( $key, $p_current_value ); 813 echo '>' . string_html_specialchars( $val ) . '</option>'; 814 } 815 echo '</select>'; 816 } else if ( count( $t_enum_list ) == 1 ) { 817 echo array_pop( $t_enum_list ); 818 } else { 819 echo MantisEnum::getLabel( lang_get( 'status_enum_string' ), $p_current_value ); 820 } 821 } 822 823 # prints the list of a project's users 824 # if no project is specified uses the current project 825 function print_project_user_option_list( $p_project_id = null ) { 826 print_user_option_list( 0, $p_project_id ); 827 } 828 829 # prints the list of access levels that are less than or equal to the access level of the 830 # logged in user. This is used when adding users to projects 831 function print_project_access_levels_option_list( $p_val, $p_project_id = null ) { 832 $t_current_user_access_level = access_get_project_level( $p_project_id ); 833 $t_access_levels_enum_string = config_get( 'access_levels_enum_string' ); 834 $t_enum_values = MantisEnum::getValues( $t_access_levels_enum_string ); 835 foreach ( $t_enum_values as $t_enum_value ) { 836 # a user must not be able to assign another user an access level that is higher than theirs. 837 if ( $t_enum_value > $t_current_user_access_level ) { 838 continue; 839 } 840 $t_access_level = get_enum_element( 'access_levels', $t_enum_value ); 841 echo '<option value="' . $t_enum_value . '"'; 842 check_selected( $p_val, $t_enum_value ); 843 echo '>' . string_html_specialchars( $t_access_level ) . '</option>'; 844 } 845 } 846 847 function print_language_option_list( $p_language ) { 848 $t_arr = config_get( 'language_choices_arr' ); 849 $enum_count = count( $t_arr ); 850 for( $i = 0;$i < $enum_count;$i++ ) { 851 $t_language = string_attribute( $t_arr[$i] ); 852 echo '<option value="' . $t_language . '"'; 853 check_selected( $t_language, $p_language ); 854 echo '>' . $t_language . '</option>'; 855 } 856 } 857 858 /** 859 * Print a dropdown list of all bug actions available to a user for a specified 860 * set of projects. 861 * @param array $p_projects An array containing one or more project IDs 862 * @return null 863 */ 864 function print_all_bug_action_option_list( $p_project_ids = null ) { 865 $t_commands = bug_group_action_get_commands( $p_project_ids ); 866 while( list( $t_action_id, $t_action_label ) = each( $t_commands ) ) { 867 echo '<option value="' . $t_action_id . '">' . $t_action_label . '</option>'; 868 } 869 } 870 871 # -------------------- 872 # list of users that are NOT in the specified project and that are enabled 873 # if no project is specified use the current project 874 # also exclude any administrators 875 function print_project_user_list_option_list( $p_project_id = null ) { 876 $t_users = user_get_unassigned_by_project_id( $p_project_id ); 877 foreach( $t_users AS $t_id=>$t_name ) { 878 echo '<option value="' . $t_id . '">' . $t_name . '</option>'; 879 } 880 } 881 882 # list of projects that a user is NOT in 883 function print_project_user_list_option_list2( $p_user_id ) { 884 $t_mantis_project_user_list_table = db_get_table( 'project_user_list' ); 885 $t_mantis_project_table = db_get_table( 'project' ); 886 887 $c_user_id = db_prepare_int( $p_user_id ); 888 889 $query = "SELECT DISTINCT p.id, p.name 890 FROM $t_mantis_project_table p 891 LEFT JOIN $t_mantis_project_user_list_table u 892 ON p.id=u.project_id AND u.user_id=" . db_param() . " 893 WHERE p.enabled = " . db_param() . " AND 894 u.user_id IS NULL 895 ORDER BY p.name"; 896 $result = db_query_bound( $query, Array( $c_user_id, true ) ); 897 $category_count = db_num_rows( $result ); 898 for( $i = 0;$i < $category_count;$i++ ) { 899 $row = db_fetch_array( $result ); 900 $t_project_name = string_attribute( $row['name'] ); 901 $t_user_id = $row['id']; 902 echo "<option value=\"$t_user_id\">$t_project_name</option>"; 903 } 904 } 905 906 # list of projects that a user is in 907 function print_project_user_list( $p_user_id, $p_include_remove_link = true ) { 908 $t_projects = user_get_assigned_projects( $p_user_id ); 909 910 foreach( $t_projects AS $t_project_id=>$t_project ) { 911 $t_project_name = string_attribute( $t_project['name'] ); 912 $t_view_state = $t_project['view_state']; 913 $t_access_level = $t_project['access_level']; 914 $t_access_level = get_enum_element( 'access_levels', $t_access_level ); 915 $t_view_state = get_enum_element( 'project_view_state', $t_view_state ); 916 917 echo $t_project_name . ' [' . $t_access_level . '] (' . $t_view_state . ')'; 918 if( $p_include_remove_link && access_has_project_level( config_get( 'project_user_threshold' ), $t_project_id ) ) { 919 html_button( 'manage_user_proj_delete.php', lang_get( 'remove_link' ), array( 'project_id' => $t_project_id, 'user_id' => $p_user_id ) ); 920 } 921 echo '<br />'; 922 } 923 } 924 925 # List of projects with which the specified field id is linked. 926 # For every project, the project name is listed and then the list of custom 927 # fields linked in order with their sequence numbers. The specified field 928 # is always highlighted in italics and project names in bold. 929 # 930 # $p_field_id - The field to list the projects associated with. 931 function print_custom_field_projects_list( $p_field_id ) { 932 $c_field_id = (integer) $p_field_id; 933 $t_project_ids = custom_field_get_project_ids( $p_field_id ); 934 935 $t_security_token = form_security_param( 'manage_proj_custom_field_remove' ); 936 937 foreach( $t_project_ids as $t_project_id ) { 938 $t_project_name = project_get_field( $t_project_id, 'name' ); 939 $t_sequence = custom_field_get_sequence( $p_field_id, $t_project_id ); 940 echo '<strong>', string_display_line( $t_project_name ), '</strong>: '; 941 print_bracket_link( "manage_proj_custom_field_remove.php?field_id=$c_field_id&project_id=$t_project_id&return=custom_field$t_security_token", lang_get( 'remove_link' ) ); 942 echo '<br />- '; 943 944 $t_linked_field_ids = custom_field_get_linked_ids( $t_project_id ); 945 946 $t_current_project_fields = array(); 947 948 $t_first = true; 949 foreach( $t_linked_field_ids as $t_current_field_id ) { 950 if( $t_first ) { 951 $t_first = false; 952 } else { 953 echo ', '; 954 } 955 956 if( $t_current_field_id == $p_field_id ) { 957 echo '<em>'; 958 } 959 960 echo string_display_line( custom_field_get_field( $t_current_field_id, 'name' ) ); 961 echo ' (', custom_field_get_sequence( $t_current_field_id, $t_project_id ), ')'; 962 963 if( $t_current_field_id == $p_field_id ) { 964 echo '</em>'; 965 } 966 } 967 968 echo '<br /><br />'; 969 } 970 } 971 972 /** 973 * List of priorities that can be assigned to a plugin. 974 * @param int current priority 975 */ 976 function print_plugin_priority_list( $p_priority ) { 977 if( $p_priority < 1 && $p_priority > 5 ) { 978 echo '<option value="', $p_priority, '" selected="selected">', $p_priority, '</option>'; 979 } 980 981 for( $i = 5;$i >= 1;$i-- ) { 982 echo '<option value="', $i, '" ', check_selected( $p_priority, $i ), ' >', $i, '</option>'; 983 } 984 } 985 986 # ########################################################################## 987 # String printing API 988 # ########################################################################## 989 990 # prints a link to VIEW a bug given an ID 991 # account for the user preference and site override 992 function print_bug_link( $p_bug_id, $p_detail_info = true ) { 993 echo string_get_bug_view_link( $p_bug_id, null, $p_detail_info ); 994 } 995 996 # formats the priority given the status 997 # shows the priority in BOLD if the bug is NOT closed and is of significant priority 998 function print_formatted_priority_string( $p_status, $p_priority ) { 999 $t_pri_str = get_enum_element( 'priority', $p_priority ); 1000 $t_priority_threshold = config_get( 'priority_significant_threshold' ); 1001 1002 if( $t_priority_threshold >= 0 && 1003 $p_priority >= $t_priority_threshold && 1004 $p_status < config_get( 'bug_closed_status_threshold' ) ) { 1005 echo "<span class=\"bold\">$t_pri_str</span>"; 1006 } else { 1007 echo $t_pri_str; 1008 } 1009 } 1010 1011 # formats the severity given the status 1012 # shows the severity in BOLD if the bug is NOT closed and is of significant severity 1013 function print_formatted_severity_string( $p_status, $p_severity ) { 1014 $t_sev_str = get_enum_element( 'severity', $p_severity ); 1015 $t_severity_threshold = config_get( 'severity_significant_threshold' ); 1016 1017 if( $t_severity_threshold >= 0 && 1018 $p_severity >= $t_severity_threshold && 1019 $p_status < config_get( 'bug_closed_status_threshold' ) ) { 1020 echo "<span class=\"bold\">$t_sev_str</span>"; 1021 } else { 1022 echo $t_sev_str; 1023 } 1024 } 1025 1026 # ########################################################################## 1027 # Link Printing API 1028 # ########################################################################## 1029 1030 # $p_columns_target: see COLUMNS_TARGET_* in constant_inc.php 1031 function print_view_bug_sort_link( $p_string, $p_sort_field, $p_sort, $p_dir, $p_columns_target = COLUMNS_TARGET_VIEW_PAGE ) { 1032 if( $p_columns_target == COLUMNS_TARGET_PRINT_PAGE ) { 1033 if( $p_sort_field == $p_sort ) { 1034 # We toggle between ASC and DESC if the user clicks the same sort order 1035 if( 'ASC' == $p_dir ) { 1036 $p_dir = 'DESC'; 1037 } else { 1038 $p_dir = 'ASC'; 1039 } 1040 } else { 1041 # Otherwise always start with ASCending 1042 $t_dir = 'ASC'; 1043 } 1044 1045 $t_sort_field = rawurlencode( $p_sort_field ); 1046 print_link( "view_all_set.php?sort=$t_sort_field&dir=$p_dir&type=2&print=1", $p_string ); 1047 } 1048 else if( $p_columns_target == COLUMNS_TARGET_VIEW_PAGE ) { 1049 if( $p_sort_field == $p_sort ) { 1050 1051 # we toggle between ASC and DESC if the user clicks the same sort order 1052 if( 'ASC' == $p_dir ) { 1053 $p_dir = 'DESC'; 1054 } else { 1055 $p_dir = 'ASC'; 1056 } 1057 } else { 1058 # Otherwise always start with ASCending 1059 $t_dir = 'ASC'; 1060 } 1061 1062 $t_sort_field = rawurlencode( $p_sort_field ); 1063 print_link( "view_all_set.php?sort=$t_sort_field&dir=$p_dir&type=2", $p_string ); 1064 } else { 1065 echo $p_string; 1066 } 1067 } 1068 1069 function print_manage_user_sort_link( $p_page, $p_string, $p_field, $p_dir, $p_sort_by, $p_hide = 0, $p_filter = ALL ) { 1070 if( $p_sort_by == $p_field ) { 1071 1072 # If this is the selected field flip the order 1073 if( 'ASC' == $p_dir || ASCENDING == $p_dir ) { 1074 $t_dir = 'DESC'; 1075 } else { 1076 $t_dir = 'ASC'; 1077 } 1078 } else { 1079 # Otherwise always start with ASCending 1080 $t_dir = 'ASC'; 1081 } 1082 1083 $t_field = rawurlencode( $p_field ); 1084 print_link( "$p_page?sort=$t_field&dir=$t_dir&save=1&hide=$p_hide&filter=$p_filter", $p_string ); 1085 } 1086 1087 function print_manage_project_sort_link( $p_page, $p_string, $p_field, $p_dir, $p_sort_by ) { 1088 if( $p_sort_by == $p_field ) { 1089 1090 # If this is the selected field flip the order 1091 if( 'ASC' == $p_dir || ASCENDING == $p_dir ) { 1092 $t_dir = 'DESC'; 1093 } else { 1094 $t_dir = 'ASC'; 1095 } 1096 } else { 1097 # Otherwise always start with ASCending 1098 $t_dir = 'ASC'; 1099 } 1100 1101 $t_field = rawurlencode( $p_field ); 1102 print_link( "$p_page?sort=$t_field&dir=$t_dir", $p_string ); 1103 } 1104 1105 # print a button which presents a standalone form. 1106 # $p_action_page - The action page 1107 # $p_label - The button label 1108 # $p_args_to_post - An associative array with key => value to be posted, can be null. 1109 function print_button( $p_action_page, $p_label, $p_args_to_post = null ) { 1110 $t_form_name = explode( '.php', $p_action_page, 2 ); 1111 # TODO: ensure all uses of print_button supply arguments via $p_args_to_post (POST) 1112 # instead of via $p_action_page (GET). Then only add the CSRF form token if 1113 # arguments are being sent via the POST method. 1114 echo '<form method="post" action="', htmlspecialchars( $p_action_page ), '" class="action-button">'; 1115 echo '<fieldset>'; 1116 echo form_security_field( $t_form_name[0] ); 1117 echo '<input type="submit" class="button-small" value="', $p_label, '" />'; 1118 1119 if( $p_args_to_post !== null ) { 1120 foreach( $p_args_to_post as $t_var => $t_value ) { 1121 echo "<input type=\"hidden\" name=\"$t_var\" value=\"$t_value\" />"; 1122 } 1123 } 1124 1125 echo '</fieldset>'; 1126 echo '</form>'; 1127 } 1128 1129 # print brackets around a pre-prepared link (i.e. '<a href' html tag). 1130 function print_bracket_link_prepared( $p_link ) { 1131 echo '<span class="bracket-link">[ ' . $p_link . ' ]</span> '; 1132 } 1133 1134 # print the bracketed links used near the top 1135 # if the $p_link is blank then the text is printed but no link is created 1136 # if $p_new_window is true, link will open in a new window, default false. 1137 function print_bracket_link( $p_link, $p_url_text, $p_new_window = false, $p_class = '' ) { 1138 echo '<span class="bracket-link'; 1139 if ($p_class !== '') { 1140 echo ' bracket-link-',$p_class; # prefix on a container allows styling of whole link, including brackets 1141 } 1142 echo '">[ '; 1143 print_link( $p_link, $p_url_text, $p_new_window, $p_class ); 1144 echo ' ]</span> '; 1145 } 1146 1147 # print a HTML link 1148 function print_link( $p_link, $p_url_text, $p_new_window = false, $p_class = '' ) { 1149 if( is_blank( $p_link ) ) { 1150 echo $p_url_text; 1151 } else { 1152 $t_link = htmlspecialchars( $p_link ); 1153 if( $p_new_window === true ) { 1154 echo "<a class=\"new-window $p_class\" href=\"$t_link\" target=\"_blank\">$p_url_text</a>"; 1155 } else { 1156 if( $p_class !== '') { 1157 echo "<a class=\"$p_class\" href=\"$t_link\">$p_url_text</a>"; 1158 } else { 1159 echo "<a href=\"$t_link\">$p_url_text</a>"; 1160 } 1161 } 1162 } 1163 } 1164 1165 # print a HTML page link 1166 function print_page_link( $p_page_url, $p_text = '', $p_page_no = 0, $p_page_cur = 0, $p_temp_filter_id = 0 ) { 1167 if( is_blank( $p_text ) ) { 1168 $p_text = $p_page_no; 1169 } 1170 1171 if( ( 0 < $p_page_no ) && ( $p_page_no != $p_page_cur ) ) { 1172 $t_delimiter = ( strpos( $p_page_url, "?" ) ? "&" : "?" ); 1173 if( $p_temp_filter_id !== 0 ) { 1174 print_link( "$p_page_url$t_delimiter}filter=$p_temp_filter_id&page_number=$p_page_no", $p_text ); 1175 } else { 1176 print_link( "$p_page_url$t_delimiter}page_number=$p_page_no", $p_text ); 1177 } 1178 } else { 1179 echo $p_text; 1180 } 1181 } 1182 1183 # print a list of page number links (eg [1 2 3]) 1184 function print_page_links( $p_page, $p_start, $p_end, $p_current, $p_temp_filter_id = 0 ) { 1185 $t_items = array(); 1186 $t_link = ''; 1187 1188 # Check if we have more than one page, 1189 # otherwise return without doing anything. 1190 1191 if( $p_end - $p_start < 1 ) { 1192 return; 1193 } 1194 1195 # Get localized strings 1196 $t_first = lang_get( 'first' ); 1197 $t_last = lang_get( 'last' ); 1198 $t_prev = lang_get( 'prev' ); 1199 $t_next = lang_get( 'next' ); 1200 1201 $t_page_links = 10; 1202 1203 print( "[ " ); 1204 1205 # First and previous links 1206 print_page_link( $p_page, $t_first, 1, $p_current, $p_temp_filter_id ); 1207 echo ' '; 1208 print_page_link( $p_page, $t_prev, $p_current - 1, $p_current, $p_temp_filter_id ); 1209 echo ' '; 1210 1211 # Page numbers ... 1212 1213 $t_first_page = max( $p_start, $p_current - $t_page_links / 2 ); 1214 $t_first_page = min( $t_first_page, $p_end - $t_page_links ); 1215 $t_first_page = max( $t_first_page, $p_start ); 1216 1217 if( $t_first_page > 1 ) { 1218 print( " ... " ); 1219 } 1220 1221 $t_last_page = $t_first_page + $t_page_links; 1222 $t_last_page = min( $t_last_page, $p_end ); 1223 1224 for( $i = $t_first_page;$i <= $t_last_page;$i++ ) { 1225 if( $i == $p_current ) { 1226 array_push( $t_items, $i ); 1227 } else { 1228 $t_delimiter = ( strpos( $p_page, "?" ) ? "&" : "?" ) ; 1229 if( $p_temp_filter_id !== 0 ) { 1230 array_push( $t_items, "<a href=\"$p_page$t_delimiter}filter=$p_temp_filter_id&page_number=$i\">$i</a>" ); 1231 } else { 1232 array_push( $t_items, "<a href=\"$p_page$t_delimiter}page_number=$i\">$i</a>" ); 1233 } 1234 } 1235 } 1236 echo implode( ' ', $t_items ); 1237 1238 if( $t_last_page < $p_end ) { 1239 print( ' ... ' ); 1240 } 1241 1242 # Next and Last links 1243 echo ' '; 1244 if( $p_current < $p_end ) { 1245 print_page_link( $p_page, $t_next, $p_current + 1, $p_current, $p_temp_filter_id ); 1246 } else { 1247 print_page_link( $p_page, $t_next, null, null, $p_temp_filter_id ); 1248 } 1249 echo ' '; 1250 print_page_link( $p_page, $t_last, $p_end, $p_current, $p_temp_filter_id ); 1251 1252 print( ' ]' ); 1253 } 1254 1255 # print a mailto: href link 1256 function print_email_link( $p_email, $p_text ) { 1257 echo get_email_link( $p_email, $p_text ); 1258 } 1259 1260 # return the mailto: href string link instead of printing it 1261 function get_email_link( $p_email, $p_text ) { 1262 return prepare_email_link( $p_email, $p_text ); 1263 } 1264 1265 # print a mailto: href link with subject 1266 function print_email_link_with_subject( $p_email, $p_text, $p_bug_id ) { 1267 $t_subject = email_build_subject( $p_bug_id ); 1268 echo get_email_link_with_subject( $p_email, $p_text, $t_subject ); 1269 } 1270 1271 # return the mailto: href string link instead of printing it 1272 # add subject line 1273 function get_email_link_with_subject( $p_email, $p_text, $p_summary ) { 1274 if( !access_has_project_level( config_get( 'show_user_email_threshold' ) ) ) { 1275 return $p_text; 1276 } 1277 1278 # If we apply string_url() to the whole mailto: link then the @ 1279 # gets turned into a %40 and you can't right click in browsers to 1280 # do Copy Email Address. If we don't apply string_url() to the 1281 # summary text then an ampersand (for example) will truncate the text 1282 $t_summary = string_url( $p_summary ); 1283 $t_email = string_url( $p_email ); 1284 $t_mailto = string_attribute( "mailto:$t_email?subject=$t_summary" ); 1285 $t_text = string_display( $p_text ); 1286 1287 return "<a href=\"$t_mailto\">$t_text</a>"; 1288 } 1289 1290 # Print a hidden input for each name=>value pair in the array 1291 # 1292 # If a value is an array an input will be created for each item with a name 1293 # that ends with [] 1294 # The names and values are passed through htmlspecialchars() before being displayed 1295 function print_hidden_inputs( $p_assoc_array ) { 1296 foreach( $p_assoc_array as $t_key => $t_val ) { 1297 print_hidden_input( $t_key, $t_val ); 1298 } 1299 } 1300 1301 function print_hidden_input( $p_field_key, $p_field_val ) { 1302 if( is_array( $p_field_val ) ) { 1303 foreach( $p_field_val AS $t_key => $t_value ) { 1304 if( is_array( $t_value ) ) { 1305 $t_key = string_html_entities( $t_key ); 1306 $t_field_key = $p_field_key . '[' . $t_key . ']'; 1307 print_hidden_input( $t_field_key, $t_value ); 1308 } else { 1309 $t_field_key = $p_field_key . '[' . $t_key . ']'; 1310 print_hidden_input( $t_field_key, $t_value ); 1311 } 1312 } 1313 } else { 1314 $t_key = string_html_entities( $p_field_key ); 1315 $t_val = string_html_entities( $p_field_val ); 1316 echo "<input type=\"hidden\" name=\"$t_key\" value=\"$t_val\" />\n"; 1317 } 1318 } 1319 1320 # ============================= 1321 # Functions that used to be in html_api 1322 # ============================= 1323 1324 # This prints the little [?] link for user help 1325 # The $p_a_name is a link into the documentation.html file 1326 function print_documentation_link( $p_a_name = '' ) { 1327 echo lang_get( $p_a_name ) . "\n"; 1328 # @@@ Disable documentation links for now. May be re-enabled if linked to new manual. 1329 # echo "<a href=\"doc/documentation.html#$p_a_name\" target=\"_info\">[?]</a>"; 1330 } 1331 1332 # prints the signup link 1333 function print_signup_link() { 1334 if ( ( ON == config_get_global( 'allow_signup' ) ) && 1335 ( LDAP != config_get_global( 'login_method' ) ) && 1336 ( ON == config_get( 'enable_email_notification' ) ) 1337 ) { 1338 print_bracket_link( 'signup_page.php', lang_get( 'signup_link' ) ); 1339 } 1340 } 1341 1342 # prints the login link 1343 function print_login_link() { 1344 print_bracket_link( 'login_page.php', lang_get( 'login_title' ) ); 1345 } 1346 1347 # prints the lost pwd link 1348 function print_lost_password_link() { 1349 # lost password feature disabled or reset password via email disabled -> stop here! 1350 if ( ( LDAP != config_get_global( 'login_method' ) ) && 1351 ( ON == config_get( 'lost_password_feature' ) ) && 1352 ( ON == config_get( 'send_reset_password' ) ) && 1353 ( ON == config_get( 'enable_email_notification' ) ) ) { 1354 print_bracket_link( 'lost_pwd_page.php', lang_get( 'lost_password_link' ) ); 1355 } 1356 } 1357 1358 # =============================== 1359 # Deprecated Functions 1360 # =============================== 1361 1362 # Get icon corresponding to the specified filename 1363 function print_file_icon( $p_filename ) { 1364 $t_icon = file_get_icon_url( $p_filename ); 1365 echo '<img src="' . string_attribute( $t_icon['url'] ) . '" alt="' . string_attribute( $t_icon['alt'] ) . ' file icon" width="16" height="16" />'; 1366 } 1367 1368 # Prints an RSS image that is hyperlinked to an RSS feed. 1369 function print_rss( $p_feed_url, $p_title = '' ) { 1370 $t_path = config_get( 'path' ); 1371 echo '<a class="rss" rel="alternate" href="', htmlspecialchars( $p_feed_url ), '" title="', $p_title, '"><img src="', $t_path, '/images/', 'rss.png" width="16" height="16" alt="', $p_title, '" /></a>'; 1372 } 1373 1374 # Prints the recently visited issues. 1375 function print_recently_visited() { 1376 if( !last_visited_enabled() ) { 1377 return; 1378 } 1379 1380 $t_ids = last_visited_get_array(); 1381 1382 if( count( $t_ids ) == 0 ) { 1383 return; 1384 } 1385 1386 echo '<div class="recently-visited">' . lang_get( 'recently_visited' ) . ': '; 1387 $t_first = true; 1388 1389 foreach( $t_ids as $t_id ) { 1390 if( !$t_first ) { 1391 echo ', '; 1392 } else { 1393 $t_first = false; 1394 } 1395 1396 echo string_get_bug_view_link( $t_id ); 1397 } 1398 echo '</div>'; 1399 } 1400 1401 # print a dropdown box from input array 1402 function get_dropdown( $p_control_array, $p_control_name, $p_match = '', $p_add_any = false, $p_multiple = false ) { 1403 $t_control_array = $p_control_array; 1404 if( $p_multiple ) { 1405 $t_size = ' size="5"'; 1406 $t_multiple = ' multiple="multiple"'; 1407 } else { 1408 $t_size = ''; 1409 $t_multiple = ''; 1410 } 1411 $t_info = sprintf( "<select %s name=\"%s\" id=\"%s\"%s>", $t_multiple, $p_control_name, $p_control_name, $t_size ); 1412 if( $p_add_any ) { 1413 array_unshift_assoc( $t_control_array, META_FILTER_ANY, lang_trans( '[any]' ) ); 1414 } 1415 while( list( $t_name, $t_desc ) = each( $t_control_array ) ) { 1416 $t_sel = ''; 1417 if( is_array( $p_match ) ) { 1418 if( in_array( $t_name, array_values( $p_match ) ) || in_array( $t_desc, array_values( $p_match ) ) ) { 1419 $t_sel = ' selected="selected"'; 1420 } 1421 } else { 1422 if(( $t_name === $p_match ) || ( $t_desc === $p_match ) ) { 1423 $t_sel = ' selected="selected"'; 1424 } 1425 } 1426 $t_info .= sprintf( "<option%s value=\"%s\">%s</option>", $t_sel, $t_name, $t_desc ); 1427 } 1428 $t_info .= "</select>\n"; 1429 return $t_info; 1430 } 1431 1432 /** 1433 * Prints the list of visible attachments belonging to a given bug. 1434 * @param int $p_bug_id ID of the bug to print attachments list for 1435 */ 1436 function print_bug_attachments_list( $p_bug_id ) { 1437 $t_attachments = file_get_visible_attachments( $p_bug_id ); 1438 $t_attachments_count = count( $t_attachments ); 1439 echo "\n<ul>"; 1440 foreach ( $t_attachments as $t_attachment ) { 1441 echo "\n<li>"; 1442 print_bug_attachment( $t_attachment ); 1443 echo "\n</li>"; 1444 } 1445 echo "\n</ul>"; 1446 } 1447 1448 /** 1449 * Prints information about a single attachment including download link, file 1450 * size, upload timestamp and an expandable preview for text and image file 1451 * types. 1452 * @param array $p_attachment An attachment arrray from within the array returned by the file_get_visible_attachments() function 1453 */ 1454 function print_bug_attachment( $p_attachment ) { 1455 $t_show_attachment_preview = $p_attachment['preview'] && $p_attachment['exists'] && ( $p_attachment['type'] == 'text' || $p_attachment['type'] == 'image' ); 1456 if ( $t_show_attachment_preview ) { 1457 $t_collapse_id = 'attachment_preview_' . $p_attachment['id']; 1458 global $g_collapse_cache_token; 1459 $g_collapse_cache_token[$t_collapse_id] = false; 1460 collapse_open( $t_collapse_id ); 1461 } 1462 print_bug_attachment_header( $p_attachment ); 1463 if ( $t_show_attachment_preview ) { 1464 echo lang_get( 'word_separator' ); 1465 collapse_icon( $t_collapse_id ); 1466 if ( $p_attachment['type'] == 'text' ) { 1467 print_bug_attachment_preview_text( $p_attachment ); 1468 } else if ( $p_attachment['type'] === 'image' ) { 1469 print_bug_attachment_preview_image( $p_attachment ); 1470 } 1471 collapse_closed( $t_collapse_id ); 1472 print_bug_attachment_header( $p_attachment ); 1473 echo lang_get( 'word_separator' ); 1474 collapse_icon( $t_collapse_id ); 1475 collapse_end( $t_collapse_id ); 1476 } 1477 } 1478 1479 /** 1480 * Prints a single textual line of information about an attachment including download link, file 1481 * size and upload timestamp. 1482 * @param array $p_attachment An attachment arrray from within the array returned by the file_get_visible_attachments() function 1483 */ 1484 function print_bug_attachment_header( $p_attachment ) { 1485 echo "\n"; 1486 if ( $p_attachment['exists'] ) { 1487 if ( $p_attachment['can_download'] ) { 1488 echo '<a href="' . string_attribute( $p_attachment['download_url'] ) . '">'; 1489 } 1490 print_file_icon( $p_attachment['display_name'] ); 1491 if ( $p_attachment['can_download'] ) { 1492 echo '</a>'; 1493 } 1494 echo lang_get( 'word_separator' ); 1495 if ( $p_attachment['can_download'] ) { 1496 echo '<a href="' . string_attribute( $p_attachment['download_url'] ) . '">'; 1497 } 1498 echo string_display_line( $p_attachment['display_name'] ); 1499 if ( $p_attachment['can_download'] ) { 1500 echo '</a>'; 1501 } 1502 echo lang_get( 'word_separator' ) . '(' . number_format( $p_attachment['size'] ) . lang_get( 'word_separator' ) . lang_get( 'bytes' ) . ')'; 1503 echo lang_get( 'word_separator' ) . '<span class="italic">' . date( config_get( 'normal_date_format' ), $p_attachment['date_added'] ) . '</span>'; 1504 if ( $p_attachment['can_delete'] ) { 1505 echo lang_get( 'word_separator' ) . '['; 1506 print_link( 'bug_file_delete.php?file_id=' . $p_attachment['id'] . form_security_param( 'bug_file_delete' ), lang_get( 'delete_link' ), false, 'small' ); 1507 echo ']'; 1508 } 1509 if ( config_get( 'file_upload_method' ) == FTP ) { 1510 echo lang_get( 'word_separator' ) . '(' . lang_get( 'cached' ) . ')'; 1511 } 1512 } else { 1513 print_file_icon( $p_attachment['display_name'] ); 1514 echo lang_get( 'word_separator' ) . '<span class="strike">' . string_display_line( $p_attachment['display_name'] ) . '</span>' . lang_get( 'word_separator' ) . '(' . lang_get( 'attachment_missing' ) . ')'; 1515 } 1516 } 1517 1518 /** 1519 * Prints the preview of a text file attachment. 1520 * @param array $p_attachment An attachment arrray from within the array returned by the file_get_visible_attachments() function 1521 */ 1522 function print_bug_attachment_preview_text( $p_attachment ) { 1523 if ( !$p_attachment['exists'] ) { 1524 return; 1525 } 1526 echo "\n<pre class=\"bug-attachment-preview-text\">"; 1527 switch( config_get( 'file_upload_method' ) ) { 1528 case DISK: 1529 if ( file_exists( $p_attachment['diskfile'] ) ) { 1530 $t_content = file_get_contents( $p_attachment['diskfile'] ); 1531 } 1532 break; 1533 case FTP: 1534 if ( file_exists( $p_attachment['diskfile'] ) ) { 1535 $t_content = file_get_contents( $p_attachment['diskfile'] ); 1536 } else { 1537 $t_ftp = file_ftp_connect(); 1538 file_ftp_get( $t_ftp, $p_attachment['diskfile'], $p_attachment['diskfile'] ); 1539 file_ftp_disconnect( $t_ftp ); 1540 if ( file_exists( $p_attachment['diskfile'] ) ) { 1541 $t_content = file_get_contents( $p_attachment['diskfile'] ); 1542 } 1543 } 1544 break; 1545 default: 1546 $t_bug_file_table = db_get_table( 'bug_file' ); 1547 $c_attachment_id = db_prepare_int( $p_attachment['id'] ); 1548 $t_query = "SELECT * FROM $t_bug_file_table WHERE id=" . db_param(); 1549 $t_result = db_query_bound( $t_query, Array( $c_attachment_id ) ); 1550 $t_row = db_fetch_array( $t_result ); 1551 $t_content = $t_row['content']; 1552 } 1553 echo htmlspecialchars( $t_content ); 1554 echo '</pre>'; 1555 } 1556 1557 /** 1558 * Prints the preview of an image file attachment. 1559 * @param array $p_attachment An attachment arrray from within the array returned by the file_get_visible_attachments() function 1560 */ 1561 function print_bug_attachment_preview_image( $p_attachment ) { 1562 $t_preview_style = 'border: 0;'; 1563 $t_max_width = config_get( 'preview_max_width' ); 1564 if ( $t_max_width > 0 ) { 1565 $t_preview_style .= ' max-width:' . $t_max_width . 'px;'; 1566 } 1567 1568 $t_max_height = config_get( 'preview_max_height' ); 1569 if ( $t_max_height > 0 ) { 1570 $t_preview_style .= ' max-height:' . $t_max_height . 'px;'; 1571 } 1572 1573 $t_title = file_get_field( $p_attachment['id'], 'title' ); 1574 $t_image_url = $p_attachment['download_url'] . '&show_inline=1' . form_security_param( 'file_show_inline' ); 1575 1576 echo "\n<div class=\"bug-attachment-preview-image\">"; 1577 echo '<a href="' . string_attribute( $p_attachment['download_url'] ) . '">'; 1578 echo '<img src="' . string_attribute( $t_image_url ) . '" alt="' . string_attribute( $t_title ) . '" style="' . string_attribute( $t_preview_style ) . '" />'; 1579 echo '</a></div>'; 1580 } 1581 1582 # -------------------- 1583 # Print the option list for timezones 1584 function print_timezone_option_list( $p_timezone ) { 1585 if ( !function_exists( 'timezone_identifiers_list' ) ) { 1586 echo "\t<option value=\"$p_timezone\" selected=\"selected\">$p_timezone</option>\n"; 1587 return; 1588 } 1589 1590 $t_identifiers = timezone_identifiers_list(); 1591 1592 foreach ( $t_identifiers as $t_identifier ) 1593 { 1594 $t_zone = explode( '/', $t_identifier ); 1595 1596 // Only use "friendly" continent names - http://us.php.net/manual/en/timezones.others.php 1597 if ($t_zone[0] == 'Africa' || 1598 $t_zone[0] == 'America' || 1599 $t_zone[0] == 'Antarctica' || 1600 $t_zone[0] == 'Arctic' || 1601 $t_zone[0] == 'Asia' || 1602 $t_zone[0] == 'Atlantic' || 1603 $t_zone[0] == 'Australia' || 1604 $t_zone[0] == 'Europe' || 1605 $t_zone[0] == 'Indian' || 1606 $t_zone[0] == 'Pacific' ) 1607 { 1608 if ( isset( $t_zone[1] ) != '' ) 1609 { 1610 $t_locations[$t_zone[0]][$t_zone[0] . '/' . $t_zone[1]] = array( str_replace( '_', ' ', $t_zone[1] ), $t_identifier ); 1611 } 1612 } 1613 } 1614 1615 foreach( $t_locations as $t_continent => $t_locations ) { 1616 echo "\t<optgroup label=\"$t_continent\">\n"; 1617 foreach ( $t_locations as $t_location ) { 1618 echo "\t\t<option value=\"" . $t_location[1] . '"'; 1619 check_selected( $p_timezone, $t_location[1] ); 1620 echo '>' . $t_location[0] . "</option>\n"; 1621 } 1622 echo "\t</optgroup>\n"; 1623 } 1624 }
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 |