europeana-blacklight 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,41 @@
1
+ require 'kaminari'
2
+
3
+ module Europeana
4
+ module Blacklight
5
+ class Response
6
+ ##
7
+ # Pagination for{Europeana::Blacklight::Response}
8
+ #
9
+ # Based on {Blacklight::SolrResponse::Pagination} v5.10.2
10
+ module Pagination
11
+ include Kaminari::PageScopeMethods
12
+ include Kaminari::ConfigurationMethods::ClassMethods
13
+
14
+ def limit_value
15
+ rows
16
+ end
17
+
18
+ def offset_value
19
+ start
20
+ end
21
+
22
+ def total_count
23
+ total
24
+ end
25
+
26
+ def model_name
27
+ return unless docs.present? && docs.first.respond_to?(:model_name)
28
+ docs.first.model_name
29
+ end
30
+
31
+ def next_page
32
+ current_page + 1 unless last_page?
33
+ end
34
+
35
+ def prev_page
36
+ current_page - 1 unless first_page?
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,195 @@
1
+ module Europeana
2
+ module Blacklight
3
+ ##
4
+ # Core search builder for {Europeana::Blacklight::ApiRepository}
5
+ class SearchBuilder < ::Blacklight::SearchBuilder
6
+ require 'europeana/blacklight/search_builder/channels'
7
+ require 'europeana/blacklight/search_builder/facet_pagination'
8
+ require 'europeana/blacklight/search_builder/more_like_this'
9
+ require 'europeana/blacklight/search_builder/ranges'
10
+
11
+ self.default_processor_chain = [
12
+ :default_api_parameters, :add_profile_to_api,
13
+ :add_wskey_to_api, :add_query_to_api, :add_qf_to_api,
14
+ :add_facet_qf_to_api, :add_reusability_to_api, :add_facetting_to_api,
15
+ :add_paging_to_api, :add_sorting_to_api
16
+ ]
17
+
18
+ include Channels
19
+ include FacetPagination
20
+ include MoreLikeThis
21
+ include Ranges
22
+
23
+ delegate :to_query, to: :to_hash
24
+
25
+ ##
26
+ # Start with general defaults from BL config. Need to use custom
27
+ # merge to dup values, to avoid later mutating the original by mistake.
28
+ #
29
+ # @todo Rename default_solr_params to default_params upstream
30
+ def default_api_parameters(api_parameters)
31
+ blacklight_config.default_solr_params.each do |key, value|
32
+ if value.respond_to?(:deep_dup)
33
+ api_parameters[key] = value.deep_dup
34
+ elsif value.respond_to?(:dup) && value.duplicable?
35
+ api_parameters[key] = value.dup
36
+ else
37
+ api_parameters[key] = value
38
+ end
39
+ end
40
+ end
41
+
42
+ ##
43
+ # Set the profile type
44
+ #
45
+ # @see http://labs.europeana.eu/api/search/#profile-parameter
46
+ def add_profile_to_api(api_parameters)
47
+ if blacklight_config.facet_fields
48
+ api_parameters[:profile] = 'params facets rich'
49
+ else
50
+ api_parameters[:profile] = 'params rich'
51
+ end
52
+ end
53
+
54
+ ##
55
+ # Add the Europeana REST API key
56
+ #
57
+ # @see http://labs.europeana.eu/api/authentication/#basic-authentication
58
+ def add_wskey_to_api(api_parameters)
59
+ api_parameters[:wskey] = blacklight_config.connection_config[:europeana_api_key]
60
+ end
61
+
62
+ ##
63
+ # Take the user-entered query, and put it in the API params,
64
+ # including config's "search field" params for current search field.
65
+ #
66
+ # @see http://labs.europeana.eu/api/query/
67
+ def add_query_to_api(api_parameters)
68
+ if [blacklight_params[:q]].flatten.reject(&:blank?).blank?
69
+ query = '*:*'
70
+ elsif search_field && search_field.field.present?
71
+ query = "#{search_field.field}:#{blacklight_params[:q]}"
72
+ elsif blacklight_params[:q].is_a?(Hash)
73
+ # @todo when would it be a Hash?
74
+ query = nil
75
+ elsif blacklight_params[:q]
76
+ query = blacklight_params[:q]
77
+ end
78
+ append_to_query_param(api_parameters, query)
79
+ end
80
+
81
+ ##
82
+ # Add the user's query filter terms
83
+ def add_qf_to_api(api_parameters)
84
+ return unless blacklight_params[:qf]
85
+ api_parameters[:qf] ||= []
86
+ api_parameters[:qf] = api_parameters[:qf] + blacklight_params[:qf]
87
+ end
88
+
89
+ ##
90
+ # Facet *filtering* of results
91
+ #
92
+ # Maps Blacklight's :f param to API's :qf param.
93
+ #
94
+ # @see http://labs.europeana.eu/api/query/#faceted-search
95
+ # @todo Handle different types of value, like
96
+ # {Blacklight::Solr::SearchBuilder#facet_value_to_fq_string} does
97
+ def add_facet_qf_to_api(api_parameters)
98
+ return unless blacklight_params[:f]
99
+
100
+ salient_facets = blacklight_params[:f].reject do |k, _v|
101
+ k == 'REUSABILITY'
102
+ end
103
+
104
+ salient_facets.each_pair do |facet_field, value_list|
105
+ Array(value_list).reject(&:blank?).each do |value|
106
+ api_parameters[:qf] ||= []
107
+ api_parameters[:qf] << "#{facet_field}:\"#{value}\""
108
+ end
109
+ end
110
+ end
111
+
112
+ # bizarrely, reusability is a distinct API param, even though it
113
+ # is returned with the facets in a search response
114
+ def add_reusability_to_api(api_parameters)
115
+ if blacklight_params[:f] && blacklight_params[:f]['REUSABILITY']
116
+ api_parameters[:reusability] = blacklight_params[:f]['REUSABILITY'].join(',')
117
+ end
118
+ end
119
+
120
+ ##
121
+ # Request facet data in results, respecting configured limits
122
+ #
123
+ # @todo Handle facet settings like query, sort, pivot, etc, like
124
+ # {Blacklight::Solr::SearchBuilder#add_facetting_to_solr} does
125
+ # @see http://labs.europeana.eu/api/search/#individual-facets
126
+ # @see http://labs.europeana.eu/api/search/#offset-and-limit-of-facets
127
+ def add_facetting_to_api(api_parameters)
128
+ api_parameters[:facet] = api_request_facet_fields.keys.join(',')
129
+
130
+ api_request_facet_fields.each do |field_name, facet|
131
+ api_parameters[:"f.#{facet.field}.facet.limit"] = (facet_limit_for(field_name) + 1) if facet_limit_for(field_name)
132
+ end
133
+ end
134
+
135
+ ##
136
+ # copy paging params from BL app over to API, changing
137
+ # app level per_page and page to API rows and start.
138
+ def add_paging_to_api(api_parameters)
139
+ rows(api_parameters[:rows] || 10) if rows.nil?
140
+ api_parameters[:rows] = rows
141
+
142
+ api_parameters[:start] = start unless start == 0
143
+ end
144
+
145
+ ##
146
+ # @todo Implement when the API supports sorting
147
+ def add_sorting_to_api(_api_parameters)
148
+ return if sort.blank?
149
+ Europeana::API.logger.warn('Europeana REST API does not support sorting')
150
+ end
151
+
152
+ ##
153
+ # Europeana API start param counts from 1
154
+ def start(start = nil)
155
+ super_start = super
156
+ super_start == self ? super_start : super_start + 1
157
+ end
158
+
159
+ protected
160
+
161
+ # Look up facet limit for given facet_field. Will look at config, and
162
+ # if config is 'true' will look up from Solr @response if available. If
163
+ # no limit is avaialble, returns nil. Used from #add_facetting_to_solr
164
+ # to supply f.fieldname.facet.limit values in solr request (no @response
165
+ # available), and used in display (with @response available) to create
166
+ # a facet paginator with the right limit.
167
+ def facet_limit_for(facet_field)
168
+ facet = blacklight_config.facet_fields[facet_field]
169
+ return if facet.blank? || !facet.limit
170
+
171
+ if facet.limit == true
172
+ blacklight_config.default_facet_limit
173
+ else
174
+ facet.limit
175
+ end
176
+ end
177
+
178
+ def api_request_facet_fields
179
+ @api_request_facet_fields ||= blacklight_config.facet_fields.select do |field_name, facet|
180
+ !facet.query &&
181
+ (facet.include_in_request || (facet.include_in_request.nil? && blacklight_config.add_facet_fields_to_solr_request)) &&
182
+ (field_name == 'REUSABILITY' || Europeana::API::Search::Fields.include?(field_name))
183
+ end
184
+ end
185
+
186
+ def append_to_query_param(api_parameters, query)
187
+ return if query.blank?
188
+ return if query == '*:*' && api_parameters[:query].present?
189
+ api_parameters[:query] ||= ''
190
+ api_parameters[:query] << ' ' unless api_parameters[:query].blank?
191
+ api_parameters[:query] << query
192
+ end
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,18 @@
1
+ module Europeana
2
+ module Blacklight
3
+ class SearchBuilder
4
+ ##
5
+ # Search builder with content channel qf
6
+ module Channels
7
+ # @todo remove hard-coded controller check
8
+ def add_channel_qf_to_api(api_parameters)
9
+ return unless blacklight_params[:controller] == 'channels' && blacklight_params[:id].present?
10
+ channel_qf = scope.channels_search_query
11
+ return if channel_qf.blank?
12
+ api_parameters[:qf] ||= []
13
+ api_parameters[:qf] << channel_qf
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,38 @@
1
+ module Europeana
2
+ module Blacklight
3
+ class SearchBuilder
4
+ ##
5
+ # Search builder methods for facet pagination
6
+ module FacetPagination
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ default_processor_chain << :add_facet_paging_to_api
11
+ end
12
+
13
+ def add_facet_paging_to_api(api_parameters)
14
+ return unless facet.present?
15
+
16
+ facet_config = blacklight_config.facet_fields[facet]
17
+
18
+ limit = if scope.respond_to?(:facet_list_limit)
19
+ scope.facet_list_limit.to_s.to_i
20
+ elsif api_parameters['facet.limit']
21
+ api_parameters['facet.limit'].to_i
22
+ else
23
+ 20
24
+ end
25
+
26
+ offset = (blacklight_params.fetch(blacklight_config.facet_paginator_class.request_keys[:page], 1).to_i - 1) * (limit)
27
+
28
+ # Need to set as f.facet_field.facet.* to make sure we
29
+ # override any field-specific default in the solr request handler.
30
+ api_parameters[:"f.#{facet}.facet.limit"] = limit + 1
31
+ api_parameters[:"f.#{facet}.facet.offset"] = offset
32
+ api_parameters[:rows] = 0
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,23 @@
1
+ module Europeana
2
+ module Blacklight
3
+ class SearchBuilder
4
+ ##
5
+ # Search builder methods for more like this queries
6
+ module MoreLikeThis
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ default_processor_chain.unshift :add_mlt_to_api
11
+ end
12
+
13
+ def add_mlt_to_api(api_parameters)
14
+ return unless blacklight_params[:mlt]
15
+ repository = blacklight_config.repository_class.new(blacklight_config)
16
+ doc_response = repository.find(blacklight_params[:mlt])
17
+ query = doc_response.documents.first.more_like_this_query(blacklight_params[:mltf])
18
+ append_to_query_param(api_parameters, query)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module Europeana
2
+ module Blacklight
3
+ class SearchBuilder
4
+ ##
5
+ # Search builder with content channel qf
6
+ module Ranges
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ default_processor_chain << :add_range_qf_to_api
11
+ end
12
+
13
+ def add_range_qf_to_api(api_parameters)
14
+ return unless blacklight_params.key?(:range) && blacklight_params[:range].is_a?(Hash)
15
+ blacklight_params[:range].each_pair do |range_field, range_values|
16
+ api_parameters[:qf] ||= []
17
+ api_parameters[:qf] << "#{range_field}:[#{range_values[:begin]} TO #{range_values[:end]}]"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,6 @@
1
+ module Europeana
2
+ #:nodoc:
3
+ module Blacklight
4
+ VERSION = '0.1.0'
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: europeana-blacklight
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Richard Doe
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: blacklight
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.12.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: 6.0.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 5.12.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 6.0.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: europeana-api
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.3.2
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.3.2
47
+ - !ruby/object:Gem::Dependency
48
+ name: kaminari
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.16'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.16'
61
+ - !ruby/object:Gem::Dependency
62
+ name: bundler
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.8'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.8'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rake
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '10.0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '10.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rspec
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '3.2'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '3.2'
103
+ description:
104
+ email:
105
+ - richard.doe@rwdit.net
106
+ executables: []
107
+ extensions: []
108
+ extra_rdoc_files: []
109
+ files:
110
+ - ".gitignore"
111
+ - ".hound.yml"
112
+ - ".rspec"
113
+ - ".rubocop.yml"
114
+ - ".ruby-style.yml"
115
+ - ".travis.yml"
116
+ - Gemfile
117
+ - LICENSE.md
118
+ - README.md
119
+ - Rakefile
120
+ - bin/console
121
+ - bin/setup
122
+ - europeana-blacklight.gemspec
123
+ - lib/europeana/blacklight.rb
124
+ - lib/europeana/blacklight/api_repository.rb
125
+ - lib/europeana/blacklight/document.rb
126
+ - lib/europeana/blacklight/document/more_like_this.rb
127
+ - lib/europeana/blacklight/document/relations.rb
128
+ - lib/europeana/blacklight/document_presenter.rb
129
+ - lib/europeana/blacklight/facet_paginator.rb
130
+ - lib/europeana/blacklight/response.rb
131
+ - lib/europeana/blacklight/response/facets.rb
132
+ - lib/europeana/blacklight/response/more_like_this.rb
133
+ - lib/europeana/blacklight/response/pagination.rb
134
+ - lib/europeana/blacklight/search_builder.rb
135
+ - lib/europeana/blacklight/search_builder/channels.rb
136
+ - lib/europeana/blacklight/search_builder/facet_pagination.rb
137
+ - lib/europeana/blacklight/search_builder/more_like_this.rb
138
+ - lib/europeana/blacklight/search_builder/ranges.rb
139
+ - lib/europeana/blacklight/version.rb
140
+ homepage: https://github.com/europeana/europeana-blacklight
141
+ licenses:
142
+ - EUPL 1.1
143
+ metadata: {}
144
+ post_install_message:
145
+ rdoc_options: []
146
+ require_paths:
147
+ - lib
148
+ required_ruby_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ requirements: []
159
+ rubyforge_project:
160
+ rubygems_version: 2.4.8
161
+ signing_key:
162
+ specification_version: 4
163
+ summary: Europeana REST API adapter for Blacklight
164
+ test_files: []