diff --git a/src/applications/audit/storage/PhabricatorAuditInlineComment.php b/src/applications/audit/storage/PhabricatorAuditInlineComment.php --- a/src/applications/audit/storage/PhabricatorAuditInlineComment.php +++ b/src/applications/audit/storage/PhabricatorAuditInlineComment.php @@ -47,6 +47,16 @@ return head(self::buildProxies($inlines)); } + public static function loadPHID($phid) { + $inlines = id(new PhabricatorAuditTransactionComment())->loadAllWhere( + 'phid = %s', + $phid); + if (!$inlines) { + return null; + } + return head(self::buildProxies($inlines)); + } + public static function loadDraftComments( PhabricatorUser $viewer, $commit_phid) { @@ -256,6 +266,24 @@ return $this->getPathID(); } + public function setReplyToCommentPHID($phid) { + $this->proxy->setReplyToCommentPHID($phid); + return $this; + } + + public function getReplyToCommentPHID() { + return $this->proxy->getReplyToCommentPHID(); + } + + public function setHasReplies($has_replies) { + $this->proxy->setHasReplies($has_replies); + return $this; + } + + public function getHasReplies() { + return $this->proxy->getHasReplies(); + } + /* -( PhabricatorMarkupInterface Implementation )-------------------------- */ diff --git a/src/applications/differential/controller/DifferentialInlineCommentEditController.php b/src/applications/differential/controller/DifferentialInlineCommentEditController.php --- a/src/applications/differential/controller/DifferentialInlineCommentEditController.php +++ b/src/applications/differential/controller/DifferentialInlineCommentEditController.php @@ -40,6 +40,12 @@ ->executeOne(); } + protected function loadCommentByPHID($phid) { + return id(new DifferentialInlineCommentQuery()) + ->withPHIDs(array($phid)) + ->executeOne(); + } + protected function loadCommentForEdit($id) { $request = $this->getRequest(); $user = $request->getUser(); diff --git a/src/applications/differential/query/DifferentialInlineCommentQuery.php b/src/applications/differential/query/DifferentialInlineCommentQuery.php --- a/src/applications/differential/query/DifferentialInlineCommentQuery.php +++ b/src/applications/differential/query/DifferentialInlineCommentQuery.php @@ -9,6 +9,7 @@ private $revisionIDs; private $notDraft; private $ids; + private $phids; private $commentIDs; private $viewerAndChangesetIDs; @@ -30,6 +31,11 @@ return $this; } + public function withPHIDs(array $phids) { + $this->phids = $phids; + return $this; + } + public function withViewerAndChangesetIDs($author_phid, array $ids) { $this->viewerAndChangesetIDs = array($author_phid, $ids); return $this; @@ -111,6 +117,13 @@ $this->ids); } + if ($this->phids !== null) { + $where[] = qsprintf( + $conn_r, + 'phid IN (%Ls)', + $this->phids); + } + if ($this->viewerAndChangesetIDs) { list($phid, $ids) = $this->viewerAndChangesetIDs; $where[] = qsprintf( diff --git a/src/applications/differential/storage/DifferentialInlineComment.php b/src/applications/differential/storage/DifferentialInlineComment.php --- a/src/applications/differential/storage/DifferentialInlineComment.php +++ b/src/applications/differential/storage/DifferentialInlineComment.php @@ -189,6 +189,25 @@ return $this; } + public function setReplyToCommentPHID($phid) { + $this->proxy->setReplyToCommentPHID($phid); + return $this; + } + + public function getReplyToCommentPHID() { + return $this->proxy->getReplyToCommentPHID(); + } + + public function setHasReplies($has_replies) { + $this->proxy->setHasReplies($has_replies); + return $this; + } + + public function getHasReplies() { + return $this->proxy->getHasReplies(); + } + + /* -( PhabricatorMarkupInterface Implementation )-------------------------- */ diff --git a/src/applications/diffusion/controller/DiffusionInlineCommentController.php b/src/applications/diffusion/controller/DiffusionInlineCommentController.php --- a/src/applications/diffusion/controller/DiffusionInlineCommentController.php +++ b/src/applications/diffusion/controller/DiffusionInlineCommentController.php @@ -43,6 +43,10 @@ return PhabricatorAuditInlineComment::loadID($id); } + protected function loadCommentByPHID($phid) { + return PhabricatorAuditInlineComment::loadPHID($phid); + } + protected function loadCommentForEdit($id) { $request = $this->getRequest(); $user = $request->getUser(); diff --git a/src/infrastructure/diff/PhabricatorInlineCommentController.php b/src/infrastructure/diff/PhabricatorInlineCommentController.php --- a/src/infrastructure/diff/PhabricatorInlineCommentController.php +++ b/src/infrastructure/diff/PhabricatorInlineCommentController.php @@ -6,6 +6,7 @@ abstract protected function createComment(); abstract protected function loadComment($id); abstract protected function loadCommentForEdit($id); + abstract protected function loadCommentByPHID($phid); abstract protected function deleteComment( PhabricatorInlineCommentInterface $inline); abstract protected function saveComment( @@ -20,6 +21,7 @@ private $operation; private $commentID; private $renderer; + private $replyToCommentPHID; public function getCommentID() { return $this->commentID; @@ -62,6 +64,15 @@ return $this->renderer; } + public function setReplyToCommentPHID($phid) { + $this->replyToCommentPHID = $phid; + return $this; + } + + public function getReplyToCommentPHID() { + return $this->replyToCommentPHID; + } + public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); @@ -114,7 +125,6 @@ $edit_dialog->addHiddenInput('id', $this->getCommentID()); $edit_dialog->addHiddenInput('op', 'edit'); - $edit_dialog->addHiddenInput('renderer', $this->getRenderer()); $edit_dialog->appendChild( $this->renderTextArea( @@ -136,6 +146,11 @@ ->setLineLength($this->getLineLength()) ->setIsNewFile($this->getIsNewFile()) ->setContent($text); + + if ($this->getReplyToCommentPHID()) { + $inline->setReplyToCommentPHID($this->getReplyToCommentPHID()); + } + $this->saveComment($inline); return $this->buildRenderedCommentResponse( @@ -162,11 +177,9 @@ } $edit_dialog->addHiddenInput('op', 'create'); - $edit_dialog->addHiddenInput('changeset', $changeset); $edit_dialog->addHiddenInput('is_new', $is_new); $edit_dialog->addHiddenInput('number', $number); $edit_dialog->addHiddenInput('length', $length); - $edit_dialog->addHiddenInput('renderer', $this->getRenderer()); $text_area = $this->renderTextArea($this->getCommentText()); $edit_dialog->appendChild($text_area); @@ -181,7 +194,7 @@ // NOTE: This isn't necessarily a DifferentialChangeset ID, just an // application identifier for the changeset. In Diffusion, it's a Path ID. - $this->changesetID = $request->getInt('changeset'); + $this->changesetID = $request->getInt('changesetID'); $this->isNewFile = (int)$request->getBool('is_new'); $this->isOnRight = $request->getBool('on_right'); @@ -191,6 +204,25 @@ $this->commentID = $request->getInt('id'); $this->operation = $request->getStr('op'); $this->renderer = $request->getStr('renderer'); + $this->replyToCommentPHID = $request->getStr('replyToCommentPHID'); + + if ($this->getReplyToCommentPHID()) { + $reply_phid = $this->getReplyToCommentPHID(); + $reply_comment = $this->loadCommentByPHID($reply_phid); + if (!$reply_comment) { + throw new Exception( + pht('Failed to load comment "%s".', $reply_phid)); + } + + if ($reply_comment->getChangesetID() != $this->getChangesetID()) { + throw new Exception( + pht( + 'Comment "%s" belongs to wrong changeset (%s vs %s).', + $reply_phid, + $reply_comment->getChangesetID(), + $this->getChangesetID())); + } + } } private function buildEditDialog() { @@ -204,7 +236,9 @@ ->setIsNewFile($this->getIsNewFile()) ->setNumber($this->getLineNumber()) ->setLength($this->getLineLength()) - ->setRenderer($this->getRenderer()); + ->setRenderer($this->getRenderer()) + ->setReplyToCommentPHID($this->getReplyToCommentPHID()) + ->setChangesetID($this->getChangesetID()); return $edit_dialog; } diff --git a/src/infrastructure/diff/interface/PhabricatorInlineCommentInterface.php b/src/infrastructure/diff/interface/PhabricatorInlineCommentInterface.php --- a/src/infrastructure/diff/interface/PhabricatorInlineCommentInterface.php +++ b/src/infrastructure/diff/interface/PhabricatorInlineCommentInterface.php @@ -19,6 +19,12 @@ public function setLineLength($length); public function getLineLength(); + public function setReplyToCommentPHID($phid); + public function getReplyToCommentPHID(); + + public function setHasReplies($has_replies); + public function getHasReplies(); + public function setContent($content); public function getContent(); diff --git a/src/infrastructure/diff/view/PHUIDiffInlineCommentDetailView.php b/src/infrastructure/diff/view/PHUIDiffInlineCommentDetailView.php --- a/src/infrastructure/diff/view/PHUIDiffInlineCommentDetailView.php +++ b/src/infrastructure/diff/view/PHUIDiffInlineCommentDetailView.php @@ -76,11 +76,14 @@ $metadata = array( 'id' => $inline->getID(), + 'phid' => $inline->getPHID(), + 'changesetID' => $inline->getChangesetID(), 'number' => $inline->getLineNumber(), 'length' => $inline->getLineLength(), 'isNewFile' => (bool)$inline->getIsNewFile(), 'on_right' => $this->onRight, 'original' => $inline->getContent(), + 'replyToCommentPHID' => $inline->getReplyToCommentPHID(), ); $sigil = 'differential-inline-comment'; @@ -104,6 +107,15 @@ $is_draft = true; } + + // TODO: This stuff is nonfinal, just making it do something. + if ($inline->getHasReplies()) { + $links[] = pht('Has Reply'); + } + if ($inline->getReplyToCommentPHID()) { + $links[] = pht('Is Reply'); + } + if (!$this->preview) { $links[] = javelin_tag( 'a', diff --git a/src/infrastructure/diff/view/PHUIDiffInlineCommentEditView.php b/src/infrastructure/diff/view/PHUIDiffInlineCommentEditView.php --- a/src/infrastructure/diff/view/PHUIDiffInlineCommentEditView.php +++ b/src/infrastructure/diff/view/PHUIDiffInlineCommentEditView.php @@ -11,6 +11,8 @@ private $length; private $renderer; private $isNewFile; + private $replyToCommentPHID; + private $changesetID; public function setIsNewFile($is_new_file) { $this->isNewFile = $is_new_file; @@ -49,9 +51,26 @@ return $this; } + public function setReplyToCommentPHID($reply_to_phid) { + $this->replyToCommentPHID = $reply_to_phid; + return $this; + } + + public function getReplyToCommentPHID() { + return $this->replyToCommentPHID; + } + + public function setChangesetID($changeset_id) { + $this->changesetID = $changeset_id; + return $this; + } + + public function getChangesetID() { + return $this->changesetID; + } + public function setOnRight($on_right) { $this->onRight = $on_right; - $this->addHiddenInput('on_right', $on_right); return $this; } @@ -114,8 +133,15 @@ } private function renderInputs() { + $inputs = $this->inputs; $out = array(); - foreach ($this->inputs as $input) { + + $inputs[] = array('on_right', (bool)$this->getIsOnRight()); + $inputs[] = array('replyToCommentPHID', $this->getReplyToCommentPHID()); + $inputs[] = array('renderer', $this->getRenderer()); + $inputs[] = array('changesetID', $this->getChangesetID()); + + foreach ($inputs as $input) { list($name, $value) = $input; $out[] = phutil_tag( 'input', @@ -170,10 +196,12 @@ 'class' => 'differential-inline-comment-edit', 'sigil' => 'differential-inline-comment', 'meta' => array( + 'changesetID' => $this->getChangesetID(), 'on_right' => $this->getIsOnRight(), 'isNewFile' => (bool)$this->getIsNewFile(), 'number' => $this->number, 'length' => $this->length, + 'replyToCommentPHID' => $this->getReplyToCommentPHID(), ), ), array( diff --git a/webroot/rsrc/js/application/differential/DifferentialInlineCommentEditor.js b/webroot/rsrc/js/application/differential/DifferentialInlineCommentEditor.js --- a/webroot/rsrc/js/application/differential/DifferentialInlineCommentEditor.js +++ b/webroot/rsrc/js/application/differential/DifferentialInlineCommentEditor.js @@ -34,9 +34,10 @@ number : this.getLineNumber(), is_new : this.getIsNew(), length : this.getLength(), - changeset : this.getChangeset(), + changesetID : this.getChangesetID(), text : this.getText() || '', - renderer: this.getRenderer() + renderer: this.getRenderer(), + replyToCommentPHID: this.getReplyToCommentPHID() || '', }; }, _draw : function(content, exact_row) { @@ -284,13 +285,14 @@ onRight : null, ID : null, lineNumber : null, - changeset : null, + changesetID : null, length : null, isNew : null, text : null, templates : null, originalText : null, - renderer: null + renderer: null, + replyToCommentPHID: null } }); diff --git a/webroot/rsrc/js/application/differential/behavior-edit-inline-comments.js b/webroot/rsrc/js/application/differential/behavior-edit-inline-comments.js --- a/webroot/rsrc/js/application/differential/behavior-edit-inline-comments.js +++ b/webroot/rsrc/js/application/differential/behavior-edit-inline-comments.js @@ -245,7 +245,7 @@ editor = new JX.DifferentialInlineCommentEditor(config.uri) .setTemplates(config.undo_templates) .setOperation('new') - .setChangeset(changeset) + .setChangesetID(changeset) .setLineNumber(o) .setLength(len) .setIsNew(isNewFile(target) ? 1 : 0) @@ -320,16 +320,25 @@ } var original = data.original; + var reply_phid = null; if (op == 'reply') { // If the user hit "reply", the original text is empty (a new reply), not // the text of the comment they're replying to. original = ''; + reply_phid = data.phid; } + var changeset_root = JX.DOM.findAbove( + node, + 'div', + 'differential-changeset'); + var view = JX.ChangesetViewManager.getForNode(changeset_root); + editor = new JX.DifferentialInlineCommentEditor(config.uri) .setTemplates(config.undo_templates) .setOperation(op) .setID(data.id) + .setChangesetID(data.changesetID) .setLineNumber(data.number) .setLength(data.length) .setOnRight(data.on_right) @@ -337,6 +346,8 @@ .setRow(row) .setOtherRows(other_rows) .setTable(row.parentNode) + .setReplyToCommentPHID(reply_phid) + .setRenderer(view.getRenderer()) .start(); set_link_state(true);