Changeset View
Changeset View
Standalone View
Standalone View
src/applications/project/storage/PhabricatorProjectTrigger.php
| Show First 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | return urisprintf( | ||||
| '/project/trigger/%d/', | '/project/trigger/%d/', | ||||
| $this->getID()); | $this->getID()); | ||||
| } | } | ||||
| public function getObjectName() { | public function getObjectName() { | ||||
| return pht('Trigger %d', $this->getID()); | return pht('Trigger %d', $this->getID()); | ||||
| } | } | ||||
| public function setRuleset(array $ruleset) { | |||||
| // Clear any cached trigger rules, since we're changing the ruleset | |||||
| // for the trigger. | |||||
| $this->triggerRules = null; | |||||
| parent::setRuleset($ruleset); | |||||
| } | |||||
| public function getTriggerRules() { | public function getTriggerRules() { | ||||
| if ($this->triggerRules === null) { | if ($this->triggerRules === null) { | ||||
| $trigger_rules = self::newTriggerRulesFromRuleSpecifications( | |||||
| $this->getRuleset(), | |||||
| $allow_invalid = true); | |||||
| // TODO: Temporary hard-coded rule specification. | $this->triggerRules = $trigger_rules; | ||||
| $rule_specifications = array( | } | ||||
| array( | |||||
| 'type' => 'status', | |||||
| 'value' => ManiphestTaskStatus::getDefaultClosedStatus(), | |||||
| ), | |||||
| // This is an intentionally unknown rule. | |||||
| array( | |||||
| 'type' => 'quack', | |||||
| 'value' => 'aaa', | |||||
| ), | |||||
| // This is an intentionally invalid rule. | |||||
| array( | |||||
| 'type' => 'status', | |||||
| 'value' => 'quack', | |||||
| ), | |||||
| ); | |||||
| // NOTE: We're trying to preserve the database state in the rule | return $this->triggerRules; | ||||
| // structure, even if it includes rule types we don't have implementations | } | ||||
| // for, or rules with invalid rule values. | |||||
| public static function newTriggerRulesFromRuleSpecifications( | |||||
| array $list, | |||||
| $allow_invalid) { | |||||
| // NOTE: With "$allow_invalid" set, we're trying to preserve the database | |||||
| // state in the rule structure, even if it includes rule types we don't | |||||
| // ha ve implementations for, or rules with invalid rule values. | |||||
amckinley: "ha ve" | |||||
| // If an administrator adds or removes extensions which add rules, or | // If an administrator adds or removes extensions which add rules, or | ||||
| // an upgrade affects rule validity, existing rules may become invalid. | // an upgrade affects rule validity, existing rules may become invalid. | ||||
| // When they do, we still want the UI to reflect the ruleset state | // When they do, we still want the UI to reflect the ruleset state | ||||
| // accurately and "Edit" + "Save" shouldn't destroy data unless the | // accurately and "Edit" + "Save" shouldn't destroy data unless the | ||||
| // user explicitly modifies the ruleset. | // user explicitly modifies the ruleset. | ||||
| // When we run into rules which are structured correctly but which have | // In this mode, when we run into rules which are structured correctly but | ||||
| // types we don't know about, we replace them with "Unknown Rules". If | // which have types we don't know about, we replace them with "Unknown | ||||
| // we know about the type of a rule but the value doesn't validate, we | // Rules". If we know about the type of a rule but the value doesn't | ||||
| // replace it with "Invalid Rules". These two rule types don't take any | // validate, we replace it with "Invalid Rules". These two rule types don't | ||||
| // actions when a card is dropped into the column, but they show the user | // take any actions when a card is dropped into the column, but they show | ||||
| // what's wrong with the ruleset and can be saved without causing any | // the user what's wrong with the ruleset and can be saved without causing | ||||
| // collateral damage. | // any collateral damage. | ||||
| $rule_map = PhabricatorProjectTriggerRule::getAllTriggerRules(); | $rule_map = PhabricatorProjectTriggerRule::getAllTriggerRules(); | ||||
| // If the stored rule data isn't a list of rules (or we encounter other | // If the stored rule data isn't a list of rules (or we encounter other | ||||
| // fundamental structural problems, below), there isn't much we can do | // fundamental structural problems, below), there isn't much we can do | ||||
| // to try to represent the state. | // to try to represent the state. | ||||
| if (!is_array($rule_specifications)) { | if (!is_array($list)) { | ||||
| throw new PhabricatorProjectTriggerCorruptionException( | throw new PhabricatorProjectTriggerCorruptionException( | ||||
| pht( | pht( | ||||
| 'Trigger ("%s") has a corrupt ruleset: expected a list of '. | 'Trigger ruleset is corrupt: expected a list of rule '. | ||||
| 'rule specifications, found "%s".', | 'specifications, found "%s".', | ||||
| $this->getPHID(), | phutil_describe_type($list))); | ||||
| phutil_describe_type($rule_specifications))); | |||||
| } | } | ||||
| $trigger_rules = array(); | $trigger_rules = array(); | ||||
| foreach ($rule_specifications as $key => $rule) { | foreach ($list as $key => $rule) { | ||||
| if (!is_array($rule)) { | if (!is_array($rule)) { | ||||
| throw new PhabricatorProjectTriggerCorruptionException( | throw new PhabricatorProjectTriggerCorruptionException( | ||||
| pht( | pht( | ||||
| 'Trigger ("%s") has a corrupt ruleset: rule (with key "%s") '. | 'Trigger ruleset is corrupt: rule (with key "%s") should be a '. | ||||
| 'should be a rule specification, but is actually "%s".', | 'rule specification, but is actually "%s".', | ||||
| $this->getPHID(), | |||||
| $key, | $key, | ||||
| phutil_describe_type($rule))); | phutil_describe_type($rule))); | ||||
| } | } | ||||
| try { | try { | ||||
| PhutilTypeSpec::checkMap( | PhutilTypeSpec::checkMap( | ||||
| $rule, | $rule, | ||||
| array( | array( | ||||
| 'type' => 'string', | 'type' => 'string', | ||||
| 'value' => 'wild', | 'value' => 'wild', | ||||
| )); | )); | ||||
| } catch (PhutilTypeCheckException $ex) { | } catch (PhutilTypeCheckException $ex) { | ||||
| throw new PhabricatorProjectTriggerCorruptionException( | throw new PhabricatorProjectTriggerCorruptionException( | ||||
| pht( | pht( | ||||
| 'Trigger ("%s") has a corrupt ruleset: rule (with key "%s") '. | 'Trigger ruleset is corrupt: rule (with key "%s") is not a '. | ||||
| 'is not a valid rule specification: %s', | 'valid rule specification: %s', | ||||
| $this->getPHID(), | |||||
| $key, | $key, | ||||
| $ex->getMessage())); | $ex->getMessage())); | ||||
| } | } | ||||
| $record = id(new PhabricatorProjectTriggerRuleRecord()) | $record = id(new PhabricatorProjectTriggerRuleRecord()) | ||||
| ->setType(idx($rule, 'type')) | ->setType(idx($rule, 'type')) | ||||
| ->setValue(idx($rule, 'value')); | ->setValue(idx($rule, 'value')); | ||||
| if (!isset($rule_map[$record->getType()])) { | if (!isset($rule_map[$record->getType()])) { | ||||
| if (!$allow_invalid) { | |||||
| throw new PhabricatorProjectTriggerCorruptionException( | |||||
| pht( | |||||
| 'Trigger ruleset is corrupt: rule type "%s" is unknown.', | |||||
| $record->getType())); | |||||
| } | |||||
| $rule = new PhabricatorProjectTriggerUnknownRule(); | $rule = new PhabricatorProjectTriggerUnknownRule(); | ||||
| } else { | } else { | ||||
| $rule = clone $rule_map[$record->getType()]; | $rule = clone $rule_map[$record->getType()]; | ||||
| } | } | ||||
| try { | try { | ||||
| $rule->setRecord($record); | $rule->setRecord($record); | ||||
| } catch (Exception $ex) { | } catch (Exception $ex) { | ||||
| if (!$allow_invalid) { | |||||
| throw new PhabricatorProjectTriggerCorruptionException( | |||||
| pht( | |||||
| 'Trigger ruleset is corrupt, rule (of type "%s") does not '. | |||||
| 'validate: %s', | |||||
| $record->getType(), | |||||
| $ex->getMessage())); | |||||
| } | |||||
| $rule = id(new PhabricatorProjectTriggerInvalidRule()) | $rule = id(new PhabricatorProjectTriggerInvalidRule()) | ||||
| ->setRecord($record); | ->setRecord($record); | ||||
| } | } | ||||
| $trigger_rules[] = $rule; | $trigger_rules[] = $rule; | ||||
| } | } | ||||
| $this->triggerRules = $trigger_rules; | return $trigger_rules; | ||||
| } | } | ||||
| return $this->triggerRules; | |||||
| } | |||||
| public function getDropEffects() { | public function getDropEffects() { | ||||
| $effects = array(); | $effects = array(); | ||||
| $rules = $this->getTriggerRules(); | $rules = $this->getTriggerRules(); | ||||
| foreach ($rules as $rule) { | foreach ($rules as $rule) { | ||||
| foreach ($rule->getDropEffects() as $effect) { | foreach ($rule->getDropEffects() as $effect) { | ||||
| $effects[] = $effect; | $effects[] = $effect; | ||||
| ▲ Show 20 Lines • Show All 133 Lines • Show Last 20 Lines | |||||
"ha ve"