[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class HeraldRule extends HeraldDAO 4 implements 5 PhabricatorFlaggableInterface, 6 PhabricatorPolicyInterface, 7 PhabricatorDestructibleInterface { 8 9 const TABLE_RULE_APPLIED = 'herald_ruleapplied'; 10 11 protected $name; 12 protected $authorPHID; 13 14 protected $contentType; 15 protected $mustMatchAll; 16 protected $repetitionPolicy; 17 protected $ruleType; 18 protected $isDisabled = 0; 19 protected $triggerObjectPHID; 20 21 protected $configVersion = 38; 22 23 // PHIDs for which this rule has been applied 24 private $ruleApplied = self::ATTACHABLE; 25 private $validAuthor = self::ATTACHABLE; 26 private $author = self::ATTACHABLE; 27 private $conditions; 28 private $actions; 29 private $triggerObject = self::ATTACHABLE; 30 31 public function getConfiguration() { 32 return array( 33 self::CONFIG_AUX_PHID => true, 34 self::CONFIG_COLUMN_SCHEMA => array( 35 'name' => 'text255', 36 'contentType' => 'text255', 37 'mustMatchAll' => 'bool', 38 'configVersion' => 'uint32', 39 'ruleType' => 'text32', 40 'isDisabled' => 'uint32', 41 'triggerObjectPHID' => 'phid?', 42 43 // T6203/NULLABILITY 44 // This should not be nullable. 45 'repetitionPolicy' => 'uint32?', 46 ), 47 self::CONFIG_KEY_SCHEMA => array( 48 'key_author' => array( 49 'columns' => array('authorPHID'), 50 ), 51 'key_ruletype' => array( 52 'columns' => array('ruleType'), 53 ), 54 'key_trigger' => array( 55 'columns' => array('triggerObjectPHID'), 56 ), 57 ), 58 ) + parent::getConfiguration(); 59 } 60 61 public function generatePHID() { 62 return PhabricatorPHID::generateNewPHID(HeraldRulePHIDType::TYPECONST); 63 } 64 65 public function getRuleApplied($phid) { 66 return $this->assertAttachedKey($this->ruleApplied, $phid); 67 } 68 69 public function setRuleApplied($phid, $applied) { 70 if ($this->ruleApplied === self::ATTACHABLE) { 71 $this->ruleApplied = array(); 72 } 73 $this->ruleApplied[$phid] = $applied; 74 return $this; 75 } 76 77 public function loadConditions() { 78 if (!$this->getID()) { 79 return array(); 80 } 81 return id(new HeraldCondition())->loadAllWhere( 82 'ruleID = %d', 83 $this->getID()); 84 } 85 86 public function attachConditions(array $conditions) { 87 assert_instances_of($conditions, 'HeraldCondition'); 88 $this->conditions = $conditions; 89 return $this; 90 } 91 92 public function getConditions() { 93 // TODO: validate conditions have been attached. 94 return $this->conditions; 95 } 96 97 public function loadActions() { 98 if (!$this->getID()) { 99 return array(); 100 } 101 return id(new HeraldAction())->loadAllWhere( 102 'ruleID = %d', 103 $this->getID()); 104 } 105 106 public function attachActions(array $actions) { 107 // TODO: validate actions have been attached. 108 assert_instances_of($actions, 'HeraldAction'); 109 $this->actions = $actions; 110 return $this; 111 } 112 113 public function getActions() { 114 return $this->actions; 115 } 116 117 public function loadEdits() { 118 if (!$this->getID()) { 119 return array(); 120 } 121 $edits = id(new HeraldRuleEdit())->loadAllWhere( 122 'ruleID = %d ORDER BY dateCreated DESC', 123 $this->getID()); 124 125 return $edits; 126 } 127 128 public function logEdit($editor_phid, $action) { 129 id(new HeraldRuleEdit()) 130 ->setRuleID($this->getID()) 131 ->setRuleName($this->getName()) 132 ->setEditorPHID($editor_phid) 133 ->setAction($action) 134 ->save(); 135 } 136 137 public function saveConditions(array $conditions) { 138 assert_instances_of($conditions, 'HeraldCondition'); 139 return $this->saveChildren( 140 id(new HeraldCondition())->getTableName(), 141 $conditions); 142 } 143 144 public function saveActions(array $actions) { 145 assert_instances_of($actions, 'HeraldAction'); 146 return $this->saveChildren( 147 id(new HeraldAction())->getTableName(), 148 $actions); 149 } 150 151 protected function saveChildren($table_name, array $children) { 152 assert_instances_of($children, 'HeraldDAO'); 153 154 if (!$this->getID()) { 155 throw new Exception('Save rule before saving children.'); 156 } 157 158 foreach ($children as $child) { 159 $child->setRuleID($this->getID()); 160 } 161 162 $this->openTransaction(); 163 queryfx( 164 $this->establishConnection('w'), 165 'DELETE FROM %T WHERE ruleID = %d', 166 $table_name, 167 $this->getID()); 168 foreach ($children as $child) { 169 $child->save(); 170 } 171 $this->saveTransaction(); 172 } 173 174 public function delete() { 175 $this->openTransaction(); 176 queryfx( 177 $this->establishConnection('w'), 178 'DELETE FROM %T WHERE ruleID = %d', 179 id(new HeraldCondition())->getTableName(), 180 $this->getID()); 181 queryfx( 182 $this->establishConnection('w'), 183 'DELETE FROM %T WHERE ruleID = %d', 184 id(new HeraldAction())->getTableName(), 185 $this->getID()); 186 $result = parent::delete(); 187 $this->saveTransaction(); 188 189 return $result; 190 } 191 192 public function hasValidAuthor() { 193 return $this->assertAttached($this->validAuthor); 194 } 195 196 public function attachValidAuthor($valid) { 197 $this->validAuthor = $valid; 198 return $this; 199 } 200 201 public function getAuthor() { 202 return $this->assertAttached($this->author); 203 } 204 205 public function attachAuthor(PhabricatorUser $user) { 206 $this->author = $user; 207 return $this; 208 } 209 210 public function isGlobalRule() { 211 return ($this->getRuleType() === HeraldRuleTypeConfig::RULE_TYPE_GLOBAL); 212 } 213 214 public function isPersonalRule() { 215 return ($this->getRuleType() === HeraldRuleTypeConfig::RULE_TYPE_PERSONAL); 216 } 217 218 public function isObjectRule() { 219 return ($this->getRuleType() == HeraldRuleTypeConfig::RULE_TYPE_OBJECT); 220 } 221 222 public function attachTriggerObject($trigger_object) { 223 $this->triggerObject = $trigger_object; 224 return $this; 225 } 226 227 public function getTriggerObject() { 228 return $this->assertAttached($this->triggerObject); 229 } 230 231 /** 232 * Get a sortable key for rule execution order. 233 * 234 * Rules execute in a well-defined order: personal rules first, then object 235 * rules, then global rules. Within each rule type, rules execute from lowest 236 * ID to highest ID. 237 * 238 * This ordering allows more powerful rules (like global rules) to override 239 * weaker rules (like personal rules) when multiple rules exist which try to 240 * affect the same field. Executing from low IDs to high IDs makes 241 * interactions easier to understand when adding new rules, because the newest 242 * rules always happen last. 243 * 244 * @return string A sortable key for this rule. 245 */ 246 public function getRuleExecutionOrderSortKey() { 247 248 $rule_type = $this->getRuleType(); 249 250 switch ($rule_type) { 251 case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: 252 $type_order = 1; 253 break; 254 case HeraldRuleTypeConfig::RULE_TYPE_OBJECT: 255 $type_order = 2; 256 break; 257 case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: 258 $type_order = 3; 259 break; 260 default: 261 throw new Exception(pht('Unknown rule type "%s"!', $rule_type)); 262 } 263 264 return sprintf('~%d%010d', $type_order, $this->getID()); 265 } 266 267 268 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 269 270 271 public function getCapabilities() { 272 return array( 273 PhabricatorPolicyCapability::CAN_VIEW, 274 PhabricatorPolicyCapability::CAN_EDIT, 275 ); 276 } 277 278 public function getPolicy($capability) { 279 if ($this->isGlobalRule()) { 280 switch ($capability) { 281 case PhabricatorPolicyCapability::CAN_VIEW: 282 return PhabricatorPolicies::POLICY_USER; 283 case PhabricatorPolicyCapability::CAN_EDIT: 284 $app = 'PhabricatorHeraldApplication'; 285 $herald = PhabricatorApplication::getByClass($app); 286 $global = HeraldManageGlobalRulesCapability::CAPABILITY; 287 return $herald->getPolicy($global); 288 } 289 } else if ($this->isObjectRule()) { 290 return $this->getTriggerObject()->getPolicy($capability); 291 } else { 292 return PhabricatorPolicies::POLICY_NOONE; 293 } 294 } 295 296 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 297 if ($this->isPersonalRule()) { 298 return ($viewer->getPHID() == $this->getAuthorPHID()); 299 } else { 300 return false; 301 } 302 } 303 304 public function describeAutomaticCapability($capability) { 305 if ($this->isPersonalRule()) { 306 return pht("A personal rule's owner can always view and edit it."); 307 } else if ($this->isObjectRule()) { 308 return pht('Object rules inherit the policies of their objects.'); 309 } 310 311 return null; 312 } 313 314 315 /* -( PhabricatorDestructibleInterface )----------------------------------- */ 316 317 public function destroyObjectPermanently( 318 PhabricatorDestructionEngine $engine) { 319 320 $this->openTransaction(); 321 $this->delete(); 322 $this->saveTransaction(); 323 } 324 325 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |