1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-09-20 09:18:48 +02: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',
'PhabricatorMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorMailReceiverTestCase.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',
'PhabricatorMailingListsEditController' => 'applications/mailinglists/controller/PhabricatorMailingListsEditController.php',
'PhabricatorMailingListsListController' => 'applications/mailinglists/controller/PhabricatorMailingListsListController.php',
@ -3207,9 +3210,16 @@ phutil_register_library_map(array(
'PhabricatorMailManagementShowOutboundWorkflow' => 'PhabricatorSearchManagementWorkflow',
'PhabricatorMailManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase',
'PhabricatorMailingListPHIDTypeList' => 'PhabricatorPHIDType',
'PhabricatorMailingListQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorMailingListSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorMailingListsController' => 'PhabricatorController',
'PhabricatorMailingListsEditController' => 'PhabricatorMailingListsController',
'PhabricatorMailingListsListController' => 'PhabricatorMailingListsController',
'PhabricatorMailingListsListController' =>
array(
0 => 'PhabricatorMailingListsController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorMainMenuGroupView' => 'AphrontView',
'PhabricatorMainMenuIconView' => 'AphrontView',
'PhabricatorMainMenuSearchView' => 'AphrontView',
@ -3226,7 +3236,11 @@ phutil_register_library_map(array(
'PhabricatorMetaMTAMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTAMailingList' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAMailingList' =>
array(
0 => 'PhabricatorMetaMTADAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception',
'PhabricatorMetaMTAReceivedMailTestCase' => 'PhabricatorTestCase',

View file

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

View file

@ -2,24 +2,27 @@
abstract class PhabricatorMailingListsController extends PhabricatorController {
public function buildSideNavView($filter = null, $for_app = false) {
public function buildSideNavView($for_app = false) {
$user = $this->getRequest()->getUser();
$nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
$nav->addLabel(pht('Mailing Lists'));
$nav->addFilter('/', pht('All Lists'));
$nav->selectFilter($filter, '/');
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;
}
public function buildApplicationMenu() {
return $this->buildSideNavView(null, true)->getMenu();
return $this->buildSideNavView(true)->getMenu();
}
public function buildApplicationCrumbs() {

View file

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

View file

@ -1,84 +1,51 @@
<?php
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() {
$request = $this->getRequest();
$user = $request->getUser();
$offset = $request->getInt('offset', 0);
$controller = id(new PhabricatorApplicationSearchController($request))
->setQueryKey($this->queryKey)
->setSearchEngine(new PhabricatorMailingListSearchEngine())
->setNavigation($this->buildSideNavView());
$pager = new AphrontPagerView();
$pager->setPageSize(250);
$pager->setOffset($offset);
$pager->setURI($request->getRequestURI(), 'offset');
return $this->delegateToController($controller);
}
$list = new PhabricatorMetaMTAMailingList();
$conn_r = $list->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T
ORDER BY name ASC
LIMIT %d, %d',
$list->getTableName(),
$pager->getOffset(), $pager->getPageSize() + 1);
$data = $pager->sliceResults($data);
public function renderResultsList(
array $lists,
PhabricatorSavedQuery $query) {
assert_instances_of($lists, 'PhabricatorMetaMTAMailingList');
$nav = $this->buildSideNavView('all');
$view = id(new PhabricatorObjectItemListView());
$lists = $list->loadAllFromArray($data);
$rows = array();
foreach ($lists as $list) {
$rows[] = array(
$list->getName(),
$list->getEmail(),
phutil_tag(
'a',
array(
'class' => 'button grey small',
'href' => $this->getApplicationURI('/edit/'.$list->getID().'/'),
),
pht('Edit')),
);
$item = new PhabricatorObjectItemView();
$item->setHeader($list->getName());
$item->setHref($list->getURI());
$item->addAttribute($list->getEmail());
$item->addAction(
id(new PHUIListItemView())
->setIcon('edit')
->setHref($this->getApplicationURI('/edit/'.$list->getID().'/')));
$view->addItem($item);
}
$table = new AphrontTableView($rows);
$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,
));
return $view;
}
}

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
final class PhabricatorMetaMTAMailingList extends PhabricatorMetaMTADAO {
final class PhabricatorMetaMTAMailingList extends PhabricatorMetaMTADAO
implements PhabricatorPolicyInterface {
protected $name;
protected $phid;
@ -9,7 +10,7 @@ final class PhabricatorMetaMTAMailingList extends PhabricatorMetaMTADAO {
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorPHIDConstants::PHID_TYPE_MLST);
PhabricatorMailingListPHIDTypeList::TYPECONST);
}
public function getConfiguration() {
@ -18,4 +19,22 @@ final class PhabricatorMetaMTAMailingList extends PhabricatorMetaMTADAO {
) + 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);
}
// TODO: Move this to PhabricatorPHIDType.
foreach ($type_map as $type => $phids) {
switch ($type) {
case PhabricatorPHIDConstants::PHID_TYPE_USER:
@ -36,7 +38,7 @@ final class PhabricatorMetaMTAActorQuery extends PhabricatorQuery {
case PhabricatorPHIDConstants::PHID_TYPE_XUSR:
$this->loadExternalUserActors($actors, $phids);
break;
case PhabricatorPHIDConstants::PHID_TYPE_MLST:
case PhabricatorMailingListPHIDTypeList::TYPECONST:
$this->loadMailingListActors($actors, $phids);
break;
default:
@ -127,9 +129,10 @@ final class PhabricatorMetaMTAActorQuery extends PhabricatorQuery {
private function loadMailingListActors(array $actors, array $phids) {
assert_instances_of($actors, 'PhabricatorMetaMTAActor');
$lists = id(new PhabricatorMetaMTAMailingList())->loadAllWhere(
'phid IN (%Ls)',
$phids);
$lists = id(new PhabricatorMailingListQuery())
->setViewer($this->getViewer())
->withPHIDs($phids)
->execute();
$lists = mpull($lists, null, 'getPHID');
foreach ($phids as $phid) {

View file

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

View file

@ -110,11 +110,6 @@ final class PhabricatorObjectHandleData {
$phids);
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:
// TODO: Update this to PhrictionDocumentQuery, already pre-package
// content DAO
@ -330,24 +325,6 @@ final class PhabricatorObjectHandleData {
}
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:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();

View file

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

View file

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