blacklight 9.0.0.beta7 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.docker/app/Dockerfile +2 -1
  3. data/.github/matrix.json +21 -20
  4. data/README.md +2 -2
  5. data/VERSION +1 -1
  6. data/app/assets/javascripts/blacklight/blacklight.esm.js +13 -7
  7. data/app/assets/javascripts/blacklight/blacklight.esm.js.map +1 -1
  8. data/app/assets/javascripts/blacklight/blacklight.js +13 -7
  9. data/app/assets/javascripts/blacklight/blacklight.js.map +1 -1
  10. data/app/components/blacklight/advanced_search_form_component.rb +2 -1
  11. data/app/components/blacklight/document_component.rb +10 -13
  12. data/app/components/blacklight/facets/filters_component.rb +2 -2
  13. data/app/components/blacklight/facets/suggest_component.html.erb +17 -12
  14. data/app/components/blacklight/facets/suggest_component.rb +2 -3
  15. data/app/components/blacklight/metadata_field_component.html.erb +2 -2
  16. data/app/components/blacklight/metadata_field_component.rb +2 -1
  17. data/app/components/blacklight/metadata_field_layout_component.rb +9 -4
  18. data/app/components/blacklight/search_bar_component.html.erb +1 -1
  19. data/app/controllers/concerns/blacklight/catalog.rb +3 -4
  20. data/app/javascript/blacklight-frontend/checkbox_submit.js +2 -2
  21. data/app/javascript/blacklight-frontend/facet_suggest.js +4 -1
  22. data/app/javascript/blacklight-frontend/modal.js +7 -4
  23. data/app/presenters/blacklight/document_presenter.rb +6 -5
  24. data/app/presenters/blacklight/facet_field_presenter.rb +10 -3
  25. data/app/presenters/blacklight/field_presenter.rb +4 -2
  26. data/app/presenters/blacklight/rendering/abstract_step.rb +7 -1
  27. data/app/presenters/blacklight/rendering/join.rb +9 -5
  28. data/app/presenters/blacklight/rendering/terminator.rb +1 -1
  29. data/app/services/blacklight/search_service.rb +4 -2
  30. data/app/views/catalog/_show_main_content.html.erb +9 -5
  31. data/app/views/catalog/index.html.erb +0 -1
  32. data/app/views/catalog/show.html.erb +2 -2
  33. data/config/locales/blacklight.en.yml +1 -1
  34. data/lib/blacklight/component.rb +2 -0
  35. data/lib/blacklight/configuration/facet_field.rb +2 -0
  36. data/lib/blacklight/configuration/view_config.rb +30 -16
  37. data/lib/blacklight/configuration.rb +56 -9
  38. data/lib/blacklight/routes/searchable.rb +1 -1
  39. data/lib/blacklight/search_builder.rb +160 -1
  40. data/lib/blacklight/search_state/pivot_filter_field.rb +1 -1
  41. data/lib/blacklight/solr/field_reflection_search_builder.rb +11 -0
  42. data/lib/blacklight/solr/repository.rb +5 -5
  43. data/lib/blacklight/solr/search_builder_behavior.rb +73 -7
  44. data/lib/blacklight/solr/single_doc_search_builder.rb +25 -0
  45. data/lib/generators/blacklight/templates/catalog_controller.rb +27 -5
  46. data/lib/generators/blacklight/templates/solr/conf/solrconfig.xml +0 -67
  47. data/package.json +1 -1
  48. data/spec/components/blacklight/document_component_spec.rb +0 -7
  49. data/spec/components/blacklight/facets/filters_component_spec.rb +3 -3
  50. data/spec/components/blacklight/facets/suggest_component_spec.rb +14 -1
  51. data/spec/components/blacklight/search_bar_component_spec.rb +24 -1
  52. data/spec/controllers/blacklight/catalog_spec.rb +1 -1
  53. data/spec/features/advanced_search_spec.rb +39 -20
  54. data/spec/features/facets_spec.rb +9 -0
  55. data/spec/models/blacklight/configuration_spec.rb +126 -0
  56. data/spec/models/blacklight/search_builder_spec.rb +11 -1
  57. data/spec/models/blacklight/solr/repository_spec.rb +6 -0
  58. data/spec/models/blacklight/solr/search_builder_behavior_spec.rb +214 -8
  59. data/spec/presenters/blacklight/document_presenter_spec.rb +3 -3
  60. data/spec/presenters/blacklight/field_presenter_spec.rb +103 -22
  61. data/spec/presenters/blacklight/rendering/pipeline_spec.rb +130 -14
  62. metadata +8 -16
  63. data/app/controllers/concerns/blacklight/facetable.rb +0 -34
  64. data/app/models/facet_search_builder.rb +0 -5
  65. data/app/services/blacklight/facet_search_service.rb +0 -44
  66. data/app/views/shared/_sitelinks_search_box.html.erb +0 -12
  67. data/lib/blacklight/abstract_search_builder.rb +0 -154
  68. data/lib/blacklight/facet_search_builder.rb +0 -18
  69. data/lib/blacklight/solr/facet_search_builder_behavior.rb +0 -62
  70. data/spec/features/sitelinks_search_box_spec.rb +0 -13
  71. data/spec/models/blacklight/facet_search_builder_spec.rb +0 -19
  72. data/spec/models/blacklight/solr/facet_search_builder_behavior_spec.rb +0 -929
@@ -47,7 +47,6 @@ module Blacklight
47
47
  property :header_component, default: Blacklight::HeaderComponent
48
48
  property :full_width_layout, default: false
49
49
 
50
- # bootstrap_version may be set to 4 or 5
51
50
  bootstrap_version = ENV['BOOTSTRAP_VERSION'].presence || "5"
52
51
  property :bootstrap_version, default: /(\d)(?:\.\d){0,2}/.match(bootstrap_version)[1].to_i
53
52
 
@@ -73,7 +72,8 @@ module Blacklight
73
72
  # @!attribute json_solr_path
74
73
  # @since v7.34.0
75
74
  # @return [String] The url path (relative to the solr base url) to use when using Solr's JSON Query DSL (as with the advanced search)
76
- property :json_solr_path, default: 'advanced'
75
+ # @note You can configure a separate custom 'advanced' requestHandler in solrconfig.xml if desired, but it isn't necessary; the default 'select' handler will work.
76
+ property :json_solr_path, default: 'select'
77
77
  # @!attribute document_unique_id_param
78
78
  # @since v5.2.0
79
79
  # @return [Symbol] The solr query parameter used for sending the unique identifiers for one or more documents
@@ -103,9 +103,6 @@ module Blacklight
103
103
  # @!attribute search_builder_class
104
104
  # @return [Class] class for converting Blacklight parameters to request parameters for the repository_class
105
105
  property :search_builder_class, default: ::SearchBuilder
106
- # @!attribute search_builder_class
107
- # @return [Class] class for converting Blacklight parameters to request parameters for the repository_class
108
- property :facet_search_builder_class, default: ::FacetSearchBuilder
109
106
  # @!attribute response_model
110
107
  # model that maps index responses to the blacklight response model
111
108
  # @return [Class]
@@ -147,11 +144,15 @@ module Blacklight
147
144
  # @return [Blacklight::Configuration::ViewConfig::Index]
148
145
  property :index, default: ViewConfig::Index.new(
149
146
  # document presenter class used by helpers and views
150
- document_presenter_class: nil,
147
+ document_presenter_class: Blacklight::IndexPresenter,
151
148
  # document presenter used for json responses
152
149
  json_presenter_class: Blacklight::JsonPresenter,
153
150
  # component class used to render a document
154
151
  document_component: Blacklight::DocumentComponent,
152
+ document_embed_component: nil,
153
+ document_metadata_component: Blacklight::DocumentMetadataComponent,
154
+ document_thumbnail_component: Blacklight::Document::ThumbnailComponent,
155
+ document_title_component: Blacklight::DocumentTitleComponent,
155
156
  sidebar_component: Blacklight::Search::SidebarComponent,
156
157
  dropdown_component: Blacklight::System::DropdownComponent,
157
158
  # solr field to use to render a document title
@@ -187,8 +188,9 @@ module Blacklight
187
188
  # @return [Blacklight::Configuration::ViewConfig::Show]
188
189
  property :show, default: ViewConfig::Show.new(
189
190
  # document presenter class used by helpers and views
190
- document_presenter_class: nil,
191
+ document_presenter_class: Blacklight::ShowPresenter,
191
192
  document_component: Blacklight::DocumentComponent,
193
+ document_thumbnail_component: nil,
192
194
  show_tools_component: Blacklight::Document::ShowToolsComponent,
193
195
  show_header_tools_component: nil,
194
196
  document_header_component: Blacklight::Document::PageHeaderComponent,
@@ -269,6 +271,10 @@ module Blacklight
269
271
  # @since v5.10.0
270
272
  # @return [Integer]
271
273
  property :default_facet_limit, default: 10
274
+ # @!attribute default_facet_suggest
275
+ # @since v9.0.0
276
+ # @return [Boolean]
277
+ property :default_facet_suggest, default: true
272
278
  # @!attribute default_more_limit
273
279
  # @since v7.0.0
274
280
  # @return [Integer]
@@ -299,8 +305,13 @@ module Blacklight
299
305
 
300
306
  # @!attribute advanced_search
301
307
  # @since v7.15.0
302
- # @return [#enabled]
303
- property :advanced_search, default: OpenStruct.new(enabled: false)
308
+ # @return [OpenStructWithHashAccess] Configuration for advanced search, including:
309
+ # enabled: (Boolean) whether advanced search is enabled
310
+ # form_solr_parameters: (Hash) optional parameters to send to Solr for the advanced search
311
+ # form; can override values that are set automatically via the
312
+ # #copy_facet_field_config_to_advanced! method
313
+ property :advanced_search, default: OpenStructWithHashAccess.new(enabled: true,
314
+ form_solr_parameters: {})
304
315
 
305
316
  # @!attribute enable_search_bar_autofocus
306
317
  # @since v7.2.0
@@ -457,6 +468,42 @@ module Blacklight
457
468
  facet_fields.map { |_facet, opts| opts[:group] }.uniq
458
469
  end
459
470
 
471
+ # Use existing search field configs to automatically prepare fields for use
472
+ # by the advanced search form.
473
+ def copy_search_field_config_to_advanced!
474
+ search_fields.each_value do |field|
475
+ next if field.include_in_advanced_search == false
476
+ next if field.clause_params
477
+
478
+ field.clause_params = {}
479
+ field.clause_params[:edismax] = field.solr_parameters.dup || {}
480
+ end
481
+ end
482
+
483
+ # Use existing facet field configs to automatically prepare fields for use
484
+ # by the advanced search form. If more specific config is needed, e.g., to
485
+ # set the facet limit for one field to a value other than -1, it can be
486
+ # expressed in the configuration in advanced_search.form_solr_parameters
487
+ def copy_facet_field_config_to_advanced!
488
+ advanced_search.form_solr_parameters ||= {}
489
+ advanced_search.form_solr_parameters['facet.sort'] ||= 'count'
490
+ advanced_search.form_solr_parameters['facet.field'] ||= []
491
+
492
+ facet_fields.each_value do |field|
493
+ next if field.include_in_advanced_search == false
494
+ # Skip query-type and pivot facets that can't be requested via facet.field
495
+ next if field.query || field.pivot || field.range
496
+
497
+ # Add the facet field to the advanced search configuration
498
+ advanced_search.form_solr_parameters['facet.field'] << field.field unless
499
+ advanced_search.form_solr_parameters['facet.field'].include?(field.field)
500
+
501
+ # Set the facet field's limit to -1 to show ALL values in advanced search
502
+ advanced_search.form_solr_parameters["f.#{field.field}.facet.limit"] = -1 unless
503
+ advanced_search.form_solr_parameters["f.#{field.field}.facet.limit"]
504
+ end
505
+ end
506
+
460
507
  # Add any configured facet fields to the default solr parameters hash
461
508
  # @overload add_facet_fields_to_solr_request!
462
509
  # add all facet fields to the solr request
@@ -18,7 +18,7 @@ module Blacklight
18
18
  mapper.get "opensearch"
19
19
  mapper.get 'suggest', as: 'suggest_index'
20
20
  mapper.get "facet/:id", action: 'facet', as: 'facet'
21
- mapper.get "facet_suggest/:id/(:query_fragment)", action: 'facet', as: 'facet_suggest', defaults: { only_values: true }
21
+ mapper.get "facet_suggest/:id", action: 'facet', as: 'facet_suggest', defaults: { only_values: true }
22
22
  end
23
23
  end
24
24
  end
@@ -5,7 +5,45 @@ module Blacklight
5
5
  # Blacklight's SearchBuilder converts blacklight request parameters into
6
6
  # query parameters appropriate for search index. It does so by evaluating a
7
7
  # chain of processing methods to populate a result hash (see {#to_hash}).
8
- class SearchBuilder < AbstractSearchBuilder
8
+ class SearchBuilder
9
+ class_attribute :default_processor_chain
10
+ self.default_processor_chain = []
11
+
12
+ attr_reader :processor_chain, :search_state, :blacklight_params
13
+
14
+ # @overload initialize(scope)
15
+ # @param [Object] scope the scope where the filter methods reside in.
16
+ # @overload initialize(processor_chain, scope)
17
+ # @param [List<Symbol>,TrueClass] processor_chain options a list of filter methods to run or true, to use the default methods
18
+ # @param [Object] scope the scope where the filter methods reside in.
19
+ def initialize(*options)
20
+ case options.size
21
+ when 1
22
+ @processor_chain = default_processor_chain.dup
23
+ @scope = options.first
24
+ when 2
25
+ @processor_chain, @scope = options
26
+ else
27
+ raise ArgumentError, "wrong number of arguments. (#{options.size} for 1..2)"
28
+ end
29
+
30
+ @blacklight_params = {}
31
+ search_state_class = @scope.try(:search_state_class) || Blacklight::SearchState
32
+ @search_state = search_state_class.new(@blacklight_params, @scope&.blacklight_config, @scope)
33
+ @additional_filters = {}
34
+ @merged_params = {}
35
+ @reverse_merged_params = {}
36
+ end
37
+
38
+ ##
39
+ # Set the parameters to pass through the processor chain
40
+ def with(blacklight_params_or_search_state = {})
41
+ params_will_change!
42
+ @search_state = blacklight_params_or_search_state.is_a?(Blacklight::SearchState) ? blacklight_params_or_search_state : @search_state.reset(blacklight_params_or_search_state)
43
+ @blacklight_params = @search_state.params.dup
44
+ self
45
+ end
46
+
9
47
  ##
10
48
  # Update the :q (query) parameter
11
49
  # @param [Hash<Symbol,Object>] conditions the field and values to query on
@@ -21,6 +59,7 @@ module Blacklight
21
59
 
22
60
  ##
23
61
  # Append additional processor chain directives
62
+ # This is used in blacklight_range_limit
24
63
  def append(*addl_processor_chain)
25
64
  params_will_change!
26
65
  builder = self.class.new(processor_chain + addl_processor_chain, scope)
@@ -55,6 +94,68 @@ module Blacklight
55
94
  builder
56
95
  end
57
96
 
97
+ ##
98
+ # Merge additional, repository-specific parameters
99
+ def merge(extra_params, &)
100
+ if extra_params
101
+ params_will_change!
102
+ @merged_params.merge!(extra_params.to_hash, &)
103
+ end
104
+ self
105
+ end
106
+
107
+ ##
108
+ # "Reverse merge" additional, repository-specific parameters
109
+ def reverse_merge(extra_params, &)
110
+ if extra_params
111
+ params_will_change!
112
+ @reverse_merged_params.reverse_merge!(extra_params.to_hash, &)
113
+ end
114
+ self
115
+ end
116
+
117
+ delegate :[], :key?, to: :to_hash
118
+
119
+ # a solr query method
120
+ # @return [Blacklight::Solr::Response] the solr response object
121
+ def to_hash
122
+ return @params unless params_need_update?
123
+
124
+ @params = processed_parameters
125
+ .reverse_merge(@reverse_merged_params)
126
+ .merge(@merged_params)
127
+ .tap { clear_changes }
128
+ end
129
+
130
+ alias_method :query, :to_hash
131
+ alias_method :to_h, :to_hash
132
+
133
+ # The CatalogController #index action uses this.
134
+ # Solr parameters can come from a number of places. From lowest
135
+ # precedence to highest:
136
+ # 1. General defaults in blacklight config (are trumped by)
137
+ # 2. defaults for the particular search field identified by params[:search_field] (are trumped by)
138
+ # 3. certain parameters directly on input HTTP query params
139
+ # * not just any parameter is grabbed willy nilly, only certain ones are allowed by HTTP input)
140
+ # * for legacy reasons, qt in http query does not over-ride qt in search field definition default.
141
+ # 4. extra parameters passed in as argument.
142
+ #
143
+ # spellcheck.q will be supplied with the [:q] value unless specifically
144
+ # specified otherwise.
145
+ #
146
+ # Incoming parameter :f is mapped to :fq solr parameter.
147
+ #
148
+ # @return a params hash for searching solr.
149
+ def processed_parameters
150
+ request.tap do |request_parameters|
151
+ processor_chain.each do |method_name|
152
+ send(method_name, request_parameters)
153
+ end
154
+ end
155
+ end
156
+
157
+ delegate :blacklight_config, to: :scope
158
+
58
159
  def start=(value)
59
160
  params_will_change!
60
161
  @start = value.to_i
@@ -109,6 +210,34 @@ module Blacklight
109
210
 
110
211
  alias per rows
111
212
 
213
+ # sets the facet that this query pertains to, for the purpose of facet pagination
214
+ def facet=(value)
215
+ params_will_change!
216
+ @facet = value
217
+ end
218
+
219
+ # @param [Object] value
220
+ def facet(value = nil)
221
+ if value
222
+ self.facet = value
223
+ return self
224
+ end
225
+ @facet
226
+ end
227
+
228
+ def facet_suggestion_query=(value)
229
+ params_will_change!
230
+ @facet_suggestion_query = value
231
+ end
232
+
233
+ def facet_suggestion_query(value = nil)
234
+ if value
235
+ self.facet_suggestion_query = value
236
+ return self
237
+ end
238
+ @facet_suggestion_query
239
+ end
240
+
112
241
  # Decode the user provided 'sort' parameter into a sort string that can be
113
242
  # passed to the search. This sanitizes the input by ensuring only
114
243
  # configured search values are passed through to the search.
@@ -116,5 +245,35 @@ module Blacklight
116
245
  def sort
117
246
  search_state.sort_field&.sort
118
247
  end
248
+
249
+ delegate :search_field, to: :search_state
250
+
251
+ private
252
+
253
+ def request
254
+ Blacklight::Solr::Request.new
255
+ end
256
+
257
+ def should_add_field_to_request? _field_name, field
258
+ field.include_in_request || (field.include_in_request.nil? && blacklight_config.add_field_configuration_to_solr_request)
259
+ end
260
+
261
+ attr_reader :scope
262
+
263
+ def params_will_change!
264
+ @dirty = true
265
+ end
266
+
267
+ def params_changed?
268
+ !!@dirty
269
+ end
270
+
271
+ def params_need_update?
272
+ params_changed? || @params.nil?
273
+ end
274
+
275
+ def clear_changes
276
+ @dirty = false
277
+ end
119
278
  end
120
279
  end
@@ -102,7 +102,7 @@ module Blacklight
102
102
  end
103
103
  queries.uniq!
104
104
  end
105
- [(queries - existing)]
105
+ [queries - existing]
106
106
  end
107
107
  end
108
108
 
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight::Solr
4
+ class FieldReflectionSearchBuilder < SearchBuilder
5
+ self.default_processor_chain = [:add_params]
6
+
7
+ def add_params(request)
8
+ request.reverse_merge!({ fl: '*', 'json.nl' => 'map' })
9
+ end
10
+ end
11
+ end
@@ -7,8 +7,7 @@ module Blacklight::Solr
7
7
  # @param [String] id document's unique key value
8
8
  # @param [Hash] params additional solr query parameters
9
9
  def find id, params = {}
10
- doc_params = params.reverse_merge(blacklight_config.default_document_solr_params)
11
- .merge(blacklight_config.document_unique_id_param => id)
10
+ doc_params = SingleDocSearchBuilder.new(self, id, params)
12
11
 
13
12
  solr_response = send_and_receive blacklight_config.document_solr_path || blacklight_config.solr_path, doc_params
14
13
  raise Blacklight::Exceptions::RecordNotFound if solr_response.documents.empty?
@@ -24,14 +23,14 @@ module Blacklight::Solr
24
23
 
25
24
  ##
26
25
  # Execute a search query against solr
27
- # @param [Hash] params solr query parameters
26
+ # @param [Hash,Blacklight::SearchBuilder] params solr query parameters
28
27
  # @param [String] path solr request handler path
29
28
  def search pos_params = nil, path: nil, params: nil, **kwargs
30
29
  if pos_params
31
30
  Blacklight.deprecation.warn("Passing positional arguments to search() is deprecated. Use the params kwarg instead.")
32
31
  end
33
32
 
34
- request_params = (params || pos_params).reverse_merge(kwargs).reverse_merge({ qt: blacklight_config.qt })
33
+ request_params = (params || pos_params || {}).reverse_merge(kwargs).reverse_merge({ qt: blacklight_config.qt })
35
34
 
36
35
  send_and_receive(path || default_search_path(request_params), request_params)
37
36
  end
@@ -47,7 +46,8 @@ module Blacklight::Solr
47
46
  # Gets a list of available fields
48
47
  # @return [Hash]
49
48
  def reflect_fields
50
- send_and_receive('admin/luke', params: { fl: '*', 'json.nl' => 'map' })['fields']
49
+ doc_params = FieldReflectionSearchBuilder.new(self)
50
+ send_and_receive('admin/luke', doc_params)['fields']
51
51
  end
52
52
 
53
53
  ##
@@ -1,16 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Blacklight::Solr
4
+ # This depends on being imported into a class that extends AbstractSearchBuilder
4
5
  module SearchBuilderBehavior
5
6
  extend ActiveSupport::Concern
6
7
 
7
8
  included do
8
9
  self.default_processor_chain = [
9
- :default_solr_parameters, :add_search_field_default_parameters,
10
- :add_query_to_solr, :add_facet_fq_to_solr,
11
- :add_facetting_to_solr, :add_solr_fields_to_query, :add_paging_to_solr,
12
- :add_sorting_to_solr, :add_group_config_to_solr,
10
+ :default_solr_parameters,
11
+ :add_search_field_default_parameters,
12
+ :add_query_to_solr,
13
+ :add_facet_fq_to_solr,
14
+ :add_facetting_to_solr,
15
+ :add_solr_fields_to_query,
16
+ :add_paging_to_solr,
17
+ :add_sorting_to_solr,
18
+ :add_group_config_to_solr,
13
19
  :add_adv_search_clauses,
20
+ :add_facets_for_advanced_search_form,
21
+ :add_facet_paging_to_solr,
22
+ :add_facet_suggestion_parameters,
14
23
  :add_additional_filters
15
24
  ]
16
25
  end
@@ -95,6 +104,13 @@ module Blacklight::Solr
95
104
  def add_adv_search_clauses(solr_parameters)
96
105
  return if search_state.clause_params.blank?
97
106
 
107
+ # We need to specify lucene as the top-level defType when using JSON Query DSL in Solr versions
108
+ # between 7.2.0 & 9.4.0. After 9.4.0 this is no longer necessary, but also not harmful to include.
109
+ solr_parameters[:defType] = 'lucene'
110
+
111
+ # Disable spellcheck, which doesn't work when using JSON Query DSL
112
+ solr_parameters[:spellcheck] = 'false'
113
+
98
114
  defaults = { must: [], must_not: [], should: [] }
99
115
  default_op = blacklight_params[:op]&.to_sym || :must
100
116
  solr_parameters[:mm] = 1 if default_op == :should && search_state.clause_params.values.any? { |clause| }
@@ -117,6 +133,16 @@ module Blacklight::Solr
117
133
  [op, field.clause_params.transform_values { |v| v.merge(query: clause[:query]) }]
118
134
  end
119
135
 
136
+ # Merge the advanced search form parameters into the solr parameters
137
+ # @param [Hash] solr_parameters the current solr parameters
138
+ # @return [Hash] the solr parameters with the additional advanced search form parameters
139
+ def add_facets_for_advanced_search_form(solr_parameters)
140
+ return unless search_state.controller&.action_name == 'advanced_search' &&
141
+ blacklight_config.advanced_search[:form_solr_parameters]
142
+
143
+ solr_parameters.merge!(blacklight_config.advanced_search[:form_solr_parameters])
144
+ end
145
+
120
146
  ##
121
147
  # Add any existing facet limits, stored in app-level HTTP query
122
148
  # as :f, to solr as appropriate :fq query.
@@ -215,8 +241,6 @@ module Blacklight::Solr
215
241
  # copy paging params from BL app over to solr, changing
216
242
  # app level per_page and page to Solr rows and start.
217
243
  def add_paging_to_solr(solr_params)
218
- rows(solr_params[:rows] || 10) if rows.nil?
219
-
220
244
  solr_params[:rows] = rows
221
245
 
222
246
  solr_params[:start] = start if start.nonzero?
@@ -233,6 +257,48 @@ module Blacklight::Solr
233
257
  solr_parameters[:group] = false if search_state.filter(grouped_key_for_results).any?
234
258
  end
235
259
 
260
+ def add_facet_paging_to_solr(solr_params)
261
+ return if facet.blank?
262
+
263
+ facet_config = blacklight_config.facet_fields[facet]
264
+
265
+ solr_params[:rows] = 0
266
+
267
+ limit = if solr_params["facet.limit"]
268
+ solr_params["facet.limit"].to_i
269
+ else
270
+ facet_config.fetch(:more_limit, blacklight_config.default_more_limit)
271
+ end
272
+
273
+ page = search_state.facet_page
274
+ sort = search_state.facet_sort
275
+ prefix = search_state.facet_prefix
276
+ offset = (page - 1) * limit
277
+
278
+ if facet_config.json
279
+ add_solr_facet_json_params(solr_parameters, facet, facet_config, limit: limit + 1, offset: offset, sort: sort, prefix: prefix)
280
+ return
281
+ end
282
+
283
+ # Now override with our specific things for fetching facet values
284
+ facet_ex = facet_config.respond_to?(:ex) ? facet_config.ex : nil
285
+ solr_params[:'facet.field'] = with_ex_local_param(facet_ex, facet_config.field)
286
+
287
+ # Need to set as f.facet_field.facet.* to make sure we
288
+ # override any field-specific default in the solr request handler.
289
+ solr_params[:"f.#{facet_config.field}.facet.limit"] = limit + 1
290
+ solr_params[:"f.#{facet_config.field}.facet.offset"] = offset
291
+ solr_params[:"f.#{facet_config.field}.facet.sort"] = sort if sort
292
+ solr_params[:"f.#{facet_config.field}.facet.prefix"] = prefix if prefix
293
+ end
294
+
295
+ def add_facet_suggestion_parameters(solr_params)
296
+ return if facet.blank? || facet_suggestion_query.blank?
297
+
298
+ solr_params[:'facet.contains'] = facet_suggestion_query[0..50]
299
+ solr_params[:'facet.contains.ignoreCase'] = true
300
+ end
301
+
236
302
  def with_ex_local_param(ex, value)
237
303
  if ex
238
304
  "{!ex=#{ex}}#{value}"
@@ -243,7 +309,7 @@ module Blacklight::Solr
243
309
 
244
310
  # Look up facet limit for given facet_field. Will look at config, and
245
311
  # if config is 'true' will look up from Solr @response if available. If
246
- # no limit is avaialble, returns nil. Used from #add_facetting_to_solr
312
+ # no limit is available, returns nil. Used from #add_facetting_to_solr
247
313
  # to supply f.fieldname.facet.limit values in solr request (no @response
248
314
  # available), and used in display (with @response available) to create
249
315
  # a facet paginator with the right limit.
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight::Solr
4
+ class SingleDocSearchBuilder < SearchBuilder
5
+ self.default_processor_chain = [:add_defaults, :add_qt, :add_unique_id]
6
+
7
+ def initialize(scope, id, other_params)
8
+ @other_params = other_params
9
+ @id = id
10
+ super(scope)
11
+ end
12
+
13
+ def add_defaults(request)
14
+ request.reverse_merge!(blacklight_config.default_document_solr_params).reverse_merge!(@other_params)
15
+ end
16
+
17
+ def add_qt(request)
18
+ request[:qt] ||= blacklight_config.document_solr_request_handler if blacklight_config.document_solr_request_handler
19
+ end
20
+
21
+ def add_unique_id(request)
22
+ request[blacklight_config.document_unique_id_param] = @id
23
+ end
24
+ end
25
+ end
@@ -12,7 +12,7 @@ class <%= controller_name.classify %>Controller < ApplicationController
12
12
  # rescue_from Blacklight::Exceptions::InvalidRequest, with: :my_handling_method
13
13
 
14
14
  configure_blacklight do |config|
15
- ## Specify the style of markup to be generated (may be 4 or 5)
15
+ ## Specify the style of markup to be generated
16
16
  # config.bootstrap_version = 5
17
17
  #
18
18
  ## Class for sending and receiving requests from a search index
@@ -29,6 +29,13 @@ class <%= controller_name.classify %>Controller < ApplicationController
29
29
  #
30
30
  ## Should the raw solr document endpoint (e.g. /catalog/:id/raw) be enabled
31
31
  # config.raw_endpoint.enabled = false
32
+ #
33
+ ## Should advanced search be enabled
34
+ # config.advanced_search.enabled = true
35
+ #
36
+ ## Optional fine-tuning for advanced search, e.g., set different limits for
37
+ ## different facets.
38
+ # config.advanced_search.form_solr_parameters = {}
32
39
 
33
40
  ## Default parameters to send to solr for all search-like requests. See also SearchBuilder#processed_parameters
34
41
  config.default_solr_params = {
@@ -38,7 +45,7 @@ class <%= controller_name.classify %>Controller < ApplicationController
38
45
  # solr path which will be added to solr base url before the other solr params.
39
46
  #config.solr_path = 'select'
40
47
  #config.document_solr_path = 'get'
41
- #config.json_solr_path = 'advanced'
48
+ #config.json_solr_path = 'select'
42
49
 
43
50
  # items to show per page, each number in the array represent another option to choose from.
44
51
  #config.per_page = [10,20,50,100]
@@ -105,6 +112,12 @@ class <%= controller_name.classify %>Controller < ApplicationController
105
112
  # :show may be set to false if you don't want the facet to be drawn in the
106
113
  # facet bar
107
114
  #
115
+ # Set :include_in_advanced_search to false for any search field or facet field
116
+ # that you want to exclude from appearing in the advanced search page.
117
+ #
118
+ # Set :include_in_simple_select to false for any search field you want to render
119
+ # in the Advanced Search page but exclude from the main search box scope selector.
120
+ #
108
121
  # Set :index_range to true if you want the facet pagination view to have facet prefix-based navigation.
109
122
  # (useful when user clicks "more" on a large facet and wants to navigate alphabetically across a large set of results)
110
123
  # :index_range can be an array or range of prefixes that will be used to create the navigation (note: It is case sensitive when searching values)
@@ -121,7 +134,9 @@ class <%= controller_name.classify %>Controller < ApplicationController
121
134
 
122
135
  config.add_facet_field 'example_pivot_field',
123
136
  label: 'Pivot Field',
124
- pivot: ['language_ssim', 'subject_geo_ssim', 'subject_ssim'], collapsing: true
137
+ pivot: ['language_ssim', 'subject_geo_ssim', 'subject_ssim'],
138
+ collapsing: true,
139
+ include_in_advanced_search: false
125
140
 
126
141
  config.add_facet_field 'example_query_facet_field', label: 'Publish Date', :query => {
127
142
  :years_5 => { label: 'within 5 Years', fq: "pub_date_ssim:[#{Time.zone.now.year - 5 } TO *]" },
@@ -165,7 +180,7 @@ class <%= controller_name.classify %>Controller < ApplicationController
165
180
  config.add_show_field 'isbn_ssim', label: 'ISBN'
166
181
 
167
182
  # "fielded" search configuration. Used by pulldown among other places.
168
- # For supported keys in hash, see rdoc for Blacklight::SearchFields
183
+ # For supported keys in hash, see rdoc for Blacklight::Configuration::SearchField
169
184
  #
170
185
  # Search fields will inherit the :qt solr request handler from
171
186
  # config[:default_solr_parameters], OR can specify a different one
@@ -208,7 +223,7 @@ class <%= controller_name.classify %>Controller < ApplicationController
208
223
 
209
224
  # Specifying a :qt only to show it's possible, and so our internal automated
210
225
  # tests can test it. In this case it's the same as
211
- # config[:default_solr_parameters][:qt], so isn't actually neccesary.
226
+ # config[:default_solr_parameters][:qt], so isn't actually necessary.
212
227
  config.add_search_field('subject') do |field|
213
228
  field.qt = 'search'
214
229
  field.solr_parameters = {
@@ -218,6 +233,13 @@ class <%= controller_name.classify %>Controller < ApplicationController
218
233
  }
219
234
  end
220
235
 
236
+ # Set up a default advanced search configuration by using the current
237
+ # search_fields and facet_fields configs.
238
+ if config.advanced_search.enabled
239
+ config.copy_search_field_config_to_advanced!
240
+ config.copy_facet_field_config_to_advanced!
241
+ end
242
+
221
243
  # "sort results by" select (pulldown)
222
244
  # label in pulldown is followed by the name of the Solr field to sort by and
223
245
  # whether the sort is ascending or descending (it must be asc or desc