• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pulibrary / orangelight / 4c391e0e-519a-40cb-8ad3-354445f4ce03

12 Aug 2025 08:47PM UTC coverage: 85.348% (-10.0%) from 95.335%
4c391e0e-519a-40cb-8ad3-354445f4ce03

push

circleci

web-flow
[#5143] Use access restriction note as Aeon ItemInfo1 if available (#5173)

With this commit, if a user visits a record with an access
restrictions note and presses the Reading Room Request
button, they will get to an Aeon form with the 'Restrictions'
field pre-filled with the restriction note.

If the record does not have an access restrictions note,
the field will be pre-filled with 'Reading Room Access Only',
as it has been previously.

Closes #5143

5493 of 6436 relevant lines covered (85.35%)

251.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.4
/app/helpers/blacklight_helper.rb
1
# frozen_string_literal: false
2

3
require 'library_stdnums'
1✔
4

5
module BlacklightHelper
1✔
6
  include Blacklight::BlacklightHelperBehavior
1✔
7
  require './lib/orangelight/string_functions'
1✔
8

9
  def json_field?(field)
1✔
10
    field[:hash]
196✔
11
  end
12

13
  def linked_record_field?(field)
1✔
14
    field[:link_field]
182✔
15
  end
16

17
  # Escape all whitespace characters within Solr queries specifying left anchor query facets
18
  # Ends all left-anchor searches with wildcards for matches that begin with search string
19
  # @param solr_parameters [Blacklight::Solr::Request] the parameters for the Solr query
20
  def prepare_left_anchor_search(solr_parameters)
1✔
21
    return unless left_anchor_search?(solr_parameters)
102✔
22
    solr_parameters.dig('json', 'query', 'bool').each_value do |value|
44✔
23
      value.select { |boolean_query| boolean_query_searches_left_anchored_field?(boolean_query) }.map! do |clause|
102✔
24
        query = escape_left_anchor_query(clause.dig(:edismax, :query).dup)
28✔
25
        query = add_wildcard(query)
28✔
26
        clause.dig(:edismax)[:query] = query
28✔
27
      end
28
    end
29
  end
30

31
  def left_anchor_search?(solr_parameters)
1✔
32
    return false unless solr_parameters.dig('json', 'query', 'bool')
103✔
33
    has_left_anchor = solr_parameters.dig('json', 'query', 'bool')
45✔
34
                                     .values
35
                                     .any? { |value| value.select { |clause| boolean_query_searches_left_anchored_field?(clause) } }
98✔
36
    return false unless has_left_anchor
45✔
37

38
    true
45✔
39
  end
40

41
  # Escape all whitespace characters within Solr queries specifying left anchor query facets
42
  def escape_left_anchor_query(query)
1✔
43
    query.gsub!(/(\s)/, '\\\\\1')
28✔
44
    query.gsub!(/(["\{\}\[\]\^\~])/, '\\\\\1')
28✔
45
    query.gsub!(/[\(\)]/, '')
28✔
46
    query
28✔
47
  end
48

49
  # Ends all left-anchor searches with wildcards for matches that begin with search string
50
  def add_wildcard(query)
1✔
51
    query.end_with?('*') ? query : query + '*'
28✔
52
  end
53

54
  def pul_holdings(solr_parameters)
1✔
55
    return unless blacklight_params[:f_inclusive] && blacklight_params[:f_inclusive][:advanced_location_s]&.include?('pul')
98✔
56
    solr_parameters[:fq].map! { |fq| fq.gsub '"pul"', '*' }
×
57
                        .reject! { |fq| fq == '{!term f=advanced_location_s}pul' }
×
58
    solr_parameters[:fq] << '-id:SCSB*'
×
59
  end
60

61
  def series_title_results(solr_parameters)
1✔
62
    return unless includes_series_search?
98✔
63
    solr_parameters[:fl] = 'id,score,author_display,marc_relator_display,format,pub_created_display,'\
1✔
64
                           'title_display,title_vern_display,isbn_s,oclc_s,lccn_s,holdings_1display,'\
65
                           'electronic_access_1display,electronic_portfolio_s,cataloged_tdt,series_display'
66
  end
67

68
  def includes_series_search?
1✔
69
    blacklight_params['clause'].map { |clause| clause[1]["field"] }.include?('series_title' || 'in_series') if blacklight_params['clause'].present?
187✔
70
  end
71

72
  # only fetch facets when an html page is requested
73
  def html_facets(solr_parameters)
1✔
74
    return if blacklight_params[:format].nil? || blacklight_params[:format] == 'html' ||
100✔
75
              blacklight_params[:format] == 'json'
76
    solr_parameters[:facet] = false
1✔
77
  end
78

79
  # Adapted from http://discovery-grindstone.blogspot.com/2014/01/cjk-with-solr-for-libraries-part-12.html
80
  def cjk_mm(solr_parameters)
1✔
81
    if blacklight_params && blacklight_params[:q].present?
101✔
82
      q_str = blacklight_params[:q]
19✔
83
      number_of_unigrams = cjk_unigrams_size(q_str)
19✔
84
      if number_of_unigrams > 2
19✔
85
        num_non_cjk_tokens = q_str.scan(/[[:alnum]]+/).size
3✔
86
        if num_non_cjk_tokens.positive?
3✔
87
          lower_limit = cjk_mm_val[0].to_i
1✔
88
          mm = (lower_limit + num_non_cjk_tokens).to_s + cjk_mm_val[1, cjk_mm_val.size]
1✔
89
          solr_parameters['mm'] = mm
1✔
90
        else
91
          solr_parameters['mm'] = cjk_mm_val
2✔
92
        end
93
      end
94
    end
95
  end
96

97
  def cjk_unigrams_size(str)
1✔
98
    if str&.is_a?(String)
19✔
99
      str.scan(/\p{Han}|\p{Katakana}|\p{Hiragana}|\p{Hangul}/).size
17✔
100
    else
101
      0
2✔
102
    end
103
  end
104

105
  def cjk_mm_val
1✔
106
    '3<86%'
6✔
107
  end
108

109
  def browse_related_name_hash(name)
1✔
110
    link_to(name, "/?f[author_s][]=#{CGI.escape name}", class: 'search-related-name', 'data-original-title' => "Search: #{name}") + '  ' +
60✔
111
      link_to('[Browse]', "/browse/names?q=#{CGI.escape name}", class: 'browse-related-name', 'data-original-title' => "Search: #{name}")
112
  end
113

114
  # render_document_heading from Blacklight v7.23.0.1
115
  # https://github.com/projectblacklight/blacklight/blob/242880eacb1c73a2a6a3d7cdf4e24cec151179f8/app/helpers/blacklight/blacklight_helper_behavior.rb#L245
116
  def render_document_heading(*args)
1✔
117
    options = args.extract_options!
29✔
118
    document = args.first
29✔
119
    tag = options.fetch(:tag, :h4)
29✔
120
    document ||= @document
29✔
121
    content_tag(tag, document_presenter(document).heading, itemprop: "name", lang: language_iana)
29✔
122
  end
123

124
  ##
125
  # Render the heading partial for a document
126
  #
127
  # @param [SolrDocument]
128
  # @return [String]
129
  def render_document_heading_partial(_document = @document)
1✔
130
    render partial: 'show_header_default'
29✔
131
  end
132

133
  # Generates markup for a <span> elements containing icons given a string value
134
  # @param value [String] value used for the CSS class
135
  # @return [String] markup for the <span> element
136
  def render_icon(var)
1✔
137
    "<span class='icon icon-#{var.parameterize}' aria-hidden='true'></span>".html_safe
×
138
  end
139

140
  # Generate the link to "start over" searches
141
  # @param path [String] the URL path for the link
142
  # @return [String] the markup for the link
143
  def render_start_over_link(path)
1✔
144
    child = "<span class=\"icon-refresh\" aria-hidden=\"true\"></span> <span>#{t('blacklight.search.start_over')}</span>"
142✔
145
    link_to(child.html_safe, path, class: 'catalog_startOverLink btn btn-primary', id: 'startOverLink')
142✔
146
  end
147

148
  # Generate the link to citations for Documents
149
  # @param path [String] the URL path for the link
150
  # @return [String] the markup for the link
151
  def render_cite_link(path)
1✔
152
    child = "<span class=\"icon-cite\" aria-hidden=\"true\"></span> #{t('blacklight.search.cite')}"
28✔
153
    link_to(child.html_safe, path, id: 'citeLink', data: { blacklight_modal: 'trigger' }, class: 'btn btn-default')
28✔
154
  end
155

156
  # Retrieve an instance of the FacetedQueryService
157
  # @return [FacetedQueryService] an instance of the service object
158
  def faceted_query_service
1✔
159
    @faceted_query_service ||= FacetedQueryService.new(Blacklight)
×
160
  end
161

162
  def oclc_resolve(oclc)
1✔
163
    oclc_norm = StringFunctions.oclc_normalize(oclc)
×
164
    unless oclc_norm.nil?
×
165
      fq = "oclc_s:#{oclc_norm}"
×
166
      resp = faceted_query_service.get_fq_solr_response(fq)
×
167
      req = JSON.parse(resp.body)
×
168
    end
169
    if oclc_norm.to_i.zero? || req['response']['docs'].empty?
×
170
      "/catalog?q=#{oclc}"
×
171
    else
172
      "/catalog/#{req['response']['docs'].first['id']}"
×
173
    end
174
  end
175

176
  def isbn_resolve(isbn)
1✔
177
    isbn_norm = StdNum::ISBN.normalize(isbn)
×
178
    unless isbn_norm.nil?
×
179
      fq = "isbn_s:#{isbn_norm}"
×
180
      resp = faceted_query_service.get_fq_solr_response(fq)
×
181
      req = JSON.parse(resp.body)
×
182
    end
183
    if isbn_norm.nil? || req['response']['docs'].empty?
×
184
      "/catalog?q=#{isbn}"
×
185
    else
186
      "/catalog/#{req['response']['docs'].first['id']}"
×
187
    end
188
  end
189

190
  def issn_resolve(issn)
1✔
191
    issn_norm = StdNum::ISSN.normalize(issn)
×
192
    unless issn_norm.nil?
×
193
      fq = "issn_s:#{issn_norm}"
×
194
      resp = faceted_query_service.get_fq_solr_response(fq)
×
195
      req = JSON.parse(resp.body)
×
196
    end
197
    if issn_norm.nil? || req['response']['docs'].empty?
×
198
      "/catalog?q=#{issn}"
×
199
    else
200
      "/catalog/#{req['response']['docs'].first['id']}"
×
201
    end
202
  end
203

204
  def lccn_resolve(lccn)
1✔
205
    lccn_norm = StdNum::LCCN.normalize(lccn)
×
206
    unless lccn_norm.nil?
×
207
      fq = "lccn_s:#{lccn_norm}"
×
208
      resp = faceted_query_service.get_fq_solr_response(fq)
×
209
      req = JSON.parse(resp.body)
×
210
    end
211
    if lccn_norm.nil? || req['response']['docs'].empty?
×
212
      "/catalog?q=#{lccn}"
×
213
    else
214
      "/catalog/#{req['response']['docs'].first['id']}"
×
215
    end
216
  end
217

218
  # Links to correct advanced search page based on advanced_type parameter value
219
  def edit_search_link
1✔
220
    url = advanced_path(params.permit!.except(:controller, :action).to_h)
73✔
221
    if params[:advanced_type] == 'numismatics'
73✔
222
      url.gsub('/advanced', '/numismatics')
6✔
223
    else
224
      url
67✔
225
    end
226
  end
227

228
  def link_back_to_catalog_safe(opts = { label: nil })
1✔
229
    link_back_to_catalog(opts)
2✔
230
  rescue ActionController::UrlGenerationError
231
    # This exception is triggered if the user's session has information that results in an
232
    # invalid back to catalog link. In that case, rather than blowing up on the user, we
233
    # render a valid link. This link does not preserve the user's previous setings and that is
234
    # OK because very likely their session is corrupted.
235
    link_to "Back to search", root_url
1✔
236
  end
237

238
    private
1✔
239

240
      def boolean_query_searches_left_anchored_field?(boolean_query)
1✔
241
        ["${left_anchor_qf}", "${in_series_qf}"].include? boolean_query.dig(:edismax, :qf)
108✔
242
      end
243
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc