[ Index ]

PHP Cross Reference of MantisBT

title

Body

[close]

/core/ -> filter_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   * Filter API
  19   *
  20   * @package CoreAPI
  21   * @subpackage FilterAPI
  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 collapse_api.php
  30   * @uses columns_api.php
  31   * @uses config_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 date_api.php
  37   * @uses error_api.php
  38   * @uses event_api.php
  39   * @uses filter_constants_inc.php
  40   * @uses gpc_api.php
  41   * @uses helper_api.php
  42   * @uses lang_api.php
  43   * @uses logging_api.php
  44   * @uses print_api.php
  45   * @uses profile_api.php
  46   * @uses project_api.php
  47   * @uses relationship_api.php
  48   * @uses string_api.php
  49   * @uses tag_api.php
  50   * @uses user_api.php
  51   * @uses utility_api.php
  52   * @uses version_api.php
  53   */
  54  
  55  require_api( 'access_api.php' );
  56  require_api( 'authentication_api.php' );
  57  require_api( 'bug_api.php' );
  58  require_api( 'collapse_api.php' );
  59  require_api( 'columns_api.php' );
  60  require_api( 'config_api.php' );
  61  require_api( 'constant_inc.php' );
  62  require_api( 'current_user_api.php' );
  63  require_api( 'custom_field_api.php' );
  64  require_api( 'database_api.php' );
  65  require_api( 'date_api.php' );
  66  require_api( 'error_api.php' );
  67  require_api( 'event_api.php' );
  68  require_api( 'filter_constants_inc.php' );
  69  require_api( 'gpc_api.php' );
  70  require_api( 'helper_api.php' );
  71  require_api( 'lang_api.php' );
  72  require_api( 'logging_api.php' );
  73  require_api( 'print_api.php' );
  74  require_api( 'profile_api.php' );
  75  require_api( 'project_api.php' );
  76  require_api( 'relationship_api.php' );
  77  require_api( 'string_api.php' );
  78  require_api( 'tag_api.php' );
  79  require_api( 'user_api.php' );
  80  require_api( 'utility_api.php' );
  81  require_api( 'version_api.php' );
  82  
  83  /**
  84   * Allow plugins to define a set of class-based filters, and register/load
  85   * them here to be used by the rest of filter_api.
  86   * @return array Mapping of field name to filter object
  87   */
  88  function filter_get_plugin_filters() {
  89      static $s_field_array = null;
  90  
  91      if ( is_null( $s_field_array ) ) {
  92          $s_field_array = array();
  93  
  94          $t_all_plugin_filters = event_signal( 'EVENT_FILTER_FIELDS' );
  95          foreach( $t_all_plugin_filters as $t_plugin => $t_plugin_filters ) {
  96              foreach( $t_plugin_filters as $t_callback => $t_plugin_filter_array ) {
  97                  if ( is_array( $t_plugin_filter_array ) ) {
  98                      foreach( $t_plugin_filter_array as $t_filter_class ) {
  99                          if ( class_exists( $t_filter_class ) && is_subclass_of( $t_filter_class, 'MantisFilter' ) ) {
 100                              $t_filter_object = new $t_filter_class();
 101                              $t_field_name = $t_plugin . '_' . $t_filter_object->field;
 102                              $s_field_array[ $t_field_name ] = $t_filter_object;
 103                          }
 104                      }
 105                  }
 106              }
 107          }
 108      }
 109  
 110      return $s_field_array;
 111  }
 112  
 113  /**
 114   *  Get a permalink for the current active filter.  The results of using these fields by other users
 115   *  can be inconsistent with the original results due to fields like "Myself", "Current Project",
 116   *  and due to access level.
 117   * @param array $p_custom_filter
 118   * @return string the search.php?xxxx or an empty string if no criteria applied.
 119   */
 120  function filter_get_url( $p_custom_filter ) {
 121      $t_query = array();
 122  
 123      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_PROJECT_ID] ) ) {
 124          $t_project_id = $p_custom_filter[FILTER_PROPERTY_PROJECT_ID];
 125  
 126          if( count( $t_project_id ) == 1 && $t_project_id[0] == META_FILTER_CURRENT ) {
 127              $t_project_id = array(
 128                  helper_get_current_project(),
 129              );
 130          }
 131  
 132          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_PROJECT_ID, $t_project_id );
 133      }
 134  
 135      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_SEARCH] ) ) {
 136          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_SEARCH, $p_custom_filter[FILTER_PROPERTY_SEARCH] );
 137      }
 138  
 139      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_CATEGORY_ID] ) ) {
 140          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_CATEGORY_ID, $p_custom_filter[FILTER_PROPERTY_CATEGORY_ID] );
 141      }
 142  
 143      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_REPORTER_ID] ) ) {
 144          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_REPORTER_ID, $p_custom_filter[FILTER_PROPERTY_REPORTER_ID] );
 145      }
 146  
 147      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_STATUS] ) ) {
 148          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_STATUS, $p_custom_filter[FILTER_PROPERTY_STATUS] );
 149      }
 150  
 151      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_MONITOR_USER_ID] ) ) {
 152          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_MONITOR_USER_ID, $p_custom_filter[FILTER_PROPERTY_MONITOR_USER_ID] );
 153      }
 154  
 155      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_HANDLER_ID] ) ) {
 156          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_HANDLER_ID, $p_custom_filter[FILTER_PROPERTY_HANDLER_ID] );
 157      }
 158  
 159      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_NOTE_USER_ID] ) ) {
 160          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_NOTE_USER_ID, $p_custom_filter[FILTER_PROPERTY_NOTE_USER_ID] );
 161      }
 162  
 163      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_SEVERITY] ) ) {
 164          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_SEVERITY, $p_custom_filter[FILTER_PROPERTY_SEVERITY] );
 165      }
 166  
 167      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_RESOLUTION] ) ) {
 168          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_RESOLUTION, $p_custom_filter[FILTER_PROPERTY_RESOLUTION] );
 169      }
 170  
 171      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_PRIORITY] ) ) {
 172          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_PRIORITY, $p_custom_filter[FILTER_PROPERTY_PRIORITY] );
 173      }
 174  
 175      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_VIEW_STATE] ) ) {
 176          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_VIEW_STATE, $p_custom_filter[FILTER_PROPERTY_VIEW_STATE] );
 177      }
 178  
 179      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_STICKY] ) ) {
 180          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_STICKY, $p_custom_filter[FILTER_PROPERTY_STICKY] );
 181      }
 182  
 183      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_VERSION] ) ) {
 184          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_VERSION, $p_custom_filter[FILTER_PROPERTY_VERSION] );
 185      }
 186  
 187      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_BUILD] ) ) {
 188          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_BUILD, $p_custom_filter[FILTER_PROPERTY_BUILD] );
 189      }
 190  
 191      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_FIXED_IN_VERSION] ) ) {
 192          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_FIXED_IN_VERSION, $p_custom_filter[FILTER_PROPERTY_FIXED_IN_VERSION] );
 193      }
 194  
 195      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_TARGET_VERSION] ) ) {
 196          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_TARGET_VERSION, $p_custom_filter[FILTER_PROPERTY_TARGET_VERSION] );
 197      }
 198  
 199      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_SORT_FIELD_NAME] ) ) {
 200          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_SORT_FIELD_NAME, $p_custom_filter[FILTER_PROPERTY_SORT_FIELD_NAME] );
 201      }
 202  
 203      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_SORT_DIRECTION] ) ) {
 204          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_SORT_DIRECTION, $p_custom_filter[FILTER_PROPERTY_SORT_DIRECTION] );
 205      }
 206  
 207      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_ISSUES_PER_PAGE] ) ) {
 208          if( $p_custom_filter[FILTER_PROPERTY_ISSUES_PER_PAGE] != config_get( 'default_limit_view' ) ) {
 209              $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_ISSUES_PER_PAGE, $p_custom_filter[FILTER_PROPERTY_ISSUES_PER_PAGE] );
 210          }
 211      }
 212  
 213      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED] ) ) {
 214          if( $p_custom_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED] != config_get( 'default_show_changed' ) ) {
 215              $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_HIGHLIGHT_CHANGED, $p_custom_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED] );
 216          }
 217      }
 218  
 219      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_HIDE_STATUS] ) ) {
 220          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_HIDE_STATUS, $p_custom_filter[FILTER_PROPERTY_HIDE_STATUS] );
 221      }
 222  
 223      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_FILTER_BY_DATE] ) ) {
 224          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_FILTER_BY_DATE, $p_custom_filter[FILTER_PROPERTY_FILTER_BY_DATE] );
 225  
 226          # The start and end dates are only applicable if filter by date is set.
 227          if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_START_DAY] ) ) {
 228              $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_START_DAY, $p_custom_filter[FILTER_PROPERTY_START_DAY] );
 229          }
 230  
 231          if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_END_DAY] ) ) {
 232              $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_END_DAY, $p_custom_filter[FILTER_PROPERTY_END_DAY] );
 233          }
 234  
 235          if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_START_MONTH] ) ) {
 236              $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_START_MONTH, $p_custom_filter[FILTER_PROPERTY_START_MONTH] );
 237          }
 238  
 239          if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_END_MONTH] ) ) {
 240              $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_END_MONTH, $p_custom_filter[FILTER_PROPERTY_END_MONTH] );
 241          }
 242  
 243          if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_START_YEAR] ) ) {
 244              $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_START_YEAR, $p_custom_filter[FILTER_PROPERTY_START_YEAR] );
 245          }
 246  
 247          if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_END_YEAR] ) ) {
 248              $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_END_YEAR, $p_custom_filter[FILTER_PROPERTY_END_YEAR] );
 249          }
 250      }
 251  
 252      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE] ) ) {
 253          if( $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE] != -1 ) {
 254              $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_RELATIONSHIP_TYPE, $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE] );
 255          }
 256      }
 257  
 258      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_BUG] ) ) {
 259          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_RELATIONSHIP_BUG, $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_BUG] );
 260      }
 261  
 262      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_PLATFORM] ) ) {
 263          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_PLATFORM, $p_custom_filter[FILTER_PROPERTY_PLATFORM] );
 264      }
 265  
 266      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_OS] ) ) {
 267          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_OS, $p_custom_filter[FILTER_PROPERTY_OS] );
 268      }
 269  
 270      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_OS_BUILD] ) ) {
 271          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_OS_BUILD, $p_custom_filter[FILTER_PROPERTY_OS_BUILD] );
 272      }
 273  
 274      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_TAG_STRING] ) ) {
 275          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_TAG_STRING, $p_custom_filter[FILTER_PROPERTY_TAG_STRING] );
 276      }
 277  
 278      if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_TAG_SELECT] ) ) {
 279          $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_TAG_SELECT, $p_custom_filter[FILTER_PROPERTY_TAG_SELECT] );
 280      }
 281  
 282      if( isset( $p_custom_filter['custom_fields'] ) ) {
 283          foreach( $p_custom_filter['custom_fields'] as $t_custom_field_id => $t_custom_field_values ) {
 284              if( !filter_field_is_any( $t_custom_field_values ) ) {
 285                  $t_query[] = filter_encode_field_and_value( 'custom_field_' . $t_custom_field_id, $t_custom_field_values );
 286              }
 287          }
 288      }
 289  
 290      # Allow plugins to add filter fields
 291      $t_plugin_filter_array = filter_get_plugin_filters();
 292      foreach( $t_plugin_filter_array as $t_field_name => $t_filter_object ) {
 293          if( !filter_field_is_any( $p_custom_filter[ $t_field_name ] ) ) {
 294              $t_query[] = filter_encode_field_and_value( $t_field_name, $p_custom_filter[ $t_field_name ], $t_filter_object->type );
 295          }
 296      }
 297  
 298      if( count( $t_query ) > 0 ) {
 299          $t_query_str = implode( $t_query, '&' );
 300          $t_url = config_get( 'path' ) . 'search.php?' . $t_query_str;
 301      } else {
 302          $t_url = '';
 303      }
 304  
 305      return $t_url;
 306  }
 307  
 308  /**
 309   *  Encodes a field and it's value for the filter URL.  This handles the URL encoding
 310   *  and arrays.
 311   * @param string $p_field_name The field name.
 312   * @param string $p_field_value The field value (can be an array)
 313   * @return string url encoded string
 314   */
 315  function filter_encode_field_and_value( $p_field_name, $p_field_value, $p_field_type=null ) {
 316      $t_query_array = array();
 317      if( is_array( $p_field_value ) ) {
 318          $t_count = count( $p_field_value );
 319          if( $t_count > 1 || $p_field_type == FILTER_TYPE_MULTI_STRING || $p_field_type == FILTER_TYPE_MULTI_INT ) {
 320              foreach( $p_field_value as $t_value ) {
 321                  $t_query_array[] = urlencode( $p_field_name . '[]' ) . '=' . urlencode( $t_value );
 322              }
 323          }
 324          else if( $t_count == 1 ) {
 325              $t_query_array[] = urlencode( $p_field_name ) . '=' . urlencode( $p_field_value[0] );
 326          }
 327      } else {
 328          $t_query_array[] = urlencode( $p_field_name ) . '=' . urlencode( $p_field_value );
 329      }
 330  
 331      return implode( $t_query_array, '&' );
 332  }
 333  
 334  # ==========================================================================
 335  # GENERAL FUNCTIONS                                                          =
 336  # ==========================================================================
 337  /**
 338   *  Checks the supplied value to see if it is an ANY value.
 339   * @param string $p_field_value - The value to check.
 340   * @return bool true for "ANY" values and false for others.  "ANY" means filter criteria not active.
 341   */
 342  function filter_field_is_any( $p_field_value ) {
 343      if( is_array( $p_field_value ) ) {
 344          if( count( $p_field_value ) == 0 ) {
 345              return true;
 346          }
 347  
 348          foreach( $p_field_value as $t_value ) {
 349              if(( META_FILTER_ANY == $t_value ) && ( is_numeric( $t_value ) ) ) {
 350                  return true;
 351              }
 352          }
 353      } else {
 354          if( is_string( $p_field_value ) && is_blank( $p_field_value ) ) {
 355              return true;
 356          }
 357  
 358          if( is_bool( $p_field_value ) && !$p_field_value ) {
 359              return true;
 360          }
 361  
 362          if(( META_FILTER_ANY == $p_field_value ) && ( is_numeric( $p_field_value ) ) ) {
 363              return true;
 364          }
 365      }
 366  
 367      return false;
 368  }
 369  
 370  /**
 371       *  Checks the supplied value to see if it is a NONE value.
 372       * @param string $p_field_value - The value to check.
 373       * @return bool true for "NONE" values and false for others.
 374   * @todo is a check for these necessary?  if ( ( $t_filter_value === 'none' ) || ( $t_filter_value === '[none]' ) )
 375       */
 376  function filter_field_is_none( $p_field_value ) {
 377      if( is_array( $p_field_value ) ) {
 378          foreach( $p_field_value as $t_value ) {
 379              if(( META_FILTER_NONE == $t_value ) && ( is_numeric( $t_value ) ) ) {
 380                  return true;
 381              }
 382          }
 383      } else {
 384          if( is_string( $p_field_value ) && is_blank( $p_field_value ) ) {
 385              return false;
 386          }
 387  
 388          if(( META_FILTER_NONE == $p_field_value ) && ( is_numeric( $p_field_value ) ) ) {
 389              return true;
 390          }
 391      }
 392  
 393      return false;
 394  }
 395  
 396  /**
 397   *  Checks the supplied value to see if it is a MYSELF value.
 398   * @param string $p_field_value - The value to check.
 399   * @return bool true for "MYSELF" values and false for others.
 400   */
 401  function filter_field_is_myself( $p_field_value ) {
 402      return( META_FILTER_MYSELF == $p_field_value ? TRUE : FALSE );
 403  }
 404  
 405  /**
 406       * @param $p_count
 407       * @param $p_per_page
 408       * @return int
 409       */
 410  function filter_per_page( $p_filter, $p_count, $p_per_page ) {
 411      $p_per_page = (( NULL == $p_per_page ) ? (int) $p_filter[FILTER_PROPERTY_ISSUES_PER_PAGE] : $p_per_page );
 412      $p_per_page = (( 0 == $p_per_page || -1 == $p_per_page ) ? $p_count : $p_per_page );
 413  
 414      return (int) abs( $p_per_page );
 415  }
 416  
 417  /**
 418       *  Use $p_count and $p_per_page to determine how many pages to split this list up into.
 419       *  For the sake of consistency have at least one page, even if it is empty.
 420       * @param $p_count
 421       * @param $p_per_page
 422       * @return $t_page_count
 423       */
 424  function filter_page_count( $p_count, $p_per_page ) {
 425      $t_page_count = ceil( $p_count / $p_per_page );
 426      if( $t_page_count < 1 ) {
 427          $t_page_count = 1;
 428      }
 429      return $t_page_count;
 430  }
 431  
 432  /**
 433       *  Checks to make sure $p_page_number isn't past the last page.
 434       *  and that $p_page_number isn't before the first page
 435       *   @param $p_page_number
 436       *   @param $p_page_count
 437       */
 438  function filter_valid_page_number( $p_page_number, $p_page_count ) {
 439      if( $p_page_number > $p_page_count ) {
 440          $p_page_number = $p_page_count;
 441      }
 442  
 443      if( $p_page_number < 1 ) {
 444          $p_page_number = 1;
 445      }
 446      return $p_page_number;
 447  }
 448  
 449  /**
 450       *  Figure out the offset into the db query, offset is which record to start querying from
 451       * @param int $p_page_number
 452       * @param int $p_per_page
 453       * @return int
 454       */
 455  function filter_offset( $p_page_number, $p_per_page ) {
 456      return(( (int) $p_page_number -1 ) * (int) $p_per_page );
 457  }
 458  
 459  /**
 460   *  Make sure that our filters are entirely correct and complete (it is possible that they are not).
 461   *  We need to do this to cover cases where we don't have complete control over the filters given.s
 462   * @param array $p_filter_arr
 463   * @return mixed
 464   * @todo function needs to be abstracted
 465   */
 466  function filter_ensure_valid_filter( $p_filter_arr ) {
 467  
 468      # extend current filter to add information passed via POST
 469      if( !isset( $p_filter_arr['_version'] ) ) {
 470          $p_filter_arr['_version'] = config_get( 'cookie_version' );
 471      }
 472      $t_cookie_vers = (int) utf8_substr( $p_filter_arr['_version'], 1 );
 473      if( utf8_substr( config_get( 'cookie_version' ), 1 ) > $t_cookie_vers ) {
 474  
 475          # if the version is old, update it
 476          $p_filter_arr['_version'] = config_get( 'cookie_version' );
 477      }
 478      if( !isset( $p_filter_arr['_view_type'] ) ) {
 479          $p_filter_arr['_view_type'] = gpc_get_string( 'view_type', 'simple' );
 480      }
 481      if( !isset( $p_filter_arr[FILTER_PROPERTY_ISSUES_PER_PAGE] ) ) {
 482          $p_filter_arr[FILTER_PROPERTY_ISSUES_PER_PAGE] = gpc_get_int( FILTER_PROPERTY_ISSUES_PER_PAGE, config_get( 'default_limit_view' ) );
 483      }
 484      if( !isset( $p_filter_arr[FILTER_PROPERTY_HIGHLIGHT_CHANGED] ) ) {
 485          $p_filter_arr[FILTER_PROPERTY_HIGHLIGHT_CHANGED] = config_get( 'default_show_changed' );
 486      }
 487      if( !isset( $p_filter_arr[FILTER_PROPERTY_STICKY] ) ) {
 488          $p_filter_arr[FILTER_PROPERTY_STICKY] = gpc_string_to_bool( config_get( 'show_sticky_issues' ) );
 489      }
 490      if( !isset( $p_filter_arr[FILTER_PROPERTY_SORT_FIELD_NAME] ) ) {
 491          $p_filter_arr[FILTER_PROPERTY_SORT_FIELD_NAME] = "last_updated";
 492      }
 493      if( !isset( $p_filter_arr[FILTER_PROPERTY_SORT_DIRECTION] ) ) {
 494          $p_filter_arr[FILTER_PROPERTY_SORT_DIRECTION] = "DESC";
 495      }
 496  
 497      if( !isset( $p_filter_arr[FILTER_PROPERTY_PLATFORM] ) ) {
 498          $p_filter_arr[FILTER_PROPERTY_PLATFORM] = array(
 499              0 => META_FILTER_ANY,
 500          );
 501      }
 502  
 503      if( !isset( $p_filter_arr[FILTER_PROPERTY_OS] ) ) {
 504          $p_filter_arr[FILTER_PROPERTY_OS] = array(
 505              0 => META_FILTER_ANY,
 506          );
 507      }
 508  
 509      if( !isset( $p_filter_arr[FILTER_PROPERTY_OS_BUILD] ) ) {
 510          $p_filter_arr[FILTER_PROPERTY_OS_BUILD] = array(
 511              0 => META_FILTER_ANY,
 512          );
 513      }
 514  
 515      if( !isset( $p_filter_arr[FILTER_PROPERTY_PROJECT_ID] ) ) {
 516          $p_filter_arr[FILTER_PROPERTY_PROJECT_ID] = array(
 517              0 => META_FILTER_CURRENT,
 518          );
 519      }
 520  
 521      if( !isset( $p_filter_arr[FILTER_PROPERTY_START_MONTH] ) ) {
 522          $p_filter_arr[FILTER_PROPERTY_START_MONTH] = gpc_get_string( FILTER_PROPERTY_START_MONTH, date( 'm' ) );
 523      }
 524      if( !isset( $p_filter_arr[FILTER_PROPERTY_START_DAY] ) ) {
 525          $p_filter_arr[FILTER_PROPERTY_START_DAY] = gpc_get_string( FILTER_PROPERTY_START_DAY, 1 );
 526      }
 527      if( !isset( $p_filter_arr[FILTER_PROPERTY_START_YEAR] ) ) {
 528          $p_filter_arr[FILTER_PROPERTY_START_YEAR] = gpc_get_string( FILTER_PROPERTY_START_YEAR, date( 'Y' ) );
 529      }
 530      if( !isset( $p_filter_arr[FILTER_PROPERTY_END_MONTH] ) ) {
 531          $p_filter_arr[FILTER_PROPERTY_END_MONTH] = gpc_get_string( FILTER_PROPERTY_END_MONTH, date( 'm' ) );
 532      }
 533      if( !isset( $p_filter_arr[FILTER_PROPERTY_END_DAY] ) ) {
 534          $p_filter_arr[FILTER_PROPERTY_END_DAY] = gpc_get_string( FILTER_PROPERTY_END_DAY, date( 'd' ) );
 535      }
 536      if( !isset( $p_filter_arr[FILTER_PROPERTY_END_YEAR] ) ) {
 537          $p_filter_arr[FILTER_PROPERTY_END_YEAR] = gpc_get_string( FILTER_PROPERTY_END_YEAR, date( 'Y' ) );
 538      }
 539      if( !isset( $p_filter_arr[FILTER_PROPERTY_SEARCH] ) ) {
 540          $p_filter_arr[FILTER_PROPERTY_SEARCH] = '';
 541      }
 542      if( !isset( $p_filter_arr[FILTER_PROPERTY_FILTER_BY_DATE] ) ) {
 543          $p_filter_arr[FILTER_PROPERTY_FILTER_BY_DATE] = gpc_get_bool( FILTER_PROPERTY_FILTER_BY_DATE, false );
 544      }
 545      if( !isset( $p_filter_arr[FILTER_PROPERTY_VIEW_STATE] ) ) {
 546          $p_filter_arr[FILTER_PROPERTY_VIEW_STATE] = gpc_get( FILTER_PROPERTY_VIEW_STATE, '' );
 547      }
 548      else if( filter_field_is_any( $p_filter_arr[FILTER_PROPERTY_VIEW_STATE] ) ) {
 549          $p_filter_arr[FILTER_PROPERTY_VIEW_STATE] = META_FILTER_ANY;
 550      }
 551      if( !isset( $p_filter_arr[FILTER_PROPERTY_RELATIONSHIP_TYPE] ) ) {
 552          $p_filter_arr[FILTER_PROPERTY_RELATIONSHIP_TYPE] = gpc_get_int( FILTER_PROPERTY_RELATIONSHIP_TYPE, -1 );
 553      }
 554      if( !isset( $p_filter_arr[FILTER_PROPERTY_RELATIONSHIP_BUG] ) ) {
 555          $p_filter_arr[FILTER_PROPERTY_RELATIONSHIP_BUG] = gpc_get_int( FILTER_PROPERTY_RELATIONSHIP_BUG, 0 );
 556      }
 557      if( !isset( $p_filter_arr[FILTER_PROPERTY_TARGET_VERSION] ) ) {
 558          $p_filter_arr[FILTER_PROPERTY_TARGET_VERSION] = META_FILTER_ANY;
 559      }
 560      if( !isset( $p_filter_arr[FILTER_PROPERTY_TAG_STRING] ) ) {
 561          $p_filter_arr[FILTER_PROPERTY_TAG_STRING] = gpc_get_string( FILTER_PROPERTY_TAG_STRING, '' );
 562      }
 563      if( !isset( $p_filter_arr[FILTER_PROPERTY_TAG_SELECT] ) ) {
 564          $p_filter_arr[FILTER_PROPERTY_TAG_SELECT] = gpc_get_string( FILTER_PROPERTY_TAG_SELECT, '' );
 565      }
 566  
 567      # initialize plugin filters
 568      $t_plugin_filters = filter_get_plugin_filters();
 569      foreach( $t_plugin_filters as $t_field_name => $t_filter_object ) {
 570          if( !isset( $p_filter_arr[ $t_field_name ] ) ) {
 571              switch( $t_filter_object->type ) {
 572                  case FILTER_TYPE_STRING:
 573                      $p_filter_arr[ $t_field_name ] = gpc_get_string( $t_field_name, $t_filter_object->default );
 574                      break;
 575  
 576                  case FILTER_TYPE_INT:
 577                      $p_filter_arr[ $t_field_name ] = gpc_get_int( $t_field_name, (int)$t_filter_object->default );
 578                      break;
 579  
 580                  case FILTER_TYPE_BOOLEAN:
 581                      $p_filter_arr[ $t_field_name ] = gpc_get_bool( $t_field_name, (bool)$t_filter_object->default );
 582                      break;
 583  
 584                  case FILTER_TYPE_MULTI_STRING:
 585                      $p_filter_arr[ $t_field_name ] = gpc_get_string_array( $t_field_name, array( 0 => META_FILTER_ANY ) );
 586                      break;
 587  
 588                  case FILTER_TYPE_MULTI_INT:
 589                      $p_filter_arr[ $t_field_name ] = gpc_get_int_array( $t_field_name, array( 0 => META_FILTER_ANY ) );
 590                      break;
 591  
 592                  default:
 593                      $p_filter_arr[ $t_field_name ] = META_FILTER_ANY;
 594              }
 595          }
 596  
 597          if ( ! $t_filter_object->validate( $p_filter_arr[ $t_field_name ] ) ) {
 598              $p_filter_arr[ $t_field_name ] = $t_filter_object->default;
 599          }
 600      }
 601  
 602      $t_custom_fields = custom_field_get_ids();
 603  
 604      # @@@ (thraxisp) This should really be the linked ids, but we don't know the project
 605      $f_custom_fields_data = array();
 606      if( is_array( $t_custom_fields ) && ( count( $t_custom_fields ) > 0 ) ) {
 607          foreach( $t_custom_fields as $t_cfid ) {
 608              if( is_array( gpc_get( 'custom_field_' . $t_cfid, null ) ) ) {
 609                  $f_custom_fields_data[$t_cfid] = gpc_get_string_array( 'custom_field_' . $t_cfid, META_FILTER_ANY );
 610              } else {
 611                  $f_custom_fields_data[$t_cfid] = gpc_get_string( 'custom_field_' . $t_cfid, META_FILTER_ANY );
 612                  $f_custom_fields_data[$t_cfid] = array(
 613                      $f_custom_fields_data[$t_cfid],
 614                  );
 615              }
 616          }
 617      }
 618  
 619      # validate sorting
 620      $t_fields = helper_get_columns_to_view();
 621      $t_n_fields = count( $t_fields );
 622      for( $i = 0;$i < $t_n_fields;$i++ ) {
 623          if( isset( $t_fields[$i] ) && in_array( $t_fields[$i], array( 'selection', 'edit', 'bugnotes_count', 'attachment' ) ) ) {
 624              unset( $t_fields[$i] );
 625          }
 626      }
 627      $t_sort_fields = explode( ',', $p_filter_arr['sort'] );
 628      $t_dir_fields = explode( ',', $p_filter_arr['dir'] );
 629      for( $i = 0;$i < 2;$i++ ) {
 630          if( isset( $t_sort_fields[$i] ) ) {
 631              $t_drop = false;
 632              $t_sort = $t_sort_fields[$i];
 633              if( strpos( $t_sort, 'custom_' ) === 0 ) {
 634                  if( false === custom_field_get_id_from_name( utf8_substr( $t_sort, utf8_strlen( 'custom_' ) ) ) ) {
 635                      $t_drop = true;
 636                  }
 637              } else {
 638                  if( !in_array( $t_sort, $t_fields ) ) {
 639                      $t_drop = true;
 640                  }
 641              }
 642              if( !in_array( $t_dir_fields[$i], array( "ASC", "DESC" ) ) ) {
 643                  $t_drop = true;
 644              }
 645              if( $t_drop ) {
 646                  unset( $t_sort_fields[$i] );
 647                  unset( $t_dir_fields[$i] );
 648              }
 649          }
 650      }
 651      if( count( $t_sort_fields ) > 0 ) {
 652          $p_filter_arr['sort'] = implode( ',', $t_sort_fields );
 653          $p_filter_arr['dir'] = implode( ',', $t_dir_fields );
 654      } else {
 655          $p_filter_arr['sort'] = "last_updated";
 656          $p_filter_arr['dir'] = "DESC";
 657      }
 658  
 659      # validate or filter junk from other fields
 660      $t_multi_select_list = array(
 661          FILTER_PROPERTY_CATEGORY_ID => 'string',
 662          FILTER_PROPERTY_SEVERITY => 'int',
 663          FILTER_PROPERTY_STATUS => 'int',
 664          FILTER_PROPERTY_REPORTER_ID => 'int',
 665          FILTER_PROPERTY_HANDLER_ID => 'int',
 666          FILTER_PROPERTY_NOTE_USER_ID => 'int',
 667          FILTER_PROPERTY_RESOLUTION => 'int',
 668          FILTER_PROPERTY_PRIORITY => 'int',
 669          FILTER_PROPERTY_BUILD => 'string',
 670          FILTER_PROPERTY_VERSION => 'string',
 671          FILTER_PROPERTY_HIDE_STATUS => 'int',
 672          FILTER_PROPERTY_FIXED_IN_VERSION => 'string',
 673          FILTER_PROPERTY_TARGET_VERSION => 'string',
 674          FILTER_PROPERTY_MONITOR_USER_ID => 'int',
 675          FILTER_PROPERTY_PROFILE_ID => 'int',
 676      );
 677      foreach( $t_multi_select_list as $t_multi_field_name => $t_multi_field_type ) {
 678          if( !isset( $p_filter_arr[$t_multi_field_name] ) ) {
 679              if( FILTER_PROPERTY_HIDE_STATUS == $t_multi_field_name ) {
 680                  $p_filter_arr[$t_multi_field_name] = array(
 681                      config_get( 'hide_status_default' ),
 682                  );
 683              }
 684              else if( 'custom_fields' == $t_multi_field_name ) {
 685                  $p_filter_arr[$t_multi_field_name] = array(
 686                      $f_custom_fields_data,
 687                  );
 688              } else {
 689                  $p_filter_arr[$t_multi_field_name] = array(
 690                      META_FILTER_ANY,
 691                  );
 692              }
 693          } else {
 694              if( !is_array( $p_filter_arr[$t_multi_field_name] ) ) {
 695                  $p_filter_arr[$t_multi_field_name] = array(
 696                      $p_filter_arr[$t_multi_field_name],
 697                  );
 698              }
 699              $t_checked_array = array();
 700              foreach( $p_filter_arr[$t_multi_field_name] as $t_filter_value ) {
 701                  $t_filter_value = stripslashes( $t_filter_value );
 702                  if(( $t_filter_value === 'any' ) || ( $t_filter_value === '[any]' ) ) {
 703                      $t_filter_value = META_FILTER_ANY;
 704                  }
 705                  if(( $t_filter_value === 'none' ) || ( $t_filter_value === '[none]' ) ) {
 706                      $t_filter_value = META_FILTER_NONE;
 707                  }
 708                  if( 'string' == $t_multi_field_type ) {
 709                      $t_checked_array[] = db_prepare_string( $t_filter_value );
 710                  }
 711                  else if( 'int' == $t_multi_field_type ) {
 712                      $t_checked_array[] = db_prepare_int( $t_filter_value );
 713                  }
 714                  else if( 'array' == $t_multi_field_type ) {
 715                      $t_checked_array[] = $t_filter_value;
 716                  }
 717              }
 718              $p_filter_arr[$t_multi_field_name] = $t_checked_array;
 719          }
 720      }
 721  
 722      if( is_array( $t_custom_fields ) && ( count( $t_custom_fields ) > 0 ) ) {
 723          foreach( $t_custom_fields as $t_cfid ) {
 724              if( !isset( $p_filter_arr['custom_fields'][$t_cfid] ) ) {
 725                  $p_filter_arr['custom_fields'][$t_cfid] = array(
 726                      META_FILTER_ANY,
 727                  );
 728              } else {
 729                  if( !is_array( $p_filter_arr['custom_fields'][$t_cfid] ) ) {
 730                      $p_filter_arr['custom_fields'][$t_cfid] = array(
 731                          $p_filter_arr['custom_fields'][$t_cfid],
 732                      );
 733                  }
 734                  $t_checked_array = array();
 735                  foreach( $p_filter_arr['custom_fields'][$t_cfid] as $t_filter_value ) {
 736                      $t_filter_value = stripslashes( $t_filter_value );
 737                      if(( $t_filter_value === 'any' ) || ( $t_filter_value === '[any]' ) ) {
 738                          $t_filter_value = META_FILTER_ANY;
 739                      }
 740                      $t_checked_array[] = db_prepare_string( $t_filter_value );
 741                  }
 742                  $p_filter_arr['custom_fields'][$t_cfid] = $t_checked_array;
 743              }
 744          }
 745      }
 746  
 747      # all of our filter values are now guaranteed to be there, and correct.
 748      return $p_filter_arr;
 749  }
 750  
 751  /**
 752   *  Get the standard filter that is to be used when no filter was previously saved.
 753   *  When creating specific filters, this can be used as a basis for the filter, where
 754   *  specific entries can be overridden.
 755   * @return mixed
 756   */
 757  function filter_get_default() {
 758      $t_hide_status_default = config_get( 'hide_status_default' );
 759      $t_default_show_changed = config_get( 'default_show_changed' );
 760  
 761      $t_filter = array(
 762          FILTER_PROPERTY_CATEGORY_ID => Array(
 763              '0' => META_FILTER_ANY,
 764          ),
 765          FILTER_PROPERTY_SEVERITY => Array(
 766              '0' => META_FILTER_ANY,
 767          ),
 768          FILTER_PROPERTY_STATUS => Array(
 769              '0' => META_FILTER_ANY,
 770          ),
 771          FILTER_PROPERTY_HIGHLIGHT_CHANGED => $t_default_show_changed,
 772          FILTER_PROPERTY_REPORTER_ID => Array(
 773              '0' => META_FILTER_ANY,
 774          ),
 775          FILTER_PROPERTY_HANDLER_ID => Array(
 776              '0' => META_FILTER_ANY,
 777          ),
 778          FILTER_PROPERTY_PROJECT_ID => Array(
 779              '0' => META_FILTER_CURRENT,
 780          ),
 781          FILTER_PROPERTY_RESOLUTION => Array(
 782              '0' => META_FILTER_ANY,
 783          ),
 784          FILTER_PROPERTY_BUILD => Array(
 785              '0' => META_FILTER_ANY,
 786          ),
 787          FILTER_PROPERTY_VERSION => Array(
 788              '0' => META_FILTER_ANY,
 789          ),
 790          FILTER_PROPERTY_HIDE_STATUS => Array(
 791              '0' => $t_hide_status_default,
 792          ),
 793          FILTER_PROPERTY_MONITOR_USER_ID => Array(
 794              '0' => META_FILTER_ANY,
 795          ),
 796          FILTER_PROPERTY_SORT_FIELD_NAME => 'last_updated',
 797          FILTER_PROPERTY_SORT_DIRECTION => 'DESC',
 798          FILTER_PROPERTY_ISSUES_PER_PAGE => config_get( 'default_limit_view' ),
 799      );
 800  
 801      return filter_ensure_valid_filter( $t_filter );
 802  }
 803  
 804  /**
 805   *  Deserialize filter string
 806   * @param string $p_serialized_filter
 807   * @return mixed $t_filter array
 808   * @see filter_ensure_valid_filter
 809   */
 810  function filter_deserialize( $p_serialized_filter ) {
 811      if( is_blank( $p_serialized_filter ) ) {
 812          return false;
 813      }
 814  
 815      # check to see if new cookie is needed
 816      $t_setting_arr = explode( '#', $p_serialized_filter, 2 );
 817      if(( $t_setting_arr[0] == 'v1' ) || ( $t_setting_arr[0] == 'v2' ) || ( $t_setting_arr[0] == 'v3' ) || ( $t_setting_arr[0] == 'v4' ) ) {
 818  
 819          # these versions can't be salvaged, they are too old to update
 820          return false;
 821      }
 822  
 823      # We shouldn't need to do this anymore, as filters from v5 onwards should cope with changing
 824      # filter indices dynamically
 825      $t_filter_array = array();
 826      if( isset( $t_setting_arr[1] ) ) {
 827          $t_filter_array = unserialize( $t_setting_arr[1] );
 828      } else {
 829          return false;
 830      }
 831      if( $t_filter_array['_version'] != config_get( 'cookie_version' ) ) {
 832  
 833          # if the version is not new enough, update it using defaults
 834          return filter_ensure_valid_filter( $t_filter_array );
 835      }
 836  
 837      return $t_filter_array;
 838  }
 839  
 840  /**
 841   *  Check if the filter cookie exists and is of the correct version.
 842   * @return bool
 843   */
 844  function filter_is_cookie_valid() {
 845      $t_view_all_cookie_id = gpc_get_cookie( config_get( 'view_all_cookie' ), '' );
 846      $t_view_all_cookie = filter_db_get_filter( $t_view_all_cookie_id );
 847  
 848      # check to see if the cookie does not exist
 849      if( is_blank( $t_view_all_cookie ) ) {
 850          return false;
 851      }
 852  
 853      # check to see if new cookie is needed
 854      $t_setting_arr = explode( '#', $t_view_all_cookie, 2 );
 855      if(( $t_setting_arr[0] == 'v1' ) || ( $t_setting_arr[0] == 'v2' ) || ( $t_setting_arr[0] == 'v3' ) || ( $t_setting_arr[0] == 'v4' ) ) {
 856          return false;
 857      }
 858  
 859      # We shouldn't need to do this anymore, as filters from v5 onwards should cope with changing
 860      # filter indices dynamically
 861      $t_filter_cookie_arr = array();
 862      if( isset( $t_setting_arr[1] ) ) {
 863          $t_filter_cookie_arr = unserialize( $t_setting_arr[1] );
 864      } else {
 865          return false;
 866      }
 867      if( $t_filter_cookie_arr['_version'] != config_get( 'cookie_version' ) ) {
 868          return false;
 869      }
 870  
 871      return true;
 872  }
 873  
 874  /**
 875   *  Get the array fields specified by $p_filter_id
 876   *  using the cached row if it's available
 877   * @param int $p_filter_id
 878   * @return mixed a filter row
 879   */
 880  function filter_get_row( $p_filter_id ) {
 881      return filter_cache_row( $p_filter_id );
 882  }
 883  
 884  /**
 885   *  Get the value of the filter field specified by filter id and field name
 886   * @param int $p_filter_id
 887   * @param string $p_field_name
 888   * @return string
 889   */
 890  function filter_get_field( $p_filter_id, $p_field_name ) {
 891      $row = filter_get_row( $p_filter_id );
 892  
 893      if( isset( $row[$p_field_name] ) ) {
 894          return $row[$p_field_name];
 895      } else {
 896          error_parameters( $p_field_name );
 897          trigger_error( ERROR_DB_FIELD_NOT_FOUND, WARNING );
 898          return '';
 899      }
 900  }
 901  
 902  /**
 903   *  Add sort parameters to the query clauses
 904   * @param array $p_filter
 905   * @param bool $p_show_sticky
 906   * @param array $p_query_clauses
 907   * @return array $p_query_clauses
 908   */
 909  function filter_get_query_sort_data( &$p_filter, $p_show_sticky, $p_query_clauses ) {
 910      $t_bug_table = db_get_table( 'bug' );
 911      $t_custom_field_string_table = db_get_table( 'custom_field_string' );
 912  
 913      # if sort is blank then default the sort and direction.  This is to fix the
 914      # symptoms of #3953.  Note that even if the main problem is fixed, we may
 915      # have to keep this code for a while to handle filters saved with this blank field.
 916      if( is_blank( $p_filter[FILTER_PROPERTY_SORT_FIELD_NAME] ) ) {
 917          $p_filter[FILTER_PROPERTY_SORT_FIELD_NAME] = 'last_updated';
 918          $p_filter[FILTER_PROPERTY_SORT_DIRECTION] = 'DESC';
 919      }
 920  
 921      $p_query_clauses['order'] = array();
 922      $t_sort_fields = explode( ',', $p_filter[FILTER_PROPERTY_SORT_FIELD_NAME] );
 923      $t_dir_fields = explode( ',', $p_filter[FILTER_PROPERTY_SORT_DIRECTION] );
 924  
 925      $t_plugin_columns = columns_get_plugin_columns();
 926  
 927      if ( gpc_string_to_bool( $p_filter[FILTER_PROPERTY_STICKY] ) && ( NULL !== $p_show_sticky ) ) {
 928          $p_query_clauses['order'][] = "$t_bug_table.sticky DESC";
 929      }
 930  
 931      $t_count = count( $t_sort_fields );
 932      for( $i = 0;$i < $t_count;$i++ ) {
 933          $c_sort = db_prepare_string( $t_sort_fields[$i] );
 934          $c_dir = 'DESC' == $t_dir_fields[$i] ? 'DESC' : 'ASC';
 935  
 936          if( !in_array( $t_sort_fields[$i], array_slice( $t_sort_fields, $i + 1 ) ) ) {
 937  
 938              # if sorting by a custom field
 939              if( strpos( $c_sort, 'custom_' ) === 0 ) {
 940                  $t_custom_field = utf8_substr( $c_sort, utf8_strlen( 'custom_' ) );
 941                  $t_custom_field_id = custom_field_get_id_from_name( $t_custom_field );
 942                  $t_def = custom_field_get_definition( $t_custom_field_id );
 943                  $t_value_field = ( $t_def['type'] == CUSTOM_FIELD_TYPE_TEXTAREA ? 'text' : 'value' );
 944                  $c_cf_alias = str_replace( ' ', '_', $t_custom_field );
 945                  $t_cf_table_alias = $t_custom_field_string_table . '_' . $t_custom_field_id;
 946                  $t_cf_select = "$t_cf_table_alias.$t_value_field $c_cf_alias";
 947  
 948                  # check to be sure this field wasn't already added to the query.
 949                  if( !in_array( $t_cf_select, $p_query_clauses['select'] ) ) {
 950                      $p_query_clauses['select'][] = $t_cf_select;
 951                      $p_query_clauses['join'][] = "LEFT JOIN $t_custom_field_string_table $t_cf_table_alias ON $t_bug_table.id = $t_cf_table_alias.bug_id AND $t_cf_table_alias.field_id = $t_custom_field_id";
 952                  }
 953  
 954                  $p_query_clauses['order'][] = "$c_cf_alias $c_dir";
 955  
 956              # if sorting by plugin columns
 957              } else if ( isset( $t_plugin_columns[ $t_sort_fields[$i] ] ) ) {
 958                  $t_column_object = $t_plugin_columns[ $t_sort_fields[$i] ];
 959  
 960                  if ( $t_column_object->sortable ) {
 961                      $t_clauses = $t_column_object->sortquery( $c_dir );
 962  
 963                      if ( is_array( $t_clauses ) ) {
 964                          if ( isset( $t_clauses['join'] ) ) {
 965                              $p_query_clauses['join'][] = $t_clauses['join'];
 966                          }
 967                          if ( isset( $t_clauses['order'] ) ) {
 968                              $p_query_clauses['order'][] = $t_clauses['order'];
 969                          }
 970                      }
 971                  }
 972  
 973              # standard column
 974              } else {
 975                  if ( 'last_updated' == $c_sort ) {
 976                      $c_sort = "last_updated";
 977                  }
 978                  $p_query_clauses['order'][] = "$t_bug_table.$c_sort $c_dir";
 979              }
 980          }
 981      }
 982  
 983      # add basic sorting if necessary
 984      if( !in_array( 'last_updated', $t_sort_fields ) ) {
 985          $p_query_clauses['order'][] = "$t_bug_table.last_updated DESC";
 986      }
 987      if( !in_array( 'date_submitted', $t_sort_fields ) ) {
 988          $p_query_clauses['order'][] = "$t_bug_table.date_submitted DESC";
 989      }
 990  
 991      return $p_query_clauses;
 992  }
 993  
 994  /**
 995       *  Remove any duplicate values in certain elements of query_clauses
 996       *  Do not loop over query clauses as some keys may contain valid duplicate values.
 997       *  We basically want unique values for just the base query elements select, from, and join
 998       *  'where' and 'where_values' key should not have duplicates as that is handled earlier and applying
 999       *  array_unique here could cause problems with the query.
1000       * @param $p_query_clauses
1001       * @return $p_query_clauses
1002       */
1003  function filter_unique_query_clauses( $p_query_clauses ) {
1004      $p_query_clauses['select'] = array_unique( $p_query_clauses['select'] );
1005      $p_query_clauses['from'] = array_unique( $p_query_clauses['from'] );
1006      $p_query_clauses['join'] = array_unique( $p_query_clauses['join'] );
1007      return $p_query_clauses;
1008  }
1009  
1010  /**
1011       *  Build a query with the query clauses array, query for bug count and return the result
1012       * @param array $p_query_clauses
1013       * @return int
1014       */
1015  function filter_get_bug_count( $p_query_clauses ) {
1016      $t_bug_table = db_get_table( 'bug' );
1017      $p_query_clauses = filter_unique_query_clauses( $p_query_clauses );
1018      $t_select_string = "SELECT Count( DISTINCT $t_bug_table.id ) as idcnt ";
1019      $t_from_string = " FROM " . implode( ', ', $p_query_clauses['from'] );
1020      $t_join_string = (( count( $p_query_clauses['join'] ) > 0 ) ? implode( ' ', $p_query_clauses['join'] ) : '' );
1021      $t_where_string = (( count( $p_query_clauses['where'] ) > 0 ) ? 'WHERE ' . implode( ' AND ', $p_query_clauses['where'] ) : '' );
1022      $t_result = db_query_bound( "$t_select_string $t_from_string $t_join_string $t_where_string", $p_query_clauses['where_values'] );
1023      return db_result( $t_result );
1024  }
1025  
1026  /**
1027   * @todo Had to make all these parameters required because we can't use
1028   *  call-time pass by reference anymore.  I really preferred not having
1029   *  to pass all the params in if you didn't want to, but I wanted to get
1030   *  rid of the errors for now.  If we can think of a better way later
1031   *  (maybe return an object) that would be great.
1032   *
1033   * @param int $p_page_number the page you want to see (set to the actual page on return)
1034   * @param int $p_per_page the number of bugs to see per page (set to actual on return)
1035   *      -1   indicates you want to see all bugs
1036   *      null indicates you want to use the value specified in the filter
1037   * @param int $p_page_count you don't need to give a value here, the number of pages will be stored here on return
1038   * @param int $p_bug_count you don't need to give a value here, the number of bugs will be stored here on return
1039   * @param mixed $p_custom_filter Filter to use.
1040   * @param int $p_project_id project id to use in filtering.
1041   * @param int $p_user_id user id to use as current user when filtering.
1042   * @param bool $p_show_sticky get sticky issues only.
1043   */
1044  function filter_get_bug_rows( &$p_page_number, &$p_per_page, &$p_page_count, &$p_bug_count, $p_custom_filter = null, $p_project_id = null, $p_user_id = null, $p_show_sticky = null ) {
1045      log_event( LOG_FILTERING, 'START NEW FILTER QUERY' );
1046  
1047      $t_bug_table = db_get_table( 'bug' );
1048      $t_bug_text_table = db_get_table( 'bug_text' );
1049      $t_bugnote_table = db_get_table( 'bugnote' );
1050      $t_category_table = db_get_table( 'category' );
1051      $t_custom_field_string_table = db_get_table( 'custom_field_string' );
1052      $t_bugnote_text_table = db_get_table( 'bugnote_text' );
1053      $t_project_table = db_get_table( 'project' );
1054      $t_bug_monitor_table = db_get_table( 'bug_monitor' );
1055      $t_limit_reporters = config_get( 'limit_reporters' );
1056      $t_bug_relationship_table = db_get_table( 'bug_relationship' );
1057      $t_report_bug_threshold = config_get( 'report_bug_threshold' );
1058      $t_where_param_count = 0;
1059  
1060      $t_current_user_id = auth_get_current_user_id();
1061  
1062      if( null === $p_user_id ) {
1063          $t_user_id = $t_current_user_id;
1064      } else {
1065          $t_user_id = $p_user_id;
1066      }
1067  
1068      $c_user_id = db_prepare_int( $t_user_id );
1069  
1070      if( null === $p_project_id ) {
1071  
1072          # @@@ If project_id is not specified, then use the project id(s) in the filter if set, otherwise, use current project.
1073          $t_project_id = helper_get_current_project();
1074      } else {
1075          $t_project_id = $p_project_id;
1076      }
1077  
1078      if( $p_custom_filter === null ) {
1079  
1080          # Prefer current_user_get_bug_filter() over user_get_filter() when applicable since it supports
1081          # cookies set by previous version of the code.
1082          if( $t_user_id == $t_current_user_id ) {
1083              $t_filter = current_user_get_bug_filter();
1084          } else {
1085              $t_filter = user_get_bug_filter( $t_user_id, $t_project_id );
1086          }
1087      } else {
1088          $t_filter = $p_custom_filter;
1089      }
1090  
1091      $t_filter = filter_ensure_valid_filter( $t_filter );
1092  
1093      if( false === $t_filter ) {
1094          return false;
1095  
1096          # signify a need to create a cookie
1097          # @@@ error instead?
1098      }
1099  
1100      $t_view_type = $t_filter['_view_type'];
1101      $t_where_clauses = array(
1102          "$t_project_table.enabled = " . db_param(),
1103          "$t_project_table.id = $t_bug_table.project_id",
1104      );
1105      $t_where_params = array(
1106          1,
1107      );
1108      $t_select_clauses = array(
1109          "$t_bug_table.*",
1110          "$t_bug_table.last_updated",
1111          "$t_bug_table.date_submitted",
1112      );
1113  
1114      $t_join_clauses = array();
1115      $t_from_clauses = array();
1116  
1117      // normalize the project filtering into an array $t_project_ids
1118      if( 'simple' == $t_view_type ) {
1119          log_event( LOG_FILTERING, 'Simple Filter' );
1120          $t_project_ids = array(
1121              $t_project_id,
1122          );
1123          $t_include_sub_projects = true;
1124      } else {
1125          log_event( LOG_FILTERING, 'Advanced Filter' );
1126          if( !is_array( $t_filter[FILTER_PROPERTY_PROJECT_ID] ) ) {
1127              $t_project_ids = array(
1128                  db_prepare_int( $t_filter[FILTER_PROPERTY_PROJECT_ID] ),
1129              );
1130          } else {
1131              $t_project_ids = array_map( 'db_prepare_int', $t_filter[FILTER_PROPERTY_PROJECT_ID] );
1132          }
1133  
1134          $t_include_sub_projects = (( count( $t_project_ids ) == 1 ) && ( ( $t_project_ids[0] == META_FILTER_CURRENT ) || ( $t_project_ids[0] == ALL_PROJECTS ) ) );
1135      }
1136  
1137      log_event( LOG_FILTERING, 'project_ids = @P' . implode( ', @P', $t_project_ids ) );
1138      log_event( LOG_FILTERING, 'include sub-projects = ' . ( $t_include_sub_projects ? '1' : '0' ) );
1139  
1140      // if the array has ALL_PROJECTS, then reset the array to only contain ALL_PROJECTS.
1141      // replace META_FILTER_CURRENT with the actualy current project id.
1142      $t_all_projects_found = false;
1143      $t_new_project_ids = array();
1144      foreach( $t_project_ids as $t_pid ) {
1145          if( $t_pid == META_FILTER_CURRENT ) {
1146              $t_pid = $t_project_id;
1147          }
1148  
1149          if( $t_pid == ALL_PROJECTS ) {
1150              $t_all_projects_found = true;
1151              log_event( LOG_FILTERING, 'all projects selected' );
1152              break;
1153          }
1154  
1155          // filter out inaccessible projects.
1156          if( !access_has_project_level( VIEWER, $t_pid, $t_user_id ) ) {
1157              continue;
1158          }
1159  
1160          $t_new_project_ids[] = $t_pid;
1161      }
1162  
1163      $t_projects_query_required = true;
1164      if( $t_all_projects_found ) {
1165          if( user_is_administrator( $t_user_id ) ) {
1166              log_event( LOG_FILTERING, 'all projects + administrator, hence no project filter.' );
1167              $t_projects_query_required = false;
1168          } else {
1169              $t_project_ids = user_get_accessible_projects( $t_user_id );
1170          }
1171      } else {
1172          $t_project_ids = $t_new_project_ids;
1173      }
1174  
1175      if( $t_projects_query_required ) {
1176  
1177          // expand project ids to include sub-projects
1178          if( $t_include_sub_projects ) {
1179              $t_top_project_ids = $t_project_ids;
1180  
1181              foreach( $t_top_project_ids as $t_pid ) {
1182                  log_event( LOG_FILTERING, 'Getting sub-projects for project id @P' . $t_pid );
1183                  $t_project_ids = array_merge( $t_project_ids, user_get_all_accessible_subprojects( $t_user_id, $t_pid ) );
1184              }
1185  
1186              $t_project_ids = array_unique( $t_project_ids );
1187          }
1188  
1189          // if no projects are accessible, then return an empty array.
1190          if( count( $t_project_ids ) == 0 ) {
1191              log_event( LOG_FILTERING, 'no accessible projects' );
1192              return array();
1193          }
1194  
1195          log_event( LOG_FILTERING, 'project_ids after including sub-projects = @P' . implode( ', @P', $t_project_ids ) );
1196  
1197          // this array is to be populated with project ids for which we only want to show public issues.  This is due to the limited
1198          // access of the current user.
1199          $t_public_only_project_ids = array();
1200  
1201          // this array is populated with project ids that the current user has full access to.
1202          $t_private_and_public_project_ids = array();
1203  
1204          $t_access_required_to_view_private_bugs = config_get( 'private_bug_threshold' );
1205          foreach( $t_project_ids as $t_pid ) {
1206              if( access_has_project_level( $t_access_required_to_view_private_bugs, $t_pid, $t_user_id ) ) {
1207                  $t_private_and_public_project_ids[] = $t_pid;
1208              } else {
1209                  $t_public_only_project_ids[] = $t_pid;
1210              }
1211          }
1212  
1213          log_event( LOG_FILTERING, 'project_ids (with public/private access) = @P' . implode( ', @P', $t_private_and_public_project_ids ) );
1214          log_event( LOG_FILTERING, 'project_ids (with public access) = @P' . implode( ', @P', $t_public_only_project_ids ) );
1215  
1216          $t_count_private_and_public_project_ids = count( $t_private_and_public_project_ids );
1217          if( $t_count_private_and_public_project_ids == 1 ) {
1218              $t_private_and_public_query = "( $t_bug_table.project_id = " . $t_private_and_public_project_ids[0] . " )";
1219          }
1220          else if( $t_count_private_and_public_project_ids > 1 ) {
1221              $t_private_and_public_query = "( $t_bug_table.project_id in (" . implode( ', ', $t_private_and_public_project_ids ) . ") )";
1222          } else {
1223              $t_private_and_public_query = null;
1224          }
1225  
1226          $t_count_public_only_project_ids = count( $t_public_only_project_ids );
1227          $t_public_view_state_check = "( ( $t_bug_table.view_state = " . VS_PUBLIC . " ) OR ( $t_bug_table.reporter_id = $t_user_id ) )";
1228          if( $t_count_public_only_project_ids == 1 ) {
1229              $t_public_only_query = "( ( $t_bug_table.project_id = " . $t_public_only_project_ids[0] . " ) AND $t_public_view_state_check )";
1230          }
1231          else if( $t_count_public_only_project_ids > 1 ) {
1232              $t_public_only_query = "( ( $t_bug_table.project_id in (" . implode( ', ', $t_public_only_project_ids ) . ") ) AND $t_public_view_state_check )";
1233          } else {
1234              $t_public_only_query = null;
1235          }
1236  
1237          // both queries can't be null, so we either have one of them or both.
1238  
1239          if( $t_private_and_public_query === null ) {
1240              $t_project_query = $t_public_only_query;
1241          } else if( $t_public_only_query === null ) {
1242              $t_project_query = $t_private_and_public_query;
1243          } else {
1244              $t_project_query = "( $t_public_only_query OR $t_private_and_public_query )";
1245          }
1246  
1247          log_event( LOG_FILTERING, 'project query = ' . $t_project_query );
1248          array_push( $t_where_clauses, $t_project_query );
1249      }
1250  
1251      # view state
1252      $t_view_state = db_prepare_int( $t_filter[FILTER_PROPERTY_VIEW_STATE] );
1253      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_VIEW_STATE] ) ) {
1254          $t_view_state_query = "($t_bug_table.view_state=" . db_param() . ')';
1255          log_event( LOG_FILTERING, 'view_state query = ' . $t_view_state_query );
1256          $t_where_params[] = $t_view_state;
1257          array_push( $t_where_clauses, $t_view_state_query );
1258      } else {
1259          log_event( LOG_FILTERING, 'no view_state query' );
1260      }
1261  
1262      # reporter
1263      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_REPORTER_ID] ) ) {
1264          $t_clauses = array();
1265  
1266          foreach( $t_filter[FILTER_PROPERTY_REPORTER_ID] as $t_filter_member ) {
1267              if( filter_field_is_none( $t_filter_member ) ) {
1268                  array_push( $t_clauses, "0" );
1269              } else {
1270                  $c_reporter_id = db_prepare_int( $t_filter_member );
1271                  if( filter_field_is_myself( $c_reporter_id ) ) {
1272                      array_push( $t_clauses, $c_user_id );
1273                  } else {
1274                      array_push( $t_clauses, $c_reporter_id );
1275                  }
1276              }
1277          }
1278  
1279          if( 1 < count( $t_clauses ) ) {
1280              $t_reporter_query = "( $t_bug_table.reporter_id in (" . implode( ', ', $t_clauses ) . ") )";
1281          } else {
1282              $t_reporter_query = "( $t_bug_table.reporter_id=$t_clauses[0] )";
1283          }
1284  
1285          log_event( LOG_FILTERING, 'reporter query = ' . $t_reporter_query );
1286          array_push( $t_where_clauses, $t_reporter_query );
1287      } else {
1288          log_event( LOG_FILTERING, 'no reporter query' );
1289      }
1290  
1291      # limit reporter
1292      # @@@ thraxisp - access_has_project_level checks greater than or equal to,
1293      #   this assumed that there aren't any holes above REPORTER where the limit would apply
1294      #
1295      if(( ON === $t_limit_reporters ) && ( !access_has_project_level( REPORTER + 1, $t_project_id, $t_user_id ) ) ) {
1296          $c_reporter_id = $c_user_id;
1297          $t_where_params[] = $c_reporter_id;
1298          array_push( $t_where_clauses, "($t_bug_table.reporter_id=" . db_param() . ')' );
1299      }
1300  
1301      # handler
1302      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_HANDLER_ID] ) ) {
1303          $t_clauses = array();
1304  
1305          foreach( $t_filter[FILTER_PROPERTY_HANDLER_ID] as $t_filter_member ) {
1306              if( filter_field_is_none( $t_filter_member ) ) {
1307                  array_push( $t_clauses, 0 );
1308              } else {
1309                  $c_handler_id = db_prepare_int( $t_filter_member );
1310                  if( filter_field_is_myself( $c_handler_id ) ) {
1311                      array_push( $t_clauses, $c_user_id );
1312                  } else {
1313                      array_push( $t_clauses, $c_handler_id );
1314                  }
1315              }
1316          }
1317  
1318          if( 1 < count( $t_clauses ) ) {
1319              $t_handler_query = "( $t_bug_table.handler_id in (" . implode( ', ', $t_clauses ) . ") )";
1320          } else {
1321              $t_handler_query = "( $t_bug_table.handler_id=$t_clauses[0] )";
1322          }
1323  
1324          log_event( LOG_FILTERING, 'handler query = ' . $t_handler_query );
1325          array_push( $t_where_clauses, $t_handler_query );
1326      } else {
1327          log_event( LOG_FILTERING, 'no handler query' );
1328      }
1329  
1330      # category
1331      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_CATEGORY_ID] ) ) {
1332          $t_clauses = array();
1333  
1334          foreach( $t_filter[FILTER_PROPERTY_CATEGORY_ID] as $t_filter_member ) {
1335              if( !filter_field_is_none( $t_filter_member ) ) {
1336                  array_push( $t_clauses, $t_filter_member );
1337              }
1338          }
1339  
1340          if( 1 < count( $t_clauses ) ) {
1341              $t_where_tmp = array();
1342              foreach( $t_clauses as $t_clause ) {
1343                  $t_where_tmp[] = db_param();
1344                  $t_where_params[] = $t_clause;
1345              }
1346              array_push( $t_where_clauses, "( $t_bug_table.category_id in ( SELECT id FROM $t_category_table WHERE name in (" . implode( ', ', $t_where_tmp ) . ") ) )" );
1347          } else {
1348              $t_where_params[] = $t_clauses[0];
1349              array_push( $t_where_clauses, "( $t_bug_table.category_id in ( SELECT id FROM $t_category_table WHERE name=" . db_param() . ") )" );
1350          }
1351      }
1352  
1353      # severity
1354      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_SEVERITY] ) ) {
1355          $t_clauses = array();
1356  
1357          foreach( $t_filter[FILTER_PROPERTY_SEVERITY] as $t_filter_member ) {
1358              $c_show_severity = db_prepare_int( $t_filter_member );
1359              array_push( $t_clauses, $c_show_severity );
1360          }
1361          if( 1 < count( $t_clauses ) ) {
1362              $t_where_tmp = array();
1363              foreach( $t_clauses as $t_clause ) {
1364                  $t_where_tmp[] = db_param();
1365                  $t_where_params[] = $t_clause;
1366              }
1367              array_push( $t_where_clauses, "( $t_bug_table.severity in (" . implode( ', ', $t_where_tmp ) . ") )" );
1368          } else {
1369              $t_where_params[] = $t_clauses[0];
1370              array_push( $t_where_clauses, "( $t_bug_table.severity=" . db_param() . " )" );
1371          }
1372      }
1373  
1374      # show / hide status
1375      # take a list of all available statuses then remove the ones that we want hidden, then make sure
1376      # the ones we want shown are still available
1377      $t_desired_statuses = array();
1378      $t_available_statuses = MantisEnum::getValues( config_get( 'status_enum_string' ) );
1379  
1380      if( 'simple' == $t_filter['_view_type'] ) {
1381  
1382          # simple filtering: if showing any, restrict by the hide status value, otherwise ignore the hide
1383          $t_any_found = false;
1384          $t_this_status = $t_filter[FILTER_PROPERTY_STATUS][0];
1385          $t_this_hide_status = $t_filter[FILTER_PROPERTY_HIDE_STATUS][0];
1386  
1387          if( filter_field_is_any( $t_this_status ) ) {
1388              foreach( $t_available_statuses as $t_this_available_status ) {
1389                  if( $t_this_hide_status > $t_this_available_status ) {
1390                      $t_desired_statuses[] = $t_this_available_status;
1391                  }
1392              }
1393          } else {
1394              $t_desired_statuses[] = $t_this_status;
1395          }
1396      } else {
1397          # advanced filtering: ignore the hide
1398          if( filter_field_is_any( $t_filter[FILTER_PROPERTY_STATUS] ) ) {
1399              $t_desired_statuses = array();
1400          } else {
1401              foreach( $t_filter[FILTER_PROPERTY_STATUS] as $t_this_status ) {
1402                  $t_desired_statuses[] = $t_this_status;
1403              }
1404          }
1405      }
1406  
1407      if( count( $t_desired_statuses ) > 0 ) {
1408          $t_clauses = array();
1409  
1410          foreach( $t_desired_statuses as $t_filter_member ) {
1411              $c_show_status = db_prepare_int( $t_filter_member );
1412              array_push( $t_clauses, $c_show_status );
1413          }
1414          if( 1 < count( $t_clauses ) ) {
1415              $t_where_tmp = array();
1416              foreach( $t_clauses as $t_clause ) {
1417                  $t_where_tmp[] = db_param();
1418                  $t_where_params[] = $t_clause;
1419              }
1420              array_push( $t_where_clauses, "( $t_bug_table.status in (" . implode( ', ', $t_where_tmp ) . ") )" );
1421          } else {
1422              $t_where_params[] = $t_clauses[0];
1423              array_push( $t_where_clauses, "( $t_bug_table.status=" . db_param() . " )" );
1424          }
1425      }
1426  
1427      # resolution
1428      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_RESOLUTION] ) ) {
1429          $t_clauses = array();
1430  
1431          foreach( $t_filter[FILTER_PROPERTY_RESOLUTION] as $t_filter_member ) {
1432              $c_show_resolution = db_prepare_int( $t_filter_member );
1433              array_push( $t_clauses, $c_show_resolution );
1434          }
1435          if( 1 < count( $t_clauses ) ) {
1436              $t_where_tmp = array();
1437              foreach( $t_clauses as $t_clause ) {
1438                  $t_where_tmp[] = db_param();
1439                  $t_where_params[] = $t_clause;
1440              }
1441              array_push( $t_where_clauses, "( $t_bug_table.resolution in (" . implode( ', ', $t_where_tmp ) . ") )" );
1442          } else {
1443              $t_where_params[] = $t_clauses[0];
1444              array_push( $t_where_clauses, "( $t_bug_table.resolution=" . db_param() . " )" );
1445          }
1446      }
1447  
1448      # priority
1449      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_PRIORITY] ) ) {
1450          $t_clauses = array();
1451  
1452          foreach( $t_filter[FILTER_PROPERTY_PRIORITY] as $t_filter_member ) {
1453              $c_show_priority = db_prepare_int( $t_filter_member );
1454              array_push( $t_clauses, $c_show_priority );
1455          }
1456          if( 1 < count( $t_clauses ) ) {
1457              $t_where_tmp = array();
1458              foreach( $t_clauses as $t_clause ) {
1459                  $t_where_tmp[] = db_param();
1460                  $t_where_params[] = $t_clause;
1461              }
1462              array_push( $t_where_clauses, "( $t_bug_table.priority in (" . implode( ', ', $t_where_tmp ) . ") )" );
1463          } else {
1464              $t_where_params[] = $t_clauses[0];
1465              array_push( $t_where_clauses, "( $t_bug_table.priority=" . db_param() . " )" );
1466          }
1467      }
1468  
1469      # product build
1470      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_BUILD] ) ) {
1471          $t_clauses = array();
1472  
1473          foreach( $t_filter[FILTER_PROPERTY_BUILD] as $t_filter_member ) {
1474              $t_filter_member = stripslashes( $t_filter_member );
1475              if( filter_field_is_none( $t_filter_member ) ) {
1476                  array_push( $t_clauses, '' );
1477              } else {
1478                  $c_show_build = db_prepare_string( $t_filter_member );
1479                  array_push( $t_clauses, $c_show_build );
1480              }
1481          }
1482          if( 1 < count( $t_clauses ) ) {
1483              $t_where_tmp = array();
1484              foreach( $t_clauses as $t_clause ) {
1485                  $t_where_tmp[] = db_param();
1486                  $t_where_params[] = $t_clause;
1487              }
1488              array_push( $t_where_clauses, "( $t_bug_table.build in (" . implode( ', ', $t_where_tmp ) . ") )" );
1489          } else {
1490              $t_where_params[] = $t_clauses[0];
1491              array_push( $t_where_clauses, "( $t_bug_table.build=" . db_param() . " )" );
1492          }
1493      }
1494  
1495      # product version
1496      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_VERSION] ) ) {
1497          $t_clauses = array();
1498  
1499          foreach( $t_filter[FILTER_PROPERTY_VERSION] as $t_filter_member ) {
1500              $t_filter_member = stripslashes( $t_filter_member );
1501              if( filter_field_is_none( $t_filter_member ) ) {
1502                  array_push( $t_clauses, '' );
1503              } else {
1504                  $c_show_version = db_prepare_string( $t_filter_member );
1505                  array_push( $t_clauses, $c_show_version );
1506              }
1507          }
1508  
1509          if( 1 < count( $t_clauses ) ) {
1510              $t_where_tmp = array();
1511              foreach( $t_clauses as $t_clause ) {
1512                  $t_where_tmp[] = db_param();
1513                  $t_where_params[] = $t_clause;
1514              }
1515              array_push( $t_where_clauses, "( $t_bug_table.version in (" . implode( ', ', $t_where_tmp ) . ") )" );
1516          } else {
1517              $t_where_params[] = $t_clauses[0];
1518              array_push( $t_where_clauses, "( $t_bug_table.version=" . db_param() . " )" );
1519          }
1520      }
1521  
1522      # profile
1523      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_PROFILE_ID] ) ) {
1524          $t_clauses = array();
1525  
1526          foreach( $t_filter[FILTER_PROPERTY_PROFILE_ID] as $t_filter_member ) {
1527              $t_filter_member = stripslashes( $t_filter_member );
1528              if( filter_field_is_none( $t_filter_member ) ) {
1529                  array_push( $t_clauses, "0" );
1530              } else {
1531                  $c_show_profile = db_prepare_int( $t_filter_member );
1532                  array_push( $t_clauses, "$c_show_profile" );
1533              }
1534          }
1535          if( 1 < count( $t_clauses ) ) {
1536              $t_where_tmp = array();
1537              foreach( $t_clauses as $t_clause ) {
1538                  $t_where_tmp[] = db_param();
1539                  $t_where_params[] = $t_clause;
1540              }
1541              array_push( $t_where_clauses, "( $t_bug_table.profile_id in (" . implode( ', ', $t_where_tmp ) . ") )" );
1542          } else {
1543              $t_where_params[] = $t_clauses[0];
1544              array_push( $t_where_clauses, "( $t_bug_table.profile_id=" . db_param() . " )" );
1545          }
1546      }
1547  
1548      # platform
1549      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_PLATFORM] ) ) {
1550          $t_clauses = array();
1551  
1552          foreach( $t_filter[FILTER_PROPERTY_PLATFORM] as $t_filter_member ) {
1553              $t_filter_member = stripslashes( $t_filter_member );
1554              if( filter_field_is_none( $t_filter_member ) ) {
1555                  array_push( $t_clauses, '' );
1556              } else {
1557                  $c_platform = db_prepare_string( $t_filter_member );
1558                  array_push( $t_clauses, $c_platform );
1559              }
1560          }
1561  
1562          if( 1 < count( $t_clauses ) ) {
1563              $t_where_tmp = array();
1564              foreach( $t_clauses as $t_clause ) {
1565                  $t_where_tmp[] = db_param();
1566                  $t_where_params[] = $t_clause;
1567              }
1568              array_push( $t_where_clauses, "( $t_bug_table.platform in (" . implode( ', ', $t_where_tmp ) . ") )" );
1569          } else {
1570              $t_where_params[] = $t_clauses[0];
1571              array_push( $t_where_clauses, "( $t_bug_table.platform = " . db_param() . " )" );
1572          }
1573      }
1574  
1575      # os
1576      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_OS] ) ) {
1577          $t_clauses = array();
1578  
1579          foreach( $t_filter[FILTER_PROPERTY_OS] as $t_filter_member ) {
1580              $t_filter_member = stripslashes( $t_filter_member );
1581              if( filter_field_is_none( $t_filter_member ) ) {
1582                  array_push( $t_clauses, '' );
1583              } else {
1584                  $c_os = db_prepare_string( $t_filter_member );
1585                  array_push( $t_clauses, $c_os );
1586              }
1587          }
1588  
1589          if( 1 < count( $t_clauses ) ) {
1590              $t_where_tmp = array();
1591              foreach( $t_clauses as $t_clause ) {
1592                  $t_where_tmp[] = db_param();
1593                  $t_where_params[] = $t_clause;
1594              }
1595              array_push( $t_where_clauses, "( $t_bug_table.os in (" . implode( ', ', $t_where_tmp ) . ") )" );
1596          } else {
1597              $t_where_params[] = $t_clauses[0];
1598              array_push( $t_where_clauses, "( $t_bug_table.os = " . db_param() . " )" );
1599          }
1600      }
1601  
1602      # os_build
1603      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_OS_BUILD] ) ) {
1604          $t_clauses = array();
1605  
1606          foreach( $t_filter[FILTER_PROPERTY_OS_BUILD] as $t_filter_member ) {
1607              $t_filter_member = stripslashes( $t_filter_member );
1608              if( filter_field_is_none( $t_filter_member ) ) {
1609                  array_push( $t_clauses, '' );
1610              } else {
1611                  $c_os_build = db_prepare_string( $t_filter_member );
1612                  array_push( $t_clauses, $c_os_build );
1613              }
1614          }
1615  
1616          if( 1 < count( $t_clauses ) ) {
1617              $t_where_tmp = array();
1618              foreach( $t_clauses as $t_clause ) {
1619                  $t_where_tmp[] = db_param();
1620                  $t_where_params[] = $t_clause;
1621              }
1622              array_push( $t_where_clauses, "( $t_bug_table.os_build in (" . implode( ', ', $t_where_tmp ) . ") )" );
1623          } else {
1624              $t_where_params[] = $t_clauses[0];
1625              array_push( $t_where_clauses, "( $t_bug_table.os_build = " . db_param() . " )" );
1626          }
1627      }
1628  
1629      # date filter
1630      if(( 'on' == $t_filter[FILTER_PROPERTY_FILTER_BY_DATE] ) && is_numeric( $t_filter[FILTER_PROPERTY_START_MONTH] ) && is_numeric( $t_filter[FILTER_PROPERTY_START_DAY] ) && is_numeric( $t_filter[FILTER_PROPERTY_START_YEAR] ) && is_numeric( $t_filter[FILTER_PROPERTY_END_MONTH] ) && is_numeric( $t_filter[FILTER_PROPERTY_END_DAY] ) && is_numeric( $t_filter[FILTER_PROPERTY_END_YEAR] ) ) {
1631  
1632          $t_start_string = $t_filter[FILTER_PROPERTY_START_YEAR] . "-" . $t_filter[FILTER_PROPERTY_START_MONTH] . "-" . $t_filter[FILTER_PROPERTY_START_DAY] . " 00:00:00";
1633          $t_end_string = $t_filter[FILTER_PROPERTY_END_YEAR] . "-" . $t_filter[FILTER_PROPERTY_END_MONTH] . "-" . $t_filter[FILTER_PROPERTY_END_DAY] . " 23:59:59";
1634  
1635          $t_where_params[] = strtotime( $t_start_string );
1636          $t_where_params[] = strtotime( $t_end_string );
1637          array_push( $t_where_clauses, "($t_bug_table.date_submitted BETWEEN " . db_param() . " AND " . db_param() . " )" );
1638      }
1639  
1640      # fixed in version
1641      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_FIXED_IN_VERSION] ) ) {
1642          $t_clauses = array();
1643  
1644          foreach( $t_filter[FILTER_PROPERTY_FIXED_IN_VERSION] as $t_filter_member ) {
1645              $t_filter_member = stripslashes( $t_filter_member );
1646              if( filter_field_is_none( $t_filter_member ) ) {
1647                  array_push( $t_clauses, '' );
1648              } else {
1649                  $c_fixed_in_version = db_prepare_string( $t_filter_member );
1650                  array_push( $t_clauses, $c_fixed_in_version );
1651              }
1652          }
1653          if( 1 < count( $t_clauses ) ) {
1654              $t_where_tmp = array();
1655              foreach( $t_clauses as $t_clause ) {
1656                  $t_where_tmp[] = db_param();
1657                  $t_where_params[] = $t_clause;
1658              }
1659              array_push( $t_where_clauses, "( $t_bug_table.fixed_in_version in (" . implode( ', ', $t_where_tmp ) . ") )" );
1660          } else {
1661              $t_where_params[] = $t_clauses[0];
1662              array_push( $t_where_clauses, "( $t_bug_table.fixed_in_version=" . db_param() . " )" );
1663          }
1664      }
1665  
1666      # target version
1667      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_TARGET_VERSION] ) ) {
1668          $t_clauses = array();
1669  
1670          foreach( $t_filter[FILTER_PROPERTY_TARGET_VERSION] as $t_filter_member ) {
1671              $t_filter_member = stripslashes( $t_filter_member );
1672              if( filter_field_is_none( $t_filter_member ) ) {
1673                  array_push( $t_clauses, '' );
1674              } else {
1675                  $c_target_version = db_prepare_string( $t_filter_member );
1676                  array_push( $t_clauses, $c_target_version );
1677              }
1678          }
1679  
1680          # echo var_dump( $t_clauses ); exit;
1681          if( 1 < count( $t_clauses ) ) {
1682              $t_where_tmp = array();
1683              foreach( $t_clauses as $t_clause ) {
1684                  $t_where_tmp[] = db_param();
1685                  $t_where_params[] = $t_clause;
1686              }
1687              array_push( $t_where_clauses, "( $t_bug_table.target_version in (" . implode( ', ', $t_where_tmp ) . ") )" );
1688          } else {
1689              $t_where_params[] = $t_clauses[0];
1690              array_push( $t_where_clauses, "( $t_bug_table.target_version=" . db_param() . " )" );
1691          }
1692      }
1693  
1694      # users monitoring a bug
1695      if( !filter_field_is_any( $t_filter[FILTER_PROPERTY_MONITOR_USER_ID] ) ) {
1696          $t_clauses = array();
1697          $t_table_name = 'user_monitor';
1698          array_push( $t_join_clauses, "LEFT JOIN $t_bug_monitor_table $t_table_name ON $t_table_name.bug_id = $t_bug_table.id" );
1699  
1700          foreach( $t_filter[FILTER_PROPERTY_MONITOR_USER_ID] as $t_filter_member ) {
1701              $c_user_monitor = db_prepare_int( $t_filter_member );
1702              if( filter_field_is_myself( $c_user_monitor ) ) {
1703                  array_push( $t_clauses, $c_user_id );
1704              } else {
1705                  array_push( $t_clauses, $c_user_monitor );
1706              }
1707          }
1708          if( 1 < count( $t_clauses ) ) {
1709              $t_where_tmp = array();
1710              foreach( $t_clauses as $t_clause ) {
1711                  $t_where_tmp[] = db_param();
1712                  $t_where_params[] = $t_clause;
1713              }
1714              array_push( $t_where_clauses, "( $t_table_name.user_id in (" . implode( ', ', $t_where_tmp ) . ") )" );
1715          } else {
1716              $t_where_params[] = $t_clauses[0];
1717              array_push( $t_where_clauses, "( $t_table_name.user_id=" . db_param() . " )" );
1718          }
1719      }
1720  
1721      # bug relationship
1722      $t_any_found = false;
1723      $c_rel_type = $t_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE];
1724      $c_rel_bug = $t_filter[FILTER_PROPERTY_RELATIONSHIP_BUG];
1725      if( -1 == $c_rel_type || 0 == $c_rel_bug ) {
1726          $t_any_found = true;
1727      }
1728      if( !$t_any_found ) {
1729          # use the complementary type
1730          $t_comp_type = relationship_get_complementary_type( $c_rel_type );
1731          $t_clauses = array();
1732          $t_table_name = 'relationship';
1733          array_push( $t_join_clauses, "LEFT JOIN $t_bug_relationship_table $t_table_name ON $t_table_name.destination_bug_id = $t_bug_table.id" );
1734          array_push(