Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php
12242 views
1
<?php
2
3
abstract class PhabricatorStandardCustomField
4
extends PhabricatorCustomField {
5
6
private $rawKey;
7
private $fieldKey;
8
private $fieldName;
9
private $fieldValue;
10
private $fieldDescription;
11
private $fieldConfig;
12
private $applicationField;
13
private $strings = array();
14
private $caption;
15
private $fieldError;
16
private $required;
17
private $default;
18
private $isCopyable;
19
private $hasStorageValue;
20
private $isBuiltin;
21
private $isEnabled = true;
22
23
abstract public function getFieldType();
24
25
public static function buildStandardFields(
26
PhabricatorCustomField $template,
27
array $config,
28
$builtin = false) {
29
30
$types = id(new PhutilClassMapQuery())
31
->setAncestorClass(__CLASS__)
32
->setUniqueMethod('getFieldType')
33
->execute();
34
35
$fields = array();
36
foreach ($config as $key => $value) {
37
$type = idx($value, 'type', 'text');
38
if (empty($types[$type])) {
39
// TODO: We should have better typechecking somewhere, and then make
40
// this more serious.
41
continue;
42
}
43
44
$namespace = $template->getStandardCustomFieldNamespace();
45
$full_key = "std:{$namespace}:{$key}";
46
47
$template = clone $template;
48
$standard = id(clone $types[$type])
49
->setRawStandardFieldKey($key)
50
->setFieldKey($full_key)
51
->setFieldConfig($value)
52
->setApplicationField($template);
53
54
if ($builtin) {
55
$standard->setIsBuiltin(true);
56
}
57
58
$field = $template->setProxy($standard);
59
$fields[] = $field;
60
}
61
62
return $fields;
63
}
64
65
public function setApplicationField(
66
PhabricatorStandardCustomFieldInterface $application_field) {
67
$this->applicationField = $application_field;
68
return $this;
69
}
70
71
public function getApplicationField() {
72
return $this->applicationField;
73
}
74
75
public function setFieldName($name) {
76
$this->fieldName = $name;
77
return $this;
78
}
79
80
public function getFieldValue() {
81
return $this->fieldValue;
82
}
83
84
public function setFieldValue($value) {
85
$this->fieldValue = $value;
86
return $this;
87
}
88
89
public function setCaption($caption) {
90
$this->caption = $caption;
91
return $this;
92
}
93
94
public function getCaption() {
95
return $this->caption;
96
}
97
98
public function setFieldDescription($description) {
99
$this->fieldDescription = $description;
100
return $this;
101
}
102
103
public function setIsBuiltin($is_builtin) {
104
$this->isBuiltin = $is_builtin;
105
return $this;
106
}
107
108
public function getIsBuiltin() {
109
return $this->isBuiltin;
110
}
111
112
public function setFieldConfig(array $config) {
113
foreach ($config as $key => $value) {
114
switch ($key) {
115
case 'name':
116
$this->setFieldName($value);
117
break;
118
case 'description':
119
$this->setFieldDescription($value);
120
break;
121
case 'strings':
122
$this->setStrings($value);
123
break;
124
case 'caption':
125
$this->setCaption($value);
126
break;
127
case 'required':
128
if ($value) {
129
$this->setRequired($value);
130
$this->setFieldError(true);
131
}
132
break;
133
case 'default':
134
$this->setFieldValue($value);
135
break;
136
case 'copy':
137
$this->setIsCopyable($value);
138
break;
139
case 'type':
140
// We set this earlier on.
141
break;
142
}
143
}
144
$this->fieldConfig = $config;
145
return $this;
146
}
147
148
public function getFieldConfigValue($key, $default = null) {
149
return idx($this->fieldConfig, $key, $default);
150
}
151
152
public function setFieldError($field_error) {
153
$this->fieldError = $field_error;
154
return $this;
155
}
156
157
public function getFieldError() {
158
return $this->fieldError;
159
}
160
161
public function setRequired($required) {
162
$this->required = $required;
163
return $this;
164
}
165
166
public function getRequired() {
167
return $this->required;
168
}
169
170
public function setRawStandardFieldKey($raw_key) {
171
$this->rawKey = $raw_key;
172
return $this;
173
}
174
175
public function getRawStandardFieldKey() {
176
return $this->rawKey;
177
}
178
179
public function setIsEnabled($is_enabled) {
180
$this->isEnabled = $is_enabled;
181
return $this;
182
}
183
184
public function getIsEnabled() {
185
return $this->isEnabled;
186
}
187
188
public function isFieldEnabled() {
189
return $this->getIsEnabled();
190
}
191
192
193
/* -( PhabricatorCustomField )--------------------------------------------- */
194
195
196
public function setFieldKey($field_key) {
197
$this->fieldKey = $field_key;
198
return $this;
199
}
200
201
public function getFieldKey() {
202
return $this->fieldKey;
203
}
204
205
public function getFieldName() {
206
return coalesce($this->fieldName, parent::getFieldName());
207
}
208
209
public function getFieldDescription() {
210
return coalesce($this->fieldDescription, parent::getFieldDescription());
211
}
212
213
public function setStrings(array $strings) {
214
$this->strings = $strings;
215
return;
216
}
217
218
public function getString($key, $default = null) {
219
return idx($this->strings, $key, $default);
220
}
221
222
public function setIsCopyable($is_copyable) {
223
$this->isCopyable = $is_copyable;
224
return $this;
225
}
226
227
public function getIsCopyable() {
228
return $this->isCopyable;
229
}
230
231
public function shouldUseStorage() {
232
try {
233
$object = $this->newStorageObject();
234
return true;
235
} catch (PhabricatorCustomFieldImplementationIncompleteException $ex) {
236
return false;
237
}
238
}
239
240
public function getValueForStorage() {
241
return $this->getFieldValue();
242
}
243
244
public function setValueFromStorage($value) {
245
return $this->setFieldValue($value);
246
}
247
248
public function didSetValueFromStorage() {
249
$this->hasStorageValue = true;
250
return $this;
251
}
252
253
public function getOldValueForApplicationTransactions() {
254
if ($this->hasStorageValue) {
255
return $this->getValueForStorage();
256
} else {
257
return null;
258
}
259
}
260
261
public function shouldAppearInApplicationTransactions() {
262
return true;
263
}
264
265
public function shouldAppearInEditView() {
266
return $this->getFieldConfigValue('edit', true);
267
}
268
269
public function readValueFromRequest(AphrontRequest $request) {
270
$value = $request->getStr($this->getFieldKey());
271
if (!strlen($value)) {
272
$value = null;
273
}
274
$this->setFieldValue($value);
275
}
276
277
public function getInstructionsForEdit() {
278
return $this->getFieldConfigValue('instructions');
279
}
280
281
public function getPlaceholder() {
282
return $this->getFieldConfigValue('placeholder', null);
283
}
284
285
public function renderEditControl(array $handles) {
286
return id(new AphrontFormTextControl())
287
->setName($this->getFieldKey())
288
->setCaption($this->getCaption())
289
->setValue($this->getFieldValue())
290
->setError($this->getFieldError())
291
->setLabel($this->getFieldName())
292
->setPlaceholder($this->getPlaceholder());
293
}
294
295
public function newStorageObject() {
296
return $this->getApplicationField()->newStorageObject();
297
}
298
299
public function shouldAppearInPropertyView() {
300
return $this->getFieldConfigValue('view', true);
301
}
302
303
public function renderPropertyViewValue(array $handles) {
304
if (!strlen($this->getFieldValue())) {
305
return null;
306
}
307
return $this->getFieldValue();
308
}
309
310
public function shouldAppearInApplicationSearch() {
311
return $this->getFieldConfigValue('search', false);
312
}
313
314
protected function newStringIndexStorage() {
315
return $this->getApplicationField()->newStringIndexStorage();
316
}
317
318
protected function newNumericIndexStorage() {
319
return $this->getApplicationField()->newNumericIndexStorage();
320
}
321
322
public function buildFieldIndexes() {
323
return array();
324
}
325
326
public function buildOrderIndex() {
327
return null;
328
}
329
330
public function readApplicationSearchValueFromRequest(
331
PhabricatorApplicationSearchEngine $engine,
332
AphrontRequest $request) {
333
return;
334
}
335
336
public function applyApplicationSearchConstraintToQuery(
337
PhabricatorApplicationSearchEngine $engine,
338
PhabricatorCursorPagedPolicyAwareQuery $query,
339
$value) {
340
return;
341
}
342
343
public function appendToApplicationSearchForm(
344
PhabricatorApplicationSearchEngine $engine,
345
AphrontFormView $form,
346
$value) {
347
return;
348
}
349
350
public function validateApplicationTransactions(
351
PhabricatorApplicationTransactionEditor $editor,
352
$type,
353
array $xactions) {
354
355
$this->setFieldError(null);
356
357
$errors = parent::validateApplicationTransactions(
358
$editor,
359
$type,
360
$xactions);
361
362
if ($this->getRequired()) {
363
$value = $this->getOldValueForApplicationTransactions();
364
365
$transaction = null;
366
foreach ($xactions as $xaction) {
367
$value = $xaction->getNewValue();
368
if (!$this->isValueEmpty($value)) {
369
$transaction = $xaction;
370
break;
371
}
372
}
373
if ($this->isValueEmpty($value)) {
374
$error = new PhabricatorApplicationTransactionValidationError(
375
$type,
376
pht('Required'),
377
pht('%s is required.', $this->getFieldName()),
378
$transaction);
379
$error->setIsMissingFieldError(true);
380
$errors[] = $error;
381
$this->setFieldError(pht('Required'));
382
}
383
}
384
385
return $errors;
386
}
387
388
protected function isValueEmpty($value) {
389
if (is_array($value)) {
390
return empty($value);
391
}
392
return !strlen($value);
393
}
394
395
public function getApplicationTransactionTitle(
396
PhabricatorApplicationTransaction $xaction) {
397
$author_phid = $xaction->getAuthorPHID();
398
$old = $xaction->getOldValue();
399
$new = $xaction->getNewValue();
400
401
if (!$old) {
402
return pht(
403
'%s set %s to %s.',
404
$xaction->renderHandleLink($author_phid),
405
$this->getFieldName(),
406
$new);
407
} else if (!$new) {
408
return pht(
409
'%s removed %s.',
410
$xaction->renderHandleLink($author_phid),
411
$this->getFieldName());
412
} else {
413
return pht(
414
'%s changed %s from %s to %s.',
415
$xaction->renderHandleLink($author_phid),
416
$this->getFieldName(),
417
$old,
418
$new);
419
}
420
}
421
422
public function getApplicationTransactionTitleForFeed(
423
PhabricatorApplicationTransaction $xaction) {
424
425
$author_phid = $xaction->getAuthorPHID();
426
$object_phid = $xaction->getObjectPHID();
427
428
$old = $xaction->getOldValue();
429
$new = $xaction->getNewValue();
430
431
if (!$old) {
432
return pht(
433
'%s set %s to %s on %s.',
434
$xaction->renderHandleLink($author_phid),
435
$this->getFieldName(),
436
$new,
437
$xaction->renderHandleLink($object_phid));
438
} else if (!$new) {
439
return pht(
440
'%s removed %s on %s.',
441
$xaction->renderHandleLink($author_phid),
442
$this->getFieldName(),
443
$xaction->renderHandleLink($object_phid));
444
} else {
445
return pht(
446
'%s changed %s from %s to %s on %s.',
447
$xaction->renderHandleLink($author_phid),
448
$this->getFieldName(),
449
$old,
450
$new,
451
$xaction->renderHandleLink($object_phid));
452
}
453
}
454
455
public function getHeraldFieldValue() {
456
return $this->getFieldValue();
457
}
458
459
public function getFieldControlID($key = null) {
460
$key = coalesce($key, $this->getRawStandardFieldKey());
461
return 'std:control:'.$key;
462
}
463
464
public function shouldAppearInGlobalSearch() {
465
return $this->getFieldConfigValue('fulltext', false);
466
}
467
468
public function updateAbstractDocument(
469
PhabricatorSearchAbstractDocument $document) {
470
471
$field_key = $this->getFieldConfigValue('fulltext');
472
473
// If the caller or configuration didn't specify a valid field key,
474
// generate one automatically from the field index.
475
if (!is_string($field_key) || (strlen($field_key) != 4)) {
476
$field_key = '!'.substr($this->getFieldIndex(), 0, 3);
477
}
478
479
$field_value = $this->getFieldValue();
480
if (strlen($field_value)) {
481
$document->addField($field_key, $field_value);
482
}
483
}
484
485
protected function newStandardEditField() {
486
$short = $this->getModernFieldKey();
487
488
return parent::newStandardEditField()
489
->setEditTypeKey($short)
490
->setIsCopyable($this->getIsCopyable());
491
}
492
493
public function shouldAppearInConduitTransactions() {
494
return true;
495
}
496
497
public function shouldAppearInConduitDictionary() {
498
return true;
499
}
500
501
public function getModernFieldKey() {
502
if ($this->getIsBuiltin()) {
503
return $this->getRawStandardFieldKey();
504
} else {
505
return 'custom.'.$this->getRawStandardFieldKey();
506
}
507
}
508
509
public function getConduitDictionaryValue() {
510
return $this->getFieldValue();
511
}
512
513
public function newExportData() {
514
return $this->getFieldValue();
515
}
516
517
}
518
519