Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/herald/controller/HeraldNewController.php
12256 views
1
<?php
2
3
final class HeraldNewController extends HeraldController {
4
5
public function handleRequest(AphrontRequest $request) {
6
$viewer = $this->getViewer();
7
8
$adapter_type_map = HeraldAdapter::getEnabledAdapterMap($viewer);
9
$adapter_type = $request->getStr('adapter');
10
11
if (!isset($adapter_type_map[$adapter_type])) {
12
$title = pht('Create Herald Rule');
13
$content = $this->newAdapterMenu($title);
14
} else {
15
$adapter = HeraldAdapter::getAdapterForContentType($adapter_type);
16
17
$rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();
18
$rule_type = $request->getStr('type');
19
20
if (!isset($rule_type_map[$rule_type])) {
21
$title = pht(
22
'Create Herald Rule: %s',
23
$adapter->getAdapterContentName());
24
25
$content = $this->newTypeMenu($adapter, $title);
26
} else {
27
if ($rule_type !== HeraldRuleTypeConfig::RULE_TYPE_OBJECT) {
28
$target_phid = null;
29
$target_okay = true;
30
} else {
31
$object_name = $request->getStr('objectName');
32
$target_okay = false;
33
34
$errors = array();
35
$e_object = null;
36
37
if ($request->isFormPost()) {
38
if (strlen($object_name)) {
39
$target_object = id(new PhabricatorObjectQuery())
40
->setViewer($viewer)
41
->withNames(array($object_name))
42
->executeOne();
43
if ($target_object) {
44
$can_edit = PhabricatorPolicyFilter::hasCapability(
45
$viewer,
46
$target_object,
47
PhabricatorPolicyCapability::CAN_EDIT);
48
if (!$can_edit) {
49
$errors[] = pht(
50
'You can not create a rule for that object, because you '.
51
'do not have permission to edit it. You can only create '.
52
'rules for objects you can edit.');
53
$e_object = pht('Not Editable');
54
} else {
55
if (!$adapter->canTriggerOnObject($target_object)) {
56
$errors[] = pht(
57
'This object is not of an allowed type for the rule. '.
58
'Rules can only trigger on certain objects.');
59
$e_object = pht('Invalid');
60
} else {
61
$target_phid = $target_object->getPHID();
62
}
63
}
64
} else {
65
$errors[] = pht('No object exists by that name.');
66
$e_object = pht('Invalid');
67
}
68
} else {
69
$errors[] = pht(
70
'You must choose an object to associate this rule with.');
71
$e_object = pht('Required');
72
}
73
74
$target_okay = !$errors;
75
}
76
}
77
78
if (!$target_okay) {
79
$title = pht('Choose Object');
80
$content = $this->newTargetForm(
81
$adapter,
82
$rule_type,
83
$object_name,
84
$errors,
85
$e_object,
86
$title);
87
} else {
88
$params = array(
89
'content_type' => $adapter_type,
90
'rule_type' => $rule_type,
91
'targetPHID' => $target_phid,
92
);
93
94
$edit_uri = $this->getApplicationURI('edit/');
95
$edit_uri = new PhutilURI($edit_uri, $params);
96
97
return id(new AphrontRedirectResponse())
98
->setURI($edit_uri);
99
}
100
}
101
}
102
103
$crumbs = $this
104
->buildApplicationCrumbs()
105
->addTextCrumb(pht('Create Rule'))
106
->setBorder(true);
107
108
$view = id(new PHUITwoColumnView())
109
->setFooter($content);
110
111
return $this->newPage()
112
->setTitle($title)
113
->setCrumbs($crumbs)
114
->appendChild($view);
115
}
116
117
private function newAdapterMenu($title) {
118
$viewer = $this->getViewer();
119
120
$types = HeraldAdapter::getEnabledAdapterMap($viewer);
121
122
foreach ($types as $key => $type) {
123
$types[$key] = HeraldAdapter::getAdapterForContentType($key);
124
}
125
126
$types = msort($types, 'getAdapterContentName');
127
128
$base_uri = $this->getApplicationURI('create/');
129
130
$menu = id(new PHUIObjectItemListView())
131
->setViewer($viewer)
132
->setBig(true);
133
134
foreach ($types as $key => $adapter) {
135
$adapter_uri = id(new PhutilURI($base_uri))
136
->replaceQueryParam('adapter', $key);
137
138
$description = $adapter->getAdapterContentDescription();
139
$description = phutil_escape_html_newlines($description);
140
141
$item = id(new PHUIObjectItemView())
142
->setHeader($adapter->getAdapterContentName())
143
->setImageIcon($adapter->getAdapterContentIcon())
144
->addAttribute($description)
145
->setHref($adapter_uri)
146
->setClickable(true);
147
148
$menu->addItem($item);
149
}
150
151
$box = id(new PHUIObjectBoxView())
152
->setHeaderText($title)
153
->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
154
->setObjectList($menu);
155
156
return id(new PHUILauncherView())
157
->appendChild($box);
158
}
159
160
private function newTypeMenu(HeraldAdapter $adapter, $title) {
161
$viewer = $this->getViewer();
162
163
$global_capability = HeraldManageGlobalRulesCapability::CAPABILITY;
164
$can_global = $this->hasApplicationCapability($global_capability);
165
166
if ($can_global) {
167
$global_note = pht(
168
'You have permission to create and manage global rules.');
169
} else {
170
$global_note = pht(
171
'You do not have permission to create or manage global rules.');
172
}
173
$global_note = phutil_tag('em', array(), $global_note);
174
175
$specs = array(
176
HeraldRuleTypeConfig::RULE_TYPE_PERSONAL => array(
177
'name' => pht('Personal Rule'),
178
'icon' => 'fa-user',
179
'help' => pht(
180
'Personal rules notify you about events. You own them, but they can '.
181
'only affect you. Personal rules only trigger for objects you have '.
182
'permission to see.'),
183
'enabled' => true,
184
),
185
HeraldRuleTypeConfig::RULE_TYPE_OBJECT => array(
186
'name' => pht('Object Rule'),
187
'icon' => 'fa-cube',
188
'help' => pht(
189
'Object rules notify anyone about events. They are bound to an '.
190
'object (like a repository) and can only act on that object. You '.
191
'must be able to edit an object to create object rules for it. '.
192
'Other users who can edit the object can edit its rules.'),
193
'enabled' => true,
194
),
195
HeraldRuleTypeConfig::RULE_TYPE_GLOBAL => array(
196
'name' => pht('Global Rule'),
197
'icon' => 'fa-globe',
198
'help' => array(
199
pht(
200
'Global rules notify anyone about events. Global rules can '.
201
'bypass access control policies and act on any object.'),
202
$global_note,
203
),
204
'enabled' => $can_global,
205
),
206
);
207
208
$adapter_type = $adapter->getAdapterContentType();
209
210
$base_uri = new PhutilURI($this->getApplicationURI('create/'));
211
212
$adapter_uri = id(clone $base_uri)
213
->replaceQueryParam('adapter', $adapter_type);
214
215
$menu = id(new PHUIObjectItemListView())
216
->setUser($viewer)
217
->setBig(true);
218
219
foreach ($specs as $rule_type => $spec) {
220
$type_uri = id(clone $adapter_uri)
221
->replaceQueryParam('type', $rule_type);
222
223
$name = $spec['name'];
224
$icon = $spec['icon'];
225
226
$description = $spec['help'];
227
$description = (array)$description;
228
229
$enabled = $spec['enabled'];
230
if ($enabled) {
231
$enabled = $adapter->supportsRuleType($rule_type);
232
if (!$enabled) {
233
$description[] = phutil_tag(
234
'em',
235
array(),
236
pht(
237
'This rule type is not supported by the selected '.
238
'content type.'));
239
}
240
}
241
242
$description = phutil_implode_html(
243
array(
244
phutil_tag('br'),
245
phutil_tag('br'),
246
),
247
$description);
248
249
$item = id(new PHUIObjectItemView())
250
->setHeader($name)
251
->setImageIcon($icon)
252
->addAttribute($description);
253
254
if ($enabled) {
255
$item
256
->setHref($type_uri)
257
->setClickable(true);
258
} else {
259
$item->setDisabled(true);
260
}
261
262
$menu->addItem($item);
263
}
264
265
$box = id(new PHUIObjectBoxView())
266
->setHeaderText($title)
267
->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
268
->setObjectList($menu);
269
270
$box->newTailButton()
271
->setText(pht('Back to Content Types'))
272
->setIcon('fa-chevron-left')
273
->setHref($base_uri);
274
275
return id(new PHUILauncherView())
276
->appendChild($box);
277
}
278
279
280
private function newTargetForm(
281
HeraldAdapter $adapter,
282
$rule_type,
283
$object_name,
284
$errors,
285
$e_object,
286
$title) {
287
288
$viewer = $this->getViewer();
289
$content_type = $adapter->getAdapterContentType();
290
$rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();
291
292
$params = array(
293
'adapter' => $content_type,
294
'type' => $rule_type,
295
);
296
297
$form = id(new AphrontFormView())
298
->setViewer($viewer)
299
->appendChild(
300
id(new AphrontFormStaticControl())
301
->setLabel(pht('Rule for'))
302
->setValue(
303
phutil_tag(
304
'strong',
305
array(),
306
$adapter->getAdapterContentName())))
307
->appendChild(
308
id(new AphrontFormStaticControl())
309
->setLabel(pht('Rule Type'))
310
->setValue(
311
phutil_tag(
312
'strong',
313
array(),
314
idx($rule_type_map, $rule_type))))
315
->appendRemarkupInstructions(
316
pht(
317
'Choose the object this rule will act on (for example, enter '.
318
'`rX` to act on the `rX` repository, or `#project` to act on '.
319
'a project).'))
320
->appendRemarkupInstructions(
321
$adapter->explainValidTriggerObjects())
322
->appendChild(
323
id(new AphrontFormTextControl())
324
->setName('objectName')
325
->setError($e_object)
326
->setValue($object_name)
327
->setLabel(pht('Object')));
328
329
foreach ($params as $key => $value) {
330
$form->addHiddenInput($key, $value);
331
}
332
333
$cancel_params = $params;
334
unset($cancel_params['type']);
335
336
$cancel_uri = $this->getApplicationURI('new/');
337
$cancel_uri = new PhutilURI($cancel_uri, $params);
338
339
$form->appendChild(
340
id(new AphrontFormSubmitControl())
341
->setValue(pht('Continue'))
342
->addCancelButton($cancel_uri, pht('Back')));
343
344
$form_box = id(new PHUIObjectBoxView())
345
->setHeaderText($title)
346
->setFormErrors($errors)
347
->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
348
->setForm($form);
349
350
return $form_box;
351
}
352
353
}
354
355