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:
parent
de30e15b7e
commit
dfef8e2f07
8 changed files with 244 additions and 5 deletions
|
@ -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',
|
||||||
|
|
|
@ -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',
|
||||||
),
|
),
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorMetaMTAMailViewController
|
||||||
|
extends PhabricatorMetaMTAController {
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorMetaMTAMailHasRecipientEdgeType
|
||||||
|
extends PhabricatorEdgeType {
|
||||||
|
|
||||||
|
const EDGECONST = 57;
|
||||||
|
|
||||||
|
}
|
|
@ -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';
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue