/core/filter_api.php
PHP | 2807 lines | 1837 code | 306 blank | 664 comment | 383 complexity | 98338e639df80d626dce598436f65169 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- <?php
- # MantisBT - A PHP based bugtracking system
- # MantisBT is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 2 of the License, or
- # (at your option) any later version.
- #
- # MantisBT is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with MantisBT. If not, see <http://www.gnu.org/licenses/>.
- /**
- * Filter API
- *
- * @package CoreAPI
- * @subpackage FilterAPI
- * @copyright Copyright 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
- * @copyright Copyright 2002 MantisBT Team - mantisbt-dev@lists.sourceforge.net
- * @link http://www.mantisbt.org
- *
- * @uses access_api.php
- * @uses authentication_api.php
- * @uses bug_api.php
- * @uses collapse_api.php
- * @uses columns_api.php
- * @uses config_api.php
- * @uses constant_inc.php
- * @uses current_user_api.php
- * @uses custom_field_api.php
- * @uses database_api.php
- * @uses date_api.php
- * @uses error_api.php
- * @uses event_api.php
- * @uses filter_constants_inc.php
- * @uses gpc_api.php
- * @uses helper_api.php
- * @uses lang_api.php
- * @uses logging_api.php
- * @uses print_api.php
- * @uses profile_api.php
- * @uses project_api.php
- * @uses relationship_api.php
- * @uses session_api.php
- * @uses string_api.php
- * @uses tag_api.php
- * @uses user_api.php
- * @uses utility_api.php
- * @uses version_api.php
- * @uses filter_form_api.php
- */
- require_api( 'access_api.php' );
- require_api( 'authentication_api.php' );
- require_api( 'bug_api.php' );
- require_api( 'collapse_api.php' );
- require_api( 'columns_api.php' );
- require_api( 'config_api.php' );
- require_api( 'constant_inc.php' );
- require_api( 'current_user_api.php' );
- require_api( 'custom_field_api.php' );
- require_api( 'database_api.php' );
- require_api( 'date_api.php' );
- require_api( 'error_api.php' );
- require_api( 'event_api.php' );
- require_api( 'filter_constants_inc.php' );
- require_api( 'gpc_api.php' );
- require_api( 'helper_api.php' );
- require_api( 'lang_api.php' );
- require_api( 'logging_api.php' );
- require_api( 'print_api.php' );
- require_api( 'profile_api.php' );
- require_api( 'project_api.php' );
- require_api( 'relationship_api.php' );
- require_api( 'session_api.php' );
- require_api( 'string_api.php' );
- require_api( 'tag_api.php' );
- require_api( 'user_api.php' );
- require_api( 'utility_api.php' );
- require_api( 'version_api.php' );
- require_api( 'filter_form_api.php' );
- # @global array $g_filter Filter array for the filter in use through view_all_bug_page
- # This gets initialized on filter load
- # @TODO cproensa We should move towards not relying on this variable, as we reuse filter logic
- # to allow operating on other filter different that the one in use for view_all_bug_page.
- # For example: manage and edit stored filters.
- $g_filter = null;
- # ==========================================================================
- # CACHING
- # ==========================================================================
- # We cache filter requests to reduce the number of SQL queries
- # @global array $g_cache_filter_db_rows
- # indexed by filter_id, contains the filter rows as read from db table
- $g_cache_filter_db_rows = array();
- # @global array $g_cache_filter_subquery
- # indexed by a hash of the filter array, contains a prebuilt BugFilterQuery object
- $g_cache_filter_subquery = array();
- /**
- * Initialize the filter API with the current filter.
- * @param array $p_filter The filter to set as the current filter.
- */
- function filter_init( $p_filter ) {
- global $g_filter;
- $g_filter = $p_filter;
- }
- /**
- * Allow plugins to define a set of class-based filters, and register/load
- * them here to be used by the rest of filter_api.
- * @return array Mapping of field name to filter object
- */
- function filter_get_plugin_filters() {
- static $s_field_array = null;
- if( is_null( $s_field_array ) ) {
- $s_field_array = array();
- $t_all_plugin_filters = event_signal( 'EVENT_FILTER_FIELDS' );
- foreach( $t_all_plugin_filters as $t_plugin => $t_plugin_filters ) {
- foreach( $t_plugin_filters as $t_callback => $t_plugin_filter_array ) {
- if( is_array( $t_plugin_filter_array ) ) {
- foreach( $t_plugin_filter_array as $t_filter_item ) {
- if( is_object( $t_filter_item ) && $t_filter_item instanceof MantisFilter ) {
- $t_filter_object = $t_filter_item;
- } elseif( class_exists( $t_filter_item ) && is_subclass_of( $t_filter_item, 'MantisFilter' ) ) {
- $t_filter_object = new $t_filter_item();
- } else {
- continue;
- }
- $t_filter_name = mb_strtolower( $t_plugin . '_' . $t_filter_object->field );
- $s_field_array[$t_filter_name] = $t_filter_object;
- }
- }
- }
- }
- }
- return $s_field_array;
- }
- /**
- * Get a permanent link for the current active filter. The results of using these fields by other users
- * can be inconsistent with the original results due to fields like "Myself", "Current Project",
- * and due to access level.
- * @param array $p_custom_filter Array containing a custom filter definition.
- * @return string the search.php?xxxx or an empty string if no criteria applied.
- */
- function filter_get_url( array $p_custom_filter ) {
- $t_query = array();
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_PROJECT_ID] ) ) {
- $t_project_id = $p_custom_filter[FILTER_PROPERTY_PROJECT_ID];
- if( count( $t_project_id ) == 1 && $t_project_id[0] == META_FILTER_CURRENT ) {
- $t_project_id = array(
- helper_get_current_project(),
- );
- }
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_PROJECT_ID, $t_project_id );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_SEARCH] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_SEARCH, $p_custom_filter[FILTER_PROPERTY_SEARCH] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_CATEGORY_ID] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_CATEGORY_ID, $p_custom_filter[FILTER_PROPERTY_CATEGORY_ID] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_REPORTER_ID] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_REPORTER_ID, $p_custom_filter[FILTER_PROPERTY_REPORTER_ID] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_STATUS] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_STATUS, $p_custom_filter[FILTER_PROPERTY_STATUS] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_MONITOR_USER_ID] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_MONITOR_USER_ID, $p_custom_filter[FILTER_PROPERTY_MONITOR_USER_ID] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_HANDLER_ID] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_HANDLER_ID, $p_custom_filter[FILTER_PROPERTY_HANDLER_ID] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_NOTE_USER_ID] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_NOTE_USER_ID, $p_custom_filter[FILTER_PROPERTY_NOTE_USER_ID] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_SEVERITY] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_SEVERITY, $p_custom_filter[FILTER_PROPERTY_SEVERITY] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_RESOLUTION] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_RESOLUTION, $p_custom_filter[FILTER_PROPERTY_RESOLUTION] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_PRIORITY] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_PRIORITY, $p_custom_filter[FILTER_PROPERTY_PRIORITY] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_VIEW_STATE] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_VIEW_STATE, $p_custom_filter[FILTER_PROPERTY_VIEW_STATE] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_STICKY] ) ) {
- $t_query[] = filter_encode_field_and_value(
- FILTER_PROPERTY_STICKY,
- $p_custom_filter[FILTER_PROPERTY_STICKY] ? 'on' : 'off' );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_VERSION] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_VERSION, $p_custom_filter[FILTER_PROPERTY_VERSION] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_BUILD] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_BUILD, $p_custom_filter[FILTER_PROPERTY_BUILD] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_FIXED_IN_VERSION] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_FIXED_IN_VERSION, $p_custom_filter[FILTER_PROPERTY_FIXED_IN_VERSION] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_TARGET_VERSION] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_TARGET_VERSION, $p_custom_filter[FILTER_PROPERTY_TARGET_VERSION] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_SORT_FIELD_NAME] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_SORT_FIELD_NAME, $p_custom_filter[FILTER_PROPERTY_SORT_FIELD_NAME] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_SORT_DIRECTION] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_SORT_DIRECTION, $p_custom_filter[FILTER_PROPERTY_SORT_DIRECTION] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_ISSUES_PER_PAGE] ) ) {
- if( $p_custom_filter[FILTER_PROPERTY_ISSUES_PER_PAGE] != config_get( 'default_limit_view' ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_ISSUES_PER_PAGE, $p_custom_filter[FILTER_PROPERTY_ISSUES_PER_PAGE] );
- }
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED] ) ) {
- if( $p_custom_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED] != config_get( 'default_show_changed' ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_HIGHLIGHT_CHANGED, $p_custom_filter[FILTER_PROPERTY_HIGHLIGHT_CHANGED] );
- }
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_HIDE_STATUS] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_HIDE_STATUS, $p_custom_filter[FILTER_PROPERTY_HIDE_STATUS] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_FILTER_BY_DATE_SUBMITTED] ) ) {
- $t_query[] = filter_encode_field_and_value(
- FILTER_PROPERTY_FILTER_BY_DATE_SUBMITTED,
- $p_custom_filter[FILTER_PROPERTY_FILTER_BY_DATE_SUBMITTED] ? 'on' : 'off' );
- # The start and end dates are only applicable if filter by date is set.
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_DATE_SUBMITTED_START_DAY] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_DATE_SUBMITTED_START_DAY, $p_custom_filter[FILTER_PROPERTY_DATE_SUBMITTED_START_DAY] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_DATE_SUBMITTED_END_DAY] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_DATE_SUBMITTED_END_DAY, $p_custom_filter[FILTER_PROPERTY_DATE_SUBMITTED_END_DAY] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_DATE_SUBMITTED_START_MONTH] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_DATE_SUBMITTED_START_MONTH, $p_custom_filter[FILTER_PROPERTY_DATE_SUBMITTED_START_MONTH] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_DATE_SUBMITTED_END_MONTH] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_DATE_SUBMITTED_END_MONTH, $p_custom_filter[FILTER_PROPERTY_DATE_SUBMITTED_END_MONTH] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_DATE_SUBMITTED_START_YEAR] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_DATE_SUBMITTED_START_YEAR, $p_custom_filter[FILTER_PROPERTY_DATE_SUBMITTED_START_YEAR] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_DATE_SUBMITTED_END_YEAR] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_DATE_SUBMITTED_END_YEAR, $p_custom_filter[FILTER_PROPERTY_DATE_SUBMITTED_END_YEAR] );
- }
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_FILTER_BY_LAST_UPDATED_DATE] ) ) {
- $t_query[] = filter_encode_field_and_value(
- FILTER_PROPERTY_FILTER_BY_LAST_UPDATED_DATE,
- $p_custom_filter[FILTER_PROPERTY_FILTER_BY_LAST_UPDATED_DATE] ? 'on' : 'off' );
- # The start and end dates are only applicable if filter by date is set.
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_LAST_UPDATED_START_DAY] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_LAST_UPDATED_START_DAY, $p_custom_filter[FILTER_PROPERTY_LAST_UPDATED_START_DAY] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_LAST_UPDATED_END_DAY] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_LAST_UPDATED_END_DAY, $p_custom_filter[FILTER_PROPERTY_LAST_UPDATED_END_DAY] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_LAST_UPDATED_START_MONTH] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_LAST_UPDATED_START_MONTH, $p_custom_filter[FILTER_PROPERTY_LAST_UPDATED_START_MONTH] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_LAST_UPDATED_END_MONTH] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_LAST_UPDATED_END_MONTH, $p_custom_filter[FILTER_PROPERTY_LAST_UPDATED_END_MONTH] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_LAST_UPDATED_START_YEAR] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_LAST_UPDATED_START_YEAR, $p_custom_filter[FILTER_PROPERTY_LAST_UPDATED_START_YEAR] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_LAST_UPDATED_END_YEAR] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_LAST_UPDATED_END_YEAR, $p_custom_filter[FILTER_PROPERTY_LAST_UPDATED_END_YEAR] );
- }
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE] ) ) {
- if( $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE] != -1 ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_RELATIONSHIP_TYPE, $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_TYPE] );
- }
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_BUG] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_RELATIONSHIP_BUG, $p_custom_filter[FILTER_PROPERTY_RELATIONSHIP_BUG] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_PLATFORM] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_PLATFORM, $p_custom_filter[FILTER_PROPERTY_PLATFORM] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_OS] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_OS, $p_custom_filter[FILTER_PROPERTY_OS] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_OS_BUILD] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_OS_BUILD, $p_custom_filter[FILTER_PROPERTY_OS_BUILD] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_TAG_STRING] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_TAG_STRING, $p_custom_filter[FILTER_PROPERTY_TAG_STRING] );
- }
- if( !filter_field_is_any( $p_custom_filter[FILTER_PROPERTY_TAG_SELECT] ) ) {
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_TAG_SELECT, $p_custom_filter[FILTER_PROPERTY_TAG_SELECT] );
- }
- $t_query[] = filter_encode_field_and_value( FILTER_PROPERTY_MATCH_TYPE, $p_custom_filter[FILTER_PROPERTY_MATCH_TYPE] );
- if( isset( $p_custom_filter['custom_fields'] ) ) {
- foreach( $p_custom_filter['custom_fields'] as $t_custom_field_id => $t_custom_field_values ) {
- if( !filter_field_is_any( $t_custom_field_values ) ) {
- $t_query[] = filter_encode_field_and_value( 'custom_field_' . $t_custom_field_id, $t_custom_field_values );
- }
- }
- }
- # Allow plugins to add filter fields
- $t_plugin_filter_array = filter_get_plugin_filters();
- foreach( $t_plugin_filter_array as $t_field_name => $t_filter_object ) {
- if( !filter_field_is_any( $p_custom_filter[$t_field_name] ) ) {
- $t_query[] = filter_encode_field_and_value( $t_field_name, $p_custom_filter[$t_field_name], $t_filter_object->type );
- }
- }
- if( count( $t_query ) > 0 ) {
- $t_query_str = implode( '&', $t_query );
- $t_url = config_get_global( 'path' ) . 'search.php?' . $t_query_str;
- } else {
- $t_url = '';
- }
- return $t_url;
- }
- /**
- * Encodes a field and it's value for the filter URL. This handles the URL encoding and arrays.
- * @param string $p_field_name The field name.
- * @param string $p_field_value The field value (can be an array).
- * @param integer $p_field_type Field Type e.g. FILTER_TYPE_MULTI_STRING.
- * @return string url encoded string
- */
- function filter_encode_field_and_value( $p_field_name, $p_field_value, $p_field_type = null ) {
- $t_query_array = array();
- if( is_array( $p_field_value ) ) {
- $t_count = count( $p_field_value );
- if( $t_count > 1 || $p_field_type == FILTER_TYPE_MULTI_STRING || $p_field_type == FILTER_TYPE_MULTI_INT ) {
- foreach( $p_field_value as $t_value ) {
- $t_query_array[] = urlencode( $p_field_name . '[]' ) . '=' . urlencode( $t_value );
- }
- } else if( $t_count == 1 ) {
- $t_query_array[] = urlencode( $p_field_name ) . '=' . urlencode( $p_field_value[0] );
- }
- } else {
- $t_query_array[] = urlencode( $p_field_name ) . '=' . urlencode( $p_field_value );
- }
- return implode( '&', $t_query_array );
- }
- /**
- * Checks the supplied value to see if it is an ANY value.
- * @param string $p_field_value The value to check.
- * @return boolean true for "ANY" values and false for others. "ANY" means filter criteria not active.
- */
- function filter_field_is_any( $p_field_value ) {
- if( is_array( $p_field_value ) ) {
- if( count( $p_field_value ) == 0 ) {
- return true;
- }
- foreach( $p_field_value as $t_value ) {
- if( ( META_FILTER_ANY == $t_value ) && ( is_numeric( $t_value ) ) ) {
- return true;
- }
- }
- } else {
- if( is_string( $p_field_value ) && is_blank( $p_field_value ) ) {
- return true;
- }
- if( is_bool( $p_field_value ) && !$p_field_value ) {
- return true;
- }
- if( ( META_FILTER_ANY == $p_field_value ) && ( is_numeric( $p_field_value ) ) ) {
- return true;
- }
- }
- return false;
- }
- /**
- * Checks the supplied value to see if it is a NONE value.
- * @param string $p_field_value The value to check.
- * @return boolean true for "NONE" values and false for others.
- * @todo is a check for these necessary? if( ( $t_filter_value === 'none' ) || ( $t_filter_value === '[none]' ) )
- */
- function filter_field_is_none( $p_field_value ) {
- if( is_array( $p_field_value ) ) {
- foreach( $p_field_value as $t_value ) {
- if( ( META_FILTER_NONE == $t_value ) && ( is_numeric( $t_value ) ) ) {
- return true;
- }
- }
- } else {
- if( is_string( $p_field_value ) && is_blank( $p_field_value ) ) {
- return false;
- }
- if( ( META_FILTER_NONE == $p_field_value ) && ( is_numeric( $p_field_value ) ) ) {
- return true;
- }
- }
- return false;
- }
- /**
- * Checks the supplied value to see if it is a MYSELF value.
- * @param string $p_field_value The value to check.
- * @return boolean true for "MYSELF" values and false for others.
- */
- function filter_field_is_myself( $p_field_value ) {
- return( META_FILTER_MYSELF == $p_field_value ? true : false );
- }
- /**
- * Filter per page
- * @param array $p_filter Filter.
- * @param integer $p_count Count.
- * @param integer $p_per_page Per page.
- * @return integer
- */
- function filter_per_page( array $p_filter, $p_count, $p_per_page ) {
- $p_per_page = (( null == $p_per_page ) ? (int)$p_filter[FILTER_PROPERTY_ISSUES_PER_PAGE] : $p_per_page );
- $p_per_page = (( 0 == $p_per_page || -1 == $p_per_page ) ? $p_count : $p_per_page );
- return (int)abs( $p_per_page );
- }
- /**
- * Use $p_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.
- * @param integer $p_count Count.
- * @param integer $p_per_page Per page.
- * @return integer page count
- */
- function filter_page_count( $p_count, $p_per_page ) {
- $t_page_count = ceil( $p_count / $p_per_page );
- if( $t_page_count < 1 ) {
- $t_page_count = 1;
- }
- return $t_page_count;
- }
- /**
- * Checks to make sure $p_page_number isn't past the last page.
- * and that $p_page_number isn't before the first page
- * @param integer $p_page_number Page number.
- * @param integer $p_page_count Page count.
- * @return integer
- */
- function filter_valid_page_number( $p_page_number, $p_page_count ) {
- if( $p_page_number > $p_page_count ) {
- $p_page_number = $p_page_count;
- }
- if( $p_page_number < 1 ) {
- $p_page_number = 1;
- }
- return $p_page_number;
- }
- /**
- * Figure out the offset into the db query, offset is which record to start querying from
- * @param integer $p_page_number Page number.
- * @param integer $p_per_page Per page.
- * @return integer
- */
- function filter_offset( $p_page_number, $p_per_page ) {
- return(( (int)$p_page_number -1 ) * (int)$p_per_page );
- }
- /**
- * Make sure the filter array contains all the fields. If any field is missing,
- * create it with a default value.
- * @param array $p_filter_arr Input filter array
- * @return array Processed filter array
- */
- function filter_ensure_fields( array $p_filter_arr ) {
- # Fill missing filter properties with defaults
- if( isset( $p_filter_arr['_view_type'] ) ) {
- $t_filter_default = filter_get_default_array( $p_filter_arr['_view_type'] );
- } else {
- $t_filter_default = filter_get_default_array();
- }
- foreach( $t_filter_default as $t_key => $t_default_value ) {
- if( !isset( $p_filter_arr[$t_key] ) ) {
- $p_filter_arr[$t_key] = $t_default_value;
- }
- }
- # Veryfy custom fields
- foreach( $t_filter_default['custom_fields'] as $t_cfid => $t_cf_data ) {
- if( !isset( $p_filter_arr['custom_fields'][$t_cfid] ) ) {
- $p_filter_arr['custom_fields'][$t_cfid] = $t_cf_data;
- }
- }
- return $p_filter_arr;
- }
- /**
- * A wrapper to compare filter version syntax
- * Note: Currently, filter versions have this syntax: "vN", * where N is an integer number.
- * @param string $p_version1 First version number
- * @param string $p_version2 Second version number
- * @param string $p_operator Comparison test, if provided. As expected by version_compare()
- * @return mixed As returned by version_compare()
- */
- function filter_version_compare( $p_version1, $p_version2, $p_operator = null ) {
- return version_compare( $p_version1, $p_version2, $p_operator );
- }
- /**
- * Upgrade a filter array to the current filter structure, by converting properties
- * that have changed from previous filter versions
- * @param array $p_filter Filter array to upgrade
- * @return array Updgraded filter array
- */
- function filter_version_upgrade( array $p_filter ) {
- # This is a stub for future version upgrades
- # After conversions are made, update filter value to current version
- $p_filter['_version'] = FILTER_VERSION;
- return $p_filter;
- }
- /**
- * Make sure that our filters are entirely correct and complete (it is possible that they are not).
- * We need to do this to cover cases where we don't have complete control over the filters given.
- * @param array $p_filter_arr A filter array
- * @return array Validated filter array
- */
- function filter_ensure_valid_filter( array $p_filter_arr ) {
- if( !isset( $p_filter_arr['_version'] ) ) {
- $p_filter_arr['_version'] = FILTER_VERSION;
- }
- if( filter_version_compare( $p_filter_arr['_version'], FILTER_VERSION, '<' ) ) {
- $p_filter_arr = filter_version_upgrade( $p_filter_arr );
- }
- $p_filter_arr = filter_ensure_fields( $p_filter_arr );
- $t_config_view_filters = config_get( 'view_filters' );
- $t_view_type = $p_filter_arr['_view_type'];
- if( ADVANCED_ONLY == $t_config_view_filters ) {
- $t_view_type = FILTER_VIEW_TYPE_ADVANCED;
- }
- if( SIMPLE_ONLY == $t_config_view_filters ) {
- $t_view_type = FILTER_VIEW_TYPE_SIMPLE;
- }
- if( !in_array( $t_view_type, array( FILTER_VIEW_TYPE_SIMPLE, FILTER_VIEW_TYPE_ADVANCED ) ) ) {
- $t_view_type = filter_get_default_view_type();
- }
- $p_filter_arr['_view_type'] = $t_view_type;
- $t_sort_fields = explode( ',', $p_filter_arr[FILTER_PROPERTY_SORT_FIELD_NAME] );
- $t_dir_fields = explode( ',', $p_filter_arr[FILTER_PROPERTY_SORT_DIRECTION] );
- # both arrays should be equal length, just in case
- $t_sort_fields_count = min( count( $t_sort_fields ), count( $t_dir_fields ) );
- # clean up sort fields, remove invalid columns
- $t_new_sort_array = array();
- $t_new_dir_array = array();
- $t_all_columns = columns_get_all_active_columns();
- for( $ix = 0; $ix < $t_sort_fields_count; $ix++ ) {
- if( isset( $t_sort_fields[$ix] ) ) {
- $t_column = $t_sort_fields[$ix];
- # check that the column name exist
- if( !in_array( $t_column, $t_all_columns ) ) {
- continue;
- }
- # check that it has not been already used
- if( in_array( $t_column, $t_new_sort_array ) ) {
- continue;
- }
- # check that it is sortable
- if( !column_is_sortable( $t_column ) ) {
- continue;
- }
- $t_new_sort_array[] = $t_column;
- # if there is no dir field, set a dummy value
- if( isset( $t_dir_fields[$ix] ) ) {
- $t_dir = $t_dir_fields[$ix];
- } else {
- $t_dir = '';
- }
- # normalize sort_dir value
- $t_dir = ( $t_dir == 'ASC' ) ? 'ASC' : 'DESC';
- $t_new_dir_array[] = $t_dir;
- }
- }
- if( count( $t_new_sort_array ) > 0 ) {
- $p_filter_arr[FILTER_PROPERTY_SORT_FIELD_NAME] = implode( ',', $t_new_sort_array );
- $p_filter_arr[FILTER_PROPERTY_SORT_DIRECTION] = implode( ',', $t_new_dir_array );
- } else {
- $p_filter_arr[FILTER_PROPERTY_SORT_FIELD_NAME] = filter_get_default_property( FILTER_PROPERTY_SORT_FIELD_NAME, $t_view_type );
- $p_filter_arr[FILTER_PROPERTY_SORT_DIRECTION] = filter_get_default_property( FILTER_PROPERTY_SORT_DIRECTION, $t_view_type );
- }
- # Validate types for values.
- # helper function to validate types
- $t_function_validate_type = function( $p_value, $p_type ) {
- $t_value = stripslashes( $p_value );
- if( ( $t_value === 'any' ) || ( $t_value === '[any]' ) ) {
- $t_value = META_FILTER_ANY;
- }
- if( ( $t_value === 'none' ) || ( $t_value === '[none]' ) ) {
- $t_value = META_FILTER_NONE;
- }
- # Ensure the filter property has the right type - see #20087
- switch( $p_type ) {
- case 'string' :
- case 'int' :
- settype( $t_value, $p_type );
- break;
- }
- return $t_value;
- };
- # Validate properties that must not be arrays
- $t_single_value_list = array(
- FILTER_PROPERTY_VIEW_STATE => 'int',
- FILTER_PROPERTY_RELATIONSHIP_TYPE => 'int',
- FILTER_PROPERTY_RELATIONSHIP_BUG => 'int',
- );
- foreach( $t_single_value_list as $t_field_name => $t_field_type ) {
- $t_value = $p_filter_arr[$t_field_name];
- if( is_array( $t_value ) ) {
- if( count( $t_value ) > 0 ) {
- $p_filter_arr[$t_field_name] = reset( $t_value );
- } else {
- $p_filter_arr[$t_field_name] = filter_get_default_property( $t_field_name, $t_view_type );
- }
- }
- $p_filter_arr[$t_field_name] = $t_function_validate_type( $p_filter_arr[$t_field_name], $t_field_type );
- }
- # Validate properties that must be arrays, and the type of its elements
- $t_array_values_list = array(
- FILTER_PROPERTY_CATEGORY_ID => 'string',
- FILTER_PROPERTY_SEVERITY => 'int',
- FILTER_PROPERTY_STATUS => 'int',
- FILTER_PROPERTY_REPORTER_ID => 'int',
- FILTER_PROPERTY_HANDLER_ID => 'int',
- FILTER_PROPERTY_NOTE_USER_ID => 'int',
- FILTER_PROPERTY_RESOLUTION => 'int',
- FILTER_PROPERTY_PRIORITY => 'int',
- FILTER_PROPERTY_BUILD => 'string',
- FILTER_PROPERTY_VERSION => 'string',
- FILTER_PROPERTY_HIDE_STATUS => 'int',
- FILTER_PROPERTY_FIXED_IN_VERSION => 'string',
- FILTER_PROPERTY_TARGET_VERSION => 'string',
- FILTER_PROPERTY_MONITOR_USER_ID => 'int',
- FILTER_PROPERTY_PROFILE_ID => 'int',
- FILTER_PROPERTY_PLATFORM => 'string',
- FILTER_PROPERTY_OS => 'string',
- FILTER_PROPERTY_OS_BUILD => 'string',
- FILTER_PROPERTY_PROJECT_ID => 'int'
- );
- foreach( $t_array_values_list as $t_multi_field_name => $t_multi_field_type ) {
- if( !is_array( $p_filter_arr[$t_multi_field_name] ) ) {
- $p_filter_arr[$t_multi_field_name] = array(
- $p_filter_arr[$t_multi_field_name],
- );
- }
- $t_checked_array = array();
- foreach( $p_filter_arr[$t_multi_field_name] as $t_filter_value ) {
- $t_checked_array[] = $t_function_validate_type( $t_filter_value, $t_multi_field_type );
- }
- $p_filter_arr[$t_multi_field_name] = $t_checked_array;
- }
- $t_custom_fields = custom_field_get_ids();
- if( is_array( $t_custom_fields ) && ( count( $t_custom_fields ) > 0 ) ) {
- foreach( $t_custom_fields as $t_cfid ) {
- if( isset( $p_filter_arr['custom_fields'][$t_cfid]) ) {
- if( !is_array( $p_filter_arr['custom_fields'][$t_cfid] ) ) {
- $p_filter_arr['custom_fields'][$t_cfid] = array(
- $p_filter_arr['custom_fields'][$t_cfid],
- );
- }
- $t_checked_array = array();
- foreach( $p_filter_arr['custom_fields'][$t_cfid] as $t_filter_value ) {
- $t_filter_value = stripslashes( $t_filter_value );
- if( ( $t_filter_value === 'any' ) || ( $t_filter_value === '[any]' ) ) {
- $t_filter_value = META_FILTER_ANY;
- }
- $t_checked_array[] = $t_filter_value;
- }
- $p_filter_arr['custom_fields'][$t_cfid] = $t_checked_array;
- }
- }
- }
- # If view_type is advanced, and hide_status is present, modify status array
- # to remove hidden status. This may happen after switching from simple to advanced.
- # Then, remove hide_status property, as it does not apply to advanced filter
- if( $p_filter_arr['_view_type'] == FILTER_VIEW_TYPE_ADVANCED
- && !filter_field_is_none( $p_filter_arr[FILTER_PROPERTY_HIDE_STATUS] ) ) {
- if( filter_field_is_any( $p_filter_arr[FILTER_PROPERTY_STATUS] ) ) {
- $t_selected_status_array = MantisEnum::getValues( config_get( 'status_enum_string' ) );
- } else {
- $t_selected_status_array = $p_filter_arr[FILTER_PROPERTY_STATUS];
- }
- $t_hide_status = $p_filter_arr[FILTER_PROPERTY_HIDE_STATUS][0];
- $t_new_status_array = array();
- foreach( $t_selected_status_array as $t_status ) {
- if( $t_status < $t_hide_status ) {
- $t_new_status_array[] = $t_status;
- }
- }
- # If there is no status left, reset the status property to "any"
- if( empty( $t_new_status_array ) ) {
- $t_new_status_array[] = META_FILTER_ANY;
- }
- $p_filter_arr[FILTER_PROPERTY_STATUS] = $t_new_status_array;
- $p_filter_arr[FILTER_PROPERTY_HIDE_STATUS] = META_FILTER_NONE;
- }
- #If view_type is simple, resolve conflicts between show_status and hide_status
- if( $p_filter_arr['_view_type'] == FILTER_VIEW_TYPE_SIMPLE
- && !filter_field_is_none( $p_filter_arr[FILTER_PROPERTY_HIDE_STATUS] ) ) {
- # get array of hidden status ids
- $t_all_status = MantisEnum::getValues( config_get( 'status_enum_string' ) );
- $t_hidden_status = $p_filter_arr[FILTER_PROPERTY_HIDE_STATUS][0];
- $t_hidden_status_array = array();
- foreach( $t_all_status as $t_status ) {
- if( $t_status >= $t_hidden_status ) {
- $t_hidden_status_array[] = $t_status;
- }
- }
- # remove hidden status from show_status property array
- # note that this will keep the "any" meta value, if present
- $t_show_status_array = array_diff( $p_filter_arr[FILTER_PROPERTY_STATUS], $t_hidden_status_array );
- # If there is no status left, reset the status property previous values, and remove hide_status
- if( empty( $t_show_status_array ) ) {
- $t_show_status_array = $p_filter_arr[FILTER_PROPERTY_STATUS];
- $p_filter_arr[FILTER_PROPERTY_HIDE_STATUS] = META_FILTER_NONE;
- }
- $p_filter_arr[FILTER_PROPERTY_STATUS] = $t_show_status_array;
- }
- # validate relationship fields
- if( !(
- $p_filter_arr[FILTER_PROPERTY_RELATIONSHIP_BUG] > 0
- || $p_filter_arr[FILTER_PROPERTY_RELATIONSHIP_BUG] == META_FILTER_ANY
- || $p_filter_arr[FILTER_PROPERTY_RELATIONSHIP_BUG] == META_FILTER_NONE
- ) ) {
- $p_filter_arr[FILTER_PROPERTY_RELATIONSHIP_BUG] = filter_get_default_property( FILTER_PROPERTY_RELATIONSHIP_BUG, $t_view_type );
- }
- # all of our filter values are now guaranteed to be there, and correct.
- return $p_filter_arr;
- }
- /**
- * Get a filter array with default values
- * Optional view type parameter is used to initialize some fields properly,
- * as some may differ in the default content.
- * @param string $p_view_type FILTER_VIEW_TYPE_SIMPLE or FILTER_VIEW_TYPE_ADVANCED
- * @return array Filter array with default values
- */
- function filter_get_default_array( $p_view_type = null ) {
- static $t_cache_default_array = array();
- $t_default_view_type = filter_get_default_view_type();
- if( !in_array( $p_view_type, array( FILTER_VIEW_TYPE_SIMPLE, FILTER_VIEW_TYPE_ADVANCED ) ) ) {
- $p_view_type = $t_default_view_type;
- }
- # this function is called multiple times from filter api so return a cached value if possible
- if( isset( $t_cache_default_array[$p_view_type] ) ) {
- return $t_cache_default_array[$p_view_type];
- }
- $t_default_show_changed = config_get( 'default_show_changed' );
- $t_meta_filter_any_array = array( META_FILTER_ANY );
- $t_config_view_filters = config_get( 'view_filters' );
- if( ADVANCED_ONLY == $t_config_view_filters ) {
- $t_view_type = FILTER_VIEW_TYPE_ADVANCED;
- } elseif( SIMPLE_ONLY == $t_config_view_filters ) {
- $t_view_type = FILTER_VIEW_TYPE_SIMPLE;
- } else {
- $t_view_type = $p_view_type;
- }
- if( $t_view_type == FILTER_VIEW_TYPE_SIMPLE ) {
- $t_hide_status_default = config_get( 'hide_status_default' );
- } else {
- $t_hide_status_default = META_FILTER_NONE;
- }
- $t_filter = array(
- '_version' => FILTER_VERSION,
- '_view_type' => $t_view_type,
- FILTER_PROPERTY_CATEGORY_ID => $t_meta_filter_any_array,
- FILTER_PROPERTY_SEVERITY => $t_meta_filter_any_array,
- FILTER_PROPERTY_STATUS => $t_meta_filter_any_array,
- FILTER_PROPERTY_HIGHLIGHT_CHANGED => $t_default_show_changed,
- FILTER_PROPERTY_REPORTER_ID => $t_meta_filter_any_array,
- FILTER_PROPERTY_HANDLER_ID => $t_meta_filter_any_array,
- FILTER_PROPERTY_PROJECT_ID => array( META_FILTER_CURRENT ),
- FILTER_PROPERTY_RESOLUTION => $t_meta_filter_any_array,
- FILTER_PROPERTY_BUILD => $t_meta_filter_any_array,
- FILTER_PROPERTY_VERSION => $t_meta_filter_any_array,
- FILTER_PROPERTY_HIDE_STATUS => array( $t_hide_status_default ),
- FILTER_PROPERTY_MONITOR_USER_ID => $t_meta_filter_any_array,
- FILTER_PROPERTY_SORT_FIELD_NAME => 'last_updated',
- FILTER_PROPERTY_SORT_DIRECTION => 'DESC',
- FILTER_PROPERTY_ISSUES_PER_PAGE => config_get( 'default_limit_view' ),
- FILTER_PROPERTY_MATCH_TYPE => FILTER_MATCH_ALL,
- FILTER_PROPERTY_PLATFORM => $t_meta_filter_any_array,
- FILTER_PROPERTY_OS => $t_meta_filter_any_array,
- FILTER_PROPERTY_OS_BUILD => $t_meta_filter_any_array,
- FILTER_PROPERTY_FIXED_IN_VERSION => $t_meta_filter_any_array,
- FILTER_PROPERTY_TARGET_VERSION => $t_meta_filter_any_array,
- FILTER_PROPERTY_PROFILE_ID => $t_meta_filter_any_array,
- FILTER_PROPERTY_PRIORITY => $t_meta_filter_any_array,
- FILTER_PROPERTY_NOTE_USER_ID => $t_meta_filter_any_array,
- FILTER_PROPERTY_STICKY => gpc_string_to_bool( config_get( 'show_sticky_issues' ) ),
- FILTER_PROPERTY_FILTER_BY_DATE_SUBMITTED => false,
- FILTER_PROPERTY_DATE_SUBMITTED_START_MONTH => date( 'm' ),
- FILTER_PROPERTY_DATE_SUBMITTED_END_MONTH => date( 'm' ),
- FILTER_PROPERTY_DATE_SUBMITTED_START_DAY => 1,
- FILTER_PROPERTY_DATE_SUBMITTED_END_DAY => date( 'd' ),
- FILTER_PROPERTY_DATE_SUBMITTED_START_YEAR => date( 'Y' ),
- FILTER_PROPERTY_DATE_SUBMITTED_END_YEAR => date( 'Y' ),
- FILTER_PROPERTY_FILTER_BY_LAST_UPDATED_DATE => false,
- FILTER_PROPERTY_LAST_UPDATED_START_MONTH => date( 'm' ),
- FILTER_PROPERTY_LAST_UPDATED_END_MONTH => date( 'm' ),
- FILTER_PROPERTY_LAST_UPDATED_START_DAY => 1,
- FILTER_PROPERTY_LAST_UPDATED_END_DAY => date( 'd' ),
- FILTER_PROPERTY_LAST_UPDATED_START_YEAR => date( 'Y' ),
- FILTER_PROPERTY_LAST_UPDATED_END_YEAR => date( 'Y' ),
- FILTER_PROPERTY_SEARCH => '',
- FILTER_PROPERTY_VIEW_STATE => META_FILTER_ANY,
- FILTER_PROPERTY_TAG_STRING => '',
- FILTER_PROPERTY_TAG_SELECT => 0,
- FILTER_PROPERTY_RELATIONSHIP_TYPE => BUG_REL_ANY,
- FILTER_PROPERTY_RELATIONSHIP_BUG => META_FILTER_ANY,
- );
- # initialize plugin filters
- $t_plugin_filters = filter_get_plugin_filters();
- foreach( $t_plugin_filters as $t_field_name => $t_filter_object ) {
- switch( $t_filter_object->type ) {
- case FILTER_TYPE_STRING:
- $t_filter[$t_field_name] = $t_filter_object->default;
- break;
- case FILTER_TYPE_INT:
- $t_filter[$t_field_name] = (int)$t_filter_object->default;
- break;
- case FILTER_TYPE_BOOLEAN:
- $t_filter[$t_field_name] = (bool)$t_filter_object->default;
- break;
- case FILTER_TYPE_MULTI_STRING:
- $t_filter[$t_field_name] = array( (string)META_FILTER_ANY );
- break;
- case FILTER_TYPE_MULTI_INT:
- $t_filter[$t_field_name] = array( META_FILTER_ANY );
- break;
- default:
- $t_filter[$t_field_name] = (string)META_FILTER_ANY;
- }
- if( !$t_filter_object->validate( $t_filter[$t_field_name] ) ) {
- $t_filter[$t_field_name] = $t_filter_object->default;
- }
- }
- $t_custom_fields = custom_field_get_ids();
- # @@@ (thraxisp) This should really be the linked ids, but we don't know the project
- $f_custom_fields_data = array();
- if( is_array( $t_custom_fields ) && ( count( $t_custom_fields ) > 0 ) ) {
- foreach( $t_custom_fields as $t_cfid ) {
- $f_custom_fields_data[$t_cfid] = array( (string)META_FILTER_ANY );
- }
- }
- $t_filter['custom_fields'] = $f_custom_fields_data;
- $t_cache_default_array[$p_view_type] = $t_filter;
- return $t_filter;
- }
- /**
- * Returns the default view type for filters
- * @return string Default view type
- */
- function filter_get_default_view_type() {
- if( ADVANCED_DEFAULT == config_get( 'view_filters' ) ) {
- return FILTER_VIEW_TYPE_ADVANCED;
- } else {
- return FILTER_VIEW_TYPE_SIMPLE;
- }
- }
- /**
- * Returns the default value for a filter property.
- * Relies on filter_get_default_array() to get a defaulted filter.
- * @param string $p_filter_property The requested filter property name
- * @param string $p_view_type Optional, view type for the defaulted filter (simple/advanced)
- * @return mixed The property default value, or null if it doesn't exist
- */
- function filter_get_default_property( $p_filter_property, $p_view_type = null ) {
- $t_default_array = filter_get_default_array( $p_view_type );
- if( isset( $t_default_array[$p_filter_property] ) ) {
- return $t_default_array[$p_filter_property];
- } else {
- return null;
- }
- }
- /**
- * Get the standard filter that is to be used when no filter was previously saved.
- * When creating specific filters, this can be used as a basis for the filter, where
- * specific entries can be overridden.
- * @return mixed
- */
- function filter_get_default() {
- # Create empty array, validation will fill it with defaults
- $t_filter = array();
- return filter_ensure_valid_filter( $t_filter );
- }
- /**
- * Deserialize filter string
- * Expected strings have this format: "<version>#<json string>" where:
- * - <version> is the versio number of the filter structure used. See constant FILTER_VERSION
- * - # is a separator
- * - <json string> is the json encoded filter array.
- * @param string $p_serialized_filter Serialized filter string.
- * @return mixed $t_filter array
- * @see filter_ensure_valid_filter
- */
- function filter_deserialize( $p_serialized_filter ) {
- if( is_blank( $p_serialized_filter ) ) {
- return false;
- }
- #@TODO cproensa, we could accept a pure json array, without version prefix
- # in this case, the filter version field inside the array is to be used
- # and if not present, set the current filter version
- # check filter version mark
- $t_setting_arr = explode( '#', $p_serialized_filter, 2 );
- $t_version_string = $t_setting_arr[0];
- if( in_array( $t_version_string, array( 'v1', 'v2', 'v3', 'v4' ) ) ) {
- # these versions can't be salvaged, they are too old to update
- return false;
- } elseif( in_array( $t_version_string, array( 'v5', 'v6', 'v7', 'v8' ) ) ) {
- # filters from v5 onwards should cope with changing filter indices dynamically
- $t_filter_array = unserialize( $t_setting_arr[1] );
- } else {
- # filters from v9 onwards are stored as json
- $t_filter_array = json_decode( $t_setting_arr[1], /* assoc array */ true );
- }
- # If the unserialez data is not an array, the some error happened, eg, invalid format
- if( !is_array( $t_filter_array ) ) {
- return false;
- }
- # Set the filter version that was loaded in the array
- $t_filter_array['_version'] = $t_setting_arr[0];
- # If upgrade in filter content is needed, it will be done in filter_ensure_valid_filter()
- return filter_ensure_valid_filter( $t_filter_array );
- }
- /**
- * Creates a serialized filter with the correct format
- * @param array $p_filter_array Filter array to be serialized
- * @return string Serialized filter string
- */
- function filter_serialize( $p_filter_array ) {
- $t_cookie_version = FILTER_VERSION;
- $p_filter_array = filter_clean_runtime_properties( $p_filter_array );
- $t_settings_serialized = json_encode( $p_filter_array );
- $t_settings_string = $t_cookie_version . '#' . $t_settings_serialized;
- return $t_settings_string;
- }
- /**
- * Get the filter db row $p_filter_id
- * using the cached row if it's available
- * @global array $g_cache_filter_db_rows
- * @param integer $p_filter_id A filter identifier to look up in the database.
- * @return array|boolean The row of filter data as stored in db table, or false if does not exist
- */
- function filter_get_row( $p_filter_id ) {
- global $g_cache_filter_db_rows;
- if( !isset( $g_cache_filter_db_rows[$p_filter_id] ) ) {
- filter_cache_rows( array($p_filter_id) );
- }
- $t_row = $g_cache_filter_db_rows[$p_filter_id];
- return $t_row;
- }
- /**
- * Get the value of the filter field specified by filter id and field name
- * @param integer $p_filter_id A filter identifier to look up in the database.
- * @param string $p_field_name Name of the filter field to retrieve.
- * @return string
- */
- function filter_get_field( $p_filter_id, $p_field_name ) {
- $t_row = filter_get_row( $p_filter_id );
- if( isset( $t_row[$p_field_name] ) ) {
- return $t_row[$p_field_name];
- } else {
- error_parameters( $p_field_name );
- trigger_error( ERROR_DB_FIELD_NOT_FOUND, WARNING );
- return '';
- }
- }
- /**
- * 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 ) {
- # assigning to $p_* for this function writes the values back in case the caller wants to know
- if( $p_custom_filter === null ) {
- $t_filter = filter_get_bug_rows_filter( $p_project_id, $p_user_id );
- } else {
- $t_filter = filter_ensure_valid_filter( $p_custom_filter );
- }
- # build a filter query, here for counting results
- $t_filter_query = new BugFilterQuery(
- $t_filter,
- array(
- 'query_type' => BugFilterQuery::QUERY_TYPE_LIST,
- 'project_id' => $p_project_id,
- 'user_id' => $p_user_id,
- 'use_sticky' => $p_show_sticky
- )
- );
- $p_bug_count = $t_filter_query->get_bug_count();
- if( 0 == $p_bug_count ) {
- return array();
- }
- # Calculate pagination
- $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_filter_query->set_limit( $p_per_page );
- $t_filter_query->set_offset( $t_offset );
- # Execute query
- $t_rows = $t_filter_query->fetch_all();
- $t_bug_id_array = array_column( $t_rows, 'id' );
- # Return the processed rows: cache data, convert to bug objects
- return filter_cache_result( $t_rows, $t_bug_id_array );
- }
- /**
- * Get the filter defined by user and project.
- * @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.
- * @return array
- */
- function filter_get_bug_rows_filter( $p_project_id = null, $p_user_id = null ) {
- $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;
- }
- 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( $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 );
- }
- # if filter isn't return above, create a new filter from an empty array.
- if( false === $t_filter ) {
- $t_filter = array();
- }
- return $t_filter;
- }
- /**
- * Cache the filter results with bugnote stats for later use
- * @param array $p_rows Results of the filter query.
- * @param array $p_id_array_lastmod Array of bug ids.
- * @return array
- */
- function filter_cache_result( array $p_rows, array $p_id_array_lastmod ) {
- $t_stats = bug_get_bugnote_stats_array( $p_id_array_lastmod );
- $t_rows = array();
- foreach( $p_rows as $t_row ) {
- if( array_key_exists( $t_row['id'], $t_stats ) ) {
- $t_rows[] = bug_row_to_object( bug_cache_database_result( $t_row, $t_stats[$t_row['id']] ) );
- } else {
- $t_rows[] = bug_row_to_object( bug_cache_database_result( $t_row ) );
- }
- }
- return $t_rows;
- }
- /**
- * Prints the filter selection area for both the bug list view screen and
- * 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.
- * @return void
- */
- function filter_draw_selection_area() {
- $t_form_name_suffix = '_open';
- $t_filter = current_user_get_bug_filter();
- $t_filter = filter_ensure_valid_filter( $t_filter === false ? array() : $t_filter );
- $t_view_type = $t_filter['_view_type'];
- ?>
- <div class="col-md-12 col-xs-12">
- <div class="filter-box">
- <?php
- $t_stored_queries_arr = filter_db_get_available_queries();
- $t_is_temporary = filter_is_temporary( $t_filter );
- $t_tmp_filter_param = $t_is_temporary ? '&filter=' . filter_get_temporary_key( $t_filter ) : '';
- $t_can_persist = filter_user_can_use_persistent( auth_get_current_user_id() );
- $t_collapse_block = is_collapsed( 'filter' );
- $t_block_css = $t_collapse_block ? 'collapsed' : '';
- $t_block_icon = $t_collapse_block ? 'fa-chevron-down' : 'fa-chevron-up';
- # further use of this icon must be inlined to avoid spaces in rendered html
- $t_temporary_icon_html = ( $t_is_temporary && $t_can_persist ) ?
- '<i class="fa fa-clock-o fa-xs-top" title="' . lang_get( 'temporary_filter' ) . '"></i>'
- : '';
- $t_url_reset_filter = 'view_all_set.php?type=' . FILTER_ACTION_RESET;
- $t_url_persist_filter = 'view_all_set.php?temporary=n' . $t_tmp_filter_param . '&set_project_id=' . helper_get_current_project();
- ?>
- <div id="filter" class="widget-box widget-color-blue2 <?php echo $t_block_css ?>">
- <div class="widget-header widget-header-small">
- <h4 class="widget-title lighter">
- <i class="ace-icon fa fa-filter"><?php echo $t_temporary_icon_html ?>
- </i>
- <?php echo lang_get( 'filters' ) ?>
- </h4>
- <div class="widget-toolbar">
- <?php
- $t_view_filters = config_get('view_filters');
- if( ( ( SIMPLE_ONLY != $t_view_filters ) && ( ADVANCED_ONLY != $t_view_filters ) ) ||
- access_has_project_level( config_get( 'create_permalink_threshold' ) ) ||
- count( $t_stored_queries_arr ) > 0 ) { ?>
- <div class="widget-menu">
- <a href="#" data-action="settings" data-toggle="dropdown">
- <i class="ace-icon fa fa-bars bigger-125"></i>
- </a>
- <ul class="dropdown-menu dropdown-menu-right dropdown-yellow dropdown-caret dropdown-closer">
- <?php
- $t_url = config_get( 'use_dynamic_filters' )
- ? 'view_all_set.php?type=' . FILTER_ACTION_PARSE_ADD . $t_tmp_filter_param . '&view_type='
- : 'view_filters_page.php?view_type=';
- filter_print_view_type_toggle( $t_url, $t_filter['_view_type'] );
- if( access_has_project_level( config_get( 'create_permalink_threshold' ) ) ) {
- # Add CSRF protection, see #22702
- $t_permalink_url = urlencode( filter_get_url( $t_filter ) )
- . form_security_param( 'permalink' );
- echo '<li>';
- echo '<a href="permalink_page.php?url=' . $t_permalink_url . '">';
- echo '<i class="ace-icon fa fa-link"></i>  ' . lang_get( 'create_filter_link' );
- echo '</a>';
- echo '</li>';
- }
- if( count( $t_stored_queries_arr ) > 0 ) {
- echo '<li>';
- echo '<a href="manage_filter_page.php">';
- echo '<i class="ace-icon fa fa-wrench"></i>  ' . lang_get( 'open_queries' );
- echo '</a>';
- echo '</li>';
- }
- if( $t_is_tempo…
Large files files are truncated, but you can click here to view the full file