blacklight 5.7.2 → 5.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -3
- data/Gemfile +1 -4
- data/VERSION +1 -1
- data/app/assets/stylesheets/blacklight/_catalog.css.scss +38 -1
- data/app/assets/stylesheets/blacklight/_facets.css.scss +10 -0
- data/app/assets/stylesheets/blacklight/_layout.css.scss +6 -0
- data/app/controllers/bookmarks_controller.rb +3 -163
- data/app/helpers/blacklight/blacklight_helper_behavior.rb +18 -186
- data/app/helpers/blacklight/catalog_helper_behavior.rb +36 -2
- data/app/helpers/blacklight/component_helper_behavior.rb +77 -0
- data/app/helpers/blacklight/configuration_helper_behavior.rb +30 -21
- data/app/helpers/blacklight/render_partials_helper.rb +185 -0
- data/app/helpers/blacklight/url_helper_behavior.rb +24 -3
- data/app/helpers/component_helper.rb +3 -0
- data/app/views/_user_util_links.html.erb +2 -15
- data/app/views/blacklight/nav/_bookmark.html.erb +4 -0
- data/app/views/blacklight/nav/_saved_searches.html.erb +1 -0
- data/app/views/blacklight/nav/_search_history.html.erb +1 -0
- data/app/views/bookmarks/_tools.html.erb +6 -9
- data/app/views/bookmarks/index.html.erb +1 -1
- data/app/views/catalog/_bookmark_control.html.erb +8 -8
- data/app/views/catalog/_constraints_element.html.erb +1 -1
- data/app/views/catalog/_document_action.html.erb +4 -0
- data/app/views/catalog/_email_form.html.erb +1 -1
- data/app/views/catalog/_facet_limit.html.erb +1 -1
- data/app/views/catalog/_index_header_default.html.erb +5 -6
- data/app/views/catalog/_per_page_widget.html.erb +3 -1
- data/app/views/catalog/_results_pagination.html.erb +1 -1
- data/app/views/catalog/_search_form.html.erb +5 -8
- data/app/views/catalog/_show_more_like_this.html.erb +2 -2
- data/app/views/catalog/_show_tools.html.erb +5 -34
- data/app/views/catalog/_sms_form.html.erb +1 -1
- data/app/views/catalog/_sort_and_per_page.html.erb +2 -6
- data/app/views/catalog/_sort_widget.html.erb +1 -1
- data/app/views/catalog/_zero_results.html.erb +2 -2
- data/app/views/catalog/citation.js.erb +1 -1
- data/app/views/catalog/email_sent.html.erb +2 -9
- data/app/views/catalog/email_success.html.erb +9 -0
- data/app/views/catalog/sms_sent.html.erb +2 -9
- data/app/views/catalog/sms_success.html.erb +9 -0
- data/app/views/kaminari/blacklight/_gap.html.erb +1 -1
- data/app/views/kaminari/blacklight/_page.html.erb +5 -1
- data/app/views/shared/_header_navbar.html.erb +1 -1
- data/config/locales/blacklight.en.yml +1 -1
- data/config/locales/blacklight.es.yml +1 -1
- data/config/locales/blacklight.fr.yml +1 -1
- data/config/locales/blacklight.pt-BR.yml +1 -1
- data/lib/blacklight.rb +3 -0
- data/lib/blacklight/base.rb +0 -1
- data/lib/blacklight/bookmarks.rb +135 -0
- data/lib/blacklight/catalog.rb +58 -77
- data/lib/blacklight/catalog/component_configuration.rb +99 -0
- data/lib/blacklight/configuration.rb +82 -4
- data/lib/blacklight/configuration/tool_config.rb +4 -0
- data/lib/blacklight/controller.rb +5 -1
- data/lib/blacklight/document_presenter.rb +17 -8
- data/lib/blacklight/request_builders.rb +136 -4
- data/lib/blacklight/routes.rb +5 -0
- data/lib/blacklight/solr_helper.rb +90 -208
- data/lib/blacklight/solr_repository.rb +69 -0
- data/lib/blacklight/token_based_user.rb +58 -0
- data/lib/blacklight/utils.rb +13 -1
- data/lib/generators/blacklight/install_generator.rb +6 -7
- data/spec/controllers/alternate_controller_spec.rb +19 -0
- data/spec/controllers/catalog_controller_spec.rb +89 -4
- data/spec/features/alternate_controller_spec.rb +0 -1
- data/spec/features/bookmarks_spec.rb +31 -6
- data/spec/features/search_results_spec.rb +11 -0
- data/spec/features/search_spec.rb +5 -0
- data/spec/helpers/blacklight_helper_spec.rb +49 -8
- data/spec/helpers/catalog_helper_spec.rb +56 -8
- data/spec/helpers/configuration_helper_spec.rb +5 -5
- data/spec/helpers/url_helper_spec.rb +15 -8
- data/spec/lib/blacklight/catalog/component_configuration_spec.rb +29 -0
- data/spec/lib/blacklight/configuration_spec.rb +15 -0
- data/spec/lib/blacklight/solr_helper_spec.rb +44 -104
- data/spec/lib/blacklight/solr_repository_spec.rb +113 -0
- data/spec/lib/utils_spec.rb +27 -0
- data/spec/views/_user_util_links.html.erb_spec.rb +6 -3
- data/spec/views/catalog/_show_sidebar.erb_spec.rb +8 -2
- data/spec/views/catalog/_show_tools.html.erb_spec.rb +82 -0
- data/spec/views/catalog/_sort_and_per_page.html.erb_spec.rb +15 -1
- data/tasks/blacklight.rake +25 -1
- metadata +24 -2
@@ -5,6 +5,7 @@ module Blacklight
|
|
5
5
|
class Configuration < OpenStructWithHashAccess
|
6
6
|
|
7
7
|
require 'blacklight/configuration/view_config'
|
8
|
+
require 'blacklight/configuration/tool_config'
|
8
9
|
# XXX this isn't very pretty, but it works.
|
9
10
|
require 'blacklight/configuration/fields'
|
10
11
|
require 'blacklight/configuration/solr_field'
|
@@ -31,6 +32,7 @@ module Blacklight
|
|
31
32
|
:default_solr_params => {},
|
32
33
|
# the model to load solr response documents into; set below in #initialize_default_values
|
33
34
|
:solr_document_model => nil,
|
35
|
+
:solr_response_model => nil,
|
34
36
|
# The solr rqeuest handler to use when requesting only a single document
|
35
37
|
:document_solr_request_handler => 'document',
|
36
38
|
# THe path to send single document requests to solr
|
@@ -56,6 +58,8 @@ module Blacklight
|
|
56
58
|
:display_type_field => 'format',
|
57
59
|
# partials to render for each document(see #render_document_partials)
|
58
60
|
:partials => [:index_header, :thumbnail, :index],
|
61
|
+
:document_actions => NestedOpenStructWithHashAccess.new(ToolConfig),
|
62
|
+
:collection_actions => NestedOpenStructWithHashAccess.new(ToolConfig),
|
59
63
|
# what field, if any, to use to render grouped results
|
60
64
|
:group => false,
|
61
65
|
# additional response formats for search results
|
@@ -69,8 +73,10 @@ module Blacklight
|
|
69
73
|
# current controller.
|
70
74
|
route: nil,
|
71
75
|
# partials to render for each document(see #render_document_partials)
|
72
|
-
partials: [:show_header, :show]
|
76
|
+
partials: [:show_header, :show],
|
77
|
+
document_actions: NestedOpenStructWithHashAccess.new(ToolConfig)
|
73
78
|
),
|
79
|
+
:navbar => OpenStructWithHashAccess.new(partials: { }),
|
74
80
|
# Configurations for specific types of index views
|
75
81
|
:view => NestedOpenStructWithHashAccess.new(ViewConfig, 'list'),
|
76
82
|
# Maxiumum number of spelling suggestions to offer
|
@@ -137,6 +143,10 @@ module Blacklight
|
|
137
143
|
super || SolrDocument
|
138
144
|
end
|
139
145
|
|
146
|
+
def solr_response_model
|
147
|
+
super || Blacklight::SolrResponse
|
148
|
+
end
|
149
|
+
|
140
150
|
##
|
141
151
|
# DSL helper
|
142
152
|
def configure
|
@@ -226,10 +236,16 @@ module Blacklight
|
|
226
236
|
# Provide a 'deep copy' of Blacklight::Configuration that can be modifyed without affecting
|
227
237
|
# the original Blacklight::Configuration instance.
|
228
238
|
#
|
229
|
-
|
230
|
-
|
239
|
+
# The Rails 3.x version only copies hashes, and ignores arrays and similar structures
|
240
|
+
if ::Rails.version < "4.0"
|
241
|
+
def deep_copy
|
242
|
+
Marshal.load(Marshal.dump(self))
|
243
|
+
end
|
244
|
+
alias_method :inheritable_copy, :deep_copy
|
245
|
+
else
|
246
|
+
alias_method :deep_copy, :deep_dup
|
247
|
+
alias_method :inheritable_copy, :deep_dup
|
231
248
|
end
|
232
|
-
alias_method :inheritable_copy, :deep_copy
|
233
249
|
|
234
250
|
##
|
235
251
|
# Get a view configuration for the given view type
|
@@ -241,5 +257,67 @@ module Blacklight
|
|
241
257
|
self.index.merge view.fetch(view_type, {})
|
242
258
|
end
|
243
259
|
end
|
260
|
+
|
261
|
+
##
|
262
|
+
# Add a partial to the tools when rendering a document.
|
263
|
+
# @param partial [String] the name of the document partial
|
264
|
+
# @param opts [Hash]
|
265
|
+
# @option opts [Symbol,Proc] :if render this action if the method identified by the symbol or the proc evaluates to true.
|
266
|
+
# The proc will receive the action configuration and the document or documents for the action.
|
267
|
+
# @option opts [Symbol,Proc] :unless render this action unless the method identified by the symbol or the proc evaluates to true
|
268
|
+
# The proc will receive the action configuration and the document or documents for the action.
|
269
|
+
def add_show_tools_partial(name, opts = {})
|
270
|
+
opts[:partial] ||= 'document_action'
|
271
|
+
add_action(show.document_actions, name, opts)
|
272
|
+
end
|
273
|
+
|
274
|
+
##
|
275
|
+
# Add a tool for the search result list itself
|
276
|
+
# @param partial [String] the name of the document partial
|
277
|
+
# @param opts [Hash]
|
278
|
+
# @option opts [Symbol,Proc] :if render this action if the method identified by the symbol or the proc evaluates to true.
|
279
|
+
# The proc will receive the action configuration and the document or documents for the action.
|
280
|
+
# @option opts [Symbol,Proc] :unless render this action unless the method identified by the symbol or the proc evaluates to true
|
281
|
+
# The proc will receive the action configuration and the document or documents for the action.
|
282
|
+
def add_results_collection_tool(name, opts = {})
|
283
|
+
add_action(index.collection_actions, name, opts)
|
284
|
+
end
|
285
|
+
|
286
|
+
##
|
287
|
+
# Add a partial to the tools for each document in the search results.
|
288
|
+
# @param partial [String] the name of the document partial
|
289
|
+
# @param opts [Hash]
|
290
|
+
# @option opts [Symbol,Proc] :if render this action if the method identified by the symbol or the proc evaluates to true.
|
291
|
+
# The proc will receive the action configuration and the document or documents for the action.
|
292
|
+
# @option opts [Symbol,Proc] :unless render this action unless the method identified by the symbol or the proc evaluates to true
|
293
|
+
# The proc will receive the action configuration and the document or documents for the action.
|
294
|
+
def add_results_document_tool(name, opts = {})
|
295
|
+
add_action(index.document_actions, name, opts)
|
296
|
+
end
|
297
|
+
|
298
|
+
##
|
299
|
+
# Add a partial to the header navbar
|
300
|
+
# @param partial [String] the name of the document partial
|
301
|
+
# @param opts [Hash]
|
302
|
+
# @option opts [Symbol,Proc] :if render this action if the method identified by the symbol or the proc evaluates to true.
|
303
|
+
# The proc will receive the action configuration and the document or documents for the action.
|
304
|
+
# @option opts [Symbol,Proc] :unless render this action unless the method identified by the symbol or the proc evaluates to true
|
305
|
+
# The proc will receive the action configuration and the document or documents for the action.
|
306
|
+
def add_nav_action name, opts = {}
|
307
|
+
add_action(navbar.partials, name, opts)
|
308
|
+
end
|
309
|
+
|
310
|
+
private
|
311
|
+
|
312
|
+
def add_action config_hash, name, opts
|
313
|
+
config = Blacklight::Configuration::ToolConfig.new opts
|
314
|
+
config.name = name
|
315
|
+
|
316
|
+
if block_given?
|
317
|
+
yield config
|
318
|
+
end
|
319
|
+
|
320
|
+
config_hash[name] = config
|
321
|
+
end
|
244
322
|
end
|
245
323
|
end
|
@@ -23,7 +23,7 @@ module Blacklight::Controller
|
|
23
23
|
# extra head content
|
24
24
|
helper_method :has_user_authentication_provider?
|
25
25
|
helper_method :blacklight_config
|
26
|
-
helper_method :search_action_url, :search_action_path
|
26
|
+
helper_method :search_action_url, :search_action_path, :search_facet_url
|
27
27
|
|
28
28
|
|
29
29
|
# This callback runs when a user first logs in
|
@@ -59,6 +59,10 @@ module Blacklight::Controller
|
|
59
59
|
search_action_url *args
|
60
60
|
end
|
61
61
|
|
62
|
+
def search_facet_url options = {}
|
63
|
+
url_for params.merge(action: "facet").merge(options).except(:page)
|
64
|
+
end
|
65
|
+
|
62
66
|
# Returns a list of Searches from the ids in the user's history.
|
63
67
|
def searches_from_history
|
64
68
|
session[:history].blank? ? Search.none : Search.where(:id => session[:history]).order("updated_at desc")
|
@@ -2,6 +2,7 @@ module Blacklight
|
|
2
2
|
class DocumentPresenter
|
3
3
|
include ActionView::Helpers::OutputSafetyHelper
|
4
4
|
include ActionView::Helpers::TagHelper
|
5
|
+
extend Deprecation
|
5
6
|
|
6
7
|
# @param [SolrDocument] document
|
7
8
|
# @param [ActionController::Base] controller scope for linking and generating urls
|
@@ -55,17 +56,25 @@ module Blacklight
|
|
55
56
|
##
|
56
57
|
# Render the document index heading
|
57
58
|
#
|
58
|
-
# @param [Hash] opts
|
59
|
+
# @param [Hash] opts (Deprecated)
|
59
60
|
# @option opts [Symbol] :label Render the given field from the document
|
60
61
|
# @option opts [Proc] :label Evaluate the given proc
|
61
62
|
# @option opts [String] :label Render the given string
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
63
|
+
# @param [Symbol, Proc, String] field Render the given field or evaluate the proc or render the given string
|
64
|
+
def render_document_index_label field, opts ={}
|
65
|
+
if field.kind_of? Hash
|
66
|
+
Deprecation.warn DocumentPresenter, "Calling render_document_index_label with a hash is deprecated"
|
67
|
+
field = field[:label]
|
68
|
+
end
|
69
|
+
label = case field
|
70
|
+
when Symbol
|
71
|
+
@document.get(field, :sep => nil)
|
72
|
+
when Proc
|
73
|
+
field.call(@document, opts)
|
74
|
+
when String
|
75
|
+
field
|
76
|
+
end
|
77
|
+
render_field_value label || @document.id
|
69
78
|
end
|
70
79
|
|
71
80
|
##
|
@@ -6,6 +6,8 @@ module Blacklight
|
|
6
6
|
#
|
7
7
|
module RequestBuilders
|
8
8
|
extend ActiveSupport::Concern
|
9
|
+
extend Deprecation
|
10
|
+
self.deprecation_horizon = 'blacklight 6.0'
|
9
11
|
|
10
12
|
included do
|
11
13
|
# We want to install a class-level place to keep
|
@@ -21,7 +23,11 @@ module Blacklight
|
|
21
23
|
# CatalogController.include ModuleDefiningNewMethod
|
22
24
|
# CatalogController.solr_search_params_logic += [:new_method]
|
23
25
|
# CatalogController.solr_search_params_logic.delete(:we_dont_want)
|
24
|
-
self.solr_search_params_logic = [:default_solr_parameters
|
26
|
+
self.solr_search_params_logic = [:default_solr_parameters, :add_query_to_solr, :add_facet_fq_to_solr, :add_facetting_to_solr, :add_solr_fields_to_query, :add_paging_to_solr, :add_sorting_to_solr, :add_group_config_to_solr ]
|
27
|
+
|
28
|
+
if self.respond_to?(:helper_method)
|
29
|
+
helper_method(:facet_limit_for)
|
30
|
+
end
|
25
31
|
end
|
26
32
|
|
27
33
|
# @returns a params hash for searching solr.
|
@@ -47,6 +53,86 @@ module Blacklight
|
|
47
53
|
end
|
48
54
|
end
|
49
55
|
|
56
|
+
##
|
57
|
+
# Retrieve the results for a list of document ids
|
58
|
+
def solr_document_ids_params(ids = [])
|
59
|
+
solr_documents_by_field_values_params blacklight_config.solr_document_model.unique_key, ids
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Retrieve the results for a list of document ids
|
64
|
+
# @deprecated
|
65
|
+
def solr_documents_by_field_values_params(field, values)
|
66
|
+
q = if Array(values).empty?
|
67
|
+
"{!lucene}NOT *:*"
|
68
|
+
else
|
69
|
+
"{!lucene}#{field}:(#{ Array(values).map { |x| solr_param_quote(x) }.join(" OR ")})"
|
70
|
+
end
|
71
|
+
|
72
|
+
{ q: q, spellcheck: 'false', fl: "*" }
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Retrieve a facet's paginated values.
|
77
|
+
def solr_facet_params(facet_field, user_params=params || {}, extra_controller_params={})
|
78
|
+
input = user_params.deep_merge(extra_controller_params)
|
79
|
+
facet_config = blacklight_config.facet_fields[facet_field]
|
80
|
+
|
81
|
+
solr_params = {}
|
82
|
+
|
83
|
+
# Now override with our specific things for fetching facet values
|
84
|
+
solr_params[:"facet.field"] = with_ex_local_param((facet_config.ex if facet_config.respond_to?(:ex)), facet_field)
|
85
|
+
|
86
|
+
limit = if respond_to?(:facet_list_limit)
|
87
|
+
facet_list_limit.to_s.to_i
|
88
|
+
elsif solr_params["facet.limit"]
|
89
|
+
solr_params["facet.limit"].to_i
|
90
|
+
else
|
91
|
+
20
|
92
|
+
end
|
93
|
+
|
94
|
+
# Need to set as f.facet_field.facet.* to make sure we
|
95
|
+
# override any field-specific default in the solr request handler.
|
96
|
+
solr_params[:"f.#{facet_field}.facet.limit"] = limit + 1
|
97
|
+
solr_params[:"f.#{facet_field}.facet.offset"] = ( input.fetch(Blacklight::Solr::FacetPaginator.request_keys[:page] , 1).to_i - 1 ) * ( limit )
|
98
|
+
solr_params[:"f.#{facet_field}.facet.sort"] = input[ Blacklight::Solr::FacetPaginator.request_keys[:sort] ] if input[ Blacklight::Solr::FacetPaginator.request_keys[:sort] ]
|
99
|
+
solr_params[:rows] = 0
|
100
|
+
|
101
|
+
solr_params
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Opensearch autocomplete parameters for plucking a field's value from the results
|
106
|
+
def solr_opensearch_params(field=nil)
|
107
|
+
if field.nil?
|
108
|
+
Deprecation.warn(Blacklight::RequestBuilders, "Calling Blacklight::RequestBuilders#solr_opensearch_params without a field name is deprecated and will be required in Blacklight 6.0.")
|
109
|
+
end
|
110
|
+
|
111
|
+
solr_params = {}
|
112
|
+
solr_params[:rows] ||= 10
|
113
|
+
solr_params[:fl] = field || blacklight_config.view_config('opensearch').title_field
|
114
|
+
solr_params
|
115
|
+
end
|
116
|
+
|
117
|
+
##
|
118
|
+
# Pagination parameters for selecting the previous and next documents
|
119
|
+
# out of a result set.
|
120
|
+
def previous_and_next_document_params(index, window = 1)
|
121
|
+
solr_params = {}
|
122
|
+
|
123
|
+
if index > 0
|
124
|
+
solr_params[:start] = index - window # get one before
|
125
|
+
solr_params[:rows] = 2*window + 1 # and one after
|
126
|
+
else
|
127
|
+
solr_params[:start] = 0 # there is no previous doc
|
128
|
+
solr_params[:rows] = 2*window # but there should be one after
|
129
|
+
end
|
130
|
+
|
131
|
+
solr_params[:fl] = '*'
|
132
|
+
solr_params[:facet] = false
|
133
|
+
solr_params
|
134
|
+
end
|
135
|
+
|
50
136
|
####
|
51
137
|
# Start with general defaults from BL config. Need to use custom
|
52
138
|
# merge to dup values, to avoid later mutating the original by mistake.
|
@@ -55,7 +141,7 @@ module Blacklight
|
|
55
141
|
solr_parameters[key] = value.dup rescue value
|
56
142
|
end
|
57
143
|
end
|
58
|
-
|
144
|
+
|
59
145
|
##
|
60
146
|
# Take the user-entered query, and put it in the solr params,
|
61
147
|
# including config's "search field" params for current search field.
|
@@ -71,7 +157,7 @@ module Blacklight
|
|
71
157
|
# rspec'd.
|
72
158
|
solr_parameters[:qt] = user_parameters[:qt] if user_parameters[:qt]
|
73
159
|
|
74
|
-
search_field_def =
|
160
|
+
search_field_def = blacklight_config.search_fields[user_parameters[:search_field]]
|
75
161
|
if (search_field_def)
|
76
162
|
solr_parameters[:qt] = search_field_def.qt
|
77
163
|
solr_parameters.merge!( search_field_def.solr_parameters) if search_field_def.solr_parameters
|
@@ -253,8 +339,55 @@ module Blacklight
|
|
253
339
|
end
|
254
340
|
end
|
255
341
|
|
342
|
+
|
343
|
+
DEFAULT_FACET_LIMIT = 10
|
344
|
+
|
345
|
+
# Look up facet limit for given facet_field. Will look at config, and
|
346
|
+
# if config is 'true' will look up from Solr @response if available. If
|
347
|
+
# no limit is avaialble, returns nil. Used from #solr_search_params
|
348
|
+
# to supply f.fieldname.facet.limit values in solr request (no @response
|
349
|
+
# available), and used in display (with @response available) to create
|
350
|
+
# a facet paginator with the right limit.
|
351
|
+
def facet_limit_for(facet_field)
|
352
|
+
facet = blacklight_config.facet_fields[facet_field]
|
353
|
+
return if facet.blank?
|
354
|
+
|
355
|
+
if facet.limit and @response and @response.facet_by_field_name(facet_field)
|
356
|
+
limit = @response.facet_by_field_name(facet_field).limit
|
357
|
+
|
358
|
+
if limit.nil? # we didn't get or a set a limit, so infer one.
|
359
|
+
facet.limit if facet.limit != true
|
360
|
+
elsif limit == -1 # limit -1 is solr-speak for unlimited
|
361
|
+
nil
|
362
|
+
else
|
363
|
+
limit.to_i - 1 # we added 1 to find out if we needed to paginate
|
364
|
+
end
|
365
|
+
elsif facet.limit
|
366
|
+
facet.limit == true ? DEFAULT_FACET_LIMIT : facet.limit
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
##
|
371
|
+
# A helper method used for generating solr LocalParams, put quotes
|
372
|
+
# around the term unless it's a bare-word. Escape internal quotes
|
373
|
+
# if needed.
|
374
|
+
def solr_param_quote(val, options = {})
|
375
|
+
options[:quote] ||= '"'
|
376
|
+
unless val =~ /^[a-zA-Z0-9$_\-\^]+$/
|
377
|
+
val = options[:quote] +
|
378
|
+
# Yes, we need crazy escaping here, to deal with regexp esc too!
|
379
|
+
val.gsub("'", "\\\\\'").gsub('"', "\\\\\"") +
|
380
|
+
options[:quote]
|
381
|
+
end
|
382
|
+
return val
|
383
|
+
end
|
384
|
+
|
256
385
|
private
|
257
386
|
|
387
|
+
def should_add_to_solr field_name, field
|
388
|
+
field.include_in_request || (field.include_in_request.nil? && blacklight_config.add_field_configuration_to_solr_request)
|
389
|
+
end
|
390
|
+
|
258
391
|
##
|
259
392
|
# Convert a facet/value pair into a solr fq parameter
|
260
393
|
def facet_value_to_fq_string(facet_field, value)
|
@@ -284,7 +417,6 @@ module Blacklight
|
|
284
417
|
"{!raw f=#{facet_field}#{(" " + local_params.join(" ")) unless local_params.empty?}}#{value}"
|
285
418
|
end
|
286
419
|
|
287
|
-
|
288
420
|
end
|
289
421
|
end
|
290
422
|
end
|
data/lib/blacklight/routes.rb
CHANGED
@@ -61,6 +61,11 @@ module Blacklight
|
|
61
61
|
def bookmarks(_)
|
62
62
|
add_routes do |options|
|
63
63
|
delete "bookmarks/clear", :to => "bookmarks#clear", :as => "clear_bookmarks"
|
64
|
+
get "bookmarks/email", :as => "email_bookmarks"
|
65
|
+
post "bookmarks/email"
|
66
|
+
get "bookmarks/sms", :as => "sms_bookmarks"
|
67
|
+
post "bookmarks/sms"
|
68
|
+
get "bookmarks/citation", :as => "citation_bookmarks"
|
64
69
|
resources :bookmarks
|
65
70
|
end
|
66
71
|
end
|
@@ -47,65 +47,30 @@
|
|
47
47
|
module Blacklight::SolrHelper
|
48
48
|
extend ActiveSupport::Concern
|
49
49
|
extend Deprecation
|
50
|
-
|
51
|
-
include Blacklight::Facet
|
52
|
-
include ActiveSupport::Benchmarkable
|
50
|
+
self.deprecation_horizon = 'blacklight 6.0'
|
53
51
|
|
54
|
-
|
55
|
-
if self.respond_to?(:helper_method)
|
56
|
-
helper_method(:facet_limit_for)
|
57
|
-
end
|
58
|
-
|
59
|
-
include Blacklight::RequestBuilders
|
60
|
-
|
61
|
-
end
|
52
|
+
include Blacklight::RequestBuilders
|
62
53
|
|
63
54
|
##
|
64
55
|
# Execute a solr query
|
65
|
-
# @see [
|
66
|
-
# @overload find(solr_path, params)
|
67
|
-
# Execute a solr query at the given path with the parameters
|
68
|
-
# @param [String] solr path (defaults to blacklight_config.solr_path)
|
69
|
-
# @param [Hash] parameters for RSolr::Client#send_and_receive
|
70
|
-
# @overload find(params)
|
71
|
-
# @param [Hash] parameters for RSolr::Client#send_and_receive
|
56
|
+
# @see [Blacklight::SolrRepository#send_and_receive]
|
72
57
|
# @return [Blacklight::SolrResponse] the solr response object
|
73
|
-
def find
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
# delete these parameters, otherwise rsolr will pass them through.
|
81
|
-
key = blacklight_config.http_method == :post ? :data : :params
|
82
|
-
res = blacklight_solr.send_and_receive(path, {key=>solr_params.to_hash, method:blacklight_config.http_method})
|
83
|
-
|
84
|
-
solr_response = Blacklight::SolrResponse.new(res, solr_params, solr_document_model: blacklight_config.solr_document_model)
|
85
|
-
|
86
|
-
Rails.logger.debug("Solr query: #{solr_params.inspect}")
|
87
|
-
Rails.logger.debug("Solr response: #{solr_response.inspect}") if defined?(::BLACKLIGHT_VERBOSE_LOGGING) and ::BLACKLIGHT_VERBOSE_LOGGING
|
88
|
-
solr_response
|
89
|
-
end
|
90
|
-
rescue Errno::ECONNREFUSED => e
|
91
|
-
raise Blacklight::Exceptions::ECONNREFUSED.new("Unable to connect to Solr instance using #{blacklight_solr.inspect}")
|
58
|
+
def find *args
|
59
|
+
solr_params = args.extract_options!
|
60
|
+
path = args.first || blacklight_config.solr_path
|
61
|
+
|
62
|
+
solr_params[:qt] ||= blacklight_config.qt
|
63
|
+
|
64
|
+
solr_repository.send_and_receive path, solr_params
|
92
65
|
end
|
93
|
-
|
94
|
-
|
95
|
-
#
|
96
|
-
|
97
|
-
|
98
|
-
def solr_param_quote(val, options = {})
|
99
|
-
options[:quote] ||= '"'
|
100
|
-
unless val =~ /^[a-zA-Z0-9$_\-\^]+$/
|
101
|
-
val = options[:quote] +
|
102
|
-
# Yes, we need crazy escaping here, to deal with regexp esc too!
|
103
|
-
val.gsub("'", "\\\\\'").gsub('"', "\\\\\"") +
|
104
|
-
options[:quote]
|
105
|
-
end
|
106
|
-
return val
|
66
|
+
deprecation_deprecate :find
|
67
|
+
|
68
|
+
# returns a params hash for finding a single solr document (CatalogController #show action)
|
69
|
+
def solr_doc_params(id=nil)
|
70
|
+
default_solr_doc_params(id)
|
107
71
|
end
|
108
|
-
|
72
|
+
deprecation_deprecate :solr_doc_params
|
73
|
+
|
109
74
|
# a solr query method
|
110
75
|
# given a user query, return a solr response containing both result docs and facets
|
111
76
|
# - mixes in the Blacklight::Solr::SpellingSuggestions module
|
@@ -132,111 +97,66 @@ module Blacklight::SolrHelper
|
|
132
97
|
def query_solr(user_params = params || {}, extra_controller_params = {})
|
133
98
|
solr_params = self.solr_search_params(user_params).merge(extra_controller_params)
|
134
99
|
|
135
|
-
|
100
|
+
solr_repository.search(solr_params)
|
136
101
|
end
|
137
|
-
|
138
|
-
# returns a params hash for finding a single solr document (CatalogController #show action)
|
139
|
-
# If the id arg is nil, then the value is fetched from params[:id]
|
140
|
-
# This method is primary called by the get_solr_response_for_doc_id method.
|
141
|
-
def solr_doc_params(id=nil)
|
142
|
-
id ||= params[:id]
|
143
102
|
|
144
|
-
# add our document id to the document_unique_id_param query parameter
|
145
|
-
p = blacklight_config.default_document_solr_params.merge({
|
146
|
-
# this assumes the request handler will map the unique id param
|
147
|
-
# to the unique key field using either solr local params, the
|
148
|
-
# real-time get handler, etc.
|
149
|
-
blacklight_config.document_unique_id_param => id
|
150
|
-
})
|
151
|
-
|
152
|
-
p[:qt] ||= blacklight_config.document_solr_request_handler
|
153
|
-
|
154
|
-
p
|
155
|
-
end
|
156
|
-
|
157
103
|
# a solr query method
|
158
104
|
# retrieve a solr document, given the doc id
|
159
105
|
# @return [Blacklight::SolrResponse, Blacklight::SolrDocument] the solr response object and the first document
|
160
106
|
def get_solr_response_for_doc_id(id=nil, extra_controller_params={})
|
161
|
-
|
162
|
-
|
163
|
-
|
107
|
+
if id.nil?
|
108
|
+
Deprecation.warn Blacklight::SolrHelper, "Calling #get_solr_response_for_doc_id without an explicit id argument is deprecated"
|
109
|
+
id ||= params[:id]
|
110
|
+
end
|
111
|
+
|
112
|
+
old_solr_doc_params = Deprecation.silence(Blacklight::SolrHelper) do
|
113
|
+
solr_doc_params(id)
|
114
|
+
end
|
115
|
+
|
116
|
+
if default_solr_doc_params(id) != old_solr_doc_params
|
117
|
+
Deprecation.warn Blacklight::SolrHelper, "The #solr_doc_params method is deprecated. Instead, you should provide a custom SolrRepository implementation for the additional behavior you're offering"
|
118
|
+
extra_controller_params = extra_controller_params.merge(old_solr_doc_params)
|
119
|
+
end
|
120
|
+
|
121
|
+
solr_response = solr_repository.find id, extra_controller_params
|
164
122
|
[solr_response, solr_response.documents.first]
|
165
123
|
end
|
166
124
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
125
|
+
##
|
126
|
+
# Retrieve a set of documents by id
|
127
|
+
# @overload get_solr_response_for_document_ids(ids, extra_controller_params)
|
128
|
+
# @overload get_solr_response_for_document_ids(ids, user_params, extra_controller_params)
|
129
|
+
def get_solr_response_for_document_ids(ids=[], *args)
|
130
|
+
# user_params = params || {}, extra_controller_params = {}
|
131
|
+
if args.length == 1
|
132
|
+
user_params = params
|
133
|
+
extra_controller_params = args.first || {}
|
176
134
|
else
|
177
|
-
|
135
|
+
user_params, extra_controller_params = args
|
136
|
+
user_params ||= params
|
137
|
+
extra_controller_params ||= {}
|
178
138
|
end
|
179
139
|
|
180
|
-
|
181
|
-
|
182
|
-
:q => q,
|
183
|
-
# not sure why fl * is neccesary, why isn't default solr_search_params
|
184
|
-
# sufficient, like it is for any other search results solr request?
|
185
|
-
# But tests fail without this. I think because some functionality requires
|
186
|
-
# this to actually get solr_doc_params, not solr_search_params. Confused
|
187
|
-
# semantics again.
|
188
|
-
:fl => "*",
|
189
|
-
:facet => 'false',
|
190
|
-
:spellcheck => 'false'
|
191
|
-
}.merge(extra_solr_params)
|
192
|
-
|
193
|
-
solr_response = find(self.solr_search_params().merge(solr_params) )
|
140
|
+
solr_response = query_solr(user_params, extra_controller_params.merge(solr_document_ids_params(ids)))
|
141
|
+
|
194
142
|
[solr_response, solr_response.documents]
|
195
143
|
end
|
196
|
-
|
197
|
-
#
|
198
|
-
#
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
def solr_facet_params(facet_field, user_params=params || {}, extra_controller_params={})
|
204
|
-
input = user_params.deep_merge(extra_controller_params)
|
205
|
-
facet_config = blacklight_config.facet_fields[facet_field]
|
206
|
-
|
207
|
-
# First start with a standard solr search params calculations,
|
208
|
-
# for any search context in our request params.
|
209
|
-
solr_params = solr_search_params(user_params).merge(extra_controller_params)
|
210
|
-
|
211
|
-
# Now override with our specific things for fetching facet values
|
212
|
-
solr_params[:"facet.field"] = with_ex_local_param((facet_config.ex if facet_config.respond_to?(:ex)), facet_field)
|
213
|
-
|
214
|
-
limit =
|
215
|
-
if respond_to?(:facet_list_limit)
|
216
|
-
facet_list_limit.to_s.to_i
|
217
|
-
elsif solr_params["facet.limit"]
|
218
|
-
solr_params["facet.limit"].to_i
|
219
|
-
else
|
220
|
-
20
|
221
|
-
end
|
222
|
-
|
223
|
-
# Need to set as f.facet_field.facet.* to make sure we
|
224
|
-
# override any field-specific default in the solr request handler.
|
225
|
-
solr_params[:"f.#{facet_field}.facet.limit"] = limit + 1
|
226
|
-
solr_params[:"f.#{facet_field}.facet.offset"] = ( input.fetch(Blacklight::Solr::FacetPaginator.request_keys[:page] , 1).to_i - 1 ) * ( limit )
|
227
|
-
solr_params[:"f.#{facet_field}.facet.sort"] = input[ Blacklight::Solr::FacetPaginator.request_keys[:sort] ] if input[ Blacklight::Solr::FacetPaginator.request_keys[:sort] ]
|
228
|
-
solr_params[:rows] = 0
|
229
|
-
|
230
|
-
return solr_params
|
144
|
+
|
145
|
+
# given a field name and array of values, get the matching SOLR documents
|
146
|
+
# @return [Blacklight::SolrResponse, Array<Blacklight::SolrDocument>] the solr response object and a list of solr documents
|
147
|
+
def get_solr_response_for_field_values(field, values, extra_controller_params = {})
|
148
|
+
solr_response = query_solr(params, extra_controller_params.merge(solr_documents_by_field_values_params(field, values)))
|
149
|
+
|
150
|
+
[solr_response, solr_response.documents]
|
231
151
|
end
|
232
|
-
|
152
|
+
deprecation_deprecate :get_solr_response_for_field_values
|
153
|
+
|
233
154
|
##
|
234
155
|
# Get the solr response when retrieving only a single facet field
|
235
156
|
# @return [Blacklight::SolrResponse] the solr response
|
236
157
|
def get_facet_field_response(facet_field, user_params = params || {}, extra_controller_params = {})
|
237
158
|
solr_params = solr_facet_params(facet_field, user_params, extra_controller_params)
|
238
|
-
|
239
|
-
find(solr_params)
|
159
|
+
query_solr(user_params, extra_controller_params.merge(solr_facet_params(facet_field, user_params, extra_controller_params)))
|
240
160
|
end
|
241
161
|
|
242
162
|
# a solr query method
|
@@ -251,28 +171,28 @@ module Blacklight::SolrHelper
|
|
251
171
|
# Actually create the paginator!
|
252
172
|
# NOTE: The sniffing of the proper sort from the solr response is not
|
253
173
|
# currently tested for, tricky to figure out how to test, since the
|
254
|
-
# default setup we test against doesn't use this feature.
|
255
|
-
return Blacklight::Solr::FacetPaginator.new(response.facets.first.items,
|
256
|
-
:offset => response.params[:"f.#{facet_field}.facet.offset"],
|
174
|
+
# default setup we test against doesn't use this feature.
|
175
|
+
return Blacklight::Solr::FacetPaginator.new(response.facets.first.items,
|
176
|
+
:offset => response.params[:"f.#{facet_field}.facet.offset"],
|
257
177
|
:limit => limit,
|
258
178
|
:sort => response.params[:"f.#{facet_field}.facet.sort"] || response.params["facet.sort"]
|
259
179
|
)
|
260
180
|
end
|
261
181
|
deprecation_deprecate :get_facet_pagination
|
262
|
-
|
182
|
+
|
263
183
|
# a solr query method
|
264
|
-
# this is used when selecting a search result: we have a query and a
|
184
|
+
# this is used when selecting a search result: we have a query and a
|
265
185
|
# position in the search results and possibly some facets
|
266
186
|
# Pass in an index where 1 is the first document in the list, and
|
267
|
-
# the Blacklight app-level request params that define the search.
|
187
|
+
# the Blacklight app-level request params that define the search.
|
268
188
|
# @return [Blacklight::SolrDocument, nil] the found document or nil if not found
|
269
189
|
def get_single_doc_via_search(index, request_params)
|
270
190
|
solr_params = solr_search_params(request_params)
|
271
191
|
|
272
|
-
solr_params[:start] = (index - 1) # start at 0 to get 1st doc, 1 to get 2nd.
|
192
|
+
solr_params[:start] = (index - 1) # start at 0 to get 1st doc, 1 to get 2nd.
|
273
193
|
solr_params[:rows] = 1
|
274
194
|
solr_params[:fl] = '*'
|
275
|
-
solr_response =
|
195
|
+
solr_response = solr_repository.search(solr_params)
|
276
196
|
solr_response.documents.first
|
277
197
|
end
|
278
198
|
deprecation_deprecate :get_single_doc_via_search
|
@@ -281,19 +201,7 @@ module Blacklight::SolrHelper
|
|
281
201
|
# @return [Blacklight::SolrResponse, Array<Blacklight::SolrDocument>] the solr response and a list of the first and last document
|
282
202
|
def get_previous_and_next_documents_for_search(index, request_params, extra_controller_params={})
|
283
203
|
|
284
|
-
|
285
|
-
|
286
|
-
if index > 0
|
287
|
-
solr_params[:start] = index - 1 # get one before
|
288
|
-
solr_params[:rows] = 3 # and one after
|
289
|
-
else
|
290
|
-
solr_params[:start] = 0 # there is no previous doc
|
291
|
-
solr_params[:rows] = 2 # but there should be one after
|
292
|
-
end
|
293
|
-
|
294
|
-
solr_params[:fl] = '*'
|
295
|
-
solr_params[:facet] = false
|
296
|
-
solr_response = find(solr_params)
|
204
|
+
solr_response = query_solr(request_params, extra_controller_params.merge(previous_and_next_document_params(index)))
|
297
205
|
|
298
206
|
document_list = solr_response.documents
|
299
207
|
|
@@ -303,16 +211,6 @@ module Blacklight::SolrHelper
|
|
303
211
|
|
304
212
|
[solr_response, [prev_doc, next_doc]]
|
305
213
|
end
|
306
|
-
|
307
|
-
# returns a solr params hash
|
308
|
-
# the :fl (solr param) is set to the "field" value.
|
309
|
-
# per_page is set to 10
|
310
|
-
def solr_opensearch_params(field=nil)
|
311
|
-
solr_params = solr_search_params
|
312
|
-
solr_params[:per_page] = 10
|
313
|
-
solr_params[:fl] = field || blacklight_config.view_config('opensearch').title_field
|
314
|
-
solr_params
|
315
|
-
end
|
316
214
|
|
317
215
|
# a solr query method
|
318
216
|
# does a standard search but returns a simplified object.
|
@@ -320,38 +218,12 @@ module Blacklight::SolrHelper
|
|
320
218
|
# the second item is an other array. This second array contains
|
321
219
|
# all of the field values for each of the documents...
|
322
220
|
# where the field is the "field" argument passed in.
|
323
|
-
def get_opensearch_response(field=nil, extra_controller_params={})
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
DEFAULT_FACET_LIMIT = 10
|
331
|
-
|
332
|
-
# Look up facet limit for given facet_field. Will look at config, and
|
333
|
-
# if config is 'true' will look up from Solr @response if available. If
|
334
|
-
# no limit is avaialble, returns nil. Used from #solr_search_params
|
335
|
-
# to supply f.fieldname.facet.limit values in solr request (no @response
|
336
|
-
# available), and used in display (with @response available) to create
|
337
|
-
# a facet paginator with the right limit.
|
338
|
-
def facet_limit_for(facet_field)
|
339
|
-
facet = blacklight_config.facet_fields[facet_field]
|
340
|
-
return if facet.blank?
|
341
|
-
|
342
|
-
if facet.limit and @response and @response.facet_by_field_name(facet_field)
|
343
|
-
limit = @response.facet_by_field_name(facet_field).limit
|
344
|
-
|
345
|
-
if limit.nil? # we didn't get or a set a limit, so infer one.
|
346
|
-
facet.limit if facet.limit != true
|
347
|
-
elsif limit == -1 # limit -1 is solr-speak for unlimited
|
348
|
-
nil
|
349
|
-
else
|
350
|
-
limit.to_i - 1 # we added 1 to find out if we needed to paginate
|
351
|
-
end
|
352
|
-
elsif facet.limit
|
353
|
-
facet.limit == true ? DEFAULT_FACET_LIMIT : facet.limit
|
354
|
-
end
|
221
|
+
def get_opensearch_response(field=nil, request_params = params || {}, extra_controller_params={})
|
222
|
+
field ||= blacklight_config.view_config('opensearch').title_field
|
223
|
+
|
224
|
+
response = query_solr(request_params, solr_opensearch_params(field).merge(extra_controller_params))
|
225
|
+
|
226
|
+
[response.params[:q], response.documents.flat_map {|doc| doc[field] }.uniq]
|
355
227
|
end
|
356
228
|
|
357
229
|
##
|
@@ -360,18 +232,28 @@ module Blacklight::SolrHelper
|
|
360
232
|
blacklight_config.index.group
|
361
233
|
end
|
362
234
|
|
363
|
-
def
|
364
|
-
@
|
365
|
-
end
|
366
|
-
|
367
|
-
def blacklight_solr_config
|
368
|
-
Blacklight.solr_config
|
235
|
+
def solr_repository
|
236
|
+
@solr_repository ||= Blacklight::SolrRepository.new(blacklight_config)
|
369
237
|
end
|
370
238
|
|
371
239
|
private
|
372
240
|
|
373
|
-
|
374
|
-
|
241
|
+
##
|
242
|
+
# @deprecated
|
243
|
+
def default_solr_doc_params(id=nil)
|
244
|
+
id ||= params[:id]
|
245
|
+
|
246
|
+
# add our document id to the document_unique_id_param query parameter
|
247
|
+
p = blacklight_config.default_document_solr_params.merge({
|
248
|
+
# this assumes the request handler will map the unique id param
|
249
|
+
# to the unique key field using either solr local params, the
|
250
|
+
# real-time get handler, etc.
|
251
|
+
blacklight_config.document_unique_id_param => id
|
252
|
+
})
|
253
|
+
|
254
|
+
p[:qt] ||= blacklight_config.document_solr_request_handler
|
255
|
+
|
256
|
+
p
|
375
257
|
end
|
376
258
|
|
377
259
|
end
|