Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/differential/query/DifferentialRevisionSearchEngine.php
12256 views
1
<?php
2
3
final class DifferentialRevisionSearchEngine
4
extends PhabricatorApplicationSearchEngine {
5
6
public function getResultTypeDescription() {
7
return pht('Differential Revisions');
8
}
9
10
public function getApplicationClassName() {
11
return 'PhabricatorDifferentialApplication';
12
}
13
14
protected function newResultBuckets() {
15
return DifferentialRevisionResultBucket::getAllResultBuckets();
16
}
17
18
public function newQuery() {
19
return id(new DifferentialRevisionQuery())
20
->needFlags(true)
21
->needDrafts(true)
22
->needReviewers(true);
23
}
24
25
protected function buildQueryFromParameters(array $map) {
26
$query = $this->newQuery();
27
28
if ($map['responsiblePHIDs']) {
29
$query->withResponsibleUsers($map['responsiblePHIDs']);
30
}
31
32
if ($map['authorPHIDs']) {
33
$query->withAuthors($map['authorPHIDs']);
34
}
35
36
if ($map['reviewerPHIDs']) {
37
$query->withReviewers($map['reviewerPHIDs']);
38
}
39
40
if ($map['repositoryPHIDs']) {
41
$query->withRepositoryPHIDs($map['repositoryPHIDs']);
42
}
43
44
if ($map['statuses']) {
45
$query->withStatuses($map['statuses']);
46
}
47
48
if ($map['createdStart'] || $map['createdEnd']) {
49
$query->withCreatedEpochBetween(
50
$map['createdStart'],
51
$map['createdEnd']);
52
}
53
54
if ($map['modifiedStart'] || $map['modifiedEnd']) {
55
$query->withUpdatedEpochBetween(
56
$map['modifiedStart'],
57
$map['modifiedEnd']);
58
}
59
60
if ($map['affectedPaths']) {
61
$query->withPaths($map['affectedPaths']);
62
}
63
64
return $query;
65
}
66
67
protected function buildCustomSearchFields() {
68
return array(
69
id(new PhabricatorSearchDatasourceField())
70
->setLabel(pht('Responsible Users'))
71
->setKey('responsiblePHIDs')
72
->setAliases(array('responsiblePHID', 'responsibles', 'responsible'))
73
->setDatasource(new DifferentialResponsibleDatasource())
74
->setDescription(
75
pht('Find revisions that a given user is responsible for.')),
76
id(new PhabricatorUsersSearchField())
77
->setLabel(pht('Authors'))
78
->setKey('authorPHIDs')
79
->setAliases(array('author', 'authors', 'authorPHID'))
80
->setDescription(
81
pht('Find revisions with specific authors.')),
82
id(new PhabricatorSearchDatasourceField())
83
->setLabel(pht('Reviewers'))
84
->setKey('reviewerPHIDs')
85
->setAliases(array('reviewer', 'reviewers', 'reviewerPHID'))
86
->setDatasource(new DifferentialReviewerFunctionDatasource())
87
->setDescription(
88
pht('Find revisions with specific reviewers.')),
89
id(new PhabricatorSearchDatasourceField())
90
->setLabel(pht('Repositories'))
91
->setKey('repositoryPHIDs')
92
->setAliases(array('repository', 'repositories', 'repositoryPHID'))
93
->setDatasource(new DiffusionRepositoryFunctionDatasource())
94
->setDescription(
95
pht('Find revisions from specific repositories.')),
96
id(new PhabricatorSearchDatasourceField())
97
->setLabel(pht('Statuses'))
98
->setKey('statuses')
99
->setAliases(array('status'))
100
->setDatasource(new DifferentialRevisionStatusFunctionDatasource())
101
->setDescription(
102
pht('Find revisions with particular statuses.')),
103
id(new PhabricatorSearchDateField())
104
->setLabel(pht('Created After'))
105
->setKey('createdStart')
106
->setDescription(
107
pht('Find revisions created at or after a particular time.')),
108
id(new PhabricatorSearchDateField())
109
->setLabel(pht('Created Before'))
110
->setKey('createdEnd')
111
->setDescription(
112
pht('Find revisions created at or before a particular time.')),
113
id(new PhabricatorSearchDateField())
114
->setLabel(pht('Modified After'))
115
->setKey('modifiedStart')
116
->setIsHidden(true)
117
->setDescription(
118
pht('Find revisions modified at or after a particular time.')),
119
id(new PhabricatorSearchDateField())
120
->setLabel(pht('Modified Before'))
121
->setKey('modifiedEnd')
122
->setIsHidden(true)
123
->setDescription(
124
pht('Find revisions modified at or before a particular time.')),
125
id(new PhabricatorSearchStringListField())
126
->setKey('affectedPaths')
127
->setLabel(pht('Affected Paths'))
128
->setDescription(
129
pht('Search for revisions affecting particular paths.'))
130
->setIsHidden(true),
131
);
132
}
133
134
protected function getURI($path) {
135
return '/differential/'.$path;
136
}
137
138
protected function getBuiltinQueryNames() {
139
$names = array();
140
141
if ($this->requireViewer()->isLoggedIn()) {
142
$names['active'] = pht('Active Revisions');
143
$names['authored'] = pht('Authored');
144
}
145
146
$names['all'] = pht('All Revisions');
147
148
return $names;
149
}
150
151
public function buildSavedQueryFromBuiltin($query_key) {
152
$query = $this->newSavedQuery();
153
$query->setQueryKey($query_key);
154
155
$viewer = $this->requireViewer();
156
157
switch ($query_key) {
158
case 'active':
159
$bucket_key = DifferentialRevisionRequiredActionResultBucket::BUCKETKEY;
160
161
return $query
162
->setParameter('responsiblePHIDs', array($viewer->getPHID()))
163
->setParameter('statuses', array('open()'))
164
->setParameter('bucket', $bucket_key);
165
case 'authored':
166
return $query
167
->setParameter('authorPHIDs', array($viewer->getPHID()));
168
case 'all':
169
return $query;
170
}
171
172
return parent::buildSavedQueryFromBuiltin($query_key);
173
}
174
175
private function getStatusOptions() {
176
return array(
177
DifferentialLegacyQuery::STATUS_ANY => pht('All'),
178
DifferentialLegacyQuery::STATUS_OPEN => pht('Open'),
179
DifferentialLegacyQuery::STATUS_ACCEPTED => pht('Accepted'),
180
DifferentialLegacyQuery::STATUS_NEEDS_REVIEW => pht('Needs Review'),
181
DifferentialLegacyQuery::STATUS_NEEDS_REVISION => pht('Needs Revision'),
182
DifferentialLegacyQuery::STATUS_CLOSED => pht('Closed'),
183
DifferentialLegacyQuery::STATUS_ABANDONED => pht('Abandoned'),
184
);
185
}
186
187
protected function renderResultList(
188
array $revisions,
189
PhabricatorSavedQuery $query,
190
array $handles) {
191
assert_instances_of($revisions, 'DifferentialRevision');
192
193
$viewer = $this->requireViewer();
194
$template = id(new DifferentialRevisionListView())
195
->setViewer($viewer)
196
->setNoBox($this->isPanelContext());
197
198
$bucket = $this->getResultBucket($query);
199
200
$unlanded = $this->loadUnlandedDependencies($revisions);
201
202
$views = array();
203
if ($bucket) {
204
$bucket->setViewer($viewer);
205
206
try {
207
$groups = $bucket->newResultGroups($query, $revisions);
208
209
foreach ($groups as $group) {
210
// Don't show groups in Dashboard Panels
211
if ($group->getObjects() || !$this->isPanelContext()) {
212
$views[] = id(clone $template)
213
->setHeader($group->getName())
214
->setNoDataString($group->getNoDataString())
215
->setRevisions($group->getObjects());
216
}
217
}
218
} catch (Exception $ex) {
219
$this->addError($ex->getMessage());
220
}
221
} else {
222
$views[] = id(clone $template)
223
->setRevisions($revisions);
224
}
225
226
if (!$views) {
227
$views[] = id(new DifferentialRevisionListView())
228
->setViewer($viewer)
229
->setNoDataString(pht('No revisions found.'));
230
}
231
232
foreach ($views as $view) {
233
$view->setUnlandedDependencies($unlanded);
234
}
235
236
if (count($views) == 1) {
237
// Reduce this to a PHUIObjectItemListView so we can get the free
238
// support from ApplicationSearch.
239
$list = head($views)->render();
240
} else {
241
$list = $views;
242
}
243
244
$result = new PhabricatorApplicationSearchResultView();
245
$result->setContent($list);
246
247
return $result;
248
}
249
250
protected function getNewUserBody() {
251
$create_button = id(new PHUIButtonView())
252
->setTag('a')
253
->setText(pht('Create a Diff'))
254
->setHref('/differential/diff/create/')
255
->setColor(PHUIButtonView::GREEN);
256
257
$icon = $this->getApplication()->getIcon();
258
$app_name = $this->getApplication()->getName();
259
$view = id(new PHUIBigInfoView())
260
->setIcon($icon)
261
->setTitle(pht('Welcome to %s', $app_name))
262
->setDescription(
263
pht('Pre-commit code review. Revisions that are waiting on your input '.
264
'will appear here.'))
265
->addAction($create_button);
266
267
return $view;
268
}
269
270
private function loadUnlandedDependencies(array $revisions) {
271
$phids = array();
272
foreach ($revisions as $revision) {
273
if (!$revision->isAccepted()) {
274
continue;
275
}
276
277
$phids[] = $revision->getPHID();
278
}
279
280
if (!$phids) {
281
return array();
282
}
283
284
$query = id(new PhabricatorEdgeQuery())
285
->withSourcePHIDs($phids)
286
->withEdgeTypes(
287
array(
288
DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST,
289
));
290
291
$query->execute();
292
293
$revision_phids = $query->getDestinationPHIDs();
294
if (!$revision_phids) {
295
return array();
296
}
297
298
$viewer = $this->requireViewer();
299
300
$blocking_revisions = id(new DifferentialRevisionQuery())
301
->setViewer($viewer)
302
->withPHIDs($revision_phids)
303
->withIsOpen(true)
304
->execute();
305
$blocking_revisions = mpull($blocking_revisions, null, 'getPHID');
306
307
$result = array();
308
foreach ($revisions as $revision) {
309
$revision_phid = $revision->getPHID();
310
$blocking_phids = $query->getDestinationPHIDs(array($revision_phid));
311
$blocking = array_select_keys($blocking_revisions, $blocking_phids);
312
if ($blocking) {
313
$result[$revision_phid] = $blocking;
314
}
315
}
316
317
return $result;
318
}
319
320
protected function newExportFields() {
321
$fields = array(
322
id(new PhabricatorStringExportField())
323
->setKey('monogram')
324
->setLabel(pht('Monogram')),
325
id(new PhabricatorPHIDExportField())
326
->setKey('authorPHID')
327
->setLabel(pht('Author PHID')),
328
id(new PhabricatorStringExportField())
329
->setKey('author')
330
->setLabel(pht('Author')),
331
id(new PhabricatorStringExportField())
332
->setKey('status')
333
->setLabel(pht('Status')),
334
id(new PhabricatorStringExportField())
335
->setKey('statusName')
336
->setLabel(pht('Status Name')),
337
id(new PhabricatorURIExportField())
338
->setKey('uri')
339
->setLabel(pht('URI')),
340
id(new PhabricatorStringExportField())
341
->setKey('title')
342
->setLabel(pht('Title')),
343
id(new PhabricatorStringExportField())
344
->setKey('summary')
345
->setLabel(pht('Summary')),
346
id(new PhabricatorStringExportField())
347
->setKey('testPlan')
348
->setLabel(pht('Test Plan')),
349
);
350
351
return $fields;
352
}
353
354
protected function newExportData(array $revisions) {
355
$viewer = $this->requireViewer();
356
357
$phids = array();
358
foreach ($revisions as $revision) {
359
$phids[] = $revision->getAuthorPHID();
360
}
361
$handles = $viewer->loadHandles($phids);
362
363
$export = array();
364
foreach ($revisions as $revision) {
365
366
$author_phid = $revision->getAuthorPHID();
367
if ($author_phid) {
368
$author_name = $handles[$author_phid]->getName();
369
} else {
370
$author_name = null;
371
}
372
373
$status = $revision->getStatusObject();
374
$status_name = $status->getDisplayName();
375
$status_value = $status->getKey();
376
377
$export[] = array(
378
'monogram' => $revision->getMonogram(),
379
'authorPHID' => $author_phid,
380
'author' => $author_name,
381
'status' => $status_value,
382
'statusName' => $status_name,
383
'uri' => PhabricatorEnv::getProductionURI($revision->getURI()),
384
'title' => (string)$revision->getTitle(),
385
'summary' => (string)$revision->getSummary(),
386
'testPlan' => (string)$revision->getTestPlan(),
387
);
388
}
389
390
return $export;
391
}
392
393
}
394
395