blacklight 5.9.4 → 5.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/VERSION +1 -1
  4. data/app/assets/stylesheets/blacklight/_facets.scss +11 -10
  5. data/app/helpers/blacklight/blacklight_helper_behavior.rb +14 -14
  6. data/app/helpers/blacklight/configuration_helper_behavior.rb +16 -10
  7. data/app/helpers/blacklight/facets_helper_behavior.rb +15 -14
  8. data/app/helpers/blacklight/url_helper_behavior.rb +1 -1
  9. data/app/models/bookmark.rb +1 -4
  10. data/app/models/search.rb +3 -6
  11. data/app/views/catalog/_facet_layout.html.erb +2 -2
  12. data/app/views/catalog/_facet_limit.html.erb +5 -3
  13. data/app/views/catalog/_facet_pivot.html.erb +4 -4
  14. data/app/views/catalog/_home_text.html.erb +8 -48
  15. data/app/views/catalog/_index_default.html.erb +3 -3
  16. data/app/views/catalog/_show_default.html.erb +3 -3
  17. data/app/views/catalog/_sms_form.html.erb +1 -1
  18. data/app/views/catalog/facet.html.erb +1 -1
  19. data/blacklight.gemspec +1 -1
  20. data/config/jetty.yml +0 -3
  21. data/config/locales/blacklight.de.yml +2 -0
  22. data/config/locales/blacklight.en.yml +2 -0
  23. data/config/locales/blacklight.es.yml +2 -0
  24. data/config/locales/blacklight.fr.yml +2 -0
  25. data/config/locales/blacklight.pt-BR.yml +2 -0
  26. data/lib/blacklight.rb +70 -26
  27. data/lib/blacklight/abstract_repository.rb +29 -0
  28. data/lib/blacklight/base.rb +7 -7
  29. data/lib/blacklight/bookmarks.rb +5 -5
  30. data/lib/blacklight/catalog.rb +34 -19
  31. data/lib/blacklight/catalog/search_context.rb +1 -1
  32. data/lib/blacklight/configuration.rb +112 -46
  33. data/lib/blacklight/configuration/facet_field.rb +9 -7
  34. data/lib/blacklight/configuration/field.rb +27 -0
  35. data/lib/blacklight/configuration/fields.rb +25 -20
  36. data/lib/blacklight/configuration/search_field.rb +6 -8
  37. data/lib/blacklight/configuration/solr_field.rb +3 -18
  38. data/lib/blacklight/configuration/sort_field.rb +6 -7
  39. data/lib/blacklight/document.rb +156 -0
  40. data/lib/blacklight/document/dublin_core.rb +41 -0
  41. data/lib/blacklight/document/email.rb +16 -0
  42. data/lib/blacklight/document/export.rb +107 -0
  43. data/lib/blacklight/document/extensions.rb +56 -0
  44. data/lib/blacklight/document/schema_org.rb +7 -0
  45. data/lib/blacklight/document/semantic_fields.rb +51 -0
  46. data/lib/blacklight/document/sms.rb +14 -0
  47. data/lib/blacklight/document_presenter.rb +3 -3
  48. data/lib/blacklight/exceptions.rb +9 -2
  49. data/lib/blacklight/facet.rb +21 -16
  50. data/lib/blacklight/request_builders.rb +60 -284
  51. data/lib/blacklight/routes.rb +1 -1
  52. data/lib/blacklight/search_builder.rb +130 -0
  53. data/lib/blacklight/search_helper.rb +316 -0
  54. data/lib/blacklight/solr.rb +1 -0
  55. data/lib/blacklight/solr/document.rb +4 -187
  56. data/lib/blacklight/solr/document/dublin_core.rb +3 -37
  57. data/lib/blacklight/solr/document/email.rb +4 -13
  58. data/lib/blacklight/solr/document/export.rb +3 -103
  59. data/lib/blacklight/solr/document/extensions.rb +4 -52
  60. data/lib/blacklight/solr/document/more_like_this.rb +1 -1
  61. data/lib/blacklight/solr/document/schema_org.rb +4 -4
  62. data/lib/blacklight/solr/document/sms.rb +4 -11
  63. data/lib/blacklight/solr/facet_paginator.rb +2 -2
  64. data/lib/blacklight/solr/search_builder.rb +264 -0
  65. data/lib/blacklight/solr_helper.rb +6 -261
  66. data/lib/blacklight/solr_repository.rb +30 -24
  67. data/lib/blacklight/solr_response.rb +3 -3
  68. data/lib/blacklight/user.rb +1 -2
  69. data/lib/blacklight/utils.rb +0 -23
  70. data/lib/generators/blacklight/controller_generator.rb +38 -0
  71. data/lib/generators/blacklight/document_generator.rb +20 -0
  72. data/lib/generators/blacklight/install_generator.rb +38 -39
  73. data/lib/generators/blacklight/models_generator.rb +2 -62
  74. data/lib/generators/blacklight/templates/catalog_controller.rb +3 -4
  75. data/lib/generators/blacklight/templates/config/{solr.yml → blacklight.yml} +3 -0
  76. data/lib/generators/blacklight/templates/config/jetty.yml +0 -3
  77. data/lib/generators/blacklight/templates/solr_document.rb +6 -6
  78. data/lib/generators/blacklight/test_support_generator.rb +1 -6
  79. data/lib/generators/blacklight/user_generator.rb +59 -0
  80. data/lib/railties/blacklight.rake +16 -7
  81. data/spec/controllers/catalog_controller_spec.rb +9 -15
  82. data/spec/features/facets_spec.rb +8 -0
  83. data/spec/helpers/configuration_helper_spec.rb +6 -13
  84. data/spec/helpers/facets_helper_spec.rb +3 -2
  85. data/spec/lib/blacklight/configuration_spec.rb +11 -38
  86. data/spec/lib/blacklight/{solr/document → document}/dublin_core_spec.rb +4 -4
  87. data/spec/lib/blacklight/{solr/document → document}/email_spec.rb +2 -2
  88. data/spec/lib/blacklight/{solr/document → document}/sms_spec.rb +2 -2
  89. data/spec/lib/blacklight/search_builder_spec.rb +145 -0
  90. data/spec/lib/blacklight/search_helper_spec.rb +775 -0
  91. data/spec/lib/blacklight/solr/document/more_like_this_spec.rb +1 -1
  92. data/spec/lib/blacklight/solr/search_builder_spec.rb +561 -0
  93. data/spec/lib/blacklight/solr_helper_spec.rb +5 -1291
  94. data/spec/lib/blacklight/solr_repository_spec.rb +13 -13
  95. data/spec/models/record_mailer_spec.rb +2 -2
  96. data/spec/spec_helper.rb +1 -0
  97. data/spec/test_app_templates/lib/generators/test_app_generator.rb +1 -1
  98. data/spec/views/catalog/_constraints.html.erb_spec.rb +1 -1
  99. data/spec/views/catalog/_paginate_compact.html.erb_spec.rb +2 -2
  100. data/spec/views/catalog/index.atom.builder_spec.rb +1 -1
  101. data/tasks/blacklight.rake +1 -1
  102. data/template.demo.rb +1 -1
  103. metadata +33 -45
  104. data/doc/Adding-new-document-actions.md +0 -94
  105. data/doc/Atom-Responses.md +0 -90
  106. data/doc/Blacklight-Add-ons.md +0 -23
  107. data/doc/Blacklight-configuration.md +0 -411
  108. data/doc/Blacklight-on-Heroku.md +0 -100
  109. data/doc/Blacklight-out-of-the-box.md +0 -47
  110. data/doc/Bookmarks.md +0 -1
  111. data/doc/Code4Lib-2014.md +0 -94
  112. data/doc/Configuration---Facet-Fields.md +0 -130
  113. data/doc/Configuration---Results-View.md +0 -224
  114. data/doc/Configuration---Solr-fields.md +0 -106
  115. data/doc/Configuring-and-Customizing-Blacklight.md +0 -257
  116. data/doc/Configuring-rails-routes.md +0 -13
  117. data/doc/Contributing-to-Blacklight.md +0 -43
  118. data/doc/Examples.md +0 -120
  119. data/doc/Extending-or-Modifying-Blacklight-Search-Behavior.md +0 -141
  120. data/doc/Home.md +0 -100
  121. data/doc/How-to-release-a-version.md +0 -45
  122. data/doc/Indexing-your-data-into-solr.md +0 -36
  123. data/doc/Internationalization.md +0 -32
  124. data/doc/JSON-API.md +0 -83
  125. data/doc/Pagination.md +0 -52
  126. data/doc/Providing-your-own-view-templates.md +0 -69
  127. data/doc/Quickstart.md +0 -153
  128. data/doc/README_SOLR.md +0 -245
  129. data/doc/Saved-Searches.md +0 -5
  130. data/doc/Solr-Configuration.md +0 -154
  131. data/doc/Sunspot-for-indexing.md +0 -46
  132. data/doc/Support.md +0 -33
  133. data/doc/Theming.md +0 -62
  134. data/doc/Understanding-Rails-and-Blacklight.md +0 -75
  135. data/doc/User-Authentication.md +0 -60
  136. data/doc/_Sidebar.md +0 -9
  137. data/doc/testing.md +0 -58
@@ -0,0 +1,7 @@
1
+ module Blacklight::Document::SchemaOrg
2
+
3
+ def itemtype
4
+ "http://schema.org/Thing"
5
+ end
6
+
7
+ end
@@ -0,0 +1,51 @@
1
+ module Blacklight::Document
2
+ module SemanticFields
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ # Returns array of hashes of registered extensions. Each hash
7
+ # has a :module_obj key and a :condition_proc key. Usually this
8
+ # method is only used internally in #apply_extensions, but if you
9
+
10
+ # Class-level method for accessing/setting semantic mappings
11
+ # for solr stored fields. Can be set by local app, key is
12
+ # a symbol for a semantic, value is a solr _stored_ field.
13
+ #
14
+ # Stored field can be single or multi-value. In some cases
15
+ # clients may only use the first value from a multi-value field.
16
+ #
17
+ # Currently documented semantic tokens, not all may be
18
+ # used by core BL, but some may be used by plugins present
19
+ # or future.
20
+ # :title, :author, :year, :language => User-presentable strings.
21
+ def field_semantics
22
+ @field_semantics ||= {}
23
+ end
24
+ end
25
+
26
+ # Returns a hash keyed by semantic tokens, value is an array of
27
+ # strings. (Array to handle multi-value fields). If no value(s)
28
+ # available, empty array is returned.
29
+ #
30
+ # Default implementation here uses field_semantics
31
+ # to just take values from Solr stored fields.
32
+ # Extensions can over-ride this method to provide better/different lookup,
33
+ # but extensions should call super and modify hash returned, to avoid
34
+ # unintentionally erasing values provided by other extensions.
35
+ def to_semantic_values
36
+ unless @semantic_value_hash
37
+ @semantic_value_hash = Hash.new([]) # default to empty array
38
+ self.class.field_semantics.each_pair do |key, field_name|
39
+ value = self[field_name]
40
+ # Make single and multi-values all arrays, so clients
41
+ # don't have to know.
42
+ unless value.nil?
43
+ value = [value] unless value.kind_of?(Array)
44
+ @semantic_value_hash[key] = value
45
+ end
46
+ end
47
+ end
48
+ return @semantic_value_hash
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,14 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # This module provides the body of an email export based on the document's semantic values
3
+ module Blacklight::Document::Sms
4
+
5
+ # Return a text string that will be the body of the email
6
+ def to_sms_text
7
+ semantics = self.to_semantic_values
8
+ body = []
9
+ body << I18n.t('blacklight.sms.text.title', value: semantics[:title].first) unless semantics[:title].blank?
10
+ body << I18n.t('blacklight.sms.text.author', value: semantics[:author].first) unless semantics[:author].blank?
11
+ return body.join unless body.empty?
12
+ end
13
+
14
+ end
@@ -55,7 +55,7 @@ module Blacklight
55
55
  # Render a value (or array of values) from a field
56
56
  #
57
57
  # @param [String] value or list of values to display
58
- # @param [Blacklight::Solr::Configuration::SolrField] solr field configuration
58
+ # @param [Blacklight::Solr::Configuration::Field] solr field configuration
59
59
  # @return [String]
60
60
  def render_field_value value=nil, field_config=nil
61
61
  safe_values = Array(value).collect { |x| x.respond_to?(:force_encoding) ? x.force_encoding("UTF-8") : x }
@@ -134,7 +134,7 @@ module Blacklight
134
134
  # simplified by pushing some of this logic into the "model"
135
135
  # @param [SolrDocument] document
136
136
  # @param [String] field name
137
- # @param [Blacklight::Solr::Configuration::SolrField] solr field configuration
137
+ # @param [Blacklight::Solr::Configuration::Field] solr field configuration
138
138
  # @param [Hash] options additional options to pass to the rendering helpers
139
139
  def get_field_values field, field_config, options = {}
140
140
  # retrieving values
@@ -166,7 +166,7 @@ module Blacklight
166
166
  @controller.send(field_config.helper_method, options.merge(:document => @document, :field => field, :value => value))
167
167
  when (field_config and field_config.link_to_search)
168
168
  link_field = if field_config.link_to_search === true
169
- field_config.field
169
+ field_config.key
170
170
  else
171
171
  field_config.link_to_search
172
172
  end
@@ -6,10 +6,17 @@ module Blacklight
6
6
  end
7
7
 
8
8
  # When a request for a single solr document by id
9
- # is not successful, raise this:
9
+ # is not successful, we can raise this exception.
10
+ # Deprecated; this will be removed in Blacklight 6.0:
10
11
  class InvalidSolrID < RuntimeError
11
12
  end
12
-
13
+ # In Blacklight 6.0, this exception can subclass RuntimeError directly
14
+ class RecordNotFound < InvalidSolrID
15
+ end
16
+
17
+ class InvalidRequest < StandardError
18
+ end
19
+
13
20
  class ExpiredSessionToken < Exception
14
21
  end
15
22
 
@@ -8,11 +8,11 @@ module Blacklight
8
8
  Blacklight::Solr::FacetPaginator.new(display_facet.items,
9
9
  sort: display_facet.sort,
10
10
  offset: display_facet.offset,
11
- limit: facet_limit_for(field_config.field))
11
+ limit: facet_limit_for(field_config.key))
12
12
  end
13
13
 
14
14
  def facets_from_request(fields = facet_field_names)
15
- fields.map { |solr_field| facet_by_field_name(solr_field) }.compact
15
+ fields.map { |field| facet_by_field_name(field) }.compact
16
16
  end
17
17
 
18
18
  def facet_field_names
@@ -20,38 +20,43 @@ module Blacklight
20
20
  end
21
21
 
22
22
  def facet_configuration_for_field(field)
23
- blacklight_config.facet_fields[field] || Blacklight::Configuration::FacetField.new(:field => field).normalize!
23
+ f = blacklight_config.facet_fields[field]
24
+ f ||= begin
25
+ _, value = blacklight_config.facet_fields.find { |k,v| v.field == field }
26
+ value
27
+ end
28
+ f ||= Blacklight::Configuration::FacetField.new(:field => field).normalize!
24
29
  end
25
30
 
26
31
 
27
32
  # Get a FacetField object from the @response
28
- def facet_by_field_name solr_field
29
- case solr_field
33
+ def facet_by_field_name field
34
+ case field
30
35
  when String, Symbol
31
- extract_solr_facet_by_field_name(solr_field)
36
+ extract_facet_by_field_name(field)
32
37
  when Blacklight::Configuration::FacetField
33
- extract_solr_facet_by_field_name(solr_field.field)
38
+ extract_facet_by_field_name(field.key)
34
39
  else
35
- solr_field
40
+ field
36
41
  end
37
42
  end
38
43
 
39
44
  private
40
45
 
41
- # Get the solr response for the solr field :field
42
- def extract_solr_facet_by_field_name facet_name
43
- facet_field = facet_configuration_for_field(facet_name)
46
+ # Get the solr response for the field :field
47
+ def extract_facet_by_field_name field_name
48
+ facet_field = facet_configuration_for_field(field_name)
44
49
  case
45
50
  when (facet_field.respond_to?(:query) and facet_field.query)
46
- create_rsolr_facet_field_response_for_query_facet_field facet_name, facet_field
51
+ create_facet_field_response_for_query_facet_field field_name, facet_field
47
52
  when (facet_field.respond_to?(:pivot) and facet_field.pivot)
48
- create_rsolr_facet_field_response_for_pivot_facet_field facet_name, facet_field
53
+ create_facet_field_response_for_pivot_facet_field field_name, facet_field
49
54
  else
50
- @response.facet_by_field_name(facet_name)
55
+ @response.facet_by_field_name(field_name)
51
56
  end
52
57
  end
53
58
 
54
- def create_rsolr_facet_field_response_for_query_facet_field facet_name, facet_field
59
+ def create_facet_field_response_for_query_facet_field facet_name, facet_field
55
60
  salient_facet_queries = facet_field.query.map { |k, x| x[:fq] }
56
61
  items = []
57
62
  @response.facet_queries.select { |k,v| salient_facet_queries.include?(k) }.reject { |value, hits| hits == 0 }.map do |value,hits|
@@ -64,7 +69,7 @@ module Blacklight
64
69
  end
65
70
 
66
71
 
67
- def create_rsolr_facet_field_response_for_pivot_facet_field facet_name, facet_field
72
+ def create_facet_field_response_for_pivot_facet_field facet_name, facet_field
68
73
  items = []
69
74
  (@response.facet_pivot[facet_field.pivot.join(",")] || []).map do |lst|
70
75
  items << construct_pivot_field(lst)
@@ -1,6 +1,6 @@
1
1
  module Blacklight
2
2
  ##
3
- # This module contains methods that are specified by SolrHelper.solr_search_params_logic
3
+ # This module contains methods that are specified by SearchHelper.search_params_logic
4
4
  # They transform user parameters into parameters that are sent as a request to Solr when
5
5
  # RequestBuilders#solr_search_params is called.
6
6
  #
@@ -10,26 +10,56 @@ module Blacklight
10
10
  self.deprecation_horizon = 'blacklight 6.0'
11
11
 
12
12
  included do
13
- # We want to install a class-level place to keep
14
- # solr_search_params_logic method names. Compare to before_filter,
13
+ # We want to install a class-level place to keep
14
+ # search_params_logic method names. Compare to before_filter,
15
15
  # similar design. Since we're a module, we have to add it in here.
16
16
  # There are too many different semantic choices in ruby 'class variables',
17
- # we choose this one for now, supplied by Rails.
18
- class_attribute :solr_search_params_logic
17
+ # we choose this one for now, supplied by Rails.
18
+ class_attribute :search_params_logic
19
+
20
+ alias_method :solr_search_params_logic, :search_params_logic
21
+ deprecation_deprecate solr_search_params_logic: :search_params_logic
22
+
23
+ alias_method :solr_search_params_logic=, :search_params_logic=
24
+ deprecation_deprecate :solr_search_params_logic= => :search_params_logic=
19
25
 
20
26
  # Set defaults. Each symbol identifies a _method_ that must be in
21
27
  # this class, taking two parameters (solr_parameters, user_parameters)
22
28
  # Can be changed in local apps or by plugins, eg:
23
29
  # CatalogController.include ModuleDefiningNewMethod
24
- # CatalogController.solr_search_params_logic += [:new_method]
25
- # CatalogController.solr_search_params_logic.delete(:we_dont_want)
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 ]
30
+ # CatalogController.search_params_logic += [:new_method]
31
+ # CatalogController.search_params_logic.delete(:we_dont_want)
32
+ self.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
33
 
28
34
  if self.respond_to?(:helper_method)
29
35
  helper_method(:facet_limit_for)
30
36
  end
31
37
  end
32
38
 
39
+ module ClassMethods
40
+ extend Deprecation
41
+ self.deprecation_horizon = 'blacklight 6.0'
42
+
43
+ def solr_search_params_logic
44
+ search_params_logic
45
+ end
46
+ deprecation_deprecate solr_search_params_logic: :search_params_logic
47
+
48
+ def solr_search_params_logic= logic
49
+ self.search_params_logic= logic
50
+ end
51
+ deprecation_deprecate :solr_search_params_logic= => :search_params_logic=
52
+ end
53
+
54
+ def search_builder_class
55
+ blacklight_config.search_builder_class
56
+ end
57
+
58
+ def search_builder processor_chain = search_params_logic
59
+ search_builder_class.new(processor_chain, self)
60
+ end
61
+
62
+
33
63
  # @returns a params hash for searching solr.
34
64
  # The CatalogController #index action uses this.
35
65
  # Solr parameters can come from a number of places. From lowest
@@ -45,32 +75,37 @@ module Blacklight
45
75
  # specified otherwise.
46
76
  #
47
77
  # Incoming parameter :f is mapped to :fq solr parameter.
48
- def solr_search_params(user_params = params || {})
49
- Blacklight::Solr::Request.new.tap do |solr_parameters|
50
- solr_search_params_logic.each do |method_name|
51
- send(method_name, solr_parameters, user_params)
52
- end
53
- end
78
+ def solr_search_params(user_params = params || {}, processor_chain = search_params_logic)
79
+ search_builder(processor_chain).with(user_params).processed_parameters
54
80
  end
55
-
81
+ deprecation_deprecate solr_search_params: :processed_parameters
82
+
83
+ ##
84
+ # @param [Hash] user_params a hash of user submitted parameters
85
+ # @param [Array] processor_chain a list of processor methods to run
86
+ # @param [Hash] extra_params an optional hash of parameters that should be
87
+ # added to the query post processing
88
+ def build_solr_query(user_params, processor_chain, extra_params=nil)
89
+ search_builder(processor_chain).with(user_params).query(extra_params)
90
+ end
91
+ deprecation_deprecate build_solr_query: :query
92
+
56
93
  ##
57
94
  # Retrieve the results for a list of document ids
58
95
  def solr_document_ids_params(ids = [])
59
- solr_documents_by_field_values_params blacklight_config.solr_document_model.unique_key, ids
96
+ Deprecation.silence(Blacklight::RequestBuilders) do
97
+ solr_documents_by_field_values_params blacklight_config.document_model.unique_key, ids
98
+ end
60
99
  end
100
+ deprecation_deprecate :solr_document_ids_params
61
101
 
62
102
  ##
63
103
  # Retrieve the results for a list of document ids
64
104
  # @deprecated
65
105
  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: "*" }
106
+ search_builder([:add_query_to_solr]).with(q: { field => values}).query(fl: '*')
73
107
  end
108
+ deprecation_deprecate :solr_documents_by_field_values_params
74
109
 
75
110
  ##
76
111
  # Retrieve a facet's paginated values.
@@ -81,7 +116,7 @@ module Blacklight
81
116
  solr_params = {}
82
117
 
83
118
  # 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)
119
+ solr_params[:"facet.field"] = search_builder.with_ex_local_param((facet_config.ex if facet_config.respond_to?(:ex)), facet_field)
85
120
 
86
121
  limit = if respond_to?(:facet_list_limit)
87
122
  facet_list_limit.to_s.to_i
@@ -132,219 +167,12 @@ module Blacklight
132
167
  solr_params[:facet] = false
133
168
  solr_params
134
169
  end
135
-
136
- ####
137
- # Start with general defaults from BL config. Need to use custom
138
- # merge to dup values, to avoid later mutating the original by mistake.
139
- def default_solr_parameters(solr_parameters, user_params)
140
- blacklight_config.default_solr_params.each do |key, value|
141
- solr_parameters[key] = value.dup rescue value
142
- end
143
- end
144
-
145
- ##
146
- # Take the user-entered query, and put it in the solr params,
147
- # including config's "search field" params for current search field.
148
- # also include setting spellcheck.q.
149
- def add_query_to_solr(solr_parameters, user_parameters)
150
- ###
151
- # Merge in search field configured values, if present, over-writing general
152
- # defaults
153
- ###
154
- # legacy behavior of user param :qt is passed through, but over-ridden
155
- # by actual search field config if present. We might want to remove
156
- # this legacy behavior at some point. It does not seem to be currently
157
- # rspec'd.
158
- solr_parameters[:qt] = user_parameters[:qt] if user_parameters[:qt]
159
-
160
- search_field_def = blacklight_config.search_fields[user_parameters[:search_field]]
161
- if (search_field_def)
162
- solr_parameters[:qt] = search_field_def.qt
163
- solr_parameters.merge!( search_field_def.solr_parameters) if search_field_def.solr_parameters
164
- end
165
-
166
- ##
167
- # Create Solr 'q' including the user-entered q, prefixed by any
168
- # solr LocalParams in config, using solr LocalParams syntax.
169
- # http://wiki.apache.org/solr/LocalParams
170
- ##
171
- if (search_field_def && hash = search_field_def.solr_local_parameters)
172
- local_params = hash.collect do |key, val|
173
- key.to_s + "=" + solr_param_quote(val, :quote => "'")
174
- end.join(" ")
175
- solr_parameters[:q] = "{!#{local_params}}#{user_parameters[:q]}"
176
- else
177
- solr_parameters[:q] = user_parameters[:q] if user_parameters[:q]
178
- end
179
-
180
-
181
- ##
182
- # Set Solr spellcheck.q to be original user-entered query, without
183
- # our local params, otherwise it'll try and spellcheck the local
184
- # params! Unless spellcheck.q has already been set by someone,
185
- # respect that.
186
- #
187
- # TODO: Change calling code to expect this as a symbol instead of
188
- # a string, for consistency? :'spellcheck.q' is a symbol. Right now
189
- # rspec tests for a string, and can't tell if other code may
190
- # insist on a string.
191
- solr_parameters["spellcheck.q"] = user_parameters[:q] unless solr_parameters["spellcheck.q"]
192
- end
193
-
194
- ##
195
- # Add any existing facet limits, stored in app-level HTTP query
196
- # as :f, to solr as appropriate :fq query.
197
- def add_facet_fq_to_solr(solr_parameters, user_params)
198
-
199
- # convert a String value into an Array
200
- if solr_parameters[:fq].is_a? String
201
- solr_parameters[:fq] = [solr_parameters[:fq]]
202
- end
203
-
204
- # :fq, map from :f.
205
- if ( user_params[:f])
206
- f_request_params = user_params[:f]
207
-
208
- f_request_params.each_pair do |facet_field, value_list|
209
- Array(value_list).each do |value|
210
- next if value.blank? # skip empty strings
211
- solr_parameters.append_filter_query facet_value_to_fq_string(facet_field, value)
212
- end
213
- end
214
- end
215
- end
216
170
 
217
- ##
218
- # Add appropriate Solr facetting directives in, including
219
- # taking account of our facet paging/'more'. This is not
220
- # about solr 'fq', this is about solr facet.* params.
221
- def add_facetting_to_solr(solr_parameters, user_params)
222
- # While not used by BL core behavior, legacy behavior seemed to be
223
- # to accept incoming params as "facet.field" or "facets", and add them
224
- # on to any existing facet.field sent to Solr. Legacy behavior seemed
225
- # to be accepting these incoming params as arrays (in Rails URL with []
226
- # on end), or single values. At least one of these is used by
227
- # Stanford for "faux hieararchial facets".
228
- if user_params.has_key?("facet.field") || user_params.has_key?("facets")
229
- solr_parameters[:"facet.field"].concat( [user_params["facet.field"], user_params["facets"]].flatten.compact ).uniq!
230
- end
231
-
232
- blacklight_config.facet_fields.select { |field_name,facet|
233
- facet.include_in_request || (facet.include_in_request.nil? && blacklight_config.add_facet_fields_to_solr_request)
234
- }.each do |field_name, facet|
235
- solr_parameters[:facet] ||= true
236
-
237
- case
238
- when facet.pivot
239
- solr_parameters.append_facet_pivot with_ex_local_param(facet.ex, facet.pivot.join(","))
240
- when facet.query
241
- solr_parameters.append_facet_query facet.query.map { |k, x| with_ex_local_param(facet.ex, x[:fq]) }
242
- else
243
- solr_parameters.append_facet_fields with_ex_local_param(facet.ex, facet.field)
244
- end
245
-
246
- if facet.sort
247
- solr_parameters[:"f.#{facet.field}.facet.sort"] = facet.sort
248
- end
249
-
250
- if facet.solr_params
251
- facet.solr_params.each do |k, v|
252
- solr_parameters[:"f.#{facet.field}.#{k}"] = v
253
- end
254
- end
255
-
256
- # Support facet paging and 'more'
257
- # links, by sending a facet.limit one more than what we
258
- # want to page at, according to configured facet limits.
259
- solr_parameters[:"f.#{facet.field}.facet.limit"] = (facet_limit_for(field_name) + 1) if facet_limit_for(field_name)
260
- end
261
- end
262
-
263
- def add_solr_fields_to_query solr_parameters, user_parameters
264
- blacklight_config.show_fields.select(&method(:should_add_to_solr)).each do |field_name, field|
265
- if field.solr_params
266
- field.solr_params.each do |k, v|
267
- solr_parameters[:"f.#{field.field}.#{k}"] = v
268
- end
269
- end
270
- end
271
-
272
- blacklight_config.index_fields.select(&method(:should_add_to_solr)).each do |field_name, field|
273
- if field.highlight
274
- solr_parameters[:hl] = true
275
- solr_parameters.append_highlight_field field.field
276
- end
277
-
278
- if field.solr_params
279
- field.solr_params.each do |k, v|
280
- solr_parameters[:"f.#{field.field}.#{k}"] = v
281
- end
282
- end
283
- end
284
- end
285
-
286
- ###
287
- # copy paging params from BL app over to solr, changing
288
- # app level per_page and page to Solr rows and start.
289
- def add_paging_to_solr(solr_params, user_params)
290
-
291
- # user-provided parameters should override any default row
292
- solr_params[:rows] = user_params[:rows].to_i unless user_params[:rows].blank?
293
- solr_params[:rows] = user_params[:per_page].to_i unless user_params[:per_page].blank?
294
-
295
- # configuration defaults should only set a default value, not override a value set elsewhere (e.g. search field parameters)
296
- solr_params[:rows] ||= blacklight_config.default_per_page unless blacklight_config.default_per_page.blank?
297
- solr_params[:rows] ||= blacklight_config.per_page.first unless blacklight_config.per_page.blank?
298
-
299
- # set a reasonable default
300
- Rails.logger.info "Solr :rows parameter not set (by the user, configuration, or default solr parameters); using 10 rows by default"
301
- solr_params[:rows] ||= 10
302
-
303
- # ensure we don't excede the max page size
304
- solr_params[:rows] = blacklight_config.max_per_page if solr_params[:rows].to_i > blacklight_config.max_per_page
305
- unless user_params[:page].blank?
306
- solr_params[:start] = solr_params[:rows].to_i * (user_params[:page].to_i - 1)
307
- solr_params[:start] = 0 if solr_params[:start].to_i < 0
308
- end
309
-
310
- end
311
-
312
- ###
313
- # copy sorting params from BL app over to solr
314
- def add_sorting_to_solr(solr_parameters, user_params)
315
- if user_params[:sort].blank? and sort_field = blacklight_config.default_sort_field
316
- # no sort param provided, use default
317
- solr_parameters[:sort] = sort_field.sort unless sort_field.sort.blank?
318
- elsif sort_field = blacklight_config.sort_fields[user_params[:sort]]
319
- # check for sort field key
320
- solr_parameters[:sort] = sort_field.sort unless sort_field.sort.blank?
321
- else
322
- # just pass the key through
323
- solr_parameters[:sort] = user_params[:sort]
324
- end
325
- end
326
-
327
- # Remove the group parameter if we've faceted on the group field (e.g. for the full results for a group)
328
- def add_group_config_to_solr solr_parameters, user_parameters
329
- if user_parameters[:f] and user_parameters[:f][grouped_key_for_results]
330
- solr_parameters[:group] = false
331
- end
332
- end
333
-
334
- def with_ex_local_param(ex, value)
335
- if ex
336
- "{!ex=#{ex}}#{value}"
337
- else
338
- value
339
- end
340
- end
341
-
342
-
343
171
  DEFAULT_FACET_LIMIT = 10
344
172
 
345
173
  # Look up facet limit for given facet_field. Will look at config, and
346
174
  # 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
175
+ # no limit is avaialble, returns nil. Used from #add_facetting_to_solr
348
176
  # to supply f.fieldname.facet.limit values in solr request (no @response
349
177
  # available), and used in display (with @response available) to create
350
178
  # a facet paginator with the right limit.
@@ -366,57 +194,5 @@ module Blacklight
366
194
  facet.limit == true ? DEFAULT_FACET_LIMIT : facet.limit
367
195
  end
368
196
  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
-
385
- private
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
-
391
- ##
392
- # Convert a facet/value pair into a solr fq parameter
393
- def facet_value_to_fq_string(facet_field, value)
394
- facet_config = blacklight_config.facet_fields[facet_field]
395
-
396
- local_params = []
397
- local_params << "tag=#{facet_config.tag}" if facet_config and facet_config.tag
398
-
399
- prefix = ""
400
- prefix = "{!#{local_params.join(" ")}}" unless local_params.empty?
401
-
402
- fq = case
403
- when (facet_config and facet_config.query)
404
- facet_config.query[value][:fq]
405
- when (facet_config and facet_config.date)
406
- # in solr 3.2+, this could be replaced by a !term query
407
- "#{prefix}#{facet_field}:#{RSolr.escape(value)}"
408
- when (value.is_a?(DateTime) or value.is_a?(Date) or value.is_a?(Time))
409
- "#{prefix}#{facet_field}:#{RSolr.escape(value.to_time.utc.strftime("%Y-%m-%dT%H:%M:%SZ"))}"
410
- when (value.is_a?(TrueClass) or value.is_a?(FalseClass) or value == 'true' or value == 'false'),
411
- (value.is_a?(Integer) or (value.to_i.to_s == value if value.respond_to? :to_i)),
412
- (value.is_a?(Float) or (value.to_f.to_s == value if value.respond_to? :to_f))
413
- "#{prefix}#{facet_field}:#{RSolr.escape(value.to_s)}"
414
- when value.is_a?(Range)
415
- "#{prefix}#{facet_field}:[#{value.first} TO #{value.last}]"
416
- else
417
- "{!raw f=#{facet_field}#{(" " + local_params.join(" ")) unless local_params.empty?}}#{value}"
418
- end
419
-
420
- end
421
197
  end
422
198
  end