1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-23 22:10:55 +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:
Bob Trahan 2014-09-09 14:21:13 -07:00
parent 0151c38b10
commit c75495e63f
11 changed files with 155 additions and 14 deletions

View file

@ -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',

View file

@ -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);
} }
} }

View file

@ -10,6 +10,7 @@ final class DifferentialRevision extends DifferentialDAO
PhabricatorSubscribableInterface, PhabricatorSubscribableInterface,
PhabricatorCustomFieldInterface, PhabricatorCustomFieldInterface,
PhabricatorApplicationTransactionInterface, PhabricatorApplicationTransactionInterface,
PhabricatorMentionableInterface,
PhabricatorDestructibleInterface, PhabricatorDestructibleInterface,
PhabricatorProjectInterface { PhabricatorProjectInterface {

View file

@ -6,6 +6,7 @@ final class ManiphestTask extends ManiphestDAO
PhabricatorPolicyInterface, PhabricatorPolicyInterface,
PhabricatorTokenReceiverInterface, PhabricatorTokenReceiverInterface,
PhabricatorFlaggableInterface, PhabricatorFlaggableInterface,
PhabricatorMentionableInterface,
PhrequentTrackableInterface, PhrequentTrackableInterface,
PhabricatorCustomFieldInterface, PhabricatorCustomFieldInterface,
PhabricatorDestructibleInterface, PhabricatorDestructibleInterface,

View file

@ -5,6 +5,7 @@ final class PhabricatorPaste extends PhabricatorPasteDAO
PhabricatorSubscribableInterface, PhabricatorSubscribableInterface,
PhabricatorTokenReceiverInterface, PhabricatorTokenReceiverInterface,
PhabricatorFlaggableInterface, PhabricatorFlaggableInterface,
PhabricatorMentionableInterface,
PhabricatorPolicyInterface, PhabricatorPolicyInterface,
PhabricatorProjectInterface { PhabricatorProjectInterface {

View file

@ -7,6 +7,7 @@ final class PhabricatorRepositoryCommit
PhabricatorFlaggableInterface, PhabricatorFlaggableInterface,
PhabricatorTokenReceiverInterface, PhabricatorTokenReceiverInterface,
PhabricatorSubscribableInterface, PhabricatorSubscribableInterface,
PhabricatorMentionableInterface,
HarbormasterBuildableInterface, HarbormasterBuildableInterface,
PhabricatorCustomFieldInterface, PhabricatorCustomFieldInterface,
PhabricatorApplicationTransactionInterface { PhabricatorApplicationTransactionInterface {

View file

@ -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);
}
}

View file

@ -0,0 +1,15 @@
<?php
final class PhabricatorObjectMentionsObject extends PhabricatorEdgeType {
const EDGECONST = 52;
public function getInverseEdgeConstant() {
return PhabricatorObjectMentionedByObject::EDGECONST;
}
public function shouldWriteInverseTransactions() {
return true;
}
}

View file

@ -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); $mentioned_phids += $engine->getTextMetadata(
$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;
} }

View file

@ -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();
}

View file

@ -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();