Page MenuHomePhabricator

D7847.diff
No OneTemporary

D7847.diff

Index: resources/sql/patches/20131227.heraldobject.sql
===================================================================
--- /dev/null
+++ resources/sql/patches/20131227.heraldobject.sql
@@ -0,0 +1,6 @@
+ALTER TABLE {$NAMESPACE}_herald.herald_rule
+ ADD triggerObjectPHID VARCHAR(64) COLLATE utf8_bin;
+
+ALTER TABLE {$NAMESPACE}_herald.herald_rule
+ ADD KEY `key_trigger` (triggerObjectPHID);
+
Index: src/applications/herald/config/HeraldRuleTypeConfig.php
===================================================================
--- src/applications/herald/config/HeraldRuleTypeConfig.php
+++ src/applications/herald/config/HeraldRuleTypeConfig.php
@@ -3,12 +3,14 @@
final class HeraldRuleTypeConfig {
const RULE_TYPE_GLOBAL = 'global';
+ const RULE_TYPE_OBJECT = 'object';
const RULE_TYPE_PERSONAL = 'personal';
public static function getRuleTypeMap() {
$map = array(
- self::RULE_TYPE_GLOBAL => pht('Global'),
- self::RULE_TYPE_PERSONAL => pht('Personal'),
+ self::RULE_TYPE_PERSONAL => pht('Personal'),
+ self::RULE_TYPE_OBJECT => pht('Object'),
+ self::RULE_TYPE_GLOBAL => pht('Global'),
);
return $map;
}
Index: src/applications/herald/controller/HeraldDisableController.php
===================================================================
--- src/applications/herald/controller/HeraldDisableController.php
+++ src/applications/herald/controller/HeraldDisableController.php
@@ -28,7 +28,7 @@
return new Aphront404Response();
}
- if ($rule->getRuleType() == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL) {
+ if ($rule->isGlobalRule()) {
$this->requireApplicationCapability(
HeraldCapabilityManageGlobalRules::CAPABILITY);
}
Index: src/applications/herald/controller/HeraldNewController.php
===================================================================
--- src/applications/herald/controller/HeraldNewController.php
+++ src/applications/herald/controller/HeraldNewController.php
@@ -147,13 +147,18 @@
private function renderRuleTypeControl(array $rule_type_map, $e_rule) {
$request = $this->getRequest();
- // Reorder array to put "personal" first.
+ // Reorder array to put less powerful rules first.
$rule_type_map = array_select_keys(
$rule_type_map,
array(
HeraldRuleTypeConfig::RULE_TYPE_PERSONAL,
+ HeraldRuleTypeConfig::RULE_TYPE_OBJECT,
+ HeraldRuleTypeConfig::RULE_TYPE_GLOBAL,
)) + $rule_type_map;
+ // TODO: Enable this.
+ unset($rule_type_map[HeraldRuleTypeConfig::RULE_TYPE_OBJECT]);
+
list($can_global, $global_link) = $this->explainApplicationCapability(
HeraldCapabilityManageGlobalRules::CAPABILITY,
pht('You have permission to create and manage global rules.'),
Index: src/applications/herald/controller/HeraldRuleController.php
===================================================================
--- src/applications/herald/controller/HeraldRuleController.php
+++ src/applications/herald/controller/HeraldRuleController.php
@@ -49,7 +49,7 @@
$cancel_uri = $this->getApplicationURI();
}
- if ($rule->getRuleType() == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL) {
+ if ($rule->isGlobalRule()) {
$this->requireApplicationCapability(
HeraldCapabilityManageGlobalRules::CAPABILITY);
}
@@ -561,7 +561,17 @@
->withContentTypes(array($rule->getContentType()))
->execute();
- if ($rule->getRuleType() == HeraldRuleTypeConfig::RULE_TYPE_PERSONAL) {
+ if ($rule->isObjectRule()) {
+ // Object rules may depend on other rules for the same object.
+ $all_rules += id(new HeraldRuleQuery())
+ ->setViewer($viewer)
+ ->withRuleTypes(array(HeraldRuleTypeConfig::RULE_TYPE_OBJECT))
+ ->withContentTypes(array($rule->getContentType()))
+ ->withTriggerObjectPHIDs(array($rule->getTriggerObjectPHID()))
+ ->execute();
+ }
+
+ if ($rule->isPersonalRule()) {
// Personal rules may depend upon your other personal rules.
$all_rules += id(new HeraldRuleQuery())
->setViewer($viewer)
Index: src/applications/herald/engine/HeraldEngine.php
===================================================================
--- src/applications/herald/engine/HeraldEngine.php
+++ src/applications/herald/engine/HeraldEngine.php
@@ -256,6 +256,11 @@
"Rule failed automatically because it is a personal rule and its ".
"owner can not see the object.");
$result = false;
+ } else if (!$this->canRuleApplyToObject($rule, $object)) {
+ $reason = pht(
+ "Rule failed automatically because it is an object rule which is ".
+ "not relevant for this object.");
+ $result = false;
} else {
foreach ($conditions as $condition) {
$match = $this->doesConditionMatch($rule, $condition, $object);
@@ -381,8 +386,8 @@
HeraldRule $rule,
HeraldAdapter $adapter) {
- // Authorship is irrelevant for global rules.
- if ($rule->isGlobalRule()) {
+ // Authorship is irrelevant for global rules and object rules.
+ if ($rule->isGlobalRule() || $rule->isObjectRule()) {
return true;
}
@@ -405,4 +410,25 @@
PhabricatorPolicyCapability::CAN_VIEW);
}
+ private function canRuleApplyToObject(
+ HeraldRule $rule,
+ HeraldAdapter $adapter) {
+
+ // Rules which are not object rules can apply to anything.
+ if (!$rule->isObjectRule()) {
+ return true;
+ }
+
+ $trigger_phid = $rule->getTriggerObjectPHID();
+ $object_phid = $adapter->getPHID();
+
+ if ($trigger_phid == $object_phid) {
+ return true;
+ }
+
+ // TODO: We should also handle projects.
+
+ return false;
+ }
+
}
Index: src/applications/herald/query/HeraldRuleQuery.php
===================================================================
--- src/applications/herald/query/HeraldRuleQuery.php
+++ src/applications/herald/query/HeraldRuleQuery.php
@@ -9,6 +9,7 @@
private $ruleTypes;
private $contentTypes;
private $disabled;
+ private $triggerObjectPHIDs;
private $needConditionsAndActions;
private $needAppliedToPHIDs;
@@ -49,6 +50,11 @@
return $this;
}
+ public function withTriggerObjectPHIDs(array $phids) {
+ $this->triggerObjectPHIDs = $phids;
+ return $this;
+ }
+
public function needConditionsAndActions($need) {
$this->needConditionsAndActions = $need;
return $this;
@@ -137,6 +143,35 @@
}
}
+ $object_phids = array();
+ foreach ($rules as $rule) {
+ if ($rule->isObjectRule()) {
+ $object_phids[] = $rule->getTriggerObjectPHID();
+ }
+ }
+
+ if ($object_phids) {
+ $objects = id(new PhabricatorObjectQuery())
+ ->setParentQuery($this)
+ ->setViewer($this->getViewer())
+ ->withPHIDs($object_phids)
+ ->execute();
+ $objects = mpull($objects, null, 'getPHID');
+ } else {
+ $objects = array();
+ }
+
+ foreach ($rules as $key => $rule) {
+ if ($rule->isObjectRule()) {
+ $object = idx($objects, $rule->getTriggerObjectPHID());
+ if (!$object) {
+ unset($rules[$key]);
+ continue;
+ }
+ $rule->attachTriggerObject($object);
+ }
+ }
+
return $rules;
}
@@ -185,6 +220,13 @@
(int)$this->disabled);
}
+ if ($this->triggerObjectPHIDs) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'rule.triggerObjectPHID IN (%Ls)',
+ $this->triggerObjectPHIDs);
+ }
+
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
@@ -192,9 +234,9 @@
private function validateRuleAuthors(array $rules) {
- // "Global" rules always have valid authors.
+ // "Global" and "Object" rules always have valid authors.
foreach ($rules as $key => $rule) {
- if ($rule->isGlobalRule()) {
+ if ($rule->isGlobalRule() || $rule->isObjectRule()) {
$rule->attachValidAuthor(true);
unset($rules[$key]);
continue;
Index: src/applications/herald/storage/HeraldRule.php
===================================================================
--- src/applications/herald/storage/HeraldRule.php
+++ src/applications/herald/storage/HeraldRule.php
@@ -15,8 +15,9 @@
protected $repetitionPolicy;
protected $ruleType;
protected $isDisabled = 0;
+ protected $triggerObjectPHID;
- protected $configVersion = 21;
+ protected $configVersion = 22;
// phids for which this rule has been applied
private $ruleApplied = self::ATTACHABLE;
@@ -24,6 +25,7 @@
private $author = self::ATTACHABLE;
private $conditions;
private $actions;
+ private $triggerObject = self::ATTACHABLE;
public function getConfiguration() {
return array(
@@ -146,9 +148,7 @@
}
public function delete() {
-
-// TODO:
-// $this->openTransaction();
+ $this->openTransaction();
queryfx(
$this->establishConnection('w'),
'DELETE FROM %T WHERE ruleID = %d',
@@ -159,8 +159,10 @@
'DELETE FROM %T WHERE ruleID = %d',
id(new HeraldAction())->getTableName(),
$this->getID());
- parent::delete();
-// $this->saveTransaction();
+ $result = parent::delete();
+ $this->saveTransaction();
+
+ return $result;
}
public function hasValidAuthor() {
@@ -189,6 +191,19 @@
return ($this->getRuleType() === HeraldRuleTypeConfig::RULE_TYPE_PERSONAL);
}
+ public function isObjectRule() {
+ return ($this->getRuleType() == HeraldRuleTypeConfig::RULE_TYPE_OBJECT);
+ }
+
+ public function attachTriggerObject($trigger_object) {
+ $this->triggerObject = $trigger_object;
+ return $this;
+ }
+
+ public function getTriggerObject() {
+ return $this->assertAttached($this->triggerObject);
+ }
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
@@ -211,6 +226,8 @@
$global = HeraldCapabilityManageGlobalRules::CAPABILITY;
return $herald->getPolicy($global);
}
+ } else if ($this->isObjectRule()) {
+ return $this->getTriggerObject()->getPolicy($capability);
} else {
return PhabricatorPolicies::POLICY_NOONE;
}
@@ -227,6 +244,8 @@
public function describeAutomaticCapability($capability) {
if ($this->isPersonalRule()) {
return pht("A personal rule's owner can always view and edit it.");
+ } else if ($this->isObjectRule()) {
+ return pht("Object rules inherit the policies of their objects.");
}
return null;
Index: src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
===================================================================
--- src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
+++ src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
@@ -1852,6 +1852,10 @@
'type' => 'sql',
'name' => $this->getPatchPath('20131224.harbormanual.sql'),
),
+ '20131227.heraldobject.sql' => array(
+ 'type' => 'sql',
+ 'name' => $this->getPatchPath('20131227.heraldobject.sql'),
+ ),
);
}
}

File Metadata

Mime Type
text/plain
Expires
Sun, Dec 29, 2:46 PM (8 h, 8 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6942562
Default Alt Text
D7847.diff (10 KB)

Event Timeline