mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-18 21:02:41 +01:00
Refactor some Herald code
Summary: I was reading herald code for a task and realized that the method was really long. So I refactor it to shorter methods. Test Plan: was still able to create a differential rule and commit rule; and verified that dry-run still worked. Reviewers: epriestley, tuomaspelkonen Reviewed By: epriestley CC: aran, epriestley Differential Revision: 1077
This commit is contained in:
parent
fbfb263cd9
commit
f46e12d0ca
1 changed files with 257 additions and 234 deletions
|
@ -71,165 +71,15 @@ class HeraldRuleController extends HeraldController {
|
|||
$e_name = true;
|
||||
$errors = array();
|
||||
if ($request->isFormPost() && $request->getStr('save')) {
|
||||
$rule->setName($request->getStr('name'));
|
||||
$rule->setMustMatchAll(($request->getStr('must_match') == 'all'));
|
||||
|
||||
$repetition_policy_param = $request->getStr('repetition_policy');
|
||||
$rule->setRepetitionPolicy(
|
||||
HeraldRepetitionPolicyConfig::toInt($repetition_policy_param)
|
||||
);
|
||||
|
||||
if (!strlen($rule->getName())) {
|
||||
$e_name = "Required";
|
||||
$errors[] = "Rule must have a name.";
|
||||
}
|
||||
|
||||
$data = json_decode($request->getStr('rule'), true);
|
||||
if (!is_array($data) ||
|
||||
!$data['conditions'] ||
|
||||
!$data['actions']) {
|
||||
throw new Exception("Failed to decode rule data.");
|
||||
}
|
||||
|
||||
$conditions = array();
|
||||
foreach ($data['conditions'] as $condition) {
|
||||
if ($condition === null) {
|
||||
// We manage this as a sparse array on the client, so may receive
|
||||
// NULL if conditions have been removed.
|
||||
continue;
|
||||
}
|
||||
|
||||
$obj = new HeraldCondition();
|
||||
$obj->setFieldName($condition[0]);
|
||||
$obj->setFieldCondition($condition[1]);
|
||||
|
||||
if (is_array($condition[2])) {
|
||||
$obj->setValue(array_keys($condition[2]));
|
||||
} else {
|
||||
$obj->setValue($condition[2]);
|
||||
}
|
||||
|
||||
$cond_type = $obj->getFieldCondition();
|
||||
|
||||
if ($cond_type == HeraldConditionConfig::CONDITION_REGEXP) {
|
||||
if (@preg_match($obj->getValue(), '') === false) {
|
||||
$errors[] =
|
||||
'The regular expression "'.$obj->getValue().'" is not valid. '.
|
||||
'Regular expressions must have enclosing characters (e.g. '.
|
||||
'"@/path/to/file@", not "/path/to/file") and be syntactically '.
|
||||
'correct.';
|
||||
}
|
||||
}
|
||||
|
||||
if ($cond_type == HeraldConditionConfig::CONDITION_REGEXP_PAIR) {
|
||||
$json = json_decode($obj->getValue(), true);
|
||||
if (!is_array($json)) {
|
||||
$errors[] =
|
||||
'The regular expression pair "'.$obj->getValue().'" is not '.
|
||||
'valid JSON. Enter a valid JSON array with two elements.';
|
||||
} else {
|
||||
if (count($json) != 2) {
|
||||
$errors[] =
|
||||
'The regular expression pair "'.$obj->getValue().'" must have '.
|
||||
'exactly two elements.';
|
||||
} else {
|
||||
$key_regexp = array_shift($json);
|
||||
$val_regexp = array_shift($json);
|
||||
|
||||
if (@preg_match($key_regexp, '') === false) {
|
||||
$errors[] =
|
||||
'The first regexp, "'.$key_regexp.'" in the regexp pair '.
|
||||
'is not a valid regexp.';
|
||||
}
|
||||
if (@preg_match($val_regexp, '') === false) {
|
||||
$errors[] =
|
||||
'The second regexp, "'.$val_regexp.'" in the regexp pair '.
|
||||
'is not a valid regexp.';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$conditions[] = $obj;
|
||||
}
|
||||
|
||||
$actions = array();
|
||||
foreach ($data['actions'] as $action) {
|
||||
if ($action === null) {
|
||||
// Sparse on the client; removals can give us NULLs.
|
||||
continue;
|
||||
}
|
||||
|
||||
$obj = new HeraldAction();
|
||||
$obj->setAction($action[0]);
|
||||
|
||||
if (!isset($action[1])) {
|
||||
// Legitimate for any action which doesn't need a target, like
|
||||
// "Do nothing".
|
||||
$action[1] = null;
|
||||
}
|
||||
|
||||
if (is_array($action[1])) {
|
||||
$obj->setTarget(array_keys($action[1]));
|
||||
} else {
|
||||
$obj->setTarget($action[1]);
|
||||
}
|
||||
|
||||
$actions[] = $obj;
|
||||
}
|
||||
|
||||
$rule->attachConditions($conditions);
|
||||
$rule->attachActions($actions);
|
||||
list($e_name, $errors) = $this->saveRule($rule, $request);
|
||||
|
||||
if (!$errors) {
|
||||
try {
|
||||
|
||||
// TODO
|
||||
// $rule->openTransaction();
|
||||
$rule->save();
|
||||
$rule->saveConditions($conditions);
|
||||
$rule->saveActions($actions);
|
||||
// $rule->saveTransaction();
|
||||
|
||||
$uri = '/herald/view/'.$rule->getContentType().'/';
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($uri);
|
||||
} catch (AphrontQueryDuplicateKeyException $ex) {
|
||||
$e_name = "Not Unique";
|
||||
$errors[] = "Rule name is not unique. Choose a unique name.";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$phids = array();
|
||||
$phids[] = $rule->getAuthorPHID();
|
||||
|
||||
foreach ($rule->getActions() as $action) {
|
||||
if (!is_array($action->getTarget())) {
|
||||
continue;
|
||||
}
|
||||
foreach ($action->getTarget() as $target) {
|
||||
$target = (array)$target;
|
||||
foreach ($target as $phid) {
|
||||
$phids[] = $phid;
|
||||
}
|
||||
$uri = '/herald/view/'.$rule->getContentType().'/';
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($uri);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($rule->getConditions() as $condition) {
|
||||
$value = $condition->getValue();
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $phid) {
|
||||
$phids[] = $phid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$handles = id(new PhabricatorObjectHandleData($phids))
|
||||
->loadHandles();
|
||||
|
||||
if ($errors) {
|
||||
$error_view = new AphrontErrorView();
|
||||
$error_view->setTitle('Form Errors');
|
||||
|
@ -238,72 +88,10 @@ class HeraldRuleController extends HeraldController {
|
|||
$error_view = null;
|
||||
}
|
||||
|
||||
$options = array(
|
||||
'all' => 'all of',
|
||||
'any' => 'any of',
|
||||
);
|
||||
$must_match_selector = $this->getMustMatchSelector($rule);
|
||||
$repetition_selector = $this->getRepetitionSelector($rule);
|
||||
|
||||
$selected = $rule->getMustMatchAll() ? 'all' : 'any';
|
||||
|
||||
$must_match = array();
|
||||
foreach ($options as $key => $option) {
|
||||
$must_match[] = phutil_render_tag(
|
||||
'option',
|
||||
array(
|
||||
'selected' => ($selected == $key) ? 'selected' : null,
|
||||
'value' => $key,
|
||||
),
|
||||
phutil_escape_html($option));
|
||||
}
|
||||
$must_match =
|
||||
'<select name="must_match">'.
|
||||
implode("\n", $must_match).
|
||||
'</select>';
|
||||
|
||||
if ($rule->getID()) {
|
||||
$action = '/herald/rule/'.$rule->getID().'/';
|
||||
} else {
|
||||
$action = '/herald/rule/'.$rule->getID().'/';
|
||||
}
|
||||
|
||||
// Make the selector for choosing how often this rule should be repeated
|
||||
$repetition_selector = "";
|
||||
$repetition_policy = HeraldRepetitionPolicyConfig::toString(
|
||||
$rule->getRepetitionPolicy()
|
||||
);
|
||||
$repetition_options = HeraldRepetitionPolicyConfig::getMapForContentType(
|
||||
$rule->getContentType()
|
||||
);
|
||||
|
||||
if (empty($repetition_options)) {
|
||||
// default option is 'every time'
|
||||
$repetition_selector = idx(
|
||||
HeraldRepetitionPolicyConfig::getMap(),
|
||||
HeraldRepetitionPolicyConfig::EVERY
|
||||
);
|
||||
} else if (count($repetition_options) == 1) {
|
||||
// if there's only 1 option, just pick it for the user
|
||||
$repetition_selector = reset($repetition_options);
|
||||
} else {
|
||||
// give the user all the options for this rule type
|
||||
$tags = array();
|
||||
|
||||
foreach ($repetition_options as $name => $option) {
|
||||
$tags[] = phutil_render_tag(
|
||||
'option',
|
||||
array (
|
||||
'selected' => ($repetition_policy == $name) ? 'selected' : null,
|
||||
'value' => $name,
|
||||
),
|
||||
phutil_escape_html($option)
|
||||
);
|
||||
}
|
||||
|
||||
$repetition_selector =
|
||||
'<select name="repetition_policy">'.
|
||||
implode("\n", $tags).
|
||||
'</select>';
|
||||
}
|
||||
$handles = $this->loadHandles($rule);
|
||||
|
||||
require_celerity_resource('herald-css');
|
||||
|
||||
|
@ -351,7 +139,7 @@ class HeraldRuleController extends HeraldController {
|
|||
),
|
||||
'Create New Condition').
|
||||
'</div>'.
|
||||
'<p>When '.$must_match.' these conditions are met:</p>'.
|
||||
'<p>When '.$must_match_selector.' these conditions are met:</p>'.
|
||||
'<div style="clear: both;"></div>'.
|
||||
javelin_render_tag(
|
||||
'table',
|
||||
|
@ -392,6 +180,157 @@ class HeraldRuleController extends HeraldController {
|
|||
->setValue('Save Rule')
|
||||
->addCancelButton('/herald/view/'.$rule->getContentType().'/'));
|
||||
|
||||
$this->setupEditorBehavior($rule, $handles);
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setHeader('Edit Herald Rule');
|
||||
$panel->setWidth(AphrontPanelView::WIDTH_WIDE);
|
||||
$panel->appendChild($form);
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
array(
|
||||
$error_view,
|
||||
$panel,
|
||||
),
|
||||
array(
|
||||
'title' => 'Edit Rule',
|
||||
));
|
||||
}
|
||||
|
||||
private function saveRule($rule, $request) {
|
||||
$rule->setName($request->getStr('name'));
|
||||
$rule->setMustMatchAll(($request->getStr('must_match') == 'all'));
|
||||
|
||||
$repetition_policy_param = $request->getStr('repetition_policy');
|
||||
$rule->setRepetitionPolicy(
|
||||
HeraldRepetitionPolicyConfig::toInt($repetition_policy_param)
|
||||
);
|
||||
|
||||
$e_name = true;
|
||||
$errors = array();
|
||||
|
||||
if (!strlen($rule->getName())) {
|
||||
$e_name = "Required";
|
||||
$errors[] = "Rule must have a name.";
|
||||
}
|
||||
|
||||
$data = json_decode($request->getStr('rule'), true);
|
||||
if (!is_array($data) ||
|
||||
!$data['conditions'] ||
|
||||
!$data['actions']) {
|
||||
throw new Exception("Failed to decode rule data.");
|
||||
}
|
||||
|
||||
$conditions = array();
|
||||
foreach ($data['conditions'] as $condition) {
|
||||
if ($condition === null) {
|
||||
// We manage this as a sparse array on the client, so may receive
|
||||
// NULL if conditions have been removed.
|
||||
continue;
|
||||
}
|
||||
|
||||
$obj = new HeraldCondition();
|
||||
$obj->setFieldName($condition[0]);
|
||||
$obj->setFieldCondition($condition[1]);
|
||||
|
||||
if (is_array($condition[2])) {
|
||||
$obj->setValue(array_keys($condition[2]));
|
||||
} else {
|
||||
$obj->setValue($condition[2]);
|
||||
}
|
||||
|
||||
$cond_type = $obj->getFieldCondition();
|
||||
|
||||
if ($cond_type == HeraldConditionConfig::CONDITION_REGEXP) {
|
||||
if (@preg_match($obj->getValue(), '') === false) {
|
||||
$errors[] =
|
||||
'The regular expression "'.$obj->getValue().'" is not valid. '.
|
||||
'Regular expressions must have enclosing characters (e.g. '.
|
||||
'"@/path/to/file@", not "/path/to/file") and be syntactically '.
|
||||
'correct.';
|
||||
}
|
||||
}
|
||||
|
||||
if ($cond_type == HeraldConditionConfig::CONDITION_REGEXP_PAIR) {
|
||||
$json = json_decode($obj->getValue(), true);
|
||||
if (!is_array($json)) {
|
||||
$errors[] =
|
||||
'The regular expression pair "'.$obj->getValue().'" is not '.
|
||||
'valid JSON. Enter a valid JSON array with two elements.';
|
||||
} else {
|
||||
if (count($json) != 2) {
|
||||
$errors[] =
|
||||
'The regular expression pair "'.$obj->getValue().'" must have '.
|
||||
'exactly two elements.';
|
||||
} else {
|
||||
$key_regexp = array_shift($json);
|
||||
$val_regexp = array_shift($json);
|
||||
|
||||
if (@preg_match($key_regexp, '') === false) {
|
||||
$errors[] =
|
||||
'The first regexp, "'.$key_regexp.'" in the regexp pair '.
|
||||
'is not a valid regexp.';
|
||||
}
|
||||
if (@preg_match($val_regexp, '') === false) {
|
||||
$errors[] =
|
||||
'The second regexp, "'.$val_regexp.'" in the regexp pair '.
|
||||
'is not a valid regexp.';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$conditions[] = $obj;
|
||||
}
|
||||
|
||||
$actions = array();
|
||||
foreach ($data['actions'] as $action) {
|
||||
if ($action === null) {
|
||||
// Sparse on the client; removals can give us NULLs.
|
||||
continue;
|
||||
}
|
||||
|
||||
$obj = new HeraldAction();
|
||||
$obj->setAction($action[0]);
|
||||
|
||||
if (!isset($action[1])) {
|
||||
// Legitimate for any action which doesn't need a target, like
|
||||
// "Do nothing".
|
||||
$action[1] = null;
|
||||
}
|
||||
|
||||
if (is_array($action[1])) {
|
||||
$obj->setTarget(array_keys($action[1]));
|
||||
} else {
|
||||
$obj->setTarget($action[1]);
|
||||
}
|
||||
|
||||
$actions[] = $obj;
|
||||
}
|
||||
|
||||
$rule->attachConditions($conditions);
|
||||
$rule->attachActions($actions);
|
||||
|
||||
if (!$errors) {
|
||||
try {
|
||||
|
||||
// TODO
|
||||
// $rule->openTransaction();
|
||||
$rule->save();
|
||||
$rule->saveConditions($conditions);
|
||||
$rule->saveActions($actions);
|
||||
// $rule->saveTransaction();
|
||||
|
||||
} catch (AphrontQueryDuplicateKeyException $ex) {
|
||||
$e_name = "Not Unique";
|
||||
$errors[] = "Rule name is not unique. Choose a unique name.";
|
||||
}
|
||||
}
|
||||
|
||||
return array($e_name, $errors);
|
||||
}
|
||||
|
||||
private function setupEditorBehavior($rule, $handles) {
|
||||
$serial_conditions = array(
|
||||
array('default', 'default', ''),
|
||||
);
|
||||
|
@ -474,27 +413,111 @@ class HeraldRuleController extends HeraldController {
|
|||
'herald-rule-editor',
|
||||
array(
|
||||
'root' => 'herald-rule-edit-form',
|
||||
'conditions' => (object) $serial_conditions,
|
||||
'actions' => (object) $serial_actions,
|
||||
'conditions' => (object)$serial_conditions,
|
||||
'actions' => (object)$serial_actions,
|
||||
'template' => $this->buildTokenizerTemplates() + array(
|
||||
'rules' => $all_rules,
|
||||
),
|
||||
'info' => $config_info,
|
||||
));
|
||||
}
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setHeader('Edit Herald Rule');
|
||||
$panel->setWidth(AphrontPanelView::WIDTH_WIDE);
|
||||
$panel->appendChild($form);
|
||||
private function loadHandles($rule) {
|
||||
$phids = array();
|
||||
$phids[] = $rule->getAuthorPHID();
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
array(
|
||||
$error_view,
|
||||
$panel,
|
||||
),
|
||||
array(
|
||||
'title' => 'Edit Rule',
|
||||
));
|
||||
foreach ($rule->getActions() as $action) {
|
||||
if (!is_array($action->getTarget())) {
|
||||
continue;
|
||||
}
|
||||
foreach ($action->getTarget() as $target) {
|
||||
$target = (array)$target;
|
||||
foreach ($target as $phid) {
|
||||
$phids[] = $phid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($rule->getConditions() as $condition) {
|
||||
$value = $condition->getValue();
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $phid) {
|
||||
$phids[] = $phid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$handles = id(new PhabricatorObjectHandleData($phids))
|
||||
->loadHandles();
|
||||
return $handles;
|
||||
}
|
||||
|
||||
private function getMustMatchSelector($rule) {
|
||||
$options = array(
|
||||
'all' => 'all of',
|
||||
'any' => 'any of',
|
||||
);
|
||||
|
||||
$selected = $rule->getMustMatchAll() ? 'all' : 'any';
|
||||
|
||||
$must_match = array();
|
||||
foreach ($options as $key => $option) {
|
||||
$must_match[] = phutil_render_tag(
|
||||
'option',
|
||||
array(
|
||||
'selected' => ($selected == $key) ? 'selected' : null,
|
||||
'value' => $key,
|
||||
),
|
||||
phutil_escape_html($option));
|
||||
}
|
||||
$must_match =
|
||||
'<select name="must_match">' .
|
||||
implode("\n", $must_match) .
|
||||
'</select>';
|
||||
return $must_match;
|
||||
}
|
||||
|
||||
private function getRepetitionSelector($rule) {
|
||||
// Make the selector for choosing how often this rule should be repeated
|
||||
$repetition_policy = HeraldRepetitionPolicyConfig::toString(
|
||||
$rule->getRepetitionPolicy()
|
||||
);
|
||||
$repetition_options = HeraldRepetitionPolicyConfig::getMapForContentType(
|
||||
$rule->getContentType()
|
||||
);
|
||||
|
||||
if (empty($repetition_options)) {
|
||||
// default option is 'every time'
|
||||
$repetition_selector = idx(
|
||||
HeraldRepetitionPolicyConfig::getMap(),
|
||||
HeraldRepetitionPolicyConfig::EVERY
|
||||
);
|
||||
return $repetition_selector;
|
||||
} else if (count($repetition_options) == 1) {
|
||||
// if there's only 1 option, just pick it for the user
|
||||
$repetition_selector = reset($repetition_options);
|
||||
return $repetition_selector;
|
||||
} else {
|
||||
// give the user all the options for this rule type
|
||||
$tags = array();
|
||||
|
||||
foreach ($repetition_options as $name => $option) {
|
||||
$tags[] = phutil_render_tag(
|
||||
'option',
|
||||
array(
|
||||
'selected' => ($repetition_policy == $name) ? 'selected' : null,
|
||||
'value' => $name,
|
||||
),
|
||||
phutil_escape_html($option)
|
||||
);
|
||||
}
|
||||
|
||||
$repetition_selector =
|
||||
'<select name="repetition_policy">' .
|
||||
implode("\n", $tags) .
|
||||
'</select>';
|
||||
return $repetition_selector;
|
||||
}
|
||||
}
|
||||
|
||||
protected function buildTokenizerTemplates() {
|
||||
|
|
Loading…
Reference in a new issue