1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-20 05:42:40 +01:00

Begin modularizing Herald fields

Summary:
Ref T8726. This lays groundwork for modularizing Herald fields and modularizes the "Content source" field.

This doesn't touch conditions or values yet.

Test Plan: Created a rule with a "content source" field, created a new task, saw rule apply.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: eadler, joshuaspence, epriestley

Maniphest Tasks: T8726

Differential Revision: https://secure.phabricator.com/D13488
This commit is contained in:
epriestley 2015-07-06 13:15:33 -07:00
parent d9ab267de6
commit b266412f3e
5 changed files with 157 additions and 19 deletions

View file

@ -934,6 +934,7 @@ phutil_register_library_map(array(
'HeraldCommitAdapter' => 'applications/herald/adapter/HeraldCommitAdapter.php',
'HeraldCondition' => 'applications/herald/storage/HeraldCondition.php',
'HeraldConditionTranscript' => 'applications/herald/storage/transcript/HeraldConditionTranscript.php',
'HeraldContentSourceField' => 'applications/herald/field/HeraldContentSourceField.php',
'HeraldController' => 'applications/herald/controller/HeraldController.php',
'HeraldCustomAction' => 'applications/herald/extension/HeraldCustomAction.php',
'HeraldDAO' => 'applications/herald/storage/HeraldDAO.php',
@ -943,6 +944,7 @@ phutil_register_library_map(array(
'HeraldDisableController' => 'applications/herald/controller/HeraldDisableController.php',
'HeraldEffect' => 'applications/herald/engine/HeraldEffect.php',
'HeraldEngine' => 'applications/herald/engine/HeraldEngine.php',
'HeraldField' => 'applications/herald/field/HeraldField.php',
'HeraldInvalidActionException' => 'applications/herald/engine/exception/HeraldInvalidActionException.php',
'HeraldInvalidConditionException' => 'applications/herald/engine/exception/HeraldInvalidConditionException.php',
'HeraldManageGlobalRulesCapability' => 'applications/herald/capability/HeraldManageGlobalRulesCapability.php',
@ -4429,6 +4431,7 @@ phutil_register_library_map(array(
'HeraldCommitAdapter' => 'HeraldAdapter',
'HeraldCondition' => 'HeraldDAO',
'HeraldConditionTranscript' => 'Phobject',
'HeraldContentSourceField' => 'HeraldField',
'HeraldController' => 'PhabricatorController',
'HeraldCustomAction' => 'Phobject',
'HeraldDAO' => 'PhabricatorLiskDAO',
@ -4438,6 +4441,7 @@ phutil_register_library_map(array(
'HeraldDisableController' => 'HeraldController',
'HeraldEffect' => 'Phobject',
'HeraldEngine' => 'Phobject',
'HeraldField' => 'Phobject',
'HeraldInvalidActionException' => 'Exception',
'HeraldInvalidConditionException' => 'Exception',
'HeraldManageGlobalRulesCapability' => 'PhabricatorPolicyCapability',

View file

@ -24,7 +24,6 @@ abstract class HeraldAdapter extends Phobject {
const FIELD_RULE = 'rule';
const FIELD_AFFECTED_PACKAGE = 'affected-package';
const FIELD_AFFECTED_PACKAGE_OWNER = 'affected-package-owner';
const FIELD_CONTENT_SOURCE = 'contentsource';
const FIELD_ALWAYS = 'always';
const FIELD_AUTHOR_PROJECTS = 'authorprojects';
const FIELD_PROJECTS = 'projects';
@ -113,6 +112,7 @@ abstract class HeraldAdapter extends Phobject {
private $emailPHIDs = array();
private $forcedEmailPHIDs = array();
private $unsubscribedPHIDs;
private $fieldMap;
public function getEmailPHIDs() {
return array_values($this->emailPHIDs);
@ -190,11 +190,14 @@ abstract class HeraldAdapter extends Phobject {
abstract public function getHeraldName();
public function getHeraldField($field_name) {
$impl = $this->getFieldImplementation($field_name);
if ($impl) {
return $impl->getHeraldFieldValue($this->getObject());
}
switch ($field_name) {
case self::FIELD_RULE:
return null;
case self::FIELD_CONTENT_SOURCE:
return $this->getContentSource()->getSource();
case self::FIELD_ALWAYS:
return true;
case self::FIELD_IS_NEW_OBJECT:
@ -354,9 +357,52 @@ abstract class HeraldAdapter extends Phobject {
/* -( Fields )------------------------------------------------------------- */
private function getFieldImplementationMap() {
if ($this->fieldMap === null) {
// We can't use PhutilClassMapQuery here because field expansion
// depends on the adapter and object.
$object = $this->getObject();
$map = array();
$all = HeraldField::getAllFields();
foreach ($all as $key => $field) {
if (!$field->supportsObject($object)) {
continue;
}
$subfields = $field->getFieldsForObject($object);
foreach ($subfields as $subkey => $subfield) {
if (isset($map[$subkey])) {
throw new Exception(
pht(
'Two HeraldFields (of classes "%s" and "%s") have the same '.
'field key ("%s") after expansion for an object of class '.
'"%s" inside adapter "%s". Each field must have a unique '.
'field key.',
get_class($subfield),
get_class($map[$subkey]),
$subkey,
get_class($object),
get_class($this)));
}
$subfield = id(clone $subfield)->setAdapter($this);
$map[$subkey] = $subfield;
}
}
$this->fieldMap = $map;
}
return $this->fieldMap;
}
private function getFieldImplementation($key) {
return idx($this->getFieldImplementationMap(), $key);
}
public function getFields() {
$fields = array();
$fields = array_keys($this->getFieldImplementationMap());
$fields[] = self::FIELD_ALWAYS;
$fields[] = self::FIELD_RULE;
@ -373,7 +419,9 @@ abstract class HeraldAdapter extends Phobject {
}
public function getFieldNameMap() {
return array(
$map = mpull($this->getFieldImplementationMap(), 'getHeraldFieldName');
return $map + array(
self::FIELD_TITLE => pht('Title'),
self::FIELD_BODY => pht('Body'),
self::FIELD_AUTHOR => pht('Author'),
@ -394,7 +442,6 @@ abstract class HeraldAdapter extends Phobject {
self::FIELD_AFFECTED_PACKAGE => pht('Any affected package'),
self::FIELD_AFFECTED_PACKAGE_OWNER =>
pht("Any affected package's owner"),
self::FIELD_CONTENT_SOURCE => pht('Content Source'),
self::FIELD_ALWAYS => pht('Always'),
self::FIELD_AUTHOR_PROJECTS => pht("Author's projects"),
self::FIELD_PROJECTS => pht('Projects'),
@ -452,6 +499,11 @@ abstract class HeraldAdapter extends Phobject {
}
public function getConditionsForField($field) {
$impl = $this->getFieldImplementation($field);
if ($impl) {
return $impl->getHeraldFieldConditions();
}
switch ($field) {
case self::FIELD_TITLE:
case self::FIELD_BODY:
@ -526,11 +578,6 @@ abstract class HeraldAdapter extends Phobject {
self::CONDITION_RULE,
self::CONDITION_NOT_RULE,
);
case self::FIELD_CONTENT_SOURCE:
return array(
self::CONDITION_IS,
self::CONDITION_IS_NOT,
);
case self::FIELD_ALWAYS:
return array(
self::CONDITION_UNCONDITIONALLY,
@ -940,6 +987,10 @@ abstract class HeraldAdapter extends Phobject {
public function getValueTypeForFieldAndCondition($field, $condition) {
$impl = $this->getFieldImplementation($field);
if ($impl) {
return $impl->getHeraldFieldValueType($condition);
}
if ($this->isHeraldCustomKey($field)) {
$value_type = $this->getCustomFieldValueTypeForFieldAndCondition(
@ -958,13 +1009,7 @@ abstract class HeraldAdapter extends Phobject {
return self::VALUE_TEXT;
case self::CONDITION_IS:
case self::CONDITION_IS_NOT:
switch ($field) {
case self::FIELD_CONTENT_SOURCE:
return self::VALUE_CONTENT_SOURCE;
default:
return self::VALUE_TEXT;
}
break;
return self::VALUE_TEXT;
case self::CONDITION_IS_ANY:
case self::CONDITION_IS_NOT_ANY:
switch ($field) {

View file

@ -67,7 +67,6 @@ final class HeraldManiphestTaskAdapter extends HeraldAdapter {
self::FIELD_AUTHOR,
self::FIELD_ASSIGNEE,
self::FIELD_CC,
self::FIELD_CONTENT_SOURCE,
self::FIELD_PROJECTS,
self::FIELD_TASK_PRIORITY,
self::FIELD_TASK_STATUS,

View file

@ -0,0 +1,30 @@
<?php
final class HeraldContentSourceField extends HeraldField {
const FIELDCONST = 'contentsource';
public function getHeraldFieldName() {
return pht('Content source');
}
public function getHeraldFieldValue($object) {
return $this->getAdapter()->getContentSource()->getSource();
}
public function getHeraldFieldConditions() {
return array(
HeraldAdapter::CONDITION_IS,
HeraldAdapter::CONDITION_IS_NOT,
);
}
public function getHeraldFieldValueType($condition) {
return HeraldAdapter::VALUE_CONTENT_SOURCE;
}
public function supportsObject($object) {
return true;
}
}

View file

@ -0,0 +1,60 @@
<?php
abstract class HeraldField extends Phobject {
private $adapter;
abstract public function getHeraldFieldName();
abstract public function getHeraldFieldValue($object);
abstract public function getHeraldFieldConditions();
abstract public function getHeraldFieldValueType($condition);
abstract public function supportsObject($object);
public function getFieldsForObject($object) {
return array($this->getFieldConstant() => $this);
}
final public function setAdapter(HeraldAdapter $adapter) {
$this->adapter = $adapter;
return $this;
}
final public function getAdapter() {
return $this->adapter;
}
final public function getFieldConstant() {
$class = new ReflectionClass($this);
$const = $class->getConstant('FIELDCONST');
if ($const === false) {
throw new Exception(
pht(
'"%s" class "%s" must define a "%s" property.',
__CLASS__,
get_class($this),
'FIELDCONST'));
}
if (!is_string($const) || (strlen($const) > 32)) {
throw new Exception(
pht(
'"%s" class "%s" has an invalid "%s" property. Field constants '.
'must be strings and no more than 32 bytes in length.',
__CLASS__,
get_class($this),
'FIELDCONST'));
}
return $const;
}
final public static function getAllFields() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getFieldConstant')
->execute();
}
}