mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-22 05:20:56 +01:00
Transactions - add infrastructure for "mentions"
Summary: Fixes T4036. Now if you say something on diff X like "This reminds me of Tx and Dy and commitHashFoo and Px." each of those objects gets a little visible transaction that the mention occurred. No feed, email, or notifications. Test Plan: made a comment like above and verified transactions. also submitted a diff that "Fixes Tx" and Tx did not get the transaction as expected. Reviewers: epriestley Reviewed By: epriestley Subscribers: joshuaspence, epriestley, Korvin Maniphest Tasks: T4036 Differential Revision: https://secure.phabricator.com/D10451
This commit is contained in:
parent
0151c38b10
commit
c75495e63f
11 changed files with 155 additions and 14 deletions
|
@ -1723,6 +1723,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorMarkupPreviewController' => 'infrastructure/markup/PhabricatorMarkupPreviewController.php',
|
'PhabricatorMarkupPreviewController' => 'infrastructure/markup/PhabricatorMarkupPreviewController.php',
|
||||||
'PhabricatorMemeRemarkupRule' => 'applications/macro/markup/PhabricatorMemeRemarkupRule.php',
|
'PhabricatorMemeRemarkupRule' => 'applications/macro/markup/PhabricatorMemeRemarkupRule.php',
|
||||||
'PhabricatorMentionRemarkupRule' => 'applications/people/markup/PhabricatorMentionRemarkupRule.php',
|
'PhabricatorMentionRemarkupRule' => 'applications/people/markup/PhabricatorMentionRemarkupRule.php',
|
||||||
|
'PhabricatorMentionableInterface' => 'applications/transactions/interface/PhabricatorMentionableInterface.php',
|
||||||
'PhabricatorMercurialGraphStream' => 'applications/repository/daemon/PhabricatorMercurialGraphStream.php',
|
'PhabricatorMercurialGraphStream' => 'applications/repository/daemon/PhabricatorMercurialGraphStream.php',
|
||||||
'PhabricatorMetaMTAActor' => 'applications/metamta/query/PhabricatorMetaMTAActor.php',
|
'PhabricatorMetaMTAActor' => 'applications/metamta/query/PhabricatorMetaMTAActor.php',
|
||||||
'PhabricatorMetaMTAActorQuery' => 'applications/metamta/query/PhabricatorMetaMTAActorQuery.php',
|
'PhabricatorMetaMTAActorQuery' => 'applications/metamta/query/PhabricatorMetaMTAActorQuery.php',
|
||||||
|
@ -1808,6 +1809,8 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorObjectListQueryTestCase' => 'applications/phid/query/__tests__/PhabricatorObjectListQueryTestCase.php',
|
'PhabricatorObjectListQueryTestCase' => 'applications/phid/query/__tests__/PhabricatorObjectListQueryTestCase.php',
|
||||||
'PhabricatorObjectMailReceiver' => 'applications/metamta/receiver/PhabricatorObjectMailReceiver.php',
|
'PhabricatorObjectMailReceiver' => 'applications/metamta/receiver/PhabricatorObjectMailReceiver.php',
|
||||||
'PhabricatorObjectMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorObjectMailReceiverTestCase.php',
|
'PhabricatorObjectMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorObjectMailReceiverTestCase.php',
|
||||||
|
'PhabricatorObjectMentionedByObject' => 'applications/transactions/edges/PhabricatorObjectMentionedByObject.php',
|
||||||
|
'PhabricatorObjectMentionsObject' => 'applications/transactions/edges/PhabricatorObjectMentionsObject.php',
|
||||||
'PhabricatorObjectQuery' => 'applications/phid/query/PhabricatorObjectQuery.php',
|
'PhabricatorObjectQuery' => 'applications/phid/query/PhabricatorObjectQuery.php',
|
||||||
'PhabricatorObjectRemarkupRule' => 'infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php',
|
'PhabricatorObjectRemarkupRule' => 'infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php',
|
||||||
'PhabricatorObjectSelectorDialog' => 'view/control/PhabricatorObjectSelectorDialog.php',
|
'PhabricatorObjectSelectorDialog' => 'view/control/PhabricatorObjectSelectorDialog.php',
|
||||||
|
@ -3084,6 +3087,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSubscribableInterface',
|
'PhabricatorSubscribableInterface',
|
||||||
'PhabricatorCustomFieldInterface',
|
'PhabricatorCustomFieldInterface',
|
||||||
'PhabricatorApplicationTransactionInterface',
|
'PhabricatorApplicationTransactionInterface',
|
||||||
|
'PhabricatorMentionableInterface',
|
||||||
'PhabricatorDestructibleInterface',
|
'PhabricatorDestructibleInterface',
|
||||||
'PhabricatorProjectInterface',
|
'PhabricatorProjectInterface',
|
||||||
),
|
),
|
||||||
|
@ -3698,6 +3702,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
'PhabricatorTokenReceiverInterface',
|
'PhabricatorTokenReceiverInterface',
|
||||||
'PhabricatorFlaggableInterface',
|
'PhabricatorFlaggableInterface',
|
||||||
|
'PhabricatorMentionableInterface',
|
||||||
'PhrequentTrackableInterface',
|
'PhrequentTrackableInterface',
|
||||||
'PhabricatorCustomFieldInterface',
|
'PhabricatorCustomFieldInterface',
|
||||||
'PhabricatorDestructibleInterface',
|
'PhabricatorDestructibleInterface',
|
||||||
|
@ -4658,6 +4663,8 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorObjectListQueryTestCase' => 'PhabricatorTestCase',
|
'PhabricatorObjectListQueryTestCase' => 'PhabricatorTestCase',
|
||||||
'PhabricatorObjectMailReceiver' => 'PhabricatorMailReceiver',
|
'PhabricatorObjectMailReceiver' => 'PhabricatorMailReceiver',
|
||||||
'PhabricatorObjectMailReceiverTestCase' => 'PhabricatorTestCase',
|
'PhabricatorObjectMailReceiverTestCase' => 'PhabricatorTestCase',
|
||||||
|
'PhabricatorObjectMentionedByObject' => 'PhabricatorEdgeType',
|
||||||
|
'PhabricatorObjectMentionsObject' => 'PhabricatorEdgeType',
|
||||||
'PhabricatorObjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhabricatorObjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhabricatorObjectRemarkupRule' => 'PhutilRemarkupRule',
|
'PhabricatorObjectRemarkupRule' => 'PhutilRemarkupRule',
|
||||||
'PhabricatorOffsetPagedQuery' => 'PhabricatorQuery',
|
'PhabricatorOffsetPagedQuery' => 'PhabricatorQuery',
|
||||||
|
@ -4693,6 +4700,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSubscribableInterface',
|
'PhabricatorSubscribableInterface',
|
||||||
'PhabricatorTokenReceiverInterface',
|
'PhabricatorTokenReceiverInterface',
|
||||||
'PhabricatorFlaggableInterface',
|
'PhabricatorFlaggableInterface',
|
||||||
|
'PhabricatorMentionableInterface',
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
'PhabricatorProjectInterface',
|
'PhabricatorProjectInterface',
|
||||||
),
|
),
|
||||||
|
@ -4908,6 +4916,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorFlaggableInterface',
|
'PhabricatorFlaggableInterface',
|
||||||
'PhabricatorTokenReceiverInterface',
|
'PhabricatorTokenReceiverInterface',
|
||||||
'PhabricatorSubscribableInterface',
|
'PhabricatorSubscribableInterface',
|
||||||
|
'PhabricatorMentionableInterface',
|
||||||
'HarbormasterBuildableInterface',
|
'HarbormasterBuildableInterface',
|
||||||
'PhabricatorCustomFieldInterface',
|
'PhabricatorCustomFieldInterface',
|
||||||
'PhabricatorApplicationTransactionInterface',
|
'PhabricatorApplicationTransactionInterface',
|
||||||
|
|
|
@ -1270,8 +1270,10 @@ final class DifferentialTransactionEditor
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
if ($tasks) {
|
if ($tasks) {
|
||||||
|
$phid_map = mpull($tasks, 'getPHID', 'getPHID');
|
||||||
$edge_related = DifferentialRevisionHasTaskEdgeType::EDGECONST;
|
$edge_related = DifferentialRevisionHasTaskEdgeType::EDGECONST;
|
||||||
$edges[$edge_related] = mpull($tasks, 'getPHID', 'getPHID');
|
$edges[$edge_related] = $phid_map;
|
||||||
|
$this->setUnmentionablePHIDMap($phid_map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ final class DifferentialRevision extends DifferentialDAO
|
||||||
PhabricatorSubscribableInterface,
|
PhabricatorSubscribableInterface,
|
||||||
PhabricatorCustomFieldInterface,
|
PhabricatorCustomFieldInterface,
|
||||||
PhabricatorApplicationTransactionInterface,
|
PhabricatorApplicationTransactionInterface,
|
||||||
|
PhabricatorMentionableInterface,
|
||||||
PhabricatorDestructibleInterface,
|
PhabricatorDestructibleInterface,
|
||||||
PhabricatorProjectInterface {
|
PhabricatorProjectInterface {
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ final class ManiphestTask extends ManiphestDAO
|
||||||
PhabricatorPolicyInterface,
|
PhabricatorPolicyInterface,
|
||||||
PhabricatorTokenReceiverInterface,
|
PhabricatorTokenReceiverInterface,
|
||||||
PhabricatorFlaggableInterface,
|
PhabricatorFlaggableInterface,
|
||||||
|
PhabricatorMentionableInterface,
|
||||||
PhrequentTrackableInterface,
|
PhrequentTrackableInterface,
|
||||||
PhabricatorCustomFieldInterface,
|
PhabricatorCustomFieldInterface,
|
||||||
PhabricatorDestructibleInterface,
|
PhabricatorDestructibleInterface,
|
||||||
|
|
|
@ -5,6 +5,7 @@ final class PhabricatorPaste extends PhabricatorPasteDAO
|
||||||
PhabricatorSubscribableInterface,
|
PhabricatorSubscribableInterface,
|
||||||
PhabricatorTokenReceiverInterface,
|
PhabricatorTokenReceiverInterface,
|
||||||
PhabricatorFlaggableInterface,
|
PhabricatorFlaggableInterface,
|
||||||
|
PhabricatorMentionableInterface,
|
||||||
PhabricatorPolicyInterface,
|
PhabricatorPolicyInterface,
|
||||||
PhabricatorProjectInterface {
|
PhabricatorProjectInterface {
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ final class PhabricatorRepositoryCommit
|
||||||
PhabricatorFlaggableInterface,
|
PhabricatorFlaggableInterface,
|
||||||
PhabricatorTokenReceiverInterface,
|
PhabricatorTokenReceiverInterface,
|
||||||
PhabricatorSubscribableInterface,
|
PhabricatorSubscribableInterface,
|
||||||
|
PhabricatorMentionableInterface,
|
||||||
HarbormasterBuildableInterface,
|
HarbormasterBuildableInterface,
|
||||||
PhabricatorCustomFieldInterface,
|
PhabricatorCustomFieldInterface,
|
||||||
PhabricatorApplicationTransactionInterface {
|
PhabricatorApplicationTransactionInterface {
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorObjectMentionedByObject extends PhabricatorEdgeType {
|
||||||
|
|
||||||
|
const EDGECONST = 51;
|
||||||
|
|
||||||
|
public function getInverseEdgeConstant() {
|
||||||
|
return PhabricatorObjectMentionsObject::EDGECONST;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldWriteInverseTransactions() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTransactionAddString(
|
||||||
|
$actor,
|
||||||
|
$add_count,
|
||||||
|
$add_edges) {
|
||||||
|
|
||||||
|
return pht(
|
||||||
|
'%s mentioned this in %s.',
|
||||||
|
$actor,
|
||||||
|
$add_edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorObjectMentionsObject extends PhabricatorEdgeType {
|
||||||
|
|
||||||
|
const EDGECONST = 52;
|
||||||
|
|
||||||
|
public function getInverseEdgeConstant() {
|
||||||
|
return PhabricatorObjectMentionedByObject::EDGECONST;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldWriteInverseTransactions() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
private $heraldAdapter;
|
private $heraldAdapter;
|
||||||
private $heraldTranscript;
|
private $heraldTranscript;
|
||||||
private $subscribers;
|
private $subscribers;
|
||||||
|
private $unmentionablePHIDMap = array();
|
||||||
|
|
||||||
private $isPreview;
|
private $isPreview;
|
||||||
private $isHeraldEditor;
|
private $isHeraldEditor;
|
||||||
|
@ -175,6 +176,15 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
return $this->disableEmail;
|
return $this->disableEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setUnmentionablePHIDMap(array $map) {
|
||||||
|
$this->unmentionablePHIDMap = $map;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUnmentionablePHIDMap() {
|
||||||
|
return $this->unmentionablePHIDMap;
|
||||||
|
}
|
||||||
|
|
||||||
public function getTransactionTypes() {
|
public function getTransactionTypes() {
|
||||||
$types = array();
|
$types = array();
|
||||||
|
|
||||||
|
@ -1013,7 +1023,7 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildMentionTransaction(
|
private function buildSubscribeTransaction(
|
||||||
PhabricatorLiskDAO $object,
|
PhabricatorLiskDAO $object,
|
||||||
array $xactions,
|
array $xactions,
|
||||||
array $blocks) {
|
array $blocks) {
|
||||||
|
@ -1119,12 +1129,12 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
$blocks[$key] = $this->getRemarkupBlocksFromTransaction($xaction);
|
$blocks[$key] = $this->getRemarkupBlocksFromTransaction($xaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
$mention_xaction = $this->buildMentionTransaction(
|
$subscribe_xaction = $this->buildSubscribeTransaction(
|
||||||
$object,
|
$object,
|
||||||
$xactions,
|
$xactions,
|
||||||
$blocks);
|
$blocks);
|
||||||
if ($mention_xaction) {
|
if ($subscribe_xaction) {
|
||||||
$xactions[] = $mention_xaction;
|
$xactions[] = $subscribe_xaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: For now, this is just a placeholder.
|
// TODO: For now, this is just a placeholder.
|
||||||
|
@ -1156,17 +1166,22 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
$blocks,
|
$blocks,
|
||||||
$engine);
|
$engine);
|
||||||
|
|
||||||
if ($object instanceof PhabricatorProjectInterface) {
|
$mentioned_phids = array();
|
||||||
$phids = array();
|
|
||||||
foreach ($blocks as $key => $xaction_blocks) {
|
foreach ($blocks as $key => $xaction_blocks) {
|
||||||
foreach ($xaction_blocks as $block) {
|
foreach ($xaction_blocks as $block) {
|
||||||
$engine->markupText($block);
|
$engine->markupText($block);
|
||||||
$phids += $engine->getTextMetadata(
|
$mentioned_phids += $engine->getTextMetadata(
|
||||||
PhabricatorObjectRemarkupRule::KEY_MENTIONED_OBJECTS,
|
PhabricatorObjectRemarkupRule::KEY_MENTIONED_OBJECTS,
|
||||||
array());
|
array());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$mentioned_phids) {
|
||||||
|
return $block_xactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($object instanceof PhabricatorProjectInterface) {
|
||||||
|
$phids = $mentioned_phids;
|
||||||
$project_type = PhabricatorProjectProjectPHIDType::TYPECONST;
|
$project_type = PhabricatorProjectProjectPHIDType::TYPECONST;
|
||||||
foreach ($phids as $key => $phid) {
|
foreach ($phids as $key => $phid) {
|
||||||
if (phid_get_type($phid) != $project_type) {
|
if (phid_get_type($phid) != $project_type) {
|
||||||
|
@ -1184,6 +1199,29 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$objects = id(new PhabricatorObjectQuery())
|
||||||
|
->setViewer($this->getActor())
|
||||||
|
->withPHIDs($mentioned_phids)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$mentionable_phids = array();
|
||||||
|
foreach ($objects as $object) {
|
||||||
|
if ($object instanceof PhabricatorMentionableInterface) {
|
||||||
|
if (idx($this->getUnmentionablePHIDMap(), $object->getPHID())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$mentionable_phids[$object->getPHID()] = $object->getPHID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($mentionable_phids) {
|
||||||
|
$edge_type = PhabricatorObjectMentionsObject::EDGECONST;
|
||||||
|
$block_xactions[] = newv(get_class(head($xactions)), array())
|
||||||
|
->setIgnoreOnNoEffect(true)
|
||||||
|
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
|
||||||
|
->setMetadataValue('edge:type', $edge_type)
|
||||||
|
->setNewValue(array('+' => $mentionable_phids));
|
||||||
|
}
|
||||||
|
|
||||||
return $block_xactions;
|
return $block_xactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow infrastructure to automagically create "mentioned" transactions
|
||||||
|
* - actually TYPE_EDGE transactions that add "mentioned" edges - to the
|
||||||
|
* implementing object.
|
||||||
|
*/
|
||||||
|
interface PhabricatorMentionableInterface {
|
||||||
|
|
||||||
|
public function getPHID();
|
||||||
|
|
||||||
|
}
|
|
@ -438,6 +438,19 @@ abstract class PhabricatorApplicationTransaction
|
||||||
if ($field) {
|
if ($field) {
|
||||||
return $field->shouldHideInApplicationTransactions($this);
|
return $field->shouldHideInApplicationTransactions($this);
|
||||||
}
|
}
|
||||||
|
case PhabricatorTransactions::TYPE_EDGE:
|
||||||
|
$edge_type = $this->getMetadataValue('edge:type');
|
||||||
|
switch ($edge_type) {
|
||||||
|
case PhabricatorObjectMentionsObject::EDGECONST:
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case PhabricatorObjectMentionedByObject::EDGECONST:
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -456,6 +469,17 @@ abstract class PhabricatorApplicationTransaction
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
case PhabricatorTransactions::TYPE_EDGE:
|
||||||
|
$edge_type = $this->getMetadataValue('edge:type');
|
||||||
|
switch ($edge_type) {
|
||||||
|
case PhabricatorObjectMentionsObject::EDGECONST:
|
||||||
|
case PhabricatorObjectMentionedByObject::EDGECONST:
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->shouldHide();
|
return $this->shouldHide();
|
||||||
|
@ -475,6 +499,17 @@ abstract class PhabricatorApplicationTransaction
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
case PhabricatorTransactions::TYPE_EDGE:
|
||||||
|
$edge_type = $this->getMetadataValue('edge:type');
|
||||||
|
switch ($edge_type) {
|
||||||
|
case PhabricatorObjectMentionsObject::EDGECONST:
|
||||||
|
case PhabricatorObjectMentionedByObject::EDGECONST:
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->shouldHide();
|
return $this->shouldHide();
|
||||||
|
|
Loading…
Reference in a new issue