1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-27 09:12:41 +01:00

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
This commit is contained in:
Bob Trahan 2015-06-23 11:37:14 -07:00
parent de30e15b7e
commit dfef8e2f07
8 changed files with 244 additions and 5 deletions

View file

@ -2108,10 +2108,14 @@ phutil_register_library_map(array(
'PhabricatorMetaMTAMail' => 'applications/metamta/storage/PhabricatorMetaMTAMail.php', 'PhabricatorMetaMTAMail' => 'applications/metamta/storage/PhabricatorMetaMTAMail.php',
'PhabricatorMetaMTAMailBody' => 'applications/metamta/view/PhabricatorMetaMTAMailBody.php', 'PhabricatorMetaMTAMailBody' => 'applications/metamta/view/PhabricatorMetaMTAMailBody.php',
'PhabricatorMetaMTAMailBodyTestCase' => 'applications/metamta/view/__tests__/PhabricatorMetaMTAMailBodyTestCase.php', 'PhabricatorMetaMTAMailBodyTestCase' => 'applications/metamta/view/__tests__/PhabricatorMetaMTAMailBodyTestCase.php',
'PhabricatorMetaMTAMailHasRecipientEdgeType' => 'applications/metamta/edge/PhabricatorMetaMTAMailHasRecipientEdgeType.php',
'PhabricatorMetaMTAMailListController' => 'applications/metamta/controller/PhabricatorMetaMTAMailListController.php',
'PhabricatorMetaMTAMailPHIDType' => 'applications/metamta/phid/PhabricatorMetaMTAMailPHIDType.php', 'PhabricatorMetaMTAMailPHIDType' => 'applications/metamta/phid/PhabricatorMetaMTAMailPHIDType.php',
'PhabricatorMetaMTAMailQuery' => 'applications/metamta/query/PhabricatorMetaMTAMailQuery.php', 'PhabricatorMetaMTAMailQuery' => 'applications/metamta/query/PhabricatorMetaMTAMailQuery.php',
'PhabricatorMetaMTAMailSearchEngine' => 'applications/metamta/query/PhabricatorMetaMTAMailSearchEngine.php',
'PhabricatorMetaMTAMailSection' => 'applications/metamta/view/PhabricatorMetaMTAMailSection.php', 'PhabricatorMetaMTAMailSection' => 'applications/metamta/view/PhabricatorMetaMTAMailSection.php',
'PhabricatorMetaMTAMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAMailTestCase.php', 'PhabricatorMetaMTAMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAMailTestCase.php',
'PhabricatorMetaMTAMailViewController' => 'applications/metamta/controller/PhabricatorMetaMTAMailViewController.php',
'PhabricatorMetaMTAMailableDatasource' => 'applications/metamta/typeahead/PhabricatorMetaMTAMailableDatasource.php', 'PhabricatorMetaMTAMailableDatasource' => 'applications/metamta/typeahead/PhabricatorMetaMTAMailableDatasource.php',
'PhabricatorMetaMTAMailableFunctionDatasource' => 'applications/metamta/typeahead/PhabricatorMetaMTAMailableFunctionDatasource.php', 'PhabricatorMetaMTAMailableFunctionDatasource' => 'applications/metamta/typeahead/PhabricatorMetaMTAMailableFunctionDatasource.php',
'PhabricatorMetaMTAMailgunReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php', 'PhabricatorMetaMTAMailgunReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php',
@ -5754,10 +5758,14 @@ phutil_register_library_map(array(
), ),
'PhabricatorMetaMTAMailBody' => 'Phobject', 'PhabricatorMetaMTAMailBody' => 'Phobject',
'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTAMailHasRecipientEdgeType' => 'PhabricatorEdgeType',
'PhabricatorMetaMTAMailListController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAMailPHIDType' => 'PhabricatorPHIDType', 'PhabricatorMetaMTAMailPHIDType' => 'PhabricatorPHIDType',
'PhabricatorMetaMTAMailQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorMetaMTAMailQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorMetaMTAMailSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorMetaMTAMailSection' => 'Phobject', 'PhabricatorMetaMTAMailSection' => 'Phobject',
'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTAMailViewController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAMailableDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorMetaMTAMailableDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'PhabricatorMetaMTAMailableFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorMetaMTAMailableFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'PhabricatorMetaMTAMailgunReceiveController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAMailgunReceiveController' => 'PhabricatorMetaMTAController',

View file

@ -37,6 +37,9 @@ final class PhabricatorMetaMTAApplication extends PhabricatorApplication {
public function getRoutes() { public function getRoutes() {
return array( return array(
'/mail/' => array( '/mail/' => array(
'(query/(?P<queryKey>[^/]+)/)?' =>
'PhabricatorMetaMTAMailListController',
'detail/(?P<id>[1-9]\d*)/' => 'PhabricatorMetaMTAMailViewController',
'sendgrid/' => 'PhabricatorMetaMTASendGridReceiveController', 'sendgrid/' => 'PhabricatorMetaMTASendGridReceiveController',
'mailgun/' => 'PhabricatorMetaMTAMailgunReceiveController', 'mailgun/' => 'PhabricatorMetaMTAMailgunReceiveController',
), ),

View file

@ -0,0 +1,30 @@
<?php
final class PhabricatorMetaMTAMailListController
extends PhabricatorMetaMTAController {
public function handleRequest(AphrontRequest $request) {
$controller = id(new PhabricatorApplicationSearchController())
->setQueryKey($request->getURIData('queryKey'))
->setSearchEngine(new PhabricatorMetaMTAMailSearchEngine())
->setNavigation($this->buildSideNav());
return $this->delegateToController($controller);
}
public function buildSideNav() {
$user = $this->getRequest()->getUser();
$nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
id(new PhabricatorMetaMTAMailSearchEngine())
->setViewer($user)
->addNavigationItems($nav->getMenu());
$nav->selectFilter(null);
return $nav;
}
}

View file

@ -0,0 +1,10 @@
<?php
final class PhabricatorMetaMTAMailViewController
extends PhabricatorMetaMTAController {
public function handleRequest(AphrontRequest $request) {
// TODO
}
}

View file

@ -0,0 +1,8 @@
<?php
final class PhabricatorMetaMTAMailHasRecipientEdgeType
extends PhabricatorEdgeType {
const EDGECONST = 57;
}

View file

@ -5,6 +5,8 @@ final class PhabricatorMetaMTAMailQuery
private $ids; private $ids;
private $phids; private $phids;
private $actorPHIDs;
private $recipientPHIDs;
public function withIDs(array $ids) { public function withIDs(array $ids) {
$this->ids = $ids; $this->ids = $ids;
@ -16,6 +18,16 @@ final class PhabricatorMetaMTAMailQuery
return $this; return $this;
} }
public function withActorPHIDs(array $phids) {
$this->actorPHIDs = $phids;
return $this;
}
public function withRecipientPHIDs(array $phids) {
$this->recipientPHIDs = $phids;
return $this;
}
protected function loadPage() { protected function loadPage() {
return $this->loadStandardPage($this->newResultObject()); return $this->loadStandardPage($this->newResultObject());
} }
@ -37,11 +49,53 @@ final class PhabricatorMetaMTAMailQuery
$this->phids); $this->phids);
} }
if ($this->actorPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'mail.actorPHID IN (%Ls)',
$this->actorPHIDs);
}
if ($this->recipientPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'recipient.dst IN (%Ls)',
$this->recipientPHIDs);
}
$viewer = $this->getViewer();
$where[] = qsprintf(
$conn_r,
'edge.dst = %s OR actorPHID = %s',
$viewer->getPHID(),
$viewer->getPHID());
$where[] = $this->buildPagingClause($conn_r); $where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where); return $this->formatWhereClause($where);
} }
protected function buildJoinClause(AphrontDatabaseConnection $conn) {
$joins = array();
$joins[] = qsprintf(
$conn,
'LEFT JOIN %T edge ON mail.phid = edge.src AND edge.type = %d',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorMetaMTAMailHasRecipientEdgeType::EDGECONST);
if ($this->recipientPHIDs !== null) {
$joins[] = qsprintf(
$conn,
'LEFT JOIN %T recipient '.
'ON mail.phid = recipient.src AND recipient.type = %d',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorMetaMTAMailHasRecipientEdgeType::EDGECONST);
}
return implode(' ', $joins);
}
protected function getPrimaryTableAlias() { protected function getPrimaryTableAlias() {
return 'mail'; return 'mail';
} }

View file

@ -0,0 +1,112 @@
<?php
final class PhabricatorMetaMTAMailSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('MetaMTA Mails');
}
public function getApplicationClassName() {
return 'PhabricatorMetaMTAApplication';
}
public function newQuery() {
return new PhabricatorMetaMTAMailQuery();
}
protected function shouldShowOrderField() {
return false;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchUsersField())
->setLabel(pht('Actors'))
->setKey('actorPHIDs')
->setAliases(array('actor', 'actors')),
id(new PhabricatorSearchUsersField())
->setLabel(pht('Recipients'))
->setKey('recipientPHIDs')
->setAliases(array('recipient', 'recipients')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['actorPHIDs']) {
$query->withActorPHIDs($map['actorPHIDs']);
}
if ($map['recipientPHIDs']) {
$query->withRecipientPHIDs($map['recipientPHIDs']);
}
return $query;
}
protected function getURI($path) {
return '/mail/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'inbox' => pht('Inbox'),
'outbox' => pht('Outbox'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$viewer = $this->requireViewer();
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'inbox':
return $query->setParameter(
'recipientPHIDs',
array($viewer->getPHID()));
case 'outbox':
return $query->setParameter(
'actorPHIDs',
array($viewer->getPHID()));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $objects,
PhabricatorSavedQuery $query) {
$phids = array();
foreach ($objects as $mail) {
$phids[] = $mail->getExpandedRecipientPHIDs();
}
return array_mergev($phids);
}
protected function renderResultList(
array $mails,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($mails, 'PhabricatorMetaMTAMail');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
foreach ($mails as $mail) {
$header = pht('Mail %d: TODO.', $mail->getID());
$item = id(new PHUIObjectItemView())
->setHeader($header);
$list->addItem($item);
}
return $list;
}
}

View file

@ -366,9 +366,20 @@ final class PhabricatorMetaMTAMail
// method. // method.
$this->openTransaction(); $this->openTransaction();
// Save to generate a task ID. // Save to generate a mail ID and PHID.
$result = parent::save(); $result = parent::save();
// Write the recipient edges.
$editor = new PhabricatorEdgeEditor();
$edge_type = PhabricatorMetaMTAMailHasRecipientEdgeType::EDGECONST;
$actor_phids = array_unique(array_merge(
$this->getAllActorPHIDs(),
$this->getExpandedRecipientPHIDs()));
foreach ($actor_phids as $actor_phid) {
$editor->addEdge($this->getPHID(), $edge_type, $actor_phid);
}
$editor->save();
// Queue a task to send this mail. // Queue a task to send this mail.
$mailer_task = PhabricatorWorker::scheduleTask( $mailer_task = PhabricatorWorker::scheduleTask(
'PhabricatorMetaMTAWorker', 'PhabricatorMetaMTAWorker',
@ -813,11 +824,15 @@ final class PhabricatorMetaMTAMail
} }
public function loadAllActors() { public function loadAllActors() {
$actor_phids = $this->getAllActorPHIDs(); $actor_phids = $this->getExpandedRecipientPHIDs();
$actor_phids = $this->expandRecipients($actor_phids);
return $this->loadActors($actor_phids); return $this->loadActors($actor_phids);
} }
public function getExpandedRecipientPHIDs() {
$actor_phids = $this->getAllActorPHIDs();
return $this->expandRecipients($actor_phids);
}
private function getAllActorPHIDs() { private function getAllActorPHIDs() {
return array_merge( return array_merge(
array($this->getParam('from')), array($this->getParam('from')),
@ -1025,8 +1040,7 @@ final class PhabricatorMetaMTAMail
} }
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
$actor_phids = $this->getAllActorPHIDs(); $actor_phids = $this->getExpandedRecipientPHIDs();
$actor_phids = $this->expandRecipients($actor_phids);
return in_array($viewer->getPHID(), $actor_phids); return in_array($viewer->getPHID(), $actor_phids);
} }