Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/herald/query/HeraldRuleQuery.php
12256 views
1
<?php
2
3
final class HeraldRuleQuery extends PhabricatorCursorPagedPolicyAwareQuery {
4
5
private $ids;
6
private $phids;
7
private $authorPHIDs;
8
private $ruleTypes;
9
private $contentTypes;
10
private $disabled;
11
private $active;
12
private $datasourceQuery;
13
private $triggerObjectPHIDs;
14
private $affectedObjectPHIDs;
15
16
private $needConditionsAndActions;
17
private $needAppliedToPHIDs;
18
private $needValidateAuthors;
19
20
public function withIDs(array $ids) {
21
$this->ids = $ids;
22
return $this;
23
}
24
25
public function withPHIDs(array $phids) {
26
$this->phids = $phids;
27
return $this;
28
}
29
30
public function withAuthorPHIDs(array $author_phids) {
31
$this->authorPHIDs = $author_phids;
32
return $this;
33
}
34
35
public function withRuleTypes(array $types) {
36
$this->ruleTypes = $types;
37
return $this;
38
}
39
40
public function withContentTypes(array $types) {
41
$this->contentTypes = $types;
42
return $this;
43
}
44
45
public function withDisabled($disabled) {
46
$this->disabled = $disabled;
47
return $this;
48
}
49
50
public function withActive($active) {
51
$this->active = $active;
52
return $this;
53
}
54
55
public function withDatasourceQuery($query) {
56
$this->datasourceQuery = $query;
57
return $this;
58
}
59
60
public function withTriggerObjectPHIDs(array $phids) {
61
$this->triggerObjectPHIDs = $phids;
62
return $this;
63
}
64
65
public function withAffectedObjectPHIDs(array $phids) {
66
$this->affectedObjectPHIDs = $phids;
67
return $this;
68
}
69
70
public function needConditionsAndActions($need) {
71
$this->needConditionsAndActions = $need;
72
return $this;
73
}
74
75
public function needAppliedToPHIDs(array $phids) {
76
$this->needAppliedToPHIDs = $phids;
77
return $this;
78
}
79
80
public function needValidateAuthors($need) {
81
$this->needValidateAuthors = $need;
82
return $this;
83
}
84
85
public function newResultObject() {
86
return new HeraldRule();
87
}
88
89
protected function willFilterPage(array $rules) {
90
$rule_ids = mpull($rules, 'getID');
91
92
// Filter out any rules that have invalid adapters, or have adapters the
93
// viewer isn't permitted to see or use (for example, Differential rules
94
// if the user can't use Differential or Differential is not installed).
95
$types = HeraldAdapter::getEnabledAdapterMap($this->getViewer());
96
foreach ($rules as $key => $rule) {
97
if (empty($types[$rule->getContentType()])) {
98
$this->didRejectResult($rule);
99
unset($rules[$key]);
100
}
101
}
102
103
if ($this->needValidateAuthors || ($this->active !== null)) {
104
$this->validateRuleAuthors($rules);
105
}
106
107
if ($this->active !== null) {
108
$need_active = (bool)$this->active;
109
foreach ($rules as $key => $rule) {
110
if ($rule->getIsDisabled()) {
111
$is_active = false;
112
} else if (!$rule->hasValidAuthor()) {
113
$is_active = false;
114
} else {
115
$is_active = true;
116
}
117
118
if ($is_active != $need_active) {
119
unset($rules[$key]);
120
}
121
}
122
}
123
124
if (!$rules) {
125
return array();
126
}
127
128
if ($this->needConditionsAndActions) {
129
$conditions = id(new HeraldCondition())->loadAllWhere(
130
'ruleID IN (%Ld)',
131
$rule_ids);
132
$conditions = mgroup($conditions, 'getRuleID');
133
134
$actions = id(new HeraldActionRecord())->loadAllWhere(
135
'ruleID IN (%Ld)',
136
$rule_ids);
137
$actions = mgroup($actions, 'getRuleID');
138
139
foreach ($rules as $rule) {
140
$rule->attachActions(idx($actions, $rule->getID(), array()));
141
$rule->attachConditions(idx($conditions, $rule->getID(), array()));
142
}
143
}
144
145
if ($this->needAppliedToPHIDs) {
146
$conn_r = id(new HeraldRule())->establishConnection('r');
147
$applied = queryfx_all(
148
$conn_r,
149
'SELECT * FROM %T WHERE ruleID IN (%Ld) AND phid IN (%Ls)',
150
HeraldRule::TABLE_RULE_APPLIED,
151
$rule_ids,
152
$this->needAppliedToPHIDs);
153
154
$map = array();
155
foreach ($applied as $row) {
156
$map[$row['ruleID']][$row['phid']] = true;
157
}
158
159
foreach ($rules as $rule) {
160
foreach ($this->needAppliedToPHIDs as $phid) {
161
$rule->setRuleApplied(
162
$phid,
163
isset($map[$rule->getID()][$phid]));
164
}
165
}
166
}
167
168
$object_phids = array();
169
foreach ($rules as $rule) {
170
if ($rule->isObjectRule()) {
171
$object_phids[] = $rule->getTriggerObjectPHID();
172
}
173
}
174
175
if ($object_phids) {
176
$objects = id(new PhabricatorObjectQuery())
177
->setParentQuery($this)
178
->setViewer($this->getViewer())
179
->withPHIDs($object_phids)
180
->execute();
181
$objects = mpull($objects, null, 'getPHID');
182
} else {
183
$objects = array();
184
}
185
186
foreach ($rules as $key => $rule) {
187
if ($rule->isObjectRule()) {
188
$object = idx($objects, $rule->getTriggerObjectPHID());
189
if (!$object) {
190
unset($rules[$key]);
191
continue;
192
}
193
$rule->attachTriggerObject($object);
194
}
195
}
196
197
return $rules;
198
}
199
200
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
201
$where = parent::buildWhereClauseParts($conn);
202
203
if ($this->ids !== null) {
204
$where[] = qsprintf(
205
$conn,
206
'rule.id IN (%Ld)',
207
$this->ids);
208
}
209
210
if ($this->phids !== null) {
211
$where[] = qsprintf(
212
$conn,
213
'rule.phid IN (%Ls)',
214
$this->phids);
215
}
216
217
if ($this->authorPHIDs !== null) {
218
$where[] = qsprintf(
219
$conn,
220
'rule.authorPHID IN (%Ls)',
221
$this->authorPHIDs);
222
}
223
224
if ($this->ruleTypes !== null) {
225
$where[] = qsprintf(
226
$conn,
227
'rule.ruleType IN (%Ls)',
228
$this->ruleTypes);
229
}
230
231
if ($this->contentTypes !== null) {
232
$where[] = qsprintf(
233
$conn,
234
'rule.contentType IN (%Ls)',
235
$this->contentTypes);
236
}
237
238
if ($this->disabled !== null) {
239
$where[] = qsprintf(
240
$conn,
241
'rule.isDisabled = %d',
242
(int)$this->disabled);
243
}
244
245
if ($this->active !== null) {
246
$where[] = qsprintf(
247
$conn,
248
'rule.isDisabled = %d',
249
(int)(!$this->active));
250
}
251
252
if ($this->datasourceQuery !== null) {
253
$where[] = qsprintf(
254
$conn,
255
'rule.name LIKE %>',
256
$this->datasourceQuery);
257
}
258
259
if ($this->triggerObjectPHIDs !== null) {
260
$where[] = qsprintf(
261
$conn,
262
'rule.triggerObjectPHID IN (%Ls)',
263
$this->triggerObjectPHIDs);
264
}
265
266
if ($this->affectedObjectPHIDs !== null) {
267
$where[] = qsprintf(
268
$conn,
269
'edge_affects.dst IN (%Ls)',
270
$this->affectedObjectPHIDs);
271
}
272
273
return $where;
274
}
275
276
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
277
$joins = parent::buildJoinClauseParts($conn);
278
279
if ($this->affectedObjectPHIDs !== null) {
280
$joins[] = qsprintf(
281
$conn,
282
'JOIN %T edge_affects ON rule.phid = edge_affects.src
283
AND edge_affects.type = %d',
284
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
285
HeraldRuleActionAffectsObjectEdgeType::EDGECONST);
286
}
287
288
return $joins;
289
}
290
291
private function validateRuleAuthors(array $rules) {
292
// "Global" and "Object" rules always have valid authors.
293
foreach ($rules as $key => $rule) {
294
if ($rule->isGlobalRule() || $rule->isObjectRule()) {
295
$rule->attachValidAuthor(true);
296
unset($rules[$key]);
297
continue;
298
}
299
}
300
301
if (!$rules) {
302
return;
303
}
304
305
// For personal rules, the author needs to exist and not be disabled.
306
$user_phids = mpull($rules, 'getAuthorPHID');
307
$users = id(new PhabricatorPeopleQuery())
308
->setViewer($this->getViewer())
309
->withPHIDs($user_phids)
310
->execute();
311
$users = mpull($users, null, 'getPHID');
312
313
foreach ($rules as $key => $rule) {
314
$author_phid = $rule->getAuthorPHID();
315
if (empty($users[$author_phid])) {
316
$rule->attachValidAuthor(false);
317
continue;
318
}
319
if (!$users[$author_phid]->isUserActivated()) {
320
$rule->attachValidAuthor(false);
321
continue;
322
}
323
324
$rule->attachValidAuthor(true);
325
$rule->attachAuthor($users[$author_phid]);
326
}
327
}
328
329
public function getQueryApplicationClass() {
330
return 'PhabricatorHeraldApplication';
331
}
332
333
protected function getPrimaryTableAlias() {
334
return 'rule';
335
}
336
337
}
338
339