Correct Aphlict websocket URI construction after PHP8 compatibility changes
[phabricator.git] / src / infrastructure / customfield / standard / PhabricatorStandardCustomFieldPHIDs.php
blob014927bcd1684d699a1093a8415b535042fc2ebc
1 <?php
3 /**
4 * Common code for standard field types which store lists of PHIDs.
5 */
6 abstract class PhabricatorStandardCustomFieldPHIDs
7 extends PhabricatorStandardCustomField {
9 public function buildFieldIndexes() {
10 $indexes = array();
12 $value = $this->getFieldValue();
13 if (is_array($value)) {
14 foreach ($value as $phid) {
15 $indexes[] = $this->newStringIndex($phid);
19 return $indexes;
22 public function readValueFromRequest(AphrontRequest $request) {
23 $value = $request->getArr($this->getFieldKey());
24 $this->setFieldValue($value);
27 public function getValueForStorage() {
28 $value = $this->getFieldValue();
29 if (!$value) {
30 return null;
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.
42 $result = array();
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);
52 return $this;
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,
64 $value) {
65 if ($value) {
66 $query->withApplicationSearchContainsConstraint(
67 $this->newStringIndex(null),
68 $value);
72 public function getRequiredHandlePHIDsForPropertyView() {
73 $value = $this->getFieldValue();
74 if ($value) {
75 return $value;
77 return array();
80 public function renderPropertyViewValue(array $handles) {
81 $value = $this->getFieldValue();
82 if (!$value) {
83 return null;
86 $handles = mpull($handles, 'renderHovercardLink');
87 $handles = phutil_implode_html(', ', $handles);
88 return $handles;
91 public function getRequiredHandlePHIDsForEdit() {
92 $value = $this->getFieldValue();
93 if ($value) {
94 return $value;
95 } else {
96 return array();
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);
122 if ($add && !$rem) {
123 return pht(
124 '%s updated %s, added %d: %s.',
125 $xaction->renderHandleLink($author_phid),
126 $this->getFieldName(),
127 phutil_count($add),
128 $xaction->renderHandleList($add));
129 } else if ($rem && !$add) {
130 return pht(
131 '%s updated %s, removed %s: %s.',
132 $xaction->renderHandleLink($author_phid),
133 $this->getFieldName(),
134 phutil_count($rem),
135 $xaction->renderHandleList($rem));
136 } else {
137 return pht(
138 '%s updated %s, added %s: %s; removed %s: %s.',
139 $xaction->renderHandleLink($author_phid),
140 $this->getFieldName(),
141 phutil_count($add),
142 $xaction->renderHandleList($add),
143 phutil_count($rem),
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);
159 if ($add && !$rem) {
160 return pht(
161 '%s updated %s for %s, added %d: %s.',
162 $xaction->renderHandleLink($author_phid),
163 $this->getFieldName(),
164 $xaction->renderHandleLink($object_phid),
165 phutil_count($add),
166 $xaction->renderHandleList($add));
167 } else if ($rem && !$add) {
168 return pht(
169 '%s updated %s for %s, removed %s: %s.',
170 $xaction->renderHandleLink($author_phid),
171 $this->getFieldName(),
172 $xaction->renderHandleLink($object_phid),
173 phutil_count($rem),
174 $xaction->renderHandleList($rem));
175 } else {
176 return pht(
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),
181 phutil_count($add),
182 $xaction->renderHandleList($add),
183 phutil_count($rem),
184 $xaction->renderHandleList($rem));
188 public function validateApplicationTransactions(
189 PhabricatorApplicationTransactionEditor $editor,
190 $type,
191 array $xactions) {
193 $errors = parent::validateApplicationTransactions(
194 $editor,
195 $type,
196 $xactions);
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(
209 $editor->getActor(),
210 $add);
212 if ($invalid) {
213 $error = new PhabricatorApplicationTransactionValidationError(
214 $type,
215 pht('Invalid'),
216 pht(
217 'Some of the selected PHIDs in field "%s" are invalid or '.
218 'restricted: %s.',
219 $this->getFieldName(),
220 implode(', ', $invalid)),
221 $xaction);
222 $errors[] = $error;
223 $this->setFieldError(pht('Invalid'));
227 return $errors;
230 public function shouldAppearInHerald() {
231 return true;
234 public function getHeraldFieldConditions() {
235 return array(
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
250 // Herald.
251 $value = parent::getHeraldFieldValue();
252 if ($value) {
253 return $value;
255 return array();
258 protected function decodeValue($value) {
259 if ($value === null) {
260 return array();
263 $value = json_decode($value);
264 if (!is_array($value)) {
265 $value = array();
268 return $value;
271 protected function getHTTPParameterType() {
272 return new AphrontPHIDListHTTPParameterType();