| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
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(