1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
# frozen_string_literal: true
module Gitlab
# Holds the contextual data used by navbar search component to
# determine the search scope, whether to search for code, or if
# a search should target snippets.
#
# Use the SearchContext::Builder to create an instance of this class
class SearchContext
attr_accessor :project, :project_metadata, :ref,
:group, :group_metadata,
:snippets,
:scope, :search_url
def initialize
@ref = nil
@project = nil
@project_metadata = {}
@group = nil
@group_metadata = {}
@snippets = []
@scope = nil
@search_url = nil
end
def for_project?
project.present? && project.persisted?
end
def for_group?
group.present? && group.persisted?
end
def for_snippets?
snippets.any?
end
def code_search?
project.present? && scope.nil?
end
class Builder
def initialize(view_context)
@view_context = view_context
@snippets = []
end
def with_snippet(snippet)
@snippets << snippet
self
end
def with_project(project)
@project = project
with_group(project&.group)
self
end
def with_group(group)
@group = group
self
end
def with_ref(ref)
@ref = ref
self
end
def build!
SearchContext.new.tap do |context|
context.project = @project
context.group = @group
context.ref = @ref
context.snippets = @snippets.dup
context.scope = search_scope
context.search_url = search_url
context.group_metadata = group_search_metadata(@group)
context.project_metadata = project_search_metadata(@project)
end
end
private
attr_accessor :view_context
def project_search_metadata(project)
return {} unless project
{
project_path: project.path,
name: project.name,
issues_path: view_context.project_issues_path(project),
mr_path: view_context.project_merge_requests_path(project),
issues_disabled: !project.issues_enabled?
}
end
def group_search_metadata(group)
return {} unless group
{
group_path: group.path,
name: group.name,
issues_path: view_context.issues_group_path(group),
mr_path: view_context.merge_requests_group_path(group)
}
end
def search_url
if @project.present?
view_context.search_path(project_id: @project.id)
elsif @group.present?
view_context.search_path(group_id: @group.id)
else
view_context.search_path
end
end
def search_scope
if view_context.current_controller?(:issues)
'issues'
elsif view_context.current_controller?(:merge_requests)
'merge_requests'
elsif view_context.current_controller?(:wikis)
'wiki_blobs'
elsif view_context.current_controller?(:commits)
'commits'
elsif view_context.current_controller?(:groups)
if %w(issues merge_requests).include?(view_context.controller.action_name)
view_context.controller.action_name
end
end
end
end
module ControllerConcern
extend ActiveSupport::Concern
included do
helper_method :search_context
end
# rubocop:disable Gitlab/ModuleWithInstanceVariables
#
# Introspect the current controller's assignments and
# and builds the proper SearchContext object for it.
def search_context
builder = Builder.new(view_context)
builder.with_snippet(@snippet) if @snippet.present?
@snippets.each(&builder.method(:with_snippet)) if @snippets.present?
builder.with_project(@project) if @project.present? && @project.persisted?
builder.with_group(@group) if @group.present? && @group.persisted?
builder.with_ref(@ref) if @ref.present?
builder.build!
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
end
end
end
|