1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 23:02:42 +01:00

Use "CommentPro" controller instead of "Comment" controller

Summary: Ref T2222. This will probabaly have a few rough edges too, but seems to work well.

Test Plan:
  - Made a bunch of comments while building this.
  - Made some new comments.
  - Verified that the Asana/JIRA integration is only a little bit janky, not completely broken.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2222

Differential Revision: https://secure.phabricator.com/D8362
This commit is contained in:
epriestley 2014-02-27 11:06:55 -08:00
parent 62143b5455
commit ba7d67f917
7 changed files with 444 additions and 539 deletions

File diff suppressed because it is too large Load diff

View file

@ -360,7 +360,6 @@ phutil_register_library_map(array(
'DifferentialCommentPreviewController' => 'applications/differential/controller/DifferentialCommentPreviewController.php',
'DifferentialCommentQuery' => 'applications/differential/query/DifferentialCommentQuery.php',
'DifferentialCommentSaveController' => 'applications/differential/controller/DifferentialCommentSaveController.php',
'DifferentialCommentSaveControllerPro' => 'applications/differential/controller/DifferentialCommentSaveControllerPro.php',
'DifferentialCommitsField' => 'applications/differential/customfield/DifferentialCommitsField.php',
'DifferentialCommitsFieldSpecification' => 'applications/differential/field/specification/DifferentialCommitsFieldSpecification.php',
'DifferentialConflictsFieldSpecification' => 'applications/differential/field/specification/DifferentialConflictsFieldSpecification.php',
@ -2925,7 +2924,6 @@ phutil_register_library_map(array(
'DifferentialCommentPreviewController' => 'DifferentialController',
'DifferentialCommentQuery' => 'PhabricatorOffsetPagedQuery',
'DifferentialCommentSaveController' => 'DifferentialController',
'DifferentialCommentSaveControllerPro' => 'DifferentialController',
'DifferentialCommitsField' => 'DifferentialCustomField',
'DifferentialCommitsFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialConflictsFieldSpecification' => 'DifferentialFieldSpecification',

View file

@ -55,8 +55,7 @@ final class PhabricatorApplicationDifferential extends PhabricatorApplication {
=> 'DifferentialRevisionLandController',
'comment/' => array(
'preview/(?P<id>[1-9]\d*)/' => 'DifferentialCommentPreviewController',
'save/' => 'DifferentialCommentSaveController',
'savepro/(?P<id>[1-9]\d*)/' => 'DifferentialCommentSaveControllerPro',
'save/(?P<id>[1-9]\d*)/' => 'DifferentialCommentSaveController',
'inline/' => array(
'preview/(?P<id>[1-9]\d*)/'
=> 'DifferentialInlineCommentPreviewController',

View file

@ -1,79 +1,144 @@
<?php
final class DifferentialCommentSaveController extends DifferentialController {
final class DifferentialCommentSaveController
extends DifferentialController {
private $id;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
if (!$request->isFormPost()) {
return new Aphront400Response();
}
$viewer = $request->getUser();
$revision_id = $request->getInt('revision_id');
$revision = id(new DifferentialRevisionQuery())
->setViewer($viewer)
->withIDs(array($revision_id))
->withIDs(array($this->id))
->needReviewerStatus(true)
->needReviewerAuthority(true)
->executeOne();
if (!$revision) {
return new Aphront400Response();
return new Aphront404Response();
}
$type_action = DifferentialTransaction::TYPE_ACTION;
$type_subscribers = PhabricatorTransactions::TYPE_SUBSCRIBERS;
$type_edge = PhabricatorTransactions::TYPE_EDGE;
$type_comment = PhabricatorTransactions::TYPE_COMMENT;
$type_inline = DifferentialTransaction::TYPE_INLINE;
$edge_reviewer = PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER;
$xactions = array();
$action = $request->getStr('action');
switch ($action) {
case DifferentialAction::ACTION_COMMENT:
case DifferentialAction::ACTION_ADDREVIEWERS:
case DifferentialAction::ACTION_ADDCCS:
// These transaction types have no direct effect, they just
// accompany other transaction types which can have an effect.
break;
default:
$xactions[] = id(new DifferentialTransaction())
->setTransactionType($type_action)
->setNewValue($request->getStr('action'));
break;
}
$ccs = $request->getArr('ccs');
if ($ccs) {
$xactions[] = id(new DifferentialTransaction())
->setTransactionType($type_subscribers)
->setNewValue(array('+' => $ccs));
}
$current_reviewers = mpull(
$revision->getReviewerStatus(),
null,
'getReviewerPHID');
$reviewer_edges = array();
$add_reviewers = $request->getArr('reviewers');
foreach ($add_reviewers as $reviewer_phid) {
if (isset($current_reviewers[$reviewer_phid])) {
continue;
}
$reviewer = new DifferentialReviewer(
$reviewer_phid,
array(
'status' => DifferentialReviewerStatus::STATUS_ADDED,
));
$reviewer_edges[$reviewer_phid] = array(
'data' => $reviewer->getEdgeData(),
);
}
if ($add_reviewers) {
$xactions[] = id(new DifferentialTransaction())
->setTransactionType($type_edge)
->setMetadataValue('edge:type', $edge_reviewer)
->setNewValue(array('+' => $reviewer_edges));
}
$inline_phids = $this->loadUnsubmittedInlinePHIDs($revision);
if ($inline_phids) {
$inlines = id(new PhabricatorApplicationTransactionCommentQuery())
->setTemplate(new DifferentialTransactionComment())
->setViewer($viewer)
->withPHIDs($inline_phids)
->execute();
} else {
$inlines = array();
}
foreach ($inlines as $inline) {
$xactions[] = id(new DifferentialTransaction())
->setTransactionType($type_inline)
->attachComment($inline);
}
// NOTE: If there are no other transactions, add an empty comment
// transaction so that we'll raise a more user-friendly error message,
// to the effect of "you can not post an empty comment".
$no_xactions = !$xactions;
$comment = $request->getStr('comment');
$action = $request->getStr('action');
$reviewers = $request->getArr('reviewers');
$ccs = $request->getArr('ccs');
if (strlen($comment) || $no_xactions) {
$xactions[] = id(new DifferentialTransaction())
->setTransactionType($type_comment)
->attachComment(
id(new DifferentialTransactionComment())
->setRevisionPHID($revision->getPHID())
->setContent($comment));
}
$editor = new DifferentialCommentEditor(
$revision,
$action);
$content_source = PhabricatorContentSource::newForSource(
PhabricatorContentSource::SOURCE_WEB,
array(
'ip' => $request->getRemoteAddr(),
));
$editor = id(new DifferentialTransactionEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect($request->isContinueRequest());
$revision_uri = '/D'.$revision->getID();
try {
$editor
->setActor($request->getUser())
->setMessage($comment)
->setContentSource($content_source)
->setAttachInlineComments(true)
->setAddedReviewers($reviewers)
->setAddedCCs($ccs)
->save();
} catch (DifferentialActionHasNoEffectException $no_effect) {
$has_inlines = id(new DifferentialInlineCommentQuery())
->withDraftComments($request->getUser()->getPHID(), $revision->getID())
->execute();
$dialog = new AphrontDialogView();
$dialog->setUser($request->getUser());
$dialog->addCancelButton('/D'.$revision_id);
$dialog->addHiddenInput('revision_id', $revision_id);
$dialog->addHiddenInput('action', 'none');
$dialog->addHiddenInput('reviewers', $reviewers);
$dialog->addHiddenInput('ccs', $ccs);
$dialog->addHiddenInput('comment', $comment);
$dialog->setTitle(pht('Action Has No Effect'));
$dialog->appendChild(
phutil_tag('p', array(), $no_effect->getMessage()));
if (strlen($comment) || $has_inlines) {
$dialog->addSubmitButton(pht('Post as Comment'));
$dialog->appendChild(phutil_tag('br'));
$dialog->appendChild(phutil_tag('p', array(), pht(
'Do you want to post your feedback anyway, as a normal comment?')));
$editor->applyTransactions($revision, $xactions);
} catch (PhabricatorApplicationTransactionNoEffectException $ex) {
return id(new PhabricatorApplicationTransactionNoEffectResponse())
->setCancelURI($revision_uri)
->setException($ex);
} catch (PhabricatorApplicationTransactionValidationException $ex) {
// TODO: Provide a nice Response for rendering these in a clean way.
throw $ex;
}
return id(new AphrontDialogResponse())->setDialog($dialog);
}
// TODO: Diff change detection?
$user = $request->getUser();
$draft = id(new PhabricatorDraft())->loadOneWhere(
'authorPHID = %s AND draftKey = %s',
@ -88,4 +153,30 @@ final class DifferentialCommentSaveController extends DifferentialController {
->setURI('/D'.$revision->getID());
}
private function loadUnsubmittedInlinePHIDs(DifferentialRevision $revision) {
$viewer = $this->getRequest()->getUser();
// TODO: This probably needs to move somewhere more central as we move
// away from DifferentialInlineCommentQuery, but
// PhabricatorApplicationTransactionCommentQuery is currently `final` and
// I'm not yet decided on how to approach that. For now, just get the PHIDs
// and then execute a PHID-based query through the standard stack.
$table = new DifferentialTransactionComment();
$conn_r = $table->establishConnection('r');
$phids = queryfx_all(
$conn_r,
'SELECT phid FROM %T
WHERE revisionPHID = %s
AND authorPHID = %s
AND transactionPHID IS NULL',
$table->getTableName(),
$revision->getPHID(),
$viewer->getPHID());
return ipull($phids, 'phid');
}
}

View file

@ -1,182 +0,0 @@
<?php
final class DifferentialCommentSaveControllerPro
extends DifferentialController {
private $id;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
if (!$request->isFormPost()) {
return new Aphront400Response();
}
$revision = id(new DifferentialRevisionQuery())
->setViewer($viewer)
->withIDs(array($this->id))
->needReviewerStatus(true)
->needReviewerAuthority(true)
->executeOne();
if (!$revision) {
return new Aphront404Response();
}
$type_action = DifferentialTransaction::TYPE_ACTION;
$type_subscribers = PhabricatorTransactions::TYPE_SUBSCRIBERS;
$type_edge = PhabricatorTransactions::TYPE_EDGE;
$type_comment = PhabricatorTransactions::TYPE_COMMENT;
$type_inline = DifferentialTransaction::TYPE_INLINE;
$edge_reviewer = PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER;
$xactions = array();
$action = $request->getStr('action');
switch ($action) {
case DifferentialAction::ACTION_COMMENT:
case DifferentialAction::ACTION_ADDREVIEWERS:
case DifferentialAction::ACTION_ADDCCS:
// These transaction types have no direct effect, they just
// accompany other transaction types which can have an effect.
break;
default:
$xactions[] = id(new DifferentialTransaction())
->setTransactionType($type_action)
->setNewValue($request->getStr('action'));
break;
}
$ccs = $request->getArr('ccs');
if ($ccs) {
$xactions[] = id(new DifferentialTransaction())
->setTransactionType($type_subscribers)
->setNewValue(array('+' => $ccs));
}
$current_reviewers = mpull(
$revision->getReviewerStatus(),
null,
'getReviewerPHID');
$reviewer_edges = array();
$add_reviewers = $request->getArr('reviewers');
foreach ($add_reviewers as $reviewer_phid) {
if (isset($current_reviewers[$reviewer_phid])) {
continue;
}
$reviewer = new DifferentialReviewer(
$reviewer_phid,
array(
'status' => DifferentialReviewerStatus::STATUS_ADDED,
));
$reviewer_edges[$reviewer_phid] = array(
'data' => $reviewer->getEdgeData(),
);
}
if ($add_reviewers) {
$xactions[] = id(new DifferentialTransaction())
->setTransactionType($type_edge)
->setMetadataValue('edge:type', $edge_reviewer)
->setNewValue(array('+' => $reviewer_edges));
}
$inline_phids = $this->loadUnsubmittedInlinePHIDs($revision);
if ($inline_phids) {
$inlines = id(new PhabricatorApplicationTransactionCommentQuery())
->setTemplate(new DifferentialTransactionComment())
->setViewer($viewer)
->withPHIDs($inline_phids)
->execute();
} else {
$inlines = array();
}
foreach ($inlines as $inline) {
$xactions[] = id(new DifferentialTransaction())
->setTransactionType($type_inline)
->attachComment($inline);
}
// NOTE: If there are no other transactions, add an empty comment
// transaction so that we'll raise a more user-friendly error message,
// to the effect of "you can not post an empty comment".
$no_xactions = !$xactions;
$comment = $request->getStr('comment');
if (strlen($comment) || $no_xactions) {
$xactions[] = id(new DifferentialTransaction())
->setTransactionType($type_comment)
->attachComment(
id(new DifferentialTransactionComment())
->setRevisionPHID($revision->getPHID())
->setContent($comment));
}
$editor = id(new DifferentialTransactionEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect($request->isContinueRequest());
$revision_uri = '/D'.$revision->getID();
try {
$editor->applyTransactions($revision, $xactions);
} catch (PhabricatorApplicationTransactionNoEffectException $ex) {
return id(new PhabricatorApplicationTransactionNoEffectResponse())
->setCancelURI($revision_uri)
->setException($ex);
} catch (PhabricatorApplicationTransactionValidationException $ex) {
// TODO: Provide a nice Response for rendering these in a clean way.
throw $ex;
}
$user = $request->getUser();
$draft = id(new PhabricatorDraft())->loadOneWhere(
'authorPHID = %s AND draftKey = %s',
$user->getPHID(),
'differential-comment-'.$revision->getID());
if ($draft) {
$draft->delete();
}
DifferentialDraft::deleteAllDrafts($user->getPHID(), $revision->getPHID());
return id(new AphrontRedirectResponse())
->setURI('/D'.$revision->getID());
}
private function loadUnsubmittedInlinePHIDs(DifferentialRevision $revision) {
$viewer = $this->getRequest()->getUser();
// TODO: This probably needs to move somewhere more central as we move
// away from DifferentialInlineCommentQuery, but
// PhabricatorApplicationTransactionCommentQuery is currently `final` and
// I'm not yet decided on how to approach that. For now, just get the PHIDs
// and then execute a PHID-based query through the standard stack.
$table = new DifferentialTransactionComment();
$conn_r = $table->establishConnection('r');
$phids = queryfx_all(
$conn_r,
'SELECT phid FROM %T
WHERE revisionPHID = %s
AND authorPHID = %s
AND transactionPHID IS NULL',
$table->getTableName(),
$revision->getPHID(),
$viewer->getPHID());
return ipull($phids, 'phid');
}
}

View file

@ -339,13 +339,8 @@ final class DifferentialRevisionViewController extends DifferentialController {
// TODO: Restore the ability for fields to add accept warnings.
$comment_form->setActions($this->getRevisionCommentActions($revision));
$action_uri = '/differential/comment/save/';
if (false) {
// TODO: Temporary for testing the new comment workflow.
$action_uri = $this->getApplicationURI(
'comment/savepro/'.$revision->getID().'/');
}
'comment/save/'.$revision->getID().'/');
$comment_form->setActionURI($action_uri);
$comment_form->setUser($user);

View file

@ -732,6 +732,10 @@ final class DifferentialTransactionEditor
return parent::requireCapabilities($object, $xaction);
}
protected function supportsFeed() {
return true;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {