Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php
12241 views
1
<?php
2
3
final class DiffusionCommitAuditorsTransaction
4
extends DiffusionCommitTransactionType {
5
6
const TRANSACTIONTYPE = 'diffusion.commit.auditors';
7
8
public function generateOldValue($object) {
9
$auditors = $object->getAudits();
10
return mpull($auditors, 'getAuditStatus', 'getAuditorPHID');
11
}
12
13
public function generateNewValue($object, $value) {
14
$actor = $this->getActor();
15
16
$auditors = $this->generateOldValue($object);
17
$old_auditors = $auditors;
18
19
$request_status = PhabricatorAuditRequestStatus::AUDIT_REQUESTED;
20
21
$rem = idx($value, '-', array());
22
foreach ($rem as $phid) {
23
unset($auditors[$phid]);
24
}
25
26
$add = idx($value, '+', array());
27
$add_map = array();
28
foreach ($add as $phid) {
29
$add_map[$phid] = $request_status;
30
}
31
32
$set = idx($value, '=', null);
33
if ($set !== null) {
34
foreach ($set as $phid) {
35
$add_map[$phid] = $request_status;
36
}
37
38
$auditors = array();
39
}
40
41
foreach ($add_map as $phid => $new_status) {
42
$old_status = idx($old_auditors, $phid);
43
44
if ($old_status) {
45
$auditors[$phid] = $old_status;
46
continue;
47
}
48
49
$auditors[$phid] = $new_status;
50
}
51
52
return $auditors;
53
}
54
55
public function getTransactionHasEffect($object, $old, $new) {
56
ksort($old);
57
ksort($new);
58
return ($old !== $new);
59
}
60
61
public function mergeTransactions(
62
$object,
63
PhabricatorApplicationTransaction $u,
64
PhabricatorApplicationTransaction $v) {
65
66
$u_new = $u->getNewValue();
67
$v_new = $v->getNewValue();
68
69
$result = $v_new;
70
foreach (array('-', '+') as $key) {
71
$u_value = idx($u_new, $key, array());
72
$v_value = idx($v_new, $key, array());
73
74
$merged = $u_value + $v_value;
75
76
if ($merged) {
77
$result[$key] = $merged;
78
}
79
}
80
81
$u->setNewValue($result);
82
83
return $u;
84
}
85
86
public function applyExternalEffects($object, $value) {
87
$src_phid = $object->getPHID();
88
89
$old = $this->generateOldValue($object);
90
$new = $value;
91
92
$auditors = $object->getAudits();
93
$auditors = mpull($auditors, null, 'getAuditorPHID');
94
95
$rem = array_diff_key($old, $new);
96
foreach ($rem as $phid => $status) {
97
$auditor = idx($auditors, $phid);
98
if ($auditor) {
99
$auditor->delete();
100
}
101
}
102
103
$this->updateAudits($object, $new);
104
}
105
106
public function getTitle() {
107
$old = $this->getOldValue();
108
$new = $this->getNewValue();
109
110
$rem = array_diff_key($old, $new);
111
$add = array_diff_key($new, $old);
112
$rem_phids = array_keys($rem);
113
$add_phids = array_keys($add);
114
$total_count = count($rem) + count($add);
115
116
if ($rem && $add) {
117
return pht(
118
'%s edited %s auditor(s), removed %s: %s; added %s: %s.',
119
$this->renderAuthor(),
120
new PhutilNumber($total_count),
121
phutil_count($rem_phids),
122
$this->renderHandleList($rem_phids),
123
phutil_count($add_phids),
124
$this->renderHandleList($add_phids));
125
} else if ($add) {
126
return pht(
127
'%s added %s auditor(s): %s.',
128
$this->renderAuthor(),
129
phutil_count($add_phids),
130
$this->renderHandleList($add_phids));
131
} else {
132
return pht(
133
'%s removed %s auditor(s): %s.',
134
$this->renderAuthor(),
135
phutil_count($rem_phids),
136
$this->renderHandleList($rem_phids));
137
}
138
}
139
140
public function getTitleForFeed() {
141
$old = $this->getOldValue();
142
$new = $this->getNewValue();
143
144
$rem = array_diff_key($old, $new);
145
$add = array_diff_key($new, $old);
146
$rem_phids = array_keys($rem);
147
$add_phids = array_keys($add);
148
$total_count = count($rem) + count($add);
149
150
if ($rem && $add) {
151
return pht(
152
'%s edited %s auditor(s) for %s, removed %s: %s; added %s: %s.',
153
$this->renderAuthor(),
154
new PhutilNumber($total_count),
155
$this->renderObject(),
156
phutil_count($rem_phids),
157
$this->renderHandleList($rem_phids),
158
phutil_count($add_phids),
159
$this->renderHandleList($add_phids));
160
} else if ($add) {
161
return pht(
162
'%s added %s auditor(s) for %s: %s.',
163
$this->renderAuthor(),
164
phutil_count($add_phids),
165
$this->renderObject(),
166
$this->renderHandleList($add_phids));
167
} else {
168
return pht(
169
'%s removed %s auditor(s) for %s: %s.',
170
$this->renderAuthor(),
171
phutil_count($rem_phids),
172
$this->renderObject(),
173
$this->renderHandleList($rem_phids));
174
}
175
}
176
177
public function validateTransactions($object, array $xactions) {
178
$actor = $this->getActor();
179
$errors = array();
180
181
if (!$xactions) {
182
return $errors;
183
}
184
185
$author_phid = $object->getEffectiveAuthorPHID();
186
$can_author_close_key = 'audit.can-author-close-audit';
187
$can_author_close = PhabricatorEnv::getEnvConfig($can_author_close_key);
188
189
$old = $this->generateOldValue($object);
190
foreach ($xactions as $xaction) {
191
$new = $this->generateNewValue($object, $xaction->getNewValue());
192
193
$add = array_diff_key($new, $old);
194
if (!$add) {
195
continue;
196
}
197
198
$objects = id(new PhabricatorObjectQuery())
199
->setViewer($actor)
200
->withPHIDs(array_keys($add))
201
->execute();
202
$objects = mpull($objects, null, 'getPHID');
203
204
foreach ($add as $phid => $status) {
205
if (!isset($objects[$phid])) {
206
$errors[] = $this->newInvalidError(
207
pht(
208
'Auditor "%s" is not a valid object.',
209
$phid),
210
$xaction);
211
continue;
212
}
213
214
switch (phid_get_type($phid)) {
215
case PhabricatorPeopleUserPHIDType::TYPECONST:
216
case PhabricatorOwnersPackagePHIDType::TYPECONST:
217
case PhabricatorProjectProjectPHIDType::TYPECONST:
218
break;
219
default:
220
$errors[] = $this->newInvalidError(
221
pht(
222
'Auditor "%s" must be a user, a package, or a project.',
223
$phid),
224
$xaction);
225
continue 2;
226
}
227
228
$is_self = ($phid === $author_phid);
229
if ($is_self && !$can_author_close) {
230
$errors[] = $this->newInvalidError(
231
pht('The author of a commit can not be an auditor.'),
232
$xaction);
233
continue;
234
}
235
}
236
}
237
238
return $errors;
239
}
240
241
}
242
243