@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Move Herald rule querying into HeraldRuleQuery

Summary: Ref T2769. The `HeraldRule` class has some query logic; move it into `HeraldRuleQuery`. Also some minor cleanup.

Test Plan: Ran test console, created a new revision, used `reparse.php --herald`. Verified rules triggered correctly.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2769

Differential Revision: https://secure.phabricator.com/D6689

+149 -89
+1
src/applications/herald/adapter/HeraldCommitAdapter.php
··· 100 100 self::ACTION_ADD_CC, 101 101 self::ACTION_REMOVE_CC, 102 102 self::ACTION_EMAIL, 103 + self::ACTION_FLAG, 103 104 self::ACTION_NOTHING, 104 105 ); 105 106 }
+1
src/applications/herald/adapter/HeraldDifferentialRevisionAdapter.php
··· 258 258 self::ACTION_ADD_CC, 259 259 self::ACTION_REMOVE_CC, 260 260 self::ACTION_EMAIL, 261 + self::ACTION_FLAG, 261 262 self::ACTION_NOTHING, 262 263 ); 263 264 }
+7 -3
src/applications/herald/controller/HeraldTestConsoleController.php
··· 68 68 throw new Exception("Can not build adapter for object!"); 69 69 } 70 70 71 - $rules = HeraldRule::loadAllByContentTypeWithFullData( 72 - $adapter->getAdapterContentType(), 73 - $object->getPHID()); 71 + $rules = id(new HeraldRuleQuery()) 72 + ->setViewer($user) 73 + ->withContentTypes(array($adapter->getAdapterContentType())) 74 + ->needConditionsAndActions(true) 75 + ->needAppliedToPHIDs(array($object->getPHID())) 76 + ->needValidateAuthors(true) 77 + ->execute(); 74 78 75 79 $engine = new HeraldEngine(); 76 80 $effects = $engine->applyRules($rules, $adapter);
+11 -8
src/applications/herald/engine/HeraldEngine.php
··· 14 14 return idx($this->rules, $id); 15 15 } 16 16 17 - public static function loadAndApplyRules(HeraldAdapter $object) { 18 - $content_type = $object->getAdapterContentType(); 19 - $rules = HeraldRule::loadAllByContentTypeWithFullData( 20 - $content_type, 21 - $object->getPHID()); 17 + public static function loadAndApplyRules(HeraldAdapter $adapter) { 18 + $rules = id(new HeraldRuleQuery()) 19 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 20 + ->withContentTypes(array($adapter->getAdapterContentType())) 21 + ->needConditionsAndActions(true) 22 + ->needAppliedToPHIDs(array($adapter->getPHID())) 23 + ->needValidateAuthors(true) 24 + ->execute(); 22 25 23 26 $engine = new HeraldEngine(); 24 - $effects = $engine->applyRules($rules, $object); 25 - $engine->applyEffects($effects, $object, $rules); 27 + $effects = $engine->applyRules($rules, $adapter); 28 + $engine->applyEffects($effects, $adapter, $rules); 26 29 27 30 return $engine->getTranscript(); 28 31 } ··· 215 218 } else if (!$conditions) { 216 219 $reason = "Rule failed automatically because it has no conditions."; 217 220 $result = false; 218 - } else if ($rule->hasInvalidOwner()) { 221 + } else if (!$rule->hasValidAuthor()) { 219 222 $reason = "Rule failed automatically because its owner is invalid ". 220 223 "or disabled."; 221 224 $result = false;
+112
src/applications/herald/query/HeraldRuleQuery.php
··· 9 9 private $ruleTypes; 10 10 private $contentTypes; 11 11 12 + private $needConditionsAndActions; 13 + private $needAppliedToPHIDs; 14 + private $needValidateAuthors; 15 + 12 16 public function withIDs(array $ids) { 13 17 $this->ids = $ids; 14 18 return $this; ··· 34 38 return $this; 35 39 } 36 40 41 + public function withExecutableRules($executable) { 42 + $this->executable = $executable; 43 + return $this; 44 + } 45 + 46 + public function needConditionsAndActions($need) { 47 + $this->needConditionsAndActions = $need; 48 + return $this; 49 + } 50 + 51 + public function needAppliedToPHIDs(array $phids) { 52 + $this->needAppliedToPHIDs = $phids; 53 + return $this; 54 + } 55 + 56 + public function needValidateAuthors($need) { 57 + $this->needValidateAuthors = $need; 58 + return $this; 59 + } 60 + 37 61 public function loadPage() { 38 62 $table = new HeraldRule(); 39 63 $conn_r = $table->establishConnection('r'); ··· 49 73 return $table->loadAllFromArray($data); 50 74 } 51 75 76 + public function willFilterPage(array $rules) { 77 + $rule_ids = mpull($rules, 'getID'); 78 + 79 + if ($this->needValidateAuthors) { 80 + $this->validateRuleAuthors($rules); 81 + } 82 + 83 + if ($this->needConditionsAndActions) { 84 + $conditions = id(new HeraldCondition())->loadAllWhere( 85 + 'ruleID IN (%Ld)', 86 + $rule_ids); 87 + $conditions = mgroup($conditions, 'getRuleID'); 88 + 89 + $actions = id(new HeraldAction())->loadAllWhere( 90 + 'ruleID IN (%Ld)', 91 + $rule_ids); 92 + $actions = mgroup($actions, 'getRuleID'); 93 + 94 + foreach ($rules as $rule) { 95 + $rule->attachActions(idx($actions, $rule->getID(), array())); 96 + $rule->attachConditions(idx($conditions, $rule->getID(), array())); 97 + } 98 + } 99 + 100 + if ($this->needAppliedToPHIDs) { 101 + $conn_r = id(new HeraldRule())->establishConnection('r'); 102 + $applied = queryfx_all( 103 + $conn_r, 104 + 'SELECT * FROM %T WHERE ruleID IN (%Ld) AND phid IN (%Ls)', 105 + HeraldRule::TABLE_RULE_APPLIED, 106 + $rule_ids, 107 + $this->needAppliedToPHIDs); 108 + 109 + $map = array(); 110 + foreach ($applied as $row) { 111 + $map[$row['ruleID']][$row['phid']] = true; 112 + } 113 + 114 + foreach ($rules as $rule) { 115 + foreach ($this->needAppliedToPHIDs as $phid) { 116 + $rule->setRuleApplied( 117 + $phid, 118 + isset($map[$rule->getID()][$phid])); 119 + } 120 + } 121 + } 122 + 123 + return $rules; 124 + } 125 + 52 126 private function buildWhereClause($conn_r) { 53 127 $where = array(); 54 128 ··· 90 164 $where[] = $this->buildPagingClause($conn_r); 91 165 92 166 return $this->formatWhereClause($where); 167 + } 168 + 169 + private function validateRuleAuthors(array $rules) { 170 + 171 + // "Global" rules always have valid authors. 172 + foreach ($rules as $key => $rule) { 173 + if ($rule->isGlobalRule()) { 174 + $rule->attachValidAuthor(true); 175 + unset($rules[$key]); 176 + continue; 177 + } 178 + } 179 + 180 + if (!$rules) { 181 + return; 182 + } 183 + 184 + // For personal rules, the author needs to exist and not be disabled. 185 + $user_phids = mpull($rules, 'getAuthorPHID'); 186 + $users = id(new PhabricatorPeopleQuery()) 187 + ->setViewer($this->getViewer()) 188 + ->withPHIDs($user_phids) 189 + ->execute(); 190 + $users = mpull($users, null, 'getPHID'); 191 + 192 + foreach ($rules as $key => $rule) { 193 + $author_phid = $rule->getAuthorPHID(); 194 + if (empty($users[$author_phid])) { 195 + $rule->attachValidAuthor(false); 196 + continue; 197 + } 198 + if ($users[$author_phid]->getIsDisabled()) { 199 + $rule->attachValidAuthor(false); 200 + continue; 201 + } 202 + 203 + $rule->attachValidAuthor(true); 204 + } 93 205 } 94 206 95 207 }
+8 -74
src/applications/herald/storage/HeraldRule.php
··· 16 16 protected $configVersion = 9; 17 17 18 18 private $ruleApplied = array(); // phids for which this rule has been applied 19 - private $invalidOwner = false; 19 + private $validAuthor = self::ATTACHABLE; 20 20 private $conditions; 21 21 private $actions; 22 22 ··· 28 28 29 29 public function generatePHID() { 30 30 return PhabricatorPHID::generateNewPHID(HeraldPHIDTypeRule::TYPECONST); 31 - } 32 - 33 - public static function loadAllByContentTypeWithFullData( 34 - $content_type, 35 - $object_phid) { 36 - 37 - $rules = id(new HeraldRule())->loadAllWhere( 38 - 'contentType = %s', 39 - $content_type); 40 - 41 - if (!$rules) { 42 - return array(); 43 - } 44 - 45 - self::flagDisabledUserRules($rules); 46 - 47 - $rule_ids = mpull($rules, 'getID'); 48 - 49 - $conditions = id(new HeraldCondition())->loadAllWhere( 50 - 'ruleID in (%Ld)', 51 - $rule_ids); 52 - 53 - $actions = id(new HeraldAction())->loadAllWhere( 54 - 'ruleID in (%Ld)', 55 - $rule_ids); 56 - 57 - $applied = queryfx_all( 58 - id(new HeraldRule())->establishConnection('r'), 59 - 'SELECT * FROM %T WHERE phid = %s', 60 - self::TABLE_RULE_APPLIED, 61 - $object_phid); 62 - $applied = ipull($applied, null, 'ruleID'); 63 - 64 - $conditions = mgroup($conditions, 'getRuleID'); 65 - $actions = mgroup($actions, 'getRuleID'); 66 - $applied = igroup($applied, 'ruleID'); 67 - 68 - foreach ($rules as $rule) { 69 - $rule->setRuleApplied($object_phid, isset($applied[$rule->getID()])); 70 - 71 - $rule->attachConditions(idx($conditions, $rule->getID(), array())); 72 - $rule->attachActions(idx($actions, $rule->getID(), array())); 73 - } 74 - 75 - return $rules; 76 - } 77 - 78 - private static function flagDisabledUserRules(array $rules) { 79 - assert_instances_of($rules, 'HeraldRule'); 80 - 81 - $users = array(); 82 - foreach ($rules as $rule) { 83 - if ($rule->getRuleType() != HeraldRuleTypeConfig::RULE_TYPE_PERSONAL) { 84 - continue; 85 - } 86 - $users[$rule->getAuthorPHID()] = true; 87 - } 88 - 89 - $handles = id(new PhabricatorObjectHandleData(array_keys($users))) 90 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 91 - ->loadHandles(); 92 - 93 - foreach ($rules as $key => $rule) { 94 - if ($rule->getRuleType() != HeraldRuleTypeConfig::RULE_TYPE_PERSONAL) { 95 - continue; 96 - } 97 - $handle = $handles[$rule->getAuthorPHID()]; 98 - if (!$handle->isComplete() || $handle->isDisabled()) { 99 - $rule->invalidOwner = true; 100 - } 101 - } 102 31 } 103 32 104 33 public function getRuleApplied($phid) { ··· 229 158 // $this->saveTransaction(); 230 159 } 231 160 232 - public function hasInvalidOwner() { 233 - return $this->invalidOwner; 161 + public function hasValidAuthor() { 162 + return $this->assertAttached($this->validAuthor); 163 + } 164 + 165 + public function attachValidAuthor($valid) { 166 + $this->validAuthor = $valid; 167 + return $this; 234 168 } 235 169 236 170 public function isGlobalRule() {
+9 -4
src/applications/repository/worker/PhabricatorRepositoryCommitHeraldWorker.php
··· 21 21 return; 22 22 } 23 23 24 - $rules = HeraldRule::loadAllByContentTypeWithFullData( 25 - id(new HeraldCommitAdapter())->getAdapterContentType(), 26 - $commit->getPHID()); 27 - 28 24 $adapter = HeraldCommitAdapter::newLegacyAdapter( 29 25 $repository, 30 26 $commit, 31 27 $data); 28 + 29 + $rules = id(new HeraldRuleQuery()) 30 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 31 + ->withContentTypes(array($adapter->getAdapterContentType())) 32 + ->needConditionsAndActions(true) 33 + ->needAppliedToPHIDs(array($adapter->getPHID())) 34 + ->needValidateAuthors(true) 35 + ->execute(); 36 + 32 37 $engine = new HeraldEngine(); 33 38 34 39 $effects = $engine->applyRules($rules, $adapter);