From aebd41f621b680e933a13fb6ccdf2eeaf9ab2952 Mon Sep 17 00:00:00 2001 From: Chris Beer Date: Tue, 27 Oct 2020 19:34:15 -0700 Subject: [PATCH] Introduce Hyrax::SearchService to mirror Blacklight::SearchService coming in Blacklight 7 --- .rubocop_fixme.yml | 4 + app/authorities/qa/authorities/collections.rb | 26 +++-- app/authorities/qa/authorities/find_works.rb | 25 +++- .../hyrax/collections_controller_behavior.rb | 21 +++- .../hyrax/dashboard/collections_controller.rb | 30 +++-- .../hyrax/dashboard/works_controller.rb | 7 +- app/controllers/hyrax/file_sets_controller.rb | 27 +++-- app/controllers/hyrax/homepage_controller.rb | 22 ++-- .../hyrax/my/collections_controller.rb | 7 +- .../hyrax/my/highlights_controller.rb | 5 +- app/controllers/hyrax/my/shares_controller.rb | 5 +- app/controllers/hyrax/my/works_controller.rb | 7 +- app/controllers/hyrax/my_controller.rb | 12 +- .../single_use_links_viewer_controller.rb | 16 ++- .../admin/repository_object_presenter.rb | 9 +- .../hyrax/collection_member_search_builder.rb | 24 +++- app/search_builders/hyrax/search_builder.rb | 5 +- .../collections/collection_member_service.rb | 93 ++++++--------- .../managed_collections_service.rb | 17 ++- app/services/hyrax/collections_service.rb | 24 ++-- app/services/hyrax/search_service.rb | 108 ++++++++++++++++++ .../hyrax/works/managed_works_service.rb | 16 ++- .../hyrax/homepage_controller_spec.rb | 6 +- .../hyrax/my/collections_controller_spec.rb | 2 +- .../hyrax/my/works_controller_spec.rb | 2 +- .../admin/repository_object_presenter_spec.rb | 3 +- .../hyrax/collections_service_spec.rb | 1 + .../hyrax/works/managed_works_service_spec.rb | 2 +- 28 files changed, 353 insertions(+), 173 deletions(-) create mode 100644 app/services/hyrax/search_service.rb diff --git a/.rubocop_fixme.yml b/.rubocop_fixme.yml index 1bea3fb219..cf7f0b930c 100644 --- a/.rubocop_fixme.yml +++ b/.rubocop_fixme.yml @@ -127,6 +127,10 @@ RSpec/AnyInstance: - 'spec/services/hyrax/workflow/sipity_actions_generator_spec.rb' - 'spec/services/hyrax/workflow/state_machine_generator_spec.rb' - 'spec/services/hyrax/workflow/workflow_permissions_generator_spec.rb' + - 'spec/controllers/hyrax/homepage_controller_spec.rb' + - 'spec/controllers/hyrax/my/collections_controller_spec.rb' + - 'spec/controllers/hyrax/my/works_controller_spec.rb' + - 'spec/presenters/hyrax/admin/repository_object_presenter_spec.rb' # Offense count: 51 RSpec/ExpectInHook: diff --git a/app/authorities/qa/authorities/collections.rb b/app/authorities/qa/authorities/collections.rb index 7cb5b7233d..885e3c1bf8 100644 --- a/app/authorities/qa/authorities/collections.rb +++ b/app/authorities/qa/authorities/collections.rb @@ -7,9 +7,7 @@ class Collections < Qa::Authorities::Base def search(_q, controller) # The Hyrax::CollectionSearchBuilder expects a current_user return [] unless controller.current_user - repo = CatalogController.new.repository - builder = search_builder(controller) - response = repo.search(builder) + response, _docs = search_response(controller) docs = response.documents docs.map do |doc| id = doc.id @@ -20,12 +18,24 @@ def search(_q, controller) private - def search_builder(controller) + def search_service(controller) + @search_service ||= Hyrax::SearchService.new( + config: controller.blacklight_config, + user_params: controller.params, + search_builder_class: search_builder_class, + scope: controller, + current_ability: controller.current_ability + ) + end + + def search_response(controller) access = controller.params[:access] || 'read' - search_builder_class.new(controller) - .where(controller.params[:q]) - .with_access(access) - .rows(100) + + search_service(controller).search_results do |builder| + builder.where(controller.params[:q]) + .with_access(access) + .rows(100) + end end end end diff --git a/app/authorities/qa/authorities/find_works.rb b/app/authorities/qa/authorities/find_works.rb index e2ee10fa1a..63dee48d5a 100644 --- a/app/authorities/qa/authorities/find_works.rb +++ b/app/authorities/qa/authorities/find_works.rb @@ -7,9 +7,8 @@ class FindWorks < Qa::Authorities::Base def search(_q, controller) # The My::FindWorksSearchBuilder expects a current_user return [] unless controller.current_user - repo = CatalogController.new.repository - builder = search_builder(controller) - response = repo.search(builder) + + response, _docs = search_response(controller) docs = response.documents docs.map do |doc| id = doc.id @@ -20,8 +19,24 @@ def search(_q, controller) private - def search_builder(controller) - search_builder_class.new(controller) + def search_service(controller) + @search_service ||= Hyrax::SearchService.new( + config: controller.blacklight_config, + user_params: controller.params, + search_builder_class: search_builder_class, + scope: controller, + current_ability: controller.current_ability + ) + end + + def search_response(controller) + access = controller.params[:access] || 'read' + + search_service(controller).search_results do |builder| + builder.where(controller.params[:q]) + .with_access(access) + .rows(100) + end end end end diff --git a/app/controllers/concerns/hyrax/collections_controller_behavior.rb b/app/controllers/concerns/hyrax/collections_controller_behavior.rb index 31072c64a9..e01b49622d 100644 --- a/app/controllers/concerns/hyrax/collections_controller_behavior.rb +++ b/app/controllers/concerns/hyrax/collections_controller_behavior.rb @@ -39,20 +39,29 @@ def collection def presenter @presenter ||= begin - # Query Solr for the collection. - # run the solr query to find the collection members - response = repository.search(single_item_search_builder.query) - curation_concern = response.documents.first - raise CanCan::AccessDenied unless curation_concern presenter_class.new(curation_concern, current_ability) end end + def curation_concern + # Query Solr for the collection. + # run the solr query to find the collection members + response, _docs = search_service.search_results + curation_concern = response.documents.first + raise CanCan::AccessDenied unless curation_concern + curation_concern + end + + def search_service + Hyrax::SearchService.new(config: blacklight_config, user_params: params.except(:q, :page), scope: self, search_builder_class: single_item_search_builder_class) + end + # Instantiates the search builder that builds a query for a single item # this is useful in the show view. def single_item_search_builder - single_item_search_builder_class.new(self).with(params.except(:q, :page)) + search_service.search_builder end + deprecation_deprecate :single_item_search_builder def collection_params form_class.model_attributes(params[:collection]) diff --git a/app/controllers/hyrax/dashboard/collections_controller.rb b/app/controllers/hyrax/dashboard/collections_controller.rb index 45beb18afb..e6921ea5f6 100644 --- a/app/controllers/hyrax/dashboard/collections_controller.rb +++ b/app/controllers/hyrax/dashboard/collections_controller.rb @@ -5,6 +5,11 @@ module Dashboard class CollectionsController < Hyrax::My::CollectionsController include Blacklight::AccessControls::Catalog include Blacklight::Base + + configure_blacklight do |config| + config.search_builder_class = Hyrax::Dashboard::CollectionsSearchBuilder + end + include BreadcrumbsForCollections with_themed_layout 'dashboard' @@ -192,10 +197,6 @@ def files render json: result end - def search_builder_class - Hyrax::Dashboard::CollectionsSearchBuilder - end - private def default_collection_type @@ -315,20 +316,29 @@ def remove_select_something_first_flash def presenter @presenter ||= begin - # Query Solr for the collection. - # run the solr query to find the collection members - response = repository.search(single_item_search_builder.query) - curation_concern = response.documents.first - raise CanCan::AccessDenied unless curation_concern presenter_class.new(curation_concern, current_ability) end end + def curation_concern + # Query Solr for the collection. + # run the solr query to find the collection members + response, _docs = single_item_search_service.search_results + curation_concern = response.documents.first + raise CanCan::AccessDenied unless curation_concern + curation_concern + end + + def single_item_search_service + Hyrax::SearchService.new(config: blacklight_config, user_params: params.except(:q, :page), scope: self, search_builder_class: single_item_search_builder_class) + end + # Instantiates the search builder that builds a query for a single item # this is useful in the show view. def single_item_search_builder - single_item_search_builder_class.new(self).with(params.except(:q, :page)) + search_service.search_builder end + deprecation_deprecate :single_item_search_builder def collection_params @participants = extract_old_style_permission_attributes(params[:collection]) diff --git a/app/controllers/hyrax/dashboard/works_controller.rb b/app/controllers/hyrax/dashboard/works_controller.rb index 0a29fe5a37..cdb8e8d63f 100644 --- a/app/controllers/hyrax/dashboard/works_controller.rb +++ b/app/controllers/hyrax/dashboard/works_controller.rb @@ -3,10 +3,9 @@ module Hyrax module Dashboard ## Shows a list of all works to the admins class WorksController < Hyrax::My::WorksController - # Search builder for a list of works - # Override of Blacklight::RequestBuilders - def search_builder_class - Hyrax::Dashboard::WorksSearchBuilder + # Define collection specific filter facets. + configure_blacklight do |config| + config.search_builder_class = Hyrax::Dashboard::WorksSearchBuilder end private diff --git a/app/controllers/hyrax/file_sets_controller.rb b/app/controllers/hyrax/file_sets_controller.rb index 5620d18312..2cc460d3bf 100644 --- a/app/controllers/hyrax/file_sets_controller.rb +++ b/app/controllers/hyrax/file_sets_controller.rb @@ -14,6 +14,10 @@ class FileSetsController < ApplicationController helper_method :curation_concern copy_blacklight_config_from(::CatalogController) + # Define collection specific filter facets. + configure_blacklight do |config| + config.search_builder_class = Hyrax::FileSetSearchBuilder + end class_attribute :show_presenter, :form_class self.show_presenter = Hyrax::FileSetPresenter @@ -140,11 +144,6 @@ def add_breadcrumb_for_action end end - # Override of Blacklight::RequestBuilders - def search_builder_class - Hyrax::FileSetSearchBuilder - end - def initialize_edit_form @parent = @file_set.in_objects.first original = @file_set.original_file @@ -162,13 +161,23 @@ def attributes def presenter @presenter ||= begin - _, document_list = search_results(params) - curation_concern = document_list.first - raise CanCan::AccessDenied unless curation_concern - show_presenter.new(curation_concern, current_ability, request) + show_presenter.new(curation_concern_document, current_ability, request) end end + def curation_concern_document + # Query Solr for the collection. + # run the solr query to find the collection members + response, _docs = single_item_search_service.search_results + curation_concern = response.documents.first + raise CanCan::AccessDenied unless curation_concern + curation_concern + end + + def single_item_search_service + Hyrax::SearchService.new(config: blacklight_config, user_params: params.except(:q, :page), scope: self, search_builder_class: search_builder_class) + end + def wants_to_revert? params.key?(:revision) && params[:revision] != curation_concern.latest_content_version.label end diff --git a/app/controllers/hyrax/homepage_controller.rb b/app/controllers/hyrax/homepage_controller.rb index 6915cb013c..70068b08aa 100644 --- a/app/controllers/hyrax/homepage_controller.rb +++ b/app/controllers/hyrax/homepage_controller.rb @@ -5,12 +5,6 @@ class Hyrax::HomepageController < ApplicationController include Blacklight::SearchHelper include Blacklight::AccessControls::Catalog - # The search builder for finding recent documents - # Override of Blacklight::RequestBuilders - def search_builder_class - Hyrax::HomepageSearchBuilder - end - class_attribute :presenter_class self.presenter_class = Hyrax::HomepagePresenter layout 'homepage' @@ -29,21 +23,27 @@ def index # Return 5 collections def collections(rows: 5) - builder = Hyrax::CollectionSearchBuilder.new(self) - .rows(rows) - response = repository.search(builder) - response.documents + Hyrax::CollectionsService.new(self).search_results do |builder| + builder.rows(rows) + end rescue Blacklight::Exceptions::ECONNREFUSED, Blacklight::Exceptions::InvalidRequest [] end def recent # grab any recent documents - (_, @recent_documents) = search_results(q: '', sort: sort_field, rows: 4) + (_, @recent_documents) = search_service.search_results do |builder| + builder.rows(4) + builder.merge(sort: sort_field) + end rescue Blacklight::Exceptions::ECONNREFUSED, Blacklight::Exceptions::InvalidRequest @recent_documents = [] end + def search_service + Hyrax::SearchService.new(config: blacklight_config, user_params: { q: '' }, scope: self, search_builder_class: Hyrax::HomepageSearchBuilder) + end + def sort_field "date_uploaded_dtsi desc" end diff --git a/app/controllers/hyrax/my/collections_controller.rb b/app/controllers/hyrax/my/collections_controller.rb index 993cfeab7d..7ec36ac5fe 100644 --- a/app/controllers/hyrax/my/collections_controller.rb +++ b/app/controllers/hyrax/my/collections_controller.rb @@ -2,6 +2,9 @@ module Hyrax module My class CollectionsController < MyController + configure_blacklight do |config| + config.search_builder_class = Hyrax::My::CollectionsSearchBuilder + end # Define collection specific filter facets. def self.configure_facets configure_blacklight do |config| @@ -18,10 +21,6 @@ def self.configure_facets end configure_facets - def search_builder_class - Hyrax::My::CollectionsSearchBuilder - end - def index add_breadcrumb t(:'hyrax.controls.home'), root_path add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path diff --git a/app/controllers/hyrax/my/highlights_controller.rb b/app/controllers/hyrax/my/highlights_controller.rb index 06153a3f36..6200014629 100644 --- a/app/controllers/hyrax/my/highlights_controller.rb +++ b/app/controllers/hyrax/my/highlights_controller.rb @@ -2,9 +2,8 @@ module Hyrax module My class HighlightsController < MyController - # Override of Blacklight::RequestBuilders - def search_builder_class - Hyrax::My::HighlightsSearchBuilder + configure_blacklight do |config| + config.search_builder_class = Hyrax::My::HighlightsSearchBuilder end def index diff --git a/app/controllers/hyrax/my/shares_controller.rb b/app/controllers/hyrax/my/shares_controller.rb index 35d8e3d3bc..def0f71544 100644 --- a/app/controllers/hyrax/my/shares_controller.rb +++ b/app/controllers/hyrax/my/shares_controller.rb @@ -2,9 +2,8 @@ module Hyrax module My class SharesController < MyController - # Override of Blacklight::RequestBuilders - def search_builder_class - Hyrax::My::SharesSearchBuilder + configure_blacklight do |config| + config.search_builder_class = Hyrax::My::SharesSearchBuilder end def index diff --git a/app/controllers/hyrax/my/works_controller.rb b/app/controllers/hyrax/my/works_controller.rb index 8e3137cdd6..f06c944270 100644 --- a/app/controllers/hyrax/my/works_controller.rb +++ b/app/controllers/hyrax/my/works_controller.rb @@ -5,6 +5,7 @@ class WorksController < MyController # Define collection specific filter facets. def self.configure_facets configure_blacklight do |config| + config.search_builder_class = Hyrax::My::WorksSearchBuilder config.add_facet_field "admin_set_sim", limit: 5 config.add_facet_field "member_of_collections_ssim", limit: 5 end @@ -14,12 +15,6 @@ def self.configure_facets class_attribute :create_work_presenter_class self.create_work_presenter_class = Hyrax::SelectTypeListPresenter - # Search builder for a list of works that belong to me - # Override of Blacklight::RequestBuilders - def search_builder_class - Hyrax::My::WorksSearchBuilder - end - def index # The user's collections for the "add to collection" form @user_collections = collections_service.search_results(:deposit) diff --git a/app/controllers/hyrax/my_controller.rb b/app/controllers/hyrax/my_controller.rb index 6ba385a09b..59f18f2792 100644 --- a/app/controllers/hyrax/my_controller.rb +++ b/app/controllers/hyrax/my_controller.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true module Hyrax class MyController < ApplicationController + extend Deprecation include Hydra::Catalog include Hyrax::Collections::AcceptsBatches @@ -35,7 +36,9 @@ def self.configure_facets def index @user = current_user - (@response, @document_list) = query_solr + Deprecation.silence(Hyrax::MyController) do + (@response, @document_list) = query_solr + end prepare_instance_variables_for_batch_control_display respond_to do |format| @@ -61,7 +64,12 @@ def prepare_instance_variables_for_batch_control_display end def query_solr - search_results(params) + search_service.search_results + end + deprecation_deprecate :query_solr + + def search_service + Hyrax::SearchService.new(config: blacklight_config, user_params: params, scope: self) end end end diff --git a/app/controllers/hyrax/single_use_links_viewer_controller.rb b/app/controllers/hyrax/single_use_links_viewer_controller.rb index 5ed1bc5774..e1a9d562e3 100644 --- a/app/controllers/hyrax/single_use_links_viewer_controller.rb +++ b/app/controllers/hyrax/single_use_links_viewer_controller.rb @@ -13,15 +13,16 @@ class SingleUseLinksViewerController < DownloadsController self.presenter_class = FileSetPresenter copy_blacklight_config_from(::CatalogController) + configure_blacklight do |config| + config.search_builder_class = SingleUseLinkSearchBuilder + end + def download raise not_found_exception unless single_use_link.path == hyrax.download_path(id: @asset) send_content end def show - _, document_list = search_results(id: single_use_link.item_id) - curation_concern = document_list.first - # Authorize using SingleUseLinksViewerController::Ability authorize! :read, curation_concern raise not_found_exception unless single_use_link.path == polymorphic_path([main_app, curation_concern]) @@ -36,8 +37,13 @@ def show private - def search_builder_class - SingleUseLinkSearchBuilder + def curation_concern + response, _document_list = search_service.search_results + response.documents.first + end + + def search_service + Hyrax::SearchService.new(config: blacklight_config, user_params: { id: single_use_link.item_id }, scope: self) end def content_options diff --git a/app/presenters/hyrax/admin/repository_object_presenter.rb b/app/presenters/hyrax/admin/repository_object_presenter.rb index 50316b2b62..71fdfb1c3a 100644 --- a/app/presenters/hyrax/admin/repository_object_presenter.rb +++ b/app/presenters/hyrax/admin/repository_object_presenter.rb @@ -22,8 +22,9 @@ def counts end def search_builder - Stats::WorkStatusSearchBuilder.new(self) + search_service.search_builder end + deprecation_deprecate :search_builder # results come from Solr in an array where the first item is the status and # the second item is the count @@ -31,9 +32,13 @@ def search_builder # [ "true", 55, "false", 205, nil, 11 ] # @return [#each] an enumerable object of tuples (status and count) def results - facet_results = repository.search(search_builder) + facet_results, _docs = search_service.search_results facet_results.facet_fields[IndexesWorkflow.suppressed_field].each_slice(2) end + + def search_service + Hyrax::SearchService.new(config: CatalogController.blacklight_config, user_params: {}, scope: self, search_builder_class: Stats::WorkStatusSearchBuilder) + end end end end diff --git a/app/search_builders/hyrax/collection_member_search_builder.rb b/app/search_builders/hyrax/collection_member_search_builder.rb index 836f8fbcc5..ef81b58b1e 100644 --- a/app/search_builders/hyrax/collection_member_search_builder.rb +++ b/app/search_builders/hyrax/collection_member_search_builder.rb @@ -3,7 +3,7 @@ module Hyrax # This search builder requires that a accessor named "collection" exists in the scope class CollectionMemberSearchBuilder < ::SearchBuilder include Hyrax::FilterByType - attr_reader :collection, :search_includes_models + attr_writer :collection, :search_includes_models class_attribute :collection_membership_field self.collection_membership_field = 'member_of_collection_ids_ssim' @@ -13,12 +13,26 @@ class CollectionMemberSearchBuilder < ::SearchBuilder # @param [scope] Typically the controller object # @param [Symbol] :works, :collections, (anything else retrieves both) - def initialize(scope:, - collection:, - search_includes_models: :works) + def initialize(*args, + scope: nil, + collection: nil, + search_includes_models: nil) @collection = collection @search_includes_models = search_includes_models - super(scope) + + if args.any? + super(*args) + else + super(scope) + end + end + + def collection + @collection || (scope.context[:collection] if scope&.respond_to?(:context)) + end + + def search_includes_models + @search_includes_models || :works end # include filters into the query to only include the collection memebers diff --git a/app/search_builders/hyrax/search_builder.rb b/app/search_builders/hyrax/search_builder.rb index 5cc23d877b..ddef717ee2 100644 --- a/app/search_builders/hyrax/search_builder.rb +++ b/app/search_builders/hyrax/search_builder.rb @@ -1,8 +1,5 @@ # frozen_string_literal: true module Hyrax - class SearchBuilder < Blacklight::SearchBuilder - include Blacklight::Solr::SearchBuilderBehavior - include Hydra::AccessControlsEnforcement - include Hyrax::SearchFilters + class SearchBuilder < ::SearchBuilder end end diff --git a/app/services/hyrax/collections/collection_member_service.rb b/app/services/hyrax/collections/collection_member_service.rb index daf6f256bc..3bcc402a7c 100644 --- a/app/services/hyrax/collections/collection_member_service.rb +++ b/app/services/hyrax/collections/collection_member_service.rb @@ -2,25 +2,36 @@ module Hyrax module Collections # Responsible for retrieving collection members - class CollectionMemberService - attr_reader :scope, :params, :collection - delegate :repository, to: :scope - + class CollectionMemberService < Hyrax::SearchService # @param scope [#repository] Typically a controller object which responds to :repository # @param [::Collection] # @param [ActionController::Parameters] query params - def initialize(scope:, collection:, params:) - @scope = scope - @collection = collection - @params = params - end + # rubocop:disable Metrics/ParameterLists + def initialize(scope:, collection:, params:, user_params: nil, current_ability: nil, search_builder_class: Hyrax::CollectionMemberSearchBuilder) + super( + config: scope.blacklight_config, + user_params: user_params || params, + collection: collection, + scope: scope, + current_ability: current_ability || scope.current_ability, + search_builder_class: search_builder_class + ) + end + # rubocop:enable Metrics/ParameterLists # @api public # # Collections which are members of the given collection # @return [Blacklight::Solr::Response] {up to 50 solr documents} def available_member_subcollections - query_solr(query_builder: subcollections_search_builder, query_params: params_for_subcollections) + response, _docs = search_results do |builder| + # To differentiate current page for works vs subcollections, we have to use a sub_collection_page + # param. Map this to the page param before querying for subcollections, if it's present + builder.page(user_params[:sub_collection_page]) + builder.search_includes_models = :collections + builder + end + response end # @api public @@ -28,7 +39,11 @@ def available_member_subcollections # Works which are members of the given collection # @return [Blacklight::Solr::Response] def available_member_works - query_solr(query_builder: works_search_builder, query_params: params) + response, _docs = search_results do |builder| + builder.search_includes_models = :works + builder + end + response end # @api public @@ -36,56 +51,12 @@ def available_member_works # Work ids of the works which are members of the given collection # @return [Blacklight::Solr::Response] def available_member_work_ids - query_solr_with_field_selection(query_builder: work_ids_search_builder, fl: 'id') - end - - private - - # @api private - # - # set up a member search builder for works only - # @return [CollectionMemberSearchBuilder] new or existing - def works_search_builder - @works_search_builder ||= Hyrax::CollectionMemberSearchBuilder.new(scope: scope, collection: collection, search_includes_models: :works) - end - - # @api private - # - # set up a member search builder for collections only - # @return [CollectionMemberSearchBuilder] new or existing - def subcollections_search_builder - @subcollections_search_builder ||= Hyrax::CollectionMemberSearchBuilder.new(scope: scope, collection: collection, search_includes_models: :collections) - end - - # @api private - # - # set up a member search builder for returning work ids only - # @return [CollectionMemberSearchBuilder] new or existing - def work_ids_search_builder - @work_ids_search_builder ||= Hyrax::CollectionMemberSearchBuilder.new(scope: scope, collection: collection, search_includes_models: :works) - end - - # @api private - # - def query_solr(query_builder:, query_params:) - repository.search(query_builder.with(query_params).query) - end - - # @api private - # - def query_solr_with_field_selection(query_builder:, fl:) - repository.search(query_builder.merge(fl: fl).query) - end - - # @api private - # - # Blacklight pagination still needs to be overridden and set up for the subcollections. - # @return the additional inputs required for the subcollection member search builder - def params_for_subcollections - # To differentiate current page for works vs subcollections, we have to use a sub_collection_page - # param. Map this to the page param before querying for subcollections, if it's present - params[:page] = params.delete(:sub_collection_page) - params + response, _docs = search_results do |builder| + builder.search_includes_models = :works + builder.merge(fl: 'id') + builder + end + response end end end diff --git a/app/services/hyrax/collections/managed_collections_service.rb b/app/services/hyrax/collections/managed_collections_service.rb index b12aff457d..ec0da581d8 100644 --- a/app/services/hyrax/collections/managed_collections_service.rb +++ b/app/services/hyrax/collections/managed_collections_service.rb @@ -9,8 +9,21 @@ module ManagedCollectionsService # @param scope [Object] Typically a controller object that responds to `repository`, `can?`, `blacklight_config`, `current_ability` # @return [Array] def self.managed_collections_count(scope:) - query_builder = Hyrax::Dashboard::CollectionsSearchBuilder.new(scope).rows(0) - scope.repository.search(query_builder.query).response["numFound"] + response, _docs = search_service(scope).search_results do |builder| + builder.rows(0) + end + + response.response['numFound'] + end + + def self.search_service(scope) + Hyrax::SearchService.new( + config: scope.blacklight_config, + user_params: {}, + current_ability: scope.current_ability, + scope: scope, + search_builder_class: Hyrax::Dashboard::CollectionsSearchBuilder + ) end end end diff --git a/app/services/hyrax/collections_service.rb b/app/services/hyrax/collections_service.rb index 8e22cea887..0a58664993 100644 --- a/app/services/hyrax/collections_service.rb +++ b/app/services/hyrax/collections_service.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true module Hyrax - class CollectionsService + class CollectionsService < Hyrax::SearchService attr_reader :context class_attribute :list_search_builder_class @@ -8,22 +8,22 @@ class CollectionsService # @param [#repository,#blacklight_config,#current_ability] context def initialize(context) - @context = context + super(config: context.blacklight_config, user_params: context.params, search_builder_class: self.class.list_search_builder_class, scope: context) + @current_ability = context.current_ability end # @param [Symbol] access :read or :edit - def search_results(access) - builder = list_search_builder(access) - response = context.repository.search(builder) - response.documents - end + def search_results(access = nil) + response, _docs = super() do |builder| + builder.with_access(access) if access + builder.rows(100) - private + yield builder if block_given? - def list_search_builder(access) - list_search_builder_class.new(context) - .rows(100) - .with_access(access) + builder + end + + response.documents end end end diff --git a/app/services/hyrax/search_service.rb b/app/services/hyrax/search_service.rb new file mode 100644 index 0000000000..ca808099f4 --- /dev/null +++ b/app/services/hyrax/search_service.rb @@ -0,0 +1,108 @@ +# frozen_string_literal: true + +# SearchService returns search results from the repository +module Hyrax + # Copied from Blacklight 7 + class SearchService + def initialize(config:, user_params: nil, search_builder_class: config.search_builder_class, **context) + @blacklight_config = config + @user_params = user_params || {} + @search_builder_class = search_builder_class + @context = context + end + + # The blacklight_config + controller are accessed by the search_builder + attr_reader :blacklight_config, :context + + def search_builder + search_builder_class.new(self) + end + + # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + # a solr query method + # @yield [search_builder] optional block yields configured SearchBuilder, caller can modify or create new SearchBuilder to be used. Block should return SearchBuilder to be used. + # @return [Blacklight::Solr::Response] the solr response object + def search_results + builder = search_builder.with(user_params) + builder.page = user_params[:page] if user_params[:page] + builder.rows = (user_params[:per_page] || user_params[:rows]) if user_params[:per_page] || user_params[:rows] + + builder = yield(builder) if block_given? + response = repository.search(builder) + + if response.grouped? && grouped_key_for_results + [response.group(grouped_key_for_results), []] + elsif response.grouped? && response.grouped.length == 1 + [response.grouped.first, []] + else + [response, response.documents] + end + end + # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + + # retrieve a document, given the doc id + # @param [Array{#to_s},#to_s] id + # @return [Blacklight::Solr::Response, Blacklight::SolrDocument] the solr response object and the first document + def fetch(id = nil, extra_controller_params = {}) + if id.is_a? Array + fetch_many(id, extra_controller_params) + else + fetch_one(id, extra_controller_params) + end + end + + private + + attr_reader :search_builder_class, :user_params, :search_state + + def repository + blacklight_config.repository || blacklight_config.repository_class.new(blacklight_config) + end + + def scope + @context[:scope] + end + + def method_missing(method_name, *arguments, &block) + if scope&.respond_to?(method_name) + Deprecation.warn(self.class, "Calling `#{method_name}` on scope " \ + 'is deprecated and will be removed in Blacklight 8. Call #to_h first if you ' \ + ' need to use hash methods (or, preferably, use your own SearchState implementation)') + scope&.public_send(method_name, *arguments, &block) + else + super + end + end + + def respond_to_missing?(method_name, include_private = false) + scope&.respond_to?(method_name, include_private) || super + end + + def current_ability + @current_ability || @context[:current_ability] + end + + ## + # Retrieve a set of documents by id + # @param [Array] ids + # @param [HashWithIndifferentAccess] extra_controller_params + def fetch_many(ids, extra_controller_params) + extra_controller_params ||= {} + + query = search_builder + .with(user_params) + .where(blacklight_config.document_model.unique_key => ids) + .merge(blacklight_config.fetch_many_document_params) + .merge(extra_controller_params) + + solr_response = repository.search(query) + + [solr_response, solr_response.documents] + end + + def fetch_one(id, extra_controller_params) + solr_response = repository.find id, extra_controller_params + [solr_response, solr_response.documents.first] + end + end +end diff --git a/app/services/hyrax/works/managed_works_service.rb b/app/services/hyrax/works/managed_works_service.rb index 637bbce2de..2c15cd14f0 100644 --- a/app/services/hyrax/works/managed_works_service.rb +++ b/app/services/hyrax/works/managed_works_service.rb @@ -9,8 +9,20 @@ module ManagedWorksService # @param scope [Object] Typically a controller object that responds to `repository`, `can?`, `blacklight_config`, `current_ability` # @return [Array] def self.managed_works_count(scope:) - query_builder = Hyrax::Dashboard::WorksSearchBuilder.new(scope).rows(0) - scope.repository.search(query_builder.query).response["numFound"] + response, _docs = search_service(scope).search_results do |builder| + builder.rows(0) + end + response.response["numFound"] + end + + def self.search_service(scope) + Hyrax::SearchService.new( + config: scope.blacklight_config, + user_params: scope.params, + scope: scope, + current_ability: scope.current_ability, + search_builder_class: Hyrax::Dashboard::WorksSearchBuilder + ) end end end diff --git a/spec/controllers/hyrax/homepage_controller_spec.rb b/spec/controllers/hyrax/homepage_controller_spec.rb index 98fa3e861d..1acac25d17 100644 --- a/spec/controllers/hyrax/homepage_controller_spec.rb +++ b/spec/controllers/hyrax/homepage_controller_spec.rb @@ -85,8 +85,7 @@ before do allow(controller).to receive(:repository).and_return(repository) allow(controller).to receive(:search_results).and_return([nil, ['recent document']]) - allow(controller.repository).to receive(:search).with(an_instance_of(Hyrax::CollectionSearchBuilder)) - .and_return(collection_results) + allow_any_instance_of(Hyrax::CollectionsService).to receive(:search_results).and_return(collection_results.documents) end it "initializes the presenter with ability and a list of collections" do @@ -124,8 +123,7 @@ context "without solr" do before do - allow(controller).to receive(:repository).and_return(instance_double(Blacklight::Solr::Repository)) - allow(controller.repository).to receive(:search).and_raise Blacklight::Exceptions::InvalidRequest + allow_any_instance_of(Hyrax::SearchService).to receive(:search_results).and_raise Blacklight::Exceptions::InvalidRequest end it "errors gracefully" do diff --git a/spec/controllers/hyrax/my/collections_controller_spec.rb b/spec/controllers/hyrax/my/collections_controller_spec.rb index 470d09205e..b8d1f2e110 100644 --- a/spec/controllers/hyrax/my/collections_controller_spec.rb +++ b/spec/controllers/hyrax/my/collections_controller_spec.rb @@ -11,7 +11,7 @@ end it "shows the search results and sets breadcrumbs" do - expect(controller).to receive(:search_results).with(ActionController::Parameters).and_return([response, doc_list]) + allow_any_instance_of(Hyrax::SearchService).to receive(:search_results).and_return([response, doc_list]) expect(controller).to receive(:add_breadcrumb).with('Home', root_path(locale: 'en')) expect(controller).to receive(:add_breadcrumb).with('Dashboard', dashboard_path(locale: 'en')) diff --git a/spec/controllers/hyrax/my/works_controller_spec.rb b/spec/controllers/hyrax/my/works_controller_spec.rb index 1d6653bbe8..60933c556c 100644 --- a/spec/controllers/hyrax/my/works_controller_spec.rb +++ b/spec/controllers/hyrax/my/works_controller_spec.rb @@ -16,7 +16,7 @@ end it "shows search results and breadcrumbs" do - expect(controller).to receive(:search_results).with(ActionController::Parameters).and_return([response, doc_list]) + expect_any_instance_of(Hyrax::SearchService).to receive(:search_results).and_return([response, doc_list]) expect(controller).to receive(:add_breadcrumb).with('Home', root_path(locale: 'en')) expect(controller).to receive(:add_breadcrumb).with('Dashboard', dashboard_path(locale: 'en')) expect(controller).to receive(:add_breadcrumb).with('Works', my_works_path(locale: 'en')) diff --git a/spec/presenters/hyrax/admin/repository_object_presenter_spec.rb b/spec/presenters/hyrax/admin/repository_object_presenter_spec.rb index ac897f0b93..13d944d434 100644 --- a/spec/presenters/hyrax/admin/repository_object_presenter_spec.rb +++ b/spec/presenters/hyrax/admin/repository_object_presenter_spec.rb @@ -5,7 +5,6 @@ describe "#as_json" do subject { instance.as_json } - let(:stub_repo) { double(search: response) } let(:response) { Blacklight::Solr::Response.new(solr_data, {}) } let(:solr_data) do { "facet_counts" => { @@ -14,7 +13,7 @@ end before do - allow(instance).to receive(:repository).and_return(stub_repo) + allow_any_instance_of(Hyrax::SearchService).to receive(:search_results).and_return([response, nil]) end it do is_expected.to eq [{ label: "Published", value: 1 }, diff --git a/spec/services/hyrax/collections_service_spec.rb b/spec/services/hyrax/collections_service_spec.rb index ac11554e5e..97f7e5d186 100644 --- a/spec/services/hyrax/collections_service_spec.rb +++ b/spec/services/hyrax/collections_service_spec.rb @@ -5,6 +5,7 @@ let(:context) do double(current_ability: Ability.new(user1), repository: controller.repository, + params: {}, blacklight_config: controller.blacklight_config) end diff --git a/spec/services/hyrax/works/managed_works_service_spec.rb b/spec/services/hyrax/works/managed_works_service_spec.rb index 7894735432..fed2efc5c8 100644 --- a/spec/services/hyrax/works/managed_works_service_spec.rb +++ b/spec/services/hyrax/works/managed_works_service_spec.rb @@ -4,7 +4,7 @@ let(:repository) { Blacklight::Solr::Repository.new(blacklight_config) } let(:current_ability) { instance_double(Ability, admin?: true) } - let(:scope) { double('Scope', can?: true, current_ability: current_ability, repository: repository, blacklight_config: blacklight_config) } + let(:scope) { double('Scope', params: {}, can?: true, current_ability: current_ability, repository: repository, blacklight_config: blacklight_config) } describe '.managed_works_count' do subject { described_class.managed_works_count(scope: scope) }