end
@available_filters["assigned_to_id"] = { :type => :list_optional, :order => 4, :values => user_values } unless user_values.empty?
@available_filters["author_id"] = { :type => :list, :order => 5, :values => user_values } unless user_values.empty?
+
+ if User.current.logged?
+ @available_filters["watcher_id"] = { :type => :list, :order => 15, :values => [["<< #{l(:label_me)} >>", "me"]] }
+ end
if project
# project specific filters
next if field == "subproject_id"
v = values_for(field).clone
next unless v and !v.empty?
-
+ operator = operator_for(field)
+
+ # "me" value subsitution
+ if %w(assigned_to_id author_id watcher_id).include?(field)
+ v.push(User.current.logged? ? User.current.id.to_s : "0") if v.delete("me")
+ end
+
sql = ''
- is_custom_filter = false
if field =~ /^cf_(\d+)$/
# custom field
db_table = CustomValue.table_name
db_field = 'value'
is_custom_filter = true
sql << "#{Issue.table_name}.id IN (SELECT #{Issue.table_name}.id FROM #{Issue.table_name} LEFT OUTER JOIN #{db_table} ON #{db_table}.customized_type='Issue' AND #{db_table}.customized_id=#{Issue.table_name}.id AND #{db_table}.custom_field_id=#{$1} WHERE "
+ sql << sql_for_field(field, operator, v, db_table, db_field, true) + ')'
+ elsif field == 'watcher_id'
+ db_table = Watcher.table_name
+ db_field = 'user_id'
+ sql << "#{Issue.table_name}.id #{ operator == '=' ? 'IN' : 'NOT IN' } (SELECT #{db_table}.watchable_id FROM #{db_table} WHERE #{db_table}.watchable_type='Issue' AND "
+ sql << sql_for_field(field, '=', v, db_table, db_field) + ')'
else
# regular field
db_table = Issue.table_name
db_field = field
- sql << '('
+ sql << '(' + sql_for_field(field, operator, v, db_table, db_field) + ')'
end
-
- # "me" value subsitution
- if %w(assigned_to_id author_id).include?(field)
- v.push(User.current.logged? ? User.current.id.to_s : "0") if v.delete("me")
- end
-
- sql = sql + sql_for_field(field, v, db_table, db_field, is_custom_filter)
-
- sql << ')'
filters_clauses << sql
+
end if filters and valid?
(filters_clauses << project_statement).join(' AND ')
private
- # Helper method to generate the WHERE sql for a +field+ with a +value+
- def sql_for_field(field, value, db_table, db_field, is_custom_filter)
+ # Helper method to generate the WHERE sql for a +field+, +operator+ and a +value+
+ def sql_for_field(field, operator, value, db_table, db_field, is_custom_filter=false)
sql = ''
- case operator_for field
+ case operator
when "="
sql = "#{db_table}.#{db_field} IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")"
when "!"
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL\r
setting_openid: Allow OpenID login and registration\r
label_login_with_open_id_option: or login with OpenID\r
+field_watcher: Watcher\r
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_comments_sorting: Display comments
field_parent_title: Parent page
field_editable: Editable
+field_watcher: Watcher
setting_app_title: Application title
setting_app_subtitle: Application subtitle
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_parent_title: Page parent
field_editable: Modifiable
field_identity_url: URL OpenID
+field_watcher: Observateur
setting_app_title: Titre de l'application
setting_app_subtitle: Sous-titre de l'application
field_identity_url: OpenID URL\r
setting_openid: Allow OpenID login and registration\r
label_login_with_open_id_option: or login with OpenID\r
+field_watcher: Watcher\r
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL\r
setting_openid: Allow OpenID login and registration\r
label_login_with_open_id_option: or login with OpenID\r
+field_watcher: Watcher\r
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL\r
setting_openid: Allow OpenID login and registration\r
label_login_with_open_id_option: or login with OpenID\r
+field_watcher: Watcher\r
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL\r
setting_openid: Allow OpenID login and registration\r
label_login_with_open_id_option: or login with OpenID\r
+field_watcher: Watcher\r
field_identity_url: OpenID URL\r
setting_openid: Allow OpenID login and registration\r
label_login_with_open_id_option: or login with OpenID\r
+field_watcher: Watcher\r
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL\r
setting_openid: Allow OpenID login and registration\r
label_login_with_open_id_option: or login with OpenID\r
+field_watcher: Watcher\r
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
field_identity_url: OpenID URL
setting_openid: Allow OpenID login and registration
label_login_with_open_id_option: or login with OpenID
+field_watcher: Watcher
watchable_type: Message
watchable_id: 1
user_id: 1
+watchers_003:
+ watchable_type: Issue
+ watchable_id: 2
+ user_id: 1
\ No newline at end of file
require File.dirname(__FILE__) + '/../test_helper'
class QueryTest < Test::Unit::TestCase
- fixtures :projects, :enabled_modules, :users, :members, :roles, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :custom_fields, :custom_values, :versions, :queries
+ fixtures :projects, :enabled_modules, :users, :members, :roles, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :watchers, :custom_fields, :custom_values, :versions, :queries
def test_custom_fields_for_all_projects_should_be_available_in_global_queries
query = Query.new(:project => nil, :name => '_')
find_issues_with_query(query)
end
+ def test_filter_watched_issues
+ User.current = User.find(1)
+ query = Query.new(:name => '_', :filters => { 'watcher_id' => {:operator => '=', :values => ['me']}})
+ result = find_issues_with_query(query)
+ assert_not_nil result
+ assert !result.empty?
+ assert_equal Issue.visible.watched_by(User.current).sort_by(&:id), result.sort_by(&:id)
+ User.current = nil
+ end
+
+ def test_filter_unwatched_issues
+ User.current = User.find(1)
+ query = Query.new(:name => '_', :filters => { 'watcher_id' => {:operator => '!', :values => ['me']}})
+ result = find_issues_with_query(query)
+ assert_not_nil result
+ assert !result.empty?
+ assert_equal((Issue.visible - Issue.watched_by(User.current)).sort_by(&:id).size, result.sort_by(&:id).size)
+ User.current = nil
+ end
+
def test_default_columns
q = Query.new
assert !q.columns.empty?