function reminder_print_status_option_list($p_name) { $t_enum_values = MantisEnum::getValues(config_get('status_enum_string')); $t_selection = plugin_config_get($p_name); echo '<select name="' . $p_name . '[]" multiple="multiple" size="' . count($t_enum_values) . '">'; foreach ($t_enum_values as $t_key) { $t_elem2 = get_enum_element('status', $t_key); echo '<option value="' . $t_key . '"'; reminder_check_selected($t_selection, $t_key); echo '>' . $t_elem2 . '</option>'; } echo '</select>'; }
/** * Return html for a row * @param string $p_caption Caption. * @param integer $p_access_level Access level. * @return string */ function get_capability_row($p_caption, $p_access_level) { $t_access_levels = MantisEnum::getValues(config_get('access_levels_enum_string')); $t_output = '<tr><td>' . string_display($p_caption) . '</td>'; foreach ($t_access_levels as $t_access_level) { if ($t_access_level >= (int) $p_access_level) { $t_value = '<img src="images/ok.gif" width="20" height="15" alt="X" title="X" />'; } else { $t_value = ' '; } $t_output .= '<td class="center">' . $t_value . '</td>'; } $t_output .= '</tr>' . "\n"; return $t_output; }
function get_status_option_list_plugin($p_user_auth = 0, $p_current_value = 0, $p_show_current = true, $p_add_close = false, $p_project_id = ALL_PROJECTS) { $t_config_var_value = config_get('status_enum_string', null, null, $p_project_id); $t_enum_workflow = config_get('status_enum_workflow', null, null, $p_project_id); $t_enum_values = MantisEnum::getValues($t_config_var_value); $t_enum_list = array(); foreach ($t_enum_values as $t_enum_value) { if (($p_show_current || $p_current_value != $t_enum_value) && access_compare_level($p_user_auth, access_get_status_threshold($t_enum_value, $p_project_id))) { $t_enum_list[$t_enum_value] = get_enum_element('status', $t_enum_value); } } if ($p_show_current) { $t_enum_list[$p_current_value] = get_enum_element('status', $p_current_value); } if ($p_add_close && access_compare_level($p_current_value, config_get('bug_resolved_status_threshold', null, null, $p_project_id))) { $t_closed = config_get('bug_closed_status_threshold', null, null, $p_project_id); if ($p_show_current || $p_current_value != $t_closed) { $t_enum_list[$t_closed] = get_enum_element('status', $t_closed); } } return $t_enum_list; }
/** * Explode a configuration enumeration name into an array structure that can * be safely converted into an ObjectRef structure. * * @param string $p_enumeration_name The name of the enumeration to convert * @return Array The converted enumeration */ function mci_explode_to_objectref($p_enumeration_name) { $t_config_var_name = $p_enumeration_name . '_enum_string'; $t_config_var_value = config_get($t_config_var_name); $t_translated_values = lang_get($t_config_var_name, mci_get_user_lang(auth_get_current_user_id())); $t_enum_values = MantisEnum::getValues($t_config_var_value); $t_result = array(); foreach ($t_enum_values as $t_key) { $t_translated = MantisEnum::getLocalizedLabel($t_config_var_value, $t_translated_values, $t_key); $t_result[] = array('id' => $t_key, 'name' => $t_translated); } return $t_result; }
/** * HTML for Row * * @param string $p_caption Caption. * @param string $p_message_type Message type. * @return void */ function get_capability_row_for_email($p_caption, $p_message_type) { $t_access_levels = MantisEnum::getValues(config_get('access_levels_enum_string')); echo '<tr><td>' . string_display($p_caption) . '</td>' . "\n"; echo ' <td' . color_notify_flag($p_message_type, 'reporter') . '>' . show_notify_flag($p_message_type, 'reporter') . '</td>' . "\n"; echo ' <td' . color_notify_flag($p_message_type, 'handler') . '>' . show_notify_flag($p_message_type, 'handler') . '</td>' . "\n"; echo ' <td' . color_notify_flag($p_message_type, 'monitor') . '>' . show_notify_flag($p_message_type, 'monitor') . '</td>' . "\n"; echo ' <td' . color_notify_flag($p_message_type, 'bugnotes') . '>' . show_notify_flag($p_message_type, 'bugnotes') . '</td>' . "\n"; echo ' <td' . color_notify_flag($p_message_type, 'category') . '>' . show_notify_flag($p_message_type, 'category') . '</td>' . "\n"; foreach ($t_access_levels as $t_access_level) { echo ' <td' . color_threshold_flag($t_access_level, $p_message_type) . '>' . show_notify_threshold($t_access_level, $p_message_type) . '</td>' . "\n"; } echo '</tr>' . "\n"; }
/** * section header * @param string $p_section_name Section name. * @return void */ function section_begin($p_section_name) { $t_enum_statuses = MantisEnum::getValues(config_get('status_enum_string')); echo '<div class="form-container">' . "\n"; echo '<h2>' . $p_section_name . '</h2>' . "\n"; echo "\t<table>\n"; echo "\t\t<thead>\n"; echo "\t\t" . '<tr class="row-category2">' . "\n"; echo "\t\t\t" . '<th class="form-title width30" rowspan="2">' . lang_get('current_status') . '</th>' . "\n"; echo "\t\t\t" . '<th class="form-title" style="text-align:center" colspan="' . (count($t_enum_statuses) + 1) . '">' . lang_get('next_status') . '</th>'; echo "\n\t\t" . '</tr>' . "\n"; echo "\t\t" . '<tr class="row-category2">' . "\n"; foreach ($t_enum_statuses as $t_status) { echo "\t\t\t" . '<th class="form-title" style="text-align:center"> ' . string_no_break(MantisEnum::getLabel(lang_get('status_enum_string'), $t_status)) . ' </th>' . "\n"; } echo "\t\t\t" . '<th class="form-title" style="text-align:center">' . lang_get('custom_field_default_value') . '</th>' . "\n"; echo "\t\t" . '</tr>' . "\n"; echo "\t\t</thead>\n"; echo "\t\t<tbody>\n"; }
/** * Print reporter effectiveness report * * @param string $p_severity_enum_string Severity enumeration string. * @param string $p_resolution_enum_string Resolution enumeration string. * @return void */ function summary_print_reporter_effectiveness($p_severity_enum_string, $p_resolution_enum_string) { $t_reporter_summary_limit = config_get('reporter_summary_limit'); $t_project_id = helper_get_current_project(); $t_severity_multipliers = config_get('severity_multipliers'); $t_resolution_multipliers = config_get('resolution_multipliers'); # Get the severity values to use $c_sev_s = MantisEnum::getValues($p_severity_enum_string); $t_enum_sev_count = count($c_sev_s); # Get the resolution values to use $c_res_s = MantisEnum::getValues($p_resolution_enum_string); # Checking if it's a per project statistic or all projects $t_specific_where = helper_project_specific_where($t_project_id); if (' 1<>1' == $t_specific_where) { return; } # Get all of the bugs and split them up into an array $t_query = 'SELECT COUNT(id) as bugcount, reporter_id, resolution, severity FROM {bug} WHERE ' . $t_specific_where . ' GROUP BY reporter_id, resolution, severity'; $t_result = db_query($t_query); $t_reporter_ressev_arr = array(); $t_reporter_bugcount_arr = array(); $t_arr = db_fetch_array($t_result); while ($t_arr) { if (!isset($t_reporter_ressev_arr[$t_arr['reporter_id']])) { $t_reporter_ressev_arr[$t_arr['reporter_id']] = array(); $t_reporter_bugcount_arr[$t_arr['reporter_id']] = 0; } if (!isset($t_reporter_ressev_arr[$t_arr['reporter_id']][$t_arr['severity']])) { $t_reporter_ressev_arr[$t_arr['reporter_id']][$t_arr['severity']] = array(); $t_reporter_ressev_arr[$t_arr['reporter_id']][$t_arr['severity']]['total'] = 0; } if (!isset($t_reporter_ressev_arr[$t_arr['reporter_id']][$t_arr['severity']][$t_arr['resolution']])) { $t_reporter_ressev_arr[$t_arr['reporter_id']][$t_arr['severity']][$t_arr['resolution']] = 0; } $t_reporter_ressev_arr[$t_arr['reporter_id']][$t_arr['severity']][$t_arr['resolution']] += $t_arr['bugcount']; $t_reporter_ressev_arr[$t_arr['reporter_id']][$t_arr['severity']]['total'] += $t_arr['bugcount']; $t_reporter_bugcount_arr[$t_arr['reporter_id']] += $t_arr['bugcount']; $t_arr = db_fetch_array($t_result); } # Sort our total bug count array so that the reporters with the highest number of bugs are listed first, arsort($t_reporter_bugcount_arr); $t_row_count = 0; # We now have a multi dimensional array of users, resolutions and severities, with the # value of each resolution and severity for each user foreach ($t_reporter_bugcount_arr as $t_reporter_id => $t_total_user_bugs) { # Limit the number of reporters listed if ($t_row_count > $t_reporter_summary_limit) { break; } # Only print reporters who have reported at least one bug. This helps # prevent divide by zeroes, showing reporters not on this project, and showing # users that aren't actually reporters... if ($t_total_user_bugs > 0) { $t_arr2 = $t_reporter_ressev_arr[$t_reporter_id]; echo '<tr>'; $t_row_count++; echo '<td>'; echo string_display_line(user_get_name($t_reporter_id)); echo '</td>'; $t_total_severity = 0; $t_total_errors = 0; for ($j = 0; $j < $t_enum_sev_count; $j++) { if (!isset($t_arr2[$c_sev_s[$j]])) { continue; } $t_sev_bug_count = $t_arr2[$c_sev_s[$j]]['total']; $t_sev_mult = 1; if ($t_severity_multipliers[$c_sev_s[$j]]) { $t_sev_mult = $t_severity_multipliers[$c_sev_s[$j]]; } if ($t_sev_bug_count > 0) { $t_total_severity += $t_sev_bug_count * $t_sev_mult; } foreach ($t_resolution_multipliers as $t_res => $t_res_mult) { if (isset($t_arr2[$c_sev_s[$j]][$t_res])) { $t_total_errors += $t_sev_mult * $t_res_mult; } } } echo '<td class="right">' . $t_total_severity . '</td>'; echo '<td class="right">' . $t_total_errors . '</td>'; printf('<td class="right">%d</td>', $t_total_severity - $t_total_errors); echo '</tr>'; } } }
</thead> <?php summary_print_reporter_resolution(config_get('resolution_enum_string')); ?> </table> <!-- DEVELOPER BY RESOLUTION --> <table> <thead> <tr class="row-category2"> <th><?php echo lang_get('developer_by_resolution'); ?> </th> <?php $t_resolutions = MantisEnum::getValues(config_get('resolution_enum_string')); foreach ($t_resolutions as $t_resolution) { echo '<td class="right">', get_enum_element('resolution', $t_resolution), "</td>\n"; } echo '<td class="right">', lang_get('percentage_fixed'), "</td>\n"; ?> </tr> </thead> <?php summary_print_developer_resolution(config_get('resolution_enum_string')); ?> </table> </div> </div>
/** * Print the legend for the status percentage * @return void */ function html_status_percentage_legend() { $t_status_percents = get_percentage_by_status(); $t_status_enum_string = config_get('status_enum_string'); $t_enum_values = MantisEnum::getValues($t_status_enum_string); $t_enum_count = count($t_enum_values); $t_bug_count = array_sum($t_status_percents); if ($t_bug_count > 0) { echo '<br />'; echo '<table class="width100" cellspacing="1">'; echo '<tr>'; echo '<td class="form-title" colspan="' . $t_enum_count . '">' . lang_get('issue_status_percentage') . '</td>'; echo '</tr>'; echo '<tr>'; foreach ($t_enum_values as $t_status) { $t_percent = isset($t_status_percents[$t_status]) ? $t_status_percents[$t_status] : 0; if ($t_percent > 0) { $t_class = html_get_status_css_class($t_status); echo '<td class="small-caption-center ' . $t_class . ' ' . str_replace('color', 'percentage', $t_class) . '">' . $t_percent . '%</td>'; } } echo '</tr>'; echo '</table>'; } }
/** * Print the legend for the status percentage * @return null */ function html_status_percentage_legend() { $t_mantis_bug_table = db_get_table('mantis_bug_table'); $t_project_id = helper_get_current_project(); $t_user_id = auth_get_current_user_id(); # checking if it's a per project statistic or all projects $t_specific_where = helper_project_specific_where($t_project_id, $t_user_id); $query = "SELECT status, COUNT(*) AS number\n\t\t\t\tFROM {$t_mantis_bug_table}\n\t\t\t\tWHERE {$t_specific_where}"; if (!access_has_project_level(config_get('private_bug_threshold'))) { $query .= ' AND view_state < ' . VS_PRIVATE; } $query .= ' GROUP BY status'; $result = db_query_bound($query); $t_bug_count = 0; $t_status_count_array = array(); while ($row = db_fetch_array($result)) { $t_status_count_array[$row['status']] = $row['number']; $t_bug_count += $row['number']; } $t_enum_values = MantisEnum::getValues(config_get('status_enum_string')); $enum_count = count($t_enum_values); if ($t_bug_count > 0) { echo '<br />'; echo '<table class="width100" cellspacing="1">'; echo '<tr>'; echo '<td class="form-title" colspan="' . $enum_count . '">' . lang_get('issue_status_percentage') . '</td>'; echo '</tr>'; echo '<tr>'; foreach ($t_enum_values as $t_status) { $t_color = get_status_color($t_status); if (!isset($t_status_count_array[$t_status])) { $t_status_count_array[$t_status] = 0; } $width = round($t_status_count_array[$t_status] / $t_bug_count * 100); if ($width > 0) { echo "<td class=\"small-caption-center\" width=\"{$width}%\" bgcolor=\"{$t_color}\">{$width}%</td>"; } } echo '</tr>'; echo '</table>'; } }
log_event(LOG_FILTERING, 'view_all_set.php: View state (simple/advanced)'); $t_setting_arr['_view_type'] = $f_view_type; break; # does nothing. catch all case # does nothing. catch all case default: log_event(LOG_FILTERING, 'view_all_set.php: default - do nothing'); break; } $tc_setting_arr = filter_ensure_valid_filter($t_setting_arr); /** * Remove any statuses that should be excluded by the hide_status field */ if ($f_view_type == "advanced") { if ($tc_setting_arr[FILTER_PROPERTY_HIDE_STATUS][0] > 0) { $t_statuses = MantisEnum::getValues(config_get('status_enum_string')); foreach ($t_statuses as $t_key => $t_val) { if ($t_val < $tc_setting_arr[FILTER_PROPERTY_HIDE_STATUS][0]) { $t_keep_statuses[$t_key] = $t_val; } } $tc_setting_arr[FILTER_PROPERTY_STATUS] = $t_keep_statuses; } } /** * If a status is selected in the status and the hide status field, remove it from * hide status */ if ($f_view_type == "simple" && $tc_setting_arr[FILTER_PROPERTY_HIDE_STATUS][0] > 0) { foreach ($tc_setting_arr[FILTER_PROPERTY_STATUS] as $t_key => $t_val) { if ($tc_setting_arr[FILTER_PROPERTY_STATUS][$t_key] == $tc_setting_arr[FILTER_PROPERTY_HIDE_STATUS][0]) {
/** * Tests getValues() method. */ public function testGetValues() { $this->assertEquals(array(10, 25, 40, 55, 70, 90), MantisEnum::getValues(MantisEnumTest::ACCESS_LEVELS_ENUM, 10)); $this->assertEquals(array(), MantisEnum::getValues(MantisEnumTest::EMPTY_ENUM, 10)); }
function section_begin($p_section_name) { $t_enum_statuses = MantisEnum::getValues(config_get('status_enum_string')); echo '<table class="width100">'; echo '<tr><td class="form-title-caps" colspan="' . (count($t_enum_statuses) + 2) . '">' . $p_section_name . '</td></tr>' . "\n"; echo '<tr><td class="form-title" width="30%" rowspan="2">' . lang_get('current_status') . '</td>'; echo '<td class="form-title" style="text-align:center" colspan="' . (count($t_enum_statuses) + 1) . '">' . lang_get('next_status') . '</td></tr>'; echo "\n<tr>"; foreach ($t_enum_statuses as $t_status) { echo '<td class="form-title" style="text-align:center"> ' . string_no_break(MantisEnum::getLabel(lang_get('status_enum_string'), $t_status)) . ' </td>'; } echo '<td class="form-title" style="text-align:center">' . lang_get('custom_field_default_value') . '</td>'; echo '</tr>' . "\n"; }
/** * @todo 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. * * @param int $p_page_number the page you want to see (set to the actual page on return) * @param int $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 * @param int $p_page_count you don't need to give a value here, the number of pages will be stored here on return * @param int $p_bug_count you don't need to give a value here, the number of bugs will be stored here on return * @param mixed $p_custom_filter Filter to use. * @param int $p_project_id project id to use in filtering. * @param int $p_user_id user id to use as current user when filtering. * @param bool $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, 'START NEW FILTER QUERY'); $t_bug_table = db_get_table('mantis_bug_table'); $t_bug_text_table = db_get_table('mantis_bug_text_table'); $t_bugnote_table = db_get_table('mantis_bugnote_table'); $t_category_table = db_get_table('mantis_category_table'); $t_custom_field_string_table = db_get_table('mantis_custom_field_string_table'); $t_bugnote_text_table = db_get_table('mantis_bugnote_text_table'); $t_project_table = db_get_table('mantis_project_table'); $t_bug_monitor_table = db_get_table('mantis_bug_monitor_table'); $t_limit_reporters = config_get('limit_reporters'); $t_bug_relationship_table = db_get_table('mantis_bug_relationship_table'); $t_report_bug_threshold = config_get('report_bug_threshold'); $t_where_param_count = 0; $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 = " . db_param(), "{$t_project_table}.id = {$t_bug_table}.project_id"); $t_where_params = array(1); $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, 'Simple Filter'); $t_project_ids = array($t_project_id); $t_include_sub_projects = true; } else { log_event(LOG_FILTERING, 'Advanced Filter'); if (!is_array($t_filter[FILTER_PROPERTY_PROJECT_ID])) { $t_project_ids = array(db_prepare_int($t_filter[FILTER_PROPERTY_PROJECT_ID])); } else { $t_project_ids = array_map('db_prepare_int', $t_filter[FILTER_PROPERTY_PROJECT_ID]); } $t_include_sub_projects = count($t_project_ids) == 1 && ($t_project_ids[0] == META_FILTER_CURRENT || $t_project_ids[0] == ALL_PROJECTS); } log_event(LOG_FILTERING, 'project_ids = @P' . implode(', @P', $t_project_ids)); log_event(LOG_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, '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, '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, 'Getting sub-projects for project id @P' . $t_pid); $t_subproject_ids = user_get_all_accessible_subprojects($t_user_id, $t_pid); if (!$t_subproject_ids) { continue; } $t_project_ids = array_merge($t_project_ids, $t_subproject_ids); } $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, 'no accessible projects'); return array(); } log_event(LOG_FILTERING, 'project_ids after including sub-projects = @P' . implode(', @P', $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(); foreach ($t_project_ids as $t_pid) { $t_access_required_to_view_private_bugs = config_get('private_bug_threshold', null, null, $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, 'project_ids (with public/private access) = @P' . implode(', @P', $t_private_and_public_project_ids)); log_event(LOG_FILTERING, 'project_ids (with public access) = @P' . implode(', @P', $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, 'project query = ' . $t_project_query); array_push($t_where_clauses, $t_project_query); } # view state $t_view_state = db_prepare_int($t_filter[FILTER_PROPERTY_VIEW_STATE_ID]); if (!filter_field_is_any($t_filter[FILTER_PROPERTY_VIEW_STATE_ID])) { $t_view_state_query = "({$t_bug_table}.view_state=" . db_param() . ')'; log_event(LOG_FILTERING, 'view_state query = ' . $t_view_state_query); $t_where_params[] = $t_view_state; array_push($t_where_clauses, $t_view_state_query); } else { log_event(LOG_FILTERING, 'no view_state query'); } # reporter if (!filter_field_is_any($t_filter[FILTER_PROPERTY_REPORTER_ID])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_REPORTER_ID] as $t_filter_member) { if (filter_field_is_none($t_filter_member)) { array_push($t_clauses, "0"); } else { $c_reporter_id = db_prepare_int($t_filter_member); if (filter_field_is_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, 'reporter query = ' . $t_reporter_query); array_push($t_where_clauses, $t_reporter_query); } else { log_event(LOG_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; $t_where_params[] = $c_reporter_id; array_push($t_where_clauses, "({$t_bug_table}.reporter_id=" . db_param() . ')'); } # handler if (!filter_field_is_any($t_filter[FILTER_PROPERTY_HANDLER_ID])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_HANDLER_ID] as $t_filter_member) { if (filter_field_is_none($t_filter_member)) { array_push($t_clauses, 0); } else { $c_handler_id = db_prepare_int($t_filter_member); if (filter_field_is_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, 'handler query = ' . $t_handler_query); array_push($t_where_clauses, $t_handler_query); } else { log_event(LOG_FILTERING, 'no handler query'); } # category if (!filter_field_is_any($t_filter[FILTER_PROPERTY_CATEGORY])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_CATEGORY] as $t_filter_member) { if (!filter_field_is_none($t_filter_member)) { array_push($t_clauses, $t_filter_member); } } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bug_table}.category_id in ( SELECT id FROM {$t_category_table} WHERE name in (" . implode(', ', $t_where_tmp) . ") ) )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bug_table}.category_id in ( SELECT id FROM {$t_category_table} WHERE name=" . db_param() . ") )"); } } # severity if (!filter_field_is_any($t_filter[FILTER_PROPERTY_SEVERITY_ID])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_SEVERITY_ID] 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)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bug_table}.severity in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bug_table}.severity=" . db_param() . " )"); } } # 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_desired_statuses = array(); $t_available_statuses = MantisEnum::getValues(config_get('status_enum_string')); 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[FILTER_PROPERTY_STATUS_ID][0]; $t_this_hide_status = $t_filter[FILTER_PROPERTY_HIDE_STATUS_ID][0]; if (filter_field_is_any($t_this_status)) { 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 if (filter_field_is_any($t_filter[FILTER_PROPERTY_STATUS_ID])) { $t_desired_statuses = array(); } else { foreach ($t_filter[FILTER_PROPERTY_STATUS_ID] as $t_this_status) { $t_desired_statuses[] = $t_this_status; } } } 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)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bug_table}.status in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bug_table}.status=" . db_param() . " )"); } } # resolution if (!filter_field_is_any($t_filter[FILTER_PROPERTY_RESOLUTION_ID])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_RESOLUTION_ID] 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)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bug_table}.resolution in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bug_table}.resolution=" . db_param() . " )"); } } # priority if (!filter_field_is_any($t_filter[FILTER_PROPERTY_PRIORITY_ID])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_PRIORITY_ID] 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)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bug_table}.priority in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bug_table}.priority=" . db_param() . " )"); } } # product build if (!filter_field_is_any($t_filter[FILTER_PROPERTY_PRODUCT_BUILD])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_PRODUCT_BUILD] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_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)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bug_table}.build in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bug_table}.build=" . db_param() . " )"); } } # product version if (!filter_field_is_any($t_filter[FILTER_PROPERTY_PRODUCT_VERSION])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_PRODUCT_VERSION] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_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)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bug_table}.version in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bug_table}.version=" . db_param() . " )"); } } # profile if (!filter_field_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 (filter_field_is_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)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bug_table}.profile_id in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bug_table}.profile_id=" . db_param() . " )"); } } # platform if (!filter_field_is_any($t_filter[FILTER_PROPERTY_PLATFORM])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_PLATFORM] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_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)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bug_table}.platform in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bug_table}.platform = " . db_param() . " )"); } } # os if (!filter_field_is_any($t_filter[FILTER_PROPERTY_OS])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_OS] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_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)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bug_table}.os in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bug_table}.os = " . db_param() . " )"); } } # os_build if (!filter_field_is_any($t_filter[FILTER_PROPERTY_OS_BUILD])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_OS_BUILD] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_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)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bug_table}.os_build in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bug_table}.os_build = " . db_param() . " )"); } } # date filter 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])) { $t_start_string = $t_filter[FILTER_PROPERTY_START_YEAR] . "-" . $t_filter[FILTER_PROPERTY_START_MONTH] . "-" . $t_filter[FILTER_PROPERTY_START_DAY] . " 00:00:00"; $t_end_string = $t_filter[FILTER_PROPERTY_END_YEAR] . "-" . $t_filter[FILTER_PROPERTY_END_MONTH] . "-" . $t_filter[FILTER_PROPERTY_END_DAY] . " 23:59:59"; $t_where_params[] = strtotime($t_start_string); $t_where_params[] = strtotime($t_end_string); array_push($t_where_clauses, "({$t_bug_table}.date_submitted BETWEEN " . db_param() . " AND " . db_param() . " )"); } # fixed in version if (!filter_field_is_any($t_filter[FILTER_PROPERTY_FIXED_IN_VERSION])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_FIXED_IN_VERSION] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_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)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bug_table}.fixed_in_version in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bug_table}.fixed_in_version=" . db_param() . " )"); } } # target version if (!filter_field_is_any($t_filter[FILTER_PROPERTY_TARGET_VERSION])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_TARGET_VERSION] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_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)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bug_table}.target_version in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bug_table}.target_version=" . db_param() . " )"); } } # users monitoring a bug if (!filter_field_is_any($t_filter[FILTER_PROPERTY_MONITOR_USER_ID])) { $t_clauses = array(); $t_table_name = 'user_monitor'; 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[FILTER_PROPERTY_MONITOR_USER_ID] as $t_filter_member) { $c_user_monitor = db_prepare_int($t_filter_member); if (filter_field_is_myself($c_user_monitor)) { array_push($t_clauses, $c_user_id); } else { array_push($t_clauses, $c_user_monitor); } } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_table_name}.user_id in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_table_name}.user_id=" . db_param() . " )"); } } # bug relationship $t_any_found = false; $c_rel_type = $t_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE]; $c_rel_bug = $t_filter[FILTER_PROPERTY_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_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 $t_where_params[] = $t_comp_type; $t_where_params[] = $c_rel_bug; $t_where_params[] = $c_rel_type; $t_where_params[] = $c_rel_bug; array_push($t_clauses, "({$t_table_name}.relationship_type=" . db_param() . " AND {$t_table_name}.source_bug_id=" . db_param() . ')'); array_push($t_clauses, "({$t_table_name}" . "2.relationship_type=" . db_param() . " AND {$t_table_name}" . "2.destination_bug_id=" . db_param() . ')'); array_push($t_where_clauses, '(' . implode(' OR ', $t_clauses) . ')'); } # tags $c_tag_string = trim($t_filter[FILTER_PROPERTY_TAG_STRING]); $c_tag_select = trim($t_filter[FILTER_PROPERTY_TAG_SELECT]); if (is_blank($c_tag_string) && !is_blank($c_tag_select) && $c_tag_select != 0) { $t_tag = tag_get($c_tag_select); $c_tag_string = $t_tag['name']; } 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[FILTER_PROPERTY_TAG_SELECT] && tag_exists($t_filter[FILTER_PROPERTY_TAG_SELECT])) { $t_tags_any[] = tag_get($t_filter[FILTER_PROPERTY_TAG_SELECT]); } $t_bug_tag_table = db_get_table('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) . ') )'); } } } # note user id if (!filter_field_is_any($t_filter[FILTER_PROPERTY_NOTE_USER_ID])) { $t_bugnote_table_alias = 'mbnt'; $t_clauses = array(); array_push($t_from_clauses, "{$t_bugnote_table} {$t_bugnote_table_alias}"); array_push($t_where_clauses, "( {$t_bug_table}.id = {$t_bugnote_table_alias}.bug_id )"); foreach ($t_filter[FILTER_PROPERTY_NOTE_USER_ID] as $t_filter_member) { $c_note_user_id = db_prepare_int($t_filter_member); if (filter_field_is_myself($c_note_user_id)) { array_push($t_clauses, $c_user_id); } else { array_push($t_clauses, $c_note_user_id); } } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, "( {$t_bugnote_table_alias}.reporter_id in (" . implode(', ', $t_where_tmp) . ") )"); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, "( {$t_bugnote_table_alias}.reporter_id=" . db_param() . " )"); } } # plugin filters $t_plugin_filters = filter_get_plugin_filters(); foreach ($t_plugin_filters as $t_field_name => $t_filter_object) { if (!filter_field_is_any($t_filter[$t_field_name]) || $t_filter_object->type == FILTER_TYPE_BOOLEAN) { $t_filter_query = $t_filter_object->query($t_filter[$t_field_name]); if (is_array($t_filter_query)) { if (isset($t_filter_query['join'])) { array_push($t_join_clauses, $t_filter_query['join']); } if (isset($t_filter_query['where'])) { array_push($t_where_clauses, $t_filter_query['where']); } if (isset($t_filter_query['params']) && is_array($t_filter_query['params'])) { $t_where_params = array_merge($t_where_params, $t_filter_query['params']); } } } } # 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_field_info = custom_field_cache_row($t_cfid, true); if (!$t_field_info['filter_by']) { continue; # skip this custom field it shouldn't be filterable } $t_custom_where_clause = ''; # Ignore all custom filters that are not set, or that are set to '' or "any" if (!filter_field_is_any($t_filter['custom_fields'][$t_cfid])) { $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_bug_table}.id = {$t_table_name}.bug_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 (filter_field_is_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_CHECKBOX: case CUSTOM_FIELD_TYPE_MULTILIST: if ($t_filter_member != '') { $t_filter_member = '%|' . $t_filter_member . '|%'; } $t_where_params[] = $t_filter_member; array_push($t_filter_array, db_helper_like("{$t_table_name}.value")); break; default: $t_where_params[] = $t_filter_member; array_push($t_filter_array, "{$t_table_name}.value = " . db_param()); } } $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 . ')'); } } } } # Text search if (!is_blank($t_filter[FILTER_PROPERTY_FREE_TEXT])) { # break up search terms by spacing or quoting preg_match_all("/-?([^'\"\\s]+|\"[^\"]+\"|'[^']+')/", $t_filter[FILTER_PROPERTY_FREE_TEXT], $t_matches, PREG_SET_ORDER); # organize terms without quoting, paying attention to negation $t_search_terms = array(); foreach ($t_matches as $t_match) { $t_search_terms[trim($t_match[1], "\\'\"")] = $t_match[0][0] == '-'; } # build a big where-clause and param list for all search terms, including negations $t_first = true; $t_textsearch_where_clause = "( "; foreach ($t_search_terms as $t_search_term => $t_negate) { if (!$t_first) { $t_textsearch_where_clause .= ' AND '; } if ($t_negate) { $t_textsearch_where_clause .= 'NOT '; } $c_search = '%' . $t_search_term . '%'; $t_textsearch_where_clause .= '( ' . db_helper_like('summary') . ' OR ' . db_helper_like("{$t_bug_text_table}.description") . ' OR ' . db_helper_like("{$t_bug_text_table}.steps_to_reproduce") . ' OR ' . db_helper_like("{$t_bug_text_table}.additional_information") . ' OR ' . db_helper_like("{$t_bugnote_text_table}.note"); $t_where_params[] = $c_search; $t_where_params[] = $c_search; $t_where_params[] = $c_search; $t_where_params[] = $c_search; $t_where_params[] = $c_search; if (is_numeric($t_search_term)) { // PostgreSQL on 64-bit OS hack (see #14014) if (PHP_INT_MAX > 0x7fffffff && db_is_pgsql()) { $t_search_max = 0x7fffffff; } else { $t_search_max = PHP_INT_MAX; } // Note: no need to test negative values, '-' sign has been removed if ($t_search_term <= $t_search_max) { $c_search_int = (int) $t_search_term; $t_textsearch_where_clause .= " OR {$t_bug_table}.id = " . db_param(); $t_textsearch_where_clause .= " OR {$t_bugnote_table}.id = " . db_param(); $t_where_params[] = $c_search_int; $t_where_params[] = $c_search_int; } } $t_textsearch_where_clause .= ' )'; $t_first = false; } $t_textsearch_where_clause .= ' )'; # add text query elements to arrays if (!$t_first) { $t_from_clauses[] = "{$t_bug_text_table}"; $t_where_clauses[] = "{$t_bug_table}.bug_text_id = {$t_bug_text_table}.id"; $t_where_clauses[] = $t_textsearch_where_clause; $t_join_clauses[] = " LEFT JOIN {$t_bugnote_table} ON {$t_bug_table}.id = {$t_bugnote_table}.bug_id"; $t_join_clauses[] = " LEFT JOIN {$t_bugnote_text_table} ON {$t_bugnote_table}.bugnote_text_id = {$t_bugnote_text_table}.id"; } } # End text search $t_from_clauses[] = $t_project_table; $t_from_clauses[] = $t_bug_table; $t_query_clauses['select'] = $t_select_clauses; $t_query_clauses['from'] = $t_from_clauses; $t_query_clauses['join'] = $t_join_clauses; $t_query_clauses['where'] = $t_where_clauses; $t_query_clauses['where_values'] = $t_where_params; $t_query_clauses = filter_get_query_sort_data($t_filter, $p_show_sticky, $t_query_clauses); # assigning to $p_* for this function writes the values back in case the caller wants to know # Get the total number of bugs that meet the criteria. $p_bug_count = filter_get_bug_count($t_query_clauses); if (0 == $p_bug_count) { return array(); } $p_per_page = filter_per_page($t_filter, $p_bug_count, $p_per_page); $p_page_count = filter_page_count($p_bug_count, $p_per_page); $p_page_number = filter_valid_page_number($p_page_number, $p_page_count); $t_offset = filter_offset($p_page_number, $p_per_page); $t_query_clauses = filter_unique_query_clauses($t_query_clauses); $t_select_string = "SELECT DISTINCT " . implode(', ', $t_query_clauses['select']); $t_from_string = " FROM " . implode(', ', $t_query_clauses['from']); $t_order_string = " ORDER BY " . implode(', ', $t_query_clauses['order']); $t_join_string = count($t_query_clauses['join']) > 0 ? implode(' ', $t_query_clauses['join']) : ''; $t_where_string = count($t_query_clauses['where']) > 0 ? 'WHERE ' . implode(' AND ', $t_query_clauses['where']) : ''; $t_result = db_query_bound("{$t_select_string} {$t_from_string} {$t_join_string} {$t_where_string} {$t_order_string}", $t_query_clauses['where_values'], $p_per_page, $t_offset); $t_row_count = db_num_rows($t_result); $t_id_array_lastmod = array(); for ($i = 0; $i < $t_row_count; $i++) { $t_row = db_fetch_array($t_result); $t_id_array_lastmod[] = (int) $t_row['id']; $t_rows[] = $t_row; } return filter_cache_result($t_rows, $t_id_array_lastmod); }
/** * Get set of bug rows from given filter * @todo 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. * * @param integer &$p_page_number Page number of the page you want to see (set to the actual page on return). * @param integer &$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. * @param integer &$p_page_count You don't need to give a value here, the number of pages will be stored here on return. * @param integer &$p_bug_count You don't need to give a value here, the number of bugs will be stored here on return. * @param mixed $p_custom_filter Custom Filter to use. * @param integer $p_project_id Project id to use in filtering. * @param integer $p_user_id User id to use as current user when filtering. * @param boolean $p_show_sticky True/false - get sticky issues only. * @return boolean|array */ 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, 'START NEW FILTER QUERY'); $t_limit_reporters = config_get('limit_reporters'); $t_report_bug_threshold = config_get('report_bug_threshold'); $t_where_param_count = 0; $t_current_user_id = auth_get_current_user_id(); if ($p_user_id === null || $p_user_id === 0) { $t_user_id = $t_current_user_id; } else { $t_user_id = $p_user_id; } $c_user_id = (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; } # if filter isn't return above, create a new filter from an empty array. if (false === $t_filter) { $t_filter = array(); } $t_filter = filter_ensure_valid_filter($t_filter); $t_view_type = $t_filter['_view_type']; # project query clauses must be AND-ed always, irrespective of how the filter # clauses are requested by the user ( all matching -> AND, any matching -> OR ) $t_where_clauses = array(); $t_project_where_clauses = array('{project}.enabled = ' . db_param()); $t_where_params = array(1); $t_select_clauses = array('{bug}.*'); $t_from_clauses = array('{bug}'); $t_join_clauses = array(' JOIN {project} ON {project}.id = {bug}.project_id'); # normalize the project filtering into an array $t_project_ids if ('simple' == $t_view_type) { log_event(LOG_FILTERING, 'Simple Filter'); $t_project_ids = array($t_project_id); $t_include_sub_projects = true; } else { log_event(LOG_FILTERING, 'Advanced Filter'); if (!is_array($t_filter[FILTER_PROPERTY_PROJECT_ID])) { $t_project_ids = array((int) $t_filter[FILTER_PROPERTY_PROJECT_ID]); } else { $t_project_ids = array_map('intval', $t_filter[FILTER_PROPERTY_PROJECT_ID]); } $t_include_sub_projects = count($t_project_ids) == 1 && ($t_project_ids[0] == META_FILTER_CURRENT || $t_project_ids[0] == ALL_PROJECTS); } log_event(LOG_FILTERING, 'project_ids = @P' . implode(', @P', $t_project_ids)); log_event(LOG_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, 'all projects selected'); break; } # filter out inaccessible projects. if (!project_exists($t_pid) || !access_has_project_level(config_get('view_bug_threshold', null, $t_user_id, $t_pid), $t_pid, $t_user_id)) { log_event(LOG_FILTERING, 'Invalid or inaccessible project: ' . $t_pid); 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, '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, 'Getting sub-projects for project id @P' . $t_pid); $t_subproject_ids = user_get_all_accessible_subprojects($t_user_id, $t_pid); if (!$t_subproject_ids) { continue; } $t_project_ids = array_merge($t_project_ids, $t_subproject_ids); } $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, 'no accessible projects'); return array(); } log_event(LOG_FILTERING, 'project_ids after including sub-projects = @P' . implode(', @P', $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_limited_projects = array(); foreach ($t_project_ids as $t_pid) { # limit reporters to visible projects if (ON === $t_limit_reporters && !access_has_project_level(config_get('report_bug_threshold', null, $t_user_id, $t_pid) + 1, $t_pid, $t_user_id)) { array_push($t_limited_projects, '({bug}.project_id=' . $t_pid . ' AND ({bug}.reporter_id=' . $t_user_id . ') )'); } else { $t_access_required_to_view_private_bugs = config_get('private_bug_threshold', null, null, $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, 'project_ids (with public/private access) = @P' . implode(', @P', $t_private_and_public_project_ids)); log_event(LOG_FILTERING, 'project_ids (with public access) = @P' . implode(', @P', $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 = '( {bug}.project_id = ' . $t_private_and_public_project_ids[0] . ' )'; } else { if ($t_count_private_and_public_project_ids > 1) { $t_private_and_public_query = '( {bug}.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 = '( ( {bug}.view_state = ' . VS_PUBLIC . ' ) OR ( {bug}.reporter_id = ' . $t_user_id . ') )'; if ($t_count_public_only_project_ids == 1) { $t_public_only_query = '( ( {bug}.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 = '( ( {bug}.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 . ' )'; } } if (!empty($t_limited_projects)) { foreach ($t_limited_projects as $t_string) { if ($t_project_query == "") { $t_project_query = " ( {$t_string} ) "; } else { $t_project_query = " ( {$t_project_query} OR ( {$t_string} ) )"; } } } log_event(LOG_FILTERING, 'project query = ' . $t_project_query); array_push($t_project_where_clauses, $t_project_query); } # date filter 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])) { $t_start_string = $t_filter[FILTER_PROPERTY_START_YEAR] . '-' . $t_filter[FILTER_PROPERTY_START_MONTH] . '-' . $t_filter[FILTER_PROPERTY_START_DAY] . ' 00:00:00'; $t_end_string = $t_filter[FILTER_PROPERTY_END_YEAR] . '-' . $t_filter[FILTER_PROPERTY_END_MONTH] . '-' . $t_filter[FILTER_PROPERTY_END_DAY] . ' 23:59:59'; $t_where_params[] = strtotime($t_start_string); $t_where_params[] = strtotime($t_end_string); array_push($t_project_where_clauses, '({bug}.date_submitted BETWEEN ' . db_param() . ' AND ' . db_param() . ' )'); } # view state $t_view_state = (int) $t_filter[FILTER_PROPERTY_VIEW_STATE]; if (!filter_field_is_any($t_filter[FILTER_PROPERTY_VIEW_STATE])) { $t_view_state_query = '({bug}.view_state=' . db_param() . ')'; log_event(LOG_FILTERING, 'view_state query = ' . $t_view_state_query); $t_where_params[] = $t_view_state; array_push($t_where_clauses, $t_view_state_query); } else { log_event(LOG_FILTERING, 'no view_state query'); } # reporter if (!filter_field_is_any($t_filter[FILTER_PROPERTY_REPORTER_ID])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_REPORTER_ID] as $t_filter_member) { if (filter_field_is_none($t_filter_member)) { array_push($t_clauses, '0'); } else { $c_reporter_id = (int) $t_filter_member; if (filter_field_is_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 = '( {bug}.reporter_id in (' . implode(', ', $t_clauses) . ') )'; } else { $t_reporter_query = '( {bug}.reporter_id=' . $t_clauses[0] . ' )'; } log_event(LOG_FILTERING, 'reporter query = ' . $t_reporter_query); array_push($t_where_clauses, $t_reporter_query); } else { log_event(LOG_FILTERING, 'no reporter query'); } # handler if (!filter_field_is_any($t_filter[FILTER_PROPERTY_HANDLER_ID])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_HANDLER_ID] as $t_filter_member) { if (filter_field_is_none($t_filter_member)) { array_push($t_clauses, 0); } else { $c_handler_id = (int) $t_filter_member; if (filter_field_is_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 = '( {bug}.handler_id in (' . implode(', ', $t_clauses) . ') )'; } else { $t_handler_query = '( {bug}.handler_id=' . $t_clauses[0] . ' )'; } log_event(LOG_FILTERING, 'handler query = ' . $t_handler_query); array_push($t_where_clauses, $t_handler_query); } else { log_event(LOG_FILTERING, 'no handler query'); } # category if (!filter_field_is_any($t_filter[FILTER_PROPERTY_CATEGORY_ID])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_CATEGORY_ID] as $t_filter_member) { if (!filter_field_is_none($t_filter_member)) { array_push($t_clauses, $t_filter_member); } } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( {bug}.category_id in ( SELECT id FROM {category} WHERE name in (' . implode(', ', $t_where_tmp) . ') ) )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( {bug}.category_id in ( SELECT id FROM {category} WHERE name=' . db_param() . ') )'); } } # severity if (!filter_field_is_any($t_filter[FILTER_PROPERTY_SEVERITY])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_SEVERITY] as $t_filter_member) { $c_show_severity = (int) $t_filter_member; array_push($t_clauses, $c_show_severity); } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( {bug}.severity in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( {bug}.severity=' . db_param() . ' )'); } } # 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_desired_statuses = array(); $t_available_statuses = MantisEnum::getValues(config_get('status_enum_string')); if ('simple' == $t_filter['_view_type']) { # simple filtering: if showing any, restrict by the hide status value, otherwise ignore the hide $t_this_status = $t_filter[FILTER_PROPERTY_STATUS][0]; $t_this_hide_status = isset($t_filter[FILTER_PROPERTY_HIDE_STATUS][0]) ? $t_filter[FILTER_PROPERTY_HIDE_STATUS][0] : null; if (filter_field_is_any($t_this_status)) { 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 if (filter_field_is_any($t_filter[FILTER_PROPERTY_STATUS])) { $t_desired_statuses = array(); } else { foreach ($t_filter[FILTER_PROPERTY_STATUS] as $t_this_status) { $t_desired_statuses[] = $t_this_status; } } } if (count($t_desired_statuses) > 0) { $t_clauses = array(); foreach ($t_desired_statuses as $t_filter_member) { $c_show_status = (int) $t_filter_member; array_push($t_clauses, $c_show_status); } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( {bug}.status in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( {bug}.status=' . db_param() . ' )'); } } # resolution if (!filter_field_is_any($t_filter[FILTER_PROPERTY_RESOLUTION])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_RESOLUTION] as $t_filter_member) { $c_show_resolution = (int) $t_filter_member; array_push($t_clauses, $c_show_resolution); } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( {bug}.resolution in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( {bug}.resolution=' . db_param() . ' )'); } } # priority if (!filter_field_is_any($t_filter[FILTER_PROPERTY_PRIORITY])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_PRIORITY] as $t_filter_member) { $c_show_priority = (int) $t_filter_member; array_push($t_clauses, $c_show_priority); } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( {bug}.priority in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( {bug}.priority=' . db_param() . ' )'); } } # product build if (!filter_field_is_any($t_filter[FILTER_PROPERTY_BUILD])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_BUILD] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_none($t_filter_member)) { array_push($t_clauses, ''); } else { $c_show_build = $t_filter_member; array_push($t_clauses, $c_show_build); } } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( {bug}.build in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( {bug}.build=' . db_param() . ' )'); } } # product version if (!filter_field_is_any($t_filter[FILTER_PROPERTY_VERSION])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_VERSION] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_none($t_filter_member)) { array_push($t_clauses, ''); } else { $c_show_version = $t_filter_member; array_push($t_clauses, $c_show_version); } } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( {bug}.version in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( {bug}.version=' . db_param() . ' )'); } } # profile if (!filter_field_is_any($t_filter[FILTER_PROPERTY_PROFILE_ID])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_PROFILE_ID] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_none($t_filter_member)) { array_push($t_clauses, '0'); } else { $c_show_profile = (int) $t_filter_member; array_push($t_clauses, $c_show_profile); } } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( {bug}.profile_id in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( {bug}.profile_id=' . db_param() . ' )'); } } # platform if (!filter_field_is_any($t_filter[FILTER_PROPERTY_PLATFORM])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_PLATFORM] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_none($t_filter_member)) { array_push($t_clauses, ''); } else { $c_platform = $t_filter_member; array_push($t_clauses, $c_platform); } } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( {bug}.platform in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( {bug}.platform = ' . db_param() . ' )'); } } # Operating System (os) if (!filter_field_is_any($t_filter[FILTER_PROPERTY_OS])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_OS] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_none($t_filter_member)) { array_push($t_clauses, ''); } else { $c_os = $t_filter_member; array_push($t_clauses, $c_os); } } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( {bug}.os in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( {bug}.os = ' . db_param() . ' )'); } } # Operating System Build (os_build) if (!filter_field_is_any($t_filter[FILTER_PROPERTY_OS_BUILD])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_OS_BUILD] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_none($t_filter_member)) { array_push($t_clauses, ''); } else { $c_os_build = $t_filter_member; array_push($t_clauses, $c_os_build); } } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( {bug}.os_build in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( {bug}.os_build = ' . db_param() . ' )'); } } # fixed in version if (!filter_field_is_any($t_filter[FILTER_PROPERTY_FIXED_IN_VERSION])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_FIXED_IN_VERSION] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_none($t_filter_member)) { array_push($t_clauses, ''); } else { $c_fixed_in_version = $t_filter_member; array_push($t_clauses, $c_fixed_in_version); } } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( {bug}.fixed_in_version in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( {bug}.fixed_in_version=' . db_param() . ' )'); } } # target version if (!filter_field_is_any($t_filter[FILTER_PROPERTY_TARGET_VERSION])) { $t_clauses = array(); foreach ($t_filter[FILTER_PROPERTY_TARGET_VERSION] as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_none($t_filter_member)) { array_push($t_clauses, ''); } else { $c_target_version = $t_filter_member; array_push($t_clauses, $c_target_version); } } # echo var_dump( $t_clauses ); exit; if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( {bug}.target_version in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( {bug}.target_version=' . db_param() . ' )'); } } # users monitoring a bug if (!filter_field_is_any($t_filter[FILTER_PROPERTY_MONITOR_USER_ID])) { $t_clauses = array(); $t_table_name = 'user_monitor'; array_push($t_join_clauses, 'LEFT JOIN {bug_monitor} ' . $t_table_name . ' ON ' . $t_table_name . '.bug_id = {bug}.id'); foreach ($t_filter[FILTER_PROPERTY_MONITOR_USER_ID] as $t_filter_member) { $c_user_monitor = (int) $t_filter_member; if (filter_field_is_myself($c_user_monitor)) { array_push($t_clauses, $c_user_id); } else { array_push($t_clauses, $c_user_monitor); } } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( ' . $t_table_name . '.user_id in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( ' . $t_table_name . '.user_id=' . db_param() . ' )'); } } # bug relationship $t_any_found = false; $c_rel_type = $t_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE]; $c_rel_bug = $t_filter[FILTER_PROPERTY_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_dst = 'rel_dst'; $t_table_src = 'rel_src'; array_push($t_join_clauses, 'LEFT JOIN {bug_relationship} ' . $t_table_dst . ' ON ' . $t_table_dst . '.destination_bug_id = {bug}.id'); array_push($t_join_clauses, 'LEFT JOIN {bug_relationship} ' . $t_table_src . ' ON ' . $t_table_src . '.source_bug_id = {bug}.id'); # get reverse relationships $t_where_params[] = $t_comp_type; $t_where_params[] = $c_rel_bug; $t_where_params[] = $c_rel_type; $t_where_params[] = $c_rel_bug; array_push($t_clauses, '(' . $t_table_dst . '.relationship_type=' . db_param() . ' AND ' . $t_table_dst . '.source_bug_id=' . db_param() . ')'); array_push($t_clauses, '(' . $t_table_src . '.relationship_type=' . db_param() . ' AND ' . $t_table_src . '.destination_bug_id=' . db_param() . ')'); array_push($t_where_clauses, '(' . implode(' OR ', $t_clauses) . ')'); } # tags $c_tag_string = trim($t_filter[FILTER_PROPERTY_TAG_STRING]); $c_tag_select = trim($t_filter[FILTER_PROPERTY_TAG_SELECT]); if (is_blank($c_tag_string) && !is_blank($c_tag_select) && $c_tag_select != 0) { $t_tag = tag_get($c_tag_select); $c_tag_string = $t_tag['name']; } 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[FILTER_PROPERTY_TAG_SELECT] && tag_exists($t_filter[FILTER_PROPERTY_TAG_SELECT])) { $t_tags_any[] = tag_get($t_filter[FILTER_PROPERTY_TAG_SELECT]); } if (count($t_tags_all)) { $t_clauses = array(); foreach ($t_tags_all as $t_tag_row) { array_push($t_clauses, '{bug}.id IN ( SELECT bug_id FROM {bug_tag} WHERE {bug_tag}.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, '{bug_tag}.tag_id = ' . $t_tag_row['id']); } array_push($t_where_clauses, '{bug}.id IN ( SELECT bug_id FROM {bug_tag} 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, '{bug_tag}.tag_id = ' . $t_tag_row['id']); } array_push($t_where_clauses, '{bug}.id NOT IN ( SELECT bug_id FROM {bug_tag} WHERE ( ' . implode(' OR ', $t_clauses) . ') )'); } } } # note user id if (!filter_field_is_any($t_filter[FILTER_PROPERTY_NOTE_USER_ID])) { $t_bugnote_table_alias = 'mbnt'; $t_clauses = array(); array_push($t_join_clauses, 'LEFT JOIN {bugnote} ' . $t_bugnote_table_alias . ' ON {bug}.id = ' . $t_bugnote_table_alias . '.bug_id'); foreach ($t_filter[FILTER_PROPERTY_NOTE_USER_ID] as $t_filter_member) { $c_note_user_id = (int) $t_filter_member; if (filter_field_is_myself($c_note_user_id)) { array_push($t_clauses, $c_user_id); } else { array_push($t_clauses, $c_note_user_id); } } if (1 < count($t_clauses)) { $t_where_tmp = array(); foreach ($t_clauses as $t_clause) { $t_where_tmp[] = db_param(); $t_where_params[] = $t_clause; } array_push($t_where_clauses, '( ' . $t_bugnote_table_alias . '.reporter_id in (' . implode(', ', $t_where_tmp) . ') )'); } else { $t_where_params[] = $t_clauses[0]; array_push($t_where_clauses, '( ' . $t_bugnote_table_alias . '.reporter_id=' . db_param() . ' )'); } } # plugin filters $t_plugin_filters = filter_get_plugin_filters(); foreach ($t_plugin_filters as $t_field_name => $t_filter_object) { if (!filter_field_is_any($t_filter[$t_field_name]) || $t_filter_object->type == FILTER_TYPE_BOOLEAN) { $t_filter_query = $t_filter_object->query($t_filter[$t_field_name]); if (is_array($t_filter_query)) { if (isset($t_filter_query['join'])) { array_push($t_join_clauses, $t_filter_query['join']); } if (isset($t_filter_query['where'])) { array_push($t_where_clauses, $t_filter_query['where']); } if (isset($t_filter_query['params']) && is_array($t_filter_query['params'])) { $t_where_params = array_merge($t_where_params, $t_filter_query['params']); } } } } # 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_field_info = custom_field_cache_row($t_cfid, true); if (!$t_field_info['filter_by']) { continue; # skip this custom field it shouldn't be filterable } $t_field = $t_filter['custom_fields'][$t_cfid]; $t_custom_where_clause = ''; # Ignore all custom filters that are not set, or that are set to '' or "any" if (!filter_field_is_any($t_field)) { $t_def = custom_field_get_definition($t_cfid); $t_table_name = '{custom_field_string}_' . $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 {custom_field_string} ' . $t_table_name . ' ON {bug}.id = ' . $t_table_name . '.bug_id AND ' . $t_table_name . '.field_id = ' . $t_cfid; if ($t_def['type'] == CUSTOM_FIELD_TYPE_DATE) { # Define the value field with type cast to integer $t_value_field = 'CAST(COALESCE(NULLIF(' . $t_table_name . '.value, \'\'), \'0\') AS DECIMAL)'; switch ($t_field[0]) { # Closing parenthesis intentionally omitted, will be added later on 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_value_field . ' = 0 '; break; case CUSTOM_FIELD_DATE_BEFORE: array_push($t_join_clauses, $t_cf_join_clause); $t_custom_where_clause = '( ' . $t_value_field . ' != 0 AND ' . $t_value_field . ' < ' . $t_field[2]; break; case CUSTOM_FIELD_DATE_AFTER: array_push($t_join_clauses, $t_cf_join_clause); $t_custom_where_clause = '( ' . $t_value_field . ' > ' . ($t_field[1] + 1); break; default: array_push($t_join_clauses, $t_cf_join_clause); $t_custom_where_clause = '( ' . $t_value_field . ' BETWEEN ' . $t_field[1] . ' AND ' . $t_field[2]; break; } } else { array_push($t_join_clauses, $t_cf_join_clause); $t_filter_array = array(); foreach ($t_field as $t_filter_member) { $t_filter_member = stripslashes($t_filter_member); if (filter_field_is_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, '{bug}.id NOT IN (SELECT bug_id FROM {custom_field_string} WHERE field_id=' . $t_cfid . ')'); } switch ($t_def['type']) { case CUSTOM_FIELD_TYPE_CHECKBOX: case CUSTOM_FIELD_TYPE_MULTILIST: $t_where_params[] = '%|' . $t_filter_member . '|%'; array_push($t_filter_array, db_helper_like($t_table_name . '.value')); break; case CUSTOM_FIELD_TYPE_TEXTAREA: $t_where_params[] = '%' . $t_filter_member . '%'; array_push($t_filter_array, db_helper_like($t_table_name . '.text')); break; default: $t_where_params[] = $t_filter_member; array_push($t_filter_array, $t_table_name . '.value = ' . db_param()); } } $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 . ')'); } } } } # Text search if (!is_blank($t_filter[FILTER_PROPERTY_SEARCH])) { # break up search terms by spacing or quoting preg_match_all("/-?([^'\"\\s]+|\"[^\"]+\"|'[^']+')/", $t_filter[FILTER_PROPERTY_SEARCH], $t_matches, PREG_SET_ORDER); # organize terms without quoting, paying attention to negation $t_search_terms = array(); foreach ($t_matches as $t_match) { $t_search_terms[trim($t_match[1], "\\'\"")] = $t_match[0][0] == '-'; } # build a big where-clause and param list for all search terms, including negations $t_first = true; $t_textsearch_where_clause = '( '; foreach ($t_search_terms as $t_search_term => $t_negate) { if (!$t_first) { $t_textsearch_where_clause .= ' AND '; } if ($t_negate) { $t_textsearch_where_clause .= 'NOT '; } $c_search = '%' . $t_search_term . '%'; $t_textsearch_where_clause .= '( ' . db_helper_like('{bug}.summary') . ' OR ' . db_helper_like('{bug_text}.description') . ' OR ' . db_helper_like('{bug_text}.steps_to_reproduce') . ' OR ' . db_helper_like('{bug_text}.additional_information') . ' OR ' . db_helper_like('{bugnote_text}.note'); $t_where_params[] = $c_search; $t_where_params[] = $c_search; $t_where_params[] = $c_search; $t_where_params[] = $c_search; $t_where_params[] = $c_search; if (is_numeric($t_search_term)) { # PostgreSQL on 64-bit OS hack (see #14014) if (PHP_INT_MAX > 0x7fffffff && db_is_pgsql()) { $t_search_max = 0x7fffffff; } else { $t_search_max = PHP_INT_MAX; } # Note: no need to test negative values, '-' sign has been removed if ($t_search_term <= $t_search_max) { $c_search_int = (int) $t_search_term; $t_textsearch_where_clause .= ' OR {bug}.id = ' . db_param(); $t_textsearch_where_clause .= ' OR {bugnote}.id = ' . db_param(); $t_where_params[] = $c_search_int; $t_where_params[] = $c_search_int; } } $t_textsearch_where_clause .= ' )'; $t_first = false; } $t_textsearch_where_clause .= ' )'; # add text query elements to arrays if (!$t_first) { $t_join_clauses[] = 'JOIN {bug_text} ON {bug}.bug_text_id = {bug_text}.id'; $t_join_clauses[] = 'LEFT JOIN {bugnote} ON {bug}.id = {bugnote}.bug_id'; # Outer join required otherwise we don't retrieve issues without notes $t_join_clauses[] = 'LEFT JOIN {bugnote_text} ON {bugnote}.bugnote_text_id = {bugnote_text}.id'; $t_where_clauses[] = $t_textsearch_where_clause; } } # End text search # Determine join operator if ($t_filter[FILTER_PROPERTY_MATCH_TYPE] == FILTER_MATCH_ANY) { $t_join_operator = ' OR '; } else { $t_join_operator = ' AND '; } log_event(LOG_FILTERING, 'Join operator : ' . $t_join_operator); $t_query_clauses['select'] = $t_select_clauses; $t_query_clauses['from'] = $t_from_clauses; $t_query_clauses['join'] = $t_join_clauses; $t_query_clauses['where'] = $t_where_clauses; $t_query_clauses['where_values'] = $t_where_params; $t_query_clauses['project_where'] = $t_project_where_clauses; $t_query_clauses['operator'] = $t_join_operator; $t_query_clauses = filter_get_query_sort_data($t_filter, $p_show_sticky, $t_query_clauses); # assigning to $p_* for this function writes the values back in case the caller wants to know # Get the total number of bugs that meet the criteria. $p_bug_count = filter_get_bug_count($t_query_clauses); if (0 == $p_bug_count) { return array(); } $p_per_page = filter_per_page($t_filter, $p_bug_count, $p_per_page); $p_page_count = filter_page_count($p_bug_count, $p_per_page); $p_page_number = filter_valid_page_number($p_page_number, $p_page_count); $t_offset = filter_offset($p_page_number, $p_per_page); $t_query_clauses = filter_unique_query_clauses($t_query_clauses); $t_select_string = 'SELECT DISTINCT ' . implode(', ', $t_query_clauses['select']); $t_from_string = ' FROM ' . implode(', ', $t_query_clauses['from']); $t_order_string = ' ORDER BY ' . implode(', ', $t_query_clauses['order']); $t_join_string = count($t_query_clauses['join']) > 0 ? implode(' ', $t_query_clauses['join']) : ' '; $t_where_string = ' WHERE ' . implode(' AND ', $t_query_clauses['project_where']); if (count($t_query_clauses['where']) > 0) { $t_where_string .= ' AND ( '; $t_where_string .= implode($t_join_operator, $t_query_clauses['where']); $t_where_string .= ' ) '; } $t_result = db_query($t_select_string . $t_from_string . $t_join_string . $t_where_string . $t_order_string, $t_query_clauses['where_values'], $p_per_page, $t_offset); $t_id_array_lastmod = array(); while ($t_row = db_fetch_array($t_result)) { $t_id_array_lastmod[] = (int) $t_row['id']; $t_rows[] = $t_row; } return filter_cache_result($t_rows, $t_id_array_lastmod); }
function print_project_access_levels_option_list($p_val, $p_project_id = null) { $t_current_user_access_level = access_get_project_level($p_project_id); $t_access_levels_enum_string = config_get('access_levels_enum_string'); $t_enum_values = MantisEnum::getValues($t_access_levels_enum_string); foreach ($t_enum_values as $t_enum_value) { # a user must not be able to assign another user an access level that is higher than theirs. if ($t_enum_value > $t_current_user_access_level) { continue; } $t_access_level = get_enum_element('access_levels', $t_enum_value); echo '<option value="' . $t_enum_value . '"'; check_selected($p_val, $t_enum_value); echo '>' . string_html_specialchars($t_access_level) . '</option>'; } }
/** * Print the legend for the status percentage * @return null */ function html_status_percentage_legend() { $t_status_percents = get_percentage_by_status(); $t_status_enum_string = config_get('status_enum_string'); $t_enum_values = MantisEnum::getValues($t_status_enum_string); $enum_count = count($t_enum_values); $t_bug_count = array_sum($t_status_percents); if ($t_bug_count > 0) { echo '<br />'; echo '<table class="width100" cellspacing="1">'; echo '<tr>'; echo '<td class="form-title" colspan="' . $enum_count . '">' . lang_get('issue_status_percentage') . '</td>'; echo '</tr>'; echo '<tr>'; foreach ($t_enum_values as $t_status) { $t_percent = isset($t_status_percents[$t_status]) ? $t_status_percents[$t_status] : 0; if ($t_percent > 0) { $t_status_label = MantisEnum::getLabel($t_status_enum_string, $t_status); echo "<td class=\"small-caption-center {$t_status_label}-color {$t_status_label}-percentage\">{$t_percent}%</td>"; } } echo '</tr>'; echo '</table>'; } }