diff --git a/src/applications/differential/constants/DifferentialAction.php b/src/applications/differential/constants/DifferentialAction.php index 9b37c3995b..655e720838 100644 --- a/src/applications/differential/constants/DifferentialAction.php +++ b/src/applications/differential/constants/DifferentialAction.php @@ -1,167 +1,168 @@ 'commented on', self::ACTION_ACCEPT => 'accepted', self::ACTION_REJECT => 'requested changes to', self::ACTION_RETHINK => 'planned changes to', self::ACTION_ABANDON => 'abandoned', self::ACTION_CLOSE => 'closed', self::ACTION_REQUEST => 'requested a review of', self::ACTION_RECLAIM => 'reclaimed', self::ACTION_UPDATE => 'updated', self::ACTION_RESIGN => 'resigned from', self::ACTION_SUMMARIZE => 'summarized', self::ACTION_TESTPLAN => 'explained the test plan for', self::ACTION_CREATE => 'created', self::ACTION_ADDREVIEWERS => 'added reviewers to', self::ACTION_ADDCCS => 'added CCs to', self::ACTION_CLAIM => 'commandeered', self::ACTION_REOPEN => 'reopened', + DifferentialTransaction::TYPE_INLINE => 'commented on', ); if (!empty($verbs[$action])) { return $verbs[$action]; } else { return 'brazenly "'.$action.'ed"'; } } public static function getActionVerb($action) { $verbs = array( self::ACTION_COMMENT => pht('Comment'), self::ACTION_ACCEPT => pht("Accept Revision \xE2\x9C\x94"), self::ACTION_REJECT => pht("Request Changes \xE2\x9C\x98"), self::ACTION_RETHINK => pht("Plan Changes \xE2\x9C\x98"), self::ACTION_ABANDON => pht('Abandon Revision'), self::ACTION_REQUEST => pht('Request Review'), self::ACTION_RECLAIM => pht('Reclaim Revision'), self::ACTION_RESIGN => pht('Resign as Reviewer'), self::ACTION_ADDREVIEWERS => pht('Add Reviewers'), self::ACTION_ADDCCS => pht('Add CCs'), self::ACTION_CLOSE => pht('Close Revision'), self::ACTION_CLAIM => pht('Commandeer Revision'), self::ACTION_REOPEN => pht('Reopen'), ); if (!empty($verbs[$action])) { return $verbs[$action]; } else { return 'brazenly '.$action; } } public static function allowReviewers($action) { if ($action == DifferentialAction::ACTION_ADDREVIEWERS || $action == DifferentialAction::ACTION_REQUEST || $action == DifferentialAction::ACTION_RESIGN) { return true; } return false; } } diff --git a/src/applications/differential/mail/DifferentialCommentMail.php b/src/applications/differential/mail/DifferentialCommentMail.php index 2c7c3c07f8..e4c462ba4b 100644 --- a/src/applications/differential/mail/DifferentialCommentMail.php +++ b/src/applications/differential/mail/DifferentialCommentMail.php @@ -1,221 +1,225 @@ changedByCommit = $changed_by_commit; return $this; } public function getChangedByCommit() { return $this->changedByCommit; } public function __construct( DifferentialRevision $revision, PhabricatorObjectHandle $actor, array $comments, array $changesets, array $inline_comments) { assert_instances_of($comments, 'DifferentialComment'); assert_instances_of($changesets, 'DifferentialChangeset'); assert_instances_of($inline_comments, 'PhabricatorInlineCommentInterface'); $this->setRevision($revision); $this->setActorHandle($actor); $this->setComments($comments); $this->setChangesets($changesets); $this->setInlineComments($inline_comments); } protected function getMailTags() { $tags = array(); foreach ($this->getComments() as $comment) { $action = $comment->getAction(); switch ($action) { case DifferentialAction::ACTION_ADDCCS: $tags[] = MetaMTANotificationType::TYPE_DIFFERENTIAL_CC; break; case DifferentialAction::ACTION_CLOSE: $tags[] = MetaMTANotificationType::TYPE_DIFFERENTIAL_CLOSED; break; case DifferentialAction::ACTION_ADDREVIEWERS: $tags[] = MetaMTANotificationType::TYPE_DIFFERENTIAL_REVIEWERS; break; case DifferentialAction::ACTION_COMMENT: // this is a comment which we will check separately below for content break; default: $tags[] = MetaMTANotificationType::TYPE_DIFFERENTIAL_OTHER; break; } $has_comment = strlen(trim($comment->getContent())); $has_inlines = (bool)$this->getInlineComments(); if ($has_comment || $has_inlines) { switch ($action) { case DifferentialAction::ACTION_CLOSE: // Commit comments are auto-generated and not especially // interesting, so don't tag them as having a comment. break; default: $tags[] = MetaMTANotificationType::TYPE_DIFFERENTIAL_COMMENT; break; } } } if (!$tags) { $tags[] = MetaMTANotificationType::TYPE_DIFFERENTIAL_OTHER; } return $tags; } protected function renderVaryPrefix() { $verb = ucwords($this->getVerb()); return "[{$verb}]"; } protected function getVerb() { // NOTE: Eventually, this will use getStrongestAction() transaction logic. // For now, pick the first comment. $comment = head($this->getComments()); $action = $comment->getAction(); $verb = DifferentialAction::getActionPastTenseVerb($action); return $verb; } protected function prepareBody() { parent::prepareBody(); // If the commented added reviewers or CCs, list them explicitly. $load = array(); foreach ($this->comments as $comment) { $meta = $comment->getMetadata(); $m_reviewers = idx( $meta, DifferentialComment::METADATA_ADDED_REVIEWERS, array()); $m_cc = idx( $meta, DifferentialComment::METADATA_ADDED_CCS, array()); $load[] = $m_reviewers; $load[] = $m_cc; } $load = array_mergev($load); if ($load) { $handles = id(new PhabricatorHandleQuery()) ->setViewer($this->getActor()) ->withPHIDs($load) ->execute(); if ($m_reviewers) { $this->addedReviewers = $this->renderHandleList($handles, $m_reviewers); } if ($m_cc) { $this->addedCCs = $this->renderHandleList($handles, $m_cc); } } } protected function renderBody() { // TODO: This will be ApplicationTransactions eventually, but split the // difference for now. $comment = head($this->getComments()); $actor = $this->getActorName(); $name = $this->getRevision()->getTitle(); $verb = $this->getVerb(); $body = array(); $body[] = "{$actor} has {$verb} the revision \"{$name}\"."; if ($this->addedReviewers) { $body[] = 'Added Reviewers: '.$this->addedReviewers; } if ($this->addedCCs) { $body[] = 'Added CCs: '.$this->addedCCs; } $body[] = null; foreach ($this->getComments() as $comment) { + if ($comment->getAction() == DifferentialTransaction::TYPE_INLINE) { + // These have comment content now, but are rendered below. + continue; + } $content = $comment->getContent(); if (strlen($content)) { $body[] = $this->formatText($content); $body[] = null; } } if ($this->getChangedByCommit()) { $body[] = 'CHANGED PRIOR TO COMMIT'; $body[] = ' '.$this->getChangedByCommit(); $body[] = null; } $inlines = $this->getInlineComments(); if ($inlines) { $body[] = 'INLINE COMMENTS'; $changesets = $this->getChangesets(); $hunk_parser = new DifferentialHunkParser(); if (PhabricatorEnv::getEnvConfig( 'metamta.differential.unified-comment-context')) { foreach ($changesets as $changeset) { $changeset->attachHunks($changeset->loadHunks()); } } foreach ($inlines as $inline) { $changeset = $changesets[$inline->getChangesetID()]; if (!$changeset) { throw new Exception('Changeset missing!'); } $file = $changeset->getFilename(); $start = $inline->getLineNumber(); $len = $inline->getLineLength(); if ($len) { $range = $start.'-'.($start + $len); } else { $range = $start; } $inline_content = $inline->getContent(); if (!PhabricatorEnv::getEnvConfig( 'metamta.differential.unified-comment-context')) { $body[] = $this->formatText("{$file}:{$range} {$inline_content}"); } else { $body[] = "================"; $body[] = "Comment at: " . $file . ":" . $range; $body[] = $hunk_parser->makeContextDiff( $changeset->getHunks(), $inline, 1); $body[] = "----------------"; $body[] = $inline_content; $body[] = null; } } $body[] = null; } $body[] = $this->renderAuxFields(DifferentialMailPhase::COMMENT); return implode("\n", $body); } }