blacklight 3.0pre1
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.
- data/.gitignore +17 -0
- data/.gitmodules +6 -0
- data/.yardopts +4 -0
- data/Gemfile +4 -0
- data/LICENSE +14 -0
- data/README.rdoc +168 -0
- data/Rakefile +9 -0
- data/app/controllers/bookmarks_controller.rb +98 -0
- data/app/controllers/feedback_controller.rb +37 -0
- data/app/controllers/folder_controller.rb +49 -0
- data/app/controllers/saved_searches_controller.rb +45 -0
- data/app/controllers/search_history_controller.rb +25 -0
- data/app/helpers/blacklight_helper.rb +606 -0
- data/app/helpers/bookmarks_helper.rb +3 -0
- data/app/helpers/catalog_helper.rb +65 -0
- data/app/helpers/feedback_helper.rb +2 -0
- data/app/helpers/hash_as_hidden_fields.rb +57 -0
- data/app/helpers/render_constraints_helper.rb +120 -0
- data/app/helpers/saved_searches_helper.rb +2 -0
- data/app/helpers/search_history_helper.rb +2 -0
- data/app/models/bookmark.rb +6 -0
- data/app/models/record_mailer.rb +43 -0
- data/app/models/search.rb +19 -0
- data/app/views/_flash_msg.html.erb +6 -0
- data/app/views/_user_util_links.html.erb +13 -0
- data/app/views/bookmarks/index.html.erb +33 -0
- data/app/views/catalog/_bookmark_control.html.erb +25 -0
- data/app/views/catalog/_bookmark_form.html.erb +8 -0
- data/app/views/catalog/_citation.html.erb +15 -0
- data/app/views/catalog/_constraints.html.erb +7 -0
- data/app/views/catalog/_constraints_element.html.erb +33 -0
- data/app/views/catalog/_did_you_mean.html.erb +10 -0
- data/app/views/catalog/_document_list.html.erb +30 -0
- data/app/views/catalog/_email_form.html.erb +11 -0
- data/app/views/catalog/_facet_limit.html.erb +33 -0
- data/app/views/catalog/_facet_pagination.html.erb +28 -0
- data/app/views/catalog/_facets.html.erb +9 -0
- data/app/views/catalog/_folder_control.html.erb +12 -0
- data/app/views/catalog/_home.html.erb +6 -0
- data/app/views/catalog/_home_text.html.erb +6 -0
- data/app/views/catalog/_index_partials/_default.erb +11 -0
- data/app/views/catalog/_marc_view.html.erb +33 -0
- data/app/views/catalog/_opensearch_response_metadata.html.erb +3 -0
- data/app/views/catalog/_previous_next_doc.html.erb +6 -0
- data/app/views/catalog/_refworks_form.html.erb +7 -0
- data/app/views/catalog/_results_pagination.html.erb +11 -0
- data/app/views/catalog/_search_form.html.erb +14 -0
- data/app/views/catalog/_show_partials/_default.html.erb +9 -0
- data/app/views/catalog/_show_sidebar.html.erb +1 -0
- data/app/views/catalog/_show_tools.html.erb +46 -0
- data/app/views/catalog/_sms_form.html.erb +23 -0
- data/app/views/catalog/_solr_request.html.erb +5 -0
- data/app/views/catalog/_sort_and_per_page.html.erb +20 -0
- data/app/views/catalog/_unapi_microformat.html.erb +1 -0
- data/app/views/catalog/citation.html.erb +1 -0
- data/app/views/catalog/email.erb +1 -0
- data/app/views/catalog/endnote.endnote.erb +1 -0
- data/app/views/catalog/facet.html.erb +28 -0
- data/app/views/catalog/index.atom.builder +108 -0
- data/app/views/catalog/index.html.erb +37 -0
- data/app/views/catalog/index.rss.builder +19 -0
- data/app/views/catalog/librarian_view.html.erb +3 -0
- data/app/views/catalog/opensearch.json.erb +0 -0
- data/app/views/catalog/opensearch.xml.erb +11 -0
- data/app/views/catalog/send_email_record.erb +0 -0
- data/app/views/catalog/show.endnote.erb +1 -0
- data/app/views/catalog/show.html.erb +42 -0
- data/app/views/catalog/show.refworks.erb +1 -0
- data/app/views/catalog/sms.erb +1 -0
- data/app/views/catalog/unapi.xml.builder +6 -0
- data/app/views/feedback/complete.html.erb +3 -0
- data/app/views/feedback/show.html.erb +20 -0
- data/app/views/folder/_tools.html.erb +23 -0
- data/app/views/folder/index.html.erb +44 -0
- data/app/views/layouts/blacklight.html.erb +49 -0
- data/app/views/record_mailer/email_record.erb +6 -0
- data/app/views/record_mailer/sms_record.erb +4 -0
- data/app/views/saved_searches/index.html.erb +27 -0
- data/app/views/search_history/index.html.erb +23 -0
- data/blacklight.gemspec +50 -0
- data/config.ru +4 -0
- data/config/routes.rb +54 -0
- data/db/seeds.rb +7 -0
- data/features/generators.feature +77 -0
- data/features/support/aruba.rb +9 -0
- data/install.rb +0 -0
- data/install/solr.yml +8 -0
- data/lib/blacklight.rb +121 -0
- data/lib/blacklight/catalog.rb +311 -0
- data/lib/blacklight/comma_link_renderer.rb +27 -0
- data/lib/blacklight/configurable.rb +46 -0
- data/lib/blacklight/controller.rb +121 -0
- data/lib/blacklight/engine.rb +32 -0
- data/lib/blacklight/exceptions.rb +13 -0
- data/lib/blacklight/marc.rb +46 -0
- data/lib/blacklight/marc/citation.rb +251 -0
- data/lib/blacklight/search_fields.rb +107 -0
- data/lib/blacklight/solr.rb +7 -0
- data/lib/blacklight/solr/document.rb +239 -0
- data/lib/blacklight/solr/document/dublin_core.rb +40 -0
- data/lib/blacklight/solr/document/email.rb +15 -0
- data/lib/blacklight/solr/document/marc.rb +84 -0
- data/lib/blacklight/solr/document/marc_export.rb +430 -0
- data/lib/blacklight/solr/document/sms.rb +13 -0
- data/lib/blacklight/solr/facet_paginator.rb +93 -0
- data/lib/blacklight/solr_helper.rb +413 -0
- data/lib/blacklight/user.rb +55 -0
- data/lib/blacklight/version.rb +3 -0
- data/lib/colorize.rb +196 -0
- data/lib/generators/blacklight/blacklight_generator.rb +134 -0
- data/lib/generators/blacklight/templates/SolrMarc.jar +0 -0
- data/lib/generators/blacklight/templates/catalog_controller.rb +8 -0
- data/lib/generators/blacklight/templates/config/SolrMarc/config-test.properties +37 -0
- data/lib/generators/blacklight/templates/config/SolrMarc/config.properties +37 -0
- data/lib/generators/blacklight/templates/config/SolrMarc/index.properties +97 -0
- data/lib/generators/blacklight/templates/config/SolrMarc/index_scripts/dewey.bsh +47 -0
- data/lib/generators/blacklight/templates/config/SolrMarc/index_scripts/format.bsh +126 -0
- data/lib/generators/blacklight/templates/config/SolrMarc/translation_maps/README_MAPS +1 -0
- data/lib/generators/blacklight/templates/config/SolrMarc/translation_maps/callnumber_map.properties +407 -0
- data/lib/generators/blacklight/templates/config/SolrMarc/translation_maps/composition_era_map.properties +56 -0
- data/lib/generators/blacklight/templates/config/SolrMarc/translation_maps/country_map.properties +379 -0
- data/lib/generators/blacklight/templates/config/SolrMarc/translation_maps/format_map.properties +50 -0
- data/lib/generators/blacklight/templates/config/SolrMarc/translation_maps/instrument_map.properties +101 -0
- data/lib/generators/blacklight/templates/config/SolrMarc/translation_maps/language_map.properties +490 -0
- data/lib/generators/blacklight/templates/config/blacklight_config.rb +245 -0
- data/lib/generators/blacklight/templates/config/solr.yml +6 -0
- data/lib/generators/blacklight/templates/migrations/add_user_types_to_bookmarks_searches.rb +11 -0
- data/lib/generators/blacklight/templates/migrations/create_bookmarks.rb +17 -0
- data/lib/generators/blacklight/templates/migrations/create_searches.rb +15 -0
- data/lib/generators/blacklight/templates/migrations/remove_editable_fields_from_bookmarks.rb +11 -0
- data/lib/generators/blacklight/templates/public/images/blacklight/bg.png +0 -0
- data/lib/generators/blacklight/templates/public/images/blacklight/border.png +0 -0
- data/lib/generators/blacklight/templates/public/images/blacklight/bul_sq_gry.gif +0 -0
- data/lib/generators/blacklight/templates/public/images/blacklight/checkmark.gif +0 -0
- data/lib/generators/blacklight/templates/public/images/blacklight/logo.png +0 -0
- data/lib/generators/blacklight/templates/public/images/blacklight/magnifying_glass.gif +0 -0
- data/lib/generators/blacklight/templates/public/images/blacklight/remove.gif +0 -0
- data/lib/generators/blacklight/templates/public/images/blacklight/separator.gif +0 -0
- data/lib/generators/blacklight/templates/public/images/blacklight/start_over.gif +0 -0
- data/lib/generators/blacklight/templates/public/javascripts/blacklight.js +485 -0
- data/lib/generators/blacklight/templates/public/javascripts/jquery-1.4.2.min.js +154 -0
- data/lib/generators/blacklight/templates/public/javascripts/jquery-ui-1.8.1.custom.min.js +756 -0
- data/lib/generators/blacklight/templates/public/stylesheets/blacklight.css +487 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-bg_gloss-wave_35_558fd0_500x100.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-icons_2e4f81_256x240.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
- data/lib/generators/blacklight/templates/public/stylesheets/jquery/ui-lightness/jquery-ui-1.8.1.custom.css +486 -0
- data/lib/generators/blacklight/templates/public/stylesheets/yui.css +31 -0
- data/lib/generators/blacklight/templates/solr_document.rb +30 -0
- data/lib/railties/blacklight.rake +66 -0
- data/lib/railties/cucumber.rake +53 -0
- data/lib/railties/rspec.rake +188 -0
- data/lib/railties/solr_marc.rake +148 -0
- data/lib/railties/test_solr_server.rb +130 -0
- data/spec/helpers/catalog_helper_spec.rb +111 -0
- data/spec/views/catalog/_sms_form.html.erb_spec.rb +19 -0
- data/tasks/blacklight_tasks.rake +4 -0
- data/uninstall.rb +1 -0
- metadata +431 -0
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
# SolrHelper is a controller layer mixin. It is in the controller scope: request params, session etc.
|
|
2
|
+
#
|
|
3
|
+
# NOTE: Be careful when creating variables here as they may be overriding something that already exists.
|
|
4
|
+
# The ActionController docs: http://api.rubyonrails.org/classes/ActionController/Base.html
|
|
5
|
+
#
|
|
6
|
+
# Override these methods in your own controller for customizations:
|
|
7
|
+
#
|
|
8
|
+
# class CatalogController < ActionController::Base
|
|
9
|
+
#
|
|
10
|
+
# include Blacklight::SolrHelper
|
|
11
|
+
#
|
|
12
|
+
# def solr_search_params
|
|
13
|
+
# super.merge :per_page=>10
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
module Blacklight::SolrHelper
|
|
20
|
+
MaxPerPage = 100
|
|
21
|
+
|
|
22
|
+
def self.included(klass)
|
|
23
|
+
if klass.respond_to?(:helper_method)
|
|
24
|
+
klass.helper_method(:facet_limit_hash)
|
|
25
|
+
klass.helper_method(:facet_limit_for)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# We want to install a class-level place to keep
|
|
29
|
+
# solr_search_params_logic method names. Compare to before_filter,
|
|
30
|
+
# similar design. Since we're a module, we have to add it in here.
|
|
31
|
+
# There are too many different semantic choices in ruby 'class variables',
|
|
32
|
+
# we choose this one for now, supplied by Rails.
|
|
33
|
+
klass.class_inheritable_accessor :solr_search_params_logic
|
|
34
|
+
# Set defaults. Each symbol identifies a _method_ that must be in
|
|
35
|
+
# this class, taking two parameters (solr_parameters, user_parameters)
|
|
36
|
+
# Can be changed in local apps or by plugins, eg:
|
|
37
|
+
# CatalogController.include ModuleDefiningNewMethod
|
|
38
|
+
# CatalogController.solr_search_params_logic << :new_method
|
|
39
|
+
# CatalogController.solr_search_params_logic.delete(:we_dont_want)
|
|
40
|
+
klass.solr_search_params_logic = [:default_solr_parameters , :add_query_to_solr, :add_facet_fq_to_solr, :add_facetting_to_solr, :add_sorting_paging_to_solr ]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# A helper method used for generating solr LocalParams, put quotes
|
|
45
|
+
# around the term unless it's a bare-word. Escape internal quotes
|
|
46
|
+
# if needed.
|
|
47
|
+
def solr_param_quote(val, options = {})
|
|
48
|
+
options[:quote] ||= '"'
|
|
49
|
+
unless val =~ /^[a-zA-Z$_\-\^]+$/
|
|
50
|
+
val = options[:quote] +
|
|
51
|
+
# Yes, we need crazy escaping here, to deal with regexp esc too!
|
|
52
|
+
val.gsub("'", "\\\\\'").gsub('"', "\\\\\"") +
|
|
53
|
+
options[:quote]
|
|
54
|
+
end
|
|
55
|
+
return val
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# returns a params hash for searching solr.
|
|
60
|
+
# The CatalogController #index action uses this.
|
|
61
|
+
# Solr parameters can come from a number of places. From lowest
|
|
62
|
+
# precedence to highest:
|
|
63
|
+
# 1. General defaults in blacklight config (are trumped by)
|
|
64
|
+
# 2. defaults for the particular search field identified by params[:search_field] (are trumped by)
|
|
65
|
+
# 3. certain parameters directly on input HTTP query params
|
|
66
|
+
# * not just any parameter is grabbed willy nilly, only certain ones are allowed by HTTP input)
|
|
67
|
+
# * for legacy reasons, qt in http query does not over-ride qt in search field definition default.
|
|
68
|
+
# 4. extra parameters passed in as argument.
|
|
69
|
+
#
|
|
70
|
+
# spellcheck.q will be supplied with the [:q] value unless specifically
|
|
71
|
+
# specified otherwise.
|
|
72
|
+
#
|
|
73
|
+
# Incoming parameter :f is mapped to :fq solr parameter.
|
|
74
|
+
def solr_search_params(user_params = params || {})
|
|
75
|
+
solr_parameters = {}
|
|
76
|
+
solr_search_params_logic.each do |method_name|
|
|
77
|
+
send(method_name, solr_parameters, user_params)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
return solr_parameters
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
####
|
|
85
|
+
# Start with general defaults from BL config. Need to use custom
|
|
86
|
+
# merge to dup values, to avoid later mutating the original by mistake.
|
|
87
|
+
def default_solr_parameters(solr_parameters, user_params)
|
|
88
|
+
if Blacklight.config[:default_solr_params]
|
|
89
|
+
Blacklight.config[:default_solr_params].each_pair do |key, value|
|
|
90
|
+
solr_parameters[key] = value.dup rescue value
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
###
|
|
96
|
+
# copy paging and sorting params from BL app over to solr, with
|
|
97
|
+
# fairly little transformation.
|
|
98
|
+
def add_sorting_paging_to_solr(solr_parameters, user_params)
|
|
99
|
+
# Omit empty strings and nil values.
|
|
100
|
+
# Apparently RSolr takes :per_page and converts it to Solr :rows,
|
|
101
|
+
# so we let it.
|
|
102
|
+
[:page, :sort, :per_page].each do |key|
|
|
103
|
+
solr_parameters[key] = user_params[key] unless user_params[key].blank?
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# limit to MaxPerPage (100). Tests want this to be a string not an integer,
|
|
107
|
+
# not sure why.
|
|
108
|
+
solr_parameters[:per_page] = solr_parameters[:per_page].to_i > self.max_per_page ? self.max_per_page.to_s : solr_parameters[:per_page]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
##
|
|
112
|
+
# Take the user-entered query, and put it in the solr params,
|
|
113
|
+
# including config's "search field" params for current search field.
|
|
114
|
+
# also include setting spellcheck.q.
|
|
115
|
+
def add_query_to_solr(solr_parameters, user_parameters)
|
|
116
|
+
###
|
|
117
|
+
# Merge in search field configured values, if present, over-writing general
|
|
118
|
+
# defaults
|
|
119
|
+
###
|
|
120
|
+
# legacy behavior of user param :qt is passed through, but over-ridden
|
|
121
|
+
# by actual search field config if present. We might want to remove
|
|
122
|
+
# this legacy behavior at some point. It does not seem to be currently
|
|
123
|
+
# rspec'd.
|
|
124
|
+
solr_parameters[:qt] = user_parameters[:qt] if user_parameters[:qt]
|
|
125
|
+
|
|
126
|
+
search_field_def = Blacklight.search_field_def_for_key(user_parameters[:search_field])
|
|
127
|
+
if (search_field_def)
|
|
128
|
+
solr_parameters[:qt] = search_field_def[:qt] if search_field_def[:qt]
|
|
129
|
+
solr_parameters.merge!( search_field_def[:solr_parameters]) if search_field_def[:solr_parameters]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
##
|
|
133
|
+
# Create Solr 'q' including the user-entered q, prefixed by any
|
|
134
|
+
# solr LocalParams in config, using solr LocalParams syntax.
|
|
135
|
+
# http://wiki.apache.org/solr/LocalParams
|
|
136
|
+
##
|
|
137
|
+
if (search_field_def && hash = search_field_def[:solr_local_parameters])
|
|
138
|
+
local_params = hash.collect do |key, val|
|
|
139
|
+
key.to_s + "=" + solr_param_quote(val, :quote => "'")
|
|
140
|
+
end.join(" ")
|
|
141
|
+
solr_parameters[:q] = "{!#{local_params}}#{user_parameters[:q]}"
|
|
142
|
+
else
|
|
143
|
+
solr_parameters[:q] = user_parameters[:q] if user_parameters[:q]
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
##
|
|
148
|
+
# Set Solr spellcheck.q to be original user-entered query, without
|
|
149
|
+
# our local params, otherwise it'll try and spellcheck the local
|
|
150
|
+
# params! Unless spellcheck.q has already been set by someone,
|
|
151
|
+
# respect that.
|
|
152
|
+
#
|
|
153
|
+
# TODO: Change calling code to expect this as a symbol instead of
|
|
154
|
+
# a string, for consistency? :'spellcheck.q' is a symbol. Right now
|
|
155
|
+
# rspec tests for a string, and can't tell if other code may
|
|
156
|
+
# insist on a string.
|
|
157
|
+
solr_parameters["spellcheck.q"] = user_parameters[:q] unless solr_parameters["spellcheck.q"]
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
##
|
|
161
|
+
# Add any existing facet limits, stored in app-level HTTP query
|
|
162
|
+
# as :f, to solr as appropriate :fq query.
|
|
163
|
+
def add_facet_fq_to_solr(solr_parameters, user_params)
|
|
164
|
+
# :fq, map from :f.
|
|
165
|
+
if ( user_params[:f])
|
|
166
|
+
f_request_params = user_params[:f]
|
|
167
|
+
|
|
168
|
+
solr_parameters[:fq] ||= []
|
|
169
|
+
f_request_params.each_pair do |facet_field, value_list|
|
|
170
|
+
value_list.each do |value|
|
|
171
|
+
solr_parameters[:fq] << "{!raw f=#{facet_field}}#{value}"
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
##
|
|
178
|
+
# Add appropriate Solr facetting directives in, including
|
|
179
|
+
# taking account of our facet paging/'more'. This is not
|
|
180
|
+
# about solr 'fq', this is about solr facet.* params.
|
|
181
|
+
def add_facetting_to_solr(solr_parameters, user_params)
|
|
182
|
+
# While not used by BL core behavior, legacy behavior seemed to be
|
|
183
|
+
# to accept incoming params as "facet.field" or "facets", and add them
|
|
184
|
+
# on to any existing facet.field sent to Solr. Legacy behavior seemed
|
|
185
|
+
# to be accepting these incoming params as arrays (in Rails URL with []
|
|
186
|
+
# on end), or single values. At least one of these is used by
|
|
187
|
+
# Stanford for "faux hieararchial facets".
|
|
188
|
+
if user_params.has_key?("facet.field") || user_params.has_key?("facets")
|
|
189
|
+
solr_parameters[:"facet.field"] ||= []
|
|
190
|
+
solr_parameters[:"facet.field"].concat( [user_params["facet.field"], user_params["facets"]].flatten.compact ).uniq!
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Support facet paging and 'more'
|
|
194
|
+
# links, by sending a facet.limit one more than what we
|
|
195
|
+
# want to page at, according to configured facet limits.
|
|
196
|
+
facet_limit_hash.each_key do |field_name|
|
|
197
|
+
next if field_name.nil? # skip the 'default' key
|
|
198
|
+
next unless (limit = facet_limit_for(field_name))
|
|
199
|
+
|
|
200
|
+
solr_parameters[:"f.#{field_name}.facet.limit"] = (limit + 1)
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
# a solr query method
|
|
207
|
+
# given a user query, return a solr response containing both result docs and facets
|
|
208
|
+
# - mixes in the Blacklight::Solr::SpellingSuggestions module
|
|
209
|
+
# - the response will have a spelling_suggestions method
|
|
210
|
+
# Returns a two-element array (aka duple) with first the solr response object,
|
|
211
|
+
# and second an array of SolrDocuments representing the response.docs
|
|
212
|
+
def get_search_results(user_params = params || {}, extra_controller_params = {})
|
|
213
|
+
|
|
214
|
+
# In later versions of Rails, the #benchmark method can do timing
|
|
215
|
+
# better for us.
|
|
216
|
+
bench_start = Time.now
|
|
217
|
+
|
|
218
|
+
solr_response = Blacklight.solr.find( self.solr_search_params(user_params).merge(extra_controller_params))
|
|
219
|
+
|
|
220
|
+
document_list = solr_response.docs.collect {|doc| SolrDocument.new(doc, solr_response)}
|
|
221
|
+
|
|
222
|
+
Rails.logger.debug("Solr fetch: #{self.class}#get_search_results (#{'%.1f' % ((Time.now.to_f - bench_start.to_f)*1000)}ms)")
|
|
223
|
+
|
|
224
|
+
return [solr_response, document_list]
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# returns a params hash for finding a single solr document (CatalogController #show action)
|
|
228
|
+
# If the id arg is nil, then the value is fetched from params[:id]
|
|
229
|
+
# This method is primary called by the get_solr_response_for_doc_id method.
|
|
230
|
+
def solr_doc_params(id=nil)
|
|
231
|
+
id ||= params[:id]
|
|
232
|
+
# just to be consistent with the other solr param methods:
|
|
233
|
+
{
|
|
234
|
+
:qt => :document,
|
|
235
|
+
:id => id
|
|
236
|
+
}
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# a solr query method
|
|
240
|
+
# retrieve a solr document, given the doc id
|
|
241
|
+
# TODO: shouldn't hardcode id field; should be setable to unique_key field in schema.xml
|
|
242
|
+
def get_solr_response_for_doc_id(id=nil, extra_controller_params={})
|
|
243
|
+
solr_response = Blacklight.solr.find solr_doc_params(id).merge(extra_controller_params)
|
|
244
|
+
raise Blacklight::Exceptions::InvalidSolrID.new if solr_response.docs.empty?
|
|
245
|
+
document = SolrDocument.new(solr_response.docs.first, solr_response)
|
|
246
|
+
[solr_response, document]
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# given a field name and array of values, get the matching SOLR documents
|
|
250
|
+
def get_solr_response_for_field_values(field, values, extra_solr_params = {})
|
|
251
|
+
value_str = "(\"" + values.to_a.join("\" OR \"") + "\")"
|
|
252
|
+
solr_params = {
|
|
253
|
+
:defType => "lucene", # need boolean for OR
|
|
254
|
+
:q => "#{field}:#{value_str}",
|
|
255
|
+
# not sure why fl * is neccesary, why isn't default solr_search_params
|
|
256
|
+
# sufficient, like it is for any other search results solr request?
|
|
257
|
+
# But tests fail without this. I think because some functionality requires
|
|
258
|
+
# this to actually get solr_doc_params, not solr_search_params. Confused
|
|
259
|
+
# semantics again.
|
|
260
|
+
:fl => "*",
|
|
261
|
+
:facet => 'false',
|
|
262
|
+
:spellcheck => 'false'
|
|
263
|
+
}.merge(extra_solr_params)
|
|
264
|
+
|
|
265
|
+
solr_response = Blacklight.solr.find( self.solr_search_params().merge(solr_params) )
|
|
266
|
+
document_list = solr_response.docs.collect{|doc| SolrDocument.new(doc, solr_response) }
|
|
267
|
+
[solr_response,document_list]
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# returns a params hash for a single facet field solr query.
|
|
271
|
+
# used primary by the get_facet_pagination method.
|
|
272
|
+
# Looks up Facet Paginator request params from current request
|
|
273
|
+
# params to figure out sort and offset.
|
|
274
|
+
# Default limit for facet list can be specified by defining a controller
|
|
275
|
+
# method facet_list_limit, otherwise 20.
|
|
276
|
+
def solr_facet_params(facet_field, user_params=params || {}, extra_controller_params={})
|
|
277
|
+
input = user_params.deep_merge(extra_controller_params)
|
|
278
|
+
|
|
279
|
+
# First start with a standard solr search params calculations,
|
|
280
|
+
# for any search context in our request params.
|
|
281
|
+
solr_params = solr_search_params(user_params).merge(extra_controller_params)
|
|
282
|
+
|
|
283
|
+
# Now override with our specific things for fetching facet values
|
|
284
|
+
solr_params[:"facet.field"] = facet_field
|
|
285
|
+
|
|
286
|
+
# Need to set as f.facet_field.facet.limit to make sure we
|
|
287
|
+
# override any field-specific default in the solr request handler.
|
|
288
|
+
solr_params[:"f.#{facet_field}.facet.limit"] =
|
|
289
|
+
if solr_params["facet.limit"]
|
|
290
|
+
solr_params["facet.limit"] + 1
|
|
291
|
+
elsif respond_to?(:facet_list_limit)
|
|
292
|
+
facet_list_limit.to_s.to_i + 1
|
|
293
|
+
else
|
|
294
|
+
20 + 1
|
|
295
|
+
end
|
|
296
|
+
solr_params['facet.offset'] = input[ Blacklight::Solr::FacetPaginator.request_keys[:offset] ].to_i # will default to 0 if nil
|
|
297
|
+
solr_params['facet.sort'] = input[ Blacklight::Solr::FacetPaginator.request_keys[:sort] ]
|
|
298
|
+
solr_params[:rows] = 0
|
|
299
|
+
|
|
300
|
+
return solr_params
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# a solr query method
|
|
304
|
+
# used to paginate through a single facet field's values
|
|
305
|
+
# /catalog/facet/language_facet
|
|
306
|
+
def get_facet_pagination(facet_field, extra_controller_params={})
|
|
307
|
+
|
|
308
|
+
solr_params = solr_facet_params(facet_field, params, extra_controller_params)
|
|
309
|
+
|
|
310
|
+
# Make the solr call
|
|
311
|
+
response = Blacklight.solr.find(solr_params)
|
|
312
|
+
|
|
313
|
+
limit =
|
|
314
|
+
if respond_to?(:facet_list_limit)
|
|
315
|
+
facet_list_limit.to_s.to_i
|
|
316
|
+
elsif solr_params[:"f.#{facet_field}.facet.limit"]
|
|
317
|
+
solr_params[:"f.#{facet_field}.facet.limit"] - 1
|
|
318
|
+
else
|
|
319
|
+
nil
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
# Actually create the paginator!
|
|
324
|
+
# NOTE: The sniffing of the proper sort from the solr response is not
|
|
325
|
+
# currently tested for, tricky to figure out how to test, since the
|
|
326
|
+
# default setup we test against doesn't use this feature.
|
|
327
|
+
return Blacklight::Solr::FacetPaginator.new(response.facets.first.items,
|
|
328
|
+
:offset => solr_params['facet.offset'],
|
|
329
|
+
:limit => limit,
|
|
330
|
+
:sort => response["responseHeader"]["params"]["f.#{facet_field}.facet.sort"] || response["responseHeader"]["params"]["facet.sort"]
|
|
331
|
+
)
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
# a solr query method
|
|
335
|
+
# this is used when selecting a search result: we have a query and a
|
|
336
|
+
# position in the search results and possibly some facets
|
|
337
|
+
# Pass in an index where 1 is the first document in the list, and
|
|
338
|
+
# the Blacklight app-level request params that define the search.
|
|
339
|
+
def get_single_doc_via_search(index, request_params)
|
|
340
|
+
solr_params = solr_search_params(request_params)
|
|
341
|
+
solr_params[:start] = index - 1 # start at 0 to get 1st doc, 1 to get 2nd.
|
|
342
|
+
solr_params[:per_page] = 1
|
|
343
|
+
solr_params[:rows] = 1
|
|
344
|
+
solr_params[:fl] = '*'
|
|
345
|
+
Blacklight.solr.find(solr_params).docs.first
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
# returns a solr params hash
|
|
349
|
+
# if field is nil, the value is fetched from Blacklight.config[:index][:show_link]
|
|
350
|
+
# the :fl (solr param) is set to the "field" value.
|
|
351
|
+
# per_page is set to 10
|
|
352
|
+
def solr_opensearch_params(field=nil)
|
|
353
|
+
solr_params = solr_search_params
|
|
354
|
+
solr_params[:per_page] = 10
|
|
355
|
+
solr_params[:fl] = Blacklight.config[:index][:show_link]
|
|
356
|
+
solr_params
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
# a solr query method
|
|
360
|
+
# does a standard search but returns a simplified object.
|
|
361
|
+
# an array is returned, the first item is the query string,
|
|
362
|
+
# the second item is an other array. This second array contains
|
|
363
|
+
# all of the field values for each of the documents...
|
|
364
|
+
# where the field is the "field" argument passed in.
|
|
365
|
+
def get_opensearch_response(field=nil, extra_controller_params={})
|
|
366
|
+
solr_params = solr_opensearch_params().merge(extra_controller_params)
|
|
367
|
+
response = Blacklight.solr.find(solr_params)
|
|
368
|
+
a = [solr_params[:q]]
|
|
369
|
+
a << response.docs.map {|doc| doc[solr_params[:fl]].to_s }
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
# Look up facet limit for given facet_field. Will look at config, and
|
|
375
|
+
# if config is 'true' will look up from Solr @response if available. If
|
|
376
|
+
# no limit is avaialble, returns nil. Used from #solr_search_params
|
|
377
|
+
# to supply f.fieldname.facet.limit values in solr request (no @response
|
|
378
|
+
# available), and used in display (with @response available) to create
|
|
379
|
+
# a facet paginator with the right limit.
|
|
380
|
+
def facet_limit_for(facet_field)
|
|
381
|
+
limits_hash = facet_limit_hash
|
|
382
|
+
return nil if limits_hash.blank?
|
|
383
|
+
|
|
384
|
+
limit = limits_hash[facet_field]
|
|
385
|
+
|
|
386
|
+
if ( limit == true && @response &&
|
|
387
|
+
@response["responseHeader"] &&
|
|
388
|
+
@response["responseHeader"]["params"])
|
|
389
|
+
limit =
|
|
390
|
+
@response["responseHeader"]["params"]["f.#{facet_field}.facet.limit"] ||
|
|
391
|
+
@response["responseHeader"]["params"]["facet.limit"]
|
|
392
|
+
limit = (limit.to_i() -1) if limit
|
|
393
|
+
limit = nil if limit == -2 # -1-1==-2, unlimited.
|
|
394
|
+
elsif limit == true
|
|
395
|
+
limit = nil
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
return limit
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
# Returns complete hash of key=facet_field, value=limit.
|
|
402
|
+
# Used by SolrHelper#solr_search_params to add limits to solr
|
|
403
|
+
# request for all configured facet limits.
|
|
404
|
+
def facet_limit_hash
|
|
405
|
+
Blacklight.config[:facet][:limits] || {}
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def max_per_page
|
|
409
|
+
MaxPerPage
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Blacklight::User
|
|
2
|
+
|
|
3
|
+
# This gives us an is_blacklight_user method that can be included in
|
|
4
|
+
# the containing applications models.
|
|
5
|
+
# SEE ALSO: The /lib/blacklight/engine.rb class for how when this
|
|
6
|
+
# is injected into the hosting application through ActiveRecord::Base extend
|
|
7
|
+
def self.included(base)
|
|
8
|
+
base.send :has_many, :bookmarks, :dependent => :destroy, :as => :user
|
|
9
|
+
base.send :has_many, :searches, :dependent => :destroy, :as => :user
|
|
10
|
+
base.send :include, InstanceMethods
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# The following methods will be included in any active model object
|
|
14
|
+
# that calls "is_blacklight_user"
|
|
15
|
+
module InstanceMethods
|
|
16
|
+
|
|
17
|
+
# fixme: This needs to be re-implemented
|
|
18
|
+
def last_search_url
|
|
19
|
+
return self.searches.last
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def has_bookmarks?
|
|
23
|
+
bookmarks.count > 0
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def has_searches?
|
|
27
|
+
searches.count > 0
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def bookmarked_document_ids
|
|
31
|
+
self.bookmarks.map{|bm|bm.document_id}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# see #current_bookmark_for, is easier
|
|
35
|
+
def document_is_bookmarked?(document_id)
|
|
36
|
+
bookmarked_document_ids.include? document_id
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# returns a Bookmark object if there is one for document_id, else
|
|
40
|
+
# nil.
|
|
41
|
+
def existing_bookmark_for(document_id)
|
|
42
|
+
# to_a, we don't want to go to the database, we want to use cached
|
|
43
|
+
# copy.
|
|
44
|
+
self.bookmarks.to_a.find {|b| b.document_id == document_id}
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def documents_to_bookmark=(docs)
|
|
48
|
+
docs.each do |doc|
|
|
49
|
+
self.bookmarks.create(doc) unless bookmarked_document_ids.include?(doc[:document_id])
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end # /InstanceMethods
|
|
54
|
+
|
|
55
|
+
end
|