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