BigW Consortium Gitlab

issuable_finder.rb 5.93 KB
Newer Older
1
# IssuableFinder
2 3 4 5 6 7 8 9 10 11 12
#
# Used to filter Issues and MergeRequests collections by set of params
#
# Arguments:
#   klass - actual class like Issue or MergeRequest
#   current_user - which user use
#   params:
#     scope: 'created-by-me' or 'assigned-to-me' or 'all'
#     state: 'open' or 'closed' or 'all'
#     group_id: integer
#     project_id: integer
13
#     milestone_title: string
14 15 16 17 18
#     assignee_id: integer
#     search: string
#     label_name: string
#     sort: string
#
19 20 21
require_relative 'projects_finder'

class IssuableFinder
22
  NONE = '0'
23

24
  attr_accessor :current_user, :params
25

26
  def initialize(current_user, params)
27 28
    @current_user = current_user
    @params = params
29
  end
30

31
  def execute
32 33
    items = init_collection
    items = by_scope(items)
34 35
    items = by_state(items)
    items = by_group(items)
36
    items = by_project(items)
37 38 39
    items = by_search(items)
    items = by_milestone(items)
    items = by_assignee(items)
40
    items = by_author(items)
41
    items = by_label(items)
42
    sort(items)
43 44
  end

45 46 47
  def group
    return @group if defined?(@group)

48
    @group =
49 50
      if params[:group_id].present?
        Group.find(params[:group_id])
51
      else
52 53 54 55
        nil
      end
  end

56 57 58 59
  def project?
    params[:project_id].present?
  end

60 61 62
  def project
    return @project if defined?(@project)

63 64
    if project?
      @project = Project.find(params[:project_id])
65

66 67
      unless Ability.abilities.allowed?(current_user, :read_project, @project)
        @project = nil
68
      end
69 70 71 72 73 74 75 76 77 78
    else
      @project = nil
    end

    @project
  end

  def projects
    return @projects if defined?(@projects)

79
    if project?
80
      @projects = project
81
    elsif current_user && params[:authorized_only].presence && !current_user_related?
82
      @projects = current_user.authorized_projects.reorder(nil)
83 84
    elsif group
      @projects = GroupProjectsFinder.new(group).execute(current_user).reorder(nil)
85
    else
86
      @projects = ProjectsFinder.new.execute(current_user).reorder(nil)
87
    end
88 89 90 91 92 93 94 95 96 97
  end

  def search
    params[:search].presence
  end

  def milestones?
    params[:milestone_title].present?
  end

Douwe Maan committed
98
  def filter_by_no_milestone?
99 100 101
    milestones? && params[:milestone_title] == Milestone::None.title
  end

102 103 104 105
  def milestones
    return @milestones if defined?(@milestones)

    @milestones =
106
      if milestones?
107
        scope = Milestone.where(project_id: projects)
108 109

        scope.where(title: params[:milestone_title])
110 111 112 113 114
      else
        nil
      end
  end

115 116 117 118
  def labels?
    params[:label_name].present?
  end

Douwe Maan committed
119
  def filter_by_no_label?
120 121 122
    labels? && params[:label_name] == Label::None.title
  end

Tap committed
123 124 125 126 127 128 129
  def labels
    return @labels if defined?(@labels)

    if labels? && !filter_by_no_label?
      @labels = Label.where(title: label_names)

      if projects
Tap committed
130
        @labels = @labels.where(project: projects)
Tap committed
131 132 133 134 135 136
      end
    else
      @labels = Label.none
    end
  end

137 138 139 140 141 142 143
  def assignee?
    params[:assignee_id].present?
  end

  def assignee
    return @assignee if defined?(@assignee)

144
    @assignee =
145 146 147 148 149 150 151 152 153 154 155 156 157 158
      if assignee? && params[:assignee_id] != NONE
        User.find(params[:assignee_id])
      else
        nil
      end
  end

  def author?
    params[:author_id].present?
  end

  def author
    return @author if defined?(@author)

159
    @author =
160 161 162 163 164 165 166
      if author? && params[:author_id] != NONE
        User.find(params[:author_id])
      else
        nil
      end
  end

167 168
  private

169
  def init_collection
170
    klass.all
171 172 173
  end

  def by_scope(items)
Douwe Maan committed
174 175
    case params[:scope]
    when 'created-by-me', 'authored'
176
      items.where(author_id: current_user.id)
Douwe Maan committed
177
    when 'assigned-to-me'
178
      items.where(assignee_id: current_user.id)
179
    else
Douwe Maan committed
180
      items
181 182 183 184 185 186 187
    end
  end

  def by_state(items)
    case params[:state]
    when 'closed'
      items.closed
188 189
    when 'merged'
      items.respond_to?(:merged) ? items.merged : items.closed
190 191 192 193 194 195 196 197 198 199
    when 'all'
      items
    when 'opened'
      items.opened
    else
      raise 'You must specify default state'
    end
  end

  def by_group(items)
200
    # Selection by group is already covered by `by_project` and `projects`
201 202 203 204
    items
  end

  def by_project(items)
205
    items =
206 207 208 209
      if project?
        items.of_projects(projects).references_project
      elsif projects
        items.merge(projects.reorder(nil)).join_project
210 211 212
      else
        items.none
      end
213 214 215 216 217

    items
  end

  def by_search(items)
218
    items = items.search(search) if search
219 220 221 222 223

    items
  end

  def sort(items)
224 225 226
    # Ensure we always have an explicit sort order (instead of inheriting
    # multiple orders when combining ActiveRecord::Relation objects).
    params[:sort] ? items.sort(params[:sort]) : items.reorder(id: :desc)
227 228 229
  end

  def by_assignee(items)
230 231
    if assignee?
      items = items.where(assignee_id: assignee.try(:id))
232 233 234 235 236
    end

    items
  end

237
  def by_author(items)
238 239
    if author?
      items = items.where(author_id: author.try(:id))
240 241 242 243 244
    end

    items
  end

tiagonbotelho committed
245
  def filter_by_upcoming_milestone?
246
    params[:milestone_title] == Milestone::Upcoming.name
247 248
  end

249 250
  def by_milestone(items)
    if milestones?
Douwe Maan committed
251
      if filter_by_no_milestone?
252
        items = items.where(milestone_id: [-1, nil])
tiagonbotelho committed
253
      elsif filter_by_upcoming_milestone?
tiagonbotelho committed
254
        upcoming = Milestone.where(project_id: projects).upcoming
Phil Hughes committed
255
        items = items.joins(:milestone).where(milestones: { title: upcoming.try(:title) })
256 257 258 259 260 261 262 263 264 265 266 267
      else
        items = items.joins(:milestone).where(milestones: { title: params[:milestone_title] })

        if projects
          items = items.where(milestones: { project_id: projects })
        end
      end
    end

    items
  end

268
  def by_label(items)
269
    if labels?
Douwe Maan committed
270
      if filter_by_no_label?
271
        items = items.without_label
272
      else
273
        items = items.with_label(label_names)
274

275 276
        if projects
          items = items.where(labels: { project_id: projects })
277
        end
278
      end
279 280 281 282
    end

    items
  end
283

Tap committed
284 285 286 287
  def label_names
    params[:label_name].split(',')
  end

288 289 290
  def current_user_related?
    params[:scope] == 'created-by-me' || params[:scope] == 'authored' || params[:scope] == 'assigned-to-me'
  end
291
end