3 abstract class HeraldField
extends Phobject
{
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() {
23 public function getRequiredAdapterStates() {
27 protected function getHeraldFieldStandardType() {
28 throw new PhutilMethodNotImplementedException();
31 protected function getDatasource() {
32 throw new PhutilMethodNotImplementedException();
35 protected function getDatasourceValueMap() {
39 public function getHeraldFieldConditions() {
40 $standard_type = $this->getHeraldFieldStandardType();
41 switch ($standard_type) {
42 case self
::STANDARD_BOOL
:
44 HeraldAdapter
::CONDITION_IS_TRUE
,
45 HeraldAdapter
::CONDITION_IS_FALSE
,
47 case self
::STANDARD_TEXT
:
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
:
58 HeraldAdapter
::CONDITION_IS_ANY
,
59 HeraldAdapter
::CONDITION_IS_NOT_ANY
,
61 case self
::STANDARD_PHID_LIST
:
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
:
71 HeraldAdapter
::CONDITION_EXISTS
,
72 HeraldAdapter
::CONDITION_NOT_EXISTS
,
74 case self
::STANDARD_PHID_NULLABLE
:
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
:
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
:
92 HeraldAdapter
::CONDITION_CONTAINS
,
93 HeraldAdapter
::CONDITION_NOT_CONTAINS
,
94 HeraldAdapter
::CONDITION_REGEXP
,
95 HeraldAdapter
::CONDITION_NOT_REGEXP
,
96 HeraldAdapter
::CONDITION_REGEXP_PAIR
,
102 'Herald field "%s" has unknown standard type "%s".',
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();
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();
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);
153 'Herald field "%s" has unknown standard type "%s".',
158 abstract public function supportsObject($object);
160 public function getFieldsForObject($object) {
161 return array($this->getFieldConstant() => $this);
164 public function renderConditionValue(
165 PhabricatorUser
$viewer,
169 $value_type = $this->getHeraldFieldValueType($condition);
170 $value_type->setViewer($viewer);
171 return $value_type->renderFieldValue($value);
174 public function getEditorValue(
175 PhabricatorUser
$viewer,
179 $value_type = $this->getHeraldFieldValueType($condition);
180 $value_type->setViewer($viewer);
181 return $value_type->renderEditorValue($value);
184 public function renderTranscriptValue(
185 PhabricatorUser
$viewer,
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) {
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)) {
215 final public function setAdapter(HeraldAdapter
$adapter) {
216 $this->adapter
= $adapter;
220 final public function getAdapter() {
221 return $this->adapter
;
224 final public function getFieldConstant() {
225 return $this->getPhobjectClassConstant(
227 self
::getFieldConstantByteLimit());
230 final public static function getFieldConstantByteLimit() {
234 final public static function getAllFields() {
235 return id(new PhutilClassMapQuery())
236 ->setAncestorClass(__CLASS__
)
237 ->setUniqueMethod('getFieldConstant')
241 final protected function hasAppliedTransactionOfType($type) {
242 $xactions = $this->getAdapter()->getAppliedTransactions();
248 foreach ($xactions as $xaction) {
249 if ($xaction->getTransactionType() === $type) {
257 final protected function getAppliedTransactionsOfTypes(array $types) {
258 $types = array_fuse($types);
259 $xactions = $this->getAdapter()->getAppliedTransactions();
262 foreach ($xactions as $key => $xaction) {
263 $xaction_type = $xaction->getTransactionType();
264 if (isset($types[$xaction_type])) {
265 $result[$key] = $xaction;
272 final protected function getAppliedEdgeTransactionOfType($edge_type) {
273 $edge_xactions = $this->getAppliedTransactionsOfTypes(
275 PhabricatorTransactions
::TYPE_EDGE
,
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) {
289 'Found more than one ("%s") applied edge transactions with given '.
290 'edge type ("%s"); expected zero or one.',
291 phutil_count($results),
296 return head($results);
302 public function isFieldAvailable() {