Correct a parameter order swap in "diffusion.historyquery" for Mercurial
[phabricator.git] / src / applications / search / field / PhabricatorSearchField.php
blob36db0523b7d4ecbe82f3bfa8866e0661e3e9f139
1 <?php
3 /**
4 * @task config Configuring Fields
5 * @task error Handling Errors
6 * @task io Reading and Writing Field Values
7 * @task conduit Integration with Conduit
8 * @task util Utility Methods
9 */
10 abstract class PhabricatorSearchField extends Phobject {
12 private $key;
13 private $conduitKey;
14 private $viewer;
15 private $value;
16 private $label;
17 private $aliases = array();
18 private $errors = array();
19 private $description;
20 private $isHidden;
22 private $enableForConduit = true;
25 /* -( Configuring Fields )------------------------------------------------- */
28 /**
29 * Set the primary key for the field, like `projectPHIDs`.
31 * You can set human-readable aliases with @{method:setAliases}.
33 * The key should be a short, unique (within a search engine) string which
34 * does not contain any special characters.
36 * @param string Unique key which identifies the field.
37 * @return this
38 * @task config
40 public function setKey($key) {
41 $this->key = $key;
42 return $this;
46 /**
47 * Get the field's key.
49 * @return string Unique key for this field.
50 * @task config
52 public function getKey() {
53 return $this->key;
57 /**
58 * Set a human-readable label for the field.
60 * This should be a short text string, like "Reviewers" or "Colors".
62 * @param string Short, human-readable field label.
63 * @return this
64 * task config
66 public function setLabel($label) {
67 $this->label = $label;
68 return $this;
72 /**
73 * Get the field's human-readable label.
75 * @return string Short, human-readable field label.
76 * @task config
78 public function getLabel() {
79 return $this->label;
83 /**
84 * Set the acting viewer.
86 * Engines do not need to do this explicitly; it will be done on their
87 * behalf by the caller.
89 * @param PhabricatorUser Viewer.
90 * @return this
91 * @task config
93 public function setViewer(PhabricatorUser $viewer) {
94 $this->viewer = $viewer;
95 return $this;
99 /**
100 * Get the acting viewer.
102 * @return PhabricatorUser Viewer.
103 * @task config
105 public function getViewer() {
106 return $this->viewer;
111 * Provide alternate field aliases, usually more human-readable versions
112 * of the key.
114 * These aliases can be used when building GET requests, so you can provide
115 * an alias like `authors` to let users write `&authors=alincoln` instead of
116 * `&authorPHIDs=alincoln`. This is a little easier to use.
118 * @param list<string> List of aliases for this field.
119 * @return this
120 * @task config
122 public function setAliases(array $aliases) {
123 $this->aliases = $aliases;
124 return $this;
129 * Get aliases for this field.
131 * @return list<string> List of aliases for this field.
132 * @task config
134 public function getAliases() {
135 return $this->aliases;
140 * Provide an alternate field key for Conduit.
142 * This can allow you to choose a more usable key for API endpoints.
143 * If no key is provided, the main key is used.
145 * @param string Alternate key for Conduit.
146 * @return this
147 * @task config
149 public function setConduitKey($conduit_key) {
150 $this->conduitKey = $conduit_key;
151 return $this;
156 * Get the field key for use in Conduit.
158 * @return string Conduit key for this field.
159 * @task config
161 public function getConduitKey() {
162 if ($this->conduitKey !== null) {
163 return $this->conduitKey;
166 return $this->getKey();
171 * Set a human-readable description for this field.
173 * @param string Human-readable description.
174 * @return this
175 * @task config
177 public function setDescription($description) {
178 $this->description = $description;
179 return $this;
184 * Get this field's human-readable description.
186 * @return string|null Human-readable description.
187 * @task config
189 public function getDescription() {
190 return $this->description;
195 * Hide this field from the web UI.
197 * @param bool True to hide the field from the web UI.
198 * @return this
199 * @task config
201 public function setIsHidden($is_hidden) {
202 $this->isHidden = $is_hidden;
203 return $this;
208 * Should this field be hidden from the web UI?
210 * @return bool True to hide the field in the web UI.
211 * @task config
213 public function getIsHidden() {
214 return $this->isHidden;
218 /* -( Handling Errors )---------------------------------------------------- */
221 protected function addError($short, $long) {
222 $this->errors[] = array($short, $long);
223 return $this;
226 public function getErrors() {
227 return $this->errors;
230 protected function validateControlValue($value) {
231 return;
234 protected function getShortError() {
235 $error = head($this->getErrors());
236 if ($error) {
237 return head($error);
239 return null;
243 /* -( Reading and Writing Field Values )----------------------------------- */
246 public function readValueFromRequest(AphrontRequest $request) {
247 $check = array_merge(array($this->getKey()), $this->getAliases());
248 foreach ($check as $key) {
249 if ($this->getValueExistsInRequest($request, $key)) {
250 return $this->getValueFromRequest($request, $key);
253 return $this->getDefaultValue();
256 protected function getValueExistsInRequest(AphrontRequest $request, $key) {
257 return $request->getExists($key);
260 abstract protected function getValueFromRequest(
261 AphrontRequest $request,
262 $key);
264 public function readValueFromSavedQuery(PhabricatorSavedQuery $saved) {
265 $value = $saved->getParameter(
266 $this->getKey(),
267 $this->getDefaultValue());
268 $this->value = $this->didReadValueFromSavedQuery($value);
269 $this->validateControlValue($value);
270 return $this;
273 protected function didReadValueFromSavedQuery($value) {
274 return $value;
277 public function getValue() {
278 return $this->value;
281 protected function getValueForControl() {
282 return $this->value;
285 protected function getDefaultValue() {
286 return null;
289 public function getValueForQuery($value) {
290 return $value;
294 /* -( Rendering Controls )------------------------------------------------- */
297 protected function newControl() {
298 throw new PhutilMethodNotImplementedException();
302 protected function renderControl() {
303 if ($this->getIsHidden()) {
304 return null;
307 $control = $this->newControl();
309 if (!$control) {
310 return null;
313 // TODO: We should `setError($this->getShortError())` here, but it looks
314 // terrible in the form layout.
316 return $control
317 ->setValue($this->getValueForControl())
318 ->setName($this->getKey())
319 ->setLabel($this->getLabel());
322 public function appendToForm(AphrontFormView $form) {
323 $control = $this->renderControl();
324 if ($control !== null) {
325 $form->appendControl($this->renderControl());
327 return $this;
331 /* -( Integration with Conduit )------------------------------------------- */
335 * @task conduit
337 final public function getConduitParameterType() {
338 if (!$this->getEnableForConduit()) {
339 return false;
342 $type = $this->newConduitParameterType();
344 if ($type) {
345 $type->setViewer($this->getViewer());
348 return $type;
351 protected function newConduitParameterType() {
352 return null;
355 public function getValueExistsInConduitRequest(array $constraints) {
356 return $this->getConduitParameterType()->getExists(
357 $constraints,
358 $this->getConduitKey());
361 public function readValueFromConduitRequest(
362 array $constraints,
363 $strict = true) {
365 return $this->getConduitParameterType()->getValue(
366 $constraints,
367 $this->getConduitKey(),
368 $strict);
371 public function getValidConstraintKeys() {
372 return $this->getConduitParameterType()->getKeys(
373 $this->getConduitKey());
376 final public function setEnableForConduit($enable) {
377 $this->enableForConduit = $enable;
378 return $this;
381 final public function getEnableForConduit() {
382 return $this->enableForConduit;
385 public function newConduitConstants() {
386 return array();
390 /* -( Utility Methods )----------------------------------------------------- */
394 * Read a list of items from the request, in either array format or string
395 * format:
397 * list[]=item1&list[]=item2
398 * list=item1,item2
400 * This provides flexibility when constructing URIs, especially from external
401 * sources.
403 * @param AphrontRequest Request to read strings from.
404 * @param string Key to read in the request.
405 * @return list<string> List of values.
406 * @task utility
408 protected function getListFromRequest(
409 AphrontRequest $request,
410 $key) {
412 $list = $request->getArr($key, null);
413 if ($list === null) {
414 $list = $request->getStrList($key);
417 if (!$list) {
418 return array();
421 return $list;