otwarchive-symphonyarchive/app/models/search/bookmark_search_form.rb
2026-03-11 22:22:11 +00:00

200 lines
5.1 KiB
Ruby

class BookmarkSearchForm
extend ActiveModel::Naming
include ActiveModel::Conversion
include ActiveModel::Validations
ATTRIBUTES = [
:bookmark_query,
:bookmarkable_query,
:rec,
:bookmark_notes,
:with_notes,
:date,
:show_private,
:pseud_ids,
:user_ids,
:bookmarker,
:bookmarkable_pseud_names,
:bookmarkable_pseud_ids,
:bookmarkable_type,
:language_id,
:excluded_tag_names,
:excluded_bookmark_tag_names,
:excluded_tag_ids,
:excluded_bookmark_tag_ids,
:other_tag_names,
:other_bookmark_tag_names,
:tag_ids,
:filter_ids,
:filter_names,
:fandom_ids,
:character_ids,
:relationship_ids,
:freeform_ids,
:rating_ids,
:archive_warning_ids,
:category_ids,
:bookmarkable_title,
:bookmarkable_date,
:bookmarkable_complete,
:collection_ids,
:bookmarkable_collection_ids,
:sort_column,
:show_restricted,
:page,
:faceted
]
attr_accessor :options
ATTRIBUTES.each do |filterable|
define_method(filterable) { options[filterable] }
end
def initialize(options = {})
@options = processed_options(options)
@searcher = BookmarkQuery.new(@options)
end
def persisted?
false
end
# This is used by SearchHelper.search_header.
def query
queries = []
%w[bookmarkable_query bookmark_query].each do |key|
queries << options[key] if options[key].present?
end
queries.join(', ')
end
def summary
summary = []
%w[bookmarkable_query bookmark_query].each do |key|
if options[key].present?
summary << options[key]
end
end
if options[:bookmarker].present?
summary << "Bookmarker: #{options[:bookmarker]}"
end
if options[:notes].present?
summary << "Notes: #{options[:notes]}"
end
tags = []
%w[other_tag_names other_bookmark_tag_names].each do |key|
if options[key].present?
tags << options[key]
end
end
all_tag_ids = []
[:filter_ids, :fandom_ids, :rating_ids, :category_ids, :archive_warning_ids, :character_ids, :relationship_ids, :freeform_ids].each do |tag_ids|
if options[tag_ids].present?
all_tag_ids += options[tag_ids]
end
end
unless all_tag_ids.empty?
tags << Tag.where(id: all_tag_ids).pluck(:name).join(", ")
end
unless tags.empty?
summary << "Tags: #{tags.uniq.join(", ")}"
end
if self.bookmarkable_type.present?
summary << "Type: #{self.bookmarkable_type}"
end
if self.language_id.present?
language = Language.find_by(short: self.language_id)
if language.present?
summary << "Work language: <span lang=#{language.short}>#{language.name}</span>"
end
end
if %w(1 true).include?(self.rec.to_s)
summary << "Rec"
end
if %w(1 true).include?(self.with_notes.to_s)
summary << "With Notes"
end
[:date, :bookmarkable_date].each do |countable|
if options[countable].present?
desc = (countable == :date) ? "Date bookmarked" : "Date updated"
summary << "#{desc}: #{options[countable]}"
end
end
summary.join(", ")
end
def search_results
@searcher.search_results
end
# Special function for returning the BookmarkableQuery results (instead of
# the BookmarkQuery results).
def bookmarkable_search_results
@searcher.bookmarkable_query.search_results
end
###############
# SORTING
###############
def sort_options
[
['Date Bookmarked', 'created_at'],
['Date Updated', 'bookmarkable_date'],
]
end
def sort_values
sort_options.map{ |option| option.last }
end
def sort_direction(sort_column)
'desc'
end
private
def processed_options(opts = {})
[:date, :bookmarkable_date].each do |countable|
if opts[countable].present?
opts[countable] = opts[countable].gsub("&gt;", ">").
gsub("&lt;", "<")
end
end
# If we call the form field 'notes', the parser adds html to it
opts[:notes] = opts[:bookmark_notes]
opts = standardize_language_ids(opts)
# Support legacy warning searches
if opts[:warning_ids].present?
opts[:archive_warning_ids] = opts.delete(:warning_ids)
end
# We need to respect some options that are deliberately set to false, and
# false.blank? is true, so we check for nil? and not blank? here.
opts.delete_if { |_, v| v.nil? }
end
# Maintain backward compatibility for old bookmark searches/filters:
def standardize_language_ids(opts)
# - Using language IDs in the "Work language" dropdown
if opts[:language_id].present? && opts[:language_id].to_i != 0
language = Language.find_by(id: opts[:language_id])
opts[:language_id] = language.short if language.present?
end
# - Using language IDs in "Any field on work" (search) or "Search within results" (filters)
if opts[:bookmarkable_query].present?
opts[:bookmarkable_query] = opts[:bookmarkable_query].gsub(/\blanguage_id\s*:\s*(\d+)/) do
lang = Language.find_by(id: Regexp.last_match[1])
lang = Language.default if lang.blank?
"language_id: " + lang.short
end
end
opts
end
end