Commit 7b52ec04 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Extract author filtering from issuable finder

This moves author filtering related code to a separate class
parent 2bfb648a
......@@ -47,6 +47,7 @@ class IssuableFinder
NEGATABLE_PARAMS_HELPER_KEYS = %i[project_id scope status include_subgroups].freeze
attr_accessor :current_user, :params
attr_reader :original_params
attr_writer :parent
delegate(*%i[assignee milestones], to: :params)
......@@ -101,6 +102,7 @@ class IssuableFinder
def initialize(current_user, params = {})
@current_user = current_user
@original_params = params
@params = params_class.new(params, current_user, klass)
end
......@@ -142,7 +144,7 @@ class IssuableFinder
end
def should_filter_negated_args?
return false unless Feature.enabled?(:not_issuable_queries, params.group || params.project, default_enabled: true)
return false unless not_filters_enabled?
# API endpoints send in `nil` values so we test if there are any non-nil
not_params.present? && not_params.values.any?
......@@ -150,7 +152,6 @@ class IssuableFinder
# Negates all params found in `negatable_params`
def filter_negated_items(items)
items = by_negated_author(items)
items = by_negated_assignee(items)
items = by_negated_label(items)
items = by_negated_milestone(items)
......@@ -372,31 +373,13 @@ class IssuableFinder
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def by_author(items)
if params.author
items.where(author_id: params.author.id)
elsif params.no_author?
items.where(author_id: nil)
elsif params.author_id? || params.author_username? # author not found
items.none
else
items
end
Issuables::AuthorFilter.new(
items,
params: original_params,
not_filters_enabled: not_filters_enabled?
).filter
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def by_negated_author(items)
if not_params.author
items.where.not(author_id: not_params.author.id)
elsif not_params.author_id? || not_params.author_username? # author not found
items.none
else
items
end
end
# rubocop: enable CodeReuse/ActiveRecord
def by_assignee(items)
if params.filter_by_no_assignee?
......@@ -514,4 +497,14 @@ class IssuableFinder
def by_non_archived(items)
params[:non_archived].present? ? items.non_archived : items
end
def not_filters_enabled?
strong_memoize(:not_filters_enabled) do
Feature.enabled?(:not_issuable_queries, feature_flag_scope, default_enabled: :yaml)
end
end
def feature_flag_scope
params.group || params.project
end
end
......@@ -27,19 +27,6 @@ class IssuableFinder
params.present?
end
def author_id?
params[:author_id].present? && params[:author_id] != NONE
end
def author_username?
params[:author_username].present? && params[:author_username] != NONE
end
def no_author?
# author_id takes precedence over author_username
params[:author_id] == NONE || params[:author_username] == NONE
end
def filter_by_no_assignee?
params[:assignee_id].to_s.downcase == FILTER_NONE
end
......@@ -169,20 +156,6 @@ class IssuableFinder
end
end
# rubocop: disable CodeReuse/ActiveRecord
def author
strong_memoize(:author) do
if author_id?
User.find_by(id: params[:author_id])
elsif author_username?
User.find_by_username(params[:author_username])
else
nil
end
end
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def assignees
strong_memoize(:assignees) do
......
module Issuables
class AuthorFilter < BaseFilter
def filter
filtered = by_author(issuables)
by_negated_author(filtered)
end
private
def by_author(issuables)
if no_author?
issuables.where(author_id: nil)
elsif params[:author_id].present?
issuables.where(author_id: params[:author_id])
elsif params[:author_username].present?
issuables.where(author_id: authors_by_username(params[:author_username]))
else
issuables
end
end
def by_negated_author(issuables)
return issuables unless not_params.present? && not_filters_enabled?
if not_params[:author_id].present?
issuables.where.not(author_id: not_params[:author_id])
elsif not_params[:author_username].present?
issuables.where.not(author_id: authors_by_username(not_params[:author_username]))
else
issuables
end
end
def no_author?
# author_id takes precedence over author_username
params[:author_id] == NONE || params[:author_username] == NONE
end
def authors_by_username(usernames)
User.where(username: usernames)
end
end
end
module Issuables
class BaseFilter
# This is used as a common filter for None / Any
FILTER_NONE = 'none'
FILTER_ANY = 'any'
# This is used in unassigning users
NONE = '0'
attr_reader :issuables, :params
def initialize(issuables, params:, not_filters_enabled: false)
@issuables = issuables
@params = params
@not_filters_enabled = not_filters_enabled
end
def filter
raise NotImplementedError
end
private
def not_params
params[:not]
end
def not_filters_enabled?
@not_filters_enabled
end
end
end
......@@ -25,6 +25,7 @@
class EpicsFinder < IssuableFinder
include TimeFrameFilter
include Gitlab::Utils::StrongMemoize
extend ::Gitlab::Utils::Override
IID_STARTS_WITH_PATTERN = %r{\A(\d)+\z}.freeze
......@@ -123,13 +124,12 @@ class EpicsFinder < IssuableFinder
end
def filter_negated_items(items)
return items unless Feature.enabled?(:not_issuable_queries, group, default_enabled: true)
return items unless not_filters_enabled?
# API endpoints send in `nil` values so we test if there are any non-nil
return items unless not_params&.values&.any?
items = by_negated_label(items)
by_negated_author(items)
by_negated_label(items)
end
def group
......@@ -242,4 +242,9 @@ class EpicsFinder < IssuableFinder
def group_projects
Project.in_namespace(permissioned_related_groups).with_issues_available_for_user(current_user)
end
override :feature_flag_scope
def feature_flag_scope
group
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment