Skip to content

Commit

Permalink
Merge pull request #322 from pulibrary/issues-218-jrgriffiniii-search…
Browse files Browse the repository at this point in the history
…-quotes-fix

Ensuring that quotes are properly escaped within the dismax parameters for joining on child resource Documents
  • Loading branch information
escowles authored Feb 21, 2018
2 parents cafbdc0 + 5504e82 commit 86671ba
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 3 deletions.
13 changes: 11 additions & 2 deletions app/models/search_builder.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
# Class for extending the default Blacklight builder for Solr queries
# @see https://github.com/projectblacklight/blacklight/wiki/Extending-or-Modifying-Blacklight-Search-Behavior
class SearchBuilder < Blacklight::SearchBuilder
include Blacklight::Solr::SearchBuilderBehavior
include Spotlight::AccessControlsEnforcementSearchBuilder

self.default_processor_chain += [:hide_parented_resources, :join_from_parent]
# Names for methods invoked when the Solr query is being built
self.default_processor_chain += %i(hide_parented_resources join_from_parent)

# Modifies the filter query in the Solr parameters to hide collections from being returned for all items in search results
# @see https://lucene.apache.org/solr/guide/6_6/common-query-parameters.html#CommonQueryParameters-Thefq_FilterQuery_Parameter
# @param solr_params [Blacklight::Solr::Request] the Solr query parameters being modified
def hide_parented_resources(solr_params)
solr_params[:fq] ||= []
solr_params[:fq] << "!#{Spotlight::Resources::Iiif::Engine.config.collection_id_field}:['' TO *]"
end

# Modifies the Solr query in order to retrieve child resources for all collections within search results
# @param solr_params [Blacklight::Solr::Request] the Solr query parameters being modified
def join_from_parent(solr_params)
solr_params[:q] = JoinChildrenQuery.new(solr_params[:q]).to_s
parent_query = solr_params[:q]
solr_params[:q] = JoinChildrenQuery.new(parent_query).to_s
end
end
18 changes: 17 additions & 1 deletion app/models/search_builder/join_children_query.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
class SearchBuilder
# Models Solr join queries for retrieving Documents modeling children of collections
class JoinChildrenQuery
attr_reader :parent_query
# Constructor
# @param parent_query [String] the query string from the client
def initialize(parent_query)
@parent_query = parent_query
end

# Generates the query string
# @return [String]
def to_s
return parent_query if parent_query.to_s.start_with?("{!lucene}")
q = queries.map do |query|
Expand All @@ -15,21 +20,32 @@ def to_s

private

# Method names used to generate the query string
# @return [Array<Symbol>] method names
def queries
[
:main_query,
:query_children
]
end

# Generates a disjunction max (dismax) join query string on the IDs of Documents modeling child resources of collections
# @param query [String] dismax query used for the join
# @return [String] the query string
def dismax_join(query)
"#{query}{!dismax}#{parent_query}"
cleaned_parent_query = parent_query.nil? ? "" : parent_query.gsub(/"/, '\"')
"#{query}{!dismax}#{cleaned_parent_query}"
end

# Primary dismax query string
# (This is meant to be overridden)
# @return [String]
def main_query
""
end

# Dismax query string joining collection_id_ssim on IDs for Solr Documents
# @return [String]
def query_children
"{!join from=collection_id_ssim to=id}"
end
Expand Down
17 changes: 17 additions & 0 deletions spec/controllers/catalog_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,23 @@

get :index, params: { q: "", exhibit_id: exhibit.id }

expect(document_ids).not_to be_empty
end
it "permits queries with quotes" do
exhibit = Spotlight::Exhibit.create title: 'Exhibit A', published: true
document = SolrDocument.new(id: 'd279a557a62937a8895eebbca2d4744c', exhibit: exhibit)
Spotlight::SolrDocumentSidecar.create!(
document: document, exhibit: exhibit,
data: { 'full_title_tesim' => ['"title1"'] }
)

document.make_private!(exhibit)
document.save
Blacklight.default_index.connection.commit
sign_in user

get :index, params: { q: '"title1"', exhibit_id: exhibit.id }

expect(document_ids).not_to be_empty
end
end
Expand Down
89 changes: 89 additions & 0 deletions spec/features/catalog_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
require 'rails_helper'

RSpec.feature 'Catalog', type: :feature do
let(:exhibit) { FactoryBot.create(:exhibit) }
let(:id) { 'd279a557a62937a8895eebbca2d4744c' }
let(:title) { 'Panoramic alphabet of peace' }
let(:rights) { 'http://rightsstatements.org/vocab/NKC/1.0/' }
let(:document) do
SolrDocument.new(
id: id,
readonly_title_tesim: [
title
],
'exhibit_abc_books_readonly_edm-rights_ssim': [
rights
],
'readonly_edm-rights_tesim': [
rights
],
exhibit_abc_books_readonly_license_ssim: [
rights
],
readonly_license_tesim: [
rights
],
access_identifier_ssim: [
"1r66j4408"
],
full_title_tesim: [
title
],
readonly_title_ssim: [
title
],
'readonly_title-sort_ssim': [
title
],
'readonly_edm-rights_ssim': [
rights
],
readonly_license_ssim: [
rights
],
_version_: 159,
timestamp: "2018-02-19T22:19:52.244Z"
)
end

context 'logged in as a site admin.' do
let(:user) { FactoryBot.create(:site_admin, exhibit: exhibit) }

before do
sign_in user
document.make_public! exhibit
document.reindex
Blacklight.default_index.connection.commit
end

scenario 'user searches for a collections with a keyword' do
visit spotlight.search_exhibit_catalog_path(exhibit, search_field: 'all_fields', q: id)
expect(page).to have_css '#documents .document h3.index_title', text: id
end

context 'when the document has metadata attributes with quotes' do
before do
exhibit2 = Spotlight::Exhibit.create title: 'Exhibit B', published: true
document2 = SolrDocument.new(id: 'd279a557a62937a8895eebbca2d4744c', exhibit: exhibit)
Spotlight::SolrDocumentSidecar.create!(
document: document2, exhibit: exhibit2,
data: { 'full_title_tesim' => ['"title1"'] }
)
document2.make_private!(exhibit2)
document2.save
Blacklight.default_index.connection.commit
end

scenario 'user searches for a collections with a keyword in quotes' do
visit spotlight.search_exhibit_catalog_path(exhibit, search_field: 'all_fields', q: '"title1"')
expect(page).to have_css '#documents .document h3.index_title', text: '"title1"'
end
end

scenario 'user browses all collections' do
visit spotlight.search_exhibit_catalog_path(exhibit, search_field: 'all_fields', q: '')
expect(page).to have_link 'Home', href: '/exhibit-title-2'
expect(page).to have_css '#documents .document h3.index_title', text: id
end
end
end

0 comments on commit 86671ba

Please sign in to comment.