Correct Aphlict websocket URI construction after PHP8 compatibility changes
[phabricator.git] / src / applications / repository / storage / PhabricatorRepositoryCommit.php
blob70beb6ea8beddbce69cb701fc41a81e94b10e32d
1 <?php
3 final class PhabricatorRepositoryCommit
4 extends PhabricatorRepositoryDAO
5 implements
6 PhabricatorPolicyInterface,
7 PhabricatorFlaggableInterface,
8 PhabricatorProjectInterface,
9 PhabricatorTokenReceiverInterface,
10 PhabricatorSubscribableInterface,
11 PhabricatorMentionableInterface,
12 HarbormasterBuildableInterface,
13 HarbormasterCircleCIBuildableInterface,
14 HarbormasterBuildkiteBuildableInterface,
15 PhabricatorCustomFieldInterface,
16 PhabricatorApplicationTransactionInterface,
17 PhabricatorTimelineInterface,
18 PhabricatorFulltextInterface,
19 PhabricatorFerretInterface,
20 PhabricatorConduitResultInterface,
21 PhabricatorDraftInterface {
23 protected $repositoryID;
24 protected $phid;
25 protected $authorIdentityPHID;
26 protected $committerIdentityPHID;
27 protected $commitIdentifier;
28 protected $epoch;
29 protected $authorPHID;
30 protected $auditStatus = DiffusionCommitAuditStatus::NONE;
31 protected $summary = '';
32 protected $importStatus = 0;
34 const IMPORTED_MESSAGE = 1;
35 const IMPORTED_CHANGE = 2;
36 const IMPORTED_PUBLISH = 8;
37 const IMPORTED_ALL = 11;
39 const IMPORTED_PERMANENT = 1024;
40 const IMPORTED_UNREACHABLE = 2048;
42 private $commitData = self::ATTACHABLE;
43 private $audits = self::ATTACHABLE;
44 private $repository = self::ATTACHABLE;
45 private $customFields = self::ATTACHABLE;
46 private $authorIdentity = self::ATTACHABLE;
47 private $committerIdentity = self::ATTACHABLE;
49 private $drafts = array();
50 private $auditAuthorityPHIDs = array();
52 public function attachRepository(PhabricatorRepository $repository) {
53 $this->repository = $repository;
54 return $this;
57 public function getRepository($assert_attached = true) {
58 if ($assert_attached) {
59 return $this->assertAttached($this->repository);
61 return $this->repository;
64 public function isPartiallyImported($mask) {
65 return (($mask & $this->getImportStatus()) == $mask);
68 public function isImported() {
69 return $this->isPartiallyImported(self::IMPORTED_ALL);
72 public function isUnreachable() {
73 return $this->isPartiallyImported(self::IMPORTED_UNREACHABLE);
76 public function writeImportStatusFlag($flag) {
77 return $this->adjustImportStatusFlag($flag, true);
80 public function clearImportStatusFlag($flag) {
81 return $this->adjustImportStatusFlag($flag, false);
84 private function adjustImportStatusFlag($flag, $set) {
85 $conn_w = $this->establishConnection('w');
86 $table_name = $this->getTableName();
87 $id = $this->getID();
89 if ($set) {
90 queryfx(
91 $conn_w,
92 'UPDATE %T SET importStatus = (importStatus | %d) WHERE id = %d',
93 $table_name,
94 $flag,
95 $id);
97 $this->setImportStatus($this->getImportStatus() | $flag);
98 } else {
99 queryfx(
100 $conn_w,
101 'UPDATE %T SET importStatus = (importStatus & ~%d) WHERE id = %d',
102 $table_name,
103 $flag,
104 $id);
106 $this->setImportStatus($this->getImportStatus() & ~$flag);
109 return $this;
112 protected function getConfiguration() {
113 return array(
114 self::CONFIG_AUX_PHID => true,
115 self::CONFIG_TIMESTAMPS => false,
116 self::CONFIG_COLUMN_SCHEMA => array(
117 'commitIdentifier' => 'text40',
118 'authorPHID' => 'phid?',
119 'authorIdentityPHID' => 'phid?',
120 'committerIdentityPHID' => 'phid?',
121 'auditStatus' => 'text32',
122 'summary' => 'text255',
123 'importStatus' => 'uint32',
125 self::CONFIG_KEY_SCHEMA => array(
126 'key_phid' => null,
127 'phid' => array(
128 'columns' => array('phid'),
129 'unique' => true,
131 'repositoryID' => array(
132 'columns' => array('repositoryID', 'importStatus'),
134 'authorPHID' => array(
135 'columns' => array('authorPHID', 'auditStatus', 'epoch'),
137 'repositoryID_2' => array(
138 'columns' => array('repositoryID', 'epoch'),
140 'key_commit_identity' => array(
141 'columns' => array('commitIdentifier', 'repositoryID'),
142 'unique' => true,
144 'key_epoch' => array(
145 'columns' => array('epoch'),
147 'key_author' => array(
148 'columns' => array('authorPHID', 'epoch'),
151 self::CONFIG_NO_MUTATE => array(
152 'importStatus',
154 ) + parent::getConfiguration();
157 public function generatePHID() {
158 return PhabricatorPHID::generateNewPHID(
159 PhabricatorRepositoryCommitPHIDType::TYPECONST);
162 public function loadCommitData() {
163 if (!$this->getID()) {
164 return null;
166 return id(new PhabricatorRepositoryCommitData())->loadOneWhere(
167 'commitID = %d',
168 $this->getID());
171 public function attachCommitData(
172 PhabricatorRepositoryCommitData $data = null) {
173 $this->commitData = $data;
174 return $this;
177 public function hasCommitData() {
178 return ($this->commitData !== self::ATTACHABLE) &&
179 ($this->commitData !== null);
182 public function getCommitData() {
183 return $this->assertAttached($this->commitData);
186 public function attachAudits(array $audits) {
187 assert_instances_of($audits, 'PhabricatorRepositoryAuditRequest');
188 $this->audits = $audits;
189 return $this;
192 public function getAudits() {
193 return $this->assertAttached($this->audits);
196 public function hasAttachedAudits() {
197 return ($this->audits !== self::ATTACHABLE);
200 public function attachIdentities(
201 PhabricatorRepositoryIdentity $author = null,
202 PhabricatorRepositoryIdentity $committer = null) {
204 $this->authorIdentity = $author;
205 $this->committerIdentity = $committer;
207 return $this;
210 public function getAuthorIdentity() {
211 return $this->assertAttached($this->authorIdentity);
214 public function getCommitterIdentity() {
215 return $this->assertAttached($this->committerIdentity);
218 public function attachAuditAuthority(
219 PhabricatorUser $user,
220 array $authority) {
222 $user_phid = $user->getPHID();
223 if (!$user->getPHID()) {
224 throw new Exception(
225 pht('You can not attach audit authority for a user with no PHID.'));
228 $this->auditAuthorityPHIDs[$user_phid] = $authority;
230 return $this;
233 public function hasAuditAuthority(
234 PhabricatorUser $user,
235 PhabricatorRepositoryAuditRequest $audit) {
237 $user_phid = $user->getPHID();
238 if (!$user_phid) {
239 return false;
242 $map = $this->assertAttachedKey($this->auditAuthorityPHIDs, $user_phid);
244 return isset($map[$audit->getAuditorPHID()]);
247 public function writeOwnersEdges(array $package_phids) {
248 $src_phid = $this->getPHID();
249 $edge_type = DiffusionCommitHasPackageEdgeType::EDGECONST;
251 $editor = new PhabricatorEdgeEditor();
253 $dst_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
254 $src_phid,
255 $edge_type);
257 foreach ($dst_phids as $dst_phid) {
258 $editor->removeEdge($src_phid, $edge_type, $dst_phid);
261 foreach ($package_phids as $package_phid) {
262 $editor->addEdge($src_phid, $edge_type, $package_phid);
265 $editor->save();
267 return $this;
270 public function getAuditorPHIDsForEdit() {
271 $audits = $this->getAudits();
272 return mpull($audits, 'getAuditorPHID');
275 public function delete() {
276 $data = $this->loadCommitData();
277 $audits = id(new PhabricatorRepositoryAuditRequest())
278 ->loadAllWhere('commitPHID = %s', $this->getPHID());
279 $this->openTransaction();
281 if ($data) {
282 $data->delete();
284 foreach ($audits as $audit) {
285 $audit->delete();
287 $result = parent::delete();
289 $this->saveTransaction();
290 return $result;
293 public function getDateCreated() {
294 // This is primarily to make analysis of commits with the Fact engine work.
295 return $this->getEpoch();
298 public function getURI() {
299 return '/'.$this->getMonogram();
303 * Synchronize a commit's overall audit status with the individual audit
304 * triggers.
306 public function updateAuditStatus(array $requests) {
307 assert_instances_of($requests, 'PhabricatorRepositoryAuditRequest');
309 $any_concern = false;
310 $any_accept = false;
311 $any_need = false;
313 foreach ($requests as $request) {
314 switch ($request->getAuditStatus()) {
315 case PhabricatorAuditRequestStatus::AUDIT_REQUIRED:
316 case PhabricatorAuditRequestStatus::AUDIT_REQUESTED:
317 $any_need = true;
318 break;
319 case PhabricatorAuditRequestStatus::ACCEPTED:
320 $any_accept = true;
321 break;
322 case PhabricatorAuditRequestStatus::CONCERNED:
323 $any_concern = true;
324 break;
328 if ($any_concern) {
329 if ($this->isAuditStatusNeedsVerification()) {
330 // If the change is in "Needs Verification", we keep it there as
331 // long as any auditors still have concerns.
332 $status = DiffusionCommitAuditStatus::NEEDS_VERIFICATION;
333 } else {
334 $status = DiffusionCommitAuditStatus::CONCERN_RAISED;
336 } else if ($any_accept) {
337 if ($any_need) {
338 $status = DiffusionCommitAuditStatus::PARTIALLY_AUDITED;
339 } else {
340 $status = DiffusionCommitAuditStatus::AUDITED;
342 } else if ($any_need) {
343 $status = DiffusionCommitAuditStatus::NEEDS_AUDIT;
344 } else {
345 $status = DiffusionCommitAuditStatus::NONE;
348 return $this->setAuditStatus($status);
351 public function getMonogram() {
352 $repository = $this->getRepository();
353 $callsign = $repository->getCallsign();
354 $identifier = $this->getCommitIdentifier();
355 if ($callsign !== null) {
356 return "r{$callsign}{$identifier}";
357 } else {
358 $id = $repository->getID();
359 return "R{$id}:{$identifier}";
363 public function getDisplayName() {
364 $repository = $this->getRepository();
365 $identifier = $this->getCommitIdentifier();
366 return $repository->formatCommitName($identifier);
370 * Return a local display name for use in the context of the containing
371 * repository.
373 * In Git and Mercurial, this returns only a short hash, like "abcdef012345".
374 * See @{method:getDisplayName} for a short name that always includes
375 * repository context.
377 * @return string Short human-readable name for use inside a repository.
379 public function getLocalName() {
380 $repository = $this->getRepository();
381 $identifier = $this->getCommitIdentifier();
382 return $repository->formatCommitName($identifier, $local = true);
385 public function loadIdentities(PhabricatorUser $viewer) {
386 if ($this->authorIdentity !== self::ATTACHABLE) {
387 return $this;
390 $commit = id(new DiffusionCommitQuery())
391 ->setViewer($viewer)
392 ->withIDs(array($this->getID()))
393 ->needIdentities(true)
394 ->executeOne();
396 $author_identity = $commit->getAuthorIdentity();
397 $committer_identity = $commit->getCommitterIdentity();
399 return $this->attachIdentities($author_identity, $committer_identity);
402 public function hasCommitterIdentity() {
403 return ($this->getCommitterIdentity() !== null);
406 public function hasAuthorIdentity() {
407 return ($this->getAuthorIdentity() !== null);
410 public function getCommitterDisplayPHID() {
411 if ($this->hasCommitterIdentity()) {
412 return $this->getCommitterIdentity()->getIdentityDisplayPHID();
415 $data = $this->getCommitData();
416 return $data->getCommitDetail('committerPHID');
419 public function getAuthorDisplayPHID() {
420 if ($this->hasAuthorIdentity()) {
421 return $this->getAuthorIdentity()->getIdentityDisplayPHID();
424 $data = $this->getCommitData();
425 return $data->getCommitDetail('authorPHID');
428 public function getEffectiveAuthorPHID() {
429 if ($this->hasAuthorIdentity()) {
430 $identity = $this->getAuthorIdentity();
431 if ($identity->hasEffectiveUser()) {
432 return $identity->getCurrentEffectiveUserPHID();
436 $data = $this->getCommitData();
437 return $data->getCommitDetail('authorPHID');
440 public function getAuditStatusObject() {
441 $status = $this->getAuditStatus();
442 return DiffusionCommitAuditStatus::newForStatus($status);
445 public function isAuditStatusNoAudit() {
446 return $this->getAuditStatusObject()->isNoAudit();
449 public function isAuditStatusNeedsAudit() {
450 return $this->getAuditStatusObject()->isNeedsAudit();
453 public function isAuditStatusConcernRaised() {
454 return $this->getAuditStatusObject()->isConcernRaised();
457 public function isAuditStatusNeedsVerification() {
458 return $this->getAuditStatusObject()->isNeedsVerification();
461 public function isAuditStatusPartiallyAudited() {
462 return $this->getAuditStatusObject()->isPartiallyAudited();
465 public function isAuditStatusAudited() {
466 return $this->getAuditStatusObject()->isAudited();
469 public function isPermanentCommit() {
470 return (bool)$this->isPartiallyImported(self::IMPORTED_PERMANENT);
473 public function newCommitAuthorView(PhabricatorUser $viewer) {
474 $author_phid = $this->getAuthorDisplayPHID();
475 if ($author_phid) {
476 $handles = $viewer->loadHandles(array($author_phid));
477 return $handles[$author_phid]->renderLink();
480 $author = $this->getRawAuthorStringForDisplay();
481 if ($author !== null && strlen($author)) {
482 return DiffusionView::renderName($author);
485 return null;
488 public function newCommitCommitterView(PhabricatorUser $viewer) {
489 $committer_phid = $this->getCommitterDisplayPHID();
490 if ($committer_phid) {
491 $handles = $viewer->loadHandles(array($committer_phid));
492 return $handles[$committer_phid]->renderLink();
495 $committer = $this->getRawCommitterStringForDisplay();
496 if ($committer !== null && strlen($committer)) {
497 return DiffusionView::renderName($committer);
500 return null;
503 public function isAuthorSameAsCommitter() {
504 $author_phid = $this->getAuthorDisplayPHID();
505 $committer_phid = $this->getCommitterDisplayPHID();
507 if ($author_phid && $committer_phid) {
508 return ($author_phid === $committer_phid);
511 if ($author_phid || $committer_phid) {
512 return false;
515 $author = $this->getRawAuthorStringForDisplay();
516 $committer = $this->getRawCommitterStringForDisplay();
518 return ($author === $committer);
521 private function getRawAuthorStringForDisplay() {
522 $data = $this->getCommitData();
523 return $data->getAuthorString();
526 private function getRawCommitterStringForDisplay() {
527 $data = $this->getCommitData();
528 return $data->getCommitterString();
531 public function getCommitMessageForDisplay() {
532 $data = $this->getCommitData();
533 $message = $data->getCommitMessage();
534 return $message;
537 public function newCommitRef(PhabricatorUser $viewer) {
538 $repository = $this->getRepository();
540 $future = $repository->newConduitFuture(
541 $viewer,
542 'internal.commit.search',
543 array(
544 'constraints' => array(
545 'repositoryPHIDs' => array($repository->getPHID()),
546 'phids' => array($this->getPHID()),
549 $result = $future->resolve();
551 $commit_display = $this->getMonogram();
553 if (empty($result['data'])) {
554 throw new Exception(
555 pht(
556 'Unable to retrieve details for commit "%s"!',
557 $commit_display));
560 if (count($result['data']) !== 1) {
561 throw new Exception(
562 pht(
563 'Got too many results (%s) for commit "%s", expected %s.',
564 phutil_count($result['data']),
565 $commit_display,
566 1));
569 $record = head($result['data']);
570 $ref_record = idxv($record, array('fields', 'ref'));
572 if (!$ref_record) {
573 throw new Exception(
574 pht(
575 'Unable to retrieve CommitRef record for commit "%s".',
576 $commit_display));
579 return DiffusionCommitRef::newFromDictionary($ref_record);
582 /* -( PhabricatorPolicyInterface )----------------------------------------- */
584 public function getCapabilities() {
585 return array(
586 PhabricatorPolicyCapability::CAN_VIEW,
587 PhabricatorPolicyCapability::CAN_EDIT,
591 public function getPolicy($capability) {
592 switch ($capability) {
593 case PhabricatorPolicyCapability::CAN_VIEW:
594 return $this->getRepository()->getPolicy($capability);
595 case PhabricatorPolicyCapability::CAN_EDIT:
596 return PhabricatorPolicies::POLICY_USER;
600 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
601 return $this->getRepository()->hasAutomaticCapability($capability, $viewer);
604 public function describeAutomaticCapability($capability) {
605 return pht(
606 'Commits inherit the policies of the repository they belong to.');
610 /* -( PhabricatorTokenReceiverInterface )---------------------------------- */
612 public function getUsersToNotifyOfTokenGiven() {
613 return array(
614 $this->getAuthorPHID(),
618 /* -( Stuff for serialization )---------------------------------------------- */
621 * NOTE: this is not a complete serialization; only the 'protected' fields are
622 * involved. This is due to ease of (ab)using the Lisk abstraction to get this
623 * done, as well as complexity of the other fields.
625 public function toDictionary() {
626 return array(
627 'repositoryID' => $this->getRepositoryID(),
628 'phid' => $this->getPHID(),
629 'commitIdentifier' => $this->getCommitIdentifier(),
630 'epoch' => $this->getEpoch(),
631 'authorPHID' => $this->getAuthorPHID(),
632 'auditStatus' => $this->getAuditStatus(),
633 'summary' => $this->getSummary(),
634 'importStatus' => $this->getImportStatus(),
638 public static function newFromDictionary(array $dict) {
639 return id(new PhabricatorRepositoryCommit())
640 ->loadFromArray($dict);
644 /* -( HarbormasterBuildableInterface )------------------------------------- */
647 public function getHarbormasterBuildableDisplayPHID() {
648 return $this->getHarbormasterBuildablePHID();
651 public function getHarbormasterBuildablePHID() {
652 return $this->getPHID();
655 public function getHarbormasterContainerPHID() {
656 return $this->getRepository()->getPHID();
659 public function getBuildVariables() {
660 $results = array();
662 $results['buildable.commit'] = $this->getCommitIdentifier();
663 $repo = $this->getRepository();
665 $results['repository.callsign'] = $repo->getCallsign();
666 $results['repository.phid'] = $repo->getPHID();
667 $results['repository.vcs'] = $repo->getVersionControlSystem();
668 $results['repository.uri'] = $repo->getPublicCloneURI();
670 return $results;
673 public function getAvailableBuildVariables() {
674 return array(
675 'buildable.commit' => pht('The commit identifier, if applicable.'),
676 'repository.callsign' =>
677 pht('The callsign of the repository.'),
678 'repository.phid' =>
679 pht('The PHID of the repository.'),
680 'repository.vcs' =>
681 pht('The version control system, either "svn", "hg" or "git".'),
682 'repository.uri' =>
683 pht('The URI to clone or checkout the repository from.'),
687 public function newBuildableEngine() {
688 return new DiffusionBuildableEngine();
692 /* -( HarbormasterCircleCIBuildableInterface )----------------------------- */
695 public function getCircleCIGitHubRepositoryURI() {
696 $repository = $this->getRepository();
698 $commit_phid = $this->getPHID();
699 $repository_phid = $repository->getPHID();
701 if ($repository->isHosted()) {
702 throw new Exception(
703 pht(
704 'This commit ("%s") is associated with a hosted repository '.
705 '("%s"). Repositories must be imported from GitHub to be built '.
706 'with CircleCI.',
707 $commit_phid,
708 $repository_phid));
711 $remote_uri = $repository->getRemoteURI();
712 $path = HarbormasterCircleCIBuildStepImplementation::getGitHubPath(
713 $remote_uri);
714 if (!$path) {
715 throw new Exception(
716 pht(
717 'This commit ("%s") is associated with a repository ("%s") which '.
718 'has a remote URI ("%s") that does not appear to be hosted on '.
719 'GitHub. Repositories must be hosted on GitHub to be built with '.
720 'CircleCI.',
721 $commit_phid,
722 $repository_phid,
723 $remote_uri));
726 return $remote_uri;
729 public function getCircleCIBuildIdentifierType() {
730 return 'revision';
733 public function getCircleCIBuildIdentifier() {
734 return $this->getCommitIdentifier();
738 /* -( HarbormasterBuildkiteBuildableInterface )---------------------------- */
741 public function getBuildkiteBranch() {
742 $viewer = PhabricatorUser::getOmnipotentUser();
743 $repository = $this->getRepository();
745 $branches = DiffusionQuery::callConduitWithDiffusionRequest(
746 $viewer,
747 DiffusionRequest::newFromDictionary(
748 array(
749 'repository' => $repository,
750 'user' => $viewer,
752 'diffusion.branchquery',
753 array(
754 'contains' => $this->getCommitIdentifier(),
755 'repository' => $repository->getPHID(),
758 if (!$branches) {
759 throw new Exception(
760 pht(
761 'Commit "%s" is not an ancestor of any branch head, so it can not '.
762 'be built with Buildkite.',
763 $this->getCommitIdentifier()));
766 $branch = head($branches);
768 return 'refs/heads/'.$branch['shortName'];
771 public function getBuildkiteCommit() {
772 return $this->getCommitIdentifier();
776 /* -( PhabricatorCustomFieldInterface )------------------------------------ */
779 public function getCustomFieldSpecificationForRole($role) {
780 return PhabricatorEnv::getEnvConfig('diffusion.fields');
783 public function getCustomFieldBaseClass() {
784 return 'PhabricatorCommitCustomField';
787 public function getCustomFields() {
788 return $this->assertAttached($this->customFields);
791 public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
792 $this->customFields = $fields;
793 return $this;
797 /* -( PhabricatorSubscribableInterface )----------------------------------- */
800 public function isAutomaticallySubscribed($phid) {
802 // TODO: This should also list auditors, but handling that is a bit messy
803 // right now because we are not guaranteed to have the data. (It should not
804 // include resigned auditors.)
806 return ($phid == $this->getAuthorPHID());
810 /* -( PhabricatorApplicationTransactionInterface )------------------------- */
813 public function getApplicationTransactionEditor() {
814 return new PhabricatorAuditEditor();
817 public function getApplicationTransactionTemplate() {
818 return new PhabricatorAuditTransaction();
821 /* -( PhabricatorFulltextInterface )--------------------------------------- */
824 public function newFulltextEngine() {
825 return new DiffusionCommitFulltextEngine();
829 /* -( PhabricatorFerretInterface )----------------------------------------- */
832 public function newFerretEngine() {
833 return new DiffusionCommitFerretEngine();
837 /* -( PhabricatorConduitResultInterface )---------------------------------- */
839 public function getFieldSpecificationsForConduit() {
840 return array(
841 id(new PhabricatorConduitSearchFieldSpecification())
842 ->setKey('identifier')
843 ->setType('string')
844 ->setDescription(pht('The commit identifier.')),
845 id(new PhabricatorConduitSearchFieldSpecification())
846 ->setKey('repositoryPHID')
847 ->setType('phid')
848 ->setDescription(pht('The repository this commit belongs to.')),
849 id(new PhabricatorConduitSearchFieldSpecification())
850 ->setKey('author')
851 ->setType('map<string, wild>')
852 ->setDescription(pht('Information about the commit author.')),
853 id(new PhabricatorConduitSearchFieldSpecification())
854 ->setKey('committer')
855 ->setType('map<string, wild>')
856 ->setDescription(pht('Information about the committer.')),
857 id(new PhabricatorConduitSearchFieldSpecification())
858 ->setKey('isImported')
859 ->setType('bool')
860 ->setDescription(pht('True if the commit is fully imported.')),
861 id(new PhabricatorConduitSearchFieldSpecification())
862 ->setKey('isUnreachable')
863 ->setType('bool')
864 ->setDescription(
865 pht(
866 'True if the commit is not the ancestor of any tag, branch, or '.
867 'ref.')),
868 id(new PhabricatorConduitSearchFieldSpecification())
869 ->setKey('auditStatus')
870 ->setType('map<string, wild>')
871 ->setDescription(pht('Information about the current audit status.')),
872 id(new PhabricatorConduitSearchFieldSpecification())
873 ->setKey('message')
874 ->setType('string')
875 ->setDescription(pht('The commit message.')),
879 public function getFieldValuesForConduit() {
880 $data = $this->getCommitData();
882 $author_identity = $this->getAuthorIdentity();
883 if ($author_identity) {
884 $author_name = $author_identity->getIdentityDisplayName();
885 $author_email = $author_identity->getIdentityEmailAddress();
886 $author_raw = $author_identity->getIdentityName();
887 $author_identity_phid = $author_identity->getPHID();
888 $author_user_phid = $author_identity->getCurrentEffectiveUserPHID();
889 } else {
890 $author_name = null;
891 $author_email = null;
892 $author_raw = null;
893 $author_identity_phid = null;
894 $author_user_phid = null;
897 $committer_identity = $this->getCommitterIdentity();
898 if ($committer_identity) {
899 $committer_name = $committer_identity->getIdentityDisplayName();
900 $committer_email = $committer_identity->getIdentityEmailAddress();
901 $committer_raw = $committer_identity->getIdentityName();
902 $committer_identity_phid = $committer_identity->getPHID();
903 $committer_user_phid = $committer_identity->getCurrentEffectiveUserPHID();
904 } else {
905 $committer_name = null;
906 $committer_email = null;
907 $committer_raw = null;
908 $committer_identity_phid = null;
909 $committer_user_phid = null;
912 $author_epoch = $data->getAuthorEpoch();
914 $audit_status = $this->getAuditStatusObject();
916 return array(
917 'identifier' => $this->getCommitIdentifier(),
918 'repositoryPHID' => $this->getRepository()->getPHID(),
919 'author' => array(
920 'name' => $author_name,
921 'email' => $author_email,
922 'raw' => $author_raw,
923 'epoch' => $author_epoch,
924 'identityPHID' => $author_identity_phid,
925 'userPHID' => $author_user_phid,
927 'committer' => array(
928 'name' => $committer_name,
929 'email' => $committer_email,
930 'raw' => $committer_raw,
931 'epoch' => (int)$this->getEpoch(),
932 'identityPHID' => $committer_identity_phid,
933 'userPHID' => $committer_user_phid,
935 'isUnreachable' => (bool)$this->isUnreachable(),
936 'isImported' => (bool)$this->isImported(),
937 'auditStatus' => array(
938 'value' => $audit_status->getKey(),
939 'name' => $audit_status->getName(),
940 'closed' => (bool)$audit_status->getIsClosed(),
941 'color.ansi' => $audit_status->getAnsiColor(),
943 'message' => $data->getCommitMessage(),
947 public function getConduitSearchAttachments() {
948 return array(
949 id(new DiffusionAuditorsSearchEngineAttachment())
950 ->setAttachmentKey('auditors'),
955 /* -( PhabricatorDraftInterface )------------------------------------------ */
957 public function newDraftEngine() {
958 return new DiffusionCommitDraftEngine();
961 public function getHasDraft(PhabricatorUser $viewer) {
962 return $this->assertAttachedKey($this->drafts, $viewer->getCacheFragment());
965 public function attachHasDraft(PhabricatorUser $viewer, $has_draft) {
966 $this->drafts[$viewer->getCacheFragment()] = $has_draft;
967 return $this;
971 /* -( PhabricatorTimelineInterface )--------------------------------------- */
974 public function newTimelineEngine() {
975 return new DiffusionCommitTimelineEngine();