diff --git a/app/logical/concerns/searchable.rb b/app/logical/concerns/searchable.rb index 3845478a0..d2875c642 100644 --- a/app/logical/concerns/searchable.rb +++ b/app/logical/concerns/searchable.rb @@ -1,7 +1,7 @@ module Searchable extend ActiveSupport::Concern - def negate(kind = :nor) + def negate(kind = :nand) unscoped.where(all.where_clause.invert(kind).ast) end diff --git a/app/logical/post_query_builder.rb b/app/logical/post_query_builder.rb index 296933682..f5db4213c 100644 --- a/app/logical/post_query_builder.rb +++ b/app/logical/post_query_builder.rb @@ -171,6 +171,29 @@ class PostQueryBuilder relation end + def status_matches(status) + case status.downcase + when "pending" + Post.pending + when "flagged" + Post.flagged + when "modqueue" + Post.pending_or_flagged + when "deleted" + Post.deleted + when "banned" + Post.banned + when "active" + Post.active + when "unmoderated" + Post.pending_or_flagged.available_for_moderation + when "all", "any" + Post.all + else + Post.none + end + end + def parent_matches(parent) if parent.downcase == "none" Post.where(parent: nil) @@ -220,16 +243,13 @@ class PostQueryBuilder def hide_deleted_posts?(q) return false if CurrentUser.admin_mode? - return false if q[:status].in?(%w[deleted active any all]) - return false if q[:status_neg].in?(%w[deleted active any all]) + return false if q[:status].to_a.any?(%w[deleted active any all]) + return false if q[:status_neg].to_a.any?(%w[deleted active any all]) return CurrentUser.user.hide_deleted_posts? end def build - unless query_string.is_a?(Hash) - q = PostQueryBuilder.parse_query(query_string) - end - + q = PostQueryBuilder.parse_query(query_string) relation = Post.all if q[:tag_count].to_i > Danbooru.config.tag_query_limit @@ -240,6 +260,10 @@ class PostQueryBuilder relation = relation.where("posts.rating = 's'") end + if hide_deleted_posts?(q) + relation = relation.undeleted + end + relation = add_joins(q, relation) relation = relation.merge(attribute_matches(q[:id], :id)) @@ -264,38 +288,12 @@ class PostQueryBuilder relation = relation.merge(attribute_matches(q[column.to_sym], column.to_sym)) end - if q[:status] == "pending" - relation = relation.where("posts.is_pending = TRUE") - elsif q[:status] == "flagged" - relation = relation.where("posts.is_flagged = TRUE") - elsif q[:status] == "modqueue" - relation = relation.where("posts.is_pending = TRUE OR posts.is_flagged = TRUE") - elsif q[:status] == "deleted" - relation = relation.where("posts.is_deleted = TRUE") - elsif q[:status] == "banned" - relation = relation.where("posts.is_banned = TRUE") - elsif q[:status] == "active" - relation = relation.where("posts.is_pending = FALSE AND posts.is_deleted = FALSE AND posts.is_banned = FALSE AND posts.is_flagged = FALSE") - elsif q[:status] == "unmoderated" - relation = relation.merge(Post.pending_or_flagged.available_for_moderation) - elsif q[:status] == "all" || q[:status] == "any" - # do nothing - elsif q[:status_neg] == "pending" - relation = relation.where("posts.is_pending = FALSE") - elsif q[:status_neg] == "flagged" - relation = relation.where("posts.is_flagged = FALSE") - elsif q[:status_neg] == "modqueue" - relation = relation.where("posts.is_pending = FALSE AND posts.is_flagged = FALSE") - elsif q[:status_neg] == "deleted" - relation = relation.where("posts.is_deleted = FALSE") - elsif q[:status_neg] == "banned" - relation = relation.where("posts.is_banned = FALSE") - elsif q[:status_neg] == "active" - relation = relation.where("posts.is_pending = TRUE OR posts.is_deleted = TRUE OR posts.is_banned = TRUE OR posts.is_flagged = TRUE") + q[:status].to_a.each do |query| + relation = relation.merge(status_matches(query)) end - if hide_deleted_posts?(q) - relation = relation.where("posts.is_deleted = FALSE") + q[:status_neg].to_a.each do |query| + relation = relation.merge(status_matches(query).negate) end if q[:filetype] @@ -1006,10 +1004,12 @@ class PostQueryBuilder # Do nothing. The controller takes care of it. when "-status" - q[:status_neg] = g2.downcase + q[:status_neg] ||= [] + q[:status_neg] << g2 when "status" - q[:status] = g2.downcase + q[:status] ||= [] + q[:status] << g2 when "embedded" q[:embedded] = g2.downcase diff --git a/app/models/post.rb b/app/models/post.rb index 8c5787085..fbda12343 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -60,6 +60,8 @@ class Post < ApplicationRecord scope :pending, -> { where(is_pending: true) } scope :flagged, -> { where(is_flagged: true) } + scope :banned, -> { where(is_banned: true) } + scope :active, -> { where(is_pending: false, is_deleted: false, is_flagged: false) } scope :pending_or_flagged, -> { pending.or(flagged) } scope :unflagged, -> { where(is_flagged: false) } diff --git a/test/unit/post_query_builder_test.rb b/test/unit/post_query_builder_test.rb index 6ccaac141..74be93823 100644 --- a/test/unit/post_query_builder_test.rb +++ b/test/unit/post_query_builder_test.rb @@ -452,7 +452,8 @@ class PostQueryBuilderTest < ActiveSupport::TestCase assert_tag_match([flagged], "status:flagged") assert_tag_match([deleted], "status:deleted") assert_tag_match([banned], "status:banned") - assert_tag_match([], "status:active") + assert_tag_match([banned], "status:active") + assert_tag_match([banned], "status:active status:banned") assert_tag_match(all, "status:any") assert_tag_match(all, "status:all") @@ -461,7 +462,10 @@ class PostQueryBuilderTest < ActiveSupport::TestCase assert_tag_match(all - [flagged], "-status:flagged") assert_tag_match(all - [deleted], "-status:deleted") assert_tag_match(all - [banned], "-status:banned") - assert_tag_match(all, "-status:active") + assert_tag_match(all - [banned], "-status:active") + + assert_tag_match([], "status:garbage") + assert_tag_match(all, "-status:garbage") end should "return posts for the status:unmoderated metatag" do