diff --git a/app/models/principal.rb b/app/models/principal.rb index d7814f595..77fe19fe0 100644 --- a/app/models/principal.rb +++ b/app/models/principal.rb @@ -33,6 +33,16 @@ class Principal < ActiveRecord::Base } } + # Principals that are members of a collection of projects + named_scope :member_of, lambda {|projects| + if projects.empty? + {:conditions => "1=0"} + else + ids = projects.map(&:id) + {:conditions => ["#{Principal.table_name}.status = 1 AND #{Principal.table_name}.id IN (SELECT DISTINCT user_id FROM #{Member.table_name} WHERE project_id IN (?))", ids]} + end + } + before_create :set_default_empty_values def name(formatter = nil) diff --git a/app/models/query.rb b/app/models/query.rb index 1cfa952ff..84ab868ff 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -232,11 +232,18 @@ class Query < ActiveRecord::Base principals = [] if project principals += project.principals.sort + unless project.leaf? + subprojects = project.descendants.visible.all + if subprojects.any? + @available_filters["subproject_id"] = { :type => :list_subprojects, :order => 13, :values => subprojects.collect{|s| [s.name, s.id.to_s] } } + principals += Principal.member_of(subprojects) + end + end else all_projects = Project.visible.all if all_projects.any? # members of visible projects - principals += Principal.active.find(:all, :conditions => ["#{User.table_name}.id IN (SELECT DISTINCT user_id FROM members WHERE project_id IN (?))", all_projects.collect(&:id)]).sort + principals += Principal.member_of(all_projects) # project filter project_values = [] @@ -250,6 +257,8 @@ class Query < ActiveRecord::Base @available_filters["project_id"] = { :type => :list, :order => 1, :values => project_values} unless project_values.empty? end end + principals.uniq! + principals.sort! users = principals.select {|p| p.is_a?(User)} assigned_to_values = [] @@ -282,12 +291,6 @@ class Query < ActiveRecord::Base unless versions.empty? @available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => versions.sort.collect{|s| ["#{s.project.name} - #{s.name}", s.id.to_s] } } end - unless project.leaf? - subprojects = project.descendants.visible.all - unless subprojects.empty? - @available_filters["subproject_id"] = { :type => :list_subprojects, :order => 13, :values => subprojects.collect{|s| [s.name, s.id.to_s] } } - end - end add_custom_fields_filters(project.all_issue_custom_fields) else # global filters for cross project issue list diff --git a/test/unit/principal_test.rb b/test/unit/principal_test.rb index a3230f1c6..694f7e027 100644 --- a/test/unit/principal_test.rb +++ b/test/unit/principal_test.rb @@ -27,6 +27,11 @@ class PrincipalTest < ActiveSupport::TestCase assert_nil result.detect {|p| p.is_a?(AnonymousUser)} end + def test_member_of_scope_should_return_the_union_of_all_members + projects = Project.find_all_by_id(1, 2) + assert_equal projects.map(&:principals).flatten.sort, Principal.member_of(projects).sort + end + context "#like" do setup do Principal.generate!(:login => 'login') diff --git a/test/unit/query_test.rb b/test/unit/query_test.rb index ca5bf9175..52e29de7e 100644 --- a/test/unit/query_test.rb +++ b/test/unit/query_test.rb @@ -766,6 +766,19 @@ class QueryTest < ActiveSupport::TestCase assert users[:values].map{|u|u[1]}.include?("3") end + should "include users of subprojects" do + user1 = User.generate_with_protected! + user2 = User.generate_with_protected! + project = Project.find(1) + Member.create!(:principal => user1, :project => project.children.visible.first, :role_ids => [1]) + @query.project = project + + users = @query.available_filters["assigned_to_id"] + assert_not_nil users + assert users[:values].map{|u|u[1]}.include?(user1.id.to_s) + assert !users[:values].map{|u|u[1]}.include?(user2.id.to_s) + end + should "include visible projects in cross-project view" do projects = @query.available_filters["project_id"] assert_not_nil projects