private function alterReviewers() { $revision = $this->revision; $added_reviewers = $this->getAddedReviewers(); $removed_reviewers = $this->getRemovedReviewers(); $reviewer_phids = $revision->getReviewers(); $reviewer_phids_map = array_fill_keys($reviewer_phids, true); foreach ($added_reviewers as $k => $user_phid) { if ($user_phid == $revision->getAuthorPHID()) { unset($added_reviewers[$k]); } if (isset($reviewer_phids_map[$user_phid])) { unset($added_reviewers[$k]); } } foreach ($removed_reviewers as $k => $user_phid) { if (!isset($reviewer_phids_map[$user_phid])) { unset($removed_reviewers[$k]); } } $added_reviewers = array_unique($added_reviewers); $removed_reviewers = array_unique($removed_reviewers); if ($added_reviewers) { DifferentialRevisionEditor::alterReviewers($revision, $reviewer_phids, $removed_reviewers, $added_reviewers, $this->actorPHID); } return array($added_reviewers, $removed_reviewers); }
public function save() { $revision = $this->revision; $action = $this->action; $actor_phid = $this->actorPHID; $actor_is_author = $actor_phid == $revision->getAuthorPHID(); $revision_status = $revision->getStatus(); $revision->loadRelationships(); $reviewer_phids = $revision->getReviewers(); if ($reviewer_phids) { $reviewer_phids = array_combine($reviewer_phids, $reviewer_phids); } $metadata = array(); switch ($action) { case DifferentialAction::ACTION_COMMENT: break; case DifferentialAction::ACTION_RESIGN: if ($actor_is_author) { throw new Exception('You can not resign from your own revision!'); } if (isset($reviewer_phids[$actor_phid])) { DifferentialRevisionEditor::alterReviewers($revision, $reviewer_phids, $rem = array($actor_phid), $add = array(), $actor_phid); } break; case DifferentialAction::ACTION_ABANDON: if (!$actor_is_author) { throw new Exception('You can only abandon your revisions.'); } if ($revision_status == DifferentialRevisionStatus::COMMITTED) { throw new Exception('You can not abandon a committed revision.'); } if ($revision_status == DifferentialRevisionStatus::ABANDONED) { $action = DifferentialAction::ACTION_COMMENT; break; } $revision->setStatus(DifferentialRevisionStatus::ABANDONED)->save(); break; case DifferentialAction::ACTION_ACCEPT: if ($actor_is_author) { throw new Exception('You can not accept your own revision.'); } if ($revision_status != DifferentialRevisionStatus::NEEDS_REVIEW && $revision_status != DifferentialRevisionStatus::NEEDS_REVISION) { $action = DifferentialAction::ACTION_COMMENT; break; } $revision->setStatus(DifferentialRevisionStatus::ACCEPTED)->save(); if (!isset($reviewer_phids[$actor_phid])) { DifferentialRevisionEditor::alterReviewers($revision, $reviewer_phids, $rem = array(), $add = array($actor_phid), $actor_phid); } break; case DifferentialAction::ACTION_REQUEST: if (!$actor_is_author) { throw new Exception('You must own a revision to request review.'); } if ($revision_status != DifferentialRevisionStatus::NEEDS_REVISION && $revision_status != DifferentialRevisionStatus::ACCEPTED) { $action = DifferentialAction::ACTION_COMMENT; break; } $revision->setStatus(DifferentialRevisionStatus::NEEDS_REVIEW)->save(); break; case DifferentialAction::ACTION_REJECT: if ($actor_is_author) { throw new Exception('You can not request changes to your own revision.'); } if ($revision_status != DifferentialRevisionStatus::NEEDS_REVIEW && $revision_status != DifferentialRevisionStatus::ACCEPTED) { $action = DifferentialAction::ACTION_COMMENT; break; } if (!isset($reviewer_phids[$actor_phid])) { DifferentialRevisionEditor::alterReviewers($revision, $reviewer_phids, $rem = array(), $add = array($actor_phid), $actor_phid); } $revision->setStatus(DifferentialRevisionStatus::NEEDS_REVISION)->save(); break; case DifferentialAction::ACTION_RETHINK: if (!$actor_is_author) { throw new Exception("You can not plan changes to somebody else's revision"); } if ($revision_status != DifferentialRevisionStatus::NEEDS_REVIEW && $revision_status != DifferentialRevisionStatus::ACCEPTED) { $action = DifferentialAction::ACTION_COMMENT; break; } $revision->setStatus(DifferentialRevisionStatus::NEEDS_REVISION)->save(); break; case DifferentialAction::ACTION_RECLAIM: if (!$actor_is_author) { throw new Exception('You can not reclaim a revision you do not own.'); } if ($revision_status != DifferentialRevisionStatus::ABANDONED) { $action = DifferentialAction::ACTION_COMMENT; break; } $revision->setStatus(DifferentialRevisionStatus::NEEDS_REVIEW)->save(); break; case DifferentialAction::ACTION_COMMIT: if (!$actor_is_author) { throw new Exception('You can not commit a revision you do not own.'); } $revision->setStatus(DifferentialRevisionStatus::COMMITTED)->save(); break; case DifferentialAction::ACTION_ADDREVIEWERS: $added_reviewers = $this->getAddedReviewers(); foreach ($added_reviewers as $k => $user_phid) { if ($user_phid == $revision->getAuthorPHID()) { unset($added_reviewers[$k]); } if (!empty($reviewer_phids[$user_phid])) { unset($added_reviewers[$k]); } } $added_reviewers = array_unique($added_reviewers); if ($added_reviewers) { DifferentialRevisionEditor::alterReviewers($revision, $reviewer_phids, $rem = array(), $add = $added_reviewers, $actor_phid); $key = DifferentialComment::METADATA_ADDED_REVIEWERS; $metadata[$key] = $added_reviewers; } else { $action = DifferentialAction::ACTION_COMMENT; } break; case DifferentialAction::ACTION_ADDCCS: $added_ccs = $this->getAddedCCs(); $current_ccs = $revision->getCCPHIDs(); if ($current_ccs) { $current_ccs = array_fill_keys($current_ccs, true); foreach ($added_ccs as $k => $cc) { if (isset($current_ccs[$cc])) { unset($added_ccs[$k]); } } } if ($added_ccs) { foreach ($added_ccs as $cc) { DifferentialRevisionEditor::addCC($revision, $cc, $this->actorPHID); } $key = DifferentialComment::METADATA_ADDED_CCS; $metadata[$key] = $added_ccs; } else { $action = DifferentialAction::ACTION_COMMENT; } break; default: throw new Exception('Unsupported action.'); } if ($this->addCC) { DifferentialRevisionEditor::addCC($revision, $this->actorPHID, $this->actorPHID); } $inline_comments = array(); if ($this->attachInlineComments) { $inline_comments = id(new DifferentialInlineComment())->loadAllWhere('authorPHID = %s AND revisionID = %d AND commentID IS NULL', $this->actorPHID, $revision->getID()); } $comment = id(new DifferentialComment())->setAuthorPHID($this->actorPHID)->setRevisionID($revision->getID())->setAction($action)->setContent((string) $this->message)->setMetadata($metadata)->save(); $changesets = array(); if ($inline_comments) { $load_ids = mpull($inline_comments, 'getChangesetID'); if ($load_ids) { $load_ids = array_unique($load_ids); $changesets = id(new DifferentialChangeset())->loadAllWhere('id in (%Ld)', $load_ids); } foreach ($inline_comments as $inline) { $inline->setCommentID($comment->getID()); $inline->save(); } } // Find any "@mentions" in the comment blocks. $content_blocks = array($comment->getContent()); foreach ($inline_comments as $inline) { $content_blocks[] = $inline->getContent(); } $mention_ccs = PhabricatorMarkupEngine::extractPHIDsFromMentions($content_blocks); if ($mention_ccs) { $current_ccs = $revision->getCCPHIDs(); if ($current_ccs) { $current_ccs = array_fill_keys($current_ccs, true); foreach ($mention_ccs as $key => $mention_cc) { if (isset($current_ccs[$mention_cc])) { unset($mention_ccs); } } } if ($mention_ccs) { $metadata = $comment->getMetadata(); $metacc = idx($metadata, DifferentialComment::METADATA_ADDED_CCS, array()); foreach ($mention_ccs as $cc_phid) { DifferentialRevisionEditor::addCC($revision, $cc_phid, $this->actorPHID); $metacc[] = $cc_phid; } $metadata[DifferentialComment::METADATA_ADDED_CCS] = $metacc; $comment->setMetadata($metadata); $comment->save(); } } $phids = array($this->actorPHID); $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); $actor_handle = $handles[$this->actorPHID]; $xherald_header = HeraldTranscript::loadXHeraldRulesHeader($revision->getPHID()); id(new DifferentialCommentMail($revision, $actor_handle, $comment, $changesets, $inline_comments))->setToPHIDs(array_merge($revision->getReviewers(), array($revision->getAuthorPHID())))->setCCPHIDs($revision->getCCPHIDs())->setChangedByCommit($this->getChangedByCommit())->setXHeraldRulesHeader($xherald_header)->setParentMessageID($this->parentMessageID)->send(); $event_data = array('revision_id' => $revision->getID(), 'revision_phid' => $revision->getPHID(), 'revision_name' => $revision->getTitle(), 'revision_author_phid' => $revision->getAuthorPHID(), 'action' => $comment->getAction(), 'feedback_content' => $comment->getContent(), 'actor_phid' => $this->actorPHID); id(new PhabricatorTimelineEvent('difx', $event_data))->recordEvent(); // TODO: Move to a daemon? id(new PhabricatorFeedStoryPublisher())->setStoryType(PhabricatorFeedStoryTypeConstants::STORY_DIFFERENTIAL)->setStoryData($event_data)->setStoryTime(time())->setStoryAuthorPHID($this->actorPHID)->setRelatedPHIDs(array($revision->getPHID(), $this->actorPHID, $revision->getAuthorPHID()))->publish(); // TODO: Move to a daemon? PhabricatorSearchDifferentialIndexer::indexRevision($revision); return $comment; }