@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class PhabricatorRepositorySearchEngine
4 extends PhabricatorApplicationSearchEngine {
5
6 public function getResultTypeDescription() {
7 return pht('Repositories');
8 }
9
10 public function getApplicationClassName() {
11 return PhabricatorDiffusionApplication::class;
12 }
13
14 public function newQuery() {
15 return id(new PhabricatorRepositoryQuery())
16 ->needProjectPHIDs(true)
17 ->needCommitCounts(true)
18 ->needMostRecentCommits(true)
19 ->needProfileImage(true);
20 }
21
22 protected function buildCustomSearchFields() {
23 return array(
24 id(new PhabricatorSearchStringListField())
25 ->setLabel(pht('Callsigns'))
26 ->setKey('callsigns')
27 ->setDescription(
28 pht('Search for repositories with specific callsigns.')),
29 id(new PhabricatorSearchStringListField())
30 ->setLabel(pht('Short Names'))
31 ->setKey('shortNames')
32 ->setDescription(
33 pht('Search for repositories with specific short names.')),
34 id(new PhabricatorSearchSelectField())
35 ->setLabel(pht('Status'))
36 ->setKey('status')
37 ->setDescription(
38 pht('Search for repositories with a specific status.'))
39 ->setOptions($this->getStatusOptions()),
40 id(new PhabricatorSearchSelectField())
41 ->setLabel(pht('Hosted'))
42 ->setKey('hosted')
43 ->setDescription(
44 pht('Search for repositories which are hosted or remote.'))
45 ->setOptions($this->getHostedOptions()),
46 id(new PhabricatorSearchCheckboxesField())
47 ->setLabel(pht('Types'))
48 ->setKey('types')
49 ->setDescription(
50 pht('Search for repositories of a specific VCS type.'))
51 ->setOptions(PhabricatorRepositoryType::getAllRepositoryTypes()),
52 id(new PhabricatorSearchStringListField())
53 ->setLabel(pht('URIs'))
54 ->setKey('uris')
55 ->setDescription(
56 pht('Search for repositories by clone/checkout URI.')),
57 id(new PhabricatorPHIDsSearchField())
58 ->setLabel(pht('Services'))
59 ->setKey('almanacServicePHIDs')
60 ->setDescription(
61 pht('Search for repositories with a specific Almanac Service.'))
62 ->setAliases(
63 array(
64 'almanacServicePHID',
65 'almanacService',
66 'almanacServices',
67 )),
68 );
69 }
70
71 protected function buildQueryFromParameters(array $map) {
72 $query = $this->newQuery();
73
74 if ($map['callsigns']) {
75 $query->withCallsigns($map['callsigns']);
76 }
77
78 if ($map['shortNames']) {
79 $query->withSlugs($map['shortNames']);
80 }
81
82 if ($map['status']) {
83 $status = idx($this->getStatusValues(), $map['status']);
84 if ($status) {
85 $query->withStatus($status);
86 }
87 }
88
89 if ($map['hosted']) {
90 $hosted = idx($this->getHostedValues(), $map['hosted']);
91 if ($hosted) {
92 $query->withHosted($hosted);
93 }
94 }
95
96 if ($map['types']) {
97 $query->withTypes($map['types']);
98 }
99
100 if ($map['uris']) {
101 $query->withURIs($map['uris']);
102 }
103
104 if ($map['almanacServicePHIDs']) {
105 $query->withAlmanacServicePHIDs($map['almanacServicePHIDs']);
106 }
107
108 return $query;
109 }
110
111 protected function getURI($path) {
112 return '/diffusion/'.$path;
113 }
114
115 protected function getBuiltinQueryNames() {
116 $names = array(
117 'active' => pht('Active Repositories'),
118 'all' => pht('All Repositories'),
119 );
120
121 return $names;
122 }
123
124 public function buildSavedQueryFromBuiltin($query_key) {
125
126 $query = $this->newSavedQuery();
127 $query->setQueryKey($query_key);
128
129 switch ($query_key) {
130 case 'active':
131 return $query->setParameter('status', 'open');
132 case 'all':
133 return $query;
134 }
135
136 return parent::buildSavedQueryFromBuiltin($query_key);
137 }
138
139 private function getStatusOptions() {
140 return array(
141 '' => pht('Active and Inactive Repositories'),
142 'open' => pht('Active Repositories'),
143 'closed' => pht('Inactive Repositories'),
144 );
145 }
146
147 private function getStatusValues() {
148 return array(
149 '' => PhabricatorRepositoryQuery::STATUS_ALL,
150 'open' => PhabricatorRepositoryQuery::STATUS_OPEN,
151 'closed' => PhabricatorRepositoryQuery::STATUS_CLOSED,
152 );
153 }
154
155 private function getHostedOptions() {
156 return array(
157 '' => pht('Hosted and Remote Repositories'),
158 'phabricator' => pht('Hosted Repositories'),
159 'remote' => pht('Remote Repositories'),
160 );
161 }
162
163 private function getHostedValues() {
164 return array(
165 '' => PhabricatorRepositoryQuery::HOSTED_ALL,
166 'phabricator' => PhabricatorRepositoryQuery::HOSTED_PHABRICATOR,
167 'remote' => PhabricatorRepositoryQuery::HOSTED_REMOTE,
168 );
169 }
170
171 protected function getRequiredHandlePHIDsForResultList(
172 array $repositories,
173 PhabricatorSavedQuery $query) {
174 return array_mergev(mpull($repositories, 'getProjectPHIDs'));
175 }
176
177 /**
178 * @param array<PhabricatorRepository> $repositories
179 * @param PhabricatorSavedQuery $query
180 * @param array<PhabricatorObjectHandle> $handles
181 */
182 protected function renderResultList(
183 array $repositories,
184 PhabricatorSavedQuery $query,
185 array $handles) {
186 assert_instances_of($repositories, PhabricatorRepository::class);
187
188 $viewer = $this->requireViewer();
189
190 $list = new PHUIObjectItemListView();
191 foreach ($repositories as $repository) {
192 $id = $repository->getID();
193
194 $item = id(new PHUIObjectItemView())
195 ->setViewer($viewer)
196 ->setObject($repository)
197 ->setHeader($repository->getName())
198 ->setObjectName($repository->getMonogram())
199 ->setHref($repository->getURI())
200 ->setImageURI($repository->getProfileImageURI());
201
202 $commit = $repository->getMostRecentCommit();
203 if ($commit) {
204 $commit_link = phutil_tag(
205 'a',
206 array(
207 'href' => $commit->getURI(),
208 ),
209 pht(
210 '%s: %s',
211 $commit->getLocalName(),
212 $commit->getSummary()));
213
214 $item->setSubhead($commit_link);
215 $item->setEpoch($commit->getEpoch());
216 }
217
218 $item->addIcon(
219 'none',
220 PhabricatorRepositoryType::getNameForRepositoryType(
221 $repository->getVersionControlSystem()));
222
223 $size = $repository->getCommitCount();
224 if ($size) {
225 $history_uri = $repository->generateURI(
226 array(
227 'action' => 'history',
228 ));
229
230 $item->addAttribute(
231 phutil_tag(
232 'a',
233 array(
234 'href' => $history_uri,
235 ),
236 pht('%s Commit(s)', new PhutilNumber($size))));
237 } else {
238 $item->addAttribute(pht('No Commits'));
239 }
240
241 $project_handles = array_select_keys(
242 $handles,
243 $repository->getProjectPHIDs());
244 if ($project_handles) {
245 $item->addAttribute(
246 id(new PHUIHandleTagListView())
247 ->setSlim(true)
248 ->setHandles($project_handles));
249 }
250
251 if (!$repository->isTracked()) {
252 $item->setDisabled(true);
253 $item->addIcon('disable-grey', pht('Inactive'));
254 } else if ($repository->isImporting()) {
255 $item->addIcon('fa-clock-o indigo', pht('Importing...'));
256 }
257
258 $list->addItem($item);
259 }
260
261 $result = new PhabricatorApplicationSearchResultView();
262 $result->setObjectList($list);
263 $result->setNoDataString(pht('No repositories found for this query.'));
264
265 return $result;
266 }
267
268 protected function willUseSavedQuery(PhabricatorSavedQuery $saved) {
269 $project_phids = $saved->getParameter('projectPHIDs', array());
270
271 $old = $saved->getParameter('projects', array());
272 foreach ($old as $phid) {
273 $project_phids[] = $phid;
274 }
275
276 $any = $saved->getParameter('anyProjectPHIDs', array());
277 foreach ($any as $project) {
278 $project_phids[] = 'any('.$project.')';
279 }
280
281 $saved->setParameter('projectPHIDs', $project_phids);
282 }
283
284 protected function getNewUserBody() {
285
286 $new_button = id(new PHUIButtonView())
287 ->setTag('a')
288 ->setText(pht('New Repository'))
289 ->setHref('/diffusion/edit/')
290 ->setColor(PHUIButtonView::GREEN);
291
292 $icon = $this->getApplication()->getIcon();
293 $app_name = $this->getApplication()->getName();
294 $view = id(new PHUIBigInfoView())
295 ->setIcon($icon)
296 ->setTitle(pht('Welcome to %s', $app_name))
297 ->setDescription(
298 pht('Import, create, or just browse repositories in Diffusion.'))
299 ->addAction($new_button);
300
301 return $view;
302 }
303
304}