diff --git a/src/applications/herald/adapter/HeraldAdapter.php b/src/applications/herald/adapter/HeraldAdapter.php --- a/src/applications/herald/adapter/HeraldAdapter.php +++ b/src/applications/herald/adapter/HeraldAdapter.php @@ -1203,7 +1203,15 @@ $rule_global = HeraldRuleTypeConfig::RULE_TYPE_GLOBAL; $action_type = $action->getAction(); - $action_name = idx($this->getActionNameMap($rule_global), $action_type); + + $default = $this->isHeraldCustomKey($action_type) + ? pht('(Unknown Custom Action "%s") equals', $action_type) + : pht('(Unknown Action "%s") equals', $action_type); + + $action_name = idx( + $this->getActionNameMap($rule_global), + $action_type, + $default); $target = $this->renderActionTargetAsText($action, $handles); @@ -1525,7 +1533,9 @@ $supported = $this->getActions($rule_type); $supported = array_fuse($supported); if (empty($supported[$action])) { - throw new Exception( + return new HeraldApplyTranscript( + $effect, + false, pht( 'Adapter "%s" does not support action "%s" for rule type "%s".', get_class($this), @@ -1548,7 +1558,9 @@ $result = $this->handleCustomHeraldEffect($effect); if (!$result) { - throw new Exception( + return new HeraldApplyTranscript( + $effect, + false, pht( 'No custom action exists to handle rule action "%s".', $action)); diff --git a/src/applications/herald/adapter/HeraldDifferentialDiffAdapter.php b/src/applications/herald/adapter/HeraldDifferentialDiffAdapter.php --- a/src/applications/herald/adapter/HeraldDifferentialDiffAdapter.php +++ b/src/applications/herald/adapter/HeraldDifferentialDiffAdapter.php @@ -154,7 +154,10 @@ pht('Blocked diff.')); break; default: - throw new Exception(pht('No rules to handle action "%s"!', $action)); + $result[] = new HeraldApplyTranscript( + $effect, + false, + pht('No rules to handle action "%s"!', $action)); } } diff --git a/src/applications/herald/controller/HeraldRuleController.php b/src/applications/herald/controller/HeraldRuleController.php --- a/src/applications/herald/controller/HeraldRuleController.php +++ b/src/applications/herald/controller/HeraldRuleController.php @@ -320,7 +320,7 @@ try { $adapter->willSaveAction($rule, $obj); } catch (HeraldInvalidActionException $ex) { - $errors[] = $ex; + $errors[] = $ex->getMessage(); } $actions[] = $obj; @@ -354,7 +354,6 @@ if ($rule->getConditions()) { $serial_conditions = array(); foreach ($rule->getConditions() as $condition) { - $value = $condition->getValue(); switch ($condition->getFieldName()) { case HeraldAdapter::FIELD_TASK_PRIORITY: @@ -394,10 +393,10 @@ $serial_actions = array( array('default', ''), ); + if ($rule->getActions()) { $serial_actions = array(); foreach ($rule->getActions() as $action) { - switch ($action->getAction()) { case HeraldAdapter::ACTION_FLAG: case HeraldAdapter::ACTION_BLOCK: @@ -438,21 +437,39 @@ // names of, so that saving a rule without touching anything doesn't change // it. foreach ($rule->getConditions() as $condition) { - if (empty($field_map[$condition->getFieldName()])) { - $field_map[$condition->getFieldName()] = pht('<Unknown Field>'); + $field_name = $condition->getFieldName(); + + if (empty($field_map[$field_name])) { + $field_map[$field_name] = pht('<Unknown Field "%s">', $field_name); } } $actions = $adapter->getActions($rule->getRuleType()); $action_map = array_select_keys($all_actions, $actions); + // Populate any actions which exist in the rule but which we don't know the + // names of, so that saving a rule without touching anything doesn't change + // it. + foreach ($rule->getActions() as $action) { + $action_name = $action->getAction(); + + if (empty($action_map[$action_name])) { + $action_map[$action_name] = pht('<Unknown Action "%s">', $action_name); + } + } + + $config_info = array(); $config_info['fields'] = $field_map; $config_info['conditions'] = $all_conditions; $config_info['actions'] = $action_map; foreach ($config_info['fields'] as $field => $name) { - $field_conditions = $adapter->getConditionsForField($field); + try { + $field_conditions = $adapter->getConditionsForField($field); + } catch (Exception $ex) { + $field_conditions = array(HeraldAdapter::CONDITION_UNCONDITIONALLY); + } $config_info['conditionMap'][$field] = $field_conditions; } @@ -468,9 +485,15 @@ $config_info['rule_type'] = $rule->getRuleType(); foreach ($config_info['actions'] as $action => $name) { - $config_info['targets'][$action] = $adapter->getValueTypeForAction( - $action, - $rule->getRuleType()); + try { + $action_value = $adapter->getValueTypeForAction( + $action, + $rule->getRuleType()); + } catch (Exception $ex) { + $action_value = array(HeraldAdapter::VALUE_NONE); + } + + $config_info['targets'][$action] = $action_value; } $changeflag_options = diff --git a/src/applications/herald/controller/HeraldTranscriptController.php b/src/applications/herald/controller/HeraldTranscriptController.php --- a/src/applications/herald/controller/HeraldTranscriptController.php +++ b/src/applications/herald/controller/HeraldTranscriptController.php @@ -380,7 +380,10 @@ $item->setState(PHUIObjectItemView::STATE_FAIL); } - $rule = idx($action_names, $apply_xscript->getAction(), pht('Unknown')); + $rule = idx( + $action_names, + $apply_xscript->getAction(), + pht('Unknown Action "%s"', $apply_xscript->getAction())); $item->setHeader(pht('%s: %s', $rule, $target)); $item->addAttribute($apply_xscript->getReason()); diff --git a/src/applications/herald/engine/HeraldEngine.php b/src/applications/herald/engine/HeraldEngine.php --- a/src/applications/herald/engine/HeraldEngine.php +++ b/src/applications/herald/engine/HeraldEngine.php @@ -272,6 +272,17 @@ $result = false; } else { foreach ($conditions as $condition) { + + try { + $object->getHeraldField($condition->getFieldName()); + } catch (Exception $ex) { + $reason = pht( + 'Field "%s" does not exist!', + $condition->getFieldName()); + $result = false; + break; + } + $match = $this->doesConditionMatch($rule, $condition, $object); if (!$all && $match) { diff --git a/webroot/rsrc/js/application/herald/HeraldRuleEditor.js b/webroot/rsrc/js/application/herald/HeraldRuleEditor.js --- a/webroot/rsrc/js/application/herald/HeraldRuleEditor.js +++ b/webroot/rsrc/js/application/herald/HeraldRuleEditor.js @@ -254,6 +254,11 @@ _renderValueInputForRow : function(row_id) { var cond = this._config.conditions[row_id]; + + if (!cond[1]) { + return; + } + var type = this._config.info.values[cond[0]][cond[1]]; var input = this._buildInput(type);