diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a72504f..d3e6169 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -174,8 +174,6 @@ class ApplicationController < ActionController::Base end def find_by_contents(asset, scope, query, paginate_options={:page => 1}, options={}) - scope = scope.send(options[:filter]) if options[:filter] - @plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options) || fallback_find_by_contents(asset, scope, query, paginate_options, options) end diff --git a/app/controllers/public/search_controller.rb b/app/controllers/public/search_controller.rb index 8ce8bd7..4277415 100644 --- a/app/controllers/public/search_controller.rb +++ b/app/controllers/public/search_controller.rb @@ -214,6 +214,13 @@ class SearchController < PublicController @searches[@asset] = find_by_contents(@asset, @scope, @query, paginate_options, {:category => @category, :filter => @filter}) end + def find_by_contents asset, scope, query, paginate_options={:page => 1}, options={} + # only apply fitlers to empty query, sorting is engine specific + scope = scope.send(options[:filter]) if options[:filter] and @empty_query + + super asset, scope, query, paginate_options, options + end + private def visible_profiles(klass, *extra_relations) diff --git a/plugins/solr/lib/ext/article.rb b/plugins/solr/lib/ext/article.rb index 53d23d2..8ffeeab 100644 --- a/plugins/solr/lib/ext/article.rb +++ b/plugins/solr/lib/ext/article.rb @@ -24,7 +24,8 @@ class Article {:slug => :text}, {:body => :text}, {:abstract => :text}, {:filename => :text}, # filtered fields - {:solr_plugin_public => :boolean}, {:environment_id => :integer}, + {:solr_plugin_public => :boolean}, {:published => :boolean}, + {:environment_id => :integer}, {:profile_id => :integer}, :language, {:solr_plugin_category_filter => :integer}, # ordered/query-boosted fields diff --git a/plugins/solr/lib/ext/profile.rb b/plugins/solr/lib/ext/profile.rb index 20eba29..2e0fb84 100644 --- a/plugins/solr/lib/ext/profile.rb +++ b/plugins/solr/lib/ext/profile.rb @@ -28,7 +28,7 @@ class Profile {:solr_plugin_category_filter => :integer}, # ordered/query-boosted fields {:solr_plugin_name_sortable => :string}, {:user_id => :integer}, - :enabled, :active, :validated, :public_profile, + :enabled, :active, :validated, :public_profile, :visible, {:lat => :float}, {:lng => :float}, :updated_at, :created_at, ], diff --git a/plugins/solr/lib/solr_plugin.rb b/plugins/solr/lib/solr_plugin.rb index a2bf16c..c3eb510 100644 --- a/plugins/solr/lib/solr_plugin.rb +++ b/plugins/solr/lib/solr_plugin.rb @@ -18,16 +18,69 @@ class SolrPlugin < Noosfero::Plugin true end + def solr_search? empty_query, klass + not empty_query or klass == Product + end + def find_by_contents(asset, scope, query, paginate_options={}, options={}) klass = asset_class(asset) - category = options.delete(:category) - filter = options.delete(:filter) + category = options[:category] + empty_query = empty_query? query, category - return if empty_query?(query, category) && klass != Product + return unless solr_search? empty_query, klass solr_options = solr_options(class_asset(klass), category) - solr_options.merge!(products_options(user)) if klass == Product && empty_query?(query, category) - klass.find_by_contents(query, paginate_options, solr_options.merge(options)) + solr_options[:filter_queries] ||= [] + solr_options[:filter_queries] += scopes_to_solr_filters scope, klass, options + solr_options.merge! products_options(user) if klass == Product and empty_query + solr_options.merge! options.except(:category, :filter) + + scope.find_by_contents query, paginate_options, solr_options + end + + protected + + def scopes_to_solr_filters scope, klass = nil, options = {} + filter_queries = [] + klass ||= scope.base_class + solr_fields = klass.configuration[:solr_fields].keys + scopes_applied = scope.scopes_applied.dup rescue [] #rescue association and class direct filtering + + scope.current_scoped_methods[:create].each do |attr, value| + next unless solr_fields.include? attr.to_sym + + # if the filter is present here, then prefer it + scopes_applied.reject!{ |name| name == attr.to_sym } + + filter_queries << "#{attr}:#{value}" + end + + scopes_applied.each do |name| + next if name.to_s == options[:filter].to_s + + has_value = name === Hash + if has_value + name, args = name.keys.first, name.values.first + value = args.first + end + + related_field = nil + related_field = name if solr_fields.include? name + related_field = "solr_plugin_#{name}" if solr_fields.include? :"solr_plugin_#{name}" + + if has_value + if related_field + filter_queries << "#{related_field}:#{value}" + else + filter_queries << klass.send("solr_filter_#{name}", *args) + end + else + raise "Undeclared solr field for scope #{name}" if related_field.nil? + filter_queries << "#{related_field}:true" + end + end + + filter_queries end def method_missing method, *args, &block diff --git a/plugins/solr/test/unit/solr_plugin/plugin_test.rb b/plugins/solr/test/unit/solr_plugin/plugin_test.rb new file mode 100644 index 0000000..5454c50 --- /dev/null +++ b/plugins/solr/test/unit/solr_plugin/plugin_test.rb @@ -0,0 +1,16 @@ +require "#{File.dirname(__FILE__)}/../../test_helper" + +class SolrPlugin::PluginTest < ActiveSupport::TestCase + + def setup + @plugin = SolrPlugin.new + end + attr_reader :plugin + + should 'convert scopes to solr filters' do + person = create_user('test').person + result = plugin.send :scopes_to_solr_filters, person.files.public.published + assert_equal result, ["profile_id:#{person.id}", "published:'true'", "solr_plugin_public:true"] + end + +end diff --git a/vendor/plugins/monkey_patches/named_scope_with_applied_names/init.rb b/vendor/plugins/monkey_patches/named_scope_with_applied_names/init.rb new file mode 100644 index 0000000..7dac14a --- /dev/null +++ b/vendor/plugins/monkey_patches/named_scope_with_applied_names/init.rb @@ -0,0 +1,57 @@ +require_dependency 'active_record/named_scope' + +if Rails::VERSION::STRING < "2.3.99" + + module ::ActiveRecord + + module NamedScope + + module ClassMethods + + def named_scope_with_applied_names name, options = {}, &block + named_scope_without_applied_names name, options, &block + + name = name.to_sym + scopes[name] = lambda do |parent_scope, *args| + scope = Scope.new(parent_scope, case options + when Hash + options + when Proc + if self.model_name != parent_scope.model_name + options.bind(parent_scope).call(*args) + else + options.call(*args) + end + end, &block) + scope.scope_name = name + scope + end + end + alias_method_chain :named_scope, :applied_names + end + + class Scope + attr_accessor :scope_name, :scopes_applied + + def initialize_with_applied_names proxy_scope, options, &block + initialize_without_applied_names proxy_scope, options, &block + self.scopes_applied ||= [] + self.scopes_applied += proxy_scope.send :scopes_applied if Scope === proxy_scope + + # unrelated bugfix: use if instead of unless + if (Scope === proxy_scope || ActiveRecord::Associations::AssociationCollection === proxy_scope) + @current_scoped_methods_when_defined = proxy_scope.send(:current_scoped_methods) + end + end + alias_method_chain :initialize, :applied_names + + def scope_name= name + @scope_name = name + self.scopes_applied << @scope_name + end + + end + + end + end +end -- libgit2 0.21.2