Changeset View
Changeset View
Standalone View
Standalone View
src/applications/herald/adapter/HeraldAdapter.php
| <?php | <?php | ||||
| /** | /** | ||||
| * @group herald | * @task customfield Custom Field Integration | ||||
| */ | */ | ||||
| abstract class HeraldAdapter { | abstract class HeraldAdapter { | ||||
| const FIELD_TITLE = 'title'; | const FIELD_TITLE = 'title'; | ||||
| const FIELD_BODY = 'body'; | const FIELD_BODY = 'body'; | ||||
| const FIELD_AUTHOR = 'author'; | const FIELD_AUTHOR = 'author'; | ||||
| const FIELD_ASSIGNEE = 'assignee'; | const FIELD_ASSIGNEE = 'assignee'; | ||||
| const FIELD_REVIEWER = 'reviewer'; | const FIELD_REVIEWER = 'reviewer'; | ||||
| ▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | abstract class HeraldAdapter { | ||||
| const CONDITION_IS_ME = 'me'; | const CONDITION_IS_ME = 'me'; | ||||
| const CONDITION_IS_NOT_ME = '!me'; | const CONDITION_IS_NOT_ME = '!me'; | ||||
| const CONDITION_REGEXP = 'regexp'; | const CONDITION_REGEXP = 'regexp'; | ||||
| const CONDITION_RULE = 'conditions'; | const CONDITION_RULE = 'conditions'; | ||||
| const CONDITION_NOT_RULE = '!conditions'; | const CONDITION_NOT_RULE = '!conditions'; | ||||
| const CONDITION_EXISTS = 'exists'; | const CONDITION_EXISTS = 'exists'; | ||||
| const CONDITION_NOT_EXISTS = '!exists'; | const CONDITION_NOT_EXISTS = '!exists'; | ||||
| const CONDITION_UNCONDITIONALLY = 'unconditionally'; | const CONDITION_UNCONDITIONALLY = 'unconditionally'; | ||||
| const CONDITION_NEVER = 'never'; | |||||
| const CONDITION_REGEXP_PAIR = 'regexp-pair'; | const CONDITION_REGEXP_PAIR = 'regexp-pair'; | ||||
| const CONDITION_HAS_BIT = 'bit'; | const CONDITION_HAS_BIT = 'bit'; | ||||
| const CONDITION_NOT_BIT = '!bit'; | const CONDITION_NOT_BIT = '!bit'; | ||||
| const CONDITION_IS_TRUE = 'true'; | const CONDITION_IS_TRUE = 'true'; | ||||
| const CONDITION_IS_FALSE = 'false'; | const CONDITION_IS_FALSE = 'false'; | ||||
| const ACTION_ADD_CC = 'addcc'; | const ACTION_ADD_CC = 'addcc'; | ||||
| const ACTION_REMOVE_CC = 'remcc'; | const ACTION_REMOVE_CC = 'remcc'; | ||||
| Show All 21 Lines | abstract class HeraldAdapter { | ||||
| const VALUE_CONTENT_SOURCE = 'contentsource'; | const VALUE_CONTENT_SOURCE = 'contentsource'; | ||||
| const VALUE_USER_OR_PROJECT = 'userorproject'; | const VALUE_USER_OR_PROJECT = 'userorproject'; | ||||
| const VALUE_BUILD_PLAN = 'buildplan'; | const VALUE_BUILD_PLAN = 'buildplan'; | ||||
| const VALUE_TASK_PRIORITY = 'taskpriority'; | const VALUE_TASK_PRIORITY = 'taskpriority'; | ||||
| const VALUE_ARCANIST_PROJECT = 'arcanistprojects'; | const VALUE_ARCANIST_PROJECT = 'arcanistprojects'; | ||||
| private $contentSource; | private $contentSource; | ||||
| private $isNewObject; | private $isNewObject; | ||||
| private $customFields = false; | |||||
| public function setContentSource(PhabricatorContentSource $content_source) { | public function setContentSource(PhabricatorContentSource $content_source) { | ||||
| $this->contentSource = $content_source; | $this->contentSource = $content_source; | ||||
| return $this; | return $this; | ||||
| } | } | ||||
| public function getContentSource() { | public function getContentSource() { | ||||
| return $this->contentSource; | return $this->contentSource; | ||||
| } | } | ||||
| Show All 19 Lines | switch ($field_name) { | ||||
| return null; | return null; | ||||
| case self::FIELD_CONTENT_SOURCE: | case self::FIELD_CONTENT_SOURCE: | ||||
| return $this->getContentSource()->getSource(); | return $this->getContentSource()->getSource(); | ||||
| case self::FIELD_ALWAYS: | case self::FIELD_ALWAYS: | ||||
| return true; | return true; | ||||
| case self::FIELD_IS_NEW_OBJECT: | case self::FIELD_IS_NEW_OBJECT: | ||||
| return $this->getIsNewObject(); | return $this->getIsNewObject(); | ||||
| default: | default: | ||||
| if ($this->isHeraldCustomKey($field_name)) { | |||||
| return $this->getCustomFieldValue($field_name); | |||||
| } | |||||
| throw new Exception( | throw new Exception( | ||||
| "Unknown field '{$field_name}'!"); | "Unknown field '{$field_name}'!"); | ||||
| } | } | ||||
| } | } | ||||
| abstract public function applyHeraldEffects(array $effects); | abstract public function applyHeraldEffects(array $effects); | ||||
| public function isAvailableToUser(PhabricatorUser $viewer) { | public function isAvailableToUser(PhabricatorUser $viewer) { | ||||
| ▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | public function getAdapterSortOrder() { | ||||
| return 1000; | return 1000; | ||||
| } | } | ||||
| /* -( Fields )------------------------------------------------------------- */ | /* -( Fields )------------------------------------------------------------- */ | ||||
| public function getFields() { | public function getFields() { | ||||
| return array( | $fields = array(); | ||||
| self::FIELD_ALWAYS, | |||||
| self::FIELD_RULE, | $fields[] = self::FIELD_ALWAYS; | ||||
| ); | $fields[] = self::FIELD_RULE; | ||||
| $custom_fields = $this->getCustomFields(); | |||||
| if ($custom_fields) { | |||||
| foreach ($custom_fields->getFields() as $custom_field) { | |||||
| $key = $custom_field->getFieldKey(); | |||||
| $fields[] = $this->getHeraldKeyFromCustomKey($key); | |||||
| } | |||||
| } | |||||
| return $fields; | |||||
| } | } | ||||
| public function getFieldNameMap() { | public function getFieldNameMap() { | ||||
| return array( | return array( | ||||
| self::FIELD_TITLE => pht('Title'), | self::FIELD_TITLE => pht('Title'), | ||||
| self::FIELD_BODY => pht('Body'), | self::FIELD_BODY => pht('Body'), | ||||
| self::FIELD_AUTHOR => pht('Author'), | self::FIELD_AUTHOR => pht('Author'), | ||||
| self::FIELD_ASSIGNEE => pht('Assignee'), | self::FIELD_ASSIGNEE => pht('Assignee'), | ||||
| Show All 27 Lines | return array( | ||||
| self::FIELD_IS_MERGE_COMMIT => pht('Commit is a merge'), | self::FIELD_IS_MERGE_COMMIT => pht('Commit is a merge'), | ||||
| self::FIELD_BRANCHES => pht('Commit\'s branches'), | self::FIELD_BRANCHES => pht('Commit\'s branches'), | ||||
| self::FIELD_AUTHOR_RAW => pht('Raw author name'), | self::FIELD_AUTHOR_RAW => pht('Raw author name'), | ||||
| self::FIELD_COMMITTER_RAW => pht('Raw committer name'), | self::FIELD_COMMITTER_RAW => pht('Raw committer name'), | ||||
| self::FIELD_IS_NEW_OBJECT => pht('Is newly created?'), | self::FIELD_IS_NEW_OBJECT => pht('Is newly created?'), | ||||
| self::FIELD_TASK_PRIORITY => pht('Task priority'), | self::FIELD_TASK_PRIORITY => pht('Task priority'), | ||||
| self::FIELD_ARCANIST_PROJECT => pht('Arcanist Project'), | self::FIELD_ARCANIST_PROJECT => pht('Arcanist Project'), | ||||
| self::FIELD_PUSHER_IS_COMMITTER => pht('Pusher same as committer'), | self::FIELD_PUSHER_IS_COMMITTER => pht('Pusher same as committer'), | ||||
| ); | ) + $this->getCustomFieldNameMap(); | ||||
| } | } | ||||
| /* -( Conditions )--------------------------------------------------------- */ | /* -( Conditions )--------------------------------------------------------- */ | ||||
| public function getConditionNameMap() { | public function getConditionNameMap() { | ||||
| return array( | return array( | ||||
| Show All 11 Lines | return array( | ||||
| self::CONDITION_IS_ME => pht('is myself'), | self::CONDITION_IS_ME => pht('is myself'), | ||||
| self::CONDITION_IS_NOT_ME => pht('is not myself'), | self::CONDITION_IS_NOT_ME => pht('is not myself'), | ||||
| self::CONDITION_REGEXP => pht('matches regexp'), | self::CONDITION_REGEXP => pht('matches regexp'), | ||||
| self::CONDITION_RULE => pht('matches:'), | self::CONDITION_RULE => pht('matches:'), | ||||
| self::CONDITION_NOT_RULE => pht('does not match:'), | self::CONDITION_NOT_RULE => pht('does not match:'), | ||||
| self::CONDITION_EXISTS => pht('exists'), | self::CONDITION_EXISTS => pht('exists'), | ||||
| self::CONDITION_NOT_EXISTS => pht('does not exist'), | self::CONDITION_NOT_EXISTS => pht('does not exist'), | ||||
| self::CONDITION_UNCONDITIONALLY => '', // don't show anything! | self::CONDITION_UNCONDITIONALLY => '', // don't show anything! | ||||
| self::CONDITION_NEVER => '', // don't show anything! | |||||
| self::CONDITION_REGEXP_PAIR => pht('matches regexp pair'), | self::CONDITION_REGEXP_PAIR => pht('matches regexp pair'), | ||||
| self::CONDITION_HAS_BIT => pht('has bit'), | self::CONDITION_HAS_BIT => pht('has bit'), | ||||
| self::CONDITION_NOT_BIT => pht('lacks bit'), | self::CONDITION_NOT_BIT => pht('lacks bit'), | ||||
| ); | ); | ||||
| } | } | ||||
| public function getConditionsForField($field) { | public function getConditionsForField($field) { | ||||
| switch ($field) { | switch ($field) { | ||||
| ▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | switch ($field) { | ||||
| case self::FIELD_DIFF_ENORMOUS: | case self::FIELD_DIFF_ENORMOUS: | ||||
| case self::FIELD_IS_NEW_OBJECT: | case self::FIELD_IS_NEW_OBJECT: | ||||
| case self::FIELD_PUSHER_IS_COMMITTER: | case self::FIELD_PUSHER_IS_COMMITTER: | ||||
| return array( | return array( | ||||
| self::CONDITION_IS_TRUE, | self::CONDITION_IS_TRUE, | ||||
| self::CONDITION_IS_FALSE, | self::CONDITION_IS_FALSE, | ||||
| ); | ); | ||||
| default: | default: | ||||
| if ($this->isHeraldCustomKey($field)) { | |||||
| return $this->getCustomFieldConditions($field); | |||||
| } | |||||
| throw new Exception( | throw new Exception( | ||||
| "This adapter does not define conditions for field '{$field}'!"); | "This adapter does not define conditions for field '{$field}'!"); | ||||
| } | } | ||||
| } | } | ||||
| public function doesConditionMatch( | public function doesConditionMatch( | ||||
| HeraldEngine $engine, | HeraldEngine $engine, | ||||
| HeraldRule $rule, | HeraldRule $rule, | ||||
| ▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | switch ($condition_type) { | ||||
| case self::CONDITION_EXISTS: | case self::CONDITION_EXISTS: | ||||
| case self::CONDITION_IS_TRUE: | case self::CONDITION_IS_TRUE: | ||||
| return (bool)$field_value; | return (bool)$field_value; | ||||
| case self::CONDITION_NOT_EXISTS: | case self::CONDITION_NOT_EXISTS: | ||||
| case self::CONDITION_IS_FALSE: | case self::CONDITION_IS_FALSE: | ||||
| return !$field_value; | return !$field_value; | ||||
| case self::CONDITION_UNCONDITIONALLY: | case self::CONDITION_UNCONDITIONALLY: | ||||
| return (bool)$field_value; | return (bool)$field_value; | ||||
| case self::CONDITION_NEVER: | |||||
| return false; | |||||
| case self::CONDITION_REGEXP: | case self::CONDITION_REGEXP: | ||||
| foreach ((array)$field_value as $value) { | foreach ((array)$field_value as $value) { | ||||
| // We add the 'S' flag because we use the regexp multiple times. | // We add the 'S' flag because we use the regexp multiple times. | ||||
| // It shouldn't cause any troubles if the flag is already there | // It shouldn't cause any troubles if the flag is already there | ||||
| // - /.*/S is evaluated same as /.*/SS. | // - /.*/S is evaluated same as /.*/SS. | ||||
| $result = @preg_match($condition_value . 'S', $value); | $result = @preg_match($condition_value . 'S', $value); | ||||
| if ($result === false) { | if ($result === false) { | ||||
| throw new HeraldInvalidConditionException( | throw new HeraldInvalidConditionException( | ||||
| ▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | switch ($condition_type) { | ||||
| case self::CONDITION_INCLUDE_NONE: | case self::CONDITION_INCLUDE_NONE: | ||||
| case self::CONDITION_IS_ME: | case self::CONDITION_IS_ME: | ||||
| case self::CONDITION_IS_NOT_ME: | case self::CONDITION_IS_NOT_ME: | ||||
| case self::CONDITION_RULE: | case self::CONDITION_RULE: | ||||
| case self::CONDITION_NOT_RULE: | case self::CONDITION_NOT_RULE: | ||||
| case self::CONDITION_EXISTS: | case self::CONDITION_EXISTS: | ||||
| case self::CONDITION_NOT_EXISTS: | case self::CONDITION_NOT_EXISTS: | ||||
| case self::CONDITION_UNCONDITIONALLY: | case self::CONDITION_UNCONDITIONALLY: | ||||
| case self::CONDITION_NEVER: | |||||
| case self::CONDITION_HAS_BIT: | case self::CONDITION_HAS_BIT: | ||||
| case self::CONDITION_NOT_BIT: | case self::CONDITION_NOT_BIT: | ||||
| case self::CONDITION_IS_TRUE: | case self::CONDITION_IS_TRUE: | ||||
| case self::CONDITION_IS_FALSE: | case self::CONDITION_IS_FALSE: | ||||
| // No explicit validation for these types, although there probably | // No explicit validation for these types, although there probably | ||||
| // should be in some cases. | // should be in some cases. | ||||
| break; | break; | ||||
| default: | default: | ||||
| ▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | /* -( Actions )------------------------------------------------------------ */ | ||||
| } | } | ||||
| /* -( Values )------------------------------------------------------------- */ | /* -( Values )------------------------------------------------------------- */ | ||||
| public function getValueTypeForFieldAndCondition($field, $condition) { | public function getValueTypeForFieldAndCondition($field, $condition) { | ||||
| if ($this->isHeraldCustomKey($field)) { | |||||
| $value_type = $this->getCustomFieldValueTypeForFieldAndCondition( | |||||
| $field, | |||||
| $condition); | |||||
| if ($value_type !== null) { | |||||
| return $value_type; | |||||
| } | |||||
| } | |||||
| switch ($condition) { | switch ($condition) { | ||||
| case self::CONDITION_CONTAINS: | case self::CONDITION_CONTAINS: | ||||
| case self::CONDITION_NOT_CONTAINS: | case self::CONDITION_NOT_CONTAINS: | ||||
| case self::CONDITION_REGEXP: | case self::CONDITION_REGEXP: | ||||
| case self::CONDITION_REGEXP_PAIR: | case self::CONDITION_REGEXP_PAIR: | ||||
| return self::VALUE_TEXT; | return self::VALUE_TEXT; | ||||
| case self::CONDITION_IS: | case self::CONDITION_IS: | ||||
| case self::CONDITION_IS_NOT: | case self::CONDITION_IS_NOT: | ||||
| Show All 40 Lines | switch ($condition) { | ||||
| return self::VALUE_USER; | return self::VALUE_USER; | ||||
| } | } | ||||
| break; | break; | ||||
| case self::CONDITION_IS_ME: | case self::CONDITION_IS_ME: | ||||
| case self::CONDITION_IS_NOT_ME: | case self::CONDITION_IS_NOT_ME: | ||||
| case self::CONDITION_EXISTS: | case self::CONDITION_EXISTS: | ||||
| case self::CONDITION_NOT_EXISTS: | case self::CONDITION_NOT_EXISTS: | ||||
| case self::CONDITION_UNCONDITIONALLY: | case self::CONDITION_UNCONDITIONALLY: | ||||
| case self::CONDITION_NEVER: | |||||
| case self::CONDITION_IS_TRUE: | case self::CONDITION_IS_TRUE: | ||||
| case self::CONDITION_IS_FALSE: | case self::CONDITION_IS_FALSE: | ||||
| return self::VALUE_NONE; | return self::VALUE_NONE; | ||||
| case self::CONDITION_RULE: | case self::CONDITION_RULE: | ||||
| case self::CONDITION_NOT_RULE: | case self::CONDITION_NOT_RULE: | ||||
| return self::VALUE_RULE; | return self::VALUE_RULE; | ||||
| default: | default: | ||||
| throw new Exception("Unknown condition '{$condition}'."); | throw new Exception("Unknown condition '{$condition}'."); | ||||
| ▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | public function renderRuleAsText(HeraldRule $rule, array $handles) { | ||||
| return phutil_implode_html("\n", $out); | return phutil_implode_html("\n", $out); | ||||
| } | } | ||||
| private function renderConditionAsText( | private function renderConditionAsText( | ||||
| HeraldCondition $condition, | HeraldCondition $condition, | ||||
| array $handles) { | array $handles) { | ||||
| $field_type = $condition->getFieldName(); | $field_type = $condition->getFieldName(); | ||||
| $field_name = idx($this->getFieldNameMap(), $field_type); | |||||
| $default = $this->isHeraldCustomKey($field_type) | |||||
| ? pht('(Unknown Custom Field "%s")', $field_type) | |||||
| : pht('(Unknown Field "%s")', $field_type); | |||||
| $field_name = idx($this->getFieldNameMap(), $field_type, $default); | |||||
| $condition_type = $condition->getFieldCondition(); | $condition_type = $condition->getFieldCondition(); | ||||
| $condition_name = idx($this->getConditionNameMap(), $condition_type); | $condition_name = idx($this->getConditionNameMap(), $condition_type); | ||||
| $value = $this->renderConditionValueAsText($condition, $handles); | $value = $this->renderConditionValueAsText($condition, $handles); | ||||
| return hsprintf(' %s %s %s', $field_name, $condition_name, $value); | return hsprintf(' %s %s %s', $field_name, $condition_name, $value); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | public static function getHandlePHIDs(HeraldRule $rule) { | ||||
| if ($rule->isObjectRule()) { | if ($rule->isObjectRule()) { | ||||
| $phids[] = $rule->getTriggerObjectPHID(); | $phids[] = $rule->getTriggerObjectPHID(); | ||||
| } | } | ||||
| return $phids; | return $phids; | ||||
| } | } | ||||
| /* -( Custom Field Integration )------------------------------------------- */ | |||||
| /** | |||||
| * Return an object which custom fields can be generated from while editing | |||||
| * rules. Adapters must return an object from this method to enable custom | |||||
| * field rules. | |||||
| * | |||||
| * Normally, you'll return an empty version of the adapted object, assuming | |||||
| * it implements @{interface:PhabricatorCustomFieldInterface}: | |||||
| * | |||||
| * return new ApplicationObject(); | |||||
| * | |||||
| * This is normally the only adapter method you need to override to enable | |||||
| * Herald rules to run against custom fields. | |||||
| * | |||||
| * @return null|PhabricatorCustomFieldInterface Template object. | |||||
| * @task customfield | |||||
| */ | |||||
| protected function getCustomFieldTemplateObject() { | |||||
| return null; | |||||
| } | |||||
| /** | |||||
| * Returns the prefix used to namespace Herald fields which are based on | |||||
| * custom fields. | |||||
| * | |||||
| * @return string Key prefix. | |||||
| * @task customfield | |||||
| */ | |||||
| private function getCustomKeyPrefix() { | |||||
| return 'herald.custom/'; | |||||
| } | |||||
| /** | |||||
| * Determine if a field key is based on a custom field or a regular internal | |||||
| * field. | |||||
| * | |||||
| * @param string Field key. | |||||
| * @return bool True if the field key is based on a custom field. | |||||
| * @task customfield | |||||
| */ | |||||
| private function isHeraldCustomKey($key) { | |||||
| $prefix = $this->getCustomKeyPrefix(); | |||||
| return (strncmp($key, $prefix, strlen($prefix)) == 0); | |||||
| } | |||||
| /** | |||||
| * Convert a custom field key into a Herald field key. | |||||
| * | |||||
| * @param string Custom field key. | |||||
| * @return string Herald field key. | |||||
| * @task customfield | |||||
| */ | |||||
| private function getHeraldKeyFromCustomKey($key) { | |||||
| return $this->getCustomKeyPrefix().$key; | |||||
| } | |||||
| /** | |||||
| * Get custom fields for this adapter, if appliable. This will either return | |||||
| * a field list or `null` if the adapted object does not implement custom | |||||
| * fields or the adapter does not support them. | |||||
| * | |||||
| * @return PhabricatorCustomFieldList|null List of fields, or `null`. | |||||
| * @task customfield | |||||
| */ | |||||
| private function getCustomFields() { | |||||
| if ($this->customFields === false) { | |||||
| $this->customFields = null; | |||||
| $template_object = $this->getCustomFieldTemplateObject(); | |||||
| if ($template_object) { | |||||
| $object = $this->getObject(); | |||||
| if (!$object) { | |||||
| $object = $template_object; | |||||
| } | |||||
| $fields = PhabricatorCustomField::getObjectFields( | |||||
| $object, | |||||
| PhabricatorCustomField::ROLE_HERALD); | |||||
| $fields->setViewer(PhabricatorUser::getOmnipotentUser()); | |||||
| $fields->readFieldsFromStorage($object); | |||||
| $this->customFields = $fields; | |||||
| } | |||||
| } | |||||
| return $this->customFields; | |||||
| } | |||||
| /** | |||||
| * Get a custom field by Herald field key, or `null` if it does not exist | |||||
| * or custom fields are not supported. | |||||
| * | |||||
| * @param string Herald field key. | |||||
| * @return PhabricatorCustomField|null Matching field, if it exists. | |||||
| * @task customfield | |||||
| */ | |||||
| private function getCustomField($herald_field_key) { | |||||
| $fields = $this->getCustomFields(); | |||||
| if (!$fields) { | |||||
| return null; | |||||
| } | |||||
| foreach ($fields->getFields() as $custom_field) { | |||||
| $key = $custom_field->getFieldKey(); | |||||
| if ($this->getHeraldKeyFromCustomKey($key) == $herald_field_key) { | |||||
| return $custom_field; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| /** | |||||
| * Get the field map for custom fields. | |||||
| * | |||||
| * @return map<string, string> Map of Herald field keys to field names. | |||||
| * @task customfield | |||||
| */ | |||||
| private function getCustomFieldNameMap() { | |||||
| $fields = $this->getCustomFields(); | |||||
| if (!$fields) { | |||||
| return array(); | |||||
| } | |||||
| $map = array(); | |||||
| foreach ($fields->getFields() as $field) { | |||||
| $key = $field->getFieldKey(); | |||||
| $name = $field->getHeraldFieldName(); | |||||
| $map[$this->getHeraldKeyFromCustomKey($key)] = $name; | |||||
| } | |||||
| return $map; | |||||
| } | |||||
| /** | |||||
| * Get the value for a custom field. | |||||
| * | |||||
| * @param string Herald field key. | |||||
| * @return wild Custom field value. | |||||
| * @task customfield | |||||
| */ | |||||
| private function getCustomFieldValue($field_key) { | |||||
| $field = $this->getCustomField($field_key); | |||||
| if (!$field) { | |||||
| return null; | |||||
| } | |||||
| return $field->getHeraldFieldValue(); | |||||
| } | |||||
| /** | |||||
| * Get the Herald conditions for a custom field. | |||||
| * | |||||
| * @param string Herald field key. | |||||
| * @return list<const> List of Herald conditions. | |||||
| * @task customfield | |||||
| */ | |||||
| private function getCustomFieldConditions($field_key) { | |||||
| $field = $this->getCustomField($field_key); | |||||
| if (!$field) { | |||||
| return array( | |||||
| self::CONDITION_NEVER, | |||||
| ); | |||||
| } | |||||
| return $field->getHeraldFieldConditions(); | |||||
| } | |||||
| /** | |||||
| * Get the Herald value type for a custom field and condition. | |||||
| * | |||||
| * @param string Herald field key. | |||||
| * @param const Herald condition constant. | |||||
| * @return const|null Herald value type constant, or null to use the default. | |||||
| * @task customfield | |||||
| */ | |||||
| private function getCustomFieldValueTypeForFieldAndCondition( | |||||
| $field_key, | |||||
| $condition) { | |||||
| $field = $this->getCustomField($field_key); | |||||
| if (!$field) { | |||||
| return self::VALUE_NONE; | |||||
| } | |||||
| return $field->getHeraldFieldValueType($condition); | |||||
| } | |||||
| } | } | ||||