1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-07 20:38:32 +01:00
phorge-phorge/src/applications/differential/editor/DifferentialCommentEditor.php

772 lines
25 KiB
PHP
Raw Normal View History

<?php
final class DifferentialCommentEditor extends PhabricatorEditor {
protected $revision;
protected $action;
protected $attachInlineComments;
protected $message;
protected $changedByCommit;
protected $addedReviewers = array();
protected $removedReviewers = array();
private $addedCCs = array();
private $parentMessageID;
private $contentSource;
private $noEmail;
private $isDaemonWorkflow;
public function __construct(
DifferentialRevision $revision,
$action) {
$this->revision = $revision;
$this->action = $action;
}
public function setParentMessageID($parent_message_id) {
$this->parentMessageID = $parent_message_id;
return $this;
}
public function setMessage($message) {
$this->message = $message;
return $this;
}
public function setAttachInlineComments($attach) {
$this->attachInlineComments = $attach;
return $this;
}
public function setChangedByCommit($changed_by_commit) {
$this->changedByCommit = $changed_by_commit;
return $this;
}
public function getChangedByCommit() {
return $this->changedByCommit;
}
public function setAddedReviewers(array $added_reviewers) {
$this->addedReviewers = $added_reviewers;
return $this;
}
public function getAddedReviewers() {
return $this->addedReviewers;
}
public function setRemovedReviewers(array $removeded_reviewers) {
$this->removedReviewers = $removeded_reviewers;
return $this;
}
public function getRemovedReviewers() {
return $this->removedReviewers;
}
public function setAddedCCs($added_ccs) {
$this->addedCCs = $added_ccs;
return $this;
}
public function getAddedCCs() {
return $this->addedCCs;
}
public function setContentSource(PhabricatorContentSource $content_source) {
$this->contentSource = $content_source;
return $this;
}
public function setIsDaemonWorkflow($is_daemon) {
$this->isDaemonWorkflow = $is_daemon;
return $this;
}
public function setNoEmail($no_email) {
$this->noEmail = $no_email;
return $this;
}
public function save() {
$actor = $this->requireActor();
// Reload the revision to pick up reviewer status, until we can lift this
// out of here.
$this->revision = id(new DifferentialRevisionQuery())
->setViewer($actor)
->withIDs(array($this->revision->getID()))
->needRelationships(true)
->needReviewerStatus(true)
->needReviewerAuthority(true)
->executeOne();
$revision = $this->revision;
$action = $this->action;
$actor_phid = $actor->getPHID();
$actor_is_author = ($actor_phid == $revision->getAuthorPHID());
$allow_self_accept = PhabricatorEnv::getEnvConfig(
'differential.allow-self-accept');
$always_allow_close = PhabricatorEnv::getEnvConfig(
'differential.always-allow-close');
$allow_reopen = PhabricatorEnv::getEnvConfig(
'differential.allow-reopen');
$revision_status = $revision->getStatus();
Make "reject" and "blocking reviewer" block acceptance in Differential Summary: Ref T1279. This is a logical change. - "Reject" (nee "Request Changes") is now sticky. The review won't transition to "Accepted" until the reviewer clears their objection. In practice, I think it always worked like this anyway (without technical enforcement, users just followed this rule naturally, since disobeying this rule is kind of a dick move) so I don't expect this to change much. I think this rule is easier to understand than the old rule now, given the multi-reviewer status and blocking reviewers. - "Blocking Reviewer" and "Reject" now prevent a revision from transitioning to "Accepted". When reviewers accept, resign, or are removed, we do a check to see if the reivsion has: at least one user reviewer who has accepted; zero rejects; and zero blocks. If all conditions are satisfied, we transition it to "accepted". Practically, the primary net effect of this is just to make blocking reviews actually block. This is pretty messy, but there's not much we can do about it until after T2222, since we have two completely separate editor pathways which are both responsible for adjusting status. Eventually, these can merge into a single sane editor which implements reasonable rules in reaonable ways. But that day is not today. Test Plan: With three users and a project, made a bunch of accepts, rejects, resigns and reviewer removals. I think I probably covered most of the pathways? There are a lot of interactions here. Reviewers: btrahan Reviewed By: btrahan CC: aran, wisutsak.jaisue.7 Maniphest Tasks: T1279 Differential Revision: https://secure.phabricator.com/D7245
2013-10-06 17:09:56 -07:00
$update_accepted_status = false;
$reviewer_phids = $revision->getReviewers();
if ($reviewer_phids) {
$reviewer_phids = array_fuse($reviewer_phids);
}
$metadata = array();
$inline_comments = array();
if ($this->attachInlineComments) {
$inline_comments = id(new DifferentialInlineCommentQuery())
->withDraftComments($actor_phid, $revision->getID())
->execute();
}
switch ($action) {
case DifferentialAction::ACTION_COMMENT:
if (!$this->message && !$inline_comments) {
throw new DifferentialActionHasNoEffectException(
"You are submitting an empty comment with no action: ".
"you must act on the revision or post a comment.");
}
// If the actor is a reviewer, and their status is "added" (that is,
// they haven't accepted or requested changes to the revision),
// upgrade their status to "commented". If they have a stronger status
// already, don't overwrite it.
if (isset($reviewer_phids[$actor_phid])) {
$status_added = DifferentialReviewerStatus::STATUS_ADDED;
$reviewer_status = $revision->getReviewerStatus();
foreach ($reviewer_status as $reviewer) {
if ($reviewer->getReviewerPHID() == $actor_phid) {
if ($reviewer->getStatus() == $status_added) {
DifferentialRevisionEditor::updateReviewerStatus(
$revision,
$actor,
$actor_phid,
DifferentialReviewerStatus::STATUS_COMMENTED);
}
}
}
}
break;
case DifferentialAction::ACTION_RESIGN:
if ($actor_is_author) {
throw new Exception('You can not resign from your own revision!');
}
if (empty($reviewer_phids[$actor_phid])) {
throw new DifferentialActionHasNoEffectException(
"You can not resign from this revision because you are not ".
"a reviewer.");
}
list($added_reviewers, $ignored) = $this->alterReviewers();
if ($added_reviewers) {
$key = DifferentialComment::METADATA_ADDED_REVIEWERS;
$metadata[$key] = $added_reviewers;
}
DifferentialRevisionEditor::updateReviewers(
$revision,
$actor,
array(),
array($actor_phid));
Make "reject" and "blocking reviewer" block acceptance in Differential Summary: Ref T1279. This is a logical change. - "Reject" (nee "Request Changes") is now sticky. The review won't transition to "Accepted" until the reviewer clears their objection. In practice, I think it always worked like this anyway (without technical enforcement, users just followed this rule naturally, since disobeying this rule is kind of a dick move) so I don't expect this to change much. I think this rule is easier to understand than the old rule now, given the multi-reviewer status and blocking reviewers. - "Blocking Reviewer" and "Reject" now prevent a revision from transitioning to "Accepted". When reviewers accept, resign, or are removed, we do a check to see if the reivsion has: at least one user reviewer who has accepted; zero rejects; and zero blocks. If all conditions are satisfied, we transition it to "accepted". Practically, the primary net effect of this is just to make blocking reviews actually block. This is pretty messy, but there's not much we can do about it until after T2222, since we have two completely separate editor pathways which are both responsible for adjusting status. Eventually, these can merge into a single sane editor which implements reasonable rules in reaonable ways. But that day is not today. Test Plan: With three users and a project, made a bunch of accepts, rejects, resigns and reviewer removals. I think I probably covered most of the pathways? There are a lot of interactions here. Reviewers: btrahan Reviewed By: btrahan CC: aran, wisutsak.jaisue.7 Maniphest Tasks: T1279 Differential Revision: https://secure.phabricator.com/D7245
2013-10-06 17:09:56 -07:00
// If you are a blocking reviewer, your presence as a reviewer may be
// the only thing keeping a revision from transitioning to "accepted".
// Recalculate state after removing the resigning reviewer.
switch ($revision_status) {
case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
$update_accepted_status = true;
break;
}
break;
case DifferentialAction::ACTION_ABANDON:
if (!$actor_is_author) {
throw new Exception('You can only abandon your own revisions.');
}
if ($revision_status == ArcanistDifferentialRevisionStatus::CLOSED) {
throw new DifferentialActionHasNoEffectException(
"You can not abandon this revision because it has already ".
"been closed.");
}
if ($revision_status == ArcanistDifferentialRevisionStatus::ABANDONED) {
throw new DifferentialActionHasNoEffectException(
"You can not abandon this revision because it has already ".
"been abandoned.");
}
$revision->setStatus(ArcanistDifferentialRevisionStatus::ABANDONED);
break;
case DifferentialAction::ACTION_ACCEPT:
if ($actor_is_author && !$allow_self_accept) {
throw new Exception('You can not accept your own revision.');
}
switch ($revision_status) {
case ArcanistDifferentialRevisionStatus::ABANDONED:
throw new DifferentialActionHasNoEffectException(
"You can not accept this revision because it has been ".
"abandoned.");
case ArcanistDifferentialRevisionStatus::CLOSED:
throw new DifferentialActionHasNoEffectException(
"You can not accept this revision because it has already ".
"been closed.");
case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
case ArcanistDifferentialRevisionStatus::ACCEPTED:
// We expect "Accept" from these states.
break;
default:
throw new Exception(
"Unexpected revision state '{$revision_status}'!");
}
$was_reviewer_already = false;
foreach ($revision->getReviewerStatus() as $reviewer) {
if ($reviewer->hasAuthority($actor)) {
DifferentialRevisionEditor::updateReviewerStatus(
$revision,
$actor,
$reviewer->getReviewerPHID(),
DifferentialReviewerStatus::STATUS_ACCEPTED);
if ($reviewer->getReviewerPHID() == $actor_phid) {
$was_reviewer_already = true;
}
}
}
if (!$was_reviewer_already) {
DifferentialRevisionEditor::updateReviewerStatus(
$revision,
$actor,
$actor_phid,
DifferentialReviewerStatus::STATUS_ACCEPTED);
}
Make "reject" and "blocking reviewer" block acceptance in Differential Summary: Ref T1279. This is a logical change. - "Reject" (nee "Request Changes") is now sticky. The review won't transition to "Accepted" until the reviewer clears their objection. In practice, I think it always worked like this anyway (without technical enforcement, users just followed this rule naturally, since disobeying this rule is kind of a dick move) so I don't expect this to change much. I think this rule is easier to understand than the old rule now, given the multi-reviewer status and blocking reviewers. - "Blocking Reviewer" and "Reject" now prevent a revision from transitioning to "Accepted". When reviewers accept, resign, or are removed, we do a check to see if the reivsion has: at least one user reviewer who has accepted; zero rejects; and zero blocks. If all conditions are satisfied, we transition it to "accepted". Practically, the primary net effect of this is just to make blocking reviews actually block. This is pretty messy, but there's not much we can do about it until after T2222, since we have two completely separate editor pathways which are both responsible for adjusting status. Eventually, these can merge into a single sane editor which implements reasonable rules in reaonable ways. But that day is not today. Test Plan: With three users and a project, made a bunch of accepts, rejects, resigns and reviewer removals. I think I probably covered most of the pathways? There are a lot of interactions here. Reviewers: btrahan Reviewed By: btrahan CC: aran, wisutsak.jaisue.7 Maniphest Tasks: T1279 Differential Revision: https://secure.phabricator.com/D7245
2013-10-06 17:09:56 -07:00
$update_accepted_status = true;
break;
case DifferentialAction::ACTION_REQUEST:
if (!$actor_is_author) {
throw new Exception('You must own a revision to request review.');
}
switch ($revision_status) {
case ArcanistDifferentialRevisionStatus::ACCEPTED:
case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
$revision->setStatus(
ArcanistDifferentialRevisionStatus::NEEDS_REVIEW);
break;
case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
throw new DifferentialActionHasNoEffectException(
"You can not request review of this revision because it has ".
"been abandoned.");
case ArcanistDifferentialRevisionStatus::ABANDONED:
throw new DifferentialActionHasNoEffectException(
"You can not request review of this revision because it has ".
"been abandoned.");
case ArcanistDifferentialRevisionStatus::CLOSED:
throw new DifferentialActionHasNoEffectException(
"You can not request review of this revision because it has ".
"already been closed.");
default:
throw new Exception(
"Unexpected revision state '{$revision_status}'!");
}
list($added_reviewers, $ignored) = $this->alterReviewers();
if ($added_reviewers) {
$key = DifferentialComment::METADATA_ADDED_REVIEWERS;
$metadata[$key] = $added_reviewers;
}
break;
case DifferentialAction::ACTION_REJECT:
if ($actor_is_author) {
throw new Exception(
'You can not request changes to your own revision.');
}
switch ($revision_status) {
case ArcanistDifferentialRevisionStatus::ACCEPTED:
case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
// We expect rejects from these states.
break;
case ArcanistDifferentialRevisionStatus::ABANDONED:
throw new DifferentialActionHasNoEffectException(
"You can not request changes to this revision because it has ".
"been abandoned.");
case ArcanistDifferentialRevisionStatus::CLOSED:
throw new DifferentialActionHasNoEffectException(
"You can not request changes to this revision because it has ".
"already been closed.");
default:
throw new Exception(
"Unexpected revision state '{$revision_status}'!");
}
DifferentialRevisionEditor::updateReviewerStatus(
$revision,
$actor,
$actor_phid,
DifferentialReviewerStatus::STATUS_REJECTED);
$revision
->setStatus(ArcanistDifferentialRevisionStatus::NEEDS_REVISION);
break;
case DifferentialAction::ACTION_RETHINK:
if (!$actor_is_author) {
throw new Exception(
"You can not plan changes to somebody else's revision");
}
switch ($revision_status) {
case ArcanistDifferentialRevisionStatus::ACCEPTED:
case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
// We expect accepts from these states.
break;
case ArcanistDifferentialRevisionStatus::ABANDONED:
throw new DifferentialActionHasNoEffectException(
"You can not plan changes to this revision because it has ".
"been abandoned.");
case ArcanistDifferentialRevisionStatus::CLOSED:
throw new DifferentialActionHasNoEffectException(
"You can not plan changes to this revision because it has ".
"already been closed.");
default:
throw new Exception(
"Unexpected revision state '{$revision_status}'!");
}
$revision
->setStatus(ArcanistDifferentialRevisionStatus::NEEDS_REVISION);
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 != ArcanistDifferentialRevisionStatus::ABANDONED) {
throw new DifferentialActionHasNoEffectException(
"You can not reclaim this revision because it is not abandoned.");
}
$revision
->setStatus(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW);
Make "reject" and "blocking reviewer" block acceptance in Differential Summary: Ref T1279. This is a logical change. - "Reject" (nee "Request Changes") is now sticky. The review won't transition to "Accepted" until the reviewer clears their objection. In practice, I think it always worked like this anyway (without technical enforcement, users just followed this rule naturally, since disobeying this rule is kind of a dick move) so I don't expect this to change much. I think this rule is easier to understand than the old rule now, given the multi-reviewer status and blocking reviewers. - "Blocking Reviewer" and "Reject" now prevent a revision from transitioning to "Accepted". When reviewers accept, resign, or are removed, we do a check to see if the reivsion has: at least one user reviewer who has accepted; zero rejects; and zero blocks. If all conditions are satisfied, we transition it to "accepted". Practically, the primary net effect of this is just to make blocking reviews actually block. This is pretty messy, but there's not much we can do about it until after T2222, since we have two completely separate editor pathways which are both responsible for adjusting status. Eventually, these can merge into a single sane editor which implements reasonable rules in reaonable ways. But that day is not today. Test Plan: With three users and a project, made a bunch of accepts, rejects, resigns and reviewer removals. I think I probably covered most of the pathways? There are a lot of interactions here. Reviewers: btrahan Reviewed By: btrahan CC: aran, wisutsak.jaisue.7 Maniphest Tasks: T1279 Differential Revision: https://secure.phabricator.com/D7245
2013-10-06 17:09:56 -07:00
$update_accepted_status = true;
break;
case DifferentialAction::ACTION_CLOSE:
// NOTE: The daemons can mark things closed from any state. We treat
// them as completely authoritative.
if (!$this->isDaemonWorkflow) {
if (!$actor_is_author && !$always_allow_close) {
throw new Exception(
"You can not mark a revision you don't own as closed.");
}
$status_closed = ArcanistDifferentialRevisionStatus::CLOSED;
$status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED;
if ($revision_status == $status_closed) {
throw new DifferentialActionHasNoEffectException(
"You can not mark this revision as closed because it has ".
"already been marked as closed.");
}
if ($revision_status != $status_accepted) {
throw new DifferentialActionHasNoEffectException(
"You can not mark this revision as closed because it is ".
"has not been accepted.");
}
}
if (!$revision->getDateCommitted()) {
$revision->setDateCommitted(time());
}
$revision->setStatus(ArcanistDifferentialRevisionStatus::CLOSED);
break;
case DifferentialAction::ACTION_REOPEN:
if (!$allow_reopen) {
throw new Exception(
"You cannot reopen a revision when this action is disabled.");
}
if ($revision_status != ArcanistDifferentialRevisionStatus::CLOSED) {
throw new Exception(
"You cannot reopen a revision that is not currently closed.");
}
$revision->setStatus(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW);
break;
case DifferentialAction::ACTION_ADDREVIEWERS:
list($added_reviewers, $ignored) = $this->alterReviewers();
if ($added_reviewers) {
$key = DifferentialComment::METADATA_ADDED_REVIEWERS;
$metadata[$key] = $added_reviewers;
} else {
$user_tried_to_add = count($this->getAddedReviewers());
if ($user_tried_to_add == 0) {
throw new DifferentialActionHasNoEffectException(
"You can not add reviewers, because you did not specify any ".
"reviewers.");
} else if ($user_tried_to_add == 1) {
throw new DifferentialActionHasNoEffectException(
"You can not add that reviewer, because they are already an ".
"author or reviewer.");
} else {
throw new DifferentialActionHasNoEffectException(
"You can not add those reviewers, because they are all already ".
"authors or reviewers.");
}
}
break;
case DifferentialAction::ACTION_ADDCCS:
$added_ccs = $this->getAddedCCs();
$user_tried_to_add = count($added_ccs);
$added_ccs = $this->filterAddedCCs($added_ccs);
if ($added_ccs) {
foreach ($added_ccs as $cc) {
DifferentialRevisionEditor::addCC(
$revision,
$cc,
$actor_phid);
}
$key = DifferentialComment::METADATA_ADDED_CCS;
$metadata[$key] = $added_ccs;
} else {
if ($user_tried_to_add == 0) {
throw new DifferentialActionHasNoEffectException(
"You can not add CCs, because you did not specify any ".
"CCs.");
} else if ($user_tried_to_add == 1) {
throw new DifferentialActionHasNoEffectException(
"You can not add that CC, because they are already an ".
"author, reviewer or CC.");
} else {
throw new DifferentialActionHasNoEffectException(
"You can not add those CCs, because they are all already ".
"authors, reviewers or CCs.");
}
}
break;
case DifferentialAction::ACTION_CLAIM:
if ($actor_is_author) {
throw new Exception("You can not commandeer your own revision.");
}
switch ($revision_status) {
case ArcanistDifferentialRevisionStatus::CLOSED:
throw new DifferentialActionHasNoEffectException(
"You can not commandeer this revision because it has ".
"already been closed.");
break;
}
$this->setAddedReviewers(array($revision->getAuthorPHID()));
$this->setRemovedReviewers(array($actor_phid));
// NOTE: Set the new author PHID before calling addReviewers(), since it
// doesn't permit the author to become a reviewer.
$revision->setAuthorPHID($actor_phid);
list($added_reviewers, $removed_reviewers) = $this->alterReviewers();
if ($added_reviewers) {
$key = DifferentialComment::METADATA_ADDED_REVIEWERS;
$metadata[$key] = $added_reviewers;
}
if ($removed_reviewers) {
$key = DifferentialComment::METADATA_REMOVED_REVIEWERS;
$metadata[$key] = $removed_reviewers;
}
break;
default:
throw new Exception('Unsupported action.');
}
// Update information about reviewer in charge.
if ($action == DifferentialAction::ACTION_ACCEPT ||
$action == DifferentialAction::ACTION_REJECT) {
$revision->setLastReviewerPHID($actor_phid);
}
// TODO: Call beginReadLocking() prior to loading the revision.
$revision->openTransaction();
// Always save the revision (even if we didn't actually change any of its
// properties) so that it jumps to the top of the revision list when sorted
// by "updated". Notably, this allows "ping" comments to push it to the
// top of the action list.
$revision->save();
Make "reject" and "blocking reviewer" block acceptance in Differential Summary: Ref T1279. This is a logical change. - "Reject" (nee "Request Changes") is now sticky. The review won't transition to "Accepted" until the reviewer clears their objection. In practice, I think it always worked like this anyway (without technical enforcement, users just followed this rule naturally, since disobeying this rule is kind of a dick move) so I don't expect this to change much. I think this rule is easier to understand than the old rule now, given the multi-reviewer status and blocking reviewers. - "Blocking Reviewer" and "Reject" now prevent a revision from transitioning to "Accepted". When reviewers accept, resign, or are removed, we do a check to see if the reivsion has: at least one user reviewer who has accepted; zero rejects; and zero blocks. If all conditions are satisfied, we transition it to "accepted". Practically, the primary net effect of this is just to make blocking reviews actually block. This is pretty messy, but there's not much we can do about it until after T2222, since we have two completely separate editor pathways which are both responsible for adjusting status. Eventually, these can merge into a single sane editor which implements reasonable rules in reaonable ways. But that day is not today. Test Plan: With three users and a project, made a bunch of accepts, rejects, resigns and reviewer removals. I think I probably covered most of the pathways? There are a lot of interactions here. Reviewers: btrahan Reviewed By: btrahan CC: aran, wisutsak.jaisue.7 Maniphest Tasks: T1279 Differential Revision: https://secure.phabricator.com/D7245
2013-10-06 17:09:56 -07:00
if ($update_accepted_status) {
$revision = DifferentialRevisionEditor::updateAcceptedStatus(
$actor,
$revision);
}
if ($action != DifferentialAction::ACTION_RESIGN) {
DifferentialRevisionEditor::addCC(
$revision,
$actor_phid,
$actor_phid);
}
$is_new = !$revision->getID();
$event = new PhabricatorEvent(
PhabricatorEventType::TYPE_DIFFERENTIAL_WILLEDITREVISION,
array(
'revision' => $revision,
'new' => $is_new,
));
$event->setUser($actor);
PhutilEventEngine::dispatchEvent($event);
$comment = id(new DifferentialComment())
->setAuthorPHID($actor_phid)
->setRevision($revision)
->setAction($action)
->setContent((string)$this->message)
->setMetadata($metadata);
if ($this->contentSource) {
$comment->setContentSource($this->contentSource);
}
$comment->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) {
2011-02-02 19:38:43 -08:00
$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) {
$mention_ccs = $this->filterAddedCCs($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,
$actor_phid);
$metacc[] = $cc_phid;
}
$metadata[DifferentialComment::METADATA_ADDED_CCS] = $metacc;
$comment->setMetadata($metadata);
$comment->save();
$event = new PhabricatorEvent(
PhabricatorEventType::TYPE_DIFFERENTIAL_DIDEDITREVISION,
array(
'revision' => $revision,
'new' => $is_new,
));
$event->setUser($actor);
PhutilEventEngine::dispatchEvent($event);
}
}
$revision->saveTransaction();
$phids = array($actor_phid);
$handles = id(new PhabricatorHandleQuery())
->setViewer($actor)
->withPHIDs($phids)
->execute();
$actor_handle = $handles[$actor_phid];
$xherald_header = HeraldTranscript::loadXHeraldRulesHeader(
$revision->getPHID());
$mailed_phids = array();
if (!$this->noEmail) {
$mail = id(new DifferentialCommentMail(
$revision,
$actor_handle,
$comment,
$changesets,
$inline_comments))
->setActor($actor)
->setExcludeMailRecipientPHIDs($this->getExcludeMailRecipientPHIDs())
->setToPHIDs(
array_merge(
$revision->getReviewers(),
array($revision->getAuthorPHID())))
->setCCPHIDs($revision->getCCPHIDs())
->setChangedByCommit($this->getChangedByCommit())
->setXHeraldRulesHeader($xherald_header)
->setParentMessageID($this->parentMessageID)
->send();
$mailed_phids = $mail->getRawMail()->buildRecipientList();
}
$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' => $actor_phid,
// NOTE: Don't use this, it will be removed after ApplicationTransactions.
// For now, it powers inline comment rendering over the Asana brdige.
'temporaryCommentID' => $comment->getID(),
);
id(new PhabricatorFeedStoryPublisher())
->setStoryType('PhabricatorFeedStoryDifferential')
->setStoryData($event_data)
->setStoryTime(time())
->setStoryAuthorPHID($actor_phid)
->setRelatedPHIDs(
array(
$revision->getPHID(),
$actor_phid,
$revision->getAuthorPHID(),
))
->setPrimaryObjectPHID($revision->getPHID())
->setSubscribedPHIDs(
array_merge(
array($revision->getAuthorPHID()),
$revision->getReviewers(),
$revision->getCCPHIDs()))
->setMailRecipientPHIDs($mailed_phids)
->publish();
Improve Search architecture Summary: The search indexing API has several problems right now: - Always runs in-process. - It would be nice to push this into the task queue for performance. However, the API currently passses an object all the way through (and some indexers depend on preloaded object attributes), so it can't be dumped into the task queue at any stage since we can't serialize it. - Being able to use the task queue will also make rebuilding indexes faster. - Instead, make the API phid-oriented. - No uniform indexing API. - Each "Editor" currently calls SomeCustomIndexer::indexThing(). This won't work with AbstractTransactions. The API is also just weird. - Instead, provide a uniform API. - No uniform CLI. - We have `scripts/search/reindex_everything.php`, but it doesn't actually index everything. Each new document type needs to be separately added to it, leading to stuff like D3839. Third-party applications can't provide indexers. - Instead, let indexers expose documents for indexing. - Not application-oriented. - All the indexers live in search/ right now, which isn't the right organization in an application-orietned view of the world. - Instead, move indexers to applications and load them with SymbolLoader. Test Plan: - `bin/search index` - Indexed one revision, one task. - Indexed `--type TASK`, `--type DREV`, etc., for all types. - Indexed `--all`. - Added the word "saboteur" to a revision, task, wiki page, and question and then searched for it. - Creating users is a pain; searched for a user after indexing. - Creating commits is a pain; searched for a commit after indexing. - Mocks aren't currently loadable in the result view, so their indexing is moot. Reviewers: btrahan, vrana Reviewed By: btrahan CC: 20after4, aran Maniphest Tasks: T1991, T2104 Differential Revision: https://secure.phabricator.com/D4261
2012-12-21 14:21:31 -08:00
id(new PhabricatorSearchIndexer())
->indexDocumentByPHID($revision->getPHID());
return $comment;
}
private function filterAddedCCs(array $ccs) {
$revision = $this->revision;
$current_ccs = $revision->getCCPHIDs();
$current_ccs = array_fill_keys($current_ccs, true);
$reviewer_phids = $revision->getReviewers();
$reviewer_phids = array_fill_keys($reviewer_phids, true);
foreach ($ccs as $key => $cc) {
if (isset($current_ccs[$cc])) {
unset($ccs[$key]);
}
if (isset($reviewer_phids[$cc])) {
unset($ccs[$key]);
}
if ($cc == $revision->getAuthorPHID()) {
unset($ccs[$key]);
}
}
return $ccs;
}
private function alterReviewers() {
$actor_phid = $this->getActor()->getPHID();
$revision = $this->revision;
$added_reviewers = $this->getAddedReviewers();
$removed_reviewers = $this->getRemovedReviewers();
$reviewer_phids = $revision->getReviewers();
$allow_self_accept = PhabricatorEnv::getEnvConfig(
'differential.allow-self-accept');
$reviewer_phids_map = array_fill_keys($reviewer_phids, true);
foreach ($added_reviewers as $k => $user_phid) {
if (!$allow_self_accept && $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::updateReviewers(
$revision,
$this->getActor(),
$added_reviewers,
$removed_reviewers);
}
return array($added_reviewers, $removed_reviewers);
}
}