blacklight 5.7.2 → 5.8.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.
- 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
|