Summary:
Ref T7447. Implements per-viewer comment hiding. Once a comment is obsolete or uninteresting, you can hide it completely.
This is sticky per-user.
My hope is that this will strike a better balance between concerns than some of the other approaches (conservative porting, summarization, hide-all).
Specifically, this adds a new action here:
{F435621}
Clicking it completely collapses the comment into a small icon on the previous line, and saves the comment state as hidden for you:
{F435626}
You can click the icon to reveal all hidden comments below the line.
Test Plan:
- Hid comments.
- Showed comments.
- Created, edited, deleted and submitted comments.
- Used Diffusion comments (hiding is not implemented there yet, but I'd plan to bring it there eventually if it works out in Differential).
Reviewers: btrahan, chad
Reviewed By: btrahan
Subscribers: jparise, yelirekim, epriestley
Maniphest Tasks: T7447
Differential Revision: https://secure.phabricator.com/D13009
192 lines
5.0 KiB
PHP
192 lines
5.0 KiB
PHP
<?php
|
|
|
|
final class DifferentialInlineCommentEditController
|
|
extends PhabricatorInlineCommentController {
|
|
|
|
private function getRevisionID() {
|
|
return $this->getRequest()->getURIData('id');
|
|
}
|
|
|
|
private function loadRevision() {
|
|
$viewer = $this->getViewer();
|
|
$revision_id = $this->getRevisionID();
|
|
|
|
$revision = id(new DifferentialRevisionQuery())
|
|
->setViewer($viewer)
|
|
->withIDs(array($revision_id))
|
|
->executeOne();
|
|
if (!$revision) {
|
|
throw new Exception(pht('Invalid revision ID "%s".', $revision_id));
|
|
}
|
|
|
|
return $revision;
|
|
}
|
|
|
|
protected function createComment() {
|
|
// Verify revision and changeset correspond to actual objects.
|
|
$changeset_id = $this->getChangesetID();
|
|
|
|
$revision = $this->loadRevision();
|
|
|
|
if (!id(new DifferentialChangeset())->load($changeset_id)) {
|
|
throw new Exception(pht('Invalid changeset ID!'));
|
|
}
|
|
|
|
return id(new DifferentialInlineComment())
|
|
->setRevision($revision)
|
|
->setChangesetID($changeset_id);
|
|
}
|
|
|
|
protected function loadComment($id) {
|
|
return id(new DifferentialInlineCommentQuery())
|
|
->setViewer($this->getViewer())
|
|
->withIDs(array($id))
|
|
->withDeletedDrafts(true)
|
|
->needHidden(true)
|
|
->executeOne();
|
|
}
|
|
|
|
protected function loadCommentByPHID($phid) {
|
|
return id(new DifferentialInlineCommentQuery())
|
|
->setViewer($this->getViewer())
|
|
->withPHIDs(array($phid))
|
|
->withDeletedDrafts(true)
|
|
->needHidden(true)
|
|
->executeOne();
|
|
}
|
|
|
|
protected function loadCommentForEdit($id) {
|
|
$request = $this->getRequest();
|
|
$user = $request->getUser();
|
|
|
|
$inline = $this->loadComment($id);
|
|
if (!$this->canEditInlineComment($user, $inline)) {
|
|
throw new Exception(pht('That comment is not editable!'));
|
|
}
|
|
return $inline;
|
|
}
|
|
|
|
protected function loadCommentForDone($id) {
|
|
$request = $this->getRequest();
|
|
$viewer = $request->getUser();
|
|
|
|
$inline = $this->loadComment($id);
|
|
if (!$inline) {
|
|
throw new Exception(pht('Unable to load inline "%d".', $id));
|
|
}
|
|
|
|
$changeset = id(new DifferentialChangesetQuery())
|
|
->setViewer($viewer)
|
|
->withIDs(array($inline->getChangesetID()))
|
|
->executeOne();
|
|
if (!$changeset) {
|
|
throw new Exception(pht('Unable to load changeset.'));
|
|
}
|
|
|
|
$diff = id(new DifferentialDiffQuery())
|
|
->setViewer($viewer)
|
|
->withIDs(array($changeset->getDiffID()))
|
|
->executeOne();
|
|
if (!$diff) {
|
|
throw new Exception(pht('Unable to load diff.'));
|
|
}
|
|
|
|
$revision = id(new DifferentialRevisionQuery())
|
|
->setViewer($viewer)
|
|
->withIDs(array($diff->getRevisionID()))
|
|
->executeOne();
|
|
if (!$revision) {
|
|
throw new Exception(pht('Unable to load revision.'));
|
|
}
|
|
|
|
if ($revision->getAuthorPHID() !== $viewer->getPHID()) {
|
|
throw new Exception(pht('You are not the revision owner.'));
|
|
}
|
|
|
|
return $inline;
|
|
}
|
|
|
|
private function canEditInlineComment(
|
|
PhabricatorUser $user,
|
|
DifferentialInlineComment $inline) {
|
|
|
|
// Only the author may edit a comment.
|
|
if ($inline->getAuthorPHID() != $user->getPHID()) {
|
|
return false;
|
|
}
|
|
|
|
// Saved comments may not be edited, for now, although the schema now
|
|
// supports it.
|
|
if (!$inline->isDraft()) {
|
|
return false;
|
|
}
|
|
|
|
// Inline must be attached to the active revision.
|
|
if ($inline->getRevisionID() != $this->getRevisionID()) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
protected function deleteComment(PhabricatorInlineCommentInterface $inline) {
|
|
$inline->openTransaction();
|
|
DifferentialDraft::deleteHasDraft(
|
|
$inline->getAuthorPHID(),
|
|
$inline->getRevisionPHID(),
|
|
$inline->getPHID());
|
|
$inline->delete();
|
|
$inline->saveTransaction();
|
|
}
|
|
|
|
protected function saveComment(PhabricatorInlineCommentInterface $inline) {
|
|
$inline->openTransaction();
|
|
$inline->save();
|
|
DifferentialDraft::markHasDraft(
|
|
$inline->getAuthorPHID(),
|
|
$inline->getRevisionPHID(),
|
|
$inline->getPHID());
|
|
$inline->saveTransaction();
|
|
}
|
|
|
|
protected function loadObjectOwnerPHID(
|
|
PhabricatorInlineCommentInterface $inline) {
|
|
return $this->loadRevision()->getAuthorPHID();
|
|
}
|
|
|
|
protected function hideComments(array $ids) {
|
|
$viewer = $this->getViewer();
|
|
$table = new DifferentialHiddenComment();
|
|
$conn_w = $table->establishConnection('w');
|
|
|
|
$sql = array();
|
|
foreach ($ids as $id) {
|
|
$sql[] = qsprintf(
|
|
$conn_w,
|
|
'(%s, %d)',
|
|
$viewer->getPHID(),
|
|
$id);
|
|
}
|
|
|
|
queryfx(
|
|
$conn_w,
|
|
'INSERT IGNORE INTO %T (userPHID, commentID) VALUES %Q',
|
|
$table->getTableName(),
|
|
implode(', ', $sql));
|
|
}
|
|
|
|
protected function showComments(array $ids) {
|
|
$viewer = $this->getViewer();
|
|
$table = new DifferentialHiddenComment();
|
|
$conn_w = $table->establishConnection('w');
|
|
|
|
queryfx(
|
|
$conn_w,
|
|
'DELETE FROM %T WHERE userPHID = %s AND commentID IN (%Ld)',
|
|
$table->getTableName(),
|
|
$viewer->getPHID(),
|
|
$ids);
|
|
}
|
|
|
|
}
|