[ Index ]

PHP Cross Reference of MantisBT

title

Body

[close]

/core/ -> print_api.php (source)

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


Generated: Thu Jul 28 15:48:31 2011 Cross-referenced by PHPXref 0.7