[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/repository/storage/ -> PhabricatorRepositoryCommit.php (source)

   1  <?php
   2  
   3  final class PhabricatorRepositoryCommit
   4    extends PhabricatorRepositoryDAO
   5    implements
   6      PhabricatorPolicyInterface,
   7      PhabricatorFlaggableInterface,
   8      PhabricatorProjectInterface,
   9      PhabricatorTokenReceiverInterface,
  10      PhabricatorSubscribableInterface,
  11      PhabricatorMentionableInterface,
  12      HarbormasterBuildableInterface,
  13      PhabricatorCustomFieldInterface,
  14      PhabricatorApplicationTransactionInterface {
  15  
  16    protected $repositoryID;
  17    protected $phid;
  18    protected $commitIdentifier;
  19    protected $epoch;
  20    protected $mailKey;
  21    protected $authorPHID;
  22    protected $auditStatus = PhabricatorAuditCommitStatusConstants::NONE;
  23    protected $summary = '';
  24    protected $importStatus = 0;
  25  
  26    const IMPORTED_MESSAGE = 1;
  27    const IMPORTED_CHANGE = 2;
  28    const IMPORTED_OWNERS = 4;
  29    const IMPORTED_HERALD = 8;
  30    const IMPORTED_ALL = 15;
  31  
  32    const IMPORTED_CLOSEABLE = 1024;
  33  
  34    private $commitData = self::ATTACHABLE;
  35    private $audits = self::ATTACHABLE;
  36    private $repository = self::ATTACHABLE;
  37    private $customFields = self::ATTACHABLE;
  38  
  39    public function attachRepository(PhabricatorRepository $repository) {
  40      $this->repository = $repository;
  41      return $this;
  42    }
  43  
  44    public function getRepository($assert_attached = true) {
  45      if ($assert_attached) {
  46        return $this->assertAttached($this->repository);
  47      }
  48      return $this->repository;
  49    }
  50  
  51    public function isPartiallyImported($mask) {
  52      return (($mask & $this->getImportStatus()) == $mask);
  53    }
  54  
  55    public function isImported() {
  56      return $this->isPartiallyImported(self::IMPORTED_ALL);
  57    }
  58  
  59    public function writeImportStatusFlag($flag) {
  60      queryfx(
  61        $this->establishConnection('w'),
  62        'UPDATE %T SET importStatus = (importStatus | %d) WHERE id = %d',
  63        $this->getTableName(),
  64        $flag,
  65        $this->getID());
  66      $this->setImportStatus($this->getImportStatus() | $flag);
  67      return $this;
  68    }
  69  
  70    public function getConfiguration() {
  71      return array(
  72        self::CONFIG_AUX_PHID   => true,
  73        self::CONFIG_TIMESTAMPS => false,
  74        self::CONFIG_COLUMN_SCHEMA => array(
  75          'commitIdentifier' => 'text40',
  76          'mailKey' => 'bytes20',
  77          'authorPHID' => 'phid?',
  78          'auditStatus' => 'uint32',
  79          'summary' => 'text80',
  80          'importStatus' => 'uint32',
  81        ),
  82        self::CONFIG_KEY_SCHEMA => array(
  83          'key_phid' => null,
  84          'phid' => array(
  85            'columns' => array('phid'),
  86            'unique' => true,
  87          ),
  88          'repositoryID' => array(
  89            'columns' => array('repositoryID', 'importStatus'),
  90          ),
  91          'authorPHID' => array(
  92            'columns' => array('authorPHID', 'auditStatus', 'epoch'),
  93          ),
  94          'repositoryID_2' => array(
  95            'columns' => array('repositoryID', 'epoch'),
  96          ),
  97          'key_commit_identity' => array(
  98            'columns' => array('commitIdentifier', 'repositoryID'),
  99            'unique' => true,
 100          ),
 101        ),
 102      ) + parent::getConfiguration();
 103    }
 104  
 105    public function generatePHID() {
 106      return PhabricatorPHID::generateNewPHID(
 107        PhabricatorRepositoryCommitPHIDType::TYPECONST);
 108    }
 109  
 110    public function loadCommitData() {
 111      if (!$this->getID()) {
 112        return null;
 113      }
 114      return id(new PhabricatorRepositoryCommitData())->loadOneWhere(
 115        'commitID = %d',
 116        $this->getID());
 117    }
 118  
 119    public function attachCommitData(
 120      PhabricatorRepositoryCommitData $data = null) {
 121      $this->commitData = $data;
 122      return $this;
 123    }
 124  
 125    public function getCommitData() {
 126      return $this->assertAttached($this->commitData);
 127    }
 128  
 129    public function attachAudits(array $audits) {
 130      assert_instances_of($audits, 'PhabricatorRepositoryAuditRequest');
 131      $this->audits = $audits;
 132      return $this;
 133    }
 134  
 135    public function getAudits() {
 136      return $this->assertAttached($this->audits);
 137    }
 138  
 139    public function getAuthorityAudits(
 140      PhabricatorUser $user,
 141      array $authority_phids) {
 142  
 143      $authority = array_fill_keys($authority_phids, true);
 144      $audits = $this->getAudits();
 145      $authority_audits = array();
 146      foreach ($audits as $audit) {
 147        $has_authority = !empty($authority[$audit->getAuditorPHID()]);
 148        if ($has_authority) {
 149          $commit_author = $this->getAuthorPHID();
 150  
 151          // You don't have authority over package and project audits on your
 152          // own commits.
 153  
 154          $auditor_is_user = ($audit->getAuditorPHID() == $user->getPHID());
 155          $user_is_author = ($commit_author == $user->getPHID());
 156  
 157          if ($auditor_is_user || !$user_is_author) {
 158            $authority_audits[$audit->getID()] = $audit;
 159          }
 160        }
 161      }
 162      return $authority_audits;
 163    }
 164  
 165    public function save() {
 166      if (!$this->mailKey) {
 167        $this->mailKey = Filesystem::readRandomCharacters(20);
 168      }
 169      return parent::save();
 170    }
 171  
 172    public function delete() {
 173      $data = $this->loadCommitData();
 174      $audits = id(new PhabricatorRepositoryAuditRequest())
 175        ->loadAllWhere('commitPHID = %s', $this->getPHID());
 176      $this->openTransaction();
 177  
 178        if ($data) {
 179          $data->delete();
 180        }
 181        foreach ($audits as $audit) {
 182          $audit->delete();
 183        }
 184        $result = parent::delete();
 185  
 186      $this->saveTransaction();
 187      return $result;
 188    }
 189  
 190    public function getDateCreated() {
 191      // This is primarily to make analysis of commits with the Fact engine work.
 192      return $this->getEpoch();
 193    }
 194  
 195    public function getURI() {
 196      $repository = $this->getRepository();
 197      $callsign = $repository->getCallsign();
 198      $commit_identifier = $this->getCommitIdentifier();
 199      return '/r'.$callsign.$commit_identifier;
 200    }
 201  
 202    /**
 203     * Synchronize a commit's overall audit status with the individual audit
 204     * triggers.
 205     */
 206    public function updateAuditStatus(array $requests) {
 207      assert_instances_of($requests, 'PhabricatorRepositoryAuditRequest');
 208  
 209      $any_concern = false;
 210      $any_accept = false;
 211      $any_need = false;
 212  
 213      foreach ($requests as $request) {
 214        switch ($request->getAuditStatus()) {
 215          case PhabricatorAuditStatusConstants::AUDIT_REQUIRED:
 216            $any_need = true;
 217            break;
 218          case PhabricatorAuditStatusConstants::ACCEPTED:
 219            $any_accept = true;
 220            break;
 221          case PhabricatorAuditStatusConstants::CONCERNED:
 222            $any_concern = true;
 223            break;
 224        }
 225      }
 226  
 227      if ($any_concern) {
 228        $status = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
 229      } else if ($any_accept) {
 230        if ($any_need) {
 231          $status = PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED;
 232        } else {
 233          $status = PhabricatorAuditCommitStatusConstants::FULLY_AUDITED;
 234        }
 235      } else if ($any_need) {
 236        $status = PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT;
 237      } else {
 238        $status = PhabricatorAuditCommitStatusConstants::NONE;
 239      }
 240  
 241      return $this->setAuditStatus($status);
 242    }
 243  
 244  
 245  /* -(  PhabricatorPolicyInterface  )----------------------------------------- */
 246  
 247    public function getCapabilities() {
 248      return array(
 249        PhabricatorPolicyCapability::CAN_VIEW,
 250        PhabricatorPolicyCapability::CAN_EDIT,
 251      );
 252    }
 253  
 254    public function getPolicy($capability) {
 255      switch ($capability) {
 256        case PhabricatorPolicyCapability::CAN_VIEW:
 257          return $this->getRepository()->getPolicy($capability);
 258        case PhabricatorPolicyCapability::CAN_EDIT:
 259          // TODO: (T603) Who should be able to edit a commit? For now, retain
 260          // the existing policy.
 261          return PhabricatorPolicies::POLICY_USER;
 262      }
 263    }
 264  
 265    public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
 266      return $this->getRepository()->hasAutomaticCapability($capability, $viewer);
 267    }
 268  
 269    public function describeAutomaticCapability($capability) {
 270      return pht(
 271        'Commits inherit the policies of the repository they belong to.');
 272    }
 273  
 274  
 275  /* -(  PhabricatorTokenReceiverInterface  )---------------------------------- */
 276  
 277    public function getUsersToNotifyOfTokenGiven() {
 278      return array(
 279        $this->getAuthorPHID(),
 280      );
 281    }
 282  
 283  /* -( Stuff for serialization )---------------------------------------------- */
 284  
 285    /**
 286     * NOTE: this is not a complete serialization; only the 'protected' fields are
 287     * involved. This is due to ease of (ab)using the Lisk abstraction to get this
 288     * done, as well as complexity of the other fields.
 289     */
 290    public function toDictionary() {
 291      return array(
 292        'repositoryID' => $this->getRepositoryID(),
 293        'phid' =>  $this->getPHID(),
 294        'commitIdentifier' =>  $this->getCommitIdentifier(),
 295        'epoch' => $this->getEpoch(),
 296        'mailKey' => $this->getMailKey(),
 297        'authorPHID' => $this->getAuthorPHID(),
 298        'auditStatus' => $this->getAuditStatus(),
 299        'summary' => $this->getSummary(),
 300        'importStatus' => $this->getImportStatus(),
 301      );
 302    }
 303  
 304    public static function newFromDictionary(array $dict) {
 305      return id(new PhabricatorRepositoryCommit())
 306        ->loadFromArray($dict);
 307    }
 308  
 309  
 310  /* -(  HarbormasterBuildableInterface  )------------------------------------- */
 311  
 312  
 313    public function getHarbormasterBuildablePHID() {
 314      return $this->getPHID();
 315    }
 316  
 317    public function getHarbormasterContainerPHID() {
 318      return $this->getRepository()->getPHID();
 319    }
 320  
 321    public function getBuildVariables() {
 322      $results = array();
 323  
 324      $results['buildable.commit'] = $this->getCommitIdentifier();
 325      $repo = $this->getRepository();
 326  
 327      $results['repository.callsign'] = $repo->getCallsign();
 328      $results['repository.vcs'] = $repo->getVersionControlSystem();
 329      $results['repository.uri'] = $repo->getPublicCloneURI();
 330  
 331      return $results;
 332    }
 333  
 334    public function getAvailableBuildVariables() {
 335      return array(
 336        'buildable.commit' => pht('The commit identifier, if applicable.'),
 337        'repository.callsign' =>
 338          pht('The callsign of the repository in Phabricator.'),
 339        'repository.vcs' =>
 340          pht('The version control system, either "svn", "hg" or "git".'),
 341        'repository.uri' =>
 342          pht('The URI to clone or checkout the repository from.'),
 343      );
 344    }
 345  
 346  
 347  /* -(  PhabricatorCustomFieldInterface  )------------------------------------ */
 348  
 349  
 350    public function getCustomFieldSpecificationForRole($role) {
 351      // TODO: We could make this configurable eventually, but just use the
 352      // defaults for now.
 353      return array();
 354    }
 355  
 356    public function getCustomFieldBaseClass() {
 357      return 'PhabricatorCommitCustomField';
 358    }
 359  
 360    public function getCustomFields() {
 361      return $this->assertAttached($this->customFields);
 362    }
 363  
 364    public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
 365      $this->customFields = $fields;
 366      return $this;
 367    }
 368  
 369  
 370  /* -(  PhabricatorSubscribableInterface  )----------------------------------- */
 371  
 372  
 373    public function isAutomaticallySubscribed($phid) {
 374  
 375      // TODO: This should also list auditors, but handling that is a bit messy
 376      // right now because we are not guaranteed to have the data.
 377  
 378      return ($phid == $this->getAuthorPHID());
 379    }
 380  
 381    public function shouldShowSubscribersProperty() {
 382      return true;
 383    }
 384  
 385    public function shouldAllowSubscription($phid) {
 386      return true;
 387    }
 388  
 389  
 390  /* -(  PhabricatorApplicationTransactionInterface  )------------------------- */
 391  
 392  
 393    public function getApplicationTransactionEditor() {
 394      return new PhabricatorAuditEditor();
 395    }
 396  
 397    public function getApplicationTransactionObject() {
 398      return $this;
 399    }
 400  
 401    public function getApplicationTransactionTemplate() {
 402      return new PhabricatorAuditTransaction();
 403    }
 404  
 405  }


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