PageRenderTime 10ms CodeModel.GetById 25ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 0ms

/core/html_api.php

https://github.com/markkimsal/mantisbt
PHP | 1798 lines | 1124 code | 237 blank | 437 comment | 223 complexity | 670e2e73235e2b265c5b9ada6f196e8c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   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 - 2010  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
  84require_api( 'access_api.php' );
  85require_api( 'authentication_api.php' );
  86require_api( 'bug_api.php' );
  87require_api( 'config_api.php' );
  88require_api( 'constant_inc.php' );
  89require_api( 'current_user_api.php' );
  90require_api( 'database_api.php' );
  91require_api( 'error_api.php' );
  92require_api( 'event_api.php' );
  93require_api( 'file_api.php' );
  94require_api( 'filter_api.php' );
  95require_api( 'filter_constants_inc.php' );
  96require_api( 'form_api.php' );
  97require_api( 'helper_api.php' );
  98require_api( 'lang_api.php' );
  99require_api( 'news_api.php' );
 100require_api( 'php_api.php' );
 101require_api( 'print_api.php' );
 102require_api( 'project_api.php' );
 103require_api( 'rss_api.php' );
 104require_api( 'string_api.php' );
 105require_api( 'user_api.php' );
 106require_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 */
 124function 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 */
 136function 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 */
 145function 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="', $g_rss_feed_url, '" />';
 150	}
 151}
 152
 153/**
 154 * Prints a <script> tag to include a javascript file.
 155 * This includes either minimal or development file from /javascript depending on whether mantis is set for debug/production use
 156 * @param string $p_filename
 157 * @return null
 158 */
 159function html_javascript_link( $p_filename) {
 160	if( config_get_global( 'minimal_jscss' ) ) {
 161		echo "\t", '<script type="text/javascript" src="', helper_mantis_url( 'javascript/min/' . $p_filename ), '"></script>' . "\n";
 162	} else {
 163		echo "\t", '<script type="text/javascript" src="', helper_mantis_url( 'javascript/dev/' . $p_filename ), '"></script>' . "\n";
 164	}
 165}
 166
 167/**
 168 * Defines the top of a HTML page
 169 * @param string $p_page_title html page title
 170 * @param string $p_redirect_url url to redirect to if necessary
 171 * @return null
 172 */
 173function html_page_top( $p_page_title = null, $p_redirect_url = null ) {
 174	html_page_top1( $p_page_title );
 175	if ( $p_redirect_url !== null ) {
 176		html_meta_redirect( $p_redirect_url );
 177	}
 178	html_page_top2();
 179}
 180
 181/**
 182 * Print the part of the page that comes before meta redirect tags should be inserted
 183 * @param string $p_page_title page title
 184 * @return null
 185 */
 186function html_page_top1( $p_page_title = null ) {
 187	html_begin();
 188	html_head_begin();
 189	html_css();
 190	html_content_type();
 191	include( config_get( 'meta_include_file' ) );
 192
 193	global $g_robots_meta;
 194	if ( !is_blank( $g_robots_meta ) ) {
 195		echo "\t", '<meta name="robots" content="', $g_robots_meta, '" />', "\n";
 196	}
 197
 198	html_rss_link();
 199
 200	$t_favicon_image = config_get( 'favicon_image' );
 201	if( !is_blank( $t_favicon_image ) ) {
 202		echo "\t", '<link rel="shortcut icon" href="', helper_mantis_url( $t_favicon_image ), '" type="image/x-icon" />', "\n";
 203	}
 204
 205	// Advertise the availability of the browser search plug-ins.
 206	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";
 207	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";
 208
 209	html_title( $p_page_title );
 210	html_head_javascript();
 211}
 212
 213/**
 214 * Print the part of the page that comes after meta tags, but before the actual page content
 215 * @return null
 216 */
 217function html_page_top2() {
 218	html_page_top2a();
 219
 220	if( !db_is_connected() ) {
 221		return;
 222	}
 223
 224	if( auth_is_user_authenticated() ) {
 225		html_login_info();
 226
 227		if( ON == config_get( 'show_project_menu_bar' ) ) {
 228			print_project_menu_bar();
 229			echo '<br />';
 230		}
 231	}
 232	print_menu();
 233
 234	event_signal( 'EVENT_LAYOUT_CONTENT_BEGIN' );
 235}
 236
 237/**
 238 * Print the part of the page that comes after meta tags and before the
 239 *  actual page content, but without login info or menus.  This is used
 240 *  directly during the login process and other times when the user may
 241 *  not be authenticated
 242 * @return null
 243 */
 244function html_page_top2a() {
 245	global $g_error_send_page_header;
 246
 247	html_head_end();
 248	html_body_begin();
 249	$g_error_send_page_header = false;
 250	html_header();
 251	html_top_banner();
 252}
 253
 254/**
 255 * Print the part of the page that comes below the page content
 256 * $p_file should always be the __FILE__ variable. This is passed to show source
 257 * @param string $p_file should always be the __FILE__ variable. This is passed to show source
 258 * @return null
 259 */
 260function html_page_bottom( $p_file = null ) {
 261	html_page_bottom1( $p_file );
 262}
 263
 264/**
 265 * Print the part of the page that comes below the page content
 266 * $p_file should always be the __FILE__ variable. This is passed to show source
 267 * @param string $p_file should always be the __FILE__ variable. This is passed to show source
 268 * @return null
 269 */
 270function html_page_bottom1( $p_file = null ) {
 271	if( !db_is_connected() ) {
 272		return;
 273	}
 274
 275	event_signal( 'EVENT_LAYOUT_CONTENT_END' );
 276
 277	if( config_get( 'show_footer_menu' ) ) {
 278		echo '<br />';
 279		print_menu();
 280	}
 281
 282	html_page_bottom1a( $p_file );
 283}
 284
 285/**
 286 * Print the part of the page that comes below the page content but leave off
 287 *  the menu.  This is used during the login process and other times when the
 288 *  user may not be authenticated.
 289 * @param string $p_file should always be the __FILE__ variable.
 290 * @return null
 291 */
 292function html_page_bottom1a( $p_file = null ) {
 293	if( null === $p_file ) {
 294		$p_file = basename( $_SERVER['SCRIPT_NAME'] );
 295	}
 296
 297	html_bottom_banner();
 298	html_footer();
 299	html_body_end();
 300	html_end();
 301}
 302
 303/**
 304 * (1) Print the document type and the opening <html> tag
 305 * @return null
 306 */
 307function html_begin() {
 308	echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">', "\n";
 309	echo '<html xmlns="http://www.w3.org/1999/xhtml">', "\n";
 310}
 311
 312/**
 313 * (2) Begin the <head> section
 314 * @return null
 315 */
 316function html_head_begin() {
 317	echo '<head>', "\n";
 318}
 319
 320/**
 321 * (3) Print the content-type
 322 * @return null
 323 */
 324function html_content_type() {
 325	echo "\t", '<meta http-equiv="Content-type" content="text/html; charset=utf-8" />', "\n";
 326}
 327
 328/**
 329 * (4) Print the window title
 330 * @param string $p_page_title window title
 331 * @return null
 332 */
 333function html_title( $p_page_title = null ) {
 334	$t_page_title = string_html_specialchars( $p_page_title );
 335	$t_title = string_html_specialchars( config_get( 'window_title' ) );
 336	echo "\t", '<title>';
 337	if( empty( $t_page_title ) ) {
 338		echo $t_title;
 339	} else {
 340		if( empty( $t_title ) ) {
 341			echo $t_page_title;
 342		} else {
 343			echo $t_page_title . ' - ' . $t_title;
 344		}
 345	}
 346	echo '</title>', "\n";
 347}
 348
 349function require_css( $p_stylesheet_path ) {
 350	global $g_stylesheets_included;
 351	$g_stylesheets_included[$p_stylesheet_path] = $p_stylesheet_path;
 352}
 353
 354/**
 355 * (5) Print the link to include the css file
 356 * @return null
 357 */
 358function html_css() {
 359	global $g_stylesheets_included;
 360	html_css_link( config_get( 'css_include_file' ) );
 361	html_css_link( 'jquery-ui.css' );
 362	# Add right-to-left css if needed
 363	if ( lang_get( 'directionality' ) == 'rtl' ) {
 364		html_css_link( config_get( 'css_rtl_include_file' ) );
 365	}
 366	foreach ( $g_stylesheets_included as $t_stylesheet_path ) {
 367		html_css_link ( $t_stylesheet_path );
 368	}
 369}
 370
 371/**
 372 * Prints a css link
 373 * @return null
 374 */
 375function html_css_link( $p_filename ) {
 376	echo "\t", '<link rel="stylesheet" type="text/css" href="', string_sanitize_url( helper_mantis_url( 'css/' . $p_filename ), true ), '" >' . "\n";
 377}
 378
 379
 380/**
 381 * (6) Print an HTML meta tag to redirect to another page
 382 * This function is optional and may be called by pages that need a redirect.
 383 * $p_time is the number of seconds to wait before redirecting.
 384 * If we have handled any errors on this page and the 'stop_on_errors' config
 385 *  option is turned on, return false and don't redirect.
 386 *
 387 * @param string $p_url The page to redirect: has to be a relative path
 388 * @param integer $p_time seconds to wait for before redirecting
 389 * @param boolean $p_sanitize apply string_sanitize_url to passed url
 390 * @return boolean
 391 */
 392function html_meta_redirect( $p_url, $p_time = null, $p_sanitize = true ) {
 393	if( ON == config_get_global( 'stop_on_errors' ) && error_handled() ) {
 394		return false;
 395	}
 396
 397	if( null === $p_time ) {
 398		$p_time = current_user_get_pref( 'redirect_delay' );
 399	}
 400
 401	$t_url = config_get( 'path' );
 402	if( $p_sanitize ) {
 403		$t_url .= string_sanitize_url( $p_url );
 404	} else {
 405		$t_url .= $p_url;
 406	}
 407
 408	$t_url = htmlspecialchars( $t_url );
 409
 410	echo "\t<meta http-equiv=\"Refresh\" content=\"$p_time;URL=$t_url\" />\n";
 411
 412	return true;
 413}
 414
 415function require_js( $p_script_path ) {
 416	global $g_scripts_included;
 417	$g_scripts_included[$p_script_path] = $p_script_path;
 418}
 419
 420/**
 421 * (6a) Javascript...
 422 * @return null
 423 */
 424function html_head_javascript() {
 425	if ( config_get( 'use_javascript' ) ) {
 426		global $g_scripts_included;
 427		echo "\t<script type=\"text/javascript\" src=\"" . helper_mantis_url( 'javascript_config.php' ) . '"></script>' . "\n";
 428		echo "\t<script type=\"text/javascript\" src=\"" . helper_mantis_url( 'javascript_translations.php' ) . '"></script>' . "\n";
 429		html_javascript_link( 'ajax.js' );
 430		html_javascript_link( 'jquery.js' );
 431		html_javascript_link( 'jquery-ui.js' );
 432		html_javascript_link( 'common.js' );
 433		foreach ( $g_scripts_included as $t_script_path ) {
 434			html_javascript_link( $t_script_path );
 435		}
 436	}
 437}
 438
 439/**
 440 * (7) End the <head> section
 441 * @return null
 442 */
 443function html_head_end() {
 444	event_signal( 'EVENT_LAYOUT_RESOURCES' );
 445
 446	echo '</head>', "\n";
 447}
 448
 449/**
 450 * (8) Begin the <body> section
 451 * @return null
 452 */
 453function html_body_begin() {
 454	echo '<body>', "\n";
 455
 456	event_signal( 'EVENT_LAYOUT_BODY_BEGIN' );
 457}
 458
 459/**
 460 * (9) Print the title displayed at the top of the page
 461 * @return null
 462 */
 463function html_header() {
 464	$t_title = config_get( 'page_title' );
 465	if( !is_blank( $t_title ) ) {
 466		echo '<div class="center"><span class="pagetitle">', string_display( $t_title ), '</span></div>', "\n";
 467	}
 468}
 469
 470/**
 471 * (10) Print a user-defined banner at the top of the page if there is one.
 472 * @return null
 473 */
 474function html_top_banner() {
 475	$t_page = config_get( 'top_include_page' );
 476	$t_logo_image = config_get( 'logo_image' );
 477	$t_logo_url = config_get( 'logo_url' );
 478
 479	if( is_blank( $t_logo_image ) ) {
 480		$t_show_logo = false;
 481	} else {
 482		$t_show_logo = true;
 483		if( is_blank( $t_logo_url ) ) {
 484			$t_show_url = false;
 485		} else {
 486			$t_show_url = true;
 487		}
 488	}
 489
 490	if( !is_blank( $t_page ) && file_exists( $t_page ) && !is_dir( $t_page ) ) {
 491		include( $t_page );
 492	} else if( $t_show_logo ) {
 493		if( is_page_name( 'login_page' ) ) {
 494			$t_align = 'center';
 495		} else {
 496			$t_align = 'left';
 497		}
 498
 499		echo '<div align="', $t_align, '">';
 500		if( $t_show_url ) {
 501			echo '<a href="', config_get( 'logo_url' ), '">';
 502		}
 503		echo '<img border="0" alt="Mantis Bug Tracker" src="' . helper_mantis_url( config_get( 'logo_image' ) ) . '" />';
 504		if( $t_show_url ) {
 505			echo '</a>';
 506		}
 507		echo '</div>';
 508	}
 509
 510	event_signal( 'EVENT_LAYOUT_PAGE_HEADER' );
 511}
 512
 513/**
 514 * (11) Print the user's account information
 515 * Also print the select box where users can switch projects
 516 * @return null
 517 */
 518function html_login_info() {
 519	$t_username = current_user_get_field( 'username' );
 520	$t_access_level = get_enum_element( 'access_levels', current_user_get_access_level() );
 521	$t_now = date( config_get( 'complete_date_format' ) );
 522	$t_realname = current_user_get_field( 'realname' );
 523
 524	echo '<table class="hide">';
 525	echo '<tr>';
 526	echo '<td class="login-info-left">';
 527	if( current_user_is_anonymous() ) {
 528		$t_return_page = $_SERVER['SCRIPT_NAME'];
 529		if( isset( $_SERVER['QUERY_STRING'] ) ) {
 530			$t_return_page .= '?' . $_SERVER['QUERY_STRING'];
 531		}
 532
 533		$t_return_page = string_url( $t_return_page );
 534		echo lang_get( 'anonymous' ) . ' | <a href="' . helper_mantis_url( 'login_page.php?return=' . $t_return_page ) . '">' . lang_get( 'login_link' ) . '</a>';
 535		if( config_get_global( 'allow_signup' ) == ON ) {
 536			echo ' | <a href="' . helper_mantis_url( 'signup_page.php' ) . '">' . lang_get( 'signup_link' ) . '</a>';
 537		}
 538	} else {
 539		echo lang_get( 'logged_in_as' ), ": <span class=\"italic\">", string_html_specialchars( $t_username ), "</span> <span class=\"small\">";
 540		echo is_blank( $t_realname ) ? "($t_access_level)" : "(" . string_html_specialchars( $t_realname ) . " - $t_access_level)";
 541		echo "</span>";
 542	}
 543	echo '</td>';
 544	echo '<td class="login-info-middle">';
 545	echo "<span class=\"italic\">$t_now</span>";
 546	echo '</td>';
 547	echo '<td class="login-info-right">';
 548	$t_show_project_selector = true;
 549	if( count( current_user_get_accessible_projects() ) == 1 ) {
 550
 551		// >1
 552		$t_project_ids = current_user_get_accessible_projects();
 553		$t_project_id = (int) $t_project_ids[0];
 554		if( count( current_user_get_accessible_subprojects( $t_project_id ) ) == 0 ) {
 555			$t_show_project_selector = false;
 556		}
 557	}
 558
 559	if( $t_show_project_selector ) {
 560		echo '<form method="post" name="form_set_project" action="' . helper_mantis_url( 'set_project.php' ) . '">';
 561		# CSRF protection not required here - form does not result in modifications
 562
 563		echo lang_get( 'email_project' ), ': ';
 564		if( ON == config_get( 'use_javascript' ) ) {
 565			echo '<select name="project_id" class="small" onchange="document.forms.form_set_project.submit();">';
 566		} else {
 567			echo '<select name="project_id" class="small">';
 568		}
 569		print_project_option_list( join( ';', helper_get_current_project_trace() ), true, null, true );
 570		echo '</select> ';
 571		echo '<input type="submit" class="button-small" value="' . lang_get( 'switch' ) . '" />';
 572		echo '</form>';
 573	}
 574	if( OFF != config_get( 'rss_enabled' ) ) {
 575
 576		# Link to RSS issues feed for the selected project, including authentication details.
 577		echo '<a href="' . htmlspecialchars( rss_get_issues_feed_url() ) . '">';
 578		echo '<img src="' . helper_mantis_url( 'images/rss.png' ) . '" alt="' . lang_get( 'rss' ) . '" style="border-style: none; margin: 5px; vertical-align: middle;" />';
 579		echo '</a>';
 580	}
 581
 582	echo '</td>';
 583	echo '</tr>';
 584	echo '</table>';
 585}
 586
 587/**
 588 * (12) Print a user-defined banner at the bottom of the page if there is one.
 589 * @return null
 590 */
 591function html_bottom_banner() {
 592	$t_page = config_get( 'bottom_include_page' );
 593
 594	if( !is_blank( $t_page ) && file_exists( $t_page ) && !is_dir( $t_page ) ) {
 595		include( $t_page );
 596	}
 597}
 598
 599/**
 600 * (13) Print the page footer information
 601 * @param string $p_file
 602 * @return null
 603 */
 604function html_footer( $p_file = null ) {
 605	global $g_queries_array, $g_request_time;
 606
 607	# If a user is logged in, update their last visit time.
 608	# We do this at the end of the page so that:
 609	#  1) we can display the user's last visit time on a page before updating it
 610	#  2) we don't invalidate the user cache immediately after fetching it
 611	#  3) don't do this on the password verification or update page, as it causes the
 612	#    verification comparison to fail
 613	if ( auth_is_user_authenticated() && !current_user_is_anonymous() && !( is_page_name( 'verify.php' ) || is_page_name( 'account_update.php' ) ) ) {
 614		$t_user_id = auth_get_current_user_id();
 615		user_update_last_visit( $t_user_id );
 616	}
 617
 618	echo "<div id=\"footer\">\n";
 619	echo "\t<hr />\n";
 620	echo "\t<div id=\"powered-by-mantisbt-logo\">\n";
 621	$t_mantisbt_logo_url = helper_mantis_url( 'images/mantis_logo_button.gif' );
 622	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";
 623	echo "\t</div>\n";
 624
 625	# Show optional user-specificed custom copyright statement
 626	$t_copyright_statement = config_get( 'copyright_statement' );
 627	if ( $t_copyright_statement ) {
 628		echo "\t<address id=\"user-copyright\">$t_copyright_statement</address>\n";
 629	}
 630
 631	# Show MantisBT version and copyright statement
 632	$t_version_suffix = '';
 633	$t_copyright_years = '';
 634	if ( config_get( 'show_version' ) ) {
 635		$t_version_suffix = htmlentities( ' ' . MANTIS_VERSION . config_get_global( 'version_suffix' ) );
 636		$t_copyright_years = ' 2000 - 2010';
 637	}
 638	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 &copy;$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";
 639
 640	# Show contact information
 641	$t_webmaster_contact_information = sprintf( lang_get( 'webmaster_contact_information' ), string_html_specialchars( config_get( 'webmaster_email' ) ) );
 642	echo "\t<address id=\"webmaster-contact-information\">$t_webmaster_contact_information</address>\n";
 643
 644	event_signal( 'EVENT_LAYOUT_PAGE_FOOTER' );
 645
 646	# Print horizontal rule if any debugging stats follow
 647	if ( config_get( 'show_timer' ) || config_get( 'show_memory_usage' ) || config_get( 'show_queries_count' ) ) {
 648		echo "\t<hr />\n";
 649	}
 650
 651	# Print the page execution time
 652	if ( config_get( 'show_timer' ) ) {
 653		$t_page_execution_time = sprintf( lang_get( 'page_execution_time' ), number_format( microtime( true ) - $g_request_time, 4 ) );
 654		echo "\t<p id=\"page-execution-time\">$t_page_execution_time</p>\n";
 655	}
 656
 657	# Print the page memory usage
 658	if ( config_get( 'show_memory_usage' ) ) {
 659		$t_page_memory_usage = sprintf( lang_get( 'memory_usage_in_kb' ), number_format( memory_get_peak_usage() / 1024 ) );
 660		echo "\t<p id=\"page-memory-usage\">$t_page_memory_usage</p>\n";
 661	}
 662
 663	# Determine number of unique queries executed
 664	if ( config_get( 'show_queries_count' ) || helper_show_queries() ) {
 665		$t_total_queries_count = count( $g_queries_array );
 666		$t_unique_queries_count = 0;
 667		$t_total_query_execution_time = 0;
 668		$t_unique_queries = array();
 669		for ( $i = 0; $i < $t_total_queries_count; $i++ ) {
 670			if ( !in_array( $g_queries_array[$i][0], $t_unique_queries ) ) {
 671				$t_unique_queries_count++;
 672				$g_queries_array[$i][3] = false;
 673				array_push( $t_unique_queries, $g_queries_array[$i][0] );
 674			} else {
 675				$g_queries_array[$i][3] = true;
 676			}
 677			$t_total_query_execution_time += $g_queries_array[$i][1];
 678		}
 679	}
 680
 681	# Print query counts
 682	if ( config_get( 'show_queries_count' ) ) {
 683		$t_total_queries_executed = sprintf( lang_get( 'total_queries_executed' ), $t_total_queries_count );
 684		echo "\t<p id=\"total-queries-count\">$t_total_queries_executed</p>\n";
 685		$t_unique_queries_executed = sprintf( lang_get( 'unique_queries_executed' ), $t_unique_queries_count );
 686		echo "\t<p id=\"unique-queries-count\">$t_unique_queries_executed</p>\n";
 687		$t_total_query_time = sprintf( lang_get( 'total_query_execution_time' ), $t_total_query_execution_time );
 688		echo "\t<p id=\"total-query-execution-time\">$t_total_query_time</p>\n";
 689	}
 690
 691	# Print table of database queries executed
 692	if ( helper_show_queries() ) {
 693		echo "\t<hr />\n";
 694		echo "\t<table id=\"query-list\">\n";
 695		echo "\t\t<caption>" . lang_get( 'sql_queries_list_caption' ) . "</caption>\n";
 696		echo "\t\t<thead>\n";
 697		echo "\t\t\t<tr>\n";
 698		echo "\t\t\t\t<th>" . lang_get( 'sql_query_number' ) . "</th>\n";
 699		echo "\t\t\t\t<th>" . lang_get( 'sql_query_time' ) . "</th>\n";
 700		echo "\t\t\t\t<th>" . lang_get( 'sql_query_caller' ) . "</th>\n";
 701		echo "\t\t\t\t<th>" . lang_get( 'sql_query' ) . "</th>\n";
 702		echo "\t\t\t</tr>\n";
 703		echo "\t\t</thead>\n";
 704		echo "\t\t<tbody>\n";
 705		for ( $t_query_number = 1; $t_query_number <= $t_total_queries_count; $t_query_number++ ) {
 706			$t_query_time = $g_queries_array[$t_query_number - 1][1];
 707			$t_query_caller = string_html_specialchars( $g_queries_array[$t_query_number - 1][2] );
 708			$t_query = string_html_specialchars( $g_queries_array[$t_query_number - 1][0] );
 709			$t_query_duplicate_class = '';
 710			if ( $g_queries_array[$t_query_number - 1][3] ) {
 711				$t_query_duplicate_class = ' class="duplicate-query"';
 712			}
 713			echo "\t\t\t<tr$t_query_duplicate_class>\n";
 714			echo "\t\t\t\t<td>$t_query_number</td>\n";
 715			echo "\t\t\t\t<td>$t_query_time</td>\n";
 716			echo "\t\t\t\t<td>$t_query_caller</td>\n";
 717			echo "\t\t\t\t<td>$t_query</td>\n";
 718			echo "\t\t\t</tr>\n";
 719		}
 720		echo "\t\t</tbody>\n";
 721		echo "\t</table>\n";
 722	}
 723
 724	echo "</div>\n";
 725}
 726
 727/**
 728 * (14) End the <body> section
 729 * @return null
 730 */
 731function html_body_end() {
 732	event_signal( 'EVENT_LAYOUT_BODY_END' );
 733
 734	echo '</body>', "\n";
 735}
 736
 737/**
 738 * (15) Print the closing <html> tag
 739 * @return null
 740 */
 741function html_end() {
 742	echo '</html>', "\n";
 743}
 744
 745/**
 746 * Prepare an array of additional menu options from a config variable
 747 * @param string $p_config config name
 748 * @return array
 749 */
 750function prepare_custom_menu_options( $p_config ) {
 751	$t_custom_menu_options = config_get( $p_config );
 752	$t_options = array();
 753
 754	foreach( $t_custom_menu_options as $t_custom_option ) {
 755		$t_access_level = $t_custom_option[1];
 756		if( access_has_project_level( $t_access_level ) ) {
 757			$t_caption = lang_get_defaulted( $t_custom_option[0] );
 758			$t_link = $t_custom_option[2];
 759			$t_options[] = "<a href=\"$t_link\">$t_caption</a>";
 760		}
 761	}
 762
 763	return $t_options;
 764}
 765
 766/**
 767 * Print the main menu
 768 * @return null
 769 */
 770function print_menu() {
 771	if( auth_is_user_authenticated() ) {
 772		$t_protected = current_user_get_field( 'protected' );
 773		$t_current_project = helper_get_current_project();
 774
 775		echo '<table class="width100" cellspacing="0">';
 776		echo '<tr>';
 777		echo '<td class="menu">';
 778		$t_menu_options = array();
 779
 780		# Main Page
 781		$t_menu_options[] = '<a href="' . helper_mantis_url( 'main_page.php' ) . '">' . lang_get( 'main_link' ) . '</a>';
 782
 783		# Plugin / Event added options
 784		$t_event_menu_options = event_signal( 'EVENT_MENU_MAIN_FRONT' );
 785		foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) {
 786			foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) {
 787				if( is_array( $t_callback_menu_options ) ) {
 788					$t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options );
 789				} else {
 790					if ( !is_null( $t_callback_menu_options ) ) {
 791						$t_menu_options[] = $t_callback_menu_options;
 792					}
 793				}
 794			}
 795		}
 796
 797		# My View
 798		$t_menu_options[] = '<a href="' . helper_mantis_url( 'my_view_page.php">' ) . lang_get( 'my_view_link' ) . '</a>';
 799
 800		# View Bugs
 801		$t_menu_options[] = '<a href="' . helper_mantis_url( 'view_all_bug_page.php">' ) . lang_get( 'view_bugs_link' ) . '</a>';
 802
 803		# Report Bugs
 804		if( access_has_project_level( config_get( 'report_bug_threshold' ) ) ) {
 805			$t_menu_options[] = string_get_bug_report_link();
 806		}
 807
 808		# Changelog Page
 809		if( access_has_project_level( config_get( 'view_changelog_threshold' ) ) ) {
 810			$t_menu_options[] = '<a href="' . helper_mantis_url( 'changelog_page.php">' ) . lang_get( 'changelog_link' ) . '</a>';
 811		}
 812
 813		# Roadmap Page
 814		if( access_has_project_level( config_get( 'roadmap_view_threshold' ) ) ) {
 815			$t_menu_options[] = '<a href="' . helper_mantis_url( 'roadmap_page.php">' ) . lang_get( 'roadmap_link' ) . '</a>';
 816		}
 817
 818		# Summary Page
 819		if( access_has_project_level( config_get( 'view_summary_threshold' ) ) ) {
 820			$t_menu_options[] = '<a href="' . helper_mantis_url( 'summary_page.php">' ) . lang_get( 'summary_link' ) . '</a>';
 821		}
 822
 823		# Project Documentation Page
 824		if( ON == config_get( 'enable_project_documentation' ) ) {
 825			$t_menu_options[] = '<a href="' . helper_mantis_url( 'proj_doc_page.php">' ) . lang_get( 'docs_link' ) . '</a>';
 826		}
 827
 828		# Project Wiki
 829		if( config_get_global( 'wiki_enable' ) == ON ) {
 830			$t_menu_options[] = '<a href="' . helper_mantis_url( 'wiki.php?type=project&amp;id=' ) . $t_current_project . '">' . lang_get( 'wiki' ) . '</a>';
 831		}
 832
 833		# Plugin / Event added options
 834		$t_event_menu_options = event_signal( 'EVENT_MENU_MAIN' );
 835		foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) {
 836			foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) {
 837				if( is_array( $t_callback_menu_options ) ) {
 838					$t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options );
 839				} else {
 840					if ( !is_null( $t_callback_menu_options ) ) {
 841						$t_menu_options[] = $t_callback_menu_options;
 842					}
 843				}
 844			}
 845		}
 846
 847		# Manage Users (admins) or Manage Project (managers) or Manage Custom Fields
 848		if( access_has_global_level( config_get( 'manage_site_threshold' ) ) ) {
 849			$t_link = helper_mantis_url( 'manage_overview_page.php' );
 850			$t_menu_options[] = "<a href=\"$t_link\">" . lang_get( 'manage_link' ) . '</a>';
 851		} else {
 852			$t_show_access = min( config_get( 'manage_user_threshold' ), config_get( 'manage_project_threshold' ), config_get( 'manage_custom_fields_threshold' ) );
 853			if( access_has_global_level( $t_show_access ) || access_has_any_project( $t_show_access ) ) {
 854				$t_current_project = helper_get_current_project();
 855				if( access_has_global_level( config_get( 'manage_user_threshold' ) ) ) {
 856					$t_link = helper_mantis_url( 'manage_user_page.php' );
 857				} else {
 858					if( access_has_project_level( config_get( 'manage_project_threshold' ), $t_current_project ) && ( $t_current_project <> ALL_PROJECTS ) ) {
 859						$t_link = helper_mantis_url( 'manage_proj_edit_page.php?project_id=' ) . $t_current_project;
 860					} else {
 861						$t_link = helper_mantis_url( 'manage_proj_page.php' );
 862					}
 863				}
 864				$t_menu_options[] = "<a href=\"$t_link\">" . lang_get( 'manage_link' ) . '</a>';
 865			}
 866		}
 867
 868		# News Page
 869		if ( news_is_enabled() && access_has_project_level( config_get( 'manage_news_threshold' ) ) ) {
 870
 871			# Admin can edit news for All Projects (site-wide)
 872			if( ALL_PROJECTS != helper_get_current_project() || current_user_is_administrator() ) {
 873				$t_menu_options[] = '<a href="' . helper_mantis_url( 'news_menu_page.php">' ) . lang_get( 'edit_news_link' ) . '</a>';
 874			} else {
 875				$t_menu_options[] = '<a href="' . helper_mantis_url( 'login_select_proj_page.php">' ) . lang_get( 'edit_news_link' ) . '</a>';
 876			}
 877		}
 878
 879		# Account Page (only show accounts that are NOT protected)
 880		if( OFF == $t_protected ) {
 881			$t_menu_options[] = '<a href="' . helper_mantis_url( 'account_page.php">' ) . lang_get( 'account_link' ) . '</a>';
 882		}
 883
 884		# Add custom options
 885		$t_custom_options = prepare_custom_menu_options( 'main_menu_custom_options' );
 886		$t_menu_options = array_merge( $t_menu_options, $t_custom_options );
 887		if( config_get( 'time_tracking_enabled' ) && config_get( 'time_tracking_with_billing' ) && access_has_global_level( config_get( 'time_tracking_reporting_threshold' ) ) ) {
 888			$t_menu_options[] = '<a href="' . helper_mantis_url( 'billing_page.php">' ) . lang_get( 'time_tracking_billing_link' ) . '</a>';
 889		}
 890
 891		# Logout (no if anonymously logged in)
 892		if( !current_user_is_anonymous() ) {
 893			$t_menu_options[] = '<a href="' . helper_mantis_url( 'logout_page.php">' ) . lang_get( 'logout_link' ) . '</a>';
 894		}
 895		echo implode( $t_menu_options, ' | ' );
 896		echo '</td>';
 897		echo '<td class="menu right nowrap">';
 898		echo '<form method="post" action="' . helper_mantis_url( 'jump_to_bug.php">' );
 899		# CSRF protection not required here - form does not result in modifications
 900
 901		if( ON == config_get( 'use_javascript' ) ) {
 902			$t_bug_label = lang_get( 'issue_id' );
 903			echo "<input type=\"text\" name=\"bug_id\" size=\"10\" class=\"small\" value=\"$t_bug_label\" onfocus=\"if (this.value == '$t_bug_label') this.value = ''\" onblur=\"if (this.value == '') this.value = '$t_bug_label'\" />&nbsp;";
 904		} else {
 905			echo "<input type=\"text\" name=\"bug_id\" size=\"10\" class=\"small\" />&nbsp;";
 906		}
 907
 908		echo '<input type="submit" class="button-small" value="' . lang_get( 'jump' ) . '" />&nbsp;';
 909		echo '</form>';
 910		echo '</td>';
 911		echo '</tr>';
 912		echo '</table>';
 913	}
 914}
 915
 916/**
 917 * Print the menu bar with a list of projects to which the user has access
 918 * @return null
 919 */
 920function print_project_menu_bar() {
 921	$t_project_ids = current_user_get_accessible_projects();
 922
 923	echo '<table class="width100" cellspacing="0">';
 924	echo '<tr>';
 925	echo '<td class="menu">';
 926	echo '<a href="' . helper_mantis_url( 'set_project.php?project_id=' . ALL_PROJECTS ) . '">' . lang_get( 'all_projects' ) . '</a>';
 927
 928	foreach( $t_project_ids as $t_id ) {
 929		echo ' | <a href="' . helper_mantis_url( 'set_project.php?project_id=' . $t_id ) . '">' . string_html_specialchars( project_get_field( $t_id, 'name' ) ) . '</a>';
 930		print_subproject_menu_bar( $t_id, $t_id . ';' );
 931	}
 932
 933	echo '</td>';
 934	echo '</tr>';
 935	echo '</table>';
 936}
 937
 938/**
 939 * Print the menu bar with a list of projects to which the user has access
 940 * @return null
 941 */
 942function print_subproject_menu_bar( $p_project_id, $p_parents = '' ) {
 943	$t_subprojects = current_user_get_accessible_subprojects( $p_project_id );
 944	$t_char = ':';
 945	foreach( $t_subprojects as $t_subproject ) {
 946		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>';
 947		print_subproject_menu_bar( $t_subproject, $p_parents . $t_subproject . ';' );
 948		$t_char = ',';
 949	}
 950}
 951
 952/**
 953 * Print the menu for the graph summary section
 954 * @return null
 955 */
 956function print_summary_submenu() {
 957	echo '<div align="center">';
 958
 959	# Plugin / Event added options
 960	$t_event_menu_options = event_signal( 'EVENT_SUBMENU_SUMMARY' );
 961	$t_menu_options = array();
 962	foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) {
 963		foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) {
 964			if( is_array( $t_callback_menu_options ) ) {
 965				$t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options );
 966			} else {
 967				if ( !is_null( $t_callback_menu_options ) ) {
 968					$t_menu_options[] = $t_callback_menu_options;
 969				}
 970			}
 971		}
 972	}
 973
 974	// Plugins menu items
 975	// TODO: this would be a call to print_pracket_link but the events returns cooked links so we cant
 976	foreach( $t_menu_options as $t_menu_item ) {
 977		echo '<span class="bracket-link">[&nbsp;';
 978		echo $t_menu_item;
 979		echo '&nbsp;]</span> ';
 980	}
 981	echo '</div>';
 982}
 983
 984/**
 985 * Print the menu for the manage section
 986 *
 987 * @param string $p_page specifies the current page name so it's link can be disabled
 988 * @return null
 989 */
 990function print_manage_menu( $p_page = '' ) {
 991	$t_manage_user_page = 'manage_user_page.php';
 992	$t_manage_project_menu_page = 'manage_proj_page.php';
 993	$t_manage_custom_field_page = 'manage_custom_field_page.php';
 994	$t_manage_plugin_page = 'manage_plugin_page.php';
 995	$t_manage_config_page = 'adm_config_report.php';
 996	$t_permissions_summary_report = 'adm_permissions_report.php';
 997	$t_manage_prof_menu_page = 'manage_prof_menu_page.php';
 998	$t_manage_tags_page = 'manage_tags_page.php';
 999
1000	switch( $p_page ) {
1001		case $t_manage_user_page:
1002			$t_manage_user_page = '';
1003			break;
1004		case $t_manage_project_menu_page:
1005			$t_manage_project_menu_page = '';
1006			break;
1007		case $t_manage_custom_field_page:
1008			$t_manage_custom_field_page = '';
1009			break;
1010		case $t_manage_config_page:
1011			$t_manage_config_page = '';
1012			break;
1013		case $t_permissions_summary_report:
1014			$t_permissions_summary_report = '';
1015			break;
1016		case $t_manage_plugin_page:
1017			$t_manage_plugin_page = '';
1018			break;
1019		case $t_manage_prof_menu_page:
1020			$t_manage_prof_menu_page = '';
1021			break;
1022		case $t_manage_tags_page:
1023			$t_manage_tags_page = '';
1024			break;
1025	}
1026
1027	echo '<div align="center"><p>';
1028	if( access_has_global_level( config_get( 'manage_user_threshold' ) ) ) {
1029		print_bracket_link( helper_mantis_url( $t_manage_user_page ), lang_get( 'manage_users_link' ) );
1030	}
1031	if( access_has_project_level( config_get( 'manage_project_threshold' ) ) ) {
1032		print_bracket_link( helper_mantis_url( $t_manage_project_menu_page ), lang_get( 'manage_projects_link' ) );
1033	}
1034	if( access_has_project_level( config_get( 'tag_edit_threshold' ) ) ) {
1035		print_bracket_link( helper_mantis_url( $t_manage_tags_page ), lang_get( 'manage_tags_link' ) );
1036	}
1037	if( access_has_global_level( config_get( 'manage_custom_fields_threshold' ) ) ) {
1038		print_bracket_link( helper_mantis_url( $t_manage_custom_field_page ), lang_get( 'manage_custom_field_link' ) );
1039	}
1040	if( access_has_global_level( config_get( 'manage_global_profile_threshold' ) ) ) {
1041		print_bracket_link( helper_mantis_url( $t_manage_prof_menu_page ), lang_get( 'manage_global_profiles_link' ) );
1042	}
1043	if( access_has_global_level( config_get( 'manage_plugin_threshold' ) ) ) {
1044		print_bracket_link( helper_mantis_url( $t_manage_plugin_page ), lang_get( 'manage_plugin_link' ) );
1045	}
1046
1047	if ( access_has_project_level( config_get( 'manage_configuration_threshold' ) ) ) {
1048		if ( access_has_global_level( config_get( 'view_configuration_threshold' ) ) ) {
1049			$t_config_page = $t_manage_config_page;
1050		} else {
1051			$t_config_page = $t_permissions_summary_report;
1052		}
1053
1054		print_bracket_link( helper_mantis_url( $t_config_page ), lang_get( 'manage_config_link' ) );
1055	}
1056
1057	# Plugin / Event added options
1058	$t_event_menu_options = event_signal( 'EVENT_MENU_MANAGE' );
1059	$t_menu_options = array();
1060	foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) {
1061		foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) {
1062			if( is_array( $t_callback_menu_options ) ) {
1063				$t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options );
1064			} else {
1065				if ( !is_null( $t_callback_menu_options ) ) {
1066					$t_menu_options[] = $t_callback_menu_options;
1067				}
1068			}
1069		}
1070	}
1071
1072	// Plugins menu items
1073	foreach( $t_menu_options as $t_menu_item ) {
1074		print_bracket_link_prepared( $t_menu_item );
1075	}
1076
1077	echo '</p></div>';
1078}
1079
1080/**
1081 * Print the menu for the manage configuration section
1082 * @param string $p_page specifies the current page name so it's link can be disabled
1083 * @return null
1084 */
1085function print_manage_config_menu( $p_page = '' ) {
1086	$t_configuration_report = 'adm_config_report.php';
1087	$t_permissions_summary_report = 'adm_permissions_report.php';
1088	$t_manage_work_threshold = 'manage_config_work_threshold_page.php';
1089	$t_manage_email = 'manage_config_email_page.php';
1090	$t_manage_workflow = 'manage_config_workflow_page.php';
1091	$t_manage_columns = 'manage_config_columns_page.php';
1092
1093	switch( $p_page ) {
1094		case $t_configuration_report:
1095			$t_configuration_report = '';
1096			break;
1097		case $t_permissions_summary_report:
1098			$t_permissions_summary_report = '';
1099			break;
1100		case $t_manage_work_threshold:
1101			$t_manage_work_threshold = '';
1102			break;
1103		case $t_manage_email:
1104			$t_manage_email = '';
1105			break;
1106		case $t_manage_workflow:
1107			$t_manage_workflow = '';
1108			break;
1109		case $t_manage_columns:
1110			$t_manage_columns = '';
1111			break;
1112	}
1113
1114	if ( access_has_project_level( config_get( 'manage_configuration_threshold' ) ) ) {
1115		echo '<br /><div align="center">';
1116
1117		if ( access_has_global_level( config_get( 'view_configuration_threshold' ) ) ) {
1118			print_bracket_link( helper_mantis_url( $t_configuration_report ), lang_get_defaulted( 'configuration_report' ) );
1119		}
1120
1121		print_bracket_link( helper_mantis_url( $t_permissions_summary_report ), lang_get( 'permissions_summary_report' ) );
1122		print_bracket_link( helper_mantis_url( $t_manage_work_threshold ), lang_get( 'manage_threshold_config' ) );
1123		print_bracket_link( helper_mantis_url( $t_manage_workflow ), lang_get( 'manage_workflow_config' ) );
1124		print_bracket_link( helper_mantis_url( $t_manage_email ), lang_get( 'manage_email_config' ) );
1125		print_bracket_link( $t_manage_columns, lang_get( 'manage_columns_config' ) );
1126
1127		# Plugin / Event added options
1128		$t_event_menu_options = event_signal( 'EVENT_MENU_MANAGE_CONFIG' );
1129		$t_menu_options = array();
1130		foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) {
1131			foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) {
1132				if( is_array( $t_callback_menu_options ) ) {
1133					$t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options );
1134				} else {
1135					if ( !is_null( $t_callback_menu_options ) ) {
1136						$t_menu_options[] = $t_callback_menu_options;
1137					}
1138				}
1139			}
1140		}
1141
1142		// Plugins menu items
1143		foreach( $t_menu_options as $t_menu_item ) {
1144			print_bracket_link_prepared( $t_menu_item );
1145		}
1146
1147		echo '</div>';
1148	}
1149}
1150
1151/**
1152 * Print the menu for the account section
1153 * @param string $p_page specifies the current page name so it's link can be disabled
1154 * @return null
1155 */
1156function print_account_menu( $p_page = '' ) {
1157	$t_account_page = 'account_page.php';
1158	$t_account_prefs_page = 'account_prefs_page.php';
1159	$t_account_profile_menu_page = 'account_prof_menu_page.php';
1160	$t_account_sponsor_page = 'account_sponsor_page.php';
1161	$t_account_manage_columns_page = 'account_manage_columns_page.php';
1162
1163	switch( $p_page ) {
1164		case $t_account_page:
1165			$t_account_page = '';
1166			break;
1167		case $t_account_prefs_page:
1168			$t_account_prefs_page = '';
1169			break;
1170		case $t_account_profile_menu_page:
1171			$t_account_profile_menu_page = '';
1172			break;
1173		case $t_account_sponsor_page:
1174			$t_account_sponsor_page = '';
1175			break;
1176		case $t_account_manage_columns_page:
1177			$t_account_manage_columns_page = '';
1178			break;
1179	}
1180
1181	print_bracket_link( $t_account_page, lang_get( 'account_link' ) );
1182	print_bracket_link( $t_account_prefs_page, lang_get( 'change_preferences_link' ) );
1183	print_bracket_link( $t_account_manage_columns_page, lang_get( 'manage_columns_config' ) );
1184
1185	if( config_get ( 'enable_profiles' ) == ON && access_has_project_level( config_get( 'add_profile_threshold' ) ) ) {
1186		print_bracket_link( helper_mantis_url( $t_account_profile_menu_page ), lang_get( 'manage_profiles_link' ) );
1187	}
1188
1189	if( config_get( 'enable_sponsorship' ) == ON && access_has_project_level( config_get( 'view_sponsorship_total_threshold' ) ) && !current_user_is_anonymous() ) {
1190		print_bracket_link( helper_mantis_url( $t_account_sponsor_page ), lang_get( 'my_sponsorship' ) );
1191	}
1192
1193	# Plugin / Event added options
1194	$t_event_menu_options = event_signal( 'EVENT_MENU_ACCOUNT' );
1195	$t_menu_options = array();
1196	foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) {
1197		foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) {
1198			if( is_array( $t_callback_menu_options ) ) {
1199				$t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options );
1200			} else {
1201				if ( !is_null( $t_callback_menu_options ) ) {
1202					$t_menu_options[] = $t_callback_menu_options;
1203				}
1204			}
1205		}
1206	}
1207
1208	// Plugins menu items
1209	// TODO: this would be a call to print_pracket_link but the events returns cooked links so we cant
1210	foreach( $t_menu_options as $t_menu_item ) {
1211		echo '<span class="bracket-link">[&nbsp;';
1212		echo $t_menu_item;
1213		echo '&nbsp;]</span> ';
1214	}
1215}
1216
1217/**
1218 * Print the menu for the docs section
1219 * @param string $p_page specifies the current page name so it's link can be disabled
1220 * @return null
1221 */
1222function print_doc_menu( $p_page = '' ) {
1223	$t_documentation_html = config_get( 'manual_url' );
1224	$t_proj_doc_page = 'proj_doc_page.php';
1225	$t_proj_doc_add_page = 'proj_doc_add_page.php';
1226
1227	switch( $p_page ) {
1228		case $t_documentation_html:
1229			$t_documentation_html = '';
1230			break;
1231		case $t_proj_doc_page:
1232			$t_proj_doc_page = '';
1233			break;
1234		case $t_proj_doc_add_page:
1235			$t_proj_doc_add_page = '';
1236			break;
1237	}
1238
1239	print_bracket_link( $t_documentation_html, lang_get( 'user_documentation' ) );
1240	print_bracket_link( helper_mantis_url( $t_proj_doc_page ), lang_get( 'project_documentation' ) );
1241	if( file_allow_project_upload() ) {
1242		print_bracket_link( helper_mantis_url( $t_proj_doc_add_page ), lang_get( 'add_file' ) );
1243	}
1244}
1245
1246/**
1247 * Print the menu for the summary section
1248 * @param string $p_page specifies the current page name so it's link can be disabled
1249 * @return null
1250 */
1251function print_summary_menu( $p_page = '' ) {
1252	echo '<div align="center">';
1253	print_bracket_link( 'print_all_bug_page.php', lang_get( 'print_all_bug_page_link' ) );
1254	print_bracket_link( helper_mantis_url( 'summary_page.php' ), lang_get( 'summary_link' ) );
1255
1256	# Plugin / Event added options
1257	$t_event_menu_options = event_signal( 'EVENT_MENU_SUMMARY' );
1258	$t_menu_options = array();
1259	foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) {
1260		foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) {
1261			if( is_array( $t_callback_menu_options ) ) {
1262				$t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options );
1263			} else {
1264				if ( !is_null( $t_callback_menu_options ) ) {
1265					$t_menu_options[] = $t_callback_menu_options;
1266				}
1267			}
1268		}
1269	}
1270
1271	// Plugins menu items
1272	// TODO: this would be a call to print_pracket_link but the events returns cooked links so we cant
1273	foreach( $t_menu_options as $t_menu_item ) {
1274		echo '<span class="bracket-link">[&nbsp;';
1275		echo $t_menu_item;
1276		echo '&nbsp;]</span> ';
1277	}
1278	echo '</div>';
1279}
1280
1281/**
1282 * Print the color legend for the status colors
1283 * @param string
1284 * @return null
1285 */
1286function html_status_legend() {
1287	# Don't show the legend if only one status is selected by the current filter
1288	$t_current_filter = current_user_get_bug_filter();
1289	if ( $t_current_filter === false ) {
1290		$t_current_filter = filter_get_default();
1291	}
1292	$t_simple_filter = $t_current_filter['_view_type'] == 'simple';
1293	if( $t_simple_filter ) {
1294		if( !filter_field_is_any( $t_current_filter[FILTER_PROPERTY_STATUS][0] ) ) {
1295			return null;
1296		}
1297	}
1298
1299	$t_status_array = MantisEnum::getAssocArrayIndexedByValues( config_get( 'status_enum_string' ) );
1300	$t_status_names = MantisEnum::getAssocArrayIndexedByValues( lang_get( 'status_enum_string' ) );
1301	$enum_count = count( $t_status_array );
1302
1303	# read through the list and eliminate unused ones for the selected project
1304	# assumes that all status are are in the enum array
1305	$t_workflow = config_get( 'status_enum_workflow' );
1306	if( !empty( $t_workflow ) ) {
1307		foreach( $t_status_array as $t_status => $t_name ) {
1308			if( !isset( $t_workflow[$t_status] ) ) {
1309
1310				# drop elements that are not in the workflow
1311				unset( $t_status_array[$t_status] );
1312			}
1313		}
1314	}
1315
1316	# Remove status values that won't appear as a result of the current filter
1317	foreach( $t_status_array as $t_status => $t_name ) {
1318		if( $t_simple_filter ) {
1319			if( !filter_field_is_none( $t_current_filter[FILTER_PROPERTY_HIDE_STATUS][0] ) &&
1320				$t_status >= $t_current_filter[FILTER_PROPERTY_HIDE_STATUS][0] ) {
1321				unset( $t_status_array[$t_status] );
1322			}
1323		} else {
1324			if( !in_array( META_FILTER_ANY, $t_current_filter[FILTER_PROPERTY_STATUS] ) &&
1325				!in_array( $t_status, $t_current_filter[FILTER_PROPERTY_STATUS] ) ) {
1326				unset( $t_status_array[$t_status] );
1327			}
1328		}
1329	}
1330
1331	# If there aren't at least two statuses showable by the current filter,
1332	# don't draw the status bar
1333	if( count( $t_status_array ) <= 1 ) {
1334		return null;
1335	}
1336
1337	echo '<br />';
1338	echo '<table class="status-legend width100" cellspacing="1">';
1339	echo '<tr>';
1340
1341	# draw the status bar
1342	$width = (int)( 100 / count( $t_status_array ) );
1343	foreach( $t_status_array as $t_status => $t_name ) {
1344		$t_val = $t_status_names[$t_status];
1345		$t_color = get_status_color( $t_status );
1346
1347		echo "<td class=\"small-caption\" width=\"$width%\" bgcolor=\"$t_color\">$t_val</td>";
1348	}
1349
1350	echo '</tr>';
1351	echo '</table>';
1352	if( ON == config_get( 'status_percentage_legend' ) ) {
1353		html_status_percentage_legend();
1354	}
1355}
1356
1357/**
1358 * Print the legend for the status percentage
1359 * @return null
1360 */
1361function html_status_percentage_legend() {
1362	$t_mantis_bug_table = db_get_table( 'bug' );
1363	$t_project_id = helper_get_current_project();
1364	$t_user_id = auth_get_current_user_id();
1365
1366	# checking if it's a per project statistic or all projects
1367	$t_specific_where = helper_project_specific_where( $t_project_id, $t_user_id );
1368
1369	$query = "SELECT status, COUNT(*) AS number
1370				FROM $t_mantis_bug_table
1371				WHERE $t_specific_where
1372				GROUP BY status";
1373	$result = db_query_bound( $query );
1374
1375	$t_bug_count = 0;
1376	$t_status_count_array = array();
1377
1378	while( $row = db_fetch_array( $result ) ) {
1379		$t_status_count_array[$row['status']] = $row['number'];
1380		$t_bug_count += $row['number'];
1381	}
1382
1383	$t_enum_values = MantisEnum::getValues( config_get( 'status_enum_string' ) );
1384	$enum_count = count( $t_enum_values );
1385
1386	if( $t_bug_count > 0 ) {
1387		echo '<br />';
1388		echo '<table class="width100" cellspacing="1">';
1389		echo '<tr>';
1390		echo '<td class="form-title" colspan="' . $enum_count . '">' . lang_get( 'issue_status_percentage' ) . '</td>';
1391		echo '</tr>';
1392		echo '<tr>';
1393
1394		foreach ( $t_enum_values as $t_status ) {
1395			$t_color = get_status_color( $t_status );
1396
1397			if ( !isset( $t_status_count_array[$t_status] ) ) {
1398				$t_status_count_array[$t_status] = 0;
1399			}
1400
1401			$width = round(( $t_status_count_array[$t_status] / $t_bug_count ) * 100 );
1402
1403			if( $width > 0 ) {
1404				echo "<td class=\"small-caption-center\" width=\"$width%\" bgcolor=\"$t_color\">$width%</td>";
1405			}
1406		}
1407
1408		echo '</tr>';
1409		echo '</table>';
1410	}
1411}
1412
1413/**
1414 * Print an html button inside a form
1415 * @param string $p_action
1416 * @param string $p_buttion_text
1417 * @param array $p_fields
1418 * @param string $p_method
1419 * @return null
1420 */
1421function html_button( $p_action, $p_button_text, $p_fields = null, $p_method = 'post' ) {
1422	$t_form_name = explode( '.php', $p_action, 2 );
1423	$p_action = urlencode( $p_action );
1424	$p_button_text = string_attribute( $p_button_text );
1425	if( null === $p_fields ) {
1426		$p_fields = array();
1427	}
1428
1429	if( utf8_strtolower( $p_method ) == 'get' ) {
1430		$t_method = 'get';
1431	} else {
1432		$t_method = 'post';
1433	}
1434
1435	echo "<form method=\"$t_method\" action=\"$p_action\">\n";
1436	# Add a CSRF token only when the form is being sent via the POST method
1437	if ( $t_method == 'post' ) {
1438		echo form_security_field( $t_form_name[0] );
1439	}
1440
1441	foreach( $p_fields as $key => $val ) {
1442		$key = string_attribute( $key );
1443		$val = string_attribute( $val );
1444
1445		echo "	<input type=\"hidden\" name=\"$key\" value=\"$val\" />\n";
1446	}
1447
1448	echo "	<input type=\"submit\" class=\"button\" value=\"$p_button_text\" />\n";
1449	echo "</form>\n";
1450}
1451
1452/**
1453 * Print a button to update the given bug
1454 * @param int $p_bug_id
1455 * @return null
1456 */
1457function html_button_bug_update( $p_bug_id ) {
1458	if( access_has_bug_level( config_get( 'update_bug_threshold' ), $p_bug_id ) ) {
1459		html_button( string_get_bug_update_page(), lang_get( 'update_bug_button' ), array( 'bug_id' => $p_bug_id ) );
1460	}
1461}
1462
1463/**
1464 * Print Change Status to: button
1465 * This code is similar to print_status_option_list except
1466 * there is no masking, except for the current state
1467 *
1468 * @param int $p_bug_id
1469 * @return null
1470 */
1471function html_button_bug_change_status( $p_bug_id ) {
1472	$t_bug_project_id = bug_get_field( $p_bug_id, 'project_id' );
1473	$t_bug_current_state = bug_get_field( $p_bug_id, 'status' );
1474	$t_current_access = access_get_project_level( $t_bug_project_id );
1475
1476	$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 );
1477
1478	if( count( $t_enum_list ) > 0 ) {
1479
1480		# resort the list into ascending order after noting the key from the first element (the default)
1481		$t_default_arr = each( $t_enum_list );
1482		$t_default = $t_default_arr['key'];
1483		ksort( $t_enum_list );
1484		reset( $t_enum_list );
1485
1486		echo "<form method=\"post\" action=\"bug_change_status_page.php\">";
1487		# CSRF protection not required here - form does not result in modifications
1488
1489		$t_button_text = lang_get( 'bug_status_to_button' );
1490		echo "<input …

Large files files are truncated, but you can click here to view the full file