4 * Common code for standard field types which store lists of PHIDs.
6 abstract class PhabricatorStandardCustomFieldPHIDs
7 extends PhabricatorStandardCustomField
{
9 public function buildFieldIndexes() {
12 $value = $this->getFieldValue();
13 if (is_array($value)) {
14 foreach ($value as $phid) {
15 $indexes[] = $this->newStringIndex($phid);
22 public function readValueFromRequest(AphrontRequest
$request) {
23 $value = $request->getArr($this->getFieldKey());
24 $this->setFieldValue($value);
27 public function getValueForStorage() {
28 $value = $this->getFieldValue();
33 return json_encode(array_values($value));
36 public function setValueFromStorage($value) {
37 // NOTE: We're accepting either a JSON string (a real storage value) or
38 // an array (from HTTP parameter prefilling). This is a little hacky, but
39 // should hold until this can get cleaned up more thoroughly.
40 // TODO: Clean this up.
43 if ($value !== null && !is_array($value)) {
44 $value = json_decode($value, true);
45 if (is_array($value)) {
46 $result = array_values($value);
50 $this->setFieldValue($value);
55 public function readApplicationSearchValueFromRequest(
56 PhabricatorApplicationSearchEngine
$engine,
57 AphrontRequest
$request) {
58 return $request->getArr($this->getFieldKey());
61 public function applyApplicationSearchConstraintToQuery(
62 PhabricatorApplicationSearchEngine
$engine,
63 PhabricatorCursorPagedPolicyAwareQuery
$query,
66 $query->withApplicationSearchContainsConstraint(
67 $this->newStringIndex(null),
72 public function getRequiredHandlePHIDsForPropertyView() {
73 $value = $this->getFieldValue();
80 public function renderPropertyViewValue(array $handles) {
81 $value = $this->getFieldValue();
86 $handles = mpull($handles, 'renderHovercardLink');
87 $handles = phutil_implode_html(', ', $handles);
91 public function getRequiredHandlePHIDsForEdit() {
92 $value = $this->getFieldValue();
100 public function getApplicationTransactionRequiredHandlePHIDs(
101 PhabricatorApplicationTransaction
$xaction) {
103 $old = $this->decodeValue($xaction->getOldValue());
104 $new = $this->decodeValue($xaction->getNewValue());
106 $add = array_diff($new, $old);
107 $rem = array_diff($old, $new);
109 return array_merge($add, $rem);
112 public function getApplicationTransactionTitle(
113 PhabricatorApplicationTransaction
$xaction) {
114 $author_phid = $xaction->getAuthorPHID();
116 $old = $this->decodeValue($xaction->getOldValue());
117 $new = $this->decodeValue($xaction->getNewValue());
119 $add = array_diff($new, $old);
120 $rem = array_diff($old, $new);
124 '%s updated %s, added %d: %s.',
125 $xaction->renderHandleLink($author_phid),
126 $this->getFieldName(),
128 $xaction->renderHandleList($add));
129 } else if ($rem && !$add) {
131 '%s updated %s, removed %s: %s.',
132 $xaction->renderHandleLink($author_phid),
133 $this->getFieldName(),
135 $xaction->renderHandleList($rem));
138 '%s updated %s, added %s: %s; removed %s: %s.',
139 $xaction->renderHandleLink($author_phid),
140 $this->getFieldName(),
142 $xaction->renderHandleList($add),
144 $xaction->renderHandleList($rem));
148 public function getApplicationTransactionTitleForFeed(
149 PhabricatorApplicationTransaction
$xaction) {
150 $author_phid = $xaction->getAuthorPHID();
151 $object_phid = $xaction->getObjectPHID();
153 $old = $this->decodeValue($xaction->getOldValue());
154 $new = $this->decodeValue($xaction->getNewValue());
156 $add = array_diff($new, $old);
157 $rem = array_diff($old, $new);
161 '%s updated %s for %s, added %d: %s.',
162 $xaction->renderHandleLink($author_phid),
163 $this->getFieldName(),
164 $xaction->renderHandleLink($object_phid),
166 $xaction->renderHandleList($add));
167 } else if ($rem && !$add) {
169 '%s updated %s for %s, removed %s: %s.',
170 $xaction->renderHandleLink($author_phid),
171 $this->getFieldName(),
172 $xaction->renderHandleLink($object_phid),
174 $xaction->renderHandleList($rem));
177 '%s updated %s for %s, added %s: %s; removed %s: %s.',
178 $xaction->renderHandleLink($author_phid),
179 $this->getFieldName(),
180 $xaction->renderHandleLink($object_phid),
182 $xaction->renderHandleList($add),
184 $xaction->renderHandleList($rem));
188 public function validateApplicationTransactions(
189 PhabricatorApplicationTransactionEditor
$editor,
193 $errors = parent
::validateApplicationTransactions(
198 // If the user is adding PHIDs, make sure the new PHIDs are valid and
199 // visible to the actor. It's OK for a user to edit a field which includes
200 // some invalid or restricted values, but they can't add new ones.
202 foreach ($xactions as $xaction) {
203 $old = $this->decodeValue($xaction->getOldValue());
204 $new = $this->decodeValue($xaction->getNewValue());
206 $add = array_diff($new, $old);
208 $invalid = PhabricatorObjectQuery
::loadInvalidPHIDsForViewer(
213 $error = new PhabricatorApplicationTransactionValidationError(
217 'Some of the selected PHIDs in field "%s" are invalid or '.
219 $this->getFieldName(),
220 implode(', ', $invalid)),
223 $this->setFieldError(pht('Invalid'));
230 public function shouldAppearInHerald() {
234 public function getHeraldFieldConditions() {
236 HeraldAdapter
::CONDITION_INCLUDE_ALL
,
237 HeraldAdapter
::CONDITION_INCLUDE_ANY
,
238 HeraldAdapter
::CONDITION_INCLUDE_NONE
,
239 HeraldAdapter
::CONDITION_EXISTS
,
240 HeraldAdapter
::CONDITION_NOT_EXISTS
,
244 public function getHeraldFieldStandardType() {
245 return HeraldField
::STANDARD_PHID_NULLABLE
;
248 public function getHeraldFieldValue() {
249 // If the field has a `null` value, make sure we hand an `array()` to
251 $value = parent
::getHeraldFieldValue();
258 protected function decodeValue($value) {
259 if ($value === null) {
263 $value = json_decode($value);
264 if (!is_array($value)) {
271 protected function getHTTPParameterType() {
272 return new AphrontPHIDListHTTPParameterType();