.
#------------------------------
# $Revision: 2643 $
# $Author: al $
# $Date: 2009-06-18 19:06:27 -0400 (Thu, 18 Jun 2009) $
#------------------------------
$t_core_dir = dirname( __FILE__ ).DIRECTORY_SEPARATOR;
require_once( $t_core_dir . 'current_user_api.php' );
require_once( $t_core_dir . 'user_api.php' );
require_once( $t_core_dir . 'bug_api.php' );
require_once( $t_core_dir . 'collapse_api.php' );
require_once( $t_core_dir . 'relationship_api.php' );
require_once( $t_core_dir . 'tag_api.php' );
###########################################################################
# Filter Property Names
###########################################################################
define( 'FILTER_PROPERTY_FREE_TEXT', 'search' );
define( 'FILTER_PROPERTY_CATEGORY', 'show_category' );
define( 'FILTER_PROPERTY_SEVERITY_ID', 'show_severity' );
define( 'FILTER_PROPERTY_STATUS_ID', 'show_status' );
define( 'FILTER_PROPERTY_PRIORITY_ID', 'show_priority' );
define( 'FILTER_PROPERTY_HIGHLIGHT_CHANGED', 'highlight_changed' );
define( 'FILTER_PROPERTY_REPORTER_ID', 'reporter_id' );
define( 'FILTER_PROPERTY_HANDLER_ID', 'handler_id' );
define( 'FILTER_PROPERTY_PROJECT_ID', 'project_id' );
define( 'FILTER_PROPERTY_RESOLUTION_ID', 'show_resolution' );
define( 'FILTER_PROPERTY_PRODUCT_BUILD', 'show_build' );
define( 'FILTER_PROPERTY_PRODUCT_VERSION', 'show_version' );
define( 'FILTER_PROPERTY_MONITOR_USER_ID', 'user_monitor' );
define( 'FILTER_PROPERTY_HIDE_STATUS_ID', 'hide_status' );
define( 'FILTER_PROPERTY_SORT_FIELD_NAME', 'sort' );
define( 'FILTER_PROPERTY_SORT_DIRECTION', 'dir' );
define( 'FILTER_PROPERTY_SHOW_STICKY_ISSUES', 'sticky_issues' );
define( 'FILTER_PROPERTY_VIEW_STATE_ID', 'view_state' );
define( 'FILTER_PROPERTY_FIXED_IN_VERSION', 'fixed_in_version' );
define( 'FILTER_PROPERTY_TARGET_VERSION', 'target_version' );
define( 'FILTER_PROPERTY_ISSUES_PER_PAGE', 'per_page' );
define( 'FILTER_PROPERTY_PROFILE', 'profile_id' );
define( 'FILTER_PROPERTY_PLATFORM', 'platform' );
define( 'FILTER_PROPERTY_OS', 'os' );
define( 'FILTER_PROPERTY_OS_BUILD', 'os_build' );
define( 'FILTER_PROPERTY_START_DAY', 'start_day' );
define( 'FILTER_PROPERTY_START_MONTH', 'start_month' );
define( 'FILTER_PROPERTY_START_YEAR', 'start_year' );
define( 'FILTER_PROPERTY_END_DAY', 'end_day' );
define( 'FILTER_PROPERTY_END_MONTH', 'end_month' );
define( 'FILTER_PROPERTY_END_YEAR', 'end_year' );
define( 'FILTER_PROPERTY_NOT_ASSIGNED', 'and_not_assigned' );
define( 'FILTER_PROPERTY_FILTER_BY_DATE', 'do_filter_by_date' );
define( 'FILTER_PROPERTY_RELATIONSHIP_TYPE', 'relationship_type' );
define( 'FILTER_PROPERTY_RELATIONSHIP_BUG', 'relationship_bug' );
define( 'FILTER_PROPERTY_TAG_STRING', 'tag_string' );
define( 'FILTER_PROPERTY_TAG_SELECT', 'tag_select' );
###########################################################################
# Filter Query Parameter Names
###########################################################################
define( 'FILTER_SEARCH_FREE_TEXT', 'search' );
define( 'FILTER_SEARCH_CATEGORY', 'category' );
define( 'FILTER_SEARCH_SEVERITY_ID', 'severity_id');
define( 'FILTER_SEARCH_STATUS_ID', 'status_id' );
define( 'FILTER_SEARCH_REPORTER_ID', 'reporter_id' );
define( 'FILTER_SEARCH_HANDLER_ID', 'handler_id' );
define( 'FILTER_SEARCH_PROJECT_ID', 'project_id' );
define( 'FILTER_SEARCH_RESOLUTION_ID', 'resolution_id' );
define( 'FILTER_SEARCH_FIXED_IN_VERSION', 'fixed_in_version' );
define( 'FILTER_SEARCH_TARGET_VERSION', 'target_version' );
define( 'FILTER_SEARCH_START_DAY', 'start_day' );
define( 'FILTER_SEARCH_START_MONTH', 'start_month' );
define( 'FILTER_SEARCH_START_YEAR', 'start_year' );
define( 'FILTER_SEARCH_END_DAY', 'end_day' );
define( 'FILTER_SEARCH_END_MONTH', 'end_month' );
define( 'FILTER_SEARCH_END_YEAR', 'end_year' );
define( 'FILTER_SEARCH_PRIORITY_ID', 'priority_id' );
define( 'FILTER_SEARCH_PROFILE', 'profile_id' );
define( 'FILTER_SEARCH_PLATFORM', 'platform' );
define( 'FILTER_SEARCH_OS', 'os' );
define( 'FILTER_SEARCH_OS_BUILD', 'os_build' );
define( 'FILTER_SEARCH_MONITOR_USER_ID', 'monitor_user_id' );
define( 'FILTER_SEARCH_PRODUCT_BUILD', 'product_build' );
define( 'FILTER_SEARCH_PRODUCT_VERSION', 'product_version' );
define( 'FILTER_SEARCH_VIEW_STATE_ID', 'view_state_id' );
define( 'FILTER_SEARCH_SHOW_STICKY_ISSUES', 'sticky_issues' );
define( 'FILTER_SEARCH_SORT_FIELD_NAME', 'sortby' );
define( 'FILTER_SEARCH_SORT_DIRECTION', 'dir' );
define( 'FILTER_SEARCH_ISSUES_PER_PAGE', 'per_page' );
define( 'FILTER_SEARCH_HIGHLIGHT_CHANGED', 'highlight_changed' );
define( 'FILTER_SEARCH_HIDE_STATUS_ID', 'hide_status_id' );
define( 'FILTER_SEARCH_NOT_ASSIGNED', 'not_assigned' );
define( 'FILTER_SEARCH_FILTER_BY_DATE', 'filter_by_date' );
define( 'FILTER_SEARCH_RELATIONSHIP_TYPE', 'relationship_type' );
define( 'FILTER_SEARCH_RELATIONSHIP_BUG', 'relationship_bug' );
define( 'FILTER_SEARCH_TAG_STRING', 'tag_string' );
define( 'FILTER_SEARCH_TAG_SELECT', 'tag_select' );
# Checks the supplied value to see if it is an ANY value.
# $p_field_value - The value to check.
# Returns true for "ANY" values and false for others. "ANY" means filter criteria not active.
function filter_str_field_is_any( $p_field_value ) {
if ( is_array( $p_field_value ) ) {
if ( count( $p_field_value ) == 0 ) {
return true;
}
foreach( $p_field_value as $t_value ) {
if ( ( META_FILTER_ANY == $t_value ) && ( is_numeric( $t_value ) ) ) {
return true;
}
}
} else {
if ( is_string( $p_field_value ) && is_blank( $p_field_value ) ) {
return true;
}
if ( is_bool( $p_field_value ) && !$p_field_value ) {
return true;
}
if ( ( META_FILTER_ANY == $p_field_value ) && ( is_numeric( $p_field_value ) ) ) {
return true;
}
}
return false;
}
# Encodes a field and it's value for the filter URL. This handles the URL encoding
# and arrays.
# $p_field_name - The field name.
# $p_field_value - The field value (can be an array)
function filter_encode_field_and_value( $p_field_name, $p_field_value ) {
$t_query_array = array();
if ( is_array( $p_field_value ) ) {
$t_count = count( $p_field_value );
if ( $t_count > 1 ) {
foreach ( $p_field_value as $t_value ) {
$t_query_array[] = urlencode( $p_field_name . '[]' ) . '=' . urlencode( $t_value );
}
} else if ( $t_count == 1 ) {
$t_query_array[] = urlencode( $p_field_name ) . '=' . urlencode( $p_field_value[0] );
}
} else {
$t_query_array[] = urlencode( $p_field_name ) . '=' . urlencode( $p_field_value );
}
return implode( $t_query_array, '&' );
}
# Get a permalink for the current active filter. The results of using these fields by other users
# can be inconsistent with the original results due to fields like "Myself", "Current Project",
# and due to access level.
# Returns the search.php?xxxx or an empty string if no criteria applied.
function filter_get_url( $p_custom_filter ) {
$t_query = array();
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_PROJECT_ID] ) ) {
$t_project_id = $p_custom_filter[FILTER_PROPERTY_PROJECT_ID];
if ( count( $t_project_id ) == 1 && $t_project_id[0] == META_FILTER_CURRENT ) {
$t_project_id = array( helper_get_current_project() );
}
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_PROJECT_ID, $t_project_id );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_FREE_TEXT] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_FREE_TEXT, $p_custom_filter[FILTER_PROPERTY_FREE_TEXT] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_CATEGORY] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_CATEGORY, $p_custom_filter[FILTER_PROPERTY_CATEGORY] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_REPORTER_ID] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_REPORTER_ID, $p_custom_filter[FILTER_PROPERTY_REPORTER_ID] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_STATUS_ID] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_STATUS_ID, $p_custom_filter[FILTER_PROPERTY_STATUS_ID] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_MONITOR_USER_ID] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_MONITOR_USER_ID, $p_custom_filter[FILTER_PROPERTY_MONITOR_USER_ID] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_HANDLER_ID] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_HANDLER_ID, $p_custom_filter[FILTER_PROPERTY_HANDLER_ID] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_SEVERITY_ID] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_SEVERITY_ID, $p_custom_filter[FILTER_PROPERTY_SEVERITY_ID] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_RESOLUTION_ID] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_RESOLUTION_ID, $p_custom_filter[FILTER_PROPERTY_RESOLUTION_ID] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_PRIORITY_ID] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_PRIORITY_ID, $p_custom_filter[FILTER_PROPERTY_PRIORITY_ID] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_VIEW_STATE_ID] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_VIEW_STATE_ID, $p_custom_filter[FILTER_PROPERTY_VIEW_STATE_ID] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_SHOW_STICKY_ISSUES] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_SHOW_STICKY_ISSUES, $p_custom_filter[FILTER_PROPERTY_SHOW_STICKY_ISSUES] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_PRODUCT_VERSION] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_PRODUCT_VERSION, $p_custom_filter[FILTER_PROPERTY_PRODUCT_VERSION] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_PRODUCT_BUILD] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_PRODUCT_BUILD, $p_custom_filter[FILTER_PROPERTY_PRODUCT_BUILD] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_FIXED_IN_VERSION] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_FIXED_IN_VERSION, $p_custom_filter[FILTER_PROPERTY_FIXED_IN_VERSION] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_TARGET_VERSION] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_TARGET_VERSION, $p_custom_filter[FILTER_PROPERTY_TARGET_VERSION] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_SORT_FIELD_NAME] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_SORT_FIELD_NAME, $p_custom_filter[FILTER_PROPERTY_SORT_FIELD_NAME] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_SORT_DIRECTION] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_SORT_DIRECTION, $p_custom_filter[FILTER_PROPERTY_SORT_DIRECTION] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_SEARCH_ISSUES_PER_PAGE] ) ) {
if ( $p_custom_filter[FILTER_SEARCH_ISSUES_PER_PAGE] != config_get( 'default_limit_view' ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_ISSUES_PER_PAGE, $p_custom_filter[FILTER_SEARCH_ISSUES_PER_PAGE] );
}
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED] ) ) {
if ( $p_custom_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED] != config_get( 'default_show_changed' ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_HIGHLIGHT_CHANGED, $p_custom_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED] );
}
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_HIDE_STATUS_ID] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_HIDE_STATUS_ID, $p_custom_filter[FILTER_PROPERTY_HIDE_STATUS_ID] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_NOT_ASSIGNED] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_NOT_ASSIGNED, $p_custom_filter[FILTER_PROPERTY_NOT_ASSIGNED] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_FILTER_BY_DATE] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_FILTER_BY_DATE, $p_custom_filter[FILTER_PROPERTY_FILTER_BY_DATE] );
# The start and end dates are only applicable if filter by date is set.
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_START_DAY] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_START_DAY, $p_custom_filter[FILTER_PROPERTY_START_DAY] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_END_DAY] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_END_DAY, $p_custom_filter[FILTER_PROPERTY_END_DAY] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_START_MONTH] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_START_MONTH, $p_custom_filter[FILTER_PROPERTY_START_MONTH] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_END_MONTH] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_END_MONTH, $p_custom_filter[FILTER_PROPERTY_END_MONTH] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_START_YEAR] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_START_YEAR, $p_custom_filter[FILTER_PROPERTY_START_YEAR] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_END_YEAR] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_END_YEAR, $p_custom_filter[FILTER_PROPERTY_END_YEAR] );
}
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE] ) ) {
if ( $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE] != -1 ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_RELATIONSHIP_TYPE, $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE] );
}
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_BUG] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_RELATIONSHIP_BUG, $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_BUG] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_PLATFORM] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_PLATFORM, $p_custom_filter[FILTER_PROPERTY_PLATFORM] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_OS] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_OS, $p_custom_filter[FILTER_PROPERTY_OS] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_OS_BUILD] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_OS_BUILD, $p_custom_filter[FILTER_PROPERTY_OS_BUILD] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_TAG_STRING] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_TAG_STRING, $p_custom_filter[FILTER_PROPERTY_TAG_STRING] );
}
if ( !filter_str_field_is_any( $p_custom_filter[FILTER_PROPERTY_TAG_SELECT] ) ) {
$t_query[] = filter_encode_field_and_value( FILTER_SEARCH_TAG_SELECT, $p_custom_filter[FILTER_PROPERTY_TAG_SELECT] );
}
if ( isset( $p_custom_filter['custom_fields'] ) ) {
foreach( $p_custom_filter['custom_fields'] as $t_custom_field_id => $t_custom_field_values ) {
if ( !filter_str_field_is_any( $t_custom_field_values ) ) {
$t_query[] = filter_encode_field_and_value( 'custom_field_' . $t_custom_field_id, $t_custom_field_values );
}
}
}
if ( count( $t_query ) > 0 ) {
$t_query_str = implode( $t_query, '&' );
$t_url = config_get( 'path' ) . 'search.php?' . $t_query_str;
} else {
$t_url = '';
}
return $t_url;
}
###########################################################################
# Filter API
###########################################################################
# Get the standard filter that is to be used when no filter was previously saved.
# When creating specific filters, this can be used as a basis for the filter, where
# specific entries can be overridden.
function filter_get_default() {
$t_hide_status_default = config_get( 'hide_status_default' );
$t_default_show_changed = config_get( 'default_show_changed' );
$t_filter = array(
'show_category' => Array ( '0' => META_FILTER_ANY ),
'show_severity' => Array ( '0' => META_FILTER_ANY ),
'show_status' => Array ( '0' => META_FILTER_ANY ),
'highlight_changed' => $t_default_show_changed,
'reporter_id' => Array ( '0' => META_FILTER_ANY ),
'handler_id' => Array ( '0' => META_FILTER_ANY ),
'project_id' => Array ( '0' => META_FILTER_CURRENT ),
'show_resolution' => Array ( '0' => META_FILTER_ANY ),
'show_build' => Array ( '0' => META_FILTER_ANY ),
'show_version' => Array ( '0' => META_FILTER_ANY ),
'hide_status' => Array ( '0' => $t_hide_status_default ),
'user_monitor' => Array ( '0' => META_FILTER_ANY ),
'sort' => 'last_updated',
'dir' => 'DESC'
);
return filter_ensure_valid_filter( $t_filter );
}
# @@@ Had to make all these parameters required because we can't use
# call-time pass by reference anymore. I really preferred not having
# to pass all the params in if you didn't want to, but I wanted to get
# rid of the errors for now. If we can think of a better way later
# (maybe return an object) that would be great.
#
# $p_page_numer
# - the page you want to see (set to the actual page on return)
# $p_per_page
# - the number of bugs to see per page (set to actual on return)
# -1 indicates you want to see all bugs
# null indicates you want to use the value specified in the filter
# $p_page_count
# - you don't need to give a value here, the number of pages will be
# stored here on return
# $p_bug_count
# - you don't need to give a value here, the number of bugs will be
# stored here on return
# $p_custom_filter
# - Filter to use.
# $p_project_id
# - project id to use in filtering.
# $p_user_id
# - user id to use as current user when filtering.
# $p_show_sticky
# - get sticky issues only.
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 ) {
log_event( LOG_FILTERING, 'FILTERING: START NEW FILTER QUERY' );
$t_bug_table = config_get( 'mantis_bug_table' );
$t_bug_text_table = config_get( 'mantis_bug_text_table' );
$t_bugnote_table = config_get( 'mantis_bugnote_table' );
$t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );
$t_bugnote_text_table = config_get( 'mantis_bugnote_text_table' );
$t_project_table = config_get( 'mantis_project_table' );
$t_bug_monitor_table = config_get( 'mantis_bug_monitor_table' );
$t_limit_reporters = config_get( 'limit_reporters' );
$t_bug_relationship_table = config_get( 'mantis_bug_relationship_table' );
$t_report_bug_threshold = config_get( 'report_bug_threshold' );
$t_current_user_id = auth_get_current_user_id();
if ( null === $p_user_id ) {
$t_user_id = $t_current_user_id;
} else {
$t_user_id = $p_user_id;
}
$c_user_id = db_prepare_int( $t_user_id );
if ( null === $p_project_id ) {
# @@@ If project_id is not specified, then use the project id(s) in the filter if set, otherwise, use current project.
$t_project_id = helper_get_current_project();
} else {
$t_project_id = $p_project_id;
}
if ( $p_custom_filter === null ) {
# Prefer current_user_get_bug_filter() over user_get_filter() when applicable since it supports
# cookies set by previous version of the code.
if ( $t_user_id == $t_current_user_id ) {
$t_filter = current_user_get_bug_filter();
} else {
$t_filter = user_get_bug_filter( $t_user_id, $t_project_id );
}
} else {
$t_filter = $p_custom_filter;
}
$t_filter = filter_ensure_valid_filter( $t_filter );
if ( false === $t_filter ) {
return false; # signify a need to create a cookie
#@@@ error instead?
}
$t_view_type = $t_filter['_view_type'];
$t_where_clauses = array( "$t_project_table.enabled = 1", "$t_project_table.id = $t_bug_table.project_id" );
$t_select_clauses = array( "$t_bug_table.*" );
$t_join_clauses = array();
$t_from_clauses = array();
// normalize the project filtering into an array $t_project_ids
if ( 'simple' == $t_view_type ) {
log_event( LOG_FILTERING, 'FILTERING: Simple Filter' );
$t_project_ids = array( $t_project_id );
$t_include_sub_projects = true;
} else {
log_event( LOG_FILTERING, 'FILTERING: Advanced Filter' );
if ( !is_array( $t_filter['project_id'] ) ) {
$t_project_ids = array( db_prepare_int( $t_filter['project_id'] ) );
} else {
$t_project_ids = array_map( 'db_prepare_int', $t_filter['project_id'] );
}
$t_include_sub_projects = ( ( count( $t_project_ids ) == 1 ) && ( $t_project_ids[0] == META_FILTER_CURRENT ) );
}
log_event( LOG_FILTERING, 'FILTERING: project_ids = ' . implode( ',', $t_project_ids ) );
log_event( LOG_FILTERING, 'FILTERING: include sub-projects = ' . ( $t_include_sub_projects ? '1' : '0' ) );
// if the array has ALL_PROJECTS, then reset the array to only contain ALL_PROJECTS.
// replace META_FILTER_CURRENT with the actualy current project id.
$t_all_projects_found = false;
$t_new_project_ids = array();
foreach ( $t_project_ids as $t_pid ) {
if ( $t_pid == META_FILTER_CURRENT ) {
$t_pid = $t_project_id;
}
if ( $t_pid == ALL_PROJECTS ) {
$t_all_projects_found = true;
log_event( LOG_FILTERING, 'FILTERING: all projects selected' );
break;
}
// filter out inaccessible projects.
if ( !access_has_project_level( VIEWER, $t_pid, $t_user_id ) ) {
continue;
}
$t_new_project_ids[] = $t_pid;
}
$t_projects_query_required = true;
if ( $t_all_projects_found ) {
if ( user_is_administrator( $t_user_id ) ) {
log_event( LOG_FILTERING, 'FILTERING: all projects + administrator, hence no project filter.' );
$t_projects_query_required = false;
} else {
$t_project_ids = user_get_accessible_projects( $t_user_id );
}
} else {
$t_project_ids = $t_new_project_ids;
}
if ( $t_projects_query_required ) {
// expand project ids to include sub-projects
if ( $t_include_sub_projects ) {
$t_top_project_ids = $t_project_ids;
foreach ( $t_top_project_ids as $t_pid ) {
log_event( LOG_FILTERING, 'FILTERING: Getting sub-projects for project id ' . $t_pid );
$t_project_ids = array_merge( $t_project_ids, user_get_all_accessible_subprojects( $t_user_id, $t_pid ) );
}
$t_project_ids = array_unique( $t_project_ids );
}
// if no projects are accessible, then return an empty array.
if ( count( $t_project_ids ) == 0 ) {
log_event( LOG_FILTERING, 'FILTERING: no accessible projects' );
return array();
}
log_event( LOG_FILTERING, 'FILTERING: project_ids after including sub-projects = ' . implode( ',', $t_project_ids ) );
// this array is to be populated with project ids for which we only want to show public issues. This is due to the limited
// access of the current user.
$t_public_only_project_ids = array();
// this array is populated with project ids that the current user has full access to.
$t_private_and_public_project_ids = array();
$t_access_required_to_view_private_bugs = config_get( 'private_bug_threshold' );
foreach ( $t_project_ids as $t_pid ) {
if ( access_has_project_level( $t_access_required_to_view_private_bugs, $t_pid, $t_user_id ) ) {
$t_private_and_public_project_ids[] = $t_pid;
} else {
$t_public_only_project_ids[] = $t_pid;
}
}
log_event( LOG_FILTERING, 'FILTERING: project_ids (with public/private access) = ' . implode( ',', $t_private_and_public_project_ids ) );
log_event( LOG_FILTERING, 'FILTERING: project_ids (with public access) = ' . implode( ',', $t_public_only_project_ids ) );
$t_count_private_and_public_project_ids = count( $t_private_and_public_project_ids );
if ( $t_count_private_and_public_project_ids == 1 ) {
$t_private_and_public_query = "( $t_bug_table.project_id = " . $t_private_and_public_project_ids[0] . " )";
} else if ( $t_count_private_and_public_project_ids > 1 ) {
$t_private_and_public_query = "( $t_bug_table.project_id in (". implode( ', ', $t_private_and_public_project_ids ) . ") )";
} else {
$t_private_and_public_query = null;
}
$t_count_public_only_project_ids = count( $t_public_only_project_ids );
$t_public_view_state_check = "( ( $t_bug_table.view_state = " . VS_PUBLIC . " ) OR ( $t_bug_table.reporter_id = $t_user_id ) )";
if ( $t_count_public_only_project_ids == 1 ) {
$t_public_only_query = "( ( $t_bug_table.project_id = " . $t_public_only_project_ids[0] . " ) AND $t_public_view_state_check )";
} else if ( $t_count_public_only_project_ids > 1 ) {
$t_public_only_query = "( ( $t_bug_table.project_id in (". implode( ', ', $t_public_only_project_ids ) . ") ) AND $t_public_view_state_check )";
} else {
$t_public_only_query = null;
}
// both queries can't be null, so we either have one of them or both.
if ( $t_private_and_public_query === null ) {
$t_project_query = $t_public_only_query;
} else if ( $t_public_only_query === null ) {
$t_project_query = $t_private_and_public_query;
} else {
$t_project_query = "( $t_public_only_query OR $t_private_and_public_query )";
}
log_event( LOG_FILTERING, 'FILTERING: project query = ' . $t_project_query );
array_push( $t_where_clauses, $t_project_query );
}
# view state
$t_view_state = db_prepare_int( $t_filter['view_state'] );
if ( ( $t_filter['view_state'] !== META_FILTER_ANY ) && ( !is_blank( $t_filter['view_state'] ) ) ) {
$t_view_state_query = "($t_bug_table.view_state='$t_view_state')";
log_event( LOG_FILTERING, 'FILTERING: view_state query = ' . $t_view_state_query );
array_push( $t_where_clauses, $t_view_state_query );
} else {
log_event( LOG_FILTERING, 'FILTERING: no view_state query' );
}
# reporter
$t_any_found = false;
foreach( $t_filter['reporter_id'] as $t_filter_member ) {
if ( ( META_FILTER_ANY === $t_filter_member ) || ( 0 === $t_filter_member ) ) {
$t_any_found = true;
}
}
if ( count( $t_filter['reporter_id'] ) == 0 ) {
$t_any_found = true;
}
if ( !$t_any_found ) {
$t_clauses = array();
foreach( $t_filter['reporter_id'] as $t_filter_member ) {
if ( META_FILTER_NONE == $t_filter_member ) {
array_push( $t_clauses, "0" );
} else {
$c_reporter_id = db_prepare_int( $t_filter_member );
if ( META_FILTER_MYSELF == $c_reporter_id ) {
array_push( $t_clauses, $c_user_id );
} else {
array_push( $t_clauses, $c_reporter_id );
}
}
}
if ( 1 < count( $t_clauses ) ) {
$t_reporter_query = "( $t_bug_table.reporter_id in (". implode( ', ', $t_clauses ) .") )";
} else {
$t_reporter_query = "( $t_bug_table.reporter_id=$t_clauses[0] )";
}
log_event( LOG_FILTERING, 'FILTERING: reporter query = ' . $t_reporter_query );
array_push( $t_where_clauses, $t_reporter_query );
} else {
log_event( LOG_FILTERING, 'FILTERING: no reporter query' );
}
# limit reporter
# @@@ thraxisp - access_has_project_level checks greater than or equal to,
# this assumed that there aren't any holes above REPORTER where the limit would apply
#
if ( ( ON === $t_limit_reporters ) && ( ! access_has_project_level( REPORTER + 1, $t_project_id, $t_user_id ) ) ) {
$c_reporter_id = $c_user_id;
array_push( $t_where_clauses, "($t_bug_table.reporter_id='$c_reporter_id')" );
}
# handler
$t_any_found = false;
foreach( $t_filter['handler_id'] as $t_filter_member ) {
if ( ( META_FILTER_ANY === $t_filter_member ) || ( 0 === $t_filter_member ) ) {
$t_any_found = true;
}
}
if ( count( $t_filter['handler_id'] ) == 0 ) {
$t_any_found = true;
}
if ( !$t_any_found ) {
$t_clauses = array();
foreach( $t_filter['handler_id'] as $t_filter_member ) {
if ( META_FILTER_NONE == $t_filter_member ) {
array_push( $t_clauses, 0 );
} else {
$c_handler_id = db_prepare_int( $t_filter_member );
if ( META_FILTER_MYSELF == $c_handler_id ) {
array_push( $t_clauses, $c_user_id );
} else {
array_push( $t_clauses, $c_handler_id );
}
}
}
if ( 1 < count( $t_clauses ) ) {
$t_handler_query = "( $t_bug_table.handler_id in (". implode( ', ', $t_clauses ) .") )";
} else {
$t_handler_query = "( $t_bug_table.handler_id=$t_clauses[0] )";
}
log_event( LOG_FILTERING, 'FILTERING: handler query = ' . $t_handler_query );
array_push( $t_where_clauses, $t_handler_query );
} else {
log_event( LOG_FILTERING, 'FILTERING: no handler query' );
}
# category
if ( !_filter_is_any( $t_filter['show_category'] ) ) {
$t_clauses = array();
foreach( $t_filter['show_category'] as $t_filter_member ) {
$t_filter_member = stripslashes( $t_filter_member );
if ( META_FILTER_NONE == $t_filter_member ) {
array_push( $t_clauses, "''" );
} else {
$c_show_category = db_prepare_string( $t_filter_member );
array_push( $t_clauses, "'$c_show_category'" );
}
}
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_bug_table.category in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.category=$t_clauses[0] )" );
}
}
# severity
$t_any_found = false;
foreach( $t_filter['show_severity'] as $t_filter_member ) {
if ( ( META_FILTER_ANY == $t_filter_member ) || ( 0 === $t_filter_member ) ) {
$t_any_found = true;
}
}
if ( count( $t_filter['show_severity'] ) == 0 ) {
$t_any_found = true;
}
if ( !$t_any_found ) {
$t_clauses = array();
foreach( $t_filter['show_severity'] as $t_filter_member ) {
$c_show_severity = db_prepare_int( $t_filter_member );
array_push( $t_clauses, $c_show_severity );
}
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_bug_table.severity in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.severity=$t_clauses[0] )" );
}
}
# show / hide status
# take a list of all available statuses then remove the ones that we want hidden, then make sure
# the ones we want shown are still available
$t_status_arr = explode_enum_string( config_get( 'status_enum_string' ) );
$t_available_statuses = array();
$t_desired_statuses = array();
foreach( $t_status_arr as $t_this_status ) {
$t_this_status_arr = explode_enum_arr( $t_this_status );
$t_available_statuses[] = $t_this_status_arr[0];
}
if ( 'simple' == $t_filter['_view_type'] ) {
# simple filtering: if showing any, restrict by the hide status value, otherwise ignore the hide
$t_any_found = false;
$t_this_status = $t_filter['show_status'][0];
$t_this_hide_status = $t_filter['hide_status'][0];
if ( ( META_FILTER_ANY == $t_this_status ) || ( is_blank( $t_this_status ) ) || ( 0 === $t_this_status ) ) {
$t_any_found = true;
}
if ( $t_any_found ) {
foreach( $t_available_statuses as $t_this_available_status ) {
if ( $t_this_hide_status > $t_this_available_status ) {
$t_desired_statuses[] = $t_this_available_status;
}
}
} else {
$t_desired_statuses[] = $t_this_status;
}
} else {
# advanced filtering: ignore the hide
$t_any_found = false;
foreach( $t_filter['show_status'] as $t_this_status ) {
$t_desired_statuses[] = $t_this_status;
if ( ( META_FILTER_ANY == $t_this_status ) || ( is_blank( $t_this_status ) ) || ( 0 === $t_this_status ) ) {
$t_any_found = true;
}
}
if ( $t_any_found ) {
$t_desired_statuses = array();
}
}
if ( count( $t_desired_statuses ) > 0 ) {
$t_clauses = array();
foreach( $t_desired_statuses as $t_filter_member ) {
$c_show_status = db_prepare_int( $t_filter_member );
array_push( $t_clauses, $c_show_status );
}
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_bug_table.status in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.status=$t_clauses[0] )" );
}
}
# resolution
$t_any_found = false;
foreach( $t_filter['show_resolution'] as $t_filter_member ) {
if ( META_FILTER_ANY == $t_filter_member ) {
$t_any_found = true;
}
}
if ( count( $t_filter['show_resolution'] ) == 0 ) {
$t_any_found = true;
}
if ( !$t_any_found ) {
$t_clauses = array();
foreach( $t_filter['show_resolution'] as $t_filter_member ) {
$c_show_resolution = db_prepare_int( $t_filter_member );
array_push( $t_clauses, $c_show_resolution );
}
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_bug_table.resolution in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.resolution=$t_clauses[0] )" );
}
}
# priority
$t_any_found = false;
foreach( $t_filter['show_priority'] as $t_filter_member ) {
if ( ( META_FILTER_ANY == $t_filter_member ) || ( 0 === $t_filter_member ) ) {
$t_any_found = true;
}
}
if ( count( $t_filter['show_priority'] ) == 0 ) {
$t_any_found = true;
}
if ( !$t_any_found ) {
$t_clauses = array();
foreach( $t_filter['show_priority'] as $t_filter_member ) {
$c_show_priority = db_prepare_int( $t_filter_member );
array_push( $t_clauses, $c_show_priority );
}
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_bug_table.priority in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.priority=$t_clauses[0] )" );
}
}
# product build
$t_any_found = false;
foreach( $t_filter['show_build'] as $t_filter_member ) {
if ( ( META_FILTER_ANY == $t_filter_member ) && ( is_numeric( $t_filter_member ) ) ) {
$t_any_found = true;
}
}
if ( count( $t_filter['show_build'] ) == 0 ) {
$t_any_found = true;
}
if ( !$t_any_found ) {
$t_clauses = array();
foreach( $t_filter['show_build'] as $t_filter_member ) {
$t_filter_member = stripslashes( $t_filter_member );
if ( META_FILTER_NONE == $t_filter_member ) {
array_push( $t_clauses, "''" );
} else {
$c_show_build = db_prepare_string( $t_filter_member );
array_push( $t_clauses, "'$c_show_build'" );
}
}
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_bug_table.build in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.build=$t_clauses[0] )" );
}
}
# product version
if ( !_filter_is_any( $t_filter['show_version'] ) ) {
$t_clauses = array();
foreach( $t_filter['show_version'] as $t_filter_member ) {
$t_filter_member = stripslashes( $t_filter_member );
if ( META_FILTER_NONE == $t_filter_member ) {
array_push( $t_clauses, "''" );
} else {
$c_show_version = db_prepare_string( $t_filter_member );
array_push( $t_clauses, "'$c_show_version'" );
}
}
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_bug_table.version in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.version=$t_clauses[0] )" );
}
}
# profile
if ( !_filter_is_any( $t_filter['show_profile'] ) ) {
$t_clauses = array();
foreach( $t_filter['show_profile'] as $t_filter_member ) {
$t_filter_member = stripslashes( $t_filter_member );
if ( META_FILTER_NONE == $t_filter_member ) {
array_push( $t_clauses, "0" );
} else {
$c_show_profile = db_prepare_int( $t_filter_member );
array_push( $t_clauses, "$c_show_profile" );
}
}
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_bug_table.profile_id in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.profile_id=$t_clauses[0] )" );
}
}
# platform
if ( !_filter_is_any( $t_filter['platform'] ) ) {
$t_clauses = array();
foreach( $t_filter['platform'] as $t_filter_member ) {
$t_filter_member = stripslashes( $t_filter_member );
if ( META_FILTER_NONE == $t_filter_member ) {
array_push( $t_clauses, '' );
} else {
$c_platform = db_prepare_string( $t_filter_member );
array_push( $t_clauses, "'$c_platform'" );
}
}
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_bug_table.platform in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.platform = $t_clauses[0] )" );
}
}
# os
if ( !_filter_is_any( $t_filter['os'] ) ) {
$t_clauses = array();
foreach( $t_filter['os'] as $t_filter_member ) {
$t_filter_member = stripslashes( $t_filter_member );
if ( META_FILTER_NONE == $t_filter_member ) {
array_push( $t_clauses, '' );
} else {
$c_os = db_prepare_string( $t_filter_member );
array_push( $t_clauses, "'$c_os'" );
}
}
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_bug_table.os in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.os = $t_clauses[0] )" );
}
}
# os_build
if ( !_filter_is_any( $t_filter['os_build'] ) ) {
$t_clauses = array();
foreach( $t_filter['os_build'] as $t_filter_member ) {
$t_filter_member = stripslashes( $t_filter_member );
if ( META_FILTER_NONE == $t_filter_member ) {
array_push( $t_clauses, '' );
} else {
$c_os_build = db_prepare_string( $t_filter_member );
array_push( $t_clauses, "'$c_os_build'" );
}
}
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_bug_table.os_build in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.os_build = $t_clauses[0] )" );
}
}
# date filter
if ( ( 'on' == $t_filter['do_filter_by_date'] ) &&
is_numeric( $t_filter['start_month'] ) &&
is_numeric( $t_filter['start_day'] ) &&
is_numeric( $t_filter['start_year'] ) &&
is_numeric( $t_filter['end_month'] ) &&
is_numeric( $t_filter['end_day'] ) &&
is_numeric( $t_filter['end_year'] )
) {
$t_start_string = db_prepare_string( $t_filter['start_year'] . "-". $t_filter['start_month'] . "-" . $t_filter['start_day'] ." 00:00:00" );
$t_end_string = db_prepare_string( $t_filter['end_year'] . "-". $t_filter['end_month'] . "-" . $t_filter['end_day'] ." 23:59:59" );
array_push( $t_where_clauses, "($t_bug_table.date_submitted BETWEEN '$t_start_string' AND '$t_end_string' )" );
}
# fixed in version
if ( !_filter_is_any( $t_filter['fixed_in_version'] ) ) {
$t_clauses = array();
foreach( $t_filter['fixed_in_version'] as $t_filter_member ) {
$t_filter_member = stripslashes( $t_filter_member );
if ( META_FILTER_NONE == $t_filter_member ) {
array_push( $t_clauses, "''" );
} else {
$c_fixed_in_version = db_prepare_string( $t_filter_member );
array_push( $t_clauses, "'$c_fixed_in_version'" );
}
}
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_bug_table.fixed_in_version in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.fixed_in_version=$t_clauses[0] )" );
}
}
# target version
if ( !_filter_is_any( $t_filter['target_version'] ) ) {
$t_clauses = array();
foreach( $t_filter['target_version'] as $t_filter_member ) {
$t_filter_member = stripslashes( $t_filter_member );
if ( META_FILTER_NONE == $t_filter_member ) {
array_push( $t_clauses, "''" );
} else {
$c_target_version = db_prepare_string( $t_filter_member );
array_push( $t_clauses, "'$c_target_version'" );
}
}
#echo var_dump( $t_clauses ); exit;
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_bug_table.target_version in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.target_version=$t_clauses[0] )" );
}
}
# users monitoring a bug
$t_any_found = false;
foreach( $t_filter['user_monitor'] as $t_filter_member ) {
if ( ( META_FILTER_ANY == $t_filter_member ) || ( 0 === $t_filter_member ) ) {
$t_any_found = true;
}
}
if ( count( $t_filter['user_monitor'] ) == 0 ) {
$t_any_found = true;
}
if ( !$t_any_found ) {
$t_clauses = array();
$t_table_name = 'user_monitor';
array_push( $t_from_clauses, $t_bug_monitor_table );
array_push( $t_join_clauses, "LEFT JOIN $t_bug_monitor_table $t_table_name ON $t_table_name.bug_id = $t_bug_table.id" );
foreach( $t_filter['user_monitor'] as $t_filter_member ) {
$c_user_monitor = db_prepare_int( $t_filter_member );
if ( META_FILTER_MYSELF == $c_user_monitor ) {
array_push( $t_clauses, $c_user_id );
} else {
array_push( $t_clauses, $c_user_monitor );
}
}
if ( 1 < count( $t_clauses ) ) {
array_push( $t_where_clauses, "( $t_table_name.user_id in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_table_name.user_id=$t_clauses[0] )" );
}
}
# bug relationship
$t_any_found = false;
$c_rel_type = $t_filter['relationship_type'];
$c_rel_bug = $t_filter['relationship_bug'];
if ( -1 == $c_rel_type || 0 == $c_rel_bug) {
$t_any_found = true;
}
if ( !$t_any_found ) {
# use the complementary type
$t_comp_type = relationship_get_complementary_type( $c_rel_type );
$t_clauses = array();
$t_table_name = 'relationship';
array_push( $t_from_clauses, $t_bug_relationship_table );
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" );
array_push( $t_join_clauses, "LEFT JOIN $t_bug_relationship_table ${t_table_name}2 ON ${t_table_name}2.source_bug_id = $t_bug_table.id" );
// get reverse relationships
array_push( $t_clauses, "($t_table_name.relationship_type='$t_comp_type' AND $t_table_name.source_bug_id='$c_rel_bug')" );
array_push( $t_clauses, "($t_table_name"."2.relationship_type='$c_rel_type' AND $t_table_name"."2.destination_bug_id='$c_rel_bug')" );
array_push( $t_where_clauses, '('. implode( ' OR ', $t_clauses ) .')' );
}
# tags
$c_tag_string = trim( $t_filter['tag_string'] );
if ( !is_blank( $c_tag_string ) ) {
$t_tags = tag_parse_filters( $c_tag_string );
if ( count( $t_tags ) ) {
$t_tags_all = array();
$t_tags_any = array();
$t_tags_none = array();
foreach( $t_tags as $t_tag_row ) {
switch ( $t_tag_row['filter'] ) {
case 1:
$t_tags_all[] = $t_tag_row;
break;
case 0:
$t_tags_any[] = $t_tag_row;
break;
case -1:
$t_tags_none[] = $t_tag_row;
break;
}
}
if ( 0 < $t_filter['tag_select'] && tag_exists( $t_filter['tag_select'] ) ) {
$t_tags_any[] = tag_get( $t_filter['tag_select'] );
}
$t_bug_tag_table = config_get( 'mantis_bug_tag_table' );
if ( count( $t_tags_all ) ) {
$t_clauses = array();
foreach ( $t_tags_all as $t_tag_row ) {
array_push( $t_clauses, "$t_bug_table.id IN ( SELECT bug_id FROM $t_bug_tag_table WHERE $t_bug_tag_table.tag_id = $t_tag_row[id] )" );
}
array_push( $t_where_clauses, '('. implode( ' AND ', $t_clauses ) .')' );
}
if ( count( $t_tags_any ) ) {
$t_clauses = array();
foreach ( $t_tags_any as $t_tag_row ) {
array_push( $t_clauses, "$t_bug_tag_table.tag_id = $t_tag_row[id]" );
}
array_push( $t_where_clauses, "$t_bug_table.id IN ( SELECT bug_id FROM $t_bug_tag_table WHERE ( ". implode( ' OR ', $t_clauses ) .') )' );
}
if ( count( $t_tags_none ) ) {
$t_clauses = array();
foreach ( $t_tags_none as $t_tag_row ) {
array_push( $t_clauses, "$t_bug_tag_table.tag_id = $t_tag_row[id]" );
}
array_push( $t_where_clauses, "$t_bug_table.id NOT IN ( SELECT bug_id FROM $t_bug_tag_table WHERE ( ". implode( ' OR ', $t_clauses ) .') )' );
}
}
}
# custom field filters
if( ON == config_get( 'filter_by_custom_fields' ) ) {
# custom field filtering
# @@@ At the moment this gets the linked fields relating to the current project
# It should get the ones relating to the project in the filter or all projects
# if multiple projects.
$t_custom_fields = custom_field_get_linked_ids( $t_project_id );
foreach( $t_custom_fields as $t_cfid ) {
$t_custom_where_clause = '';
# Ignore all custom filters that are not set, or that are set to '' or "any"
$t_any_found = false;
foreach( $t_filter['custom_fields'][$t_cfid] as $t_filter_member ) {
if ( ( META_FILTER_ANY == $t_filter_member ) && ( is_numeric( $t_filter_member ) ) ) {
$t_any_found = true;
}
}
if ( !isset( $t_filter['custom_fields'][$t_cfid] ) ) {
$t_any_found = true;
}
if ( !$t_any_found ) {
$t_def = custom_field_get_definition( $t_cfid );
$t_table_name = $t_custom_field_string_table . '_' . $t_cfid;
# We need to filter each joined table or the result query will explode in dimensions
# Each custom field will result in a exponential growth like Number_of_Issues^Number_of_Custom_Fields
# and only after this process ends (if it is able to) the result query will be filtered
# by the WHERE clause and by the DISTINCT clause
$t_cf_join_clause = "LEFT JOIN $t_custom_field_string_table $t_table_name ON $t_table_name.bug_id = $t_bug_table.id AND $t_table_name.field_id = $t_cfid ";
if ($t_def['type'] == CUSTOM_FIELD_TYPE_DATE) {
switch ($t_filter['custom_fields'][$t_cfid][0]) {
case CUSTOM_FIELD_DATE_ANY:
break ;
case CUSTOM_FIELD_DATE_NONE:
array_push( $t_join_clauses, $t_cf_join_clause );
$t_custom_where_clause = '(( ' . $t_table_name . '.bug_id is null) OR ( ' . $t_table_name . '.value = 0)' ;
break ;
case CUSTOM_FIELD_DATE_BEFORE:
array_push( $t_join_clauses, $t_cf_join_clause );
$t_custom_where_clause = '(( ' . $t_table_name . '.value != 0 AND (' . $t_table_name . '.value+0) < ' . ($t_filter['custom_fields'][$t_cfid][2]) . ')' ;
break ;
case CUSTOM_FIELD_DATE_AFTER:
array_push( $t_join_clauses, $t_cf_join_clause );
$t_custom_where_clause = '( (' . $t_table_name . '.value+0) > ' . ($t_filter['custom_fields'][$t_cfid][1]+1) ;
break ;
default:
array_push( $t_join_clauses, $t_cf_join_clause );
$t_custom_where_clause = '( (' . $t_table_name . '.value+0) BETWEEN ' . $t_filter['custom_fields'][$t_cfid][1] . ' AND ' . $t_filter['custom_fields'][$t_cfid][2];
break ;
}
} else {
array_push( $t_join_clauses, $t_cf_join_clause );
$t_filter_array = array();
foreach( $t_filter['custom_fields'][$t_cfid] as $t_filter_member ) {
$t_filter_member = stripslashes( $t_filter_member );
if ( META_FILTER_NONE == $t_filter_member ) {
# coerce filter value if selecting META_FILTER_NONE so it will match empty fields
$t_filter_member = '';
# but also add those _not_ present in the custom field string table
array_push( $t_filter_array , "$t_bug_table.id NOT IN (SELECT bug_id FROM $t_custom_field_string_table WHERE field_id=$t_cfid)" );
}
switch( $t_def['type'] ) {
case CUSTOM_FIELD_TYPE_MULTILIST:
case CUSTOM_FIELD_TYPE_CHECKBOX:
array_push( $t_filter_array , db_helper_like( "$t_table_name.value", '%|' . db_prepare_string( $t_filter_member ) . '|%' ) );
break;
default:
array_push( $t_filter_array, "$t_table_name.value = '" . db_prepare_string( $t_filter_member ) . "'" );
}
}
$t_custom_where_clause .= '(' . implode( ' OR ', $t_filter_array );
}
if ( !is_blank( $t_custom_where_clause ) ) {
array_push( $t_where_clauses, $t_custom_where_clause . ')' );
}
}
}
}
$t_textsearch_where_clause = '';
$t_textsearch_wherejoin_clause = '';
# Simple Text Search - Thanks to Alan Knowles
if ( !is_blank( $t_filter['search'] ) ) {
$c_search = db_prepare_string( $t_filter['search'] );
$c_search_int = db_prepare_int( $t_filter['search'] );
$t_textsearch_where_clause = '(' . db_helper_like( 'summary', "%$c_search%" ) .
' OR ' . db_helper_like( "$t_bug_text_table.description", "%$c_search%" ) .
' OR ' . db_helper_like( "$t_bug_text_table.steps_to_reproduce", "%$c_search%" ) .
' OR ' . db_helper_like( "$t_bug_text_table.additional_information", "%$c_search%" ) .
" OR ( $t_bug_table.id = '$c_search_int' ) )";
$t_textsearch_wherejoin_clause = '(' . db_helper_like( 'summary', "%$c_search%" ) .
' OR ' . db_helper_like( "$t_bug_text_table.description", "%$c_search%" ) .
' OR ' . db_helper_like( "$t_bug_text_table.steps_to_reproduce", "%$c_search%" ) .
' OR ' . db_helper_like( "$t_bug_text_table.additional_information", "%$c_search%" ) .
' OR ' . db_helper_like( "$t_bug_table.id", "%$c_search%" ) .
' OR ' . db_helper_like( "$t_bugnote_text_table.note", "%$c_search%" ) . ' )';
array_push( $t_where_clauses, "($t_bug_text_table.id = $t_bug_table.bug_text_id)" );
$t_from_clauses = array( $t_bug_text_table, $t_project_table, $t_bug_table );
} else {
$t_from_clauses = array( $t_project_table, $t_bug_table );
}
$t_select = implode( ', ', array_unique( $t_select_clauses ) );
$t_from = 'FROM ' . implode( ', ', array_unique( $t_from_clauses ) );
$t_join = implode( ' ', $t_join_clauses );
if ( count( $t_where_clauses ) > 0 ) {
$t_where = 'WHERE ' . implode( ' AND ', $t_where_clauses );
} else {
$t_where = '';
}
# Possibly do two passes. First time, grab the IDs of issues that match the filters. Second time, grab the IDs of issues that
# have bugnotes that match the text search if necessary.
$t_id_array = array();
for ( $i = 0; $i < 2; $i++ ) {
$t_id_where = $t_where;
$t_id_join = $t_join;
if ( $i == 0 ) {
if ( !is_blank( $t_id_where ) && !is_blank( $t_textsearch_where_clause ) ) {
$t_id_where = $t_id_where . ' AND ' . $t_textsearch_where_clause;
}
} else if ( !is_blank( $t_textsearch_wherejoin_clause ) ) {
$t_id_where = $t_id_where . ' AND ' . $t_textsearch_wherejoin_clause;
$t_id_join = $t_id_join . " INNER JOIN $t_bugnote_table ON $t_bugnote_table.bug_id = $t_bug_table.id";
$t_id_join = $t_id_join . " INNER JOIN $t_bugnote_text_table ON $t_bugnote_text_table.id = $t_bugnote_table.bugnote_text_id";
}
$query = "SELECT DISTINCT $t_bug_table.id AS id
$t_from
$t_id_join
$t_id_where";
if ( ( $i == 0 ) || ( !is_blank( $t_textsearch_wherejoin_clause ) ) ) {
$result = db_query( $query );
$row_count = db_num_rows( $result );
for ( $j=0; $j < $row_count; $j++ ) {
$row = db_fetch_array( $result );
$t_id_array[] = db_prepare_int ( $row['id'] );
}
}
}
$t_id_array = array_unique( $t_id_array );
# Get the total number of bugs that meet the criteria.
$bug_count = count( $t_id_array );
$rows = array();
if ( $bug_count > 0 ) {
$t_where = "WHERE $t_bug_table.id in (" . implode( ", ", $t_id_array ) . ")";
} else {
return $rows;
}
$t_from = 'FROM ' . $t_bug_table;
# write the value back in case the caller wants to know
$p_bug_count = $bug_count;
if ( null === $p_per_page ) {
$p_per_page = (int)$t_filter['per_page'];
} else if ( -1 == $p_per_page ) {
$p_per_page = $bug_count;
}
# Guard against silly values of $f_per_page.
if ( 0 == $p_per_page ) {
$p_per_page = $bug_count; // 0 - means show all
}
$p_per_page = (int)abs( $p_per_page );
# Use $bug_count and $p_per_page to determine how many pages
# to split this list up into.
# For the sake of consistency have at least one page, even if it
# is empty.
$t_page_count = ceil($bug_count / $p_per_page);
if ( $t_page_count < 1 ) {
$t_page_count = 1;
}
# write the value back in case the caller wants to know
$p_page_count = $t_page_count;
# Make sure $p_page_number isn't past the last page.
if ( $p_page_number > $t_page_count ) {
$p_page_number = $t_page_count;
}
# Make sure $p_page_number isn't before the first page
if ( $p_page_number < 1 ) {
$p_page_number = 1;
}
# Now add the rest of the criteria i.e. sorting, limit.
# if sort is blank then default the sort and direction. This is to fix the
# symptoms of #3953. Note that even if the main problem is fixed, we may
# have to keep this code for a while to handle filters saved with this blank field.
if ( is_blank( $t_filter['sort'] ) ) {
$t_filter['sort'] = 'last_updated';
$t_filter['dir'] = 'DESC';
}
$t_order_array = array();
$t_sort_fields = split( ',', $t_filter['sort'] );
$t_dir_fields = split( ',', $t_filter['dir'] );
if ( ( 'on' == $t_filter['sticky_issues'] ) && ( NULL !== $p_show_sticky ) ) {
$t_order_array[] = "sticky DESC";
}
$t_join = '';
for ( $i=0; $i < count( $t_sort_fields ); $i++ ) {
$c_sort = db_prepare_string( $t_sort_fields[$i] );
if ( ! in_array( $t_sort_fields[$i], array_slice( $t_sort_fields, $i + 1) ) ) {
# if sorting by a custom field
if ( strpos( $c_sort, 'custom_' ) === 0 ) {
$t_custom_field = substr( $c_sort, strlen( 'custom_' ) );
$t_custom_field_id = custom_field_get_id_from_name( $t_custom_field );
$t_join .= " LEFT JOIN $t_custom_field_string_table ON ( ( $t_custom_field_string_table.bug_id = $t_bug_table.id ) AND ( $t_custom_field_string_table.field_id = $t_custom_field_id ) )";
$c_sort = "$t_custom_field_string_table.value";
$t_select_clauses[] = "$t_custom_field_string_table.value";
}
if ( 'DESC' == $t_dir_fields[$i] ) {
$c_dir = 'DESC';
} else {
$c_dir = 'ASC';
}
$t_order_array[] = "$c_sort $c_dir";
}
}
# add basic sorting if necessary
if ( ! in_array( 'last_updated', $t_sort_fields ) ) {
$t_order_array[] = 'last_updated DESC';
}
if ( ! in_array( 'date_submitted', $t_sort_fields ) ) {
$t_order_array[] = 'date_submitted DESC';
}
$t_order = " ORDER BY " . implode( ', ', $t_order_array );
$t_select = implode( ', ', array_unique( $t_select_clauses ) );
$query2 = "SELECT DISTINCT $t_select
$t_from
$t_join
$t_where
$t_order";
# Figure out the offset into the db query
#
# for example page number 1, per page 5:
# t_offset = 0
# for example page number 2, per page 5:
# t_offset = 5
$c_per_page = db_prepare_int( $p_per_page );
$c_page_number = db_prepare_int( $p_page_number );
$t_offset = ( ( $c_page_number - 1 ) * $c_per_page );
# perform query
$result2 = db_query( $query2, $c_per_page, $t_offset );
$row_count = db_num_rows( $result2 );
$t_id_array_lastmod = array();
for ( $i=0 ; $i < $row_count ; $i++ ) {
$row = db_fetch_array( $result2 );
$t_id_array_lastmod[] = db_prepare_int ( $row['id'] );
$row['date_submitted'] = db_unixtimestamp ( $row['date_submitted'] );
$row['last_updated'] = db_unixtimestamp ( $row['last_updated'] );
array_push( $rows, $row );
}
$t_id_array_lastmod = array_unique( $t_id_array_lastmod );
// paulr: it should be impossible for t_id_array_lastmod to be array():
// that would imply that $t_id_array is null which aborts this function early
//if ( count( $t_id_array_lastmod ) > 0 ) {
$t_where = "WHERE $t_bugnote_table.bug_id in (" . implode( ", ", $t_id_array_lastmod ) . ")";
$query3 = "SELECT DISTINCT bug_id,MAX(last_modified) as last_modified, COUNT(last_modified) as count FROM $t_bugnote_table $t_where GROUP BY bug_id";
# perform query
$result3 = db_query( $query3 );
$row_count = db_num_rows( $result3 );
for ( $i=0 ; $i < $row_count ; $i++ ) {
$row = db_fetch_array( $result3 );
$t_stats[ $row['bug_id'] ] = $row;
}
foreach($rows as $row) {
if( !isset( $t_stats[ $row['id'] ] ) ) {
bug_cache_database_result( $row, false );
} else {
bug_cache_database_result( $row, $t_stats[ $row['id'] ] );
}
}
return $rows;
}
# --------------------
# return true if the filter cookie exists and is of the correct version,
# false otherwise
function filter_is_cookie_valid() {
$t_view_all_cookie_id = gpc_get_cookie( config_get( 'view_all_cookie' ), '' );
$t_view_all_cookie = filter_db_get_filter( $t_view_all_cookie_id );
# check to see if the cookie does not exist
if ( is_blank( $t_view_all_cookie ) ) {
return false;
}
# check to see if new cookie is needed
$t_setting_arr = explode( '#', $t_view_all_cookie, 2 );
if ( ( $t_setting_arr[0] == 'v1' ) ||
( $t_setting_arr[0] == 'v2' ) ||
( $t_setting_arr[0] == 'v3' ) ||
( $t_setting_arr[0] == 'v4' ) ) {
return false;
}
# We shouldn't need to do this anymore, as filters from v5 onwards should cope with changing
# filter indices dynamically
$t_filter_cookie_arr = array();
if ( isset( $t_setting_arr[1] ) ) {
$t_filter_cookie_arr = unserialize( $t_setting_arr[1] );
} else {
return false;
}
if ( $t_filter_cookie_arr['_version'] != config_get( 'cookie_version' ) ) {
return false;
}
return true;
}
# --------------------
# return filter array if supplied serialized filter is valid, otherwise false.otherwise
function filter_deserialize( $p_serialized_filter ) {
if ( is_blank( $p_serialized_filter ) ) {
return false;
}
# check to see if new cookie is needed
$t_setting_arr = explode( '#', $p_serialized_filter, 2 );
if ( ( $t_setting_arr[0] == 'v1' ) ||
( $t_setting_arr[0] == 'v2' ) ||
( $t_setting_arr[0] == 'v3' ) ||
( $t_setting_arr[0] == 'v4' ) ) {
# these versions can't be salvaged, they are too old to update
return false;
}
# We shouldn't need to do this anymore, as filters from v5 onwards should cope with changing
# filter indices dynamically
$t_filter_array = array();
if ( isset( $t_setting_arr[1] ) ) {
$t_filter_array = unserialize( $t_setting_arr[1] );
} else {
return false;
}
if ( $t_filter_array['_version'] != config_get( 'cookie_version' ) ) {
# if the version is not new enough, update it using defaults
return filter_ensure_valid_filter( $t_filter_array );
}
return $t_filter_array;
}
# --------------------
# Mainly based on filter_draw_selection_area2() but adds the support for the collapsible
# filter display.
function filter_draw_selection_area( $p_page_number, $p_for_screen = true )
{
collapse_open( 'filter' );
filter_draw_selection_area2( $p_page_number, $p_for_screen, true );
collapse_closed( 'filter' );
filter_draw_selection_area2( $p_page_number, $p_for_screen, false );
collapse_end( 'filter' );
}
# --------------------
# Will print the filter selection area for both the bug list view screen, as well
# as the bug list print screen. This function was an attempt to make it easier to
# add new filters and rearrange them on screen for both pages.
function filter_draw_selection_area2( $p_page_number, $p_for_screen = true, $p_expanded = true )
{
$t_form_name_suffix = $p_expanded ? '_open' : '_closed';
$t_filter = current_user_get_bug_filter();
$t_filter = filter_ensure_valid_filter( $t_filter );
$t_project_id = helper_get_current_project();
$t_page_number = (int) $p_page_number;
$t_view_type = $t_filter['_view_type'];
$t_tdclass = 'small-caption';
$t_trclass = 'row-category2';
$t_action = 'view_all_set.php?f=3';
if ( $p_for_screen == false ) {
$t_tdclass = 'print';
$t_trclass = '';
$t_action = 'view_all_set.php';
}
?>