2011-03-22 21:22:40 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
2012-01-14 08:08:19 +01:00
|
|
|
* Copyright 2012 Facebook, Inc.
|
2011-03-22 21:22:40 +01:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2012-03-14 00:21:04 +01:00
|
|
|
final class HeraldEngine {
|
2011-03-22 21:22:40 +01:00
|
|
|
|
|
|
|
protected $rules = array();
|
|
|
|
protected $results = array();
|
|
|
|
protected $stack = array();
|
|
|
|
protected $activeRule = null;
|
|
|
|
|
|
|
|
protected $fieldCache = array();
|
|
|
|
protected $object = null;
|
|
|
|
|
2011-03-25 05:32:26 +01:00
|
|
|
public static function loadAndApplyRules(HeraldObjectAdapter $object) {
|
2011-03-22 21:22:40 +01:00
|
|
|
$content_type = $object->getHeraldTypeName();
|
Remove massive "rule applied" query
Summary:
Herald rules may be marked as "one-time". We track this by writing a row with
<ruleID, phid> when we apply a rule.
However, the current test for rule application involves loading every <ruleID,
*> pair. We also always write this row even for rules which are not one-time, so
if there are 100 rules, we'll load 1,000,000 rows after processing 10,000
objects.
Instead, load only the <phid, *> pairs, which are guaranteed to be bounded to at
most the number of rules.
I'll follow up with a diff that causes us to write rows only for one-time rules,
and deletes all historic rows which are not associated with one-time rules.
Test Plan:
Grepped for callsites to loadAllByContentTypeWithFullData(). Ran
rules in test console.
Reviewers: nh, btrahan, jungejason
Reviewed By: nh
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1483
2012-01-25 04:03:30 +01:00
|
|
|
$rules = HeraldRule::loadAllByContentTypeWithFullData(
|
|
|
|
$content_type,
|
|
|
|
$object->getPHID());
|
2011-03-22 21:22:40 +01:00
|
|
|
|
|
|
|
$engine = new HeraldEngine();
|
|
|
|
$effects = $engine->applyRules($rules, $object);
|
2012-01-25 20:53:39 +01:00
|
|
|
$engine->applyEffects($effects, $object, $rules);
|
2011-03-22 21:22:40 +01:00
|
|
|
|
|
|
|
return $engine->getTranscript();
|
|
|
|
}
|
|
|
|
|
2011-03-25 05:32:26 +01:00
|
|
|
public function applyRules(array $rules, HeraldObjectAdapter $object) {
|
2012-04-03 21:10:45 +02:00
|
|
|
assert_instances_of($rules, 'HeraldRule');
|
2011-03-22 21:22:40 +01:00
|
|
|
$t_start = microtime(true);
|
|
|
|
|
|
|
|
$rules = mpull($rules, null, 'getID');
|
|
|
|
|
|
|
|
$this->transcript = new HeraldTranscript();
|
2011-03-25 05:32:26 +01:00
|
|
|
$this->transcript->setObjectPHID((string)$object->getPHID());
|
2011-03-22 21:22:40 +01:00
|
|
|
$this->fieldCache = array();
|
|
|
|
$this->results = array();
|
|
|
|
$this->rules = $rules;
|
|
|
|
$this->object = $object;
|
|
|
|
|
|
|
|
$effects = array();
|
|
|
|
foreach ($rules as $id => $rule) {
|
|
|
|
$this->stack = array();
|
|
|
|
try {
|
2011-05-28 00:52:26 +02:00
|
|
|
if (($rule->getRepetitionPolicy() ==
|
|
|
|
HeraldRepetitionPolicyConfig::FIRST) &&
|
|
|
|
$rule->getRuleApplied($object->getPHID())) {
|
|
|
|
// This rule is only supposed to be applied a single time, and it's
|
|
|
|
// aleady been applied, so this is an automatic failure.
|
|
|
|
$xscript = id(new HeraldRuleTranscript())
|
|
|
|
->setRuleID($id)
|
|
|
|
->setResult(false)
|
|
|
|
->setRuleName($rule->getName())
|
|
|
|
->setRuleOwner($rule->getAuthorPHID())
|
|
|
|
->setReason(
|
|
|
|
"This rule is only supposed to be repeated a single time, ".
|
|
|
|
"and it has already been applied."
|
|
|
|
);
|
|
|
|
$this->transcript->addRuleTranscript($xscript);
|
|
|
|
$rule_matches = false;
|
|
|
|
} else {
|
|
|
|
$rule_matches = $this->doesRuleMatch($rule, $object);
|
|
|
|
}
|
2011-03-22 21:22:40 +01:00
|
|
|
} catch (HeraldRecursiveConditionsException $ex) {
|
|
|
|
$names = array();
|
|
|
|
foreach ($this->stack as $rule_id => $ignored) {
|
|
|
|
$names[] = '"'.$rules[$rule_id]->getName().'"';
|
|
|
|
}
|
|
|
|
$names = implode(', ', $names);
|
|
|
|
foreach ($this->stack as $rule_id => $ignored) {
|
|
|
|
$xscript = new HeraldRuleTranscript();
|
|
|
|
$xscript->setRuleID($rule_id);
|
|
|
|
$xscript->setResult(false);
|
|
|
|
$xscript->setReason(
|
|
|
|
"Rules {$names} are recursively dependent upon one another! ".
|
|
|
|
"Don't do this! You have formed an unresolvable cycle in the ".
|
|
|
|
"dependency graph!");
|
|
|
|
$xscript->setRuleName($rules[$rule_id]->getName());
|
2011-03-25 05:32:26 +01:00
|
|
|
$xscript->setRuleOwner($rules[$rule_id]->getAuthorPHID());
|
2011-03-22 21:22:40 +01:00
|
|
|
$this->transcript->addRuleTranscript($xscript);
|
|
|
|
}
|
|
|
|
$rule_matches = false;
|
|
|
|
}
|
|
|
|
$this->results[$id] = $rule_matches;
|
|
|
|
|
|
|
|
if ($rule_matches) {
|
|
|
|
foreach ($this->getRuleEffects($rule, $object) as $effect) {
|
|
|
|
$effects[] = $effect;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$object_transcript = new HeraldObjectTranscript();
|
2011-03-25 05:32:26 +01:00
|
|
|
$object_transcript->setPHID($object->getPHID());
|
2011-03-22 21:22:40 +01:00
|
|
|
$object_transcript->setName($object->getHeraldName());
|
|
|
|
$object_transcript->setType($object->getHeraldTypeName());
|
|
|
|
$object_transcript->setFields($this->fieldCache);
|
|
|
|
|
|
|
|
$this->transcript->setObjectTranscript($object_transcript);
|
|
|
|
|
|
|
|
$t_end = microtime(true);
|
|
|
|
|
|
|
|
$this->transcript->setDuration($t_end - $t_start);
|
|
|
|
|
|
|
|
return $effects;
|
|
|
|
}
|
|
|
|
|
2012-01-25 20:53:39 +01:00
|
|
|
public function applyEffects(
|
|
|
|
array $effects,
|
|
|
|
HeraldObjectAdapter $object,
|
|
|
|
array $rules) {
|
2012-04-03 21:10:45 +02:00
|
|
|
assert_instances_of($effects, 'HeraldEffect');
|
|
|
|
assert_instances_of($rules, 'HeraldRule');
|
2012-01-25 20:53:39 +01:00
|
|
|
|
2011-05-28 00:52:26 +02:00
|
|
|
$this->transcript->setDryRun($object instanceof HeraldDryRunAdapter);
|
|
|
|
|
|
|
|
$xscripts = $object->applyHeraldEffects($effects);
|
|
|
|
foreach ($xscripts as $apply_xscript) {
|
2011-03-22 21:22:40 +01:00
|
|
|
if (!($apply_xscript instanceof HeraldApplyTranscript)) {
|
|
|
|
throw new Exception(
|
|
|
|
"Heraldable must return HeraldApplyTranscripts from ".
|
|
|
|
"applyHeraldEffect().");
|
|
|
|
}
|
|
|
|
$this->transcript->addApplyTranscript($apply_xscript);
|
|
|
|
}
|
2011-05-28 00:52:26 +02:00
|
|
|
|
|
|
|
if (!$this->transcript->getDryRun()) {
|
2012-01-25 20:53:39 +01:00
|
|
|
|
|
|
|
$rules = mpull($rules, null, 'getID');
|
|
|
|
$applied_ids = array();
|
|
|
|
$first_policy = HeraldRepetitionPolicyConfig::toInt(
|
|
|
|
HeraldRepetitionPolicyConfig::FIRST);
|
|
|
|
|
2011-05-28 00:52:26 +02:00
|
|
|
// Mark all the rules that have had their effects applied as having been
|
|
|
|
// executed for the current object.
|
2011-06-09 22:48:39 +02:00
|
|
|
$rule_ids = mpull($xscripts, 'getRuleID');
|
2012-01-25 20:53:39 +01:00
|
|
|
|
2011-06-09 22:48:39 +02:00
|
|
|
foreach ($rule_ids as $rule_id) {
|
|
|
|
if (!$rule_id) {
|
|
|
|
// Some apply transcripts are purely informational and not associated
|
|
|
|
// with a rule, e.g. carryover emails from earlier revisions.
|
|
|
|
continue;
|
|
|
|
}
|
2012-01-25 20:53:39 +01:00
|
|
|
|
|
|
|
$rule = idx($rules, $rule_id);
|
|
|
|
if (!$rule) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($rule->getRepetitionPolicy() == $first_policy) {
|
|
|
|
$applied_ids[] = $rule_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($applied_ids) {
|
|
|
|
$conn_w = id(new HeraldRule())->establishConnection('w');
|
|
|
|
$sql = array();
|
|
|
|
foreach ($applied_ids as $id) {
|
|
|
|
$sql[] = qsprintf(
|
|
|
|
$conn_w,
|
|
|
|
'(%s, %d)',
|
|
|
|
$object->getPHID(),
|
|
|
|
$id);
|
|
|
|
}
|
|
|
|
queryfx(
|
|
|
|
$conn_w,
|
|
|
|
'INSERT IGNORE INTO %T (phid, ruleID) VALUES %Q',
|
|
|
|
HeraldRule::TABLE_RULE_APPLIED,
|
|
|
|
implode(', ', $sql));
|
2011-05-28 00:52:26 +02:00
|
|
|
}
|
|
|
|
}
|
2011-03-22 21:22:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function getTranscript() {
|
|
|
|
$this->transcript->save();
|
|
|
|
return $this->transcript;
|
|
|
|
}
|
|
|
|
|
2011-03-25 05:32:26 +01:00
|
|
|
protected function doesRuleMatch(
|
|
|
|
HeraldRule $rule,
|
|
|
|
HeraldObjectAdapter $object) {
|
|
|
|
|
2011-03-22 21:22:40 +01:00
|
|
|
$id = $rule->getID();
|
|
|
|
|
|
|
|
if (isset($this->results[$id])) {
|
|
|
|
// If we've already evaluated this rule because another rule depends
|
|
|
|
// on it, we don't need to reevaluate it.
|
|
|
|
return $this->results[$id];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($this->stack[$id])) {
|
|
|
|
// We've recursed, fail all of the rules on the stack. This happens when
|
|
|
|
// there's a dependency cycle with "Rule conditions match for rule ..."
|
|
|
|
// conditions.
|
|
|
|
foreach ($this->stack as $rule_id => $ignored) {
|
|
|
|
$this->results[$rule_id] = false;
|
|
|
|
}
|
|
|
|
throw new HeraldRecursiveConditionsException();
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->stack[$id] = true;
|
|
|
|
|
|
|
|
$all = $rule->getMustMatchAll();
|
|
|
|
|
|
|
|
$conditions = $rule->getConditions();
|
|
|
|
|
|
|
|
$result = null;
|
|
|
|
|
|
|
|
$local_version = id(new HeraldRule())->getConfigVersion();
|
|
|
|
if ($rule->getConfigVersion() > $local_version) {
|
|
|
|
$reason = "Rule could not be processed, it was created with a newer ".
|
|
|
|
"version of Herald.";
|
|
|
|
$result = false;
|
|
|
|
} else if (!$conditions) {
|
|
|
|
$reason = "Rule failed automatically because it has no conditions.";
|
|
|
|
$result = false;
|
Disable personal Herald rules from invalid owners
Summary: Since mailing list rules are now "global", don't run "personal" rules
for disabled/invalid users.
Test Plan: Added a personal rule that matches every revision for a test user.
Created a revision, checked transcript, rule matched. Disabled user, updated
revision, checked transcript, rule got auto-disabled.
Reviewers: btrahan, jungejason, nh, xela
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1517
2012-01-31 21:11:31 +01:00
|
|
|
} else if ($rule->hasInvalidOwner()) {
|
|
|
|
$reason = "Rule failed automatically because its owner is invalid ".
|
|
|
|
"or disabled.";
|
2011-03-22 21:22:40 +01:00
|
|
|
$result = false;
|
|
|
|
} else {
|
|
|
|
foreach ($conditions as $condition) {
|
|
|
|
$match = $this->doesConditionMatch($rule, $condition, $object);
|
|
|
|
|
|
|
|
if (!$all && $match) {
|
|
|
|
$reason = "Any condition matched.";
|
|
|
|
$result = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($all && !$match) {
|
|
|
|
$reason = "Not all conditions matched.";
|
|
|
|
$result = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($result === null) {
|
|
|
|
if ($all) {
|
|
|
|
$reason = "All conditions matched.";
|
|
|
|
$result = true;
|
|
|
|
} else {
|
|
|
|
$reason = "No conditions matched.";
|
|
|
|
$result = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$rule_transcript = new HeraldRuleTranscript();
|
|
|
|
$rule_transcript->setRuleID($rule->getID());
|
|
|
|
$rule_transcript->setResult($result);
|
|
|
|
$rule_transcript->setReason($reason);
|
|
|
|
$rule_transcript->setRuleName($rule->getName());
|
2011-03-25 05:32:26 +01:00
|
|
|
$rule_transcript->setRuleOwner($rule->getAuthorPHID());
|
2011-03-22 21:22:40 +01:00
|
|
|
|
|
|
|
$this->transcript->addRuleTranscript($rule_transcript);
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function doesConditionMatch(
|
|
|
|
HeraldRule $rule,
|
|
|
|
HeraldCondition $condition,
|
2011-03-25 05:32:26 +01:00
|
|
|
HeraldObjectAdapter $object) {
|
2011-03-22 21:22:40 +01:00
|
|
|
|
|
|
|
$object_value = $this->getConditionObjectValue($condition, $object);
|
|
|
|
$test_value = $condition->getValue();
|
|
|
|
|
2011-03-25 05:32:26 +01:00
|
|
|
$cond = $condition->getFieldCondition();
|
2011-03-22 21:22:40 +01:00
|
|
|
|
|
|
|
$transcript = new HeraldConditionTranscript();
|
|
|
|
$transcript->setRuleID($rule->getID());
|
|
|
|
$transcript->setConditionID($condition->getID());
|
|
|
|
$transcript->setFieldName($condition->getFieldName());
|
|
|
|
$transcript->setCondition($cond);
|
|
|
|
$transcript->setTestValue($test_value);
|
|
|
|
|
|
|
|
$result = null;
|
|
|
|
switch ($cond) {
|
|
|
|
case HeraldConditionConfig::CONDITION_CONTAINS:
|
|
|
|
// "Contains" can take an array of strings, as in "Any changed
|
|
|
|
// filename" for diffs.
|
|
|
|
foreach ((array)$object_value as $value) {
|
|
|
|
$result = (stripos($value, $test_value) !== false);
|
|
|
|
if ($result) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_NOT_CONTAINS:
|
|
|
|
$result = (stripos($object_value, $test_value) === false);
|
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_IS:
|
|
|
|
$result = ($object_value == $test_value);
|
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_IS_NOT:
|
|
|
|
$result = ($object_value != $test_value);
|
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_IS_ME:
|
2011-03-25 05:32:26 +01:00
|
|
|
$result = ($object_value == $rule->getAuthorPHID());
|
2011-03-22 21:22:40 +01:00
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_IS_NOT_ME:
|
2011-03-25 05:32:26 +01:00
|
|
|
$result = ($object_value != $rule->getAuthorPHID());
|
2011-03-22 21:22:40 +01:00
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_IS_ANY:
|
|
|
|
$test_value = array_flip($test_value);
|
|
|
|
$result = isset($test_value[$object_value]);
|
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_IS_NOT_ANY:
|
|
|
|
$test_value = array_flip($test_value);
|
|
|
|
$result = !isset($test_value[$object_value]);
|
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_INCLUDE_ALL:
|
|
|
|
if (!is_array($object_value)) {
|
|
|
|
$transcript->setNote('Object produced bad value!');
|
|
|
|
$result = false;
|
|
|
|
} else {
|
|
|
|
$have = array_select_keys(array_flip($object_value),
|
|
|
|
$test_value);
|
|
|
|
$result = (count($have) == count($test_value));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_INCLUDE_ANY:
|
|
|
|
$result = (bool)array_select_keys(array_flip($object_value),
|
|
|
|
$test_value);
|
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_INCLUDE_NONE:
|
|
|
|
$result = !array_select_keys(array_flip($object_value),
|
|
|
|
$test_value);
|
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_EXISTS:
|
|
|
|
$result = (bool)$object_value;
|
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_NOT_EXISTS:
|
|
|
|
$result = !$object_value;
|
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_REGEXP:
|
|
|
|
foreach ((array)$object_value as $value) {
|
|
|
|
$result = @preg_match($test_value, $value);
|
|
|
|
if ($result === false) {
|
|
|
|
$transcript->setNote(
|
|
|
|
"Regular expression is not valid!");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ($result) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$result = (bool)$result;
|
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_REGEXP_PAIR:
|
|
|
|
// Match a JSON-encoded pair of regular expressions against a
|
|
|
|
// dictionary. The first regexp must match the dictionary key, and the
|
|
|
|
// second regexp must match the dictionary value. If any key/value pair
|
|
|
|
// in the dictionary matches both regexps, the condition is satisfied.
|
|
|
|
$regexp_pair = json_decode($test_value, true);
|
|
|
|
if (!is_array($regexp_pair)) {
|
|
|
|
$result = false;
|
|
|
|
$transcript->setNote("Regular expression pair is not valid JSON!");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (count($regexp_pair) != 2) {
|
|
|
|
$result = false;
|
|
|
|
$transcript->setNote("Regular expression pair is not a pair!");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
$key_regexp = array_shift($regexp_pair);
|
|
|
|
$value_regexp = array_shift($regexp_pair);
|
|
|
|
|
|
|
|
foreach ((array)$object_value as $key => $value) {
|
|
|
|
$key_matches = @preg_match($key_regexp, $key);
|
|
|
|
if ($key_matches === false) {
|
|
|
|
$result = false;
|
|
|
|
$transcript->setNote("First regular expression is invalid!");
|
|
|
|
break 2;
|
|
|
|
}
|
|
|
|
if ($key_matches) {
|
|
|
|
$value_matches = @preg_match($value_regexp, $value);
|
|
|
|
if ($value_matches === false) {
|
|
|
|
$result = false;
|
|
|
|
$transcript->setNote("Second regular expression is invalid!");
|
|
|
|
break 2;
|
|
|
|
}
|
|
|
|
if ($value_matches) {
|
|
|
|
$result = true;
|
|
|
|
break 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$result = false;
|
|
|
|
break;
|
|
|
|
case HeraldConditionConfig::CONDITION_RULE:
|
|
|
|
case HeraldConditionConfig::CONDITION_NOT_RULE:
|
|
|
|
|
|
|
|
$rule = idx($this->rules, $test_value);
|
|
|
|
if (!$rule) {
|
|
|
|
$transcript->setNote(
|
|
|
|
"Condition references a rule which does not exist!");
|
|
|
|
$result = false;
|
|
|
|
} else {
|
|
|
|
$is_not = ($cond == HeraldConditionConfig::CONDITION_NOT_RULE);
|
|
|
|
$result = $this->doesRuleMatch($rule, $object);
|
|
|
|
if ($is_not) {
|
|
|
|
$result = !$result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new HeraldInvalidConditionException(
|
|
|
|
"Unknown condition '{$cond}'.");
|
|
|
|
}
|
|
|
|
|
|
|
|
$transcript->setResult($result);
|
|
|
|
|
|
|
|
$this->transcript->addConditionTranscript($transcript);
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getConditionObjectValue(
|
|
|
|
HeraldCondition $condition,
|
2011-03-25 05:32:26 +01:00
|
|
|
HeraldObjectAdapter $object) {
|
2011-03-22 21:22:40 +01:00
|
|
|
|
|
|
|
$field = $condition->getFieldName();
|
|
|
|
|
|
|
|
return $this->getObjectFieldValue($field);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getObjectFieldValue($field) {
|
|
|
|
if (isset($this->fieldCache[$field])) {
|
|
|
|
return $this->fieldCache[$field];
|
|
|
|
}
|
|
|
|
|
|
|
|
$result = null;
|
|
|
|
switch ($field) {
|
|
|
|
case HeraldFieldConfig::FIELD_RULE:
|
|
|
|
$result = null;
|
|
|
|
break;
|
|
|
|
case HeraldFieldConfig::FIELD_TITLE:
|
|
|
|
case HeraldFieldConfig::FIELD_BODY:
|
|
|
|
case HeraldFieldConfig::FIELD_DIFF_FILE:
|
|
|
|
case HeraldFieldConfig::FIELD_DIFF_CONTENT:
|
|
|
|
// TODO: Type should be string.
|
|
|
|
$result = $this->object->getHeraldField($field);
|
|
|
|
break;
|
|
|
|
case HeraldFieldConfig::FIELD_AUTHOR:
|
|
|
|
case HeraldFieldConfig::FIELD_REPOSITORY:
|
|
|
|
case HeraldFieldConfig::FIELD_MERGE_REQUESTER:
|
2011-03-25 05:32:26 +01:00
|
|
|
// TODO: Type should be PHID.
|
2011-03-22 21:22:40 +01:00
|
|
|
$result = $this->object->getHeraldField($field);
|
|
|
|
break;
|
|
|
|
case HeraldFieldConfig::FIELD_TAGS:
|
|
|
|
case HeraldFieldConfig::FIELD_REVIEWER:
|
|
|
|
case HeraldFieldConfig::FIELD_REVIEWERS:
|
|
|
|
case HeraldFieldConfig::FIELD_CC:
|
|
|
|
case HeraldFieldConfig::FIELD_DIFFERENTIAL_REVIEWERS:
|
|
|
|
case HeraldFieldConfig::FIELD_DIFFERENTIAL_CCS:
|
|
|
|
// TODO: Type should be list.
|
|
|
|
$result = $this->object->getHeraldField($field);
|
|
|
|
break;
|
|
|
|
case HeraldFieldConfig::FIELD_AFFECTED_PACKAGE:
|
|
|
|
case HeraldFieldConfig::FIELD_AFFECTED_PACKAGE_OWNER:
|
2012-01-14 08:08:19 +01:00
|
|
|
case HeraldFieldConfig::FIELD_NEED_AUDIT_FOR_PACKAGE:
|
2011-03-22 21:22:40 +01:00
|
|
|
$result = $this->object->getHeraldField($field);
|
|
|
|
if (!is_array($result)) {
|
|
|
|
throw new HeraldInvalidFieldException(
|
|
|
|
"Value of field type {$field} is not an array!");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case HeraldFieldConfig::FIELD_DIFFERENTIAL_REVISION:
|
|
|
|
// TODO: Type should be boolean I guess.
|
|
|
|
$result = $this->object->getHeraldField($field);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new HeraldInvalidConditionException(
|
|
|
|
"Unknown field type '{$field}'!");
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->fieldCache[$field] = $result;
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
2011-03-25 05:32:26 +01:00
|
|
|
protected function getRuleEffects(
|
|
|
|
HeraldRule $rule,
|
|
|
|
HeraldObjectAdapter $object) {
|
|
|
|
|
2011-03-22 21:22:40 +01:00
|
|
|
$effects = array();
|
|
|
|
foreach ($rule->getActions() as $action) {
|
|
|
|
$effect = new HeraldEffect();
|
2011-03-25 05:32:26 +01:00
|
|
|
$effect->setObjectPHID($object->getPHID());
|
2011-03-22 21:22:40 +01:00
|
|
|
$effect->setAction($action->getAction());
|
|
|
|
$effect->setTarget($action->getTarget());
|
|
|
|
|
|
|
|
$effect->setRuleID($rule->getID());
|
|
|
|
|
|
|
|
$name = $rule->getName();
|
|
|
|
$id = $rule->getID();
|
|
|
|
$effect->setReason(
|
|
|
|
'Conditions were met for Herald rule "'.$name.'" (#'.$id.').');
|
|
|
|
|
|
|
|
$effects[] = $effect;
|
|
|
|
}
|
|
|
|
return $effects;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|