Page MenuHomestyx hydra

No OneTemporary

diff --git a/resources/sql/autopatches/20180124.herald.01.repetition.sql b/resources/sql/autopatches/20180124.herald.01.repetition.sql
new file mode 100644
index 0000000000..3be9ec627d
--- /dev/null
+++ b/resources/sql/autopatches/20180124.herald.01.repetition.sql
@@ -0,0 +1,22 @@
+/* This column was previously "uint32?" with these values:
+
+ 1: run every time
+ 0: run only the first time
+
+*/
+
+ALTER TABLE {$NAMESPACE}_herald.herald_rule
+ CHANGE repetitionPolicy
+ repetitionPolicy VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT};
+
+/* If the old value was "0", the new value is "first". */
+
+UPDATE {$NAMESPACE}_herald.herald_rule
+ SET repetitionPolicy = 'first'
+ WHERE repetitionPolicy = '0';
+
+/* If the old value was anything else, the new value is "every". */
+
+UPDATE {$NAMESPACE}_herald.herald_rule
+ SET repetitionPolicy = 'every'
+ WHERE repetitionPolicy NOT IN ('first', '0');
diff --git a/src/applications/herald/storage/HeraldRule.php b/src/applications/herald/storage/HeraldRule.php
index 6d6f04c7c7..8fd1127eb7 100644
--- a/src/applications/herald/storage/HeraldRule.php
+++ b/src/applications/herald/storage/HeraldRule.php
@@ -1,418 +1,392 @@
<?php
final class HeraldRule extends HeraldDAO
implements
PhabricatorApplicationTransactionInterface,
PhabricatorFlaggableInterface,
PhabricatorPolicyInterface,
PhabricatorDestructibleInterface,
PhabricatorSubscribableInterface {
const TABLE_RULE_APPLIED = 'herald_ruleapplied';
protected $name;
protected $authorPHID;
protected $contentType;
protected $mustMatchAll;
protected $repetitionPolicy;
protected $ruleType;
protected $isDisabled = 0;
protected $triggerObjectPHID;
protected $configVersion = 38;
// PHIDs for which this rule has been applied
private $ruleApplied = self::ATTACHABLE;
private $validAuthor = self::ATTACHABLE;
private $author = self::ATTACHABLE;
private $conditions;
private $actions;
private $triggerObject = self::ATTACHABLE;
const REPEAT_EVERY = 'every';
const REPEAT_FIRST = 'first';
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
'name' => 'sort255',
'contentType' => 'text255',
'mustMatchAll' => 'bool',
'configVersion' => 'uint32',
+ 'repetitionPolicy' => 'text32',
'ruleType' => 'text32',
'isDisabled' => 'uint32',
'triggerObjectPHID' => 'phid?',
-
- // T6203/NULLABILITY
- // This should not be nullable.
- 'repetitionPolicy' => 'uint32?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_name' => array(
'columns' => array('name(128)'),
),
'key_author' => array(
'columns' => array('authorPHID'),
),
'key_ruletype' => array(
'columns' => array('ruleType'),
),
'key_trigger' => array(
'columns' => array('triggerObjectPHID'),
),
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(HeraldRulePHIDType::TYPECONST);
}
public function getRuleApplied($phid) {
return $this->assertAttachedKey($this->ruleApplied, $phid);
}
public function setRuleApplied($phid, $applied) {
if ($this->ruleApplied === self::ATTACHABLE) {
$this->ruleApplied = array();
}
$this->ruleApplied[$phid] = $applied;
return $this;
}
public function loadConditions() {
if (!$this->getID()) {
return array();
}
return id(new HeraldCondition())->loadAllWhere(
'ruleID = %d',
$this->getID());
}
public function attachConditions(array $conditions) {
assert_instances_of($conditions, 'HeraldCondition');
$this->conditions = $conditions;
return $this;
}
public function getConditions() {
// TODO: validate conditions have been attached.
return $this->conditions;
}
public function loadActions() {
if (!$this->getID()) {
return array();
}
return id(new HeraldActionRecord())->loadAllWhere(
'ruleID = %d',
$this->getID());
}
public function attachActions(array $actions) {
// TODO: validate actions have been attached.
assert_instances_of($actions, 'HeraldActionRecord');
$this->actions = $actions;
return $this;
}
public function getActions() {
return $this->actions;
}
public function saveConditions(array $conditions) {
assert_instances_of($conditions, 'HeraldCondition');
return $this->saveChildren(
id(new HeraldCondition())->getTableName(),
$conditions);
}
public function saveActions(array $actions) {
assert_instances_of($actions, 'HeraldActionRecord');
return $this->saveChildren(
id(new HeraldActionRecord())->getTableName(),
$actions);
}
protected function saveChildren($table_name, array $children) {
assert_instances_of($children, 'HeraldDAO');
if (!$this->getID()) {
throw new PhutilInvalidStateException('save');
}
foreach ($children as $child) {
$child->setRuleID($this->getID());
}
$this->openTransaction();
queryfx(
$this->establishConnection('w'),
'DELETE FROM %T WHERE ruleID = %d',
$table_name,
$this->getID());
foreach ($children as $child) {
$child->save();
}
$this->saveTransaction();
}
public function delete() {
$this->openTransaction();
queryfx(
$this->establishConnection('w'),
'DELETE FROM %T WHERE ruleID = %d',
id(new HeraldCondition())->getTableName(),
$this->getID());
queryfx(
$this->establishConnection('w'),
'DELETE FROM %T WHERE ruleID = %d',
id(new HeraldActionRecord())->getTableName(),
$this->getID());
$result = parent::delete();
$this->saveTransaction();
return $result;
}
public function hasValidAuthor() {
return $this->assertAttached($this->validAuthor);
}
public function attachValidAuthor($valid) {
$this->validAuthor = $valid;
return $this;
}
public function getAuthor() {
return $this->assertAttached($this->author);
}
public function attachAuthor(PhabricatorUser $user) {
$this->author = $user;
return $this;
}
public function isGlobalRule() {
return ($this->getRuleType() === HeraldRuleTypeConfig::RULE_TYPE_GLOBAL);
}
public function isPersonalRule() {
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);
}
/**
* Get a sortable key for rule execution order.
*
* Rules execute in a well-defined order: personal rules first, then object
* rules, then global rules. Within each rule type, rules execute from lowest
* ID to highest ID.
*
* This ordering allows more powerful rules (like global rules) to override
* weaker rules (like personal rules) when multiple rules exist which try to
* affect the same field. Executing from low IDs to high IDs makes
* interactions easier to understand when adding new rules, because the newest
* rules always happen last.
*
* @return string A sortable key for this rule.
*/
public function getRuleExecutionOrderSortKey() {
$rule_type = $this->getRuleType();
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
$type_order = 1;
break;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
$type_order = 2;
break;
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
$type_order = 3;
break;
default:
throw new Exception(pht('Unknown rule type "%s"!', $rule_type));
}
return sprintf('~%d%010d', $type_order, $this->getID());
}
public function getMonogram() {
return 'H'.$this->getID();
}
/* -( Repetition Policies )------------------------------------------------ */
public function getRepetitionPolicyStringConstant() {
- $map = self::getRepetitionPolicyMap();
- $map = ipull($map, 'key.string', 'key.int');
-
- return idx($map, $this->getRepetitionPolicyIntegerConstant());
- }
-
- public function getRepetitionPolicyIntegerConstant() {
- $map = self::getRepetitionPolicyMap();
- $map = ipull($map, 'key.int', 'key.int');
- $int = $this->getRepetitionPolicy();
-
- if (!isset($map[$int])) {
- return head_key($map);
- }
-
- return $int;
+ return $this->getRepetitionPolicy();
}
public function setRepetitionPolicyStringConstant($value) {
$map = self::getRepetitionPolicyMap();
- $map = ipull($map, 'key.int', 'key.string');
if (!isset($map[$value])) {
throw new Exception(
pht(
'Rule repetition string constant "%s" is unknown.',
$value));
}
- $int = $map[$value];
-
- return $this->setRepetitionPolicy($int);
+ return $this->setRepetitionPolicy($value);
}
public function isRepeatEvery() {
return ($this->getRepetitionPolicyStringConstant() === self::REPEAT_EVERY);
}
public function isRepeatFirst() {
return ($this->getRepetitionPolicyStringConstant() === self::REPEAT_FIRST);
}
public static function getRepetitionPolicySelectOptionMap() {
$map = self::getRepetitionPolicyMap();
- $map = ipull($map, 'select', 'key.string');
- return $map;
+ return ipull($map, 'select');
}
private static function getRepetitionPolicyMap() {
return array(
self::REPEAT_EVERY => array(
- 'key.int' => 1,
- 'key.string' => self::REPEAT_EVERY,
'select' => pht('every time'),
),
self::REPEAT_FIRST => array(
- 'key.int' => 0,
- 'key.string' => self::REPEAT_FIRST,
'select' => pht('only the first time'),
),
);
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new HeraldRuleEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new HeraldRuleTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
if ($capability == PhabricatorPolicyCapability::CAN_VIEW) {
return PhabricatorPolicies::getMostOpenPolicy();
}
if ($this->isGlobalRule()) {
$app = 'PhabricatorHeraldApplication';
$herald = PhabricatorApplication::getByClass($app);
$global = HeraldManageGlobalRulesCapability::CAPABILITY;
return $herald->getPolicy($global);
} else if ($this->isObjectRule()) {
return $this->getTriggerObject()->getPolicy($capability);
} else {
return $this->getAuthorPHID();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
public function describeAutomaticCapability($capability) {
if ($capability == PhabricatorPolicyCapability::CAN_VIEW) {
return null;
}
if ($this->isGlobalRule()) {
return pht(
'Global Herald rules can be edited by users with the "Can Manage '.
'Global Rules" Herald application permission.');
} else if ($this->isObjectRule()) {
return pht('Object rules inherit the edit policies of their objects.');
} else {
return pht('A personal rule can only be edited by its owner.');
}
}
/* -( PhabricatorSubscribableInterface )----------------------------------- */
public function isAutomaticallySubscribed($phid) {
return $this->isPersonalRule() && $phid == $this->getAuthorPHID();
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$this->openTransaction();
$this->delete();
$this->saveTransaction();
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Apr 29, 12:22 AM (18 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
108137
Default Alt Text
(12 KB)

Event Timeline