Correct a parameter order swap in "diffusion.historyquery" for Mercurial
[phabricator.git] / src / applications / herald / field / HeraldField.php
blobcdfdd7e51812b3202b547157133dc80ffa0384e8
1 <?php
3 abstract class HeraldField extends Phobject {
5 private $adapter;
7 const STANDARD_BOOL = 'standard.bool';
8 const STANDARD_TEXT = 'standard.text';
9 const STANDARD_TEXT_LIST = 'standard.text.list';
10 const STANDARD_TEXT_MAP = 'standard.text.map';
11 const STANDARD_PHID = 'standard.phid';
12 const STANDARD_PHID_LIST = 'standard.phid.list';
13 const STANDARD_PHID_BOOL = 'standard.phid.bool';
14 const STANDARD_PHID_NULLABLE = 'standard.phid.nullable';
16 abstract public function getHeraldFieldName();
17 abstract public function getHeraldFieldValue($object);
19 public function getFieldGroupKey() {
20 return null;
23 public function getRequiredAdapterStates() {
24 return array();
27 protected function getHeraldFieldStandardType() {
28 throw new PhutilMethodNotImplementedException();
31 protected function getDatasource() {
32 throw new PhutilMethodNotImplementedException();
35 protected function getDatasourceValueMap() {
36 return null;
39 public function getHeraldFieldConditions() {
40 $standard_type = $this->getHeraldFieldStandardType();
41 switch ($standard_type) {
42 case self::STANDARD_BOOL:
43 return array(
44 HeraldAdapter::CONDITION_IS_TRUE,
45 HeraldAdapter::CONDITION_IS_FALSE,
47 case self::STANDARD_TEXT:
48 return array(
49 HeraldAdapter::CONDITION_CONTAINS,
50 HeraldAdapter::CONDITION_NOT_CONTAINS,
51 HeraldAdapter::CONDITION_IS,
52 HeraldAdapter::CONDITION_IS_NOT,
53 HeraldAdapter::CONDITION_REGEXP,
54 HeraldAdapter::CONDITION_NOT_REGEXP,
56 case self::STANDARD_PHID:
57 return array(
58 HeraldAdapter::CONDITION_IS_ANY,
59 HeraldAdapter::CONDITION_IS_NOT_ANY,
61 case self::STANDARD_PHID_LIST:
62 return array(
63 HeraldAdapter::CONDITION_INCLUDE_ALL,
64 HeraldAdapter::CONDITION_INCLUDE_ANY,
65 HeraldAdapter::CONDITION_INCLUDE_NONE,
66 HeraldAdapter::CONDITION_EXISTS,
67 HeraldAdapter::CONDITION_NOT_EXISTS,
69 case self::STANDARD_PHID_BOOL:
70 return array(
71 HeraldAdapter::CONDITION_EXISTS,
72 HeraldAdapter::CONDITION_NOT_EXISTS,
74 case self::STANDARD_PHID_NULLABLE:
75 return array(
76 HeraldAdapter::CONDITION_IS_ANY,
77 HeraldAdapter::CONDITION_IS_NOT_ANY,
78 HeraldAdapter::CONDITION_EXISTS,
79 HeraldAdapter::CONDITION_NOT_EXISTS,
81 case self::STANDARD_TEXT_LIST:
82 return array(
83 HeraldAdapter::CONDITION_CONTAINS,
84 HeraldAdapter::CONDITION_NOT_CONTAINS,
85 HeraldAdapter::CONDITION_REGEXP,
86 HeraldAdapter::CONDITION_NOT_REGEXP,
87 HeraldAdapter::CONDITION_EXISTS,
88 HeraldAdapter::CONDITION_NOT_EXISTS,
90 case self::STANDARD_TEXT_MAP:
91 return array(
92 HeraldAdapter::CONDITION_CONTAINS,
93 HeraldAdapter::CONDITION_NOT_CONTAINS,
94 HeraldAdapter::CONDITION_REGEXP,
95 HeraldAdapter::CONDITION_NOT_REGEXP,
96 HeraldAdapter::CONDITION_REGEXP_PAIR,
100 throw new Exception(
101 pht(
102 'Herald field "%s" has unknown standard type "%s".',
103 get_class($this),
104 $standard_type));
107 public function getHeraldFieldValueType($condition) {
109 // NOTE: The condition type may be "null" to indicate that the caller
110 // wants a generic field value type. This is used when rendering field
111 // values in the object transcript.
113 $standard_type = $this->getHeraldFieldStandardType();
114 switch ($standard_type) {
115 case self::STANDARD_BOOL:
116 case self::STANDARD_PHID_BOOL:
117 return new HeraldBoolFieldValue();
118 case self::STANDARD_TEXT:
119 case self::STANDARD_TEXT_LIST:
120 case self::STANDARD_TEXT_MAP:
121 switch ($condition) {
122 case HeraldAdapter::CONDITION_EXISTS:
123 case HeraldAdapter::CONDITION_NOT_EXISTS:
124 return new HeraldEmptyFieldValue();
125 default:
126 return new HeraldTextFieldValue();
128 case self::STANDARD_PHID:
129 case self::STANDARD_PHID_NULLABLE:
130 case self::STANDARD_PHID_LIST:
131 switch ($condition) {
132 case HeraldAdapter::CONDITION_EXISTS:
133 case HeraldAdapter::CONDITION_NOT_EXISTS:
134 return new HeraldEmptyFieldValue();
135 default:
136 $tokenizer = id(new HeraldTokenizerFieldValue())
137 ->setKey($this->getHeraldFieldName())
138 ->setDatasource($this->getDatasource());
140 $value_map = $this->getDatasourceValueMap();
141 if ($value_map !== null) {
142 $tokenizer->setValueMap($value_map);
145 return $tokenizer;
147 break;
151 throw new Exception(
152 pht(
153 'Herald field "%s" has unknown standard type "%s".',
154 get_class($this),
155 $standard_type));
158 abstract public function supportsObject($object);
160 public function getFieldsForObject($object) {
161 return array($this->getFieldConstant() => $this);
164 public function renderConditionValue(
165 PhabricatorUser $viewer,
166 $condition,
167 $value) {
169 $value_type = $this->getHeraldFieldValueType($condition);
170 $value_type->setViewer($viewer);
171 return $value_type->renderFieldValue($value);
174 public function getEditorValue(
175 PhabricatorUser $viewer,
176 $condition,
177 $value) {
179 $value_type = $this->getHeraldFieldValueType($condition);
180 $value_type->setViewer($viewer);
181 return $value_type->renderEditorValue($value);
184 public function renderTranscriptValue(
185 PhabricatorUser $viewer,
186 $field_value) {
187 $value_type = $this->getHeraldFieldValueType($condition_type = null);
188 $value_type->setViewer($viewer);
189 return $value_type->renderTranscriptValue($field_value);
192 public function getPHIDsAffectedByCondition(HeraldCondition $condition) {
193 try {
194 $standard_type = $this->getHeraldFieldStandardType();
195 } catch (PhutilMethodNotImplementedException $ex) {
196 $standard_type = null;
199 switch ($standard_type) {
200 case self::STANDARD_PHID:
201 case self::STANDARD_PHID_NULLABLE:
202 case self::STANDARD_PHID_LIST:
203 $phids = $condition->getValue();
205 if (!is_array($phids)) {
206 $phids = array();
209 return $phids;
212 return array();
215 final public function setAdapter(HeraldAdapter $adapter) {
216 $this->adapter = $adapter;
217 return $this;
220 final public function getAdapter() {
221 return $this->adapter;
224 final public function getFieldConstant() {
225 return $this->getPhobjectClassConstant(
226 'FIELDCONST',
227 self::getFieldConstantByteLimit());
230 final public static function getFieldConstantByteLimit() {
231 return 64;
234 final public static function getAllFields() {
235 return id(new PhutilClassMapQuery())
236 ->setAncestorClass(__CLASS__)
237 ->setUniqueMethod('getFieldConstant')
238 ->execute();
241 final protected function hasAppliedTransactionOfType($type) {
242 $xactions = $this->getAdapter()->getAppliedTransactions();
244 if (!$xactions) {
245 return false;
248 foreach ($xactions as $xaction) {
249 if ($xaction->getTransactionType() === $type) {
250 return true;
254 return false;
257 final protected function getAppliedTransactionsOfTypes(array $types) {
258 $types = array_fuse($types);
259 $xactions = $this->getAdapter()->getAppliedTransactions();
261 $result = array();
262 foreach ($xactions as $key => $xaction) {
263 $xaction_type = $xaction->getTransactionType();
264 if (isset($types[$xaction_type])) {
265 $result[$key] = $xaction;
269 return $result;
272 final protected function getAppliedEdgeTransactionOfType($edge_type) {
273 $edge_xactions = $this->getAppliedTransactionsOfTypes(
274 array(
275 PhabricatorTransactions::TYPE_EDGE,
278 $results = array();
279 foreach ($edge_xactions as $edge_xaction) {
280 $xaction_edge_type = $edge_xaction->getMetadataValue('edge:type');
281 if ($xaction_edge_type == $edge_type) {
282 $results[] = $edge_xaction;
286 if (count($results) > 1) {
287 throw new Exception(
288 pht(
289 'Found more than one ("%s") applied edge transactions with given '.
290 'edge type ("%s"); expected zero or one.',
291 phutil_count($results),
292 $edge_type));
295 if ($results) {
296 return head($results);
299 return null;
302 public function isFieldAvailable() {
303 return true;