# This is currently being tested without loading most of Rails # so beware of changes that rely on other classes or Rails methods class QueryCleaner attr_reader :params SORT_OPTIONS = [ %w[Creator authors_to_sort_on], %w[Title title_to_sort_on], ['Date Posted', 'created_at'], ['Date Updated', 'revised_at'], ['Word Count', 'word_count'], %w[Hits hits], %w[Kudos kudos_count], %w[Comments comments_count], %w[Bookmarks bookmarks_count] ].freeze def initialize(params = {}) @params = params.dup end def clean return params if params[:query].nil? || params[:query].empty? unescape_angle_brackets extract_countables set_sorting add_quotes_to_categories escape_angle_brackets clean_up_query params end private def unescape_angle_brackets params[:query] = params[:query].gsub('>', '>').gsub('<', '<') end def escape_angle_brackets params[:query] = params[:query].gsub('>', '>').gsub('<', '<') end # extract countable params def extract_countables %w(word kudo comment bookmark hit).each do |term| count_regex = /#{term}s?\s*(?:\_?count)?\s*:?\s*((?:<|>|=|:)\s*\d+(?:\-\d+)?)/i m = params[:query].match(count_regex) next if m.nil? params[:query] = params[:query].gsub(count_regex, '') # pluralize, add _count, convert to symbol term = term.pluralize unless term == 'word' term += '_count' unless term == 'hits' term = term.to_sym value = m[1].gsub(/^(:|=)/, '').strip # get rid of : and = # don't overwrite if submitting from advanced search? params[term] = value if params[term].nil? || params[term].empty? end end # get sort-by def set_sorting sort_regex = /sort(?:ed)?\s*(?:by)?\s*:?\s*(<|>|=|:)\s*(\w+)\s*(ascending|descending)?/i return unless m = params[:query].match(sort_regex) params[:query] = params[:query].gsub(sort_regex, '') sortdir = m[3] || m[1] # turn word_count or word count or words into just "word" eg sortby = m[2].gsub(/\s*_?count/, '').singularize sort_column = SORT_OPTIONS.find { |opt, _| opt =~ /#{sortby}/i }&.last params[:sort_column] = sort_column unless sort_column.nil? params[:sort_direction] = sort_direction(sortdir) end def sort_direction(sortdir) if sortdir == '>' || sortdir == 'ascending' 'asc' elsif sortdir == '<' || sortdir == 'descending' 'desc' end end # put categories into quotes # don't match if the letters are part of larger words (ie, "Tom/Mark") def add_quotes_to_categories qr = Regexp.new('(?:"|\')?') %w(m/m f/f f/m m/f).each do |cat| cr = Regexp.new("(\\A|\\s)#{qr}#{cat}#{qr}(\\z|\\s)", Regexp::IGNORECASE) params[:query] = params[:query].gsub(cr, " \"#{cat}\" ") end end # If we've stripped out everything in the query, null it out def clean_up_query if params[:query] =~ /^\s*$/ params[:query] = nil else params[:query] = params[:query].strip end end end