mirror of
https://we.phorge.it/source/phorge.git
synced 2025-03-31 14:38:15 +02:00
Lift inline state transactions into core (in Diffusion)
Summary: Ref T1460. Ref T6403. Replace `Diffusion::INLINEDONE` with `Transactions::INLINESTATE` and generalize things enough that we can lift it into core. The next change will lift Differential's similar implementation into the core. Also start implementing a fix for T6403, providing an alternate hook for optional builtin transactions. Test Plan: Changed inline state in Diffusion. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T6403, T1460 Differential Revision: https://secure.phabricator.com/D12129
This commit is contained in:
parent
cbb5a297d5
commit
8c053f02a7
5 changed files with 129 additions and 83 deletions
|
@ -9,7 +9,8 @@ final class PhabricatorAuditEditor
|
||||||
private $heraldEmailPHIDs = array();
|
private $heraldEmailPHIDs = array();
|
||||||
private $affectedFiles;
|
private $affectedFiles;
|
||||||
private $rawPatch;
|
private $rawPatch;
|
||||||
private $expandedDone;
|
|
||||||
|
private $didExpandInlineState;
|
||||||
|
|
||||||
public function addAuditReason($phid, $reason) {
|
public function addAuditReason($phid, $reason) {
|
||||||
if (!isset($this->auditReasonMap[$phid])) {
|
if (!isset($this->auditReasonMap[$phid])) {
|
||||||
|
@ -53,9 +54,9 @@ final class PhabricatorAuditEditor
|
||||||
|
|
||||||
$types[] = PhabricatorTransactions::TYPE_COMMENT;
|
$types[] = PhabricatorTransactions::TYPE_COMMENT;
|
||||||
$types[] = PhabricatorTransactions::TYPE_EDGE;
|
$types[] = PhabricatorTransactions::TYPE_EDGE;
|
||||||
|
$types[] = PhabricatorTransactions::TYPE_INLINESTATE;
|
||||||
|
|
||||||
$types[] = PhabricatorAuditTransaction::TYPE_COMMIT;
|
$types[] = PhabricatorAuditTransaction::TYPE_COMMIT;
|
||||||
$types[] = PhabricatorAuditTransaction::TYPE_INLINEDONE;
|
|
||||||
|
|
||||||
// TODO: These will get modernized eventually, but that can happen one
|
// TODO: These will get modernized eventually, but that can happen one
|
||||||
// at a time later on.
|
// at a time later on.
|
||||||
|
@ -104,7 +105,6 @@ final class PhabricatorAuditEditor
|
||||||
case PhabricatorAuditActionConstants::INLINE:
|
case PhabricatorAuditActionConstants::INLINE:
|
||||||
case PhabricatorAuditActionConstants::ADD_AUDITORS:
|
case PhabricatorAuditActionConstants::ADD_AUDITORS:
|
||||||
case PhabricatorAuditTransaction::TYPE_COMMIT:
|
case PhabricatorAuditTransaction::TYPE_COMMIT:
|
||||||
case PhabricatorAuditTransaction::TYPE_INLINEDONE:
|
|
||||||
return $xaction->getNewValue();
|
return $xaction->getNewValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,6 @@ final class PhabricatorAuditEditor
|
||||||
case PhabricatorAuditActionConstants::INLINE:
|
case PhabricatorAuditActionConstants::INLINE:
|
||||||
case PhabricatorAuditActionConstants::ADD_AUDITORS:
|
case PhabricatorAuditActionConstants::ADD_AUDITORS:
|
||||||
case PhabricatorAuditTransaction::TYPE_COMMIT:
|
case PhabricatorAuditTransaction::TYPE_COMMIT:
|
||||||
case PhabricatorAuditTransaction::TYPE_INLINEDONE:
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,18 +146,6 @@ final class PhabricatorAuditEditor
|
||||||
$reply->setHasReplies(1)->save();
|
$reply->setHasReplies(1)->save();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case PhabricatorAuditTransaction::TYPE_INLINEDONE:
|
|
||||||
$table = new PhabricatorAuditTransactionComment();
|
|
||||||
$conn_w = $table->establishConnection('w');
|
|
||||||
foreach ($xaction->getNewValue() as $phid => $state) {
|
|
||||||
queryfx(
|
|
||||||
$conn_w,
|
|
||||||
'UPDATE %T SET fixedState = %s WHERE phid = %s',
|
|
||||||
$table->getTableName(),
|
|
||||||
$state,
|
|
||||||
$phid);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case PhabricatorAuditActionConstants::ADD_AUDITORS:
|
case PhabricatorAuditActionConstants::ADD_AUDITORS:
|
||||||
$new = $xaction->getNewValue();
|
$new = $xaction->getNewValue();
|
||||||
if (!is_array($new)) {
|
if (!is_array($new)) {
|
||||||
|
@ -204,6 +191,28 @@ final class PhabricatorAuditEditor
|
||||||
return parent::applyCustomExternalTransaction($object, $xaction);
|
return parent::applyCustomExternalTransaction($object, $xaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function applyBuiltinExternalTransaction(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
|
||||||
|
switch ($xaction->getTransactionType()) {
|
||||||
|
case PhabricatorTransactions::TYPE_INLINESTATE:
|
||||||
|
$table = new PhabricatorAuditTransactionComment();
|
||||||
|
$conn_w = $table->establishConnection('w');
|
||||||
|
foreach ($xaction->getNewValue() as $phid => $state) {
|
||||||
|
queryfx(
|
||||||
|
$conn_w,
|
||||||
|
'UPDATE %T SET fixedState = %s WHERE phid = %s',
|
||||||
|
$table->getTableName(),
|
||||||
|
$state,
|
||||||
|
$phid);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::applyBuiltinExternalTransaction($object, $xaction);
|
||||||
|
}
|
||||||
|
|
||||||
protected function applyFinalEffects(
|
protected function applyFinalEffects(
|
||||||
PhabricatorLiskDAO $object,
|
PhabricatorLiskDAO $object,
|
||||||
array $xactions) {
|
array $xactions) {
|
||||||
|
@ -361,12 +370,11 @@ final class PhabricatorAuditEditor
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->expandedDone) {
|
if (!$this->didExpandInlineState) {
|
||||||
|
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
case PhabricatorTransactions::TYPE_COMMENT:
|
case PhabricatorTransactions::TYPE_COMMENT:
|
||||||
case PhabricatorAuditActionConstants::ACTION:
|
case PhabricatorAuditActionConstants::ACTION:
|
||||||
$this->expandedDone = true;
|
$this->didExpandInlineState = true;
|
||||||
|
|
||||||
$actor_phid = $this->getActingAsPHID();
|
$actor_phid = $this->getActingAsPHID();
|
||||||
$actor_is_author = ($object->getAuthorPHID() == $actor_phid);
|
$actor_is_author = ($object->getAuthorPHID() == $actor_phid);
|
||||||
|
@ -374,12 +382,7 @@ final class PhabricatorAuditEditor
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$state_map = array(
|
$state_map = PhabricatorTransactions::getInlineStateMap();
|
||||||
PhabricatorInlineCommentInterface::STATE_DRAFT =>
|
|
||||||
PhabricatorInlineCommentInterface::STATE_DONE,
|
|
||||||
PhabricatorInlineCommentInterface::STATE_UNDRAFT =>
|
|
||||||
PhabricatorInlineCommentInterface::STATE_UNDONE,
|
|
||||||
);
|
|
||||||
|
|
||||||
$inlines = id(new DiffusionDiffInlineCommentQuery())
|
$inlines = id(new DiffusionDiffInlineCommentQuery())
|
||||||
->setViewer($this->getActor())
|
->setViewer($this->getActor())
|
||||||
|
@ -398,7 +401,7 @@ final class PhabricatorAuditEditor
|
||||||
}
|
}
|
||||||
|
|
||||||
$xactions[] = id(new PhabricatorAuditTransaction())
|
$xactions[] = id(new PhabricatorAuditTransaction())
|
||||||
->setTransactionType(PhabricatorAuditTransaction::TYPE_INLINEDONE)
|
->setTransactionType(PhabricatorTransactions::TYPE_INLINESTATE)
|
||||||
->setIgnoreOnNoEffect(true)
|
->setIgnoreOnNoEffect(true)
|
||||||
->setOldValue($old_value)
|
->setOldValue($old_value)
|
||||||
->setNewValue($new_value);
|
->setNewValue($new_value);
|
||||||
|
|
|
@ -4,7 +4,6 @@ final class PhabricatorAuditTransaction
|
||||||
extends PhabricatorApplicationTransaction {
|
extends PhabricatorApplicationTransaction {
|
||||||
|
|
||||||
const TYPE_COMMIT = 'audit:commit';
|
const TYPE_COMMIT = 'audit:commit';
|
||||||
const TYPE_INLINEDONE = 'audit:inlinedone';
|
|
||||||
|
|
||||||
const MAILTAG_ACTION_CONCERN = 'audit-action-concern';
|
const MAILTAG_ACTION_CONCERN = 'audit-action-concern';
|
||||||
const MAILTAG_ACTION_ACCEPT = 'audit-action-accept';
|
const MAILTAG_ACTION_ACCEPT = 'audit-action-accept';
|
||||||
|
@ -183,36 +182,6 @@ final class PhabricatorAuditTransaction
|
||||||
}
|
}
|
||||||
return $title;
|
return $title;
|
||||||
|
|
||||||
case self::TYPE_INLINEDONE:
|
|
||||||
$done = 0;
|
|
||||||
$undone = 0;
|
|
||||||
foreach ($new as $phid => $state) {
|
|
||||||
if ($state == PhabricatorInlineCommentInterface::STATE_DONE) {
|
|
||||||
$done++;
|
|
||||||
} else {
|
|
||||||
$undone++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($done && $undone) {
|
|
||||||
return pht(
|
|
||||||
'%s marked %s inline comment(s) as done and %s inline comment(s) '.
|
|
||||||
'as not done.',
|
|
||||||
$author_handle,
|
|
||||||
new PhutilNumber($done),
|
|
||||||
new PhutilNumber($undone));
|
|
||||||
} else if ($done) {
|
|
||||||
return pht(
|
|
||||||
'%s marked %s inline comment(s) as done.',
|
|
||||||
$author_handle,
|
|
||||||
new PhutilNumber($done));
|
|
||||||
} else {
|
|
||||||
return pht(
|
|
||||||
'%s marked %s inline comment(s) as not done.',
|
|
||||||
$author_handle,
|
|
||||||
new PhutilNumber($undone));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PhabricatorAuditActionConstants::INLINE:
|
case PhabricatorAuditActionConstants::INLINE:
|
||||||
return pht(
|
return pht(
|
||||||
'%s added inline comments.',
|
'%s added inline comments.',
|
||||||
|
@ -418,39 +387,17 @@ final class PhabricatorAuditTransaction
|
||||||
return parent::getBodyForFeed($story);
|
return parent::getBodyForFeed($story);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isInlineCommentTransaction() {
|
||||||
public function shouldGenerateOldValue() {
|
|
||||||
switch ($this->getTransactionType()) {
|
switch ($this->getTransactionType()) {
|
||||||
case self::TYPE_INLINEDONE:
|
case PhabricatorAuditActionConstants::INLINE:
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::shouldGenerateOldValue();
|
return parent::isInlineCommentTransaction();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: These two mail methods can likely be abstracted by introducing a
|
|
||||||
// formal concept of "inline comment" transactions.
|
|
||||||
|
|
||||||
public function shouldHideForMail(array $xactions) {
|
|
||||||
$type_inline = PhabricatorAuditActionConstants::INLINE;
|
|
||||||
switch ($this->getTransactionType()) {
|
|
||||||
case $type_inline:
|
|
||||||
foreach ($xactions as $xaction) {
|
|
||||||
if ($xaction->getTransactionType() != $type_inline) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ($this !== head($xactions));
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent::shouldHideForMail($xactions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBodyForMail() {
|
public function getBodyForMail() {
|
||||||
switch ($this->getTransactionType()) {
|
switch ($this->getTransactionType()) {
|
||||||
case PhabricatorAuditActionConstants::INLINE:
|
|
||||||
return null;
|
|
||||||
case self::TYPE_COMMIT:
|
case self::TYPE_COMMIT:
|
||||||
$data = $this->getNewValue();
|
$data = $this->getNewValue();
|
||||||
return $data['description'];
|
return $data['description'];
|
||||||
|
|
|
@ -11,6 +11,7 @@ final class PhabricatorTransactions {
|
||||||
const TYPE_CUSTOMFIELD = 'core:customfield';
|
const TYPE_CUSTOMFIELD = 'core:customfield';
|
||||||
const TYPE_BUILDABLE = 'harbormaster:buildable';
|
const TYPE_BUILDABLE = 'harbormaster:buildable';
|
||||||
const TYPE_TOKEN = 'token:give';
|
const TYPE_TOKEN = 'token:give';
|
||||||
|
const TYPE_INLINESTATE = 'core:inlinestate';
|
||||||
|
|
||||||
const COLOR_RED = 'red';
|
const COLOR_RED = 'red';
|
||||||
const COLOR_ORANGE = 'orange';
|
const COLOR_ORANGE = 'orange';
|
||||||
|
@ -23,4 +24,14 @@ final class PhabricatorTransactions {
|
||||||
const COLOR_GREY = 'grey';
|
const COLOR_GREY = 'grey';
|
||||||
const COLOR_BLACK = 'black';
|
const COLOR_BLACK = 'black';
|
||||||
|
|
||||||
|
|
||||||
|
public static function getInlineStateMap() {
|
||||||
|
return array(
|
||||||
|
PhabricatorInlineCommentInterface::STATE_DRAFT =>
|
||||||
|
PhabricatorInlineCommentInterface::STATE_DONE,
|
||||||
|
PhabricatorInlineCommentInterface::STATE_UNDRAFT =>
|
||||||
|
PhabricatorInlineCommentInterface::STATE_UNDONE,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,6 +294,7 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
case PhabricatorTransactions::TYPE_JOIN_POLICY:
|
case PhabricatorTransactions::TYPE_JOIN_POLICY:
|
||||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||||
case PhabricatorTransactions::TYPE_TOKEN:
|
case PhabricatorTransactions::TYPE_TOKEN:
|
||||||
|
case PhabricatorTransactions::TYPE_INLINESTATE:
|
||||||
return $xaction->getNewValue();
|
return $xaction->getNewValue();
|
||||||
case PhabricatorTransactions::TYPE_EDGE:
|
case PhabricatorTransactions::TYPE_EDGE:
|
||||||
return $this->getEdgeTransactionNewValue($xaction);
|
return $this->getEdgeTransactionNewValue($xaction);
|
||||||
|
@ -395,6 +396,8 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
||||||
$field = $this->getCustomFieldForTransaction($object, $xaction);
|
$field = $this->getCustomFieldForTransaction($object, $xaction);
|
||||||
return $field->applyApplicationTransactionInternalEffects($xaction);
|
return $field->applyApplicationTransactionInternalEffects($xaction);
|
||||||
|
case PhabricatorTransactions::TYPE_INLINESTATE:
|
||||||
|
return $this->applyBuiltinInternalTransaction($object, $xaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->applyCustomInternalTransaction($object, $xaction);
|
return $this->applyCustomInternalTransaction($object, $xaction);
|
||||||
|
@ -489,6 +492,8 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
||||||
$field = $this->getCustomFieldForTransaction($object, $xaction);
|
$field = $this->getCustomFieldForTransaction($object, $xaction);
|
||||||
return $field->applyApplicationTransactionExternalEffects($xaction);
|
return $field->applyApplicationTransactionExternalEffects($xaction);
|
||||||
|
case PhabricatorTransactions::TYPE_INLINESTATE:
|
||||||
|
return $this->applyBuiltinExternalTransaction($object, $xaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->applyCustomExternalTransaction($object, $xaction);
|
return $this->applyCustomExternalTransaction($object, $xaction);
|
||||||
|
@ -512,6 +517,23 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
"implementation!");
|
"implementation!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Write proper documentation for these hooks. These are like the
|
||||||
|
// "applyCustom" hooks, except that implementation is optional, so you do
|
||||||
|
// not need to handle all of the builtin transaction types. See T6403. These
|
||||||
|
// are not completely implemented.
|
||||||
|
|
||||||
|
protected function applyBuiltinInternalTransaction(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function applyBuiltinExternalTransaction(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill in a transaction's common values, like author and content source.
|
* Fill in a transaction's common values, like author and content source.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -57,6 +57,7 @@ abstract class PhabricatorApplicationTransaction
|
||||||
case PhabricatorTransactions::TYPE_BUILDABLE:
|
case PhabricatorTransactions::TYPE_BUILDABLE:
|
||||||
case PhabricatorTransactions::TYPE_TOKEN:
|
case PhabricatorTransactions::TYPE_TOKEN:
|
||||||
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
||||||
|
case PhabricatorTransactions::TYPE_INLINESTATE:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -501,6 +502,26 @@ abstract class PhabricatorApplicationTransaction
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a transaction publishes an inline comment:
|
||||||
|
//
|
||||||
|
// - Don't show it if there are other kinds of transactions. The
|
||||||
|
// rationale here is that application mail will make the presence
|
||||||
|
// of inline comments obvious enough by including them prominently
|
||||||
|
// in the body. We could change this in the future if the obviousness
|
||||||
|
// needs to be increased.
|
||||||
|
// - If there are only inline transactions, only show the first
|
||||||
|
// transaction. The rationale is that seeing multiple "added an inline
|
||||||
|
// comment" transactions is not useful.
|
||||||
|
|
||||||
|
if ($this->isInlineCommentTransaction()) {
|
||||||
|
foreach ($xactions as $xaction) {
|
||||||
|
if (!$xaction->isInlineCommentTransaction()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ($this !== head($xactions));
|
||||||
|
}
|
||||||
|
|
||||||
return $this->shouldHide();
|
return $this->shouldHide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,10 +560,18 @@ abstract class PhabricatorApplicationTransaction
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBodyForMail() {
|
public function getBodyForMail() {
|
||||||
|
if ($this->isInlineCommentTransaction()) {
|
||||||
|
// We don't return inline comment content as mail body content, because
|
||||||
|
// applications need to contextualize it (by adding line numbers, for
|
||||||
|
// example) in order for it to make sense.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
$comment = $this->getComment();
|
$comment = $this->getComment();
|
||||||
if ($comment && strlen($comment->getContent())) {
|
if ($comment && strlen($comment->getContent())) {
|
||||||
return $comment->getContent();
|
return $comment->getContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -720,6 +749,36 @@ abstract class PhabricatorApplicationTransaction
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case PhabricatorTransactions::TYPE_INLINESTATE:
|
||||||
|
$done = 0;
|
||||||
|
$undone = 0;
|
||||||
|
foreach ($new as $phid => $state) {
|
||||||
|
if ($state == PhabricatorInlineCommentInterface::STATE_DONE) {
|
||||||
|
$done++;
|
||||||
|
} else {
|
||||||
|
$undone++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($done && $undone) {
|
||||||
|
return pht(
|
||||||
|
'%s marked %s inline comment(s) as done and %s inline comment(s) '.
|
||||||
|
'as not done.',
|
||||||
|
$this->renderHandleLink($author_phid),
|
||||||
|
new PhutilNumber($done),
|
||||||
|
new PhutilNumber($undone));
|
||||||
|
} else if ($done) {
|
||||||
|
return pht(
|
||||||
|
'%s marked %s inline comment(s) as done.',
|
||||||
|
$this->renderHandleLink($author_phid),
|
||||||
|
new PhutilNumber($done));
|
||||||
|
} else {
|
||||||
|
return pht(
|
||||||
|
'%s marked %s inline comment(s) as not done.',
|
||||||
|
$this->renderHandleLink($author_phid),
|
||||||
|
new PhutilNumber($undone));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return pht(
|
return pht(
|
||||||
'%s edited this %s.',
|
'%s edited this %s.',
|
||||||
|
@ -932,6 +991,10 @@ abstract class PhabricatorApplicationTransaction
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isInlineCommentTransaction() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public function getActionName() {
|
public function getActionName() {
|
||||||
switch ($this->getTransactionType()) {
|
switch ($this->getTransactionType()) {
|
||||||
case PhabricatorTransactions::TYPE_COMMENT:
|
case PhabricatorTransactions::TYPE_COMMENT:
|
||||||
|
|
Loading…
Add table
Reference in a new issue