[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/herald/adapter/ -> HeraldDifferentialRevisionAdapter.php (source)

   1  <?php
   2  
   3  final class HeraldDifferentialRevisionAdapter
   4    extends HeraldDifferentialAdapter {
   5  
   6    protected $revision;
   7  
   8    protected $explicitCCs;
   9    protected $explicitReviewers;
  10    protected $forbiddenCCs;
  11  
  12    protected $newCCs = array();
  13    protected $remCCs = array();
  14    protected $emailPHIDs = array();
  15    protected $addReviewerPHIDs = array();
  16    protected $blockingReviewerPHIDs = array();
  17    protected $buildPlans = array();
  18    protected $requiredSignatureDocumentPHIDs = array();
  19  
  20    protected $affectedPackages;
  21    protected $changesets;
  22    private $haveHunks;
  23  
  24    public function getAdapterApplicationClass() {
  25      return 'PhabricatorDifferentialApplication';
  26    }
  27  
  28    public function getObject() {
  29      return $this->revision;
  30    }
  31  
  32    public function getDiff() {
  33      return $this->diff;
  34    }
  35  
  36    public function getAdapterContentType() {
  37      return 'differential';
  38    }
  39  
  40    public function getAdapterContentName() {
  41      return pht('Differential Revisions');
  42    }
  43  
  44    public function getAdapterContentDescription() {
  45      return pht(
  46        "React to revisions being created or updated.\n".
  47        "Revision rules can send email, flag revisions, add reviewers, ".
  48        "and run build plans.");
  49    }
  50  
  51    public function supportsRuleType($rule_type) {
  52      switch ($rule_type) {
  53        case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
  54        case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
  55          return true;
  56        case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
  57        default:
  58          return false;
  59      }
  60    }
  61  
  62    public function getFields() {
  63      return array_merge(
  64        array(
  65          self::FIELD_TITLE,
  66          self::FIELD_BODY,
  67          self::FIELD_AUTHOR,
  68          self::FIELD_AUTHOR_PROJECTS,
  69          self::FIELD_REVIEWERS,
  70          self::FIELD_CC,
  71          self::FIELD_REPOSITORY,
  72          self::FIELD_REPOSITORY_PROJECTS,
  73          self::FIELD_DIFF_FILE,
  74          self::FIELD_DIFF_CONTENT,
  75          self::FIELD_DIFF_ADDED_CONTENT,
  76          self::FIELD_DIFF_REMOVED_CONTENT,
  77          self::FIELD_AFFECTED_PACKAGE,
  78          self::FIELD_AFFECTED_PACKAGE_OWNER,
  79          self::FIELD_IS_NEW_OBJECT,
  80          self::FIELD_ARCANIST_PROJECT,
  81        ),
  82        parent::getFields());
  83    }
  84  
  85    public function getRepetitionOptions() {
  86      return array(
  87        HeraldRepetitionPolicyConfig::EVERY,
  88        HeraldRepetitionPolicyConfig::FIRST,
  89      );
  90    }
  91  
  92    public static function newLegacyAdapter(
  93      DifferentialRevision $revision,
  94      DifferentialDiff $diff) {
  95      $object = new HeraldDifferentialRevisionAdapter();
  96  
  97      // Reload the revision to pick up relationship information.
  98      $revision = id(new DifferentialRevisionQuery())
  99        ->withIDs(array($revision->getID()))
 100        ->setViewer(PhabricatorUser::getOmnipotentUser())
 101        ->needRelationships(true)
 102        ->needReviewerStatus(true)
 103        ->executeOne();
 104  
 105      $object->revision = $revision;
 106      $object->diff = $diff;
 107  
 108      return $object;
 109    }
 110  
 111    public function setExplicitCCs($explicit_ccs) {
 112      $this->explicitCCs = $explicit_ccs;
 113      return $this;
 114    }
 115  
 116    public function setExplicitReviewers($explicit_reviewers) {
 117      $this->explicitReviewers = $explicit_reviewers;
 118      return $this;
 119    }
 120  
 121    public function setForbiddenCCs($forbidden_ccs) {
 122      $this->forbiddenCCs = $forbidden_ccs;
 123      return $this;
 124    }
 125  
 126    public function getCCsAddedByHerald() {
 127      return array_diff_key($this->newCCs, $this->remCCs);
 128    }
 129  
 130    public function getCCsRemovedByHerald() {
 131      return $this->remCCs;
 132    }
 133  
 134    public function getEmailPHIDsAddedByHerald() {
 135      return $this->emailPHIDs;
 136    }
 137  
 138    public function getReviewersAddedByHerald() {
 139      return $this->addReviewerPHIDs;
 140    }
 141  
 142    public function getBlockingReviewersAddedByHerald() {
 143      return $this->blockingReviewerPHIDs;
 144    }
 145  
 146    public function getRequiredSignatureDocumentPHIDs() {
 147      return $this->requiredSignatureDocumentPHIDs;
 148    }
 149  
 150    public function getBuildPlans() {
 151      return $this->buildPlans;
 152    }
 153  
 154    public function getPHID() {
 155      return $this->revision->getPHID();
 156    }
 157  
 158    public function getHeraldName() {
 159      return $this->revision->getTitle();
 160    }
 161  
 162    protected function loadChangesets() {
 163      if ($this->changesets === null) {
 164        $this->changesets = $this->diff->loadChangesets();
 165      }
 166      return $this->changesets;
 167    }
 168  
 169    protected function loadChangesetsWithHunks() {
 170      $changesets = $this->loadChangesets();
 171  
 172      if ($changesets && !$this->haveHunks) {
 173        $this->haveHunks = true;
 174  
 175        id(new DifferentialHunkQuery())
 176          ->setViewer(PhabricatorUser::getOmnipotentUser())
 177          ->withChangesets($changesets)
 178          ->needAttachToChangesets(true)
 179          ->execute();
 180      }
 181  
 182      return $changesets;
 183    }
 184  
 185    public function loadAffectedPackages() {
 186      if ($this->affectedPackages === null) {
 187        $this->affectedPackages = array();
 188  
 189        $repository = $this->loadRepository();
 190        if ($repository) {
 191          $packages = PhabricatorOwnersPackage::loadAffectedPackages(
 192            $repository,
 193            $this->loadAffectedPaths());
 194          $this->affectedPackages = $packages;
 195        }
 196      }
 197      return $this->affectedPackages;
 198    }
 199  
 200    public function getHeraldField($field) {
 201      switch ($field) {
 202        case self::FIELD_TITLE:
 203          return $this->revision->getTitle();
 204          break;
 205        case self::FIELD_BODY:
 206          return $this->revision->getSummary()."\n".
 207                 $this->revision->getTestPlan();
 208          break;
 209        case self::FIELD_AUTHOR:
 210          return $this->revision->getAuthorPHID();
 211          break;
 212        case self::FIELD_AUTHOR_PROJECTS:
 213          $author_phid = $this->revision->getAuthorPHID();
 214          if (!$author_phid) {
 215            return array();
 216          }
 217  
 218          $projects = id(new PhabricatorProjectQuery())
 219            ->setViewer(PhabricatorUser::getOmnipotentUser())
 220            ->withMemberPHIDs(array($author_phid))
 221            ->execute();
 222  
 223          return mpull($projects, 'getPHID');
 224        case self::FIELD_DIFF_FILE:
 225          return $this->loadAffectedPaths();
 226        case self::FIELD_CC:
 227          if (isset($this->explicitCCs)) {
 228            return array_keys($this->explicitCCs);
 229          } else {
 230            return $this->revision->getCCPHIDs();
 231          }
 232        case self::FIELD_REVIEWERS:
 233          if (isset($this->explicitReviewers)) {
 234            return array_keys($this->explicitReviewers);
 235          } else {
 236            return $this->revision->getReviewers();
 237          }
 238        case self::FIELD_REPOSITORY:
 239          $repository = $this->loadRepository();
 240          if (!$repository) {
 241            return null;
 242          }
 243          return $repository->getPHID();
 244        case self::FIELD_REPOSITORY_PROJECTS:
 245          $repository = $this->loadRepository();
 246          if (!$repository) {
 247            return array();
 248          }
 249          return $repository->getProjectPHIDs();
 250        case self::FIELD_DIFF_CONTENT:
 251          return $this->loadContentDictionary();
 252        case self::FIELD_DIFF_ADDED_CONTENT:
 253          return $this->loadAddedContentDictionary();
 254        case self::FIELD_DIFF_REMOVED_CONTENT:
 255          return $this->loadRemovedContentDictionary();
 256        case self::FIELD_AFFECTED_PACKAGE:
 257          $packages = $this->loadAffectedPackages();
 258          return mpull($packages, 'getPHID');
 259        case self::FIELD_AFFECTED_PACKAGE_OWNER:
 260          $packages = $this->loadAffectedPackages();
 261          return PhabricatorOwnersOwner::loadAffiliatedUserPHIDs(
 262            mpull($packages, 'getID'));
 263        case self::FIELD_ARCANIST_PROJECT:
 264          return $this->revision->getArcanistProjectPHID();
 265      }
 266  
 267      return parent::getHeraldField($field);
 268    }
 269  
 270    public function getActions($rule_type) {
 271      switch ($rule_type) {
 272        case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
 273          return array_merge(
 274            array(
 275              self::ACTION_ADD_CC,
 276              self::ACTION_REMOVE_CC,
 277              self::ACTION_EMAIL,
 278              self::ACTION_ADD_REVIEWERS,
 279              self::ACTION_ADD_BLOCKING_REVIEWERS,
 280              self::ACTION_APPLY_BUILD_PLANS,
 281              self::ACTION_REQUIRE_SIGNATURE,
 282              self::ACTION_NOTHING,
 283            ),
 284            parent::getActions($rule_type));
 285        case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
 286          return array_merge(
 287            array(
 288              self::ACTION_ADD_CC,
 289              self::ACTION_REMOVE_CC,
 290              self::ACTION_EMAIL,
 291              self::ACTION_FLAG,
 292              self::ACTION_ADD_REVIEWERS,
 293              self::ACTION_ADD_BLOCKING_REVIEWERS,
 294              self::ACTION_NOTHING,
 295            ),
 296            parent::getActions($rule_type));
 297      }
 298    }
 299  
 300    public function applyHeraldEffects(array $effects) {
 301      assert_instances_of($effects, 'HeraldEffect');
 302  
 303      $result = array();
 304      if ($this->explicitCCs) {
 305        $effect = new HeraldEffect();
 306        $effect->setAction(self::ACTION_ADD_CC);
 307        $effect->setTarget(array_keys($this->explicitCCs));
 308        $effect->setReason(
 309          pht('CCs provided explicitly by revision author or carried over '.
 310          'from a previous version of the revision.'));
 311        $result[] = new HeraldApplyTranscript(
 312          $effect,
 313          true,
 314          pht('Added addresses to CC list.'));
 315      }
 316  
 317      $forbidden_ccs = array_fill_keys(
 318        nonempty($this->forbiddenCCs, array()),
 319        true);
 320  
 321      foreach ($effects as $effect) {
 322        $action = $effect->getAction();
 323        switch ($action) {
 324          case self::ACTION_NOTHING:
 325            $result[] = new HeraldApplyTranscript(
 326              $effect,
 327              true,
 328              pht('OK, did nothing.'));
 329            break;
 330          case self::ACTION_FLAG:
 331            $result[] = parent::applyFlagEffect(
 332              $effect,
 333              $this->revision->getPHID());
 334            break;
 335          case self::ACTION_EMAIL:
 336          case self::ACTION_ADD_CC:
 337            $op = ($action == self::ACTION_EMAIL) ? 'email' : 'CC';
 338            $base_target = $effect->getTarget();
 339            $forbidden = array();
 340            foreach ($base_target as $key => $fbid) {
 341              if (isset($forbidden_ccs[$fbid])) {
 342                $forbidden[] = $fbid;
 343                unset($base_target[$key]);
 344              } else {
 345                if ($action == self::ACTION_EMAIL) {
 346                  $this->emailPHIDs[$fbid] = true;
 347                } else {
 348                  $this->newCCs[$fbid] = true;
 349                }
 350              }
 351            }
 352  
 353            if ($forbidden) {
 354              $failed = clone $effect;
 355              $failed->setTarget($forbidden);
 356              if ($base_target) {
 357                $effect->setTarget($base_target);
 358                $result[] = new HeraldApplyTranscript(
 359                  $effect,
 360                  true,
 361                  pht('Added these addresses to %s list. '.
 362                  'Others could not be added.', $op));
 363              }
 364              $result[] = new HeraldApplyTranscript(
 365                $failed,
 366                false,
 367                pht('%s forbidden, these addresses have unsubscribed.', $op));
 368            } else {
 369              $result[] = new HeraldApplyTranscript(
 370                $effect,
 371                true,
 372                pht('Added addresses to %s list.', $op));
 373            }
 374            break;
 375          case self::ACTION_REMOVE_CC:
 376            foreach ($effect->getTarget() as $fbid) {
 377              $this->remCCs[$fbid] = true;
 378            }
 379            $result[] = new HeraldApplyTranscript(
 380              $effect,
 381              true,
 382              pht('Removed addresses from CC list.'));
 383            break;
 384          case self::ACTION_ADD_REVIEWERS:
 385            foreach ($effect->getTarget() as $phid) {
 386              $this->addReviewerPHIDs[$phid] = true;
 387            }
 388            $result[] = new HeraldApplyTranscript(
 389              $effect,
 390              true,
 391              pht('Added reviewers.'));
 392            break;
 393          case self::ACTION_ADD_BLOCKING_REVIEWERS:
 394            // This adds reviewers normally, it just also marks them blocking.
 395            foreach ($effect->getTarget() as $phid) {
 396              $this->addReviewerPHIDs[$phid] = true;
 397              $this->blockingReviewerPHIDs[$phid] = true;
 398            }
 399            $result[] = new HeraldApplyTranscript(
 400              $effect,
 401              true,
 402              pht('Added blocking reviewers.'));
 403            break;
 404          case self::ACTION_APPLY_BUILD_PLANS:
 405            foreach ($effect->getTarget() as $phid) {
 406              $this->buildPlans[] = $phid;
 407            }
 408            $result[] = new HeraldApplyTranscript(
 409              $effect,
 410              true,
 411              pht('Applied build plans.'));
 412            break;
 413          case self::ACTION_REQUIRE_SIGNATURE:
 414            foreach ($effect->getTarget() as $phid) {
 415              $this->requiredSignatureDocumentPHIDs[] = $phid;
 416            }
 417            $result[] = new HeraldApplyTranscript(
 418              $effect,
 419              true,
 420              pht('Required signatures.'));
 421            break;
 422          default:
 423            $custom_result = parent::handleCustomHeraldEffect($effect);
 424            if ($custom_result === null) {
 425              throw new Exception(pht(
 426                "No rules to handle action '%s'.",
 427                $action));
 428            }
 429  
 430            $result[] = $custom_result;
 431            break;
 432        }
 433      }
 434      return $result;
 435    }
 436  
 437  }


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