From fef90b46eed838d82e6663e4a0eafc6a39019ca6 Mon Sep 17 00:00:00 2001 From: evazion Date: Mon, 20 Apr 2020 04:07:59 -0500 Subject: [PATCH] search: clean up filetype: metatag. * Fix not being able to use the filetype: metatag twice in the same search. * Support comma-separated filetypes (filetype:png,jpg). --- app/logical/concerns/searchable.rb | 2 +- app/logical/post_query_builder.rb | 32 +++++++++++++++++----------- test/unit/post_query_builder_test.rb | 4 ++++ 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/app/logical/concerns/searchable.rb b/app/logical/concerns/searchable.rb index d2875c642..ba121cbf4 100644 --- a/app/logical/concerns/searchable.rb +++ b/app/logical/concerns/searchable.rb @@ -265,7 +265,7 @@ module Searchable def apply_default_order(params) if params[:order] == "custom" - parse_ids = PostQueryBuilder.parse_range(params[:id]) + parse_ids = PostQueryBuilder.parse_range(params[:id], :integer) if parse_ids[0] == :in return find_ordered(parse_ids[1]) end diff --git a/app/logical/post_query_builder.rb b/app/logical/post_query_builder.rb index f5db4213c..0788186d2 100644 --- a/app/logical/post_query_builder.rb +++ b/app/logical/post_query_builder.rb @@ -93,7 +93,7 @@ class PostQueryBuilder def attribute_matches(values, field, type = :integer) values.to_a.reduce(Post.all) do |relation, value| - operator, *args = PostQueryBuilder.parse_range(value, type) + operator, *args = PostQueryBuilder.parse_metatag_value(value, type) relation.where_operator(field, operator, *args) end end @@ -280,6 +280,9 @@ class PostQueryBuilder relation = relation.merge(attribute_matches(q[:pixiv_id], :pixiv_id)) relation = relation.merge(attribute_matches(q[:post_tag_count], :tag_count)) + relation = relation.merge(attribute_matches(q[:filetype], :file_ext, :enum)) + relation = relation.merge(attribute_matches(q[:filetype_neg], :file_ext, :enum).negate(:nor)) if q[:filetype_neg].present? + TagCategory.categories.each do |category| relation = relation.merge(attribute_matches(q["#{category}_tag_count".to_sym], "tag_count_#{category}".to_sym)) end @@ -296,14 +299,6 @@ class PostQueryBuilder relation = relation.merge(status_matches(query).negate) end - if q[:filetype] - relation = relation.where("posts.file_ext": q[:filetype]) - end - - if q[:filetype_neg] - relation = relation.where.not("posts.file_ext": q[:filetype_neg]) - end - if q[:source] if q[:source] == "none" relation = relation.where_like(:source, '') @@ -1015,10 +1010,12 @@ class PostQueryBuilder q[:embedded] = g2.downcase when "filetype" - q[:filetype] = g2.downcase + q[:filetype] ||= [] + q[:filetype] << g2 when "-filetype" - q[:filetype_neg] = g2.downcase + q[:filetype_neg] ||= [] + q[:filetype_neg] << g2 when "pixiv_id", "pixiv" q[:pixiv_id] ||= [] @@ -1100,6 +1097,9 @@ class PostQueryBuilder def parse_cast(object, type) case type + when :enum + object.to_s.downcase + when :integer object.to_i @@ -1143,7 +1143,15 @@ class PostQueryBuilder end end - def parse_range(string, type = :integer) + def parse_metatag_value(string, type) + if type == :enum + [:in, string.split(/[, ]+/).map { |x| parse_cast(x, type) }] + else + parse_range(string, type) + end + end + + def parse_range(string, type) range = case string when /\A(.+?)\.\.\.(.+)/ # A...B lo, hi = [parse_cast($1, type), parse_cast($2, type)].sort diff --git a/test/unit/post_query_builder_test.rb b/test/unit/post_query_builder_test.rb index 74be93823..50a7592f3 100644 --- a/test/unit/post_query_builder_test.rb +++ b/test/unit/post_query_builder_test.rb @@ -496,6 +496,10 @@ class PostQueryBuilderTest < ActiveSupport::TestCase assert_tag_match([png], "filetype:png") assert_tag_match([jpg], "-filetype:png") + assert_tag_match([jpg, png], "filetype:png,jpg") + assert_tag_match([], "filetype:png filetype:jpg") + assert_tag_match([], "-filetype:png -filetype:jpg") + assert_tag_match([], "filetype:garbage") end should "return posts for the tagcount: metatags" do