2015-06-05 20:21:08 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @task config Configuring Fields
|
|
|
|
* @task error Handling Errors
|
|
|
|
* @task io Reading and Writing Field Values
|
|
|
|
* @task util Utility Methods
|
|
|
|
*/
|
|
|
|
abstract class PhabricatorSearchField extends Phobject {
|
|
|
|
|
|
|
|
private $key;
|
|
|
|
private $viewer;
|
|
|
|
private $value;
|
|
|
|
private $label;
|
|
|
|
private $aliases = array();
|
|
|
|
private $errors = array();
|
|
|
|
|
|
|
|
|
|
|
|
/* -( Configuring Fields )------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the primary key for the field, like `projectPHIDs`.
|
|
|
|
*
|
|
|
|
* You can set human-readable aliases with @{method:setAliases}.
|
|
|
|
*
|
|
|
|
* The key should be a short, unique (within a search engine) string which
|
|
|
|
* does not contain any special characters.
|
|
|
|
*
|
|
|
|
* @param string Unique key which identifies the field.
|
|
|
|
* @return this
|
|
|
|
* @task config
|
|
|
|
*/
|
|
|
|
public function setKey($key) {
|
|
|
|
$this->key = $key;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the field's key.
|
|
|
|
*
|
|
|
|
* @return string Unique key for this field.
|
|
|
|
* @task config
|
|
|
|
*/
|
|
|
|
public function getKey() {
|
|
|
|
return $this->key;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set a human-readable label for the field.
|
|
|
|
*
|
|
|
|
* This should be a short text string, like "Reviewers" or "Colors".
|
|
|
|
*
|
|
|
|
* @param string Short, human-readable field label.
|
|
|
|
* @return this
|
|
|
|
* task config
|
|
|
|
*/
|
|
|
|
public function setLabel($label) {
|
|
|
|
$this->label = $label;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the field's human-readable label.
|
|
|
|
*
|
|
|
|
* @return string Short, human-readable field label.
|
|
|
|
* @task config
|
|
|
|
*/
|
|
|
|
public function getLabel() {
|
|
|
|
return $this->label;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the acting viewer.
|
|
|
|
*
|
|
|
|
* Engines do not need to do this explicitly; it will be done on their
|
|
|
|
* behalf by the caller.
|
|
|
|
*
|
|
|
|
* @param PhabricatorUser Viewer.
|
|
|
|
* @return this
|
|
|
|
* @task config
|
|
|
|
*/
|
|
|
|
public function setViewer(PhabricatorUser $viewer) {
|
|
|
|
$this->viewer = $viewer;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the acting viewer.
|
|
|
|
*
|
|
|
|
* @return PhabricatorUser Viewer.
|
|
|
|
* @task config
|
|
|
|
*/
|
|
|
|
public function getViewer() {
|
|
|
|
return $this->viewer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provide alternate field aliases, usually more human-readable versions
|
|
|
|
* of the key.
|
|
|
|
*
|
|
|
|
* These aliases can be used when building GET requests, so you can provide
|
|
|
|
* an alias like `authors` to let users write `&authors=alincoln` instead of
|
|
|
|
* `&authorPHIDs=alincoln`. This is a little easier to use.
|
|
|
|
*
|
|
|
|
* @param list<string> List of aliases for this field.
|
|
|
|
* @return this
|
|
|
|
* @task config
|
|
|
|
*/
|
|
|
|
public function setAliases(array $aliases) {
|
|
|
|
$this->aliases = $aliases;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get aliases for this field.
|
|
|
|
*
|
|
|
|
* @return list<string> List of aliases for this field.
|
|
|
|
* @task config
|
|
|
|
*/
|
|
|
|
public function getAliases() {
|
|
|
|
return $this->aliases;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -( Handling Errors )---------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
protected function addError($short, $long) {
|
|
|
|
$this->errors[] = array($short, $long);
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getErrors() {
|
|
|
|
return $this->errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function validateControlValue($value) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getShortError() {
|
|
|
|
$error = head($this->getErrors());
|
|
|
|
if ($error) {
|
|
|
|
return head($error);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -( Reading and Writing Field Values )----------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
public function readValueFromRequest(AphrontRequest $request) {
|
|
|
|
$check = array_merge(array($this->getKey()), $this->getAliases());
|
|
|
|
foreach ($check as $key) {
|
|
|
|
if ($this->getValueExistsInRequest($request, $key)) {
|
|
|
|
return $this->getValueFromRequest($request, $key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $this->getDefaultValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getValueExistsInRequest(AphrontRequest $request, $key) {
|
|
|
|
return $request->getExists($key);
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract protected function getValueFromRequest(
|
|
|
|
AphrontRequest $request,
|
|
|
|
$key);
|
|
|
|
|
|
|
|
public function readValueFromSavedQuery(PhabricatorSavedQuery $saved) {
|
|
|
|
$value = $saved->getParameter(
|
|
|
|
$this->getKey(),
|
|
|
|
$this->getDefaultValue());
|
|
|
|
$this->value = $this->didReadValueFromSavedQuery($value);
|
|
|
|
$this->validateControlValue($value);
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function didReadValueFromSavedQuery($value) {
|
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getValue() {
|
|
|
|
return $this->value;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getValueForControl() {
|
|
|
|
return $this->value;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getDefaultValue() {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2015-06-05 20:21:22 +02:00
|
|
|
public function getValueForQuery($value) {
|
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
|
2015-06-05 20:21:08 +02:00
|
|
|
|
|
|
|
/* -( Rendering Controls )------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
abstract protected function newControl();
|
|
|
|
|
|
|
|
|
|
|
|
protected function renderControl() {
|
|
|
|
// TODO: We should `setError($this->getShortError())` here, but it looks
|
|
|
|
// terrible in the form layout.
|
|
|
|
|
|
|
|
return $this->newControl()
|
|
|
|
->setValue($this->getValueForControl())
|
|
|
|
->setName($this->getKey())
|
|
|
|
->setLabel($this->getLabel());
|
|
|
|
}
|
|
|
|
|
|
|
|
public function appendToForm(AphrontFormView $form) {
|
|
|
|
$form->appendControl($this->renderControl());
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -( Utility Methods )----------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Read a list of items from the request, in either array format or string
|
|
|
|
* format:
|
|
|
|
*
|
|
|
|
* list[]=item1&list[]=item2
|
|
|
|
* list=item1,item2
|
|
|
|
*
|
|
|
|
* This provides flexibility when constructing URIs, especially from external
|
|
|
|
* sources.
|
|
|
|
*
|
|
|
|
* @param AphrontRequest Request to read strings from.
|
|
|
|
* @param string Key to read in the request.
|
|
|
|
* @return list<string> List of values.
|
|
|
|
* @task utility
|
|
|
|
*/
|
|
|
|
protected function getListFromRequest(
|
|
|
|
AphrontRequest $request,
|
|
|
|
$key) {
|
|
|
|
|
|
|
|
$list = $request->getArr($key, null);
|
|
|
|
if ($list === null) {
|
|
|
|
$list = $request->getStrList($key);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$list) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $list;
|
|
|
|
}
|
|
|
|
}
|