| [ 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 * HTML API 19 * 20 * These functions control the HTML output of each page. 21 * 22 * This is the call order of these functions, should you need to figure out 23 * which to modify or which to leave out: 24 * 25 * html_page_top1 26 * html_begin 27 * html_head_begin 28 * html_css 29 * html_content_type 30 * html_rss_link 31 * (html_meta_redirect) 32 * html_title 33 * html_page_top2 34 * html_page_top2a 35 * html_head_end 36 * html_body_begin 37 * html_header 38 * html_top_banner 39 * html_login_info 40 * (print_project_menu_bar) 41 * print_menu 42 * 43 * ...Page content here... 44 * 45 * html_page_bottom1 46 * (print_menu) 47 * html_page_bottom1a 48 * html_bottom_banner 49 * html_footer 50 * html_body_end 51 * html_end 52 * 53 * @package CoreAPI 54 * @subpackage HTMLAPI 55 * @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org 56 * @copyright Copyright (C) 2002 - 2011 MantisBT Team - mantisbt-dev@lists.sourceforge.net 57 * @link http://www.mantisbt.org 58 * 59 * @uses access_api.php 60 * @uses authentication_api.php 61 * @uses bug_api.php 62 * @uses config_api.php 63 * @uses constant_inc.php 64 * @uses current_user_api.php 65 * @uses database_api.php 66 * @uses error_api.php 67 * @uses event_api.php 68 * @uses file_api.php 69 * @uses filter_api.php 70 * @uses filter_constants_inc.php 71 * @uses form_api.php 72 * @uses helper_api.php 73 * @uses lang_api.php 74 * @uses news_api.php 75 * @uses php_api.php 76 * @uses print_api.php 77 * @uses project_api.php 78 * @uses rss_api.php 79 * @uses string_api.php 80 * @uses user_api.php 81 * @uses utility_api.php 82 */ 83 84 require_api( 'access_api.php' ); 85 require_api( 'authentication_api.php' ); 86 require_api( 'bug_api.php' ); 87 require_api( 'config_api.php' ); 88 require_api( 'constant_inc.php' ); 89 require_api( 'current_user_api.php' ); 90 require_api( 'database_api.php' ); 91 require_api( 'error_api.php' ); 92 require_api( 'event_api.php' ); 93 require_api( 'file_api.php' ); 94 require_api( 'filter_api.php' ); 95 require_api( 'filter_constants_inc.php' ); 96 require_api( 'form_api.php' ); 97 require_api( 'helper_api.php' ); 98 require_api( 'lang_api.php' ); 99 require_api( 'news_api.php' ); 100 require_api( 'php_api.php' ); 101 require_api( 'print_api.php' ); 102 require_api( 'project_api.php' ); 103 require_api( 'rss_api.php' ); 104 require_api( 'string_api.php' ); 105 require_api( 'user_api.php' ); 106 require_api( 'utility_api.php' ); 107 108 $g_rss_feed_url = null; 109 110 $g_robots_meta = ''; 111 112 # flag for error handler to skip header menus 113 $g_error_send_page_header = true; 114 115 $g_stylesheets_included = array(); 116 $g_scripts_included = array(); 117 118 /** 119 * Sets the url for the rss link associated with the current page. 120 * null: means no feed (default). 121 * @param string $p_rss_feed_url rss feed url 122 * @return null 123 */ 124 function html_set_rss_link( $p_rss_feed_url ) { 125 if( OFF != config_get( 'rss_enabled' ) ) { 126 global $g_rss_feed_url; 127 $g_rss_feed_url = $p_rss_feed_url; 128 } 129 } 130 131 /** 132 * This method must be called before the html_page_top* methods. It marks the page as not 133 * for indexing. 134 * @return null 135 */ 136 function html_robots_noindex() { 137 global $g_robots_meta; 138 $g_robots_meta = 'noindex,follow'; 139 } 140 141 /** 142 * Prints the link that allows auto-detection of the associated feed. 143 * @return null 144 */ 145 function html_rss_link() { 146 global $g_rss_feed_url; 147 148 if( $g_rss_feed_url !== null ) { 149 echo '<link rel="alternate" type="application/rss+xml" title="RSS" href="' . string_attribute( $g_rss_feed_url ) . "\" />\n"; 150 } 151 } 152 153 /** 154 * Prints a <script> tag to include a JavaScript file. 155 * @param string $p_filename Name of JavaScript file (with extension) to include 156 * @return null 157 */ 158 function html_javascript_link( $p_filename) { 159 echo "\t", '<script type="text/javascript" src="', helper_mantis_url( 'javascript/' . $p_filename ), '"></script>' . "\n"; 160 } 161 162 /** 163 * Defines the top of a HTML page 164 * @param string $p_page_title html page title 165 * @param string $p_redirect_url url to redirect to if necessary 166 * @return null 167 */ 168 function html_page_top( $p_page_title = null, $p_redirect_url = null ) { 169 html_page_top1( $p_page_title ); 170 if ( $p_redirect_url !== null ) { 171 html_meta_redirect( $p_redirect_url ); 172 } 173 html_page_top2(); 174 } 175 176 /** 177 * Print the part of the page that comes before meta redirect tags should be inserted 178 * @param string $p_page_title page title 179 * @return null 180 */ 181 function html_page_top1( $p_page_title = null ) { 182 html_begin(); 183 html_head_begin(); 184 html_css(); 185 html_content_type(); 186 include( config_get( 'meta_include_file' ) ); 187 188 global $g_robots_meta; 189 if ( !is_blank( $g_robots_meta ) ) { 190 echo "\t", '<meta name="robots" content="', $g_robots_meta, '" />', "\n"; 191 } 192 193 html_rss_link(); 194 195 $t_favicon_image = config_get( 'favicon_image' ); 196 if( !is_blank( $t_favicon_image ) ) { 197 echo "\t", '<link rel="shortcut icon" href="', helper_mantis_url( $t_favicon_image ), '" type="image/x-icon" />', "\n"; 198 } 199 200 // Advertise the availability of the browser search plug-ins. 201 echo "\t", '<link rel="search" type="application/opensearchdescription+xml" title="MantisBT: Text Search" href="' . string_sanitize_url( 'browser_search_plugin.php?type=text', true) . '" />' . "\n"; 202 echo "\t", '<link rel="search" type="application/opensearchdescription+xml" title="MantisBT: Issue Id" href="' . string_sanitize_url( 'browser_search_plugin.php?type=id', true) . '" />' . "\n"; 203 204 html_title( $p_page_title ); 205 html_head_javascript(); 206 } 207 208 /** 209 * Print the part of the page that comes after meta tags, but before the actual page content 210 * @return null 211 */ 212 function html_page_top2() { 213 html_page_top2a(); 214 215 if( !db_is_connected() ) { 216 return; 217 } 218 219 if( auth_is_user_authenticated() ) { 220 html_login_info(); 221 222 if( ON == config_get( 'show_project_menu_bar' ) ) { 223 print_project_menu_bar(); 224 echo '<br />'; 225 } 226 } 227 print_menu(); 228 echo '<div id="content">', "\n"; 229 event_signal( 'EVENT_LAYOUT_CONTENT_BEGIN' ); 230 } 231 232 /** 233 * Print the part of the page that comes after meta tags and before the 234 * actual page content, but without login info or menus. This is used 235 * directly during the login process and other times when the user may 236 * not be authenticated 237 * @return null 238 */ 239 function html_page_top2a() { 240 global $g_error_send_page_header; 241 242 html_head_end(); 243 html_body_begin(); 244 $g_error_send_page_header = false; 245 html_header(); 246 html_top_banner(); 247 } 248 249 /** 250 * Print the part of the page that comes below the page content 251 * $p_file should always be the __FILE__ variable. This is passed to show source 252 * @param string $p_file should always be the __FILE__ variable. This is passed to show source 253 * @return null 254 */ 255 function html_page_bottom( $p_file = null ) { 256 html_page_bottom1( $p_file ); 257 } 258 259 /** 260 * Print the part of the page that comes below the page content 261 * $p_file should always be the __FILE__ variable. This is passed to show source 262 * @param string $p_file should always be the __FILE__ variable. This is passed to show source 263 * @return null 264 */ 265 function html_page_bottom1( $p_file = null ) { 266 if( !db_is_connected() ) { 267 return; 268 } 269 270 event_signal( 'EVENT_LAYOUT_CONTENT_END' ); 271 echo '</div>', "\n"; 272 if( config_get( 'show_footer_menu' ) ) { 273 echo '<br />'; 274 print_menu(); 275 } 276 277 html_page_bottom1a( $p_file ); 278 } 279 280 /** 281 * Print the part of the page that comes below the page content but leave off 282 * the menu. This is used during the login process and other times when the 283 * user may not be authenticated. 284 * @param string $p_file should always be the __FILE__ variable. 285 * @return null 286 */ 287 function html_page_bottom1a( $p_file = null ) { 288 if( null === $p_file ) { 289 $p_file = basename( $_SERVER['SCRIPT_NAME'] ); 290 } 291 292 html_bottom_banner(); 293 html_footer(); 294 html_body_end(); 295 html_end(); 296 } 297 298 /** 299 * (1) Print the document type and the opening <html> tag 300 * @return null 301 */ 302 function html_begin() { 303 echo '<?xml version="1.0" encoding="utf-8"?>'; 304 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'; 305 echo '<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >'; 306 } 307 308 /** 309 * (2) Begin the <head> section 310 * @return null 311 */ 312 function html_head_begin() { 313 echo '<head>', "\n"; 314 } 315 316 /** 317 * (3) Print the content-type 318 * @return null 319 */ 320 function html_content_type() { 321 echo "\t", '<meta http-equiv="Content-type" content="application/xhtml+xml; charset=UTF-8" />', "\n"; 322 } 323 324 /** 325 * (4) Print the window title 326 * @param string $p_page_title window title 327 * @return null 328 */ 329 function html_title( $p_page_title = null ) { 330 $t_page_title = string_html_specialchars( $p_page_title ); 331 $t_title = string_html_specialchars( config_get( 'window_title' ) ); 332 echo "\t", '<title>'; 333 if( empty( $t_page_title ) ) { 334 echo $t_title; 335 } else { 336 if( empty( $t_title ) ) { 337 echo $t_page_title; 338 } else { 339 echo $t_page_title . ' - ' . $t_title; 340 } 341 } 342 echo '</title>', "\n"; 343 } 344 345 function require_css( $p_stylesheet_path ) { 346 global $g_stylesheets_included; 347 $g_stylesheets_included[$p_stylesheet_path] = $p_stylesheet_path; 348 } 349 350 /** 351 * (5) Print the link to include the css file 352 * @return null 353 */ 354 function html_css() { 355 global $g_stylesheets_included; 356 html_css_link( config_get( 'css_include_file' ) ); 357 html_css_link( 'jquery-ui.css' ); 358 html_css_link( 'common_config.php' ); 359 # Add right-to-left css if needed 360 if ( lang_get( 'directionality' ) == 'rtl' ) { 361 html_css_link( config_get( 'css_rtl_include_file' ) ); 362 } 363 foreach ( $g_stylesheets_included as $t_stylesheet_path ) { 364 html_css_link ( $t_stylesheet_path ); 365 } 366 } 367 368 /** 369 * Prints a css link 370 * @return null 371 */ 372 function html_css_link( $p_filename ) { 373 echo "\t", '<link rel="stylesheet" type="text/css" href="', string_sanitize_url( helper_mantis_url( 'css/' . $p_filename ), true ), '" />' . "\n"; 374 } 375 376 377 /** 378 * (6) Print an HTML meta tag to redirect to another page 379 * This function is optional and may be called by pages that need a redirect. 380 * $p_time is the number of seconds to wait before redirecting. 381 * If we have handled any errors on this page and the 'stop_on_errors' config 382 * option is turned on, return false and don't redirect. 383 * 384 * @param string $p_url The page to redirect: has to be a relative path 385 * @param integer $p_time seconds to wait for before redirecting 386 * @param boolean $p_sanitize apply string_sanitize_url to passed url 387 * @return boolean 388 */ 389 function html_meta_redirect( $p_url, $p_time = null, $p_sanitize = true ) { 390 if( ON == config_get_global( 'stop_on_errors' ) && error_handled() ) { 391 return false; 392 } 393 394 if( null === $p_time ) { 395 $p_time = current_user_get_pref( 'redirect_delay' ); 396 } 397 398 $t_url = config_get( 'path' ); 399 if( $p_sanitize ) { 400 $t_url .= string_sanitize_url( $p_url ); 401 } else { 402 $t_url .= $p_url; 403 } 404 405 $t_url = htmlspecialchars( $t_url ); 406 407 echo "\t<meta http-equiv=\"Refresh\" content=\"$p_time;URL=$t_url\" />\n"; 408 409 return true; 410 } 411 412 function require_js( $p_script_path ) { 413 global $g_scripts_included; 414 $g_scripts_included[$p_script_path] = $p_script_path; 415 } 416 417 /** 418 * (6a) Javascript... 419 * @return null 420 */ 421 function html_head_javascript() { 422 if ( config_get( 'use_javascript' ) ) { 423 global $g_scripts_included; 424 echo "\t<script type=\"text/javascript\" src=\"" . helper_mantis_url( 'javascript_config.php' ) . '"></script>' . "\n"; 425 echo "\t<script type=\"text/javascript\" src=\"" . helper_mantis_url( 'javascript_translations.php' ) . '"></script>' . "\n"; 426 html_javascript_link( 'jquery.js' ); 427 html_javascript_link( 'jquery-ui.js' ); 428 html_javascript_link( 'common.js' ); 429 foreach ( $g_scripts_included as $t_script_path ) { 430 html_javascript_link( $t_script_path ); 431 } 432 } 433 } 434 435 /** 436 * (7) End the <head> section 437 * @return null 438 */ 439 function html_head_end() { 440 event_signal( 'EVENT_LAYOUT_RESOURCES' ); 441 442 echo '</head>', "\n"; 443 } 444 445 /** 446 * (8) Begin the <body> section 447 * @return null 448 */ 449 function html_body_begin() { 450 echo '<body>', "\n"; 451 echo '<div id="mantis">', "\n"; 452 453 event_signal( 'EVENT_LAYOUT_BODY_BEGIN' ); 454 } 455 456 /** 457 * (9) Print the title displayed at the top of the page 458 * @return null 459 */ 460 function html_header() { 461 $t_title = config_get( 'page_title' ); 462 if( !is_blank( $t_title ) ) { 463 echo '<div class="center"><span class="pagetitle">', string_display( $t_title ), '</span></div>', "\n"; 464 } 465 } 466 467 /** 468 * (10) Print a user-defined banner at the top of the page if there is one. 469 * @return null 470 */ 471 function html_top_banner() { 472 $t_page = config_get( 'top_include_page' ); 473 $t_logo_image = config_get( 'logo_image' ); 474 $t_logo_url = config_get( 'logo_url' ); 475 476 if( is_blank( $t_logo_image ) ) { 477 $t_show_logo = false; 478 } else { 479 $t_show_logo = true; 480 if( is_blank( $t_logo_url ) ) { 481 $t_show_url = false; 482 } else { 483 $t_show_url = true; 484 } 485 } 486 487 if( !is_blank( $t_page ) && file_exists( $t_page ) && !is_dir( $t_page ) ) { 488 include( $t_page ); 489 } else if( $t_show_logo ) { 490 echo '<div id="banner">'; 491 if( $t_show_url ) { 492 echo '<a id="logo-link" href="', config_get( 'logo_url' ), '">'; 493 } 494 echo '<img id="logo-image" alt="Mantis Bug Tracker" src="' . helper_mantis_url( config_get( 'logo_image' ) ) . '" />'; 495 if( $t_show_url ) { 496 echo '</a>'; 497 } 498 echo '</div>'; 499 } 500 501 event_signal( 'EVENT_LAYOUT_PAGE_HEADER' ); 502 } 503 504 /** 505 * (11) Print the user's account information 506 * Also print the select box where users can switch projects 507 * @return null 508 */ 509 function html_login_info() { 510 $t_username = current_user_get_field( 'username' ); 511 $t_access_level = get_enum_element( 'access_levels', current_user_get_access_level() ); 512 $t_now = date( config_get( 'complete_date_format' ) ); 513 $t_realname = current_user_get_field( 'realname' ); 514 515 echo '<div id="login-info">'; 516 if( current_user_is_anonymous() ) { 517 $t_return_page = $_SERVER['SCRIPT_NAME']; 518 if( isset( $_SERVER['QUERY_STRING'] ) ) { 519 $t_return_page .= '?' . $_SERVER['QUERY_STRING']; 520 } 521 522 $t_return_page = string_url( $t_return_page ); 523 524 echo '<span id="logged-anon-label">' . lang_get( 'anonymous' ) . '</span>'; 525 echo '<span id="login-link"><a href="' . helper_mantis_url( 'login_page.php?return=' . $t_return_page ) . '">' . lang_get( 'login_link' ) . '</a></span>'; 526 if( config_get_global( 'allow_signup' ) == ON ) { 527 echo '<span id="signup-link"><a href="' . helper_mantis_url( 'signup_page.php' ) . '">' . lang_get( 'signup_link' ) . '</a></span>'; 528 } 529 } else { 530 echo '<span id="logged-in-label">' . lang_get( 'logged_in_as' ) . '</span>'; 531 echo '<span id="logged-in-user">' . string_html_specialchars( $t_username ) . '</span>'; 532 echo '<span id="logged-in">'; 533 echo !is_blank( $t_realname ) ? '<span id="logged-in-realname">' . string_html_specialchars( $t_realname ) . '</span>' : ''; 534 echo '<span id="logged-in-accesslevel" class="' . $t_access_level . '">' . $t_access_level . '</span>'; 535 echo '</span>'; 536 } 537 echo '</div>'; 538 539 540 $t_show_project_selector = true; 541 if( count( current_user_get_accessible_projects() ) == 1 ) { 542 543 // >1 544 $t_project_ids = current_user_get_accessible_projects(); 545 $t_project_id = (int) $t_project_ids[0]; 546 if( count( current_user_get_accessible_subprojects( $t_project_id ) ) == 0 ) { 547 $t_show_project_selector = false; 548 } 549 } 550 551 if( OFF != config_get( 'rss_enabled' ) ) { 552 echo '<div id="rss-feed">'; 553 # Link to RSS issues feed for the selected project, including authentication details. 554 echo '<a href="' . htmlspecialchars( rss_get_issues_feed_url() ) . '">'; 555 echo '<img src="' . helper_mantis_url( 'images/rss.png' ) . '" alt="' . lang_get( 'rss' ) . '" title="' . lang_get( 'rss' ) . '" />'; 556 echo '</a>'; 557 echo '</div>'; 558 } 559 560 if( $t_show_project_selector ) { 561 echo '<form method="post" id="form-set-project" action="' . helper_mantis_url( 'set_project.php' ) . '">'; 562 echo '<fieldset id="project-selector">'; 563 # CSRF protection not required here - form does not result in modifications 564 565 echo '<label for="form-set-project-id">' . lang_get( 'email_project' ) . '</label>'; 566 echo '<select id="form-set-project-id" name="project_id">'; 567 print_project_option_list( join( ';', helper_get_current_project_trace() ), true, null, true ); 568 echo '</select> '; 569 echo '<input type="submit" class="button" value="' . lang_get( 'switch' ) . '" />'; 570 echo '</fieldset>'; 571 echo '</form>'; 572 echo '<div id="current-time">' . $t_now . '</div>'; 573 } else { 574 echo '<div id="current-time-centered">' . $t_now . '</div>'; 575 } 576 } 577 578 /** 579 * (12) Print a user-defined banner at the bottom of the page if there is one. 580 * @return null 581 */ 582 function html_bottom_banner() { 583 $t_page = config_get( 'bottom_include_page' ); 584 585 if( !is_blank( $t_page ) && file_exists( $t_page ) && !is_dir( $t_page ) ) { 586 include( $t_page ); 587 } 588 } 589 590 /** 591 * (13) Print the page footer information 592 * @param string $p_file 593 * @return null 594 */ 595 function html_footer( $p_file = null ) { 596 global $g_queries_array, $g_request_time; 597 598 # If a user is logged in, update their last visit time. 599 # We do this at the end of the page so that: 600 # 1) we can display the user's last visit time on a page before updating it 601 # 2) we don't invalidate the user cache immediately after fetching it 602 # 3) don't do this on the password verification or update page, as it causes the 603 # verification comparison to fail 604 if ( auth_is_user_authenticated() && !current_user_is_anonymous() && !( is_page_name( 'verify.php' ) || is_page_name( 'account_update.php' ) ) ) { 605 $t_user_id = auth_get_current_user_id(); 606 user_update_last_visit( $t_user_id ); 607 } 608 609 echo "<div id=\"footer\">\n"; 610 echo "\t<hr />\n"; 611 echo "\t<div id=\"powered-by-mantisbt-logo\">\n"; 612 $t_mantisbt_logo_url = helper_mantis_url( 'images/mantis_logo_button.gif' ); 613 echo "\t\t<a href=\"http://www.mantisbt.org\" title=\"Mantis Bug Tracker: a free and open source web based bug tracking system.\"><img src=\"$t_mantisbt_logo_url\" width=\"88\" height=\"35\" alt=\"Powered by Mantis Bug Tracker: a free and open source web based bug tracking system.\" /></a>\n"; 614 echo "\t</div>\n"; 615 616 # Show optional user-specificed custom copyright statement 617 $t_copyright_statement = config_get( 'copyright_statement' ); 618 if ( $t_copyright_statement ) { 619 echo "\t<address id=\"user-copyright\">$t_copyright_statement</address>\n"; 620 } 621 622 # Show MantisBT version and copyright statement 623 $t_version_suffix = ''; 624 $t_copyright_years = ''; 625 if ( config_get( 'show_version' ) ) { 626 $t_version_suffix = htmlentities( ' ' . MANTIS_VERSION . config_get_global( 'version_suffix' ) ); 627 $t_copyright_years = ' 2000 - 2011'; 628 } 629 echo "\t<address id=\"mantisbt-copyright\">Powered by <a href=\"http://www.mantisbt.org\" title=\"Mantis Bug Tracker: a free and open source web based bug tracking system.\">Mantis Bug Tracker</a> (MantisBT)$t_version_suffix. Copyright ©$t_copyright_years MantisBT contributors. Licensed under the terms of the <a href=\"http://www.gnu.org/licenses/old-licenses/gpl-2.0.html\" title=\"GNU General Public License (GPL) version 2\">GNU General Public License (GPL) version 2</a> or a later version.</address>\n"; 630 631 # Show contact information 632 $t_webmaster_contact_information = sprintf( lang_get( 'webmaster_contact_information' ), string_html_specialchars( config_get( 'webmaster_email' ) ) ); 633 echo "\t<address id=\"webmaster-contact-information\">$t_webmaster_contact_information</address>\n"; 634 635 event_signal( 'EVENT_LAYOUT_PAGE_FOOTER' ); 636 637 # Print horizontal rule if any debugging stats follow 638 if ( config_get( 'show_timer' ) || config_get( 'show_memory_usage' ) || config_get( 'show_queries_count' ) ) { 639 echo "\t<hr />\n"; 640 } 641 642 # Print the page execution time 643 if ( config_get( 'show_timer' ) ) { 644 $t_page_execution_time = sprintf( lang_get( 'page_execution_time' ), number_format( microtime( true ) - $g_request_time, 4 ) ); 645 echo "\t<p id=\"page-execution-time\">$t_page_execution_time</p>\n"; 646 } 647 648 # Print the page memory usage 649 if ( config_get( 'show_memory_usage' ) ) { 650 $t_page_memory_usage = sprintf( lang_get( 'memory_usage_in_kb' ), number_format( memory_get_peak_usage() / 1024 ) ); 651 echo "\t<p id=\"page-memory-usage\">$t_page_memory_usage</p>\n"; 652 } 653 654 # Determine number of unique queries executed 655 if ( config_get( 'show_queries_count' ) ) { 656 $t_total_queries_count = count( $g_queries_array ); 657 $t_unique_queries_count = 0; 658 $t_total_query_execution_time = 0; 659 $t_unique_queries = array(); 660 for ( $i = 0; $i < $t_total_queries_count; $i++ ) { 661 if ( !in_array( $g_queries_array[$i][0], $t_unique_queries ) ) { 662 $t_unique_queries_count++; 663 $g_queries_array[$i][3] = false; 664 array_push( $t_unique_queries, $g_queries_array[$i][0] ); 665 } else { 666 $g_queries_array[$i][3] = true; 667 } 668 $t_total_query_execution_time += $g_queries_array[$i][1]; 669 } 670 671 $t_total_queries_executed = sprintf( lang_get( 'total_queries_executed' ), $t_total_queries_count ); 672 echo "\t<p id=\"total-queries-count\">$t_total_queries_executed</p>\n"; 673 if ( config_get_global( 'db_log_queries' ) ) { 674 $t_unique_queries_executed = sprintf( lang_get( 'unique_queries_executed' ), $t_unique_queries_count ); 675 echo "\t<p id=\"unique-queries-count\">$t_unique_queries_executed</p>\n"; 676 } 677 $t_total_query_time = sprintf( lang_get( 'total_query_execution_time' ), $t_total_query_execution_time ); 678 echo "\t<p id=\"total-query-execution-time\">$t_total_query_time</p>\n"; 679 } 680 681 # Print table of log events 682 log_print_to_page(); 683 684 echo "</div>\n"; 685 686 } 687 688 /** 689 * (14) End the <body> section 690 * @return null 691 */ 692 function html_body_end() { 693 event_signal( 'EVENT_LAYOUT_BODY_END' ); 694 695 echo '</div>', "\n"; 696 697 echo '</body>', "\n"; 698 } 699 700 /** 701 * (15) Print the closing <html> tag 702 * @return null 703 */ 704 function html_end() { 705 echo '</html>', "\n"; 706 } 707 708 /** 709 * Prepare an array of additional menu options from a config variable 710 * @param string $p_config config name 711 * @return array 712 */ 713 function prepare_custom_menu_options( $p_config ) { 714 $t_custom_menu_options = config_get( $p_config ); 715 $t_options = array(); 716 717 foreach( $t_custom_menu_options as $t_custom_option ) { 718 $t_access_level = $t_custom_option[1]; 719 if( access_has_project_level( $t_access_level ) ) { 720 $t_caption = string_html_specialchars( lang_get_defaulted( $t_custom_option[0] ) ); 721 $t_link = string_attribute( $t_custom_option[2] ); 722 $t_options[] = "<a href=\"$t_link\">$t_caption</a>"; 723 } 724 } 725 726 return $t_options; 727 } 728 729 /** 730 * Print the main menu 731 * @return null 732 */ 733 function print_menu() { 734 if( auth_is_user_authenticated() ) { 735 $t_protected = current_user_get_field( 'protected' ); 736 $t_current_project = helper_get_current_project(); 737 738 $t_menu_options = array(); 739 740 # Main Page 741 $t_menu_options[] = '<a href="' . helper_mantis_url( 'main_page.php' ) . '">' . lang_get( 'main_link' ) . '</a>'; 742 743 # Plugin / Event added options 744 $t_event_menu_options = event_signal( 'EVENT_MENU_MAIN_FRONT' ); 745 foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) { 746 foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) { 747 if( is_array( $t_callback_menu_options ) ) { 748 $t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options ); 749 } else { 750 if ( !is_null( $t_callback_menu_options ) ) { 751 $t_menu_options[] = $t_callback_menu_options; 752 } 753 } 754 } 755 } 756 757 # My View 758 $t_menu_options[] = '<a href="' . helper_mantis_url( 'my_view_page.php">' ) . lang_get( 'my_view_link' ) . '</a>'; 759 760 # View Bugs 761 $t_menu_options[] = '<a href="' . helper_mantis_url( 'view_all_bug_page.php">' ) . lang_get( 'view_bugs_link' ) . '</a>'; 762 763 # Report Bugs 764 if( access_has_project_level( config_get( 'report_bug_threshold' ) ) ) { 765 $t_menu_options[] = string_get_bug_report_link(); 766 } 767 768 # Changelog Page 769 if( access_has_project_level( config_get( 'view_changelog_threshold' ) ) ) { 770 $t_menu_options[] = '<a href="' . helper_mantis_url( 'changelog_page.php">' ) . lang_get( 'changelog_link' ) . '</a>'; 771 } 772 773 # Roadmap Page 774 if( access_has_project_level( config_get( 'roadmap_view_threshold' ) ) ) { 775 $t_menu_options[] = '<a href="' . helper_mantis_url( 'roadmap_page.php">' ) . lang_get( 'roadmap_link' ) . '</a>'; 776 } 777 778 # Summary Page 779 if( access_has_project_level( config_get( 'view_summary_threshold' ) ) ) { 780 $t_menu_options[] = '<a href="' . helper_mantis_url( 'summary_page.php">' ) . lang_get( 'summary_link' ) . '</a>'; 781 } 782 783 # Project Documentation Page 784 if( ON == config_get( 'enable_project_documentation' ) ) { 785 $t_menu_options[] = '<a href="' . helper_mantis_url( 'proj_doc_page.php">' ) . lang_get( 'docs_link' ) . '</a>'; 786 } 787 788 # Project Wiki 789 if( config_get_global( 'wiki_enable' ) == ON ) { 790 $t_menu_options[] = '<a href="' . helper_mantis_url( 'wiki.php?type=project&id=' ) . $t_current_project . '">' . lang_get( 'wiki' ) . '</a>'; 791 } 792 793 # Plugin / Event added options 794 $t_event_menu_options = event_signal( 'EVENT_MENU_MAIN' ); 795 foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) { 796 foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) { 797 if( is_array( $t_callback_menu_options ) ) { 798 $t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options ); 799 } else { 800 if ( !is_null( $t_callback_menu_options ) ) { 801 $t_menu_options[] = $t_callback_menu_options; 802 } 803 } 804 } 805 } 806 807 # Manage Users (admins) or Manage Project (managers) or Manage Custom Fields 808 if( access_has_global_level( config_get( 'manage_site_threshold' ) ) ) { 809 $t_link = helper_mantis_url( 'manage_overview_page.php' ); 810 $t_menu_options[] = '<a class="manage-menu-link" href="' . $t_link . '">' . lang_get( 'manage_link' ) . '</a>'; 811 } else { 812 $t_show_access = min( config_get( 'manage_user_threshold' ), config_get( 'manage_project_threshold' ), config_get( 'manage_custom_fields_threshold' ) ); 813 if( access_has_global_level( $t_show_access ) || access_has_any_project( $t_show_access ) ) { 814 $t_current_project = helper_get_current_project(); 815 if( access_has_global_level( config_get( 'manage_user_threshold' ) ) ) { 816 $t_link = helper_mantis_url( 'manage_user_page.php' ); 817 } else { 818 if( access_has_project_level( config_get( 'manage_project_threshold' ), $t_current_project ) && ( $t_current_project <> ALL_PROJECTS ) ) { 819 $t_link = helper_mantis_url( 'manage_proj_edit_page.php?project_id=' ) . $t_current_project; 820 } else { 821 $t_link = helper_mantis_url( 'manage_proj_page.php' ); 822 } 823 } 824 $t_menu_options[] = "<a href=\"$t_link\">" . lang_get( 'manage_link' ) . '</a>'; 825 } 826 } 827 828 # News Page 829 if ( news_is_enabled() && access_has_project_level( config_get( 'manage_news_threshold' ) ) ) { 830 831 # Admin can edit news for All Projects (site-wide) 832 if( ALL_PROJECTS != helper_get_current_project() || current_user_is_administrator() ) { 833 $t_menu_options[] = '<a href="' . helper_mantis_url( 'news_menu_page.php">' ) . lang_get( 'edit_news_link' ) . '</a>'; 834 } else { 835 $t_menu_options[] = '<a href="' . helper_mantis_url( 'login_select_proj_page.php">' ) . lang_get( 'edit_news_link' ) . '</a>'; 836 } 837 } 838 839 # Account Page (only show accounts that are NOT protected) 840 if( OFF == $t_protected ) { 841 $t_menu_options[] = '<a class="account-menu-link" href="' . helper_mantis_url( 'account_page.php">' ) . lang_get( 'account_link' ) . '</a>'; 842 } 843 844 # Add custom options 845 $t_custom_options = prepare_custom_menu_options( 'main_menu_custom_options' ); 846 $t_menu_options = array_merge( $t_menu_options, $t_custom_options ); 847 if( config_get( 'time_tracking_enabled' ) && config_get( 'time_tracking_with_billing' ) && access_has_global_level( config_get( 'time_tracking_reporting_threshold' ) ) ) { 848 $t_menu_options[] = '<a href="' . helper_mantis_url( 'billing_page.php">' ) . lang_get( 'time_tracking_billing_link' ) . '</a>'; 849 } 850 851 # Logout (no if anonymously logged in) 852 if( !current_user_is_anonymous() ) { 853 $t_menu_options[] = '<a id="logout-link" href="' . helper_mantis_url( 'logout_page.php">' ) . lang_get( 'logout_link' ) . '</a>'; 854 } 855 echo '<form method="post" action="' . helper_mantis_url( 'jump_to_bug.php" class="bug-jump-form">' ); 856 echo '<fieldset class="bug-jump">'; 857 # CSRF protection not required here - form does not result in modifications 858 859 $t_bug_label = lang_get( 'issue_id' ); 860 echo '<input type="hidden" name="bug_label" value="', $t_bug_label, '" />'; 861 echo '<input type="text" name="bug_id" size="10" class="small" /> '; 862 863 echo '<input type="submit" class="button-small" value="' . lang_get( 'jump' ) . '" /> '; 864 echo '</fieldset>'; 865 echo '</form>'; 866 echo '<div class="main-menu">'; 867 echo '<div>'; 868 echo '<ul class="menu">'; 869 echo '<li>'; 870 echo implode( $t_menu_options, "</li>\n<li>" ); 871 echo '</li>'; 872 echo '</ul>'; 873 echo '</div>'; 874 echo '</div>'; 875 } 876 } 877 878 /** 879 * Print the menu bar with a list of projects to which the user has access 880 * @return null 881 */ 882 function print_project_menu_bar() { 883 $t_project_ids = current_user_get_accessible_projects(); 884 885 echo '<table class="width100" cellspacing="0">'; 886 echo '<tr>'; 887 echo '<td class="menu">'; 888 echo '<a href="' . helper_mantis_url( 'set_project.php?project_id=' . ALL_PROJECTS ) . '">' . lang_get( 'all_projects' ) . '</a>'; 889 890 foreach( $t_project_ids as $t_id ) { 891 echo ' | <a href="' . helper_mantis_url( 'set_project.php?project_id=' . $t_id ) . '">' . string_html_specialchars( project_get_field( $t_id, 'name' ) ) . '</a>'; 892 print_subproject_menu_bar( $t_id, $t_id . ';' ); 893 } 894 895 echo '</td>'; 896 echo '</tr>'; 897 echo '</table>'; 898 } 899 900 /** 901 * Print the menu bar with a list of projects to which the user has access 902 * @return null 903 */ 904 function print_subproject_menu_bar( $p_project_id, $p_parents = '' ) { 905 $t_subprojects = current_user_get_accessible_subprojects( $p_project_id ); 906 $t_char = ':'; 907 foreach( $t_subprojects as $t_subproject ) { 908 echo $t_char . ' <a href="' . helper_mantis_url( 'set_project.php?project_id=' . $p_parents . $t_subproject ) . '">' . string_html_specialchars( project_get_field( $t_subproject, 'name' ) ) . '</a>'; 909 print_subproject_menu_bar( $t_subproject, $p_parents . $t_subproject . ';' ); 910 $t_char = ','; 911 } 912 } 913 914 /** 915 * Print the menu for the graph summary section 916 * @return null 917 */ 918 function print_summary_submenu() { 919 # Plugin / Event added options 920 $t_event_menu_options = event_signal( 'EVENT_SUBMENU_SUMMARY' ); 921 $t_menu_options = array(); 922 foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) { 923 foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) { 924 if( is_array( $t_callback_menu_options ) ) { 925 $t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options ); 926 } else { 927 if ( !is_null( $t_callback_menu_options ) ) { 928 $t_menu_options[] = $t_callback_menu_options; 929 } 930 } 931 } 932 } 933 934 echo '<div id="summary-submenu">'; 935 echo '<ul class="menu">'; 936 // Plugins menu items - these are cooked links 937 foreach ( $t_menu_options as $t_menu_item ) { 938 echo '<li>', $t_menu_item, '</li>'; 939 } 940 echo '</ul>'; 941 echo '</div>'; 942 } 943 944 /** 945 * Print the menu for the manage section 946 * 947 * @param string $p_page specifies the current page name so it's link can be disabled 948 * @return null 949 */ 950 function print_manage_menu( $p_page = '' ) { 951 if( access_has_global_level( config_get( 'manage_user_threshold' ) ) ) { 952 $t_pages['manage_user_page.php'] = array( 'url' => 'manage_user_page.php', 'label' => 'manage_users_link' ); 953 } 954 if( access_has_project_level( config_get( 'manage_project_threshold' ) ) ) { 955 $t_pages['manage_proj_page.php'] = array( 'url' => 'manage_proj_page.php', 'label' => 'manage_projects_link' ); 956 } 957 if( access_has_project_level( config_get( 'tag_edit_threshold' ) ) ) { 958 $t_pages['manage_tags_page.php'] = array( 'url' => 'manage_tags_page.php', 'label' => 'manage_tags_link' ); 959 } 960 if( access_has_global_level( config_get( 'manage_custom_fields_threshold' ) ) ) { 961 $t_pages['manage_custom_field_page.php'] = array( 'url' => 'manage_custom_field_page.php', 'label' => 'manage_custom_field_link' ); 962 } 963 if( access_has_global_level( config_get( 'manage_global_profile_threshold' ) ) ) { 964 $t_pages['manage_prof_menu_page.php'] = array( 'url' => 'manage_prof_menu_page.php', 'label' => 'manage_global_profiles_link' ); 965 } 966 if( access_has_global_level( config_get( 'manage_plugin_threshold' ) ) ) { 967 $t_pages['manage_plugin_page.php'] = array( 'url' => 'manage_plugin_page.php', 'label' => 'manage_plugin_link' ); 968 } 969 970 if ( access_has_project_level( config_get( 'manage_configuration_threshold' ) ) ) { 971 if ( access_has_global_level( config_get( 'view_configuration_threshold' ) ) ) { 972 $t_pages['adm_config_report.php'] = array( 'url' => 'adm_config_report.php', 'label' => 'manage_config_link' ); 973 } else { 974 $t_pages['adm_permissions_report.php'] = array( 'url' => 'adm_permissions_report.php', 'label' => 'manage_config_link' ); 975 } 976 } 977 # Remove the link from the current page 978 if ( isset( $t_pages[$p_page] ) ) { 979 $t_pages[$p_page]['url'] = ''; 980 } 981 982 # Plugin / Event added options 983 $t_event_menu_options = event_signal( 'EVENT_MENU_MANAGE' ); 984 $t_menu_options = array(); 985 foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) { 986 foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) { 987 if( is_array( $t_callback_menu_options ) ) { 988 $t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options ); 989 } else { 990 if ( !is_null( $t_callback_menu_options ) ) { 991 $t_menu_options[] = $t_callback_menu_options; 992 } 993 } 994 } 995 } 996 997 echo '<div id="manage-menu">'; 998 echo '<ul class="menu">'; 999 foreach( $t_pages AS $t_page ) { 1000 if( $t_page['url'] == '' ) { 1001 echo '<li>', lang_get( $t_page['label'] ), '</li>'; 1002 } else { 1003 echo '<li><a href="'. helper_mantis_url( $t_page['url'] ) .'">' . lang_get( $t_page['label'] ) . '</a></li>'; 1004 } 1005 } 1006 1007 // Plugins menu items - these are cooked links 1008 foreach( $t_menu_options as $t_menu_item ) { 1009 echo '<li>', $t_menu_item, '</li>'; 1010 } 1011 1012 echo '</ul>'; 1013 echo '</div>'; 1014 } 1015 1016 /** 1017 * Print the menu for the manage configuration section 1018 * @param string $p_page specifies the current page name so it's link can be disabled 1019 * @return null 1020 */ 1021 function print_manage_config_menu( $p_page = '' ) { 1022 if ( !access_has_project_level( config_get( 'manage_configuration_threshold' ) ) ) { 1023 return; 1024 } 1025 1026 $t_pages = array(); 1027 1028 if ( access_has_global_level( config_get( 'view_configuration_threshold' ) ) ) { 1029 $t_pages['adm_config_report.php'] = array( 'url' => 'adm_config_report.php', 1030 'label' => 'configuration_report' ); 1031 } 1032 1033 $t_pages['adm_permissions_report.php'] = array( 'url' => 'adm_permissions_report.php', 1034 'label' => 'permissions_summary_report' ); 1035 1036 $t_pages['manage_config_work_threshold_page.php'] = array( 'url' => 'manage_config_work_threshold_page.php', 1037 'label' => 'manage_threshold_config' ); 1038 1039 $t_pages['manage_config_workflow_page.php'] = array( 'url' => 'manage_config_workflow_page.php', 1040 'label' => 'manage_workflow_config' ); 1041 1042 if ( config_get( 'relationship_graph_enable' ) ) { 1043 $t_pages['manage_config_workflow_graph_page.php'] = array( 'url' => 'manage_config_workflow_graph_page.php', 1044 'label' => 'manage_workflow_graph' ); 1045 } 1046 1047 $t_pages['manage_config_email_page.php'] = array( 'url' => 'manage_config_email_page.php', 1048 'label' => 'manage_email_config' ); 1049 1050 $t_pages['manage_config_columns_page.php'] = array( 'url' => 'manage_config_columns_page.php', 1051 'label' => 'manage_columns_config' ); 1052 1053 # Remove the link from the current page 1054 if ( isset( $t_pages[$p_page] ) ) { 1055 $t_pages[$p_page]['url'] = ''; 1056 } 1057 1058 # Plugin / Event added options 1059 $t_event_menu_options = event_signal( 'EVENT_MENU_MANAGE_CONFIG' ); 1060 $t_menu_options = array(); 1061 foreach ( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) { 1062 foreach ( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) { 1063 if ( is_array( $t_callback_menu_options ) ) { 1064 $t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options ); 1065 } else { 1066 if ( !is_null( $t_callback_menu_options ) ) { 1067 $t_menu_options[] = $t_callback_menu_options; 1068 } 1069 } 1070 } 1071 } 1072 1073 echo '<br /><div id="manage-config-menu">'; 1074 echo '<ul class="menu">'; 1075 foreach ( $t_pages as $t_page ) { 1076 if( $t_page['url'] == '' ) { 1077 echo '<li>', lang_get( $t_page['label'] ), '</li>'; 1078 } else { 1079 echo '<li><a href="'. helper_mantis_url( $t_page['url'] ) .'">' . lang_get( $t_page['label'] ) . '</a></li>'; 1080 } 1081 } 1082 1083 foreach ( $t_menu_options as $t_menu_item ) { 1084 echo '<li>', $t_menu_item, '</li>'; 1085 } 1086 1087 echo '</ul>'; 1088 echo '</div>'; 1089 } 1090 1091 /** 1092 * Print the menu for the account section 1093 * @param string $p_page specifies the current page name so it's link can be disabled 1094 * @return null 1095 */ 1096 function print_account_menu( $p_page = '' ) { 1097 $t_pages['account_page.php'] = array( 'url'=>'account_page.php', 'label'=>'account_link' ); 1098 $t_pages['account_prefs_page.php'] = array( 'url'=>'account_prefs_page.php', 'label'=>'change_preferences_link' ); 1099 $t_pages['account_manage_columns_page.php'] = array( 'url'=>'account_manage_columns_page.php', 'label'=>'manage_columns_config' ); 1100 1101 if( config_get ( 'enable_profiles' ) == ON && access_has_project_level( config_get( 'add_profile_threshold' ) ) ) { 1102 $t_pages['account_prof_menu_page.php'] = array( 'url'=>'account_prof_menu_page.php', 'label'=>'manage_profiles_link' ); 1103 } 1104 1105 if( config_get( 'enable_sponsorship' ) == ON && access_has_project_level( config_get( 'view_sponsorship_total_threshold' ) ) && !current_user_is_anonymous() ) { 1106 $t_pages['account_sponsor_page.php'] = array( 'url'=>'account_sponsor_page.php', 'label'=>'my_sponsorship' ); 1107 } 1108 1109 # Remove the link from the current page 1110 if ( isset( $t_pages[$p_page] ) ) { 1111 $t_pages[$p_page]['url'] = ''; 1112 } 1113 1114 # Plugin / Event added options 1115 $t_event_menu_options = event_signal( 'EVENT_MENU_ACCOUNT' ); 1116 $t_menu_options = array(); 1117 foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) { 1118 foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) { 1119 if( is_array( $t_callback_menu_options ) ) { 1120 $t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options ); 1121 } else { 1122 if ( !is_null( $t_callback_menu_options ) ) { 1123 $t_menu_options[] = $t_callback_menu_options; 1124 } 1125 } 1126 } 1127 } 1128 1129 echo '<div id="account-menu">'; 1130 echo '<ul class="menu">'; 1131 foreach ( $t_pages as $t_page ) { 1132 if( $t_page['url'] == '' ) { 1133 echo '<li>', lang_get( $t_page['label'] ), '</li>'; 1134 } else { 1135 echo '<li><a href="'. helper_mantis_url( $t_page['url'] ) .'">' . lang_get( $t_page['label'] ) . '</a></li>'; 1136 } 1137 } 1138 1139 // Plugins menu items - these are cooked links 1140 foreach ( $t_menu_options as $t_menu_item ) { 1141 echo '<li>', $t_menu_item, '</li>'; 1142 } 1143 echo '</ul>'; 1144 echo '</div>'; 1145 } 1146 1147 /** 1148 * Print the menu for the docs section 1149 * @param string $p_page specifies the current page name so it's link can be disabled 1150 * @return null 1151 */ 1152 function print_doc_menu( $p_page = '' ) { 1153 $t_documentation_html = config_get( 'manual_url' ); 1154 $t_pages[$t_documentation_html] = array( 'url'=>$t_documentation_html, 'label'=>'user_documentation' ); 1155 $t_pages['proj_doc_page.php'] = array( 'url'=>'proj_doc_page.php', 'label'=>'project_documentation' ); 1156 if( file_allow_project_upload() ) { 1157 $t_pages['proj_doc_add_page.php'] = array( 'url'=>'proj_doc_add_page.php', 'label'=>'add_file' ); 1158 } 1159 1160 # Remove the link from the current page 1161 if ( isset( $t_pages[$p_page] ) ) { 1162 $t_pages[$p_page]['url'] = ''; 1163 } 1164 1165 echo '<div id="doc-menu">'; 1166 echo '<ul class="menu">'; 1167 foreach ( $t_pages as $t_page ) { 1168 if( $t_page['url'] == '' ) { 1169 echo '<li>', lang_get( $t_page['label'] ), '</li>'; 1170 } else { 1171 echo '<li><a href="'. helper_mantis_url( $t_page['url'] ) .'">' . lang_get( $t_page['label'] ) . '</a></li>'; 1172 } 1173 } 1174 echo '</ul>'; 1175 echo '</div>'; 1176 } 1177 1178 /** 1179 * Print the menu for the summary section 1180 * @param string $p_page specifies the current page name so it's link can be disabled 1181 * @return null 1182 */ 1183 function print_summary_menu( $p_page = '' ) { 1184 # Plugin / Event added options 1185 $t_event_menu_options = event_signal( 'EVENT_MENU_SUMMARY' ); 1186 $t_menu_options = array(); 1187 foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) { 1188 foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) { 1189 if( is_array( $t_callback_menu_options ) ) { 1190 $t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options ); 1191 } else { 1192 if ( !is_null( $t_callback_menu_options ) ) { 1193 $t_menu_options[] = $t_callback_menu_options; 1194 } 1195 } 1196 } 1197 } 1198 1199 $t_pages['print_all_bug_page.php'] = array( 'url'=>'print_all_bug_page.php', 'label'=>'print_all_bug_page_link' ); 1200 $t_pages['summary_page.php'] = array( 'url'=>'summary_page.php', 'label'=>'summary_link' ); 1201 # Remove the link from the current page 1202 if ( isset( $t_pages[$p_page] ) ) { 1203 $t_pages[$p_page]['url'] = ''; 1204 } 1205 1206 echo '<div id="summary-menu">'; 1207 echo '<ul class="menu">'; 1208 1209 foreach ( $t_pages as $t_page ) { 1210 if( $t_page['url'] == '' ) { 1211 echo '<li>', lang_get( $t_page['label'] ), '</li>'; 1212 } else { 1213 echo '<li><a href="'. helper_mantis_url( $t_page['url'] ) .'">' . lang_get( $t_page['label'] ) . '</a></li>'; 1214 } 1215 } 1216 1217 // Plugins menu items - these are cooked links 1218 foreach ( $t_menu_options as $t_menu_item ) { 1219 echo '<li>', $t_menu_item, '</li>'; 1220 } 1221 echo '</ul>'; 1222 echo '</div>'; 1223 } 1224 1225 /** 1226 * Print the color legend for the status colors 1227 * @param string 1228 * @return null 1229 */ 1230 function html_status_legend() { 1231 # Don't show the legend if only one status is selected by the current filter 1232 $t_current_filter = current_user_get_bug_filter(); 1233 if ( $t_current_filter === false ) { 1234 $t_current_filter = filter_get_default(); 1235 } 1236 $t_simple_filter = $t_current_filter['_view_type'] == 'simple'; 1237 if( $t_simple_filter ) { 1238 if( !filter_field_is_any( $t_current_filter[FILTER_PROPERTY_STATUS][0] ) ) { 1239 return null; 1240 } 1241 } 1242 1243 $t_status_array = MantisEnum::getAssocArrayIndexedByValues( config_get( 'status_enum_string' ) ); 1244 $t_status_names = MantisEnum::getAssocArrayIndexedByValues( lang_get( 'status_enum_string' ) ); 1245 $enum_count = count( $t_status_array ); 1246 1247 # read through the list and eliminate unused ones for the selected project 1248 # assumes that all status are are in the enum array 1249 $t_workflow = config_get( 'status_enum_workflow' ); 1250 if( !empty( $t_workflow ) ) { 1251 foreach( $t_status_array as $t_status => $t_name ) { 1252 if( !isset( $t_workflow[$t_status] ) ) { 1253 1254 # drop elements that are not in the workflow 1255 unset( $t_status_array[$t_status] ); 1256 } 1257 } 1258 } 1259 1260 # Remove status values that won't appear as a result of the current filter 1261 foreach( $t_status_array as $t_status => $t_name ) { 1262 if( $t_simple_filter ) { 1263 if( !filter_field_is_none( $t_current_filter[FILTER_PROPERTY_HIDE_STATUS][0] ) && 1264 $t_status >= $t_current_filter[FILTER_PROPERTY_HIDE_STATUS][0] ) { 1265 unset( $t_status_array[$t_status] ); 1266 } 1267 } else { 1268 if( !in_array( META_FILTER_ANY, $t_current_filter[FILTER_PROPERTY_STATUS] ) && 1269 !in_array( $t_status, $t_current_filter[FILTER_PROPERTY_STATUS] ) ) { 1270 unset( $t_status_array[$t_status] ); 1271 } 1272 } 1273 } 1274 1275 # If there aren't at least two statuses showable by the current filter, 1276 # don't draw the status bar 1277 if( count( $t_status_array ) <= 1 ) { 1278 return null; 1279 } 1280 1281 echo '<br />'; 1282 echo '<table class="status-legend width100" cellspacing="1">'; 1283 echo '<tr>'; 1284 1285 # draw the status bar 1286 $width = (int)( 100 / count( $t_status_array ) ); 1287 $t_status_enum_string = config_get('status_enum_string' ); 1288 foreach( $t_status_array as $t_status => $t_name ) { 1289 $t_val = $t_status_names[$t_status]; 1290 $t_status_label = MantisEnum::getLabel( $t_status_enum_string, $t_status ); 1291 1292 echo "<td class=\"small-caption $t_status_label-color\">$t_val</td>"; 1293 } 1294 1295 echo '</tr>'; 1296 echo '</table>'; 1297 if( ON == config_get( 'status_percentage_legend' ) ) { 1298 html_status_percentage_legend(); 1299 } 1300 } 1301 1302 /** 1303 * Print the legend for the status percentage 1304 * @return null 1305 */ 1306 function html_status_percentage_legend() { 1307 $t_status_percents = get_percentage_by_status(); 1308 $t_status_enum_string = config_get('status_enum_string' ); 1309 $t_enum_values = MantisEnum::getValues( $t_status_enum_string ); 1310 $enum_count = count( $t_enum_values ); 1311 1312 $t_bug_count = array_sum( $t_status_percents ); 1313 1314 if( $t_bug_count > 0 ) { 1315 echo '<br />'; 1316 echo '<table class="width100" cellspacing="1">'; 1317 echo '<tr>'; 1318 echo '<td class="form-title" colspan="' . $enum_count . '">' . lang_get( 'issue_status_percentage' ) . '</td>'; 1319 echo '</tr>'; 1320 echo '<tr>'; 1321 1322 foreach ( $t_enum_values as $t_status ) { 1323 $t_percent = ( isset( $t_status_percents[$t_status] ) ? $t_status_percents[$t_status] : 0 ); 1324 1325 if( $t_percent > 0 ) { 1326 $t_status_label = MantisEnum::getLabel( $t_status_enum_string, $t_status ); 1327 echo "<td class=\"small-caption-center $t_status_label-color $t_status_label-percentage\">$t_percent%</td>"; 1328 } 1329 } 1330 1331 echo '</tr>'; 1332 echo '</table>'; 1333 } 1334 } 1335 1336 /** 1337 * Print an html button inside a form 1338 * @param string $p_action 1339 * @param string $p_buttion_text 1340 * @param array $p_fields 1341 * @param string $p_method 1342 * @return null 1343 */ 1344 function html_button( $p_action, $p_button_text, $p_fields = null, $p_method = 'post' ) { 1345 $t_form_name = explode( '.php', $p_action, 2 ); 1346 $p_action = urlencode( $p_action ); 1347 $p_button_text = string_attribute( $p_button_text ); 1348 if( null === $p_fields ) { 1349 $p_fields = array(); 1350 } 1351 1352 if( utf8_strtolower( $p_method ) == 'get' ) { 1353 $t_method = 'get'; 1354 } else { 1355 $t_method = 'post'; 1356 } 1357 1358 echo "<form method=\"$t_method\" action=\"$p_action\" class=\"action-button\">\n"; 1359 echo "\t<fieldset>"; 1360 # Add a CSRF token only when the form is being sent via the POST method 1361 if ( $t_method == 'post' ) { 1362 echo form_security_field( $t_form_name[0] ); 1363 } 1364 1365 foreach( $p_fields as $key => $val ) { 1366 $key = string_attribute( $key ); 1367 $val = string_attribute( $val ); 1368 1369 echo "\t\t<input type=\"hidden\" name=\"$key\" value=\"$val\" />\n"; 1370 } 1371 1372 echo "\t\t<input type=\"submit\" class=\"button\" value=\"$p_button_text\" />\n"; 1373 echo "\t</fieldset>"; 1374 echo "</form>\n"; 1375 } 1376 1377 /** 1378 * Print a button to update the given bug 1379 * @param int $p_bug_id 1380 * @return null 1381 */ 1382 function html_button_bug_update( $p_bug_id ) { 1383 if( access_has_bug_level( config_get( 'update_bug_threshold' ), $p_bug_id ) ) { 1384 html_button( string_get_bug_update_page(), lang_get( 'update_bug_button' ), array( 'bug_id' => $p_bug_id ) ); 1385 } 1386 } 1387 1388 /** 1389 * Print Change Status to: button 1390 * This code is similar to print_status_option_list except 1391 * there is no masking, except for the current state 1392 * 1393 * @param int $p_bug_id 1394 * @return null 1395 */ 1396 function html_button_bug_change_status( $p_bug_id ) { 1397 $t_bug_project_id = bug_get_field( $p_bug_id, 'project_id' ); 1398 $t_bug_current_state = bug_get_field( $p_bug_id, 'status' ); 1399 $t_current_access = access_get_project_level( $t_bug_project_id ); 1400 1401 $t_enum_list = get_status_option_list( $t_current_access, $t_bug_current_state, false, ( bug_get_field( $p_bug_id, 'reporter_id' ) == auth_get_current_user_id() && ( ON == config_get( 'allow_reporter_close' ) ) ), $t_bug_project_id ); 1402 1403 if( count( $t_enum_list ) > 0 ) { 1404 1405 # resort the list into ascending order after noting the key from the first element (the default) 1406 $t_default_arr = each( $t_enum_list ); 1407 $t_default = $t_default_arr['key']; 1408 ksort( $t_enum_list ); 1409 reset( $t_enum_list ); 1410 1411 echo "<form method=\"post\" action=\"bug_change_status_page.php\">"; 1412 # CSRF protection not required here - form does not result in modifications 1413 1414 $t_button_text = lang_get( 'bug_status_to_button' ); 1415 echo "<input type=\"submit\" class=\"button\" value=\"$t_button_text\" />"; 1416 1417 echo " <select name=\"new_status\">"; 1418 1419 # space at beginning of line is important 1420 foreach( $t_enum_list as $key => $val ) { 1421 echo "<option value=\"$key\" "; 1422 check_selected( $key, $t_default ); 1423 echo ">$val</option>"; 1424 } 1425 echo '</select>'; 1426 1427 $t_bug_id = string_attribute( $p_bug_id ); 1428 echo "<input type=\"hidden\" name=\"id\" value=\"$t_bug_id\" />\n"; 1429 1430 echo "</form>\n"; 1431 } 1432 } 1433 1434 /** 1435 * Print Assign To: combo box of possible handlers 1436 * @param int $p_bug_id 1437 * @return null 1438 */ 1439 function html_button_bug_assign_to( $p_bug_id ) { 1440 1441 # make sure status is allowed of assign would cause auto-set-status 1442 $t_status = bug_get_field( $p_bug_id, 'status' ); 1443 1444 # workflow implementation 1445 1446 if( ON == config_get( 'auto_set_status_to_assigned' ) && !bug_check_workflow( $t_status, config_get( 'bug_assigned_status' ) ) ) { 1447 1448 # workflow 1449 return; 1450 } 1451 1452 # make sure current user has access to modify bugs. 1453 if( !access_has_bug_level( config_get( 'update_bug_assign_threshold', config_get( 'update_bug_threshold' ) ), $p_bug_id ) ) { 1454 return; 1455 } 1456 1457 $t_reporter_id = bug_get_field( $p_bug_id, 'reporter_id' ); 1458 $t_handler_id = bug_get_field( $p_bug_id, 'handler_id' ); 1459 $t_current_user_id = auth_get_current_user_id(); 1460 $t_new_status = ( ON == config_get( 'auto_set_status_to_assigned' ) ) ? config_get( 'bug_assigned_status' ) : $t_status; 1461 1462 $t_options = array(); 1463 $t_default_assign_to = null; 1464 1465 if(( $t_handler_id != $t_current_user_id ) && ( access_has_bug_level( config_get( 'handle_bug_threshold' ), $p_bug_id, $t_current_user_id ) ) ) { 1466 $t_options[] = array( 1467 $t_current_user_id, 1468 '[' . lang_get( 'myself' ) . ']', 1469 ); 1470 $t_default_assign_to = $t_current_user_id; 1471 } 1472 1473 if(( $t_handler_id != $t_reporter_id ) && user_exists( $t_reporter_id ) && ( access_has_bug_level( config_get( 'handle_bug_threshold' ), $p_bug_id, $t_reporter_id ) ) ) { 1474 $t_options[] = array( 1475 $t_reporter_id, 1476 '[' . lang_get( 'reporter' ) . ']', 1477 ); 1478 1479 if( $t_default_assign_to === null ) { 1480 $t_default_assign_to = $t_reporter_id; 1481 } 1482 } 1483 1484 echo "<form method=\"post\" action=\"bug_update.php\">"; 1485 echo form_security_field( 'bug_update' ); 1486 1487 $t_button_text = lang_get( 'bug_assign_to_button' ); 1488 echo "<input type=\"submit\" class=\"button\" value=\"$t_button_text\" />"; 1489 1490 echo " <select name=\"handler_id\">"; 1491 1492 # space at beginning of line is important 1493 1494 $t_already_selected = false; 1495 1496 foreach( $t_options as $t_entry ) { 1497 $t_id = string_attribute( $t_entry[0] ); 1498 $t_caption = string_attribute( $t_entry[1] ); 1499 1500 # if current user and reporter can't be selected, then select the first 1501 # user in the list. 1502 if( $t_default_assign_to === null ) { 1503 $t_default_assign_to = $t_id; 1504 } 1505 1506 echo '<option value="' . $t_id . '" '; 1507 1508 if(( $t_id == $t_default_assign_to ) && !$t_already_selected ) { 1509 check_selected( $t_id, $t_default_assign_to ); 1510 $t_already_selected = true; 1511 } 1512 1513 echo '>' . $t_caption . '</option>'; 1514 } 1515 1516 # allow un-assigning if already assigned. 1517 if( $t_handler_id != 0 ) { 1518 echo "<option value=\"0\"></option>"; 1519 } 1520 1521 $t_project_id = bug_get_field( $p_bug_id, 'project_id' ); 1522 1523 # 0 means currently selected 1524 print_assign_to_option_list( 0, $t_project_id ); 1525 echo "</select>"; 1526 1527 $t_bug_id = string_attribute( $p_bug_id ); 1528 echo "<input type=\"hidden\" name=\"bug_id\" value=\"$t_bug_id\" />\n"; 1529 1530 echo "</form>\n"; 1531 } 1532 1533 /** 1534 * Print a button to move the given bug to a different project 1535 * @param int $p_bug_id 1536 * @return null 1537 */ 1538 function html_button_bug_move( $p_bug_id ) { 1539 if( access_has_bug_level( config_get( 'move_bug_threshold' ), $p_bug_id ) ) { 1540 html_button( 'bug_actiongroup_page.php', lang_get( 'move_bug_button' ), array( 'bug_arr[]' => $p_bug_id, 'action' => 'MOVE' ) ); 1541 } 1542 } 1543 1544 /** 1545 * Print a button to move the given bug to a different project 1546 * @param int $p_bug_id 1547 * @return null 1548 */ 1549 function html_button_bug_create_child( $p_bug_id ) { 1550 if( access_has_bug_level( config_get( 'update_bug_threshold' ), $p_bug_id ) ) { 1551 html_button( string_get_bug_report_url(), lang_get( 'create_child_bug_button' ), array( 'm_id' => $p_bug_id ) ); 1552 } 1553 } 1554 1555 /** 1556 * Print a button to reopen the given bug 1557 * @param int $p_bug_id 1558 * @return null 1559 */ 1560 function html_button_bug_reopen( $p_bug_id ) { 1561 $t_status = bug_get_field( $p_bug_id, 'status' ); 1562 $t_project = bug_get_field( $p_bug_id, 'project_id' ); 1563 $t_reopen_status = config_get( 'bug_reopen_status', null, null, $t_project ); 1564 1565 if( access_has_bug_level( config_get( 'reopen_bug_threshold', null, null, $t_project ), $p_bug_id ) || 1566 (( bug_get_field( $p_bug_id, 'reporter_id' ) == auth_get_current_user_id() ) && ( ON == config_get( 'allow_reporter_reopen', null, null, $t_project ) ) ) ) { 1567 html_button( 'bug_change_status_page.php', lang_get( 'reopen_bug_button' ), array( 'id' => $p_bug_id, 'new_status' => $t_reopen_status, 'reopen_flag' => ON ) ); 1568 } 1569 } 1570 1571 /** 1572 * Print a button to monitor the given bug 1573 * @param int $p_bug_id 1574 * @return null 1575 */ 1576 function html_button_bug_monitor( $p_bug_id ) { 1577 if( access_has_bug_level( config_get( 'monitor_bug_threshold' ), $p_bug_id ) ) { 1578 html_button( 'bug_monitor_add.php', lang_get( 'monitor_bug_button' ), array( 'bug_id' => $p_bug_id ) ); 1579 } 1580 } 1581 1582 /** 1583 * Print a button to unmonitor the given bug 1584 * no reason to ever disallow someone from unmonitoring a bug 1585 * @param int $p_bug_id 1586 * @return null 1587 */ 1588 function html_button_bug_unmonitor( $p_bug_id ) { 1589 html_button( 'bug_monitor_delete.php', lang_get( 'unmonitor_bug_button' ), array( 'bug_id' => $p_bug_id ) ); 1590 } 1591 1592 /** 1593 * Print a button to stick the given bug 1594 * @param int $p_bug_id 1595 * @return null 1596 */ 1597 function html_button_bug_stick( $p_bug_id ) { 1598 if ( access_has_bug_level( config_get( 'set_bug_sticky_threshold' ), $p_bug_id ) ) { 1599 html_button( 'bug_stick.php', lang_get( 'stick_bug_button' ), array( 'bug_id' => $p_bug_id, 'action' => 'stick' ) ); 1600 } 1601 } 1602 1603 /** 1604 * Print a button to unstick the given bug 1605 * @param int $p_bug_id 1606 * @return null 1607 */ 1608 function html_button_bug_unstick( $p_bug_id ) { 1609 if ( access_has_bug_level( config_get( 'set_bug_sticky_threshold' ), $p_bug_id ) ) { 1610 html_button( 'bug_stick.php', lang_get( 'unstick_bug_button' ), array( 'bug_id' => $p_bug_id, 'action' => 'unstick' ) ); 1611 } 1612 } 1613 1614 /** 1615 * Print a button to delete the given bug 1616 * @param int $p_bug_id 1617 * @return null 1618 */ 1619 function html_button_bug_delete( $p_bug_id ) { 1620 if( access_has_bug_level( config_get( 'delete_bug_threshold' ), $p_bug_id ) ) { 1621 html_button( 'bug_actiongroup_page.php', lang_get( 'delete_bug_button' ), array( 'bug_arr[]' => $p_bug_id, 'action' => 'DELETE' ) ); 1622 } 1623 } 1624 1625 /** 1626 * Print a button to create a wiki page 1627 * @param int $p_bug_id 1628 * @return null 1629 */ 1630 function html_button_wiki( $p_bug_id ) { 1631 if( config_get_global( 'wiki_enable' ) == ON ) { 1632 if( access_has_bug_level( config_get( 'update_bug_threshold' ), $p_bug_id ) ) { 1633 html_button( 'wiki.php', lang_get_defaulted( 'Wiki' ), array( 'id' => $p_bug_id, 'type' => 'issue' ), 'get' ); 1634 } 1635 } 1636 } 1637 1638 /** 1639 * Print all buttons for view bug pages 1640 * @param int $p_bug_id 1641 * @return null 1642 */ 1643 function html_buttons_view_bug_page( $p_bug_id ) { 1644 $t_resolved = config_get( 'bug_resolved_status_threshold' ); 1645 $t_status = bug_get_field( $p_bug_id, 'status' ); 1646 $t_readonly = bug_is_readonly( $p_bug_id ); 1647 $t_sticky = config_get( 'set_bug_sticky_threshold' ); 1648 1649 echo '<table><tr class="vcenter">'; 1650 if( !$t_readonly ) { 1651 # UPDATE button 1652 echo '<td class="center">'; 1653 html_button_bug_update( $p_bug_id ); 1654 echo '</td>'; 1655 1656 # ASSIGN button 1657 echo '<td class="center">'; 1658 html_button_bug_assign_to( $p_bug_id ); 1659 echo '</td>'; 1660 } 1661 1662 # Change status button/dropdown 1663 if ( !$t_readonly || config_get( 'allow_reporter_close' ) ) { 1664 echo '<td class="center">'; 1665 html_button_bug_change_status( $p_bug_id ); 1666 echo '</td>'; 1667 } 1668 1669 # MONITOR/UNMONITOR button 1670 if( !current_user_is_anonymous() ) { 1671 echo '<td class="center">'; 1672 if( user_is_monitoring_bug( auth_get_current_user_id(), $p_bug_id ) ) { 1673 html_button_bug_unmonitor( $p_bug_id ); 1674 } else { 1675 html_button_bug_monitor( $p_bug_id ); 1676 } 1677 echo '</td>'; 1678 } 1679 1680 # STICK/UNSTICK button 1681 if ( access_has_bug_level( $t_sticky, $p_bug_id ) ) { 1682 echo '<td class="center">'; 1683 if ( !bug_get_field( $p_bug_id, 'sticky' ) ) { 1684 html_button_bug_stick( $p_bug_id ); 1685 } else { 1686 html_button_bug_unstick( $p_bug_id ); 1687 } 1688 echo '</td>'; 1689 } 1690 1691 if( !$t_readonly ) { 1692 # CREATE CHILD button 1693 echo '<td class="center">'; 1694 html_button_bug_create_child( $p_bug_id ); 1695 echo '</td>'; 1696 } 1697 1698 if( $t_resolved <= $t_status ) { 1699 # resolved is not the same as readonly 1700 echo '<td class="center">'; 1701 1702 # REOPEN button 1703 html_button_bug_reopen( $p_bug_id ); 1704 echo '</td>'; 1705 } 1706 1707 # MOVE button 1708 echo '<td class="center">'; 1709 html_button_bug_move( $p_bug_id ); 1710 echo '</td>'; 1711 1712 # DELETE button 1713 echo '<td class="center">'; 1714 html_button_bug_delete( $p_bug_id ); 1715 echo '</td>'; 1716 1717 helper_call_custom_function( 'print_bug_view_page_custom_buttons', array( $p_bug_id ) ); 1718 1719 echo '</tr></table>'; 1720 } 1721 1722 /** 1723 * get the css class name for the given status 1724 * @param int $p_status 1725 * @return string 1726 */ 1727 function html_get_status_css_class( $p_status ) { 1728 return string_attribute( MantisEnum::getLabel( config_get('status_enum_string' ), $p_status ) . '-color' ); 1729 }
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 |