[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/herald/storage/ -> HeraldRule.php (source)

   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  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1