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 ),
'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 $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 ) {
$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 ) {
$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_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();
if ( ALL_PROJECTS == $t_project_id ) {
if ( !user_is_administrator( $t_user_id ) ) {
$t_topprojects = $t_projects = user_get_accessible_projects( $t_user_id );
foreach ( $t_topprojects as $t_project ) {
$t_projects = array_merge( $t_projects, user_get_all_accessible_subprojects( $t_user_id, $t_project ) );
}
$t_projects = array_unique( $t_projects );
if ( 0 == count( $t_projects ) ) {
return array(); # no accessible projects, return an empty array
} else if ( 1 == count( $t_projects ) ) {
$t_project = $t_projects[0];
array_push( $t_where_clauses, "( $t_bug_table.project_id=$t_project )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.project_id in (". implode( ', ', $t_projects ) . ") )" );
}
}
} else {
access_ensure_project_level( VIEWER, $t_project_id, $t_user_id );
$t_projects = user_get_all_accessible_subprojects( $t_user_id, $t_project_id );
$t_projects[] = $t_project_id;
$t_projects = array_unique( $t_projects );
if ( 1 == count( $t_projects ) ) {
$t_project = $t_projects[0];
array_push( $t_where_clauses, "( $t_bug_table.project_id=$t_project )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.project_id in (". implode( ', ', $t_projects ) . ") )" );
}
}
# private bug selection
if ( !access_has_project_level( config_get( 'private_bug_threshold' ), $t_project_id, $t_user_id ) ) {
$t_public = VS_PUBLIC;
$t_private = VS_PRIVATE;
switch ( $t_filter['view_state'] ) {
case VS_PUBLIC:
array_push( $t_where_clauses, "($t_bug_table.view_state='$t_public')" );
break;
case VS_PRIVATE:
array_push( $t_where_clauses, "($t_bug_table.view_state='$t_private' AND $t_bug_table.reporter_id='$t_user_id')" );
break;
case META_FILTER_ANY:
default:
array_push( $t_where_clauses, "($t_bug_table.view_state='$t_public' OR $t_bug_table.reporter_id='$t_user_id')" );
break;
}
} else {
$t_view_state = db_prepare_int( $t_filter['view_state'] );
if ( ( $t_filter['view_state'] !== META_FILTER_ANY ) && ( !is_blank( $t_filter['view_state'] ) ) ) {
array_push( $t_where_clauses, "($t_bug_table.view_state='$t_view_state')" );
}
}
# 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 ) ) {
array_push( $t_where_clauses, "( $t_bug_table.reporter_id in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.reporter_id=$t_clauses[0] )" );
}
}
# 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 ) ) {
array_push( $t_where_clauses, "( $t_bug_table.handler_id in (". implode( ', ', $t_clauses ) .") )" );
} else {
array_push( $t_where_clauses, "( $t_bug_table.handler_id=$t_clauses[0] )" );
}
}
# category
$t_any_found = false;
foreach( $t_filter['show_category'] 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_category'] ) == 0 ) {
$t_any_found = true;
}
if ( !$t_any_found ) {
$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
$t_any_found = false;
foreach( $t_filter['show_version'] 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_version'] ) == 0 ) {
$t_any_found = true;
}
if ( !$t_any_found ) {
$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
$t_any_found = false;
foreach( $t_filter['show_profile'] 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_profile'] ) == 0 ) {
$t_any_found = true;
}
if ( !$t_any_found ) {
$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] )" );
}
}
# 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
$t_any_found = false;
foreach( $t_filter['fixed_in_version'] as $t_filter_member ) {
if ( ( META_FILTER_ANY == $t_filter_member ) && ( is_numeric( $t_filter_member ) ) ) {
$t_any_found = true;
}
}
if ( count( $t_filter['fixed_in_version'] ) == 0 ) {
$t_any_found = true;
}
if ( !$t_any_found ) {
$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] )" );
}
}
# 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
$c_rel_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" );
// get reverse relationships
if ( $c_rel_type == 1 ) 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" );
array_push( $t_clauses, "($t_table_name.relationship_type='$c_rel_type' AND $t_table_name.source_bug_id='$c_rel_bug')" );
// get reverse relationships
if ( $c_rel_type == 1 ) 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 ) .')' );
}
# custom field filters
if( ON == config_get( 'filter_by_custom_fields' ) ) {
# custom field filtering
$t_custom_fields = custom_field_get_linked_ids( $t_project_id );
foreach( $t_custom_fields as $t_cfid ) {
$t_first_time = true;
$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 . '.field_id = ' . $t_cfid . ' AND (' . $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 . '.field_id = ' . $t_cfid . ' AND (' . $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 );
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
$t_filter_member = '';
}
if( $t_first_time ) {
$t_first_time = false;
$t_custom_where_clause = '(';
} else {
$t_custom_where_clause .= ' OR ';
}
$t_custom_where_clause .= "$t_table_name.value ";
switch( $t_def['type'] ) {
case CUSTOM_FIELD_TYPE_MULTILIST:
case CUSTOM_FIELD_TYPE_CHECKBOX:
$t_custom_where_clause .= "LIKE '%|";
$t_custom_where_clause_closing = "|%'";
break;
default:
$t_custom_where_clause .= "= '";
$t_custom_where_clause_closing = "'";
}
$t_custom_where_clause .= db_prepare_string( $t_filter_member );
$t_custom_where_clause .= $t_custom_where_clause_closing;
}
}
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 = "((summary LIKE '%$c_search%')
OR ($t_bug_text_table.description LIKE '%$c_search%')
OR ($t_bug_text_table.steps_to_reproduce LIKE '%$c_search%')
OR ($t_bug_text_table.additional_information LIKE '%$c_search%')
OR ($t_bug_table.id = '$c_search_int'))";
$t_textsearch_wherejoin_clause = "((summary LIKE '%$c_search%')
OR ($t_bug_text_table.description LIKE '%$c_search%')
OR ($t_bug_text_table.steps_to_reproduce LIKE '%$c_search%')
OR ($t_bug_text_table.additional_information LIKE '%$c_search%')
OR ($t_bug_table.id LIKE '%$c_search%')
OR ($t_bugnote_text_table.note LIKE '%$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 );
if ( count( $t_id_array ) > 0 ) {
$t_where = "WHERE $t_bug_table.id in (" . implode( ", ", $t_id_array ) . ")";
} else {
$t_where = "WHERE 1 != 1";
}
$t_from = 'FROM ' . $t_bug_table;
# Get the total number of bugs that meet the criteria.
$bug_count = count( $t_id_array );
# 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 = 1;
}
$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";
}
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 );
$rows = array();
for ( $i=0 ; $i < $row_count ; $i++ ) {
$row = db_fetch_array( $result2 );
$row['date_submitted'] = db_unixtimestamp ( $row['date_submitted'] );
$row['last_updated'] = db_unixtimestamp ( $row['last_updated'] );
array_push( $rows, $row );
bug_add_to_cache( $row );
}
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 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';
}
?>