From 4c14dd1e8925677f407b5ef4f1bd268a7d460daf Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 5 Feb 2018 05:58:21 -0800 Subject: [PATCH] (stable) Fix a Herald repetition policy selection error for rule types which support only one policy Summary: Ref T13048. See . When a rule supports only one repetition policy (always "every time") like "Commit Hook" rules, we don't render a control for `repetition_policy` and fail to update it when saving. Before the changes to support the new "if the rule did not match the last time" policy, this workflow just defaulted to "every time" if the input was invalid, but this was changed by accident in D18926 when I removed some of the toInt/toString juggling code. (This patch also prevents users from fiddling with the form to create a rule which evaluates with an invalid policy; this wasn't validated before.) Test Plan: - Created new "Commit Hook" (only one policy available) rule. - Saved existing "Commit Hook" rule. - Created new "Task" (multiple policies) rule. - Saved existing Task rule. - Set task rule to each repetition policy, saved, verified the save worked. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13048 Differential Revision: https://secure.phabricator.com/D18992 --- .../controller/HeraldRuleController.php | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/applications/herald/controller/HeraldRuleController.php b/src/applications/herald/controller/HeraldRuleController.php index c61c29e90e..d400f8ae90 100644 --- a/src/applications/herald/controller/HeraldRuleController.php +++ b/src/applications/herald/controller/HeraldRuleController.php @@ -265,7 +265,15 @@ final class HeraldRuleController extends HeraldController { $new_name = $request->getStr('name'); $match_all = ($request->getStr('must_match') == 'all'); - $repetition_policy_param = $request->getStr('repetition_policy'); + $repetition_policy = $request->getStr('repetition_policy'); + + // If the user selected an invalid policy, or there's only one possible + // value so we didn't render a control, adjust the value to the first + // valid policy value. + $repetition_options = $this->getRepetitionOptionMap($adapter); + if (!isset($repetition_options[$repetition_policy])) { + $repetition_policy = head_key($repetition_options); + } $e_name = true; $errors = array(); @@ -348,7 +356,7 @@ final class HeraldRuleController extends HeraldController { $match_all, $conditions, $actions, - $repetition_policy_param); + $repetition_policy); $xactions = array(); $xactions[] = id(new HeraldRuleTransaction()) @@ -373,7 +381,7 @@ final class HeraldRuleController extends HeraldController { // mutate current rule, so it would be sent to the client in the right state $rule->setMustMatchAll((int)$match_all); $rule->setName($new_name); - $rule->setRepetitionPolicyStringConstant($repetition_policy_param); + $rule->setRepetitionPolicyStringConstant($repetition_policy); $rule->attachConditions($conditions); $rule->attachActions($actions); @@ -594,13 +602,9 @@ final class HeraldRuleController extends HeraldController { */ private function renderRepetitionSelector($rule, HeraldAdapter $adapter) { $repetition_policy = $rule->getRepetitionPolicyStringConstant(); - - $repetition_options = $adapter->getRepetitionOptions(); - $repetition_names = HeraldRule::getRepetitionPolicySelectOptionMap(); - $repetition_map = array_select_keys($repetition_names, $repetition_options); - + $repetition_map = $this->getRepetitionOptionMap($adapter); if (count($repetition_map) < 2) { - return head($repetition_names); + return head($repetition_map); } else { return AphrontFormSelectControl::renderSelectTag( $repetition_policy, @@ -611,6 +615,11 @@ final class HeraldRuleController extends HeraldController { } } + private function getRepetitionOptionMap(HeraldAdapter $adapter) { + $repetition_options = $adapter->getRepetitionOptions(); + $repetition_names = HeraldRule::getRepetitionPolicySelectOptionMap(); + return array_select_keys($repetition_names, $repetition_options); + } protected function buildTokenizerTemplates() { $template = new AphrontTokenizerTemplateView();