PageRenderTime 145ms CodeModel.GetById 32ms RepoModel.GetById 7ms app.codeStats 0ms

/MantisBT/core/print_api.php

https://bitbucket.org/crypticrod/sr_wp_code
PHP | 1771 lines | 1511 code | 110 blank | 150 comment | 128 complexity | 7efe3bd837ea696a7da50718baed4a34 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, LGPL-2.1, GPL-3.0, LGPL-2.0, AGPL-3.0

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. * this file handles printing functions
  17. * @package CoreAPI
  18. * @subpackage PrintAPI
  19. * @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
  20. * @copyright Copyright (C) 2002 - 2011 MantisBT Team - mantisbt-dev@lists.sourceforge.net
  21. * @link http://www.mantisbt.org
  22. */
  23. /**
  24. * requires current_user_api
  25. */
  26. require_once( 'current_user_api.php' );
  27. /**
  28. * requires string_api
  29. */
  30. require_once( 'string_api.php' );
  31. /**
  32. * requires prepare_api
  33. */
  34. require_once( 'prepare_api.php' );
  35. /**
  36. * requires profile_api
  37. */
  38. require_once( 'profile_api.php' );
  39. /**
  40. * requires last_visited_api
  41. */
  42. require_once( 'last_visited_api.php' );
  43. /**
  44. * requires file_api
  45. */
  46. require_once( 'file_api.php' );
  47. require_once( 'bug_group_action_api.php' );
  48. # --------------------
  49. # Print the headers to cause the page to redirect to $p_url
  50. # If $p_die is true (default), terminate the execution of the script
  51. # immediately
  52. # If we have handled any errors on this page and the 'stop_on_errors' config
  53. # option is turned on, return false and don't redirect.
  54. # $p_sanitize - true/false - true in the case where the URL is extracted from GET/POST or untrusted source.
  55. # This would be false if the URL is trusted (e.g. read from config_inc.php).
  56. #
  57. # @param string The page to redirect: has to be a relative path
  58. # @param boolean if true, stop the script after redirecting
  59. # @param boolean apply string_sanitize_url to passed url
  60. # @return boolean
  61. function print_header_redirect( $p_url, $p_die = true, $p_sanitize = false, $p_absolute = false ) {
  62. $t_use_iis = config_get( 'use_iis' );
  63. if( ON == config_get_global( 'stop_on_errors' ) && error_handled() ) {
  64. return false;
  65. }
  66. # validate the url as part of this site before continuing
  67. if( $p_absolute ) {
  68. if( $p_sanitize ) {
  69. $t_url = string_sanitize_url( $p_url );
  70. } else {
  71. $t_url = $p_url;
  72. }
  73. } else {
  74. if( $p_sanitize ) {
  75. $t_url = string_sanitize_url( $p_url, true );
  76. } else {
  77. $t_url = config_get( 'path' ) . $p_url;
  78. }
  79. }
  80. $t_url = string_prepare_header( $t_url );
  81. # don't send more headers if they have already been sent (guideweb)
  82. if( !headers_sent() ) {
  83. header( 'Content-Type: text/html; charset=utf-8' );
  84. if( ON == $t_use_iis ) {
  85. header( "Refresh: 0;url=$t_url" );
  86. } else {
  87. header( "Location: $t_url" );
  88. }
  89. } else {
  90. trigger_error( ERROR_PAGE_REDIRECTION, ERROR );
  91. return false;
  92. }
  93. if( $p_die ) {
  94. die;
  95. # additional output can cause problems so let's just stop output here
  96. }
  97. return true;
  98. }
  99. # --------------------
  100. # Print a redirect header to view a bug
  101. function print_header_redirect_view( $p_bug_id ) {
  102. print_header_redirect( string_get_bug_view_url( $p_bug_id ) );
  103. }
  104. # --------------------
  105. # Get a view URL for the bug id based on the user's preference and
  106. # call print_successful_redirect() with that URL
  107. function print_successful_redirect_to_bug( $p_bug_id ) {
  108. $t_url = string_get_bug_view_url( $p_bug_id, auth_get_current_user_id() );
  109. print_successful_redirect( $t_url );
  110. }
  111. # --------------------
  112. # If the show query count is ON, print success and redirect after the
  113. # configured system wait time.
  114. # If the show query count is OFF, redirect right away.
  115. function print_successful_redirect( $p_redirect_to ) {
  116. if( helper_show_queries() ) {
  117. html_page_top( null, $p_redirect_to );
  118. echo '<br /><div class="center">';
  119. echo lang_get( 'operation_successful' ) . '<br />';
  120. print_bracket_link( $p_redirect_to, lang_get( 'proceed' ) );
  121. echo '</div>';
  122. html_page_bottom();
  123. } else {
  124. print_header_redirect( $p_redirect_to );
  125. }
  126. }
  127. # Print avatar image for the given user ID
  128. function print_avatar( $p_user_id, $p_size = 80 ) {
  129. if( !user_exists( $p_user_id ) ) {
  130. return;
  131. }
  132. if( access_has_project_level( config_get( 'show_avatar_threshold' ), null, $p_user_id ) ) {
  133. $t_avatar = user_get_avatar( $p_user_id, $p_size );
  134. if( false !== $t_avatar ) {
  135. $t_avatar_url = htmlspecialchars( $t_avatar[0] );
  136. $t_width = $t_avatar[1];
  137. $t_height = $t_avatar[2];
  138. echo '<a rel="nofollow" href="http://site.gravatar.com"><img class="avatar" src="' . $t_avatar_url . '" alt="User avatar" width="' . $t_width . '" height="' . $t_height . '" /></a>';
  139. }
  140. }
  141. }
  142. # --------------------
  143. # prints the name of the user given the id. also makes it an email link.
  144. function print_user( $p_user_id ) {
  145. echo prepare_user_name( $p_user_id );
  146. }
  147. # --------------------
  148. # same as print_user() but fills in the subject with the bug summary
  149. function print_user_with_subject( $p_user_id, $p_bug_id ) {
  150. $c_user_id = db_prepare_int( $p_user_id );
  151. if( NO_USER == $p_user_id ) {
  152. return;
  153. }
  154. $t_username = user_get_name( $p_user_id );
  155. if( user_exists( $p_user_id ) && user_get_field( $p_user_id, 'enabled' ) ) {
  156. $t_email = user_get_email( $p_user_id );
  157. print_email_link_with_subject( $t_email, $t_username, $p_bug_id );
  158. } else {
  159. echo '<font STYLE="text-decoration: line-through">';
  160. echo $t_username;
  161. echo '</font>';
  162. }
  163. }
  164. # --------------------
  165. # print out an email editing input
  166. function print_email_input( $p_field_name, $p_email ) {
  167. $t_limit_email_domain = config_get( 'limit_email_domain' );
  168. if( $t_limit_email_domain ) {
  169. # remove the domain part
  170. $p_email = preg_replace( '/@' . preg_quote( $t_limit_email_domain, '/' ) . '$/i', '', $p_email );
  171. echo '<input type="text" name="' . string_attribute( $p_field_name ) . '" size="20" maxlength="64" value="' . string_attribute( $p_email ) . '" />@' . string_display_line( $t_limit_email_domain );
  172. } else {
  173. echo '<input type="text" name="' . string_attribute( $p_field_name ) . '" size="32" maxlength="64" value="' . string_attribute( $p_email ) . '" />';
  174. }
  175. }
  176. # --------------------
  177. # print out an email editing input
  178. function print_captcha_input( $p_field_name ) {
  179. echo '<input type="text" name="' . $p_field_name . '" size="5" maxlength="5" value="" />';
  180. }
  181. # ##########################################################################
  182. # Option List Printing API
  183. # ##########################################################################
  184. # --------------------
  185. # This populates an option list with the appropriate users by access level
  186. #
  187. # @todo from print_reporter_option_list
  188. function print_user_option_list( $p_user_id, $p_project_id = null, $p_access = ANYBODY ) {
  189. $t_users = array();
  190. if( null === $p_project_id ) {
  191. $p_project_id = helper_get_current_project();
  192. }
  193. $t_users = project_get_all_user_rows( $p_project_id, $p_access );
  194. # handles ALL_PROJECTS case
  195. $t_display = array();
  196. $t_sort = array();
  197. $t_show_realname = ( ON == config_get( 'show_realname' ) );
  198. $t_sort_by_last_name = ( ON == config_get( 'sort_by_last_name' ) );
  199. foreach( $t_users as $t_user ) {
  200. $t_user_name = string_attribute( $t_user['username'] );
  201. $t_sort_name = utf8_strtolower( $t_user_name );
  202. if( $t_show_realname && ( $t_user['realname'] <> '' ) ) {
  203. $t_user_name = string_attribute( $t_user['realname'] );
  204. if( $t_sort_by_last_name ) {
  205. $t_sort_name_bits = explode( ' ', utf8_strtolower( $t_user_name ), 2 );
  206. $t_sort_name = ( isset( $t_sort_name_bits[1] ) ? $t_sort_name_bits[1] . ', ' : '' ) . $t_sort_name_bits[0];
  207. } else {
  208. $t_sort_name = utf8_strtolower( $t_user_name );
  209. }
  210. }
  211. $t_display[] = $t_user_name;
  212. $t_sort[] = $t_sort_name;
  213. }
  214. array_multisort( $t_sort, SORT_ASC, SORT_STRING, $t_users, $t_display );
  215. $t_count = count( $t_sort );
  216. for( $i = 0;$i < $t_count;$i++ ) {
  217. $t_row = $t_users[$i];
  218. echo '<option value="' . $t_row['id'] . '" ';
  219. check_selected( $p_user_id, $t_row['id'] );
  220. echo '>' . $t_display[$i] . '</option>';
  221. }
  222. }
  223. # --------------------
  224. # ugly functions need to be refactored
  225. # This populates the reporter option list with the appropriate users
  226. #
  227. # @todo This function really ought to print out all the users, I think.
  228. # I just encountered a situation where a project used to be public and
  229. # was made private, so now I can't filter on any of the reporters who
  230. # actually reported the bugs at the time. Maybe we could get all user
  231. # who are listed as the reporter in any bug? It would probably be a
  232. # faster query actually.
  233. function print_reporter_option_list( $p_user_id, $p_project_id = null ) {
  234. print_user_option_list( $p_user_id, $p_project_id, config_get( 'report_bug_threshold' ) );
  235. }
  236. /**
  237. * Print the entire form for attaching a tag to a bug.
  238. * @param integer Bug ID
  239. * @param string Default contents of the input box
  240. */
  241. function print_tag_attach_form( $p_bug_id, $p_string = '' ) {
  242. ?>
  243. <small><?php echo sprintf( lang_get( 'tag_separate_by' ), config_get( 'tag_separator' ) )?></small>
  244. <form method="post" action="tag_attach.php">
  245. <?php echo form_security_field( 'tag_attach' )?>
  246. <input type="hidden" name="bug_id" value="<?php echo $p_bug_id?>" />
  247. <?php
  248. print_tag_input( $p_bug_id, $p_string );
  249. ?>
  250. <input type="submit" value="<?php echo lang_get( 'tag_attach' )?>" class="button" />
  251. </form>
  252. <?php
  253. return true;
  254. }
  255. /**
  256. * Print the separator comment, input box, and existing tag dropdown menu.
  257. * @param integer Bug ID
  258. * @param string Default contents of the input box
  259. */
  260. function print_tag_input( $p_bug_id = 0, $p_string = '' ) {
  261. ?>
  262. <input type="hidden" id="tag_separator" value="<?php echo config_get( 'tag_separator' )?>" />
  263. <input type="text" name="tag_string" id="tag_string" size="40" value="<?php echo string_attribute( $p_string )?>" />
  264. <select <?php echo helper_get_tab_index()?> name="tag_select" id="tag_select" onchange="tag_string_append( this.options[ this.selectedIndex ].title );">
  265. <?php print_tag_option_list( $p_bug_id );?>
  266. </select>
  267. <?php
  268. return true;
  269. }
  270. /**
  271. * Print the dropdown combo-box of existing tags.
  272. * When passed a bug ID, the option list will not contain any tags attached to the given bug.
  273. * @param integer Bug ID
  274. */
  275. function print_tag_option_list( $p_bug_id = 0 ) {
  276. $t_rows = tag_get_candidates_for_bug( $p_bug_id );
  277. echo '<option value="0">', string_html_specialchars( lang_get( 'tag_existing' ) ), '</option>';
  278. foreach ( $t_rows as $row ) {
  279. $t_string = $row['name'];
  280. if ( !empty( $row['description'] ) ) {
  281. $t_string .= ' - ' . utf8_substr( $row['description'], 0, 20 );
  282. }
  283. echo '<option value="', $row['id'], '" title="', string_attribute( $row['name'] ), '">', string_attribute( $t_string ), '</option>';
  284. }
  285. }
  286. # --------------------
  287. # Get current headlines and id prefix with v_
  288. function print_news_item_option_list() {
  289. $t_mantis_news_table = db_get_table( 'mantis_news_table' );
  290. $t_project_id = helper_get_current_project();
  291. $t_global = access_has_global_level( config_get_global( 'admin_site_threshold' ) );
  292. if( $t_global ) {
  293. $query = "SELECT id, headline, announcement, view_state
  294. FROM $t_mantis_news_table
  295. ORDER BY date_posted DESC";
  296. } else {
  297. $query = "SELECT id, headline, announcement, view_state
  298. FROM $t_mantis_news_table
  299. WHERE project_id=" . db_param() . "
  300. ORDER BY date_posted DESC";
  301. }
  302. $result = db_query_bound( $query, ($t_global == true ? Array() : Array( $t_project_id ) ) );
  303. $news_count = db_num_rows( $result );
  304. for( $i = 0;$i < $news_count;$i++ ) {
  305. $row = db_fetch_array( $result );
  306. $t_headline = string_display( $row['headline'] );
  307. $t_announcement = $row['announcement'];
  308. $t_view_state = $row['view_state'];
  309. $t_id = $row['id'];
  310. $t_notes = array();
  311. $t_note_string = '';
  312. if ( 1 == $t_announcement ) {
  313. array_push( $t_notes, lang_get( 'announcement' ) );
  314. }
  315. if ( VS_PRIVATE == $t_view_state ) {
  316. array_push( $t_notes, lang_get( 'private' ) );
  317. }
  318. if ( count( $t_notes ) > 0 ) {
  319. $t_note_string = ' [' . implode( ' ', $t_notes ) . ']';
  320. }
  321. echo "<option value=\"$t_id\">$t_headline$t_note_string</option>";
  322. }
  323. }
  324. # ---------------
  325. # Constructs the string for one news entry given the row retrieved from the news table.
  326. function print_news_entry( $p_headline, $p_body, $p_poster_id, $p_view_state, $p_announcement, $p_date_posted ) {
  327. $t_headline = string_display_links( $p_headline );
  328. $t_body = string_display_links( $p_body );
  329. $t_date_posted = date( config_get( 'normal_date_format' ), $p_date_posted );
  330. if( VS_PRIVATE == $p_view_state ) {
  331. $t_news_css = 'news-heading-private';
  332. } else {
  333. $t_news_css = 'news-heading-public';
  334. }
  335. $output = '<div align="center">';
  336. $output .= '<table class="width75" cellspacing="0">';
  337. $output .= '<tr>';
  338. $output .= "<td class=\"$t_news_css\">";
  339. $output .= "<span class=\"bold\">$t_headline</span> - ";
  340. $output .= "<span class=\"italic-small\">$t_date_posted</span> - ";
  341. echo $output;
  342. /** @todo eventually we should replace print's with methods to construct the strings. */
  343. print_user( $p_poster_id );
  344. $output = '';
  345. if( 1 == $p_announcement ) {
  346. $output .= ' <span class="small">';
  347. $output .= '[' . lang_get( 'announcement' ) . ']';
  348. $output .= '</span>';
  349. }
  350. if( VS_PRIVATE == $p_view_state ) {
  351. $output .= ' <span class="small">';
  352. $output .= '[' . lang_get( 'private' ) . ']';
  353. $output .= '</span>';
  354. }
  355. $output .= '</td>';
  356. $output .= '</tr>';
  357. $output .= '<tr>';
  358. $output .= "<td class=\"news-body\">$t_body</td>";
  359. $output .= '</tr>';
  360. $output .= '</table>';
  361. $output .= '</div>';
  362. echo $output;
  363. }
  364. # --------------------
  365. # print a news item given a row in the news table.
  366. function print_news_entry_from_row( $p_news_row ) {
  367. $t_headline = $p_news_row['headline'];
  368. $t_body = $p_news_row['body'];
  369. $t_poster_id = $p_news_row['poster_id'];
  370. $t_view_state = $p_news_row['view_state'];
  371. $t_announcement = $p_news_row['announcement'];
  372. $t_date_posted = $p_news_row['date_posted'];
  373. print_news_entry( $t_headline, $t_body, $t_poster_id, $t_view_state, $t_announcement, $t_date_posted );
  374. }
  375. # --------------------
  376. # print a news item
  377. function print_news_string_by_news_id( $p_news_id ) {
  378. $row = news_get_row( $p_news_id );
  379. # only show VS_PRIVATE posts to configured threshold and above
  380. if(( VS_PRIVATE == $row['view_state'] ) && !access_has_project_level( config_get( 'private_news_threshold' ) ) ) {
  381. return;
  382. }
  383. print_news_entry_from_row( $row );
  384. }
  385. # --------------------
  386. function print_assign_to_option_list( $p_user_id = '', $p_project_id = null, $p_threshold = null ) {
  387. if( null === $p_threshold ) {
  388. $p_threshold = config_get( 'handle_bug_threshold' );
  389. }
  390. print_user_option_list( $p_user_id, $p_project_id, $p_threshold );
  391. }
  392. /**
  393. * List projects that the current user has access to.
  394. *
  395. * @param integer $p_project_id The current project id or null to use cookie.
  396. * @param bool $p_include_all_projects true: include "All Projects", otherwise false.
  397. * @param mixed $p_filter_project_id The id of a project to exclude or null.
  398. * @param string $p_trace The current project trace, identifies the sub-project via a path from top to bottom.
  399. * @return void
  400. */
  401. function print_project_option_list( $p_project_id = null, $p_include_all_projects = true, $p_filter_project_id = null, $p_trace = false ) {
  402. $t_project_ids = current_user_get_accessible_projects();
  403. project_cache_array_rows( $t_project_ids );
  404. if( $p_include_all_projects ) {
  405. echo '<option value="' . ALL_PROJECTS . '"';
  406. check_selected( $p_project_id, ALL_PROJECTS );
  407. echo '>' . lang_get( 'all_projects' ) . '</option>' . "\n";
  408. }
  409. $t_project_count = count( $t_project_ids );
  410. for( $i = 0;$i < $t_project_count;$i++ ) {
  411. $t_id = $t_project_ids[$i];
  412. if( $t_id != $p_filter_project_id ) {
  413. echo '<option value="' . $t_id . '"';
  414. check_selected( $p_project_id, $t_id );
  415. echo '>' . string_attribute( project_get_field( $t_id, 'name' ) ) . '</option>' . "\n";
  416. print_subproject_option_list( $t_id, $p_project_id, $p_filter_project_id, $p_trace, Array() );
  417. }
  418. }
  419. }
  420. # --------------------
  421. # List projects that the current user has access to
  422. function print_subproject_option_list( $p_parent_id, $p_project_id = null, $p_filter_project_id = null, $p_trace = false, $p_parents = Array() ) {
  423. array_push( $p_parents, $p_parent_id );
  424. $t_project_ids = current_user_get_accessible_subprojects( $p_parent_id );
  425. $t_project_count = count( $t_project_ids );
  426. for( $i = 0;$i < $t_project_count;$i++ ) {
  427. $t_full_id = $t_id = $t_project_ids[$i];
  428. if( $t_id != $p_filter_project_id ) {
  429. echo "<option value=\"";
  430. if( $p_trace ) {
  431. $t_full_id = join( $p_parents, ";" ) . ';' . $t_id;
  432. }
  433. echo $t_full_id . '"';
  434. check_selected( $p_project_id, $t_full_id );
  435. echo '>' . str_repeat( '&#160;', count( $p_parents ) ) . str_repeat( '&raquo;', count( $p_parents ) ) . ' ' . string_attribute( project_get_field( $t_id, 'name' ) ) . '</option>' . "\n";
  436. print_subproject_option_list( $t_id, $p_project_id, $p_filter_project_id, $p_trace, $p_parents );
  437. }
  438. }
  439. }
  440. # --------------------
  441. # Print extended project browser
  442. function print_extended_project_browser( $p_trace = Array(), $p_project_id = null ) {
  443. project_cache_all();
  444. $t_project_ids = current_user_get_accessible_projects();
  445. echo '<script type="text/javascript" language="JavaScript">' . "\n";
  446. echo "<!--\n";
  447. echo "var subprojects = new Object();\n";
  448. echo 'function unescapeHTML(html) {' . "\n";
  449. echo ' var htmlNode = document.createElement("DIV");' . "\n";
  450. echo ' htmlNode.innerHTML = html;' . "\n";
  451. echo ' if(htmlNode.innerText)' . "\n";
  452. echo ' return htmlNode.innerText; // IE' . "\n";
  453. echo ' return htmlNode.textContent; // FF' . "\n";
  454. echo '} ' . "\n";
  455. $t_projects = Array();
  456. $t_project_count = count( $t_project_ids );
  457. for( $i = 0;$i < $t_project_count;$i++ ) {
  458. $t_id = $t_project_ids[$i];
  459. echo 'subprojects[\'' . $t_id . '\'] = new Object();' . "\n";
  460. $t_name = project_get_field( $t_id, 'name' );
  461. $c_name = addslashes( $t_name );
  462. echo 'subprojects[\'' . $t_id . '\'][\'' . $t_id . '\'] = \'' . $c_name . '\';' . "\n";
  463. $t_projects[$t_id] = $t_name;
  464. print_extended_project_browser_subproject_javascript( $t_id );
  465. }
  466. echo "\n";
  467. echo 'function setProject(projectVal) {' . "\n";
  468. echo "\t" . 'var spInput = document.form_set_project.project_id;' . "\n";
  469. echo "\t" . 'spInput.options.length = 0' . "\n";
  470. echo "\t" . 'if (projectVal == "' . ALL_PROJECTS . '") {' . "\n";
  471. echo "\t\t" . 'spInput.options[0] = new Option(\'' . lang_get( 'all_projects' ) . '\', \'' . ALL_PROJECTS . '\');' . "\n";
  472. echo "\t" . '} else {' . "\n";
  473. echo "\t\t" . 'var i = 0;' . "\n";
  474. echo "\t\t" . 'var project = subprojects[ projectVal ];' . "\n";
  475. echo "\t\t" . 'for ( var sp in project ) {' . "\n";
  476. echo "\t\t\t" . 'spInput.options[ i++ ] = new Option( unescapeHTML(project[sp]), sp );' . "\n";
  477. echo "\t\t" . '}' . "\n";
  478. echo "\t" . '}' . "\n";
  479. echo '}' . "\n";
  480. echo '// --></script>' . "\n";
  481. echo '<select name="top_id" onChange="setProject(this.value); document.form_set_project.submit()" class="small">' . "\n";
  482. echo '<option value="' . ALL_PROJECTS . '"';
  483. echo check_selected( $p_project_id, ALL_PROJECTS );
  484. echo '>' . lang_get( 'all_projects' ) . '</option>' . "\n";
  485. foreach( $t_projects as $t_id => $t_name ) {
  486. $c_name = string_attribute( $t_name );
  487. echo '<option value="' . $t_id . '"';
  488. echo check_selected( $p_project_id, $t_id );
  489. echo '>' . $c_name . '</option>' . "\n";
  490. }
  491. echo '</select>' . "\n";
  492. if( 0 === count( $p_trace ) ) {
  493. $t_top_id = ALL_PROJECTS;
  494. } else {
  495. $t_top_id = $p_trace[0];
  496. $t_trace_str = join( ';', $p_trace );
  497. }
  498. echo '<select name="project_id" onChange="document.form_set_project.submit()" class="small-subprojects"></select>' . "\n";
  499. echo '<script type="text/javascript" language="JavaScript">' . "\n";
  500. echo '<!--' . "\n";
  501. echo 'document.form_set_project.top_id.value = \'' . $t_top_id . '\';' . "\n";
  502. echo 'setProject(' . $t_top_id . ');' . "\n";
  503. echo 'document.form_set_project.project_id.value = \'' . $t_trace_str . '\';' . "\n";
  504. echo '// --></script>' . "\n";
  505. }
  506. # --------------------
  507. # print the subproject javascript for the extended project browser
  508. function print_extended_project_browser_subproject_javascript( $p_trace ) {
  509. $t_trace_projects = explode( ';', $p_trace );
  510. $t_top_id = $t_trace_projects[0];
  511. $t_level = count( $t_trace_projects );
  512. $t_parent_id = $t_trace_projects[$t_level - 1];
  513. $t_project_ids = current_user_get_accessible_subprojects( $t_parent_id );
  514. $t_project_count = count( $t_project_ids );
  515. for( $i = 0;$i < $t_project_count;$i++ ) {
  516. $t_id = $t_project_ids[$i];
  517. $t_name = addslashes( str_repeat(( '&#160;' ), $t_level ) . str_repeat(( '&raquo;' ), $t_level ) . ' ' . project_get_field( $t_id, 'name' ) );
  518. echo 'subprojects[\'' . $t_top_id . '\'][\'' . $p_trace . ';' . $t_id . '\'] = \'' . $t_name . '\';' . "\n";
  519. print_extended_project_browser_subproject_javascript( $p_trace . ';' . $t_id );
  520. }
  521. }
  522. # --------------------
  523. # prints the profiles given the user id
  524. function print_profile_option_list( $p_user_id, $p_select_id = '', $p_profiles = null ) {
  525. if( '' === $p_select_id ) {
  526. $p_select_id = profile_get_default( $p_user_id );
  527. }
  528. if( $p_profiles != null ) {
  529. $t_profiles = $p_profiles;
  530. } else {
  531. $t_profiles = profile_get_all_for_user( $p_user_id );
  532. }
  533. print_profile_option_list_from_profiles( $t_profiles, $p_select_id );
  534. }
  535. # --------------------
  536. # prints the profiles used in a certain project
  537. function print_profile_option_list_for_project( $p_project_id, $p_select_id = '', $p_profiles = null ) {
  538. if( '' === $p_select_id ) {
  539. $p_select_id = profile_get_default( auth_get_current_user_id() );
  540. }
  541. if( $p_profiles != null ) {
  542. $t_profiles = $p_profiles;
  543. } else {
  544. $t_profiles = profile_get_all_for_project( $p_project_id );
  545. }
  546. print_profile_option_list_from_profiles( $t_profiles, $p_select_id );
  547. }
  548. # --------------------
  549. # print the profile option list from profiles array
  550. function print_profile_option_list_from_profiles( $p_profiles, $p_select_id ) {
  551. echo '<option value=""></option>';
  552. foreach( $p_profiles as $t_profile ) {
  553. extract( $t_profile, EXTR_PREFIX_ALL, 'v' );
  554. $t_platform = string_attribute( $t_profile['platform'] );
  555. $t_os = string_attribute( $t_profile['os'] );
  556. $t_os_build = string_attribute( $t_profile['os_build'] );
  557. echo '<option value="' . $t_profile['id'] . '"';
  558. check_selected( $p_select_id, $t_profile['id'] );
  559. echo '>' . $t_platform . ' ' . $t_os . ' ' . $t_os_build . '</option>';
  560. }
  561. }
  562. # --------------------
  563. # Since categories can be orphaned we need to grab all unique instances of category
  564. # We check in the project category table and in the bug table
  565. # We put them all in one array and make sure the entries are unique
  566. function print_category_option_list( $p_category_id = 0, $p_project_id = null ) {
  567. $t_category_table = db_get_table( 'mantis_category_table' );
  568. $t_project_table = db_get_table( 'mantis_project_table' );
  569. if( null === $p_project_id ) {
  570. $t_project_id = helper_get_current_project();
  571. } else {
  572. $t_project_id = $p_project_id;
  573. }
  574. if( config_get( 'allow_no_category' ) ) {
  575. echo "<option value=\"0\"", check_selected( $p_category_id, 0 ), '>';
  576. echo category_full_name( 0, /* show project */ false ), '</option>';
  577. } else {
  578. if( 0 == $p_category_id ) {
  579. echo "<option value=\"0\"", check_selected( $p_category_id, 0 ), '>';
  580. echo string_attribute( lang_get( 'select_option' ) ), '</option>';
  581. }
  582. }
  583. $cat_arr = category_get_all_rows( $t_project_id, /* inherit */ null, /* sortByProject */ true );
  584. foreach( $cat_arr as $t_category_row ) {
  585. $t_category_id = $t_category_row['id'];
  586. echo "<option value=\"$t_category_id\"";
  587. check_selected( $p_category_id, $t_category_id );
  588. echo '>' . string_attribute( category_full_name( $t_category_id, $t_category_row['project_id'] != $t_project_id ) ) . '</option>';
  589. }
  590. }
  591. /**
  592. * Now that categories are identified by numerical ID, we need an old-style name
  593. * based option list to keep existing filter functionality.
  594. * @param string $p_category_name The selected category
  595. * @param mixed $p_project_id A specific project or null
  596. */
  597. function print_category_filter_option_list( $p_category_name = '', $p_project_id = null ) {
  598. $t_cat_arr = category_get_filter_list( $p_project_id );
  599. natcasesort( $t_cat_arr );
  600. foreach( $t_cat_arr as $t_cat ) {
  601. $t_name = string_attribute( $t_cat );
  602. echo '<option value="' . $t_name . '"';
  603. check_selected( string_attribute( $p_category_name ), $t_name );
  604. echo '>' . $t_name . '</option>';
  605. }
  606. }
  607. # --------------------
  608. # Print the option list for platforms accessible for the specified user.
  609. function print_platform_option_list( $p_platform, $p_user_id = null ) {
  610. $t_platforms_array = profile_get_field_all_for_user( 'platform', $p_user_id );
  611. foreach( $t_platforms_array as $t_platform ) {
  612. $t_platform = string_attribute( $t_platform );
  613. echo '<option value="' . $t_platform . '"';
  614. check_selected( string_attribute( $p_platform ), $t_platform );
  615. echo '>' . $t_platform . '</option>';
  616. }
  617. }
  618. # --------------------
  619. # Print the option list for OSes accessible for the specified user.
  620. function print_os_option_list( $p_os, $p_user_id = null ) {
  621. $t_os_array = profile_get_field_all_for_user( 'os', $p_user_id );
  622. foreach( $t_os_array as $t_os ) {
  623. $t_os = string_attribute( $t_os );
  624. echo '<option value="' . $t_os . '"';
  625. check_selected( string_attribute( $p_os ), $t_os );
  626. echo '>' . $t_os . '</option>';
  627. }
  628. }
  629. # Print the option list for os_build accessible for the specified user.
  630. function print_os_build_option_list( $p_os_build, $p_user_id = null ) {
  631. $t_os_build_array = profile_get_field_all_for_user( 'os_build', $p_user_id );
  632. foreach( $t_os_build_array as $t_os_build ) {
  633. $t_os_build = string_attribute( $t_os_build );
  634. echo '<option value="' . $t_os_build . '"';
  635. check_selected( string_attribute( $p_os_build ), $t_os_build );
  636. echo '>' . $t_os_build . '</option>';
  637. }
  638. }
  639. # Print the option list for versions
  640. # $p_version = currently selected version.
  641. # $p_project_id = project id, otherwise current project will be used.
  642. # $p_released = null to get all, 1: only released, 0: only future versions
  643. # $p_leading_black = allow selection of no version
  644. # $p_with_subs = include subprojects
  645. function print_version_option_list( $p_version = '', $p_project_id = null, $p_released = null, $p_leading_blank = true, $p_with_subs = false ) {
  646. if( null === $p_project_id ) {
  647. $c_project_id = helper_get_current_project();
  648. } else {
  649. $c_project_id = db_prepare_int( $p_project_id );
  650. }
  651. if( $p_with_subs ) {
  652. $versions = version_get_all_rows_with_subs( $c_project_id, $p_released,
  653. /* obsolete */
  654. null );
  655. } else {
  656. $versions = version_get_all_rows( $c_project_id, $p_released,
  657. /* obsolete */
  658. null );
  659. }
  660. if( $p_leading_blank ) {
  661. echo '<option value=""></option>';
  662. }
  663. $t_listed = array();
  664. $t_max_length = config_get( 'max_dropdown_length' );
  665. $t_show_version_dates = access_has_project_level( config_get( 'show_version_dates_threshold' ) );
  666. $t_short_date_format = config_get( 'short_date_format' );
  667. foreach( $versions as $version ) {
  668. # If the current version is obsolete, and current version not equal to $p_version,
  669. # then skip it.
  670. if(( (int) $version['obsolete'] ) == 1 ) {
  671. if( $version['version'] != $p_version ) {
  672. continue;
  673. }
  674. }
  675. $t_version = string_attribute( $version['version'] );
  676. if ( !in_array( $t_version, $t_listed ) ) {
  677. $t_listed[] = $t_version;
  678. echo '<option value="' . $t_version . '"';
  679. check_selected( string_attribute( $p_version ), $t_version );
  680. $t_version_string = string_attribute( prepare_version_string( $c_project_id, $version['id'] ) );
  681. echo '>', string_shorten( $t_version_string , $t_max_length ), '</option>';
  682. }
  683. }
  684. }
  685. function print_build_option_list( $p_build = '' ) {
  686. $t_bug_table = db_get_table( 'mantis_bug_table' );
  687. $t_overall_build_arr = array();
  688. $t_project_id = helper_get_current_project();
  689. $t_project_where = helper_project_specific_where( $t_project_id );
  690. # Get the "found in" build list
  691. $query = "SELECT DISTINCT build
  692. FROM $t_bug_table
  693. WHERE $t_project_where
  694. ORDER BY build DESC";
  695. $result = db_query_bound( $query );
  696. $option_count = db_num_rows( $result );
  697. for( $i = 0;$i < $option_count;$i++ ) {
  698. $row = db_fetch_array( $result );
  699. $t_overall_build_arr[] = $row['build'];
  700. }
  701. $t_max_length = config_get( 'max_dropdown_length' );
  702. foreach( $t_overall_build_arr as $t_build ) {
  703. $t_build = string_attribute( $t_build );
  704. echo "<option value=\"$t_build\"";
  705. check_selected( string_attribute( $p_build ), $t_build );
  706. echo ">" . string_shorten( $t_build, $t_max_length ) . "</option>";
  707. }
  708. }
  709. # select the proper enum values based on the input parameter
  710. # $p_enum_name - name of enumeration (eg: status)
  711. # $p_val: current value
  712. function print_enum_string_option_list( $p_enum_name, $p_val = 0 ) {
  713. $t_config_var_name = $p_enum_name . '_enum_string';
  714. $t_config_var_value = config_get( $t_config_var_name );
  715. $t_enum_values = MantisEnum::getValues( $t_config_var_value );
  716. foreach ( $t_enum_values as $t_key ) {
  717. $t_elem2 = get_enum_element( $p_enum_name, $t_key );
  718. echo '<option value="' . $t_key . '"';
  719. check_selected( $p_val, $t_key );
  720. echo '>' . $t_elem2 . '</option>';
  721. }
  722. }
  723. # Select the proper enum values for status based on workflow
  724. # or the input parameter if workflows are not used
  725. # $p_enum_name : name of enumeration (eg: status)
  726. # $p_current_value : current value
  727. function get_status_option_list( $p_user_auth = 0, $p_current_value = 0, $p_show_current = true, $p_add_close = false, $p_project_id = ALL_PROJECTS ) {
  728. $t_config_var_value = config_get( 'status_enum_string', null, null, $p_project_id );
  729. $t_enum_workflow = config_get( 'status_enum_workflow', null, null, $p_project_id );
  730. if( count( $t_enum_workflow ) < 1 ) {
  731. # workflow not defined, use default enum
  732. $t_enum_values = MantisEnum::getValues( $t_config_var_value );
  733. } else {
  734. # workflow defined - find allowed states
  735. if( isset( $t_enum_workflow[$p_current_value] ) ) {
  736. $t_enum_values = MantisEnum::getValues( $t_enum_workflow[$p_current_value] );
  737. } else {
  738. # workflow was not set for this status, this shouldn't happen
  739. $t_enum_values = MantisEnum::getValues( $t_config_var_value );
  740. }
  741. }
  742. $t_enum_list = array();
  743. foreach ( $t_enum_values as $t_enum_value ) {
  744. if ( ( access_compare_level( $p_user_auth, access_get_status_threshold( $t_enum_value, $p_project_id ) ) )
  745. && ( !(( false == $p_show_current ) && ( $p_current_value == $t_enum_value ) ) ) ) {
  746. $t_enum_list[$t_enum_value] = get_enum_element( 'status', $t_enum_value );
  747. }
  748. }
  749. if ( $p_show_current ) {
  750. $t_enum_list[$p_current_value] = get_enum_element( 'status', $p_current_value );
  751. }
  752. if ( $p_add_close && access_compare_level( $p_current_value, config_get( 'bug_resolved_status_threshold', null, null, $p_project_id ) ) ) {
  753. $t_closed = config_get( 'bug_closed_status_threshold', null, null, $p_project_id );
  754. $t_enum_list[$t_closed] = get_enum_element( 'status', $t_closed );
  755. }
  756. return $t_enum_list;
  757. }
  758. # print the status option list for the bug_update pages
  759. function print_status_option_list( $p_select_label, $p_current_value = 0, $p_allow_close = false, $p_project_id = ALL_PROJECTS ) {
  760. $t_current_auth = access_get_project_level( $p_project_id );
  761. $t_enum_list = get_status_option_list( $t_current_auth, $p_current_value, true, $p_allow_close, $p_project_id );
  762. if( count( $t_enum_list ) > 1 ) {
  763. # resort the list into ascending order
  764. ksort( $t_enum_list );
  765. reset( $t_enum_list );
  766. echo '<select ', helper_get_tab_index(), ' name="' . $p_select_label . '">';
  767. foreach( $t_enum_list as $key => $val ) {
  768. echo '<option value="' . $key . '"';
  769. check_selected( $key, $p_current_value );
  770. echo '>' . $val . '</option>';
  771. }
  772. echo '</select>';
  773. } else if ( count( $t_enum_list ) == 1 ) {
  774. echo array_pop( $t_enum_list );
  775. } else {
  776. echo MantisEnum::getLabel( lang_get( 'status_enum_string' ), $p_current_value );
  777. }
  778. }
  779. # prints the list of a project's users
  780. # if no project is specified uses the current project
  781. function print_project_user_option_list( $p_project_id = null ) {
  782. print_user_option_list( 0, $p_project_id );
  783. }
  784. # prints the list of access levels that are less than or equal to the access level of the
  785. # logged in user. This is used when adding users to projects
  786. function print_project_access_levels_option_list( $p_val, $p_project_id = null ) {
  787. $t_current_user_access_level = access_get_project_level( $p_project_id );
  788. $t_access_levels_enum_string = config_get( 'access_levels_enum_string' );
  789. $t_enum_values = MantisEnum::getValues( $t_access_levels_enum_string );
  790. foreach ( $t_enum_values as $t_enum_value ) {
  791. # a user must not be able to assign another user an access level that is higher than theirs.
  792. if ( $t_enum_value > $t_current_user_access_level ) {
  793. continue;
  794. }
  795. $t_access_level = get_enum_element( 'access_levels', $t_enum_value );
  796. echo '<option value="' . $t_enum_value . '"';
  797. check_selected( $p_val, $t_enum_value );
  798. echo '>' . $t_access_level . '</option>';
  799. }
  800. }
  801. function print_language_option_list( $p_language ) {
  802. $t_arr = config_get( 'language_choices_arr' );
  803. $enum_count = count( $t_arr );
  804. for( $i = 0;$i < $enum_count;$i++ ) {
  805. $t_language = string_attribute( $t_arr[$i] );
  806. echo '<option value="' . $t_language . '"';
  807. check_selected( $t_language, $p_language );
  808. echo '>' . $t_language . '</option>';
  809. }
  810. }
  811. /**
  812. * Print a dropdown list of all bug actions available to a user for a specified
  813. * set of projects.
  814. * @param array $p_projects An array containing one or more project IDs
  815. * @return null
  816. */
  817. function print_all_bug_action_option_list( $p_project_ids = null ) {
  818. $t_commands = bug_group_action_get_commands( $p_project_ids);
  819. while( list( $t_action_id, $t_action_label ) = each( $t_commands ) ) {
  820. echo '<option value="' . $t_action_id . '">' . $t_action_label . '</option>';
  821. }
  822. }
  823. # --------------------
  824. # list of users that are NOT in the specified project and that are enabled
  825. # if no project is specified use the current project
  826. # also exclude any administrators
  827. function print_project_user_list_option_list( $p_project_id = null ) {
  828. $t_mantis_project_user_list_table = db_get_table( 'mantis_project_user_list_table' );
  829. $t_mantis_user_table = db_get_table( 'mantis_user_table' );
  830. if( null === $p_project_id ) {
  831. $p_project_id = helper_get_current_project();
  832. }
  833. $c_project_id = (int) $p_project_id;
  834. $t_adm = config_get_global( 'admin_site_threshold' );
  835. $query = "SELECT DISTINCT u.id, u.username, u.realname
  836. FROM $t_mantis_user_table u
  837. LEFT JOIN $t_mantis_project_user_list_table p
  838. ON p.user_id=u.id AND p.project_id=" . db_param() . "
  839. WHERE u.access_level<" . db_param() . " AND
  840. u.enabled = " . db_param() . " AND
  841. p.user_id IS NULL
  842. ORDER BY u.realname, u.username";
  843. $result = db_query_bound( $query, Array( $c_project_id, $t_adm, true ) );
  844. $t_display = array();
  845. $t_sort = array();
  846. $t_users = array();
  847. $t_show_realname = ( ON == config_get( 'show_realname' ) );
  848. $t_sort_by_last_name = ( ON == config_get( 'sort_by_last_name' ) );
  849. $category_count = db_num_rows( $result );
  850. for( $i = 0;$i < $category_count;$i++ ) {
  851. $row = db_fetch_array( $result );
  852. $t_users[] = $row['id'];
  853. $t_user_name = string_attribute( $row['username'] );
  854. $t_sort_name = $t_user_name;
  855. if(( isset( $row['realname'] ) ) && ( $row['realname'] <> '' ) && $t_show_realname ) {
  856. $t_user_name = string_attribute( $row['realname'] );
  857. if( $t_sort_by_last_name ) {
  858. $t_sort_name_bits = explode( ' ', utf8_strtolower( $t_user_name ), 2 );
  859. $t_sort_name = ( isset( $t_sort_name_bits[1] ) ? $t_sort_name_bits[1] . ', ' : '' ) . $t_sort_name_bits[0];
  860. } else {
  861. $t_sort_name = utf8_strtolower( $t_user_name );
  862. }
  863. }
  864. $t_display[] = $t_user_name;
  865. $t_sort[] = $t_sort_name;
  866. }
  867. array_multisort( $t_sort, SORT_ASC, SORT_STRING, $t_users, $t_display );
  868. $t_count = count( $t_sort );
  869. for( $i = 0;$i < $t_count; $i++ ) {
  870. echo '<option value="' . $t_users[$i] . '">' . $t_display[$i] . '</option>';
  871. }
  872. }
  873. # list of projects that a user is NOT in
  874. function print_project_user_list_option_list2( $p_user_id ) {
  875. $t_mantis_project_user_list_table = db_get_table( 'mantis_project_user_list_table' );
  876. $t_mantis_project_table = db_get_table( 'mantis_project_table' );
  877. $c_user_id = db_prepare_int( $p_user_id );
  878. $query = "SELECT DISTINCT p.id, p.name
  879. FROM $t_mantis_project_table p
  880. LEFT JOIN $t_mantis_project_user_list_table u
  881. ON p.id=u.project_id AND u.user_id=" . db_param() . "
  882. WHERE p.enabled = " . db_param() . " AND
  883. u.user_id IS NULL
  884. ORDER BY p.name";
  885. $result = db_query_bound( $query, Array( $c_user_id, true ) );
  886. $category_count = db_num_rows( $result );
  887. for( $i = 0;$i < $category_count;$i++ ) {
  888. $row = db_fetch_array( $result );
  889. $t_project_name = string_attribute( $row['name'] );
  890. $t_user_id = $row['id'];
  891. echo "<option value=\"$t_user_id\">$t_project_name</option>";
  892. }
  893. }
  894. # list of projects that a user is in
  895. function print_project_user_list( $p_user_id, $p_include_remove_link = true ) {
  896. $t_mantis_project_user_list_table = db_get_table( 'mantis_project_user_list_table' );
  897. $t_mantis_project_table = db_get_table( 'mantis_project_table' );
  898. $c_user_id = db_prepare_int( $p_user_id );
  899. $query = "SELECT DISTINCT p.id, p.name, p.view_state, u.access_level
  900. FROM $t_mantis_project_table p
  901. LEFT JOIN $t_mantis_project_user_list_table u
  902. ON p.id=u.project_id
  903. WHERE p.enabled = '1' AND
  904. u.user_id=" . db_param() . "
  905. ORDER BY p.name";
  906. $result = db_query_bound( $query, Array( $c_user_id ) );
  907. $category_count = db_num_rows( $result );
  908. for( $i = 0;$i < $category_count;$i++ ) {
  909. $row = db_fetch_array( $result );
  910. $t_project_id = $row['id'];
  911. $t_project_name = string_attribute( $row['name'] );
  912. $t_view_state = $row['view_state'];
  913. $t_access_level = $row['access_level'];
  914. $t_access_level = get_enum_element( 'access_levels', $t_access_level );
  915. $t_view_state = get_enum_element( 'project_view_state', $t_view_state );
  916. echo $t_project_name . ' [' . $t_access_level . '] (' . $t_view_state . ')';
  917. if( $p_include_remove_link && access_has_project_level( config_get( 'project_user_threshold' ), $t_project_id ) ) {
  918. html_button( 'manage_user_proj_delete.php', lang_get( 'remove_link' ), array( 'project_id' => $t_project_id, 'user_id' => $p_user_id ) );
  919. }
  920. echo '<br />';
  921. }
  922. }
  923. # List of projects with which the specified field id is linked.
  924. # For every project, the project name is listed and then the list of custom
  925. # fields linked in order with their sequence numbers. The specified field
  926. # is always highlighted in italics and project names in bold.
  927. #
  928. # $p_field_id - The field to list the projects associated with.
  929. function print_custom_field_projects_list( $p_field_id ) {
  930. $c_field_id = (integer) $p_field_id;
  931. $t_project_ids = custom_field_get_project_ids( $p_field_id );
  932. $t_security_token = form_security_param( 'manage_proj_custom_field_remove' );
  933. foreach( $t_project_ids as $t_project_id ) {
  934. $t_project_name = project_get_field( $t_project_id, 'name' );
  935. $t_sequence = custom_field_get_sequence( $p_field_id, $t_project_id );
  936. echo '<b>', string_display_line( $t_project_name ), '</b>: ';
  937. print_bracket_link( "manage_proj_custom_field_remove.php?field_id=$c_field_id&project_id=$t_project_id&return=custom_field$t_security_token", lang_get( 'remove_link' ) );
  938. echo '<br />- ';
  939. $t_linked_field_ids = custom_field_get_linked_ids( $t_project_id );
  940. $t_current_project_fields = array();
  941. $t_first = true;
  942. foreach( $t_linked_field_ids as $t_current_field_id ) {
  943. if( $t_first ) {
  944. $t_first = false;
  945. } else {
  946. echo ', ';
  947. }
  948. if( $t_current_field_id == $p_field_id ) {
  949. echo '<em>';
  950. }
  951. echo string_display_line( custom_field_get_field( $t_current_field_id, 'name' ) );
  952. echo ' (', custom_field_get_sequence( $t_current_field_id, $t_project_id ), ')';
  953. if( $t_current_field_id == $p_field_id ) {
  954. echo '</em>';
  955. }
  956. }
  957. echo '<br /><br />';
  958. }
  959. }
  960. /**
  961. * List of priorities that can be assigned to a plugin.
  962. * @param int current priority
  963. */
  964. function print_plugin_priority_list( $p_priority ) {
  965. if( $p_priority < 1 && $p_priority > 5 ) {
  966. echo '<option value="', $p_priority, '" selected="selected">', $p_priority, '</option>';
  967. }
  968. for( $i = 5;$i >= 1;$i-- ) {
  969. echo '<option value="', $i, '" ', check_selected( $p_priority, $i ), ' >', $i, '</option>';
  970. }
  971. }
  972. # ##########################################################################
  973. # String printing API
  974. # ##########################################################################
  975. # prints a link to VIEW a bug given an ID
  976. # account for the user preference and site override
  977. function print_bug_link( $p_bug_id, $p_detail_info = true ) {
  978. echo string_get_bug_view_link( $p_bug_id, null, $p_detail_info );
  979. }
  980. # formats the priority given the status
  981. # shows the priority in BOLD if the bug is NOT closed and is of significant priority
  982. function print_formatted_priority_string( $p_status, $p_priority ) {
  983. $t_pri_str = get_enum_element( 'priority', $p_priority );
  984. $t_priority_threshold = config_get( 'priority_significant_threshold' );
  985. if( $t_priority_threshold >= 0 &&
  986. $p_priority >= $t_priority_threshold &&
  987. $p_status < config_get( 'bug_closed_status_threshold' ) ) {
  988. echo "<span class=\"bold\">$t_pri_str</span>";
  989. } else {
  990. echo $t_pri_str;
  991. }
  992. }
  993. # formats the severity given the status
  994. # shows the severity in BOLD if the bug is NOT closed and is of significant severity
  995. function print_formatted_severity_string( $p_status, $p_severity ) {
  996. $t_sev_str = get_enum_element( 'severity', $p_severity );
  997. $t_severity_threshold = config_get( 'severity_significant_threshold' );
  998. if( $t_severity_threshold >= 0 &&
  999. $p_severity >= $t_severity_threshold &&
  1000. $p_status < config_get( 'bug_closed_status_threshold' ) ) {
  1001. echo "<span class=\"bold\">$t_sev_str</span>";
  1002. } else {
  1003. echo $t_sev_str;
  1004. }
  1005. }
  1006. # ##########################################################################
  1007. # Link Printing API
  1008. # ##########################################################################
  1009. # $p_columns_target: see COLUMNS_TARGET_* in constant_inc.php
  1010. function print_view_bug_sort_link( $p_string, $p_sort_field, $p_sort, $p_dir, $p_columns_target = COLUMNS_TARGET_VIEW_PAGE ) {
  1011. if( $p_columns_target == COLUMNS_TARGET_PRINT_PAGE ) {
  1012. if( $p_sort_field == $p_sort ) {
  1013. # We toggle between ASC and DESC if the user clicks the same sort order
  1014. if( 'ASC' == $p_dir ) {
  1015. $p_dir = 'DESC';
  1016. } else {
  1017. $p_dir = 'ASC';
  1018. }
  1019. } else {
  1020. # Otherwise always start with ASCending
  1021. $t_dir = 'ASC';
  1022. }
  1023. $t_sort_field = rawurlencode( $p_sort_field );
  1024. print_link( "view_all_set.php?sort=$t_sort_field&dir=$p_dir&type=2&print=1", $p_string );
  1025. }
  1026. else if( $p_columns_target == COLUMNS_TARGET_VIEW_PAGE ) {
  1027. if( $p_sort_field == $p_sort ) {
  1028. # we toggle between ASC and DESC if the user clicks the same sort order
  1029. if( 'ASC' == $p_dir ) {
  1030. $p_dir = 'DESC';
  1031. } else {
  1032. $p_dir = 'ASC';
  1033. }
  1034. } else {
  1035. # Otherwise always start with ASCending
  1036. $t_dir = 'ASC';
  1037. }
  1038. $t_sort_field = rawurlencode( $p_sort_field );
  1039. print_link( "view_all_set.php?sort=$t_sort_field&dir=$p_dir&type=2", $p_string );
  1040. } else {
  1041. echo $p_string;
  1042. }
  1043. }
  1044. function print_manage_user_sort_link( $p_page, $p_string, $p_field, $p_dir, $p_sort_by, $p_hide = 0, $p_filter = ALL ) {
  1045. if( $p_sort_by == $p_field ) {
  1046. # If this is the selected field flip the order
  1047. if( 'ASC' == $p_dir || ASCENDING == $p_dir ) {
  1048. $t_dir = 'DESC';
  1049. } else {
  1050. $t_dir = 'ASC';
  1051. }
  1052. } else {
  1053. # Otherwise always start with ASCending
  1054. $t_dir = 'ASC';
  1055. }
  1056. $t_field = rawurlencode( $p_field );
  1057. print_link( "$p_page?sort=$t_field&dir=$t_dir&save=1&hide=$p_hide&filter=$p_filter", $p_string );
  1058. }
  1059. function print_manage_project_sort_link( $p_page, $p_string, $p_field, $p_dir, $p_sort_by ) {
  1060. if( $p_sort_by == $p_field ) {
  1061. # If this is the selected field flip the order
  1062. if( 'ASC' == $p_dir || ASCENDING == $p_dir ) {
  1063. $t_dir = 'DESC';
  1064. } else {
  1065. $t_dir = 'ASC';
  1066. }
  1067. } else {
  1068. # Otherwise always start with ASCending
  1069. $t_dir = 'ASC';
  1070. }
  1071. $t_field = rawurlencode( $p_field );
  1072. print_link( "$p_page?sort=$t_field&dir=$t_dir", $p_string );
  1073. }
  1074. # print a button which presents a standalone form.
  1075. # $p_action_page - The action page
  1076. # $p_label - The button label
  1077. # $p_args_to_post - An associative array with key => value to be posted, can be null.
  1078. function print_button( $p_action_page, $p_label, $p_args_to_post = null ) {
  1079. $t_form_name = explode( '.php', $p_action_page, 2 );
  1080. # TODO: ensure all uses of print_button supply arguments via $p_args_to_post (POST)
  1081. # instead of via $p_action_page (GET). Then only add the CSRF form token if
  1082. # arguments are being sent via the POST method.
  1083. echo '<form method="post" action="', htmlspecialchars( $p_action_page ), '">';
  1084. echo form_security_field( $t_form_name[0] );
  1085. echo '<input type="submit" class="button-small" value="', $p_label, '" />';
  1086. if( $p_args_to_post !== null ) {
  1087. foreach( $p_args_to_post as $t_var => $t_value ) {
  1088. echo "<input type=\"hidden\" name=\"$t_var\" value=\"$t_value\" />";
  1089. }
  1090. }
  1091. echo '</form>';
  1092. }
  1093. # print brackets around a pre-prepared link (i.e. '<a href' html tag).
  1094. function print_bracket_link_prepared( $p_link ) {
  1095. echo '<span class="bracket-link">[&#160;' . $p_link . '&#160;]</span> ';
  1096. }
  1097. # print the bracketed links used near the top
  1098. # if the $p_link is blank then the text is printed but no link is created
  1099. # if $p_new_window is true, link will open in a new window, default false.
  1100. function print_bracket_link( $p_link, $p_url_text, $p_new_window = false, $p_class = '' ) {
  1101. echo '<span class="bracket-link">[&#160;';
  1102. print_link( $p_link, $p_url_text, $p_new_window, $p_class );
  1103. echo '&#160;]</span> ';
  1104. }
  1105. # print a HTML link
  1106. function print_link( $p_link, $p_url_text, $p_new_window = false, $p_class = '' ) {
  1107. if( is_blank( $p_link ) ) {
  1108. echo $p_url_text;
  1109. } else {
  1110. $t_link = htmlspecialchars( $p_link );
  1111. if( $p_new_window === true ) {
  1112. if( $p_class !== '') {
  1113. echo "<a class=\"$p_class\" href=\"$t_link\" target=\"_blank\">$p_url_text</a>";
  1114. } else {
  1115. echo "<a href=\"$t_link\" target=\"_blank\">$p_url_text</a>";
  1116. }
  1117. } else {
  1118. if( $p_class !== '') {
  1119. echo "<a class=\"$p_class\" href=\"$t_link\">$p_url_text</a>";
  1120. } else {
  1121. echo "<a href=\"$t_link\">$p_url_text</a>";
  1122. }
  1123. }
  1124. }
  1125. }
  1126. # print a HTML page link
  1127. function print_page_link( $p_page_url, $p_text = '', $p_page_no = 0, $p_page_cur = 0, $p_temp_filter_id = 0 ) {
  1128. if( is_blank( $p_text ) ) {
  1129. $p_text = $p_page_no;
  1130. }
  1131. if( ( 0 < $p_page_no ) && ( $p_page_no != $p_page_cur ) ) {
  1132. $t_delimiter = ( strpos( $p_page_url, "?" ) ? "&" : "?" );
  1133. if( $p_temp_filter_id !== 0 ) {
  1134. print_link( "$p_page_url${t_delimiter}filter=$p_temp_filter_id&page_number=$p_page_no", $p_text );
  1135. } else {
  1136. print_link( "$p_page_url${t_delimiter}page_number=$p_page_no", $p_text );
  1137. }
  1138. } else {
  1139. echo $p_text;
  1140. }
  1141. }
  1142. # print a list of page number links (eg [1 2 3])
  1143. function print_page_links( $p_page, $p_start, $p_end, $p_current, $p_temp_filter_id = 0 ) {
  1144. $t_items = array();
  1145. $t_link = '';
  1146. # Check if we have more than one page,
  1147. # otherwise return without doing anything.
  1148. if( $p_end - $p_start < 1 ) {
  1149. return;
  1150. }
  1151. # Get localized strings
  1152. $t_first = lang_get( 'first' );
  1153. $t_last = lang_get( 'last' );
  1154. $t_prev = lang_get( 'prev' );
  1155. $t_next = lang_get( 'next' );
  1156. $t_page_links = 10;
  1157. print( "[ " );
  1158. # First and previous links
  1159. print_page_link( $p_page, $t_first, 1, $p_current, $p_temp_filter_id );
  1160. echo '&#160;';
  1161. print_page_link( $p_page, $t_prev, $p_current - 1, $p_current, $p_temp_filter_id );
  1162. echo '&#160;';
  1163. # Page numbers ...
  1164. $t_first_page = max( $p_start, $p_current - $t_page_links / 2 );
  1165. $t_first_page = min( $t_first_page, $p_end - $t_page_links );
  1166. $t_first_page = max( $t_first_page, $p_start );
  1167. if( $t_first_page > 1 ) {
  1168. print( " ... " );
  1169. }
  1170. $t_last_page = $t_first_page + $t_page_links;
  1171. $t_last_page = min( $t_last_page, $p_end );
  1172. for( $i = $t_first_page;$i <= $t_last_page;$i++ ) {
  1173. if( $i == $p_current ) {
  1174. array_push( $t_items, $i );
  1175. } else {
  1176. $t_delimiter = ( strpos( $p_page, "?" ) ? "&" : "?" ) ;
  1177. if( $p_temp_filter_id !== 0 ) {
  1178. array_push( $t_items, "<a href=\"$p_page${t_delimiter}filter=$p_temp_filter_id&page_number=$i\">$i</a>" );
  1179. } else {
  1180. array_push( $t_items, "<a href=\"$p_page${t_delimiter}page_number=$i\">$i</a>" );
  1181. }
  1182. }
  1183. }
  1184. echo implode( '&#160;', $t_items );
  1185. if( $t_last_page < $p_end ) {
  1186. print( ' ... ' );
  1187. }
  1188. # Next and Last links
  1189. echo '&#160;';
  1190. if( $p_current < $p_end ) {
  1191. print_page_link( $p_page, $t_next, $p_current + 1, $p_current, $p_temp_filter_id );
  1192. } else {
  1193. print_page_link( $p_page, $t_next, null, null, $p_temp_filter_id );
  1194. }
  1195. echo '&#160;';
  1196. print_page_link( $p_page, $t_last, $p_end, $p_current, $p_temp_filter_id );
  1197. print( ' ]' );
  1198. }
  1199. # print a mailto: href link
  1200. function print_email_link( $p_email, $p_text ) {
  1201. echo get_email_link( $p_email, $p_text );
  1202. }
  1203. # return the mailto: href string link instead of printing it
  1204. function get_email_link( $p_email, $p_text ) {
  1205. return prepare_email_link( $p_email, $p_text );
  1206. }
  1207. # print a mailto: href link with subject
  1208. function print_email_link_with_subject( $p_email, $p_text, $p_bug_id ) {
  1209. $t_subject = email_build_subject( $p_bug_id );
  1210. echo get_email_link_with_subject( $p_email, $p_text, $t_subject );
  1211. }
  1212. # return the mailto: href string link instead of printing it
  1213. # add subject line
  1214. function get_email_link_with_subject( $p_email, $p_text, $p_summary ) {
  1215. if( !access_has_project_level( config_get( 'show_user_email_threshold' ) ) ) {
  1216. return $p_text;
  1217. }
  1218. # If we a

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