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

pulibrary / orangelight / 4e01fe00-694b-47b4-8b30-2de4dc4acc66

31 Jul 2025 07:56PM UTC coverage: 92.891% (-2.5%) from 95.4%
4e01fe00-694b-47b4-8b30-2de4dc4acc66

Pull #4962

circleci

web-flow
Merge pull request #5130 from pulibrary/clean_up_scss_comments

Remove SCSS commented code.
Pull Request #4962: Orangelight pos workcycle 07-07-2025

193 of 197 new or added lines in 24 files covered. (97.97%)

161 existing lines in 35 files now uncovered.

5932 of 6386 relevant lines covered (92.89%)

1443.08 hits per line

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

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

3
require 'library_stdnums'
2✔
4

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

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

13
  def linked_record_field?(field)
2✔
14
    field[:link_field]
717✔
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)
2✔
21
    return unless left_anchor_search?(solr_parameters)
165✔
22
    solr_parameters.dig('json', 'query', 'bool').each_value do |value|
79✔
23
      value.select { |boolean_query| boolean_query_searches_left_anchored_field?(boolean_query) }.map! do |clause|
170✔
24
        query = escape_left_anchor_query(clause.dig(:edismax, :query).dup)
35✔
25
        query = add_wildcard(query)
35✔
26
        clause.dig(:edismax)[:query] = query
35✔
27
      end
28
    end
29
  end
30

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

38
    true
79✔
39
  end
40

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

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

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

61
  def series_title_results(solr_parameters)
2✔
62
    return unless includes_series_search?
165✔
63
    solr_parameters[:fl] = 'id,score,author_display,marc_relator_display,format,pub_created_display,'\
4✔
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?
2✔
69
    blacklight_params['clause'].map { |clause| clause[1]["field"] }.include?('series_title' || 'in_series') if blacklight_params['clause'].present?
254✔
70
  end
71

72
  # only fetch facets when an html page is requested
73
  def html_facets(solr_parameters)
2✔
74
    return if blacklight_params[:format].nil? || blacklight_params[:format] == 'html' ||
165✔
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)
2✔
81
    if blacklight_params && blacklight_params[:q].present?
165✔
82
      q_str = blacklight_params[:q]
52✔
83
      number_of_unigrams = cjk_unigrams_size(q_str)
52✔
84
      if number_of_unigrams > 2
52✔
85
        num_non_cjk_tokens = q_str.scan(/[[:alnum]]+/).size
1✔
86
        if num_non_cjk_tokens.positive?
1✔
UNCOV
87
          lower_limit = cjk_mm_val[0].to_i
×
UNCOV
88
          mm = (lower_limit + num_non_cjk_tokens).to_s + cjk_mm_val[1, cjk_mm_val.size]
×
UNCOV
89
          solr_parameters['mm'] = mm
×
90
        else
91
          solr_parameters['mm'] = cjk_mm_val
1✔
92
        end
93
      end
94
    end
95
  end
96

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

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

109
  def browse_related_name_hash(name)
2✔
110
    link_to(name, "/?f[author_s][]=#{CGI.escape name}", class: 'search-related-name', 'data-original-title' => "Search: #{name}") + '  ' +
266✔
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)
2✔
117
    options = args.extract_options!
93✔
118
    document = args.first
93✔
119
    tag = options.fetch(:tag, :h4)
93✔
120
    document ||= @document
93✔
121
    content_tag(tag, document_presenter(document).heading, itemprop: "name", lang: language_iana)
93✔
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)
2✔
130
    render partial: 'show_header_default'
93✔
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)
2✔
UNCOV
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)
2✔
144
    child = "<span class=\"icon-refresh\" aria-hidden=\"true\"></span> <span>#{t('blacklight.search.start_over')}</span>"
277✔
145
    link_to(child.html_safe, path, class: 'catalog_startOverLink btn btn-primary', id: 'startOverLink')
277✔
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)
2✔
152
    child = "<span class=\"icon-cite\" aria-hidden=\"true\"></span> #{t('blacklight.search.cite')}"
80✔
153
    link_to(child.html_safe, path, id: 'citeLink', data: { blacklight_modal: 'trigger' }, class: 'btn btn-default')
80✔
154
  end
155

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

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

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

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

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

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

228
  def link_back_to_catalog_safe(opts = { label: nil })
2✔
UNCOV
229
    link_back_to_catalog(opts)
×
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.
UNCOV
235
    link_to "Back to search", root_url
×
236
  end
237

238
    private
2✔
239

240
      def boolean_query_searches_left_anchored_field?(boolean_query)
2✔
241
        ["${left_anchor_qf}", "${in_series_qf}"].include? boolean_query.dig(:edismax, :qf)
178✔
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