1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 08:52:39 +01:00

Use application PHIDs for mailing lists

Summary:
Ref T2715. Ref T603. Ref T2625.

  - Implement policies.
  - Use policy queries.
  - Use ApplicationSearch.
  - Use application PHIDs.

Test Plan: Browsed things with lists CC'd; edited lists; created a list, used `phid.query` to query handles.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T603, T2625, T2715

Differential Revision: https://secure.phabricator.com/D6513
This commit is contained in:
epriestley 2013-07-21 10:42:07 -07:00
parent d2e5afb095
commit c5a06a624a
14 changed files with 259 additions and 122 deletions

View file

@ -1232,6 +1232,9 @@ phutil_register_library_map(array(
'PhabricatorMailReceiver' => 'applications/metamta/receiver/PhabricatorMailReceiver.php', 'PhabricatorMailReceiver' => 'applications/metamta/receiver/PhabricatorMailReceiver.php',
'PhabricatorMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorMailReceiverTestCase.php', 'PhabricatorMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorMailReceiverTestCase.php',
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php', 'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php',
'PhabricatorMailingListPHIDTypeList' => 'applications/mailinglists/phid/PhabricatorMailingListPHIDTypeList.php',
'PhabricatorMailingListQuery' => 'applications/mailinglists/query/PhabricatorMailingListQuery.php',
'PhabricatorMailingListSearchEngine' => 'applications/mailinglists/query/PhabricatorMailingListSearchEngine.php',
'PhabricatorMailingListsController' => 'applications/mailinglists/controller/PhabricatorMailingListsController.php', 'PhabricatorMailingListsController' => 'applications/mailinglists/controller/PhabricatorMailingListsController.php',
'PhabricatorMailingListsEditController' => 'applications/mailinglists/controller/PhabricatorMailingListsEditController.php', 'PhabricatorMailingListsEditController' => 'applications/mailinglists/controller/PhabricatorMailingListsEditController.php',
'PhabricatorMailingListsListController' => 'applications/mailinglists/controller/PhabricatorMailingListsListController.php', 'PhabricatorMailingListsListController' => 'applications/mailinglists/controller/PhabricatorMailingListsListController.php',
@ -3207,9 +3210,16 @@ phutil_register_library_map(array(
'PhabricatorMailManagementShowOutboundWorkflow' => 'PhabricatorSearchManagementWorkflow', 'PhabricatorMailManagementShowOutboundWorkflow' => 'PhabricatorSearchManagementWorkflow',
'PhabricatorMailManagementWorkflow' => 'PhutilArgumentWorkflow', 'PhabricatorMailManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase', 'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase',
'PhabricatorMailingListPHIDTypeList' => 'PhabricatorPHIDType',
'PhabricatorMailingListQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorMailingListSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorMailingListsController' => 'PhabricatorController', 'PhabricatorMailingListsController' => 'PhabricatorController',
'PhabricatorMailingListsEditController' => 'PhabricatorMailingListsController', 'PhabricatorMailingListsEditController' => 'PhabricatorMailingListsController',
'PhabricatorMailingListsListController' => 'PhabricatorMailingListsController', 'PhabricatorMailingListsListController' =>
array(
0 => 'PhabricatorMailingListsController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorMainMenuGroupView' => 'AphrontView', 'PhabricatorMainMenuGroupView' => 'AphrontView',
'PhabricatorMainMenuIconView' => 'AphrontView', 'PhabricatorMainMenuIconView' => 'AphrontView',
'PhabricatorMainMenuSearchView' => 'AphrontView', 'PhabricatorMainMenuSearchView' => 'AphrontView',
@ -3226,7 +3236,11 @@ phutil_register_library_map(array(
'PhabricatorMetaMTAMail' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTAMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTAMailingList' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTAMailingList' =>
array(
0 => 'PhabricatorMetaMTADAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception', 'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception',
'PhabricatorMetaMTAReceivedMailTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAReceivedMailTestCase' => 'PhabricatorTestCase',

View file

@ -25,7 +25,8 @@ final class PhabricatorApplicationMailingLists extends PhabricatorApplication {
public function getRoutes() { public function getRoutes() {
return array( return array(
'/mailinglists/' => array( '/mailinglists/' => array(
'' => 'PhabricatorMailingListsListController', '(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PhabricatorMailingListsListController',
'edit/(?:(?P<id>[1-9]\d*)/)?' 'edit/(?:(?P<id>[1-9]\d*)/)?'
=> 'PhabricatorMailingListsEditController', => 'PhabricatorMailingListsEditController',
), ),

View file

@ -2,24 +2,27 @@
abstract class PhabricatorMailingListsController extends PhabricatorController { abstract class PhabricatorMailingListsController extends PhabricatorController {
public function buildSideNavView($filter = null, $for_app = false) { public function buildSideNavView($for_app = false) {
$user = $this->getRequest()->getUser(); $user = $this->getRequest()->getUser();
$nav = new AphrontSideNavFilterView(); $nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI($this->getApplicationURI())); $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
$nav->addLabel(pht('Mailing Lists'));
$nav->addFilter('/', pht('All Lists'));
$nav->selectFilter($filter, '/');
if ($for_app) { if ($for_app) {
$nav->addFilter('edit/', pht('Create List')); $nav->addFilter('edit', pht('Create List'));
} }
id(new PhabricatorMailingListSearchEngine())
->setViewer($user)
->addNavigationItems($nav->getMenu());
$nav->selectFilter(null);
return $nav; return $nav;
} }
public function buildApplicationMenu() { public function buildApplicationMenu() {
return $this->buildSideNavView(null, true)->getMenu(); return $this->buildSideNavView(true)->getMenu();
} }
public function buildApplicationCrumbs() { public function buildApplicationCrumbs() {

View file

@ -10,9 +10,14 @@ final class PhabricatorMailingListsEditController
} }
public function processRequest() { public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
if ($this->id) { if ($this->id) {
$list = id(new PhabricatorMetaMTAMailingList())->load($this->id); $list = id(new PhabricatorMailingListQuery())
->setViewer($viewer)
->withIDs(array($this->id))
->executeOne();
if (!$list) { if (!$list) {
return new Aphront404Response(); return new Aphront404Response();
} }
@ -25,9 +30,8 @@ final class PhabricatorMailingListsEditController
$e_name = true; $e_name = true;
$errors = array(); $errors = array();
$crumbs = $this->buildApplicationCrumbs($this->buildSideNavView()); $crumbs = $this->buildApplicationCrumbs();
$request = $this->getRequest();
if ($request->isFormPost()) { if ($request->isFormPost()) {
$list->setName($request->getStr('name')); $list->setName($request->getStr('name'));
$list->setEmail($request->getStr('email')); $list->setEmail($request->getStr('email'));
@ -105,10 +109,6 @@ final class PhabricatorMailingListsEditController
->setError($e_uri) ->setError($e_uri)
->setCaption(pht('Optional link to mailing list archives or info.')) ->setCaption(pht('Optional link to mailing list archives or info.'))
->setValue($list->getURI())) ->setValue($list->getURI()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('PHID')
->setValue(nonempty($list->getPHID(), '-')))
->appendChild( ->appendChild(
id(new AphrontFormSubmitControl()) id(new AphrontFormSubmitControl())
->setValue(pht('Save')) ->setValue(pht('Save'))
@ -117,13 +117,11 @@ final class PhabricatorMailingListsEditController
if ($list->getID()) { if ($list->getID()) {
$crumbs->addCrumb( $crumbs->addCrumb(
id(new PhabricatorCrumbView()) id(new PhabricatorCrumbView())
->setName(pht('Edit Mailing List')) ->setName(pht('Edit Mailing List')));
->setHref($this->getApplicationURI('/edit/'.$list->getID().'/')));
} else { } else {
$crumbs->addCrumb( $crumbs->addCrumb(
id(new PhabricatorCrumbView()) id(new PhabricatorCrumbView())
->setName(pht('Create Mailing List')) ->setName(pht('Create Mailing List')));
->setHref($this->getApplicationURI('/edit/')));
} }
return $this->buildApplicationPage( return $this->buildApplicationPage(

View file

@ -1,84 +1,51 @@
<?php <?php
final class PhabricatorMailingListsListController final class PhabricatorMailingListsListController
extends PhabricatorMailingListsController { extends PhabricatorMailingListsController
implements PhabricatorApplicationSearchResultsControllerInterface {
private $queryKey;
public function shouldAllowPublic() {
return true;
}
public function willProcessRequest(array $data) {
$this->queryKey = idx($data, 'queryKey');
}
public function processRequest() { public function processRequest() {
$request = $this->getRequest(); $request = $this->getRequest();
$user = $request->getUser(); $controller = id(new PhabricatorApplicationSearchController($request))
$offset = $request->getInt('offset', 0); ->setQueryKey($this->queryKey)
->setSearchEngine(new PhabricatorMailingListSearchEngine())
->setNavigation($this->buildSideNavView());
$pager = new AphrontPagerView(); return $this->delegateToController($controller);
$pager->setPageSize(250); }
$pager->setOffset($offset);
$pager->setURI($request->getRequestURI(), 'offset');
$list = new PhabricatorMetaMTAMailingList(); public function renderResultsList(
$conn_r = $list->establishConnection('r'); array $lists,
$data = queryfx_all( PhabricatorSavedQuery $query) {
$conn_r, assert_instances_of($lists, 'PhabricatorMetaMTAMailingList');
'SELECT * FROM %T
ORDER BY name ASC
LIMIT %d, %d',
$list->getTableName(),
$pager->getOffset(), $pager->getPageSize() + 1);
$data = $pager->sliceResults($data);
$nav = $this->buildSideNavView('all'); $view = id(new PhabricatorObjectItemListView());
$lists = $list->loadAllFromArray($data);
$rows = array();
foreach ($lists as $list) { foreach ($lists as $list) {
$rows[] = array( $item = new PhabricatorObjectItemView();
$list->getName(),
$list->getEmail(), $item->setHeader($list->getName());
phutil_tag( $item->setHref($list->getURI());
'a', $item->addAttribute($list->getEmail());
array( $item->addAction(
'class' => 'button grey small', id(new PHUIListItemView())
'href' => $this->getApplicationURI('/edit/'.$list->getID().'/'), ->setIcon('edit')
), ->setHref($this->getApplicationURI('/edit/'.$list->getID().'/')));
pht('Edit')),
); $view->addItem($item);
} }
$table = new AphrontTableView($rows); return $view;
$table->setHeaders(
array(
pht('Name'),
pht('Email'),
'',
));
$table->setColumnClasses(
array(
null,
'wide',
'action',
));
$crumbs = $this->buildApplicationCrumbs($this->buildSideNavView());
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('All Lists'))
->setHref($this->getApplicationURI()));
$nav->setCrumbs($crumbs);
$panel = new AphrontPanelView();
$panel->appendChild($table);
$panel->setHeader(pht('Mailing Lists'));
$panel->appendChild($pager);
$panel->setNoBackground();
$nav->appendChild($panel);
return $this->buildApplicationPage(
array(
$nav,
),
array(
'title' => pht('Mailing Lists'),
'device' => true,
));
} }
} }

View file

@ -0,0 +1,46 @@
<?php
final class PhabricatorMailingListPHIDTypeList extends PhabricatorPHIDType {
const TYPECONST = 'MLST';
public function getTypeConstant() {
return self::TYPECONST;
}
public function getTypeName() {
return pht('Mailing List');
}
public function newObject() {
return new PhabricatorMetaMTAMailingList();
}
public function loadObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorMailingListQuery())
->setViewer($query->getViewer())
->withPHIDs($phids)
->execute();
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$list = $objects[$phid];
$handle->setName($list->getName());
$handle->setURI($list->getURI());
}
}
public function canLoadNamedObject($name) {
return false;
}
}

View file

@ -0,0 +1,56 @@
<?php
final class PhabricatorMailingListQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $phids;
private $ids;
public function withIDs($ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs($phids) {
$this->phids = $phids;
return $this;
}
public function loadPage() {
$table = new PhabricatorMetaMTAMailingList();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
}

View file

@ -0,0 +1,54 @@
<?php
final class PhabricatorMailingListSearchEngine
extends PhabricatorApplicationSearchEngine {
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhabricatorMailingListQuery());
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved_query) {
// This just makes it clear to the user that the lack of filters is
// intentional, not a bug.
$form->appendChild(
id(new AphrontFormMarkupControl())
->setValue(pht('No query filters are available for mailing lists.')));
}
protected function getURI($path) {
return '/mailinglists/'.$path;
}
public function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Lists'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
}

View file

@ -1,6 +1,7 @@
<?php <?php
final class PhabricatorMetaMTAMailingList extends PhabricatorMetaMTADAO { final class PhabricatorMetaMTAMailingList extends PhabricatorMetaMTADAO
implements PhabricatorPolicyInterface {
protected $name; protected $name;
protected $phid; protected $phid;
@ -9,7 +10,7 @@ final class PhabricatorMetaMTAMailingList extends PhabricatorMetaMTADAO {
public function generatePHID() { public function generatePHID() {
return PhabricatorPHID::generateNewPHID( return PhabricatorPHID::generateNewPHID(
PhabricatorPHIDConstants::PHID_TYPE_MLST); PhabricatorMailingListPHIDTypeList::TYPECONST);
} }
public function getConfiguration() { public function getConfiguration() {
@ -18,4 +19,22 @@ final class PhabricatorMetaMTAMailingList extends PhabricatorMetaMTADAO {
) + parent::getConfiguration(); ) + parent::getConfiguration();
} }
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
);
}
public function getPolicy($capability) {
return PhabricatorPolicies::POLICY_USER;
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
} }

View file

@ -28,6 +28,8 @@ final class PhabricatorMetaMTAActorQuery extends PhabricatorQuery {
$actors[$phid] = id(new PhabricatorMetaMTAActor())->setPHID($phid); $actors[$phid] = id(new PhabricatorMetaMTAActor())->setPHID($phid);
} }
// TODO: Move this to PhabricatorPHIDType.
foreach ($type_map as $type => $phids) { foreach ($type_map as $type => $phids) {
switch ($type) { switch ($type) {
case PhabricatorPHIDConstants::PHID_TYPE_USER: case PhabricatorPHIDConstants::PHID_TYPE_USER:
@ -36,7 +38,7 @@ final class PhabricatorMetaMTAActorQuery extends PhabricatorQuery {
case PhabricatorPHIDConstants::PHID_TYPE_XUSR: case PhabricatorPHIDConstants::PHID_TYPE_XUSR:
$this->loadExternalUserActors($actors, $phids); $this->loadExternalUserActors($actors, $phids);
break; break;
case PhabricatorPHIDConstants::PHID_TYPE_MLST: case PhabricatorMailingListPHIDTypeList::TYPECONST:
$this->loadMailingListActors($actors, $phids); $this->loadMailingListActors($actors, $phids);
break; break;
default: default:
@ -127,9 +129,10 @@ final class PhabricatorMetaMTAActorQuery extends PhabricatorQuery {
private function loadMailingListActors(array $actors, array $phids) { private function loadMailingListActors(array $actors, array $phids) {
assert_instances_of($actors, 'PhabricatorMetaMTAActor'); assert_instances_of($actors, 'PhabricatorMetaMTAActor');
$lists = id(new PhabricatorMetaMTAMailingList())->loadAllWhere( $lists = id(new PhabricatorMailingListQuery())
'phid IN (%Ls)', ->setViewer($this->getViewer())
$phids); ->withPHIDs($phids)
->execute();
$lists = mpull($lists, null, 'getPHID'); $lists = mpull($lists, null, 'getPHID');
foreach ($phids as $phid) { foreach ($phids as $phid) {

View file

@ -3,7 +3,6 @@
final class PhabricatorPHIDConstants { final class PhabricatorPHIDConstants {
const PHID_TYPE_USER = 'USER'; const PHID_TYPE_USER = 'USER';
const PHID_TYPE_MLST = 'MLST';
const PHID_TYPE_TASK = 'TASK'; const PHID_TYPE_TASK = 'TASK';
const PHID_TYPE_FILE = 'FILE'; const PHID_TYPE_FILE = 'FILE';
const PHID_TYPE_PROJ = 'PROJ'; const PHID_TYPE_PROJ = 'PROJ';

View file

@ -110,11 +110,6 @@ final class PhabricatorObjectHandleData {
$phids); $phids);
return mpull($projects, null, 'getPHID'); return mpull($projects, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_MLST:
$object = new PhabricatorMetaMTAMailingList();
$lists = $object->loadAllWhere('phid IN (%Ls)', $phids);
return mpull($lists, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_WIKI: case PhabricatorPHIDConstants::PHID_TYPE_WIKI:
// TODO: Update this to PhrictionDocumentQuery, already pre-package // TODO: Update this to PhrictionDocumentQuery, already pre-package
// content DAO // content DAO
@ -330,24 +325,6 @@ final class PhabricatorObjectHandleData {
} }
break; break;
case PhabricatorPHIDConstants::PHID_TYPE_MLST:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Mailing List');
} else {
$list = $objects[$phid];
$handle->setName($list->getName());
$handle->setURI($list->getURI());
$handle->setFullName($list->getName());
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_CMIT: case PhabricatorPHIDConstants::PHID_TYPE_CMIT:
foreach ($phids as $phid) { foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle(); $handle = new PhabricatorObjectHandle();

View file

@ -198,7 +198,9 @@ final class PhabricatorTypeaheadCommonDatasourceController
} }
if ($need_lists) { if ($need_lists) {
$lists = id(new PhabricatorMetaMTAMailingList())->loadAll(); $lists = id(new PhabricatorMailingListQuery())
->setViewer($viewer)
->execute();
foreach ($lists as $list) { foreach ($lists as $list) {
$results[] = id(new PhabricatorTypeaheadResult()) $results[] = id(new PhabricatorTypeaheadResult())
->setName($list->getName()) ->setName($list->getName())

View file

@ -159,8 +159,6 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
PhabricatorPHIDConstants::PHID_TYPE_FILE => 'PhabricatorFile', PhabricatorPHIDConstants::PHID_TYPE_FILE => 'PhabricatorFile',
PhabricatorPHIDConstants::PHID_TYPE_USER => 'PhabricatorUser', PhabricatorPHIDConstants::PHID_TYPE_USER => 'PhabricatorUser',
PhabricatorPHIDConstants::PHID_TYPE_PROJ => 'PhabricatorProject', PhabricatorPHIDConstants::PHID_TYPE_PROJ => 'PhabricatorProject',
PhabricatorPHIDConstants::PHID_TYPE_MLST =>
'PhabricatorMetaMTAMailingList',
PhabricatorPHIDConstants::PHID_TYPE_TOBJ => 'HarbormasterObject', PhabricatorPHIDConstants::PHID_TYPE_TOBJ => 'HarbormasterObject',
PhabricatorPHIDConstants::PHID_TYPE_BLOG => 'PhameBlog', PhabricatorPHIDConstants::PHID_TYPE_BLOG => 'PhameBlog',
PhabricatorPHIDConstants::PHID_TYPE_POST => 'PhamePost', PhabricatorPHIDConstants::PHID_TYPE_POST => 'PhamePost',