[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
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 }
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 |