PageRenderTime 58ms CodeModel.GetById 20ms RepoModel.GetById 0ms 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
Possible License(s): GPL-2.0, LGPL-2.1

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

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