@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

MetaMTA - more progress towards a mail application

Summary:
Ref T5791. This diff does a few things...

- Adds code to write recipients to edges on save
- Makes Query performance for policy filtering okay-ish
- Adds a Search Engine for PhabricatorMetaMTAMail
- Adds "working" List Controller
- Inbox and Outbox both work
- Adds stub View Controller

Test Plan: ran `./bin/storage upgrade` and saw my inbox and outbox start getting data. played with application and saw new entries in inbox and outbox

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: epriestley, Korvin

Maniphest Tasks: T5791

Differential Revision: https://secure.phabricator.com/D13397

+244 -5
+8
src/__phutil_library_map__.php
··· 2108 2108 'PhabricatorMetaMTAMail' => 'applications/metamta/storage/PhabricatorMetaMTAMail.php', 2109 2109 'PhabricatorMetaMTAMailBody' => 'applications/metamta/view/PhabricatorMetaMTAMailBody.php', 2110 2110 'PhabricatorMetaMTAMailBodyTestCase' => 'applications/metamta/view/__tests__/PhabricatorMetaMTAMailBodyTestCase.php', 2111 + 'PhabricatorMetaMTAMailHasRecipientEdgeType' => 'applications/metamta/edge/PhabricatorMetaMTAMailHasRecipientEdgeType.php', 2112 + 'PhabricatorMetaMTAMailListController' => 'applications/metamta/controller/PhabricatorMetaMTAMailListController.php', 2111 2113 'PhabricatorMetaMTAMailPHIDType' => 'applications/metamta/phid/PhabricatorMetaMTAMailPHIDType.php', 2112 2114 'PhabricatorMetaMTAMailQuery' => 'applications/metamta/query/PhabricatorMetaMTAMailQuery.php', 2115 + 'PhabricatorMetaMTAMailSearchEngine' => 'applications/metamta/query/PhabricatorMetaMTAMailSearchEngine.php', 2113 2116 'PhabricatorMetaMTAMailSection' => 'applications/metamta/view/PhabricatorMetaMTAMailSection.php', 2114 2117 'PhabricatorMetaMTAMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAMailTestCase.php', 2118 + 'PhabricatorMetaMTAMailViewController' => 'applications/metamta/controller/PhabricatorMetaMTAMailViewController.php', 2115 2119 'PhabricatorMetaMTAMailableDatasource' => 'applications/metamta/typeahead/PhabricatorMetaMTAMailableDatasource.php', 2116 2120 'PhabricatorMetaMTAMailableFunctionDatasource' => 'applications/metamta/typeahead/PhabricatorMetaMTAMailableFunctionDatasource.php', 2117 2121 'PhabricatorMetaMTAMailgunReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php', ··· 5754 5758 ), 5755 5759 'PhabricatorMetaMTAMailBody' => 'Phobject', 5756 5760 'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase', 5761 + 'PhabricatorMetaMTAMailHasRecipientEdgeType' => 'PhabricatorEdgeType', 5762 + 'PhabricatorMetaMTAMailListController' => 'PhabricatorMetaMTAController', 5757 5763 'PhabricatorMetaMTAMailPHIDType' => 'PhabricatorPHIDType', 5758 5764 'PhabricatorMetaMTAMailQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 5765 + 'PhabricatorMetaMTAMailSearchEngine' => 'PhabricatorApplicationSearchEngine', 5759 5766 'PhabricatorMetaMTAMailSection' => 'Phobject', 5760 5767 'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase', 5768 + 'PhabricatorMetaMTAMailViewController' => 'PhabricatorMetaMTAController', 5761 5769 'PhabricatorMetaMTAMailableDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 5762 5770 'PhabricatorMetaMTAMailableFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 5763 5771 'PhabricatorMetaMTAMailgunReceiveController' => 'PhabricatorMetaMTAController',
+3
src/applications/metamta/application/PhabricatorMetaMTAApplication.php
··· 37 37 public function getRoutes() { 38 38 return array( 39 39 '/mail/' => array( 40 + '(query/(?P<queryKey>[^/]+)/)?' => 41 + 'PhabricatorMetaMTAMailListController', 42 + 'detail/(?P<id>[1-9]\d*)/' => 'PhabricatorMetaMTAMailViewController', 40 43 'sendgrid/' => 'PhabricatorMetaMTASendGridReceiveController', 41 44 'mailgun/' => 'PhabricatorMetaMTAMailgunReceiveController', 42 45 ),
+30
src/applications/metamta/controller/PhabricatorMetaMTAMailListController.php
··· 1 + <?php 2 + 3 + final class PhabricatorMetaMTAMailListController 4 + extends PhabricatorMetaMTAController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + $controller = id(new PhabricatorApplicationSearchController()) 8 + ->setQueryKey($request->getURIData('queryKey')) 9 + ->setSearchEngine(new PhabricatorMetaMTAMailSearchEngine()) 10 + ->setNavigation($this->buildSideNav()); 11 + 12 + return $this->delegateToController($controller); 13 + } 14 + 15 + public function buildSideNav() { 16 + $user = $this->getRequest()->getUser(); 17 + 18 + $nav = new AphrontSideNavFilterView(); 19 + $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); 20 + 21 + id(new PhabricatorMetaMTAMailSearchEngine()) 22 + ->setViewer($user) 23 + ->addNavigationItems($nav->getMenu()); 24 + 25 + $nav->selectFilter(null); 26 + 27 + return $nav; 28 + } 29 + 30 + }
+10
src/applications/metamta/controller/PhabricatorMetaMTAMailViewController.php
··· 1 + <?php 2 + 3 + final class PhabricatorMetaMTAMailViewController 4 + extends PhabricatorMetaMTAController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + // TODO 8 + } 9 + 10 + }
+8
src/applications/metamta/edge/PhabricatorMetaMTAMailHasRecipientEdgeType.php
··· 1 + <?php 2 + 3 + final class PhabricatorMetaMTAMailHasRecipientEdgeType 4 + extends PhabricatorEdgeType { 5 + 6 + const EDGECONST = 57; 7 + 8 + }
+54
src/applications/metamta/query/PhabricatorMetaMTAMailQuery.php
··· 5 5 6 6 private $ids; 7 7 private $phids; 8 + private $actorPHIDs; 9 + private $recipientPHIDs; 8 10 9 11 public function withIDs(array $ids) { 10 12 $this->ids = $ids; ··· 13 15 14 16 public function withPHIDs(array $phids) { 15 17 $this->phids = $phids; 18 + return $this; 19 + } 20 + 21 + public function withActorPHIDs(array $phids) { 22 + $this->actorPHIDs = $phids; 23 + return $this; 24 + } 25 + 26 + public function withRecipientPHIDs(array $phids) { 27 + $this->recipientPHIDs = $phids; 16 28 return $this; 17 29 } 18 30 ··· 37 49 $this->phids); 38 50 } 39 51 52 + if ($this->actorPHIDs !== null) { 53 + $where[] = qsprintf( 54 + $conn_r, 55 + 'mail.actorPHID IN (%Ls)', 56 + $this->actorPHIDs); 57 + } 58 + 59 + if ($this->recipientPHIDs !== null) { 60 + $where[] = qsprintf( 61 + $conn_r, 62 + 'recipient.dst IN (%Ls)', 63 + $this->recipientPHIDs); 64 + } 65 + 66 + $viewer = $this->getViewer(); 67 + $where[] = qsprintf( 68 + $conn_r, 69 + 'edge.dst = %s OR actorPHID = %s', 70 + $viewer->getPHID(), 71 + $viewer->getPHID()); 72 + 40 73 $where[] = $this->buildPagingClause($conn_r); 41 74 42 75 return $this->formatWhereClause($where); 76 + } 77 + 78 + protected function buildJoinClause(AphrontDatabaseConnection $conn) { 79 + $joins = array(); 80 + 81 + $joins[] = qsprintf( 82 + $conn, 83 + 'LEFT JOIN %T edge ON mail.phid = edge.src AND edge.type = %d', 84 + PhabricatorEdgeConfig::TABLE_NAME_EDGE, 85 + PhabricatorMetaMTAMailHasRecipientEdgeType::EDGECONST); 86 + 87 + if ($this->recipientPHIDs !== null) { 88 + $joins[] = qsprintf( 89 + $conn, 90 + 'LEFT JOIN %T recipient '. 91 + 'ON mail.phid = recipient.src AND recipient.type = %d', 92 + PhabricatorEdgeConfig::TABLE_NAME_EDGE, 93 + PhabricatorMetaMTAMailHasRecipientEdgeType::EDGECONST); 94 + } 95 + 96 + return implode(' ', $joins); 43 97 } 44 98 45 99 protected function getPrimaryTableAlias() {
+112
src/applications/metamta/query/PhabricatorMetaMTAMailSearchEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorMetaMTAMailSearchEngine 4 + extends PhabricatorApplicationSearchEngine { 5 + 6 + public function getResultTypeDescription() { 7 + return pht('MetaMTA Mails'); 8 + } 9 + 10 + public function getApplicationClassName() { 11 + return 'PhabricatorMetaMTAApplication'; 12 + } 13 + 14 + public function newQuery() { 15 + return new PhabricatorMetaMTAMailQuery(); 16 + } 17 + 18 + protected function shouldShowOrderField() { 19 + return false; 20 + } 21 + 22 + protected function buildCustomSearchFields() { 23 + return array( 24 + id(new PhabricatorSearchUsersField()) 25 + ->setLabel(pht('Actors')) 26 + ->setKey('actorPHIDs') 27 + ->setAliases(array('actor', 'actors')), 28 + id(new PhabricatorSearchUsersField()) 29 + ->setLabel(pht('Recipients')) 30 + ->setKey('recipientPHIDs') 31 + ->setAliases(array('recipient', 'recipients')), 32 + ); 33 + } 34 + 35 + protected function buildQueryFromParameters(array $map) { 36 + $query = $this->newQuery(); 37 + 38 + if ($map['actorPHIDs']) { 39 + $query->withActorPHIDs($map['actorPHIDs']); 40 + } 41 + 42 + if ($map['recipientPHIDs']) { 43 + $query->withRecipientPHIDs($map['recipientPHIDs']); 44 + } 45 + 46 + return $query; 47 + } 48 + 49 + protected function getURI($path) { 50 + return '/mail/'.$path; 51 + } 52 + 53 + protected function getBuiltinQueryNames() { 54 + $names = array( 55 + 'inbox' => pht('Inbox'), 56 + 'outbox' => pht('Outbox'), 57 + ); 58 + 59 + return $names; 60 + } 61 + 62 + public function buildSavedQueryFromBuiltin($query_key) { 63 + $viewer = $this->requireViewer(); 64 + 65 + $query = $this->newSavedQuery(); 66 + $query->setQueryKey($query_key); 67 + 68 + switch ($query_key) { 69 + case 'inbox': 70 + return $query->setParameter( 71 + 'recipientPHIDs', 72 + array($viewer->getPHID())); 73 + case 'outbox': 74 + return $query->setParameter( 75 + 'actorPHIDs', 76 + array($viewer->getPHID())); 77 + } 78 + 79 + return parent::buildSavedQueryFromBuiltin($query_key); 80 + } 81 + 82 + protected function getRequiredHandlePHIDsForResultList( 83 + array $objects, 84 + PhabricatorSavedQuery $query) { 85 + 86 + $phids = array(); 87 + foreach ($objects as $mail) { 88 + $phids[] = $mail->getExpandedRecipientPHIDs(); 89 + } 90 + return array_mergev($phids); 91 + } 92 + 93 + protected function renderResultList( 94 + array $mails, 95 + PhabricatorSavedQuery $query, 96 + array $handles) { 97 + 98 + assert_instances_of($mails, 'PhabricatorMetaMTAMail'); 99 + $viewer = $this->requireViewer(); 100 + $list = new PHUIObjectItemListView(); 101 + 102 + foreach ($mails as $mail) { 103 + 104 + $header = pht('Mail %d: TODO.', $mail->getID()); 105 + $item = id(new PHUIObjectItemView()) 106 + ->setHeader($header); 107 + $list->addItem($item); 108 + } 109 + 110 + return $list; 111 + } 112 + }
+19 -5
src/applications/metamta/storage/PhabricatorMetaMTAMail.php
··· 366 366 // method. 367 367 368 368 $this->openTransaction(); 369 - // Save to generate a task ID. 369 + // Save to generate a mail ID and PHID. 370 370 $result = parent::save(); 371 + 372 + // Write the recipient edges. 373 + $editor = new PhabricatorEdgeEditor(); 374 + $edge_type = PhabricatorMetaMTAMailHasRecipientEdgeType::EDGECONST; 375 + $actor_phids = array_unique(array_merge( 376 + $this->getAllActorPHIDs(), 377 + $this->getExpandedRecipientPHIDs())); 378 + foreach ($actor_phids as $actor_phid) { 379 + $editor->addEdge($this->getPHID(), $edge_type, $actor_phid); 380 + } 381 + $editor->save(); 371 382 372 383 // Queue a task to send this mail. 373 384 $mailer_task = PhabricatorWorker::scheduleTask( ··· 813 824 } 814 825 815 826 public function loadAllActors() { 816 - $actor_phids = $this->getAllActorPHIDs(); 817 - $actor_phids = $this->expandRecipients($actor_phids); 827 + $actor_phids = $this->getExpandedRecipientPHIDs(); 818 828 return $this->loadActors($actor_phids); 829 + } 830 + 831 + public function getExpandedRecipientPHIDs() { 832 + $actor_phids = $this->getAllActorPHIDs(); 833 + return $this->expandRecipients($actor_phids); 819 834 } 820 835 821 836 private function getAllActorPHIDs() { ··· 1025 1040 } 1026 1041 1027 1042 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 1028 - $actor_phids = $this->getAllActorPHIDs(); 1029 - $actor_phids = $this->expandRecipients($actor_phids); 1043 + $actor_phids = $this->getExpandedRecipientPHIDs(); 1030 1044 return in_array($viewer->getPHID(), $actor_phids); 1031 1045 } 1032 1046