[ Index ]

PHP Cross Reference of MantisBT

title

Body

[close]

/core/ -> string_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   * String Processing API
  19   *
  20   * @package CoreAPI
  21   * @subpackage StringProcessingAPI
  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_api.php
  29   * @uses bugnote_api.php
  30   * @uses config_api.php
  31   * @uses constant_inc.php
  32   * @uses email_api.php
  33   * @uses event_api.php
  34   * @uses helper_api.php
  35   * @uses lang_api.php
  36   * @uses user_api.php
  37   * @uses utility_api.php
  38   */
  39  
  40  require_api( 'access_api.php' );
  41  require_api( 'authentication_api.php' );
  42  require_api( 'bug_api.php' );
  43  require_api( 'bugnote_api.php' );
  44  require_api( 'config_api.php' );
  45  require_api( 'constant_inc.php' );
  46  require_api( 'email_api.php' );
  47  require_api( 'event_api.php' );
  48  require_api( 'helper_api.php' );
  49  require_api( 'lang_api.php' );
  50  require_api( 'user_api.php' );
  51  require_api( 'utility_api.php' );
  52  
  53  $g_cache_html_valid_tags = '';
  54  $g_cache_html_valid_tags_single_line = '';
  55  
  56  /**
  57   * Preserve spaces at beginning of lines.
  58   * Lines must be separated by \n rather than <br />
  59   * @param string $p_string
  60   * @return string
  61   */
  62   function string_preserve_spaces_at_bol( $p_string ) {
  63      $lines = explode( "\n", $p_string );
  64      $line_count = count( $lines );
  65      for( $i = 0;$i < $line_count;$i++ ) {
  66          $count = 0;
  67          $prefix = '';
  68  
  69          $t_char = utf8_substr( $lines[$i], $count, 1 );
  70          $spaces = 0;
  71          while(( $t_char == ' ' ) || ( $t_char == "\t" ) ) {
  72              if( $t_char == ' ' ) {
  73                  $spaces++;
  74              } else {
  75                  $spaces += 4;
  76              }
  77  
  78              // 1 tab = 4 spaces, can be configurable.
  79  
  80              $count++;
  81              $t_char = utf8_substr( $lines[$i], $count, 1 );
  82          }
  83  
  84          for( $j = 0;$j < $spaces;$j++ ) {
  85              $prefix .= '&#160;';
  86          }
  87  
  88          $lines[$i] = $prefix . utf8_substr( $lines[$i], $count );
  89      }
  90      return implode( "\n", $lines );
  91  }
  92  
  93  /**
  94   * Prepare a string to be printed without being broken into multiple lines
  95   * @param string $p_string
  96   * @return string
  97   */
  98  function string_no_break( $p_string ) {
  99      if( strpos( $p_string, ' ' ) !== false ) {
 100          return '<span class="nowrap">' . $p_string . "</span>";
 101      } else {
 102          return $p_string;
 103      }
 104  }
 105  
 106  /**
 107   * Similar to nl2br, but fixes up a problem where new lines are doubled between
 108   * html pre tags.
 109   * additionally, wrap the text an $p_wrap character intervals if the config is set
 110   * @param string $p_string
 111   * @param int $p_wrap
 112   * @return string
 113   */
 114  function string_nl2br( $p_string, $p_wrap = 100 ) {
 115      $output = '';
 116      $pieces = preg_split( '/(<pre[^>]*>.*?<\/pre>)/is', $p_string, -1, PREG_SPLIT_DELIM_CAPTURE );
 117      if( isset( $pieces[1] ) ) {
 118          foreach( $pieces as $piece ) {
 119              if( preg_match( '/(<pre[^>]*>.*?<\/pre>)/is', $piece ) ) {
 120                  $piece = preg_replace( "/<br[^>]*?>/", '', $piece );
 121  
 122                  # @@@ thraxisp - this may want to be replaced by html_entity_decode (or equivalent)
 123                  #     if other encoded characters are a problem
 124                  $piece = preg_replace( '/&#160;/', ' ', $piece );
 125                  if( ON == config_get( 'wrap_in_preformatted_text' ) ) {
 126                      $output .= preg_replace( '/([^\n]{' . $p_wrap . ',}?[\s]+)(?!<\/pre>)/', "$1\n", $piece );
 127                  } else {
 128                      $output .= $piece;
 129                  }
 130              } else {
 131                  $output .= nl2br( $piece );
 132              }
 133          }
 134          return $output;
 135      } else {
 136          return nl2br( $p_string );
 137      }
 138  }
 139  
 140  /**
 141   * Prepare a multiple line string for display to HTML
 142   * @param string $p_string
 143   * @return string
 144   */
 145  function string_display( $p_string ) {
 146      $t_data = event_signal( 'EVENT_DISPLAY_TEXT', $p_string, true );
 147      return $t_data;
 148  }
 149  
 150  /**
 151   * Prepare a single line string for display to HTML
 152   * @param string $p_string
 153   * @return string
 154   */
 155  function string_display_line( $p_string ) {
 156      $t_data = event_signal( 'EVENT_DISPLAY_TEXT', $p_string, false );
 157      return $t_data;
 158  }
 159  
 160  /**
 161   * Prepare a string for display to HTML and add href anchors for URLs, emails
 162   * and bug references
 163   * @param string $p_string
 164   * @return string
 165   */
 166  function string_display_links( $p_string ) {
 167      $t_data = event_signal( 'EVENT_DISPLAY_FORMATTED', $p_string, true );
 168      return $t_data;
 169  }
 170  
 171  /**
 172   * Prepare a single line string for display to HTML and add href anchors for
 173   * URLs, emails and bug references
 174   * @param string $p_string
 175   * @return string
 176   */
 177  function string_display_line_links( $p_string ) {
 178      $t_data = event_signal( 'EVENT_DISPLAY_FORMATTED', $p_string, false );
 179      return $t_data;
 180  }
 181  
 182  /**
 183   * Prepare a string for display in rss
 184   * @param string
 185   * @return string
 186   */
 187  function string_rss_links( $p_string ) {
 188      # rss can not start with &#160; which spaces will be replaced into by string_display().
 189      $t_string = trim( $p_string );
 190  
 191      $t_string = event_signal( 'EVENT_DISPLAY_RSS', $t_string );
 192  
 193      # another escaping to escape the special characters created by the generated links
 194      return string_html_specialchars( $t_string );
 195  }
 196  
 197  /**
 198   * Prepare a string for plain text display in email
 199   * @param string $p_string
 200   * @return string
 201   */
 202  function string_email( $p_string ) {
 203      return string_strip_hrefs( $p_string );
 204  }
 205  
 206  /**
 207   * Prepare a string for plain text display in email and add URLs for bug
 208   * links
 209   * @param string
 210   * @return string
 211   */
 212  function string_email_links( $p_string ) {
 213      return event_signal( 'EVENT_DISPLAY_EMAIL', $p_string );
 214  }
 215  
 216  # --------------------
 217  # Process a string for display in a textarea box
 218  /**
 219   * @todo function documentation
 220   * @param string
 221   * @return string
 222   */
 223  function string_textarea( $p_string ) {
 224      return string_html_specialchars( $p_string );
 225  }
 226  
 227  /**
 228   * Process a string for display in a text box
 229   * @param string
 230   * @return string
 231   */
 232  function string_attribute( $p_string ) {
 233      return string_html_specialchars( $p_string );
 234  }
 235  
 236  /**
 237   * Process a string for inclusion in a URL as a GET parameter
 238   * @param string $p_string
 239   * @return string
 240   */
 241  function string_url( $p_string ) {
 242      return rawurlencode( $p_string );
 243  }
 244  
 245  /**
 246   * validate the url as part of this site before continuing
 247   * @param string $p_url
 248   * @param bool $p_return_absolute
 249   * @return string
 250   */
 251  function string_sanitize_url( $p_url, $p_return_absolute = false ) {
 252      $t_url = strip_tags( urldecode( $p_url ) );
 253  
 254      $t_path = rtrim( config_get( 'path' ), '/' );
 255      $t_short_path = rtrim( config_get( 'short_path' ), '/' );
 256  
 257      $t_pattern = '(?:/*(?P<script>[^\?#]*))(?:\?(?P<query>[^#]*))?(?:#(?P<anchor>[^#]*))?';
 258  
 259      # Break the given URL into pieces for path, script, query, and anchor
 260      $t_type = 0;
 261      if ( preg_match( '@^(?P<path>' . preg_quote( $t_path, '@' ) . ')' . $t_pattern . '$@', $t_url, $t_matches ) ) {
 262          $t_type = 1;
 263      } else if ( preg_match( '@^(?P<path>' . preg_quote( $t_short_path, '@' ) . ')' . $t_pattern . '$@', $t_url, $t_matches ) ) {
 264          $t_type = 2;
 265      } else if ( preg_match( '@^(?P<path>)' . $t_pattern . '$@', $t_url, $t_matches ) ) {
 266          $t_type = 3;
 267      }
 268  
 269      # Check for URL's pointing to other domains
 270      if ( 0 == $t_type || empty( $t_matches['script'] ) ||
 271          3 == $t_type && preg_match( '@(?:[^:]*)?://@', $t_url ) > 0 ) {
 272  
 273          return ( $p_return_absolute ? $t_path . '/' : '' ) . 'index.php';
 274      }
 275  
 276      # Start extracting regex matches
 277      $t_script = $t_matches['script'];
 278      $t_script_path = $t_matches['path'];
 279  
 280      # Clean/encode query params
 281      $t_query = '';
 282      if ( isset( $t_matches['query'] ) ) {
 283          $t_pairs = array();
 284          parse_str( html_entity_decode( $t_matches['query'] ), $t_pairs );
 285  
 286          $t_clean_pairs = array();
 287          foreach( $t_pairs as $t_key => $t_value ) {
 288              if ( is_array( $t_value ) ) {
 289                  foreach( $t_value as $t_value_each ) {
 290                      $t_clean_pairs[] .= rawurlencode( $t_key ) . '[]=' . rawurlencode( $t_value_each );
 291                  }
 292              } else {
 293                  $t_clean_pairs[] = rawurlencode( $t_key ) . '=' . rawurlencode( $t_value );
 294              }
 295          }
 296  
 297          if ( !empty( $t_clean_pairs ) ) {
 298              $t_query = '?' . join( '&', $t_clean_pairs );
 299          }
 300      }
 301  
 302      # encode link anchor
 303      $t_anchor = '';
 304      if ( isset( $t_matches['anchor'] ) ) {
 305          $t_anchor = '#' . rawurlencode( $t_matches['anchor'] );
 306      }
 307  
 308      # Return an appropriate re-combined URL string
 309      if ( $p_return_absolute ) {
 310          return $t_path . '/' . $t_script . $t_query . $t_anchor;
 311      } else {
 312          return ( !empty( $t_script_path ) ? $t_script_path . '/' : '' ) . $t_script . $t_query . $t_anchor;
 313      }
 314  }
 315  
 316  $string_process_bug_link_callback = array();
 317  
 318  /**
 319   * Process $p_string, looking for bug ID references and creating bug view
 320   * links for them.
 321   *
 322   * Returns the processed string.
 323   *
 324   * If $p_include_anchor is true, include the href tag, otherwise just insert
 325   * the URL
 326   *
 327   * The bug tag ('#' by default) must be at the beginning of the string or
 328   * preceeded by a character that is not a letter, a number or an underscore
 329   *
 330   * if $p_include_anchor = false, $p_fqdn is ignored and assumed to true.
 331   * @param string $p_string
 332   * @param bool $p_include_anchor
 333   * @param bool $p_detail_info
 334   * @param bool $p_fqdn
 335   * @return string
 336   */
 337  function string_process_bug_link( $p_string, $p_include_anchor = true, $p_detail_info = true, $p_fqdn = false ) {
 338      global $string_process_bug_link_callback;
 339  
 340      $t_tag = config_get( 'bug_link_tag' );
 341  
 342      # bail if the link tag is blank
 343      if( '' == $t_tag || $p_string == '' ) {
 344          return $p_string;
 345      }
 346  
 347      if( !isset( $string_process_bug_link_callback[$p_include_anchor][$p_detail_info][$p_fqdn] ) ) {
 348          if( $p_include_anchor ) {
 349              $string_process_bug_link_callback[$p_include_anchor][$p_detail_info][$p_fqdn] = create_function( '$p_array', '
 350                                          if ( bug_exists( (int)$p_array[2] ) && access_has_bug_level( VIEWER, (int)$p_array[2] ) ) {
 351                                              return $p_array[1] . string_get_bug_view_link( (int)$p_array[2], null, ' . ( $p_detail_info ? 'true' : 'false' ) . ', ' . ( $p_fqdn ? 'true' : 'false' ) . ');
 352                                          } else {
 353                                              return $p_array[0];
 354                                          }
 355                                          ' );
 356          } else {
 357              $string_process_bug_link_callback[$p_include_anchor][$p_detail_info][$p_fqdn] = create_function( '$p_array', '
 358                                          # We might as well create the link here even if the bug
 359                                          #  doesnt exist.  In the case above we dont want to do
 360                                          #  the summary lookup on a non-existant bug.  But here, we
 361                                          #  can create the link and by the time it is clicked on, the
 362                                          #  bug may exist.
 363                                          return $p_array[1] . string_get_bug_view_url_with_fqdn( (int)$p_array[2], null );
 364                                          ' );
 365          }
 366      }
 367  
 368      $p_string = preg_replace_callback( '/(^|[^\w&])' . preg_quote( $t_tag, '/' ) . '(\d+)\b/', $string_process_bug_link_callback[$p_include_anchor][$p_detail_info][$p_fqdn], $p_string );
 369      return $p_string;
 370  }
 371  
 372  $string_process_bugnote_link_callback = array();
 373  
 374  /**
 375   * Process $p_string, looking for bugnote ID references and creating bug view
 376   * links for them.
 377   *
 378   * Returns the processed string.
 379   *
 380   * If $p_include_anchor is true, include the href tag, otherwise just insert
 381   * the URL
 382   *
 383   * The bugnote tag ('~' by default) must be at the beginning of the string or
 384   * preceeded by a character that is not a letter, a number or an underscore
 385   *
 386   * if $p_include_anchor = false, $p_fqdn is ignored and assumed to true.
 387   * @param string $p_string
 388   * @param bool $p_include_anchor
 389   * @param bool $p_detail_info
 390   * @param bool $p_fqdn
 391   * @return string
 392   */
 393  function string_process_bugnote_link( $p_string, $p_include_anchor = true, $p_detail_info = true, $p_fqdn = false ) {
 394      global $string_process_bugnote_link_callback;
 395      $t_tag = config_get( 'bugnote_link_tag' );
 396  
 397      # bail if the link tag is blank
 398      if( '' == $t_tag || $p_string == '' ) {
 399          return $p_string;
 400      }
 401  
 402      if( !isset( $string_process_bugnote_link_callback[$p_include_anchor][$p_detail_info][$p_fqdn] ) ) {
 403          if( $p_include_anchor ) {
 404              $string_process_bugnote_link_callback[$p_include_anchor][$p_detail_info][$p_fqdn] = create_function( '$p_array', '
 405                                          if ( bugnote_exists( (int)$p_array[2] ) ) {
 406                                              $t_bug_id = bugnote_get_field( (int)$p_array[2], \'bug_id\' );
 407                                              $g_project_override = bug_get_field( $t_bug_id, \'project_id\' );
 408                                              if ( bug_exists( $t_bug_id ) && ( access_compare_level( user_get_access_level( auth_get_current_user_id(), bug_get_field( $t_bug_id, \'project_id\' ) ), config_get( \'private_bugnote_threshold\' ) ) || ( bugnote_get_field( (int)$p_array[2], \'reporter_id\' ) == auth_get_current_user_id() ) || bugnote_get_field( (int)$p_array[2], \'view_state\' ) == VS_PUBLIC ) ) {
 409                                                  $g_project_override = null;
 410                                                  return $p_array[1] . string_get_bugnote_view_link( $t_bug_id, (int)$p_array[2], null, ' . ( $p_detail_info ? 'true' : 'false' ) . ', ' . ( $p_fqdn ? 'true' : 'false' ) . ' );
 411                                              } else {
 412                                                  $g_project_override = null;
 413                                                  return $p_array[0];
 414                                              }
 415                                          } else {
 416                                              return $p_array[0];
 417                                          }
 418                                          ' );
 419          } else {
 420              $string_process_bugnote_link_callback[$p_include_anchor][$p_detail_info][$p_fqdn] = create_function( '$p_array', '
 421                                          # We might as well create the link here even if the bug
 422                                          #  doesnt exist.  In the case above we dont want to do
 423                                          #  the summary lookup on a non-existant bug.  But here, we
 424                                          #  can create the link and by the time it is clicked on, the
 425                                          #  bug may exist.
 426                                          $t_bug_id = bugnote_get_field( (int)$p_array[2], \'bug_id\' );
 427                                          if ( bug_exists( $t_bug_id ) ) {
 428                                              return $p_array[1] . string_get_bugnote_view_url_with_fqdn( $t_bug_id, (int)$p_array[2], null );
 429                                          } else {
 430                                              return $p_array[0];
 431                                          }
 432                                          ' );
 433          }
 434      }
 435      $p_string = preg_replace_callback( '/(^|[^\w])' . preg_quote( $t_tag, '/' ) . '(\d+)\b/', $string_process_bugnote_link_callback[$p_include_anchor][$p_detail_info][$p_fqdn], $p_string );
 436      return $p_string;
 437  }
 438  
 439  /**
 440   * Detect URLs and email addresses in the string and replace them with href anchors
 441   * @param string $p_string
 442   * @return string
 443   */
 444  function string_insert_hrefs( $p_string ) {
 445      static $s_url_regex = null;
 446  
 447      if( !config_get( 'html_make_links' ) ) {
 448          return $p_string;
 449      }
 450  
 451      $t_change_quotes = false;
 452      if( ini_get_bool( 'magic_quotes_sybase' ) && function_exists( 'ini_set' ) ) {
 453          $t_change_quotes = true;
 454          ini_set( 'magic_quotes_sybase', false );
 455      }
 456  
 457      # Find any URL in a string and replace it by a clickable link
 458      if ( is_null( $s_url_regex ) ) {
 459          # %2A notation in url's
 460          $t_url_hex = '%[[:digit:]A-Fa-f]{2}';
 461  
 462          # valid set of characters that may occur in url scheme. Note: - should be first (A-F != -AF).
 463          $t_url_valid_chars = '-_.,!~*\';\/?%^\\\\:@&={\|}+$#[:alnum:]\pL';
 464  
 465          $t_url_chars = "(?:$t_url_hex}|[$t_url_valid_chars}\(\)\[\]])";
 466          $t_url_chars2 = "(?:$t_url_hex}|[$t_url_valid_chars}])";
 467          $t_url_chars_in_brackets = "(?:$t_url_hex}|[$t_url_valid_chars}\(\)])";
 468          $t_url_chars_in_parens    = "(?:$t_url_hex}|[$t_url_valid_chars}\[\]])";
 469  
 470          $t_url_part1 = "$t_url_chars}";
 471          $t_url_part2 = "(?:\($t_url_chars_in_parens}*\)|\[$t_url_chars_in_brackets}*\]|$t_url_chars2})";
 472  
 473          $s_url_regex = "/(([[:alpha:]][-+.[:alnum:]]*):\/\/($t_url_part1}*?$t_url_part2}+))/sue";
 474      }
 475  
 476      $p_string = preg_replace( $s_url_regex, "'<a href=\"'.rtrim('\\1','.').'\">\\1</a>'", $p_string );
 477      if( $t_change_quotes ) {
 478          ini_set( 'magic_quotes_sybase', true );
 479      }
 480  
 481      $p_string = preg_replace( email_regex_simple(), '<a href="mailto:\0">\0</a>', $p_string );
 482  
 483      return $p_string;
 484  }
 485  
 486  /**
 487   * Detect href anchors in the string and replace them with URLs and email addresses
 488   * @param string $p_string
 489   * @return string
 490   */
 491  function string_strip_hrefs( $p_string ) {
 492      # First grab mailto: hrefs.  We don't care whether the URL is actually
 493      # correct - just that it's inside an href attribute.
 494      $p_string = preg_replace( '/<a\s[^\>]*href="mailto:([^\"]+)"[^\>]*>[^\<]*<\/a>/si', '\1', $p_string );
 495  
 496      # Then grab any other href
 497      $p_string = preg_replace( '/<a\s[^\>]*href="([^\"]+)"[^\>]*>[^\<]*<\/a>/si', '\1', $p_string );
 498      return $p_string;
 499  }
 500  
 501  /**
 502   * This function looks for text with htmlentities
 503   * like &lt;b&gt; and converts is into corresponding
 504   * html < b > tag based on the configuration presets
 505   * @param string $p_string
 506   * @param bool $p_multiline
 507   * @return string
 508   */
 509  function string_restore_valid_html_tags( $p_string, $p_multiline = true ) {
 510      global $g_cache_html_valid_tags_single_line, $g_cache_html_valid_tags;
 511      $tags = '';
 512      if( is_blank(( $p_multiline ? $g_cache_html_valid_tags : $g_cache_html_valid_tags_single_line ) ) ) {
 513          $t_html_valid_tags = config_get( $p_multiline ? 'html_valid_tags' : 'html_valid_tags_single_line' );
 514  
 515          if( OFF === $t_html_valid_tags || is_blank( $t_html_valid_tags ) ) {
 516              return $p_string;
 517          }
 518  
 519          $tags = explode( ',', $t_html_valid_tags );
 520          foreach( $tags as $key => $value ) {
 521              if( !is_blank( $value ) ) {
 522                  $tags[$key] = trim( $value );
 523              }
 524          }
 525          $tags = implode( '|', $tags );
 526          if( $p_multiline ) {
 527              $g_cache_html_valid_tags = $tags;
 528          } else {
 529              $g_cache_html_valid_tags_single_line = $tags;
 530          }
 531      } else {
 532          $tags = ( $p_multiline ? $g_cache_html_valid_tags : $g_cache_html_valid_tags_single_line );
 533      }
 534  
 535      $p_string = preg_replace( '/&lt;(' . $tags . ')\s*&gt;/ui', '<\\1>', $p_string );
 536      $p_string = preg_replace( '/&lt;\/(' . $tags . ')\s*&gt;/ui', '</\\1>', $p_string );
 537      $p_string = preg_replace( '/&lt;(' . $tags . ')\s*\/&gt;/ui', '<\\1 />', $p_string );
 538  
 539      return $p_string;
 540  }
 541  
 542  /**
 543   * return the name of a bug page for the user
 544   * account for the user preference and site override
 545   * $p_action should be something like 'view', 'update', or 'report'
 546   * If $p_user_id is null or not specified, use the current user * @param string $p_action
 547   * @param string $p_action
 548   * @param int $p_user_id
 549   * @return string
 550   */
 551  function string_get_bug_page( $p_action, $p_user_id = null ) {
 552      if ( $p_action == 'view' ) {
 553          return 'bug_view_page.php';
 554      }
 555  
 556      if ( $p_action == 'update' ) {
 557          return 'bug_update_page.php';
 558      }
 559  
 560      if ( $p_action == 'report' ) {
 561          return 'bug_report_page.php';
 562      }
 563  
 564      trigger_error( ERROR_GENERIC, ERROR );
 565  }
 566  
 567  /**
 568   * return an href anchor that links to a bug VIEW page for the given bug
 569   * account for the user preference and site override
 570   * @param int $p_bug_id
 571   * @param int $p_user_id
 572   * @param bool $p_detail_info
 573   * @param bool $p_fqdn
 574   * @return string
 575   */
 576  function string_get_bug_view_link( $p_bug_id, $p_user_id = null, $p_detail_info = true, $p_fqdn = false ) {
 577      if( bug_exists( $p_bug_id ) ) {
 578          $t_link = '<a href="';
 579          if( $p_fqdn ) {
 580              $t_link .= config_get_global( 'path' );
 581          } else {
 582              $t_link .= config_get_global( 'short_path' );
 583          }
 584          $t_link .= string_get_bug_view_url( $p_bug_id, $p_user_id ) . '"';
 585          if( $p_detail_info ) {
 586              $t_summary = string_attribute( bug_get_field( $p_bug_id, 'summary' ) );
 587              $t_project_id = bug_get_field( $p_bug_id, 'project_id' );
 588              $t_status = string_attribute( get_enum_element( 'status', bug_get_field( $p_bug_id, 'status' ), $t_project_id ) );
 589              $t_link .= ' title="[' . $t_status . '] ' . $t_summary . '"';
 590  
 591              $t_resolved = bug_get_field( $p_bug_id, 'status' ) >= config_get( 'bug_resolved_status_threshold', null, null, $t_project_id );
 592              if( $t_resolved ) {
 593                  $t_link .= ' class="resolved"';
 594              }
 595          }
 596          $t_link .= '>' . bug_format_id( $p_bug_id ) . '</a>';
 597      } else {
 598          $t_link = bug_format_id( $p_bug_id );
 599      }
 600  
 601      return $t_link;
 602  }
 603  
 604  /**
 605   * return an href anchor that links to a bug VIEW page for the given bug
 606   * account for the user preference and site override
 607   * @param int $p_bug_id
 608   * @param int $p_bugnote_id
 609   * @param int $p_user_id
 610   * @param bool $p_detail_info
 611   * @param bool $p_fqdn
 612   * @return string
 613   */
 614  function string_get_bugnote_view_link( $p_bug_id, $p_bugnote_id, $p_user_id = null, $p_detail_info = true, $p_fqdn = false ) {
 615      $t_bug_id = (int)$p_bug_id;
 616  
 617      if( bug_exists( $t_bug_id ) && bugnote_exists( $p_bugnote_id ) ) {
 618          $t_link = '<a href="';
 619          if( $p_fqdn ) {
 620              $t_link .= config_get_global( 'path' );
 621          } else {
 622              $t_link .= config_get_global( 'short_path' );
 623          }
 624  
 625          $t_link .= string_get_bugnote_view_url( $p_bug_id, $p_bugnote_id, $p_user_id ) . '"';
 626          if( $p_detail_info ) {
 627              $t_reporter = string_attribute( user_get_name( bugnote_get_field( $p_bugnote_id, 'reporter_id' ) ) );
 628              $t_update_date = string_attribute( date( config_get( 'normal_date_format' ), ( bugnote_get_field( $p_bugnote_id, 'last_modified' ) ) ) );
 629              $t_link .= ' title="' . bug_format_id( $t_bug_id ) . ': [' . $t_update_date . '] ' . $t_reporter . '"';
 630          }
 631  
 632          $t_link .= '>' . bug_format_id( $t_bug_id ) . ':' . bugnote_format_id( $p_bugnote_id ) . '</a>';
 633      } else {
 634          $t_link = bugnote_format_id( $t_bug_id ) . ':' . bugnote_format_id( $p_bugnote_id );
 635      }
 636  
 637      return $t_link;
 638  }
 639  
 640  /**
 641   * return the name and GET parameters of a bug VIEW page for the given bug
 642   * @param int $p_bug_id
 643   * @return string
 644   */
 645  function string_get_bug_view_url( $p_bug_id ) {
 646      return 'view.php?id=' . $p_bug_id;
 647  }
 648  
 649  /**
 650   * return the name and GET parameters of a bug VIEW page for the given bug
 651   * @param int $p_bug_id
 652   * @param int $p_bugnote_id
 653   * @return string
 654   */
 655  function string_get_bugnote_view_url( $p_bug_id, $p_bugnote_id ) {
 656      return 'view.php?id=' . $p_bug_id . '#c' . $p_bugnote_id;
 657  }
 658  
 659  /**
 660   * return the name and GET parameters of a bug VIEW page for the given bug
 661   * account for the user preference and site override
 662   * The returned url includes the fully qualified domain, hence it is suitable to be included
 663   * in emails.
 664   * @param int $p_bug_id
 665   * @param int $p_bugnote_id
 666   * @param int $p_user_id
 667   * @return string
 668   */
 669  function string_get_bugnote_view_url_with_fqdn( $p_bug_id, $p_bugnote_id, $p_user_id = null ) {
 670      return config_get( 'path' ) . string_get_bug_view_url( $p_bug_id, $p_user_id ) . '#c' . $p_bugnote_id;
 671  }
 672  
 673  /**
 674   * return the name and GET parameters of a bug VIEW page for the given bug
 675   * account for the user preference and site override
 676   * The returned url includes the fully qualified domain, hence it is suitable to be included in emails.
 677   * @param int $p_bug_id
 678   * @param int $p_user_id
 679   * @return string
 680   */
 681  function string_get_bug_view_url_with_fqdn( $p_bug_id, $p_user_id = null ) {
 682      return config_get( 'path' ) . string_get_bug_view_url( $p_bug_id, $p_user_id );
 683  }
 684  
 685  /**
 686   * return the name of a bug VIEW page for the user
 687   * account for the user preference and site override
 688   * @param int $p_user_id
 689   * @return string
 690   */
 691  function string_get_bug_view_page( $p_user_id = null ) {
 692      return string_get_bug_page( 'view', $p_user_id );
 693  }
 694  
 695  /**
 696   * return an href anchor that links to a bug UPDATE page for the given bug
 697   * account for the user preference and site override
 698   * @param int $p_bug_id
 699   * @param int $p_user_id
 700   * @return string
 701   */
 702  function string_get_bug_update_link( $p_bug_id, $p_user_id = null ) {
 703      $t_summary = string_attribute( bug_get_field( $p_bug_id, 'summary' ) );
 704      return '<a href="' . helper_mantis_url( string_get_bug_update_url( $p_bug_id, $p_user_id ) ) . '" title="' . $t_summary . '">' . bug_format_id( $p_bug_id ) . '</a>';
 705  }
 706  
 707  /**
 708   * return the name and GET parameters of a bug UPDATE page for the given bug
 709   * account for the user preference and site override
 710   * @param int $p_bug_id
 711   * @param int $p_user_id
 712   * @return string
 713   */
 714  function string_get_bug_update_url( $p_bug_id, $p_user_id = null ) {
 715      return string_get_bug_update_page( $p_user_id ) . '?bug_id=' . $p_bug_id;
 716  }
 717  
 718  /**
 719   * return the name of a bug UPDATE page for the user
 720   * account for the user preference and site override
 721   * @param int $p_user_id
 722   * @return string
 723   */
 724  function string_get_bug_update_page( $p_user_id = null ) {
 725      return string_get_bug_page( 'update', $p_user_id );
 726  }
 727  
 728  /**
 729   * return an href anchor that links to a bug REPORT page for the given bug
 730   * account for the user preference and site override
 731   * @param int $p_user_id
 732   * @return string
 733   */
 734  function string_get_bug_report_link( $p_user_id = null ) {
 735      return '<a href="' . helper_mantis_url( string_get_bug_report_url( $p_user_id ) ) . '">' . lang_get( 'report_bug_link' ) . '</a>';
 736  }
 737  
 738  /**
 739   * return the name and GET parameters of a bug REPORT page for the given bug
 740   * account for the user preference and site override
 741   * @param int $p_user_id
 742   * @return string
 743   */
 744  function string_get_bug_report_url( $p_user_id = null ) {
 745      return string_get_bug_report_page( $p_user_id );
 746  }
 747  
 748  /**
 749   * return the name of a bug REPORT page for the user
 750   * account for the user preference and site override
 751   * @param int $p_user_id
 752   * @return string
 753   */
 754  function string_get_bug_report_page( $p_user_id = null ) {
 755      return string_get_bug_page( 'report', $p_user_id );
 756  }
 757  
 758  /**
 759   * return the complete url link to checkin using the confirm_hash
 760   * @param int $p_user_id
 761   * @param string $p_confirm_hash
 762   * @return string
 763   */
 764  function string_get_confirm_hash_url( $p_user_id, $p_confirm_hash ) {
 765      $t_path = config_get( 'path' );
 766      return $t_path . "verify.php?id=" . string_url( $p_user_id ) . "&confirm_hash=" . string_url( $p_confirm_hash );
 767  }
 768  
 769  /**
 770   * Format date for display
 771   * @param int $p_date
 772   * @return string
 773   */
 774  function string_format_complete_date( $p_date ) {
 775      return date( config_get( 'complete_date_format' ), $p_date );
 776  }
 777  
 778  /**
 779   * Shorten a string for display on a dropdown to prevent the page rendering too wide
 780   * ref issues #4630, #5072, #5131
 781   * @param string $p_string
 782   * @param int $p_max
 783   * @return string
 784   */
 785  function string_shorten( $p_string, $p_max = null ) {
 786      if( $p_max === null ) {
 787          $t_max = config_get( 'max_dropdown_length' );
 788      } else {
 789          $t_max = (int) $p_max;
 790      }
 791  
 792      if( ( $t_max > 0 ) && ( utf8_strlen( $p_string ) > $t_max ) ) {
 793          $t_pattern = '/([\s|.|,|\-|_|\/|\?]+)/';
 794          $t_bits = preg_split( $t_pattern, $p_string, -1, PREG_SPLIT_DELIM_CAPTURE );
 795  
 796          $t_string = '';
 797          $t_last = $t_bits[count( $t_bits ) - 1];
 798          $t_last_len = strlen( $t_last );
 799  
 800          if( count( $t_bits ) == 1 ) {
 801              $t_string .= utf8_substr( $t_last, 0, $t_max - 3 );
 802              $t_string .= '...';
 803          } else {
 804              foreach( $t_bits as $t_bit ) {
 805                  if(( utf8_strlen( $t_string ) + utf8_strlen( $t_bit ) + $t_last_len + 3 <= $t_max ) || ( strpos( $t_bit, '.,-/?' ) > 0 ) ) {
 806                      $t_string .= $t_bit;
 807                  } else {
 808                      break;
 809                  }
 810              }
 811              $t_string .= '...' . $t_last;
 812          }
 813          return $t_string;
 814      } else {
 815          return $p_string;
 816      }
 817  }
 818  
 819  /**
 820   * Normalize a string by removing leading, trailing and excessive internal spaces
 821   * note a space is used as the pattern instead of '\s' to make it work with UTF-8 strings
 822   * @param string $p_string
 823   * @return string
 824   */
 825  function string_normalize( $p_string ) {
 826      return preg_replace( '/ +/', ' ', trim( $p_string ) );
 827  }
 828  
 829  /**
 830   * remap a field name to a string name (for sort filter)
 831   * @param string $p_string
 832   * @return string
 833   */
 834  function string_get_field_name( $p_string ) {
 835      $t_map = array(
 836          'attachment_count' => 'attachments',
 837          'category_id' => 'category',
 838          'handler_id' => 'assigned_to',
 839          'id' => 'email_bug',
 840          'last_updated' => 'updated',
 841          'project_id' => 'email_project',
 842          'reporter_id' => 'reporter',
 843          'view_state' => 'view_status',
 844      );
 845  
 846      $t_string = $p_string;
 847      if( isset( $t_map[$p_string] ) ) {
 848          $t_string = $t_map[$p_string];
 849      }
 850      return lang_get_defaulted( $t_string );
 851  }
 852  
 853  /**
 854   * Calls htmlentities on the specified string, passing along
 855   * the current charset.
 856   * @param string $p_string
 857   * @return string
 858   */
 859  function string_html_entities( $p_string ) {
 860      return htmlentities( $p_string, ENT_COMPAT, 'utf-8' );
 861  }
 862  
 863  /**
 864   * Calls htmlspecialchars on the specified string, handling utf8
 865   * @param string $p_string
 866   * @return string
 867   */
 868  function string_html_specialchars( $p_string ) {
 869      # achumakov: @ added to avoid warning output in unsupported codepages
 870      # e.g. 8859-2, windows-1257, Korean, which are treated as 8859-1.
 871      # This is VERY important for Eastern European, Baltic and Korean languages
 872      return preg_replace( "/&amp;(#[0-9]+|[a-z]+);/i", "&$1;", @htmlspecialchars( $p_string, ENT_COMPAT, 'utf-8' ) );
 873  }
 874  
 875  /**
 876   * Prepares a string to be used as part of header().
 877   * @param string $p_string
 878   * @return string
 879   */
 880  function string_prepare_header( $p_string ) {
 881      $t_string= explode( "\n", $p_string, 2 );
 882      $t_string= explode( "\r", $t_string[0], 2 );
 883      return $t_string[0];
 884  }


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