1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-18 18:51:12 +01:00

Implement ApplicationSearch in People

Summary:
Ref T2625. Fixes T2812. Implement ApplicationSearch in People.

{F44788}

Test Plan: Made People queries. Used Conduit. Used `@mentions`.

Reviewers: btrahan, chad

Reviewed By: chad

CC: aran

Maniphest Tasks: T2625, T2812

Differential Revision: https://secure.phabricator.com/D6092
This commit is contained in:
epriestley 2013-05-31 10:51:20 -07:00
parent 3aae972406
commit 59cea9bfc3
12 changed files with 368 additions and 101 deletions

View file

@ -1255,7 +1255,8 @@ phutil_register_library_map(array(
'PhabricatorPeopleListController' => 'applications/people/controller/PhabricatorPeopleListController.php', 'PhabricatorPeopleListController' => 'applications/people/controller/PhabricatorPeopleListController.php',
'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php', 'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php',
'PhabricatorPeopleProfileController' => 'applications/people/controller/PhabricatorPeopleProfileController.php', 'PhabricatorPeopleProfileController' => 'applications/people/controller/PhabricatorPeopleProfileController.php',
'PhabricatorPeopleQuery' => 'applications/people/PhabricatorPeopleQuery.php', 'PhabricatorPeopleQuery' => 'applications/people/query/PhabricatorPeopleQuery.php',
'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php',
'PhabricatorPeopleTestDataGenerator' => 'applications/people/lipsum/PhabricatorPeopleTestDataGenerator.php', 'PhabricatorPeopleTestDataGenerator' => 'applications/people/lipsum/PhabricatorPeopleTestDataGenerator.php',
'PhabricatorPhabricatorOAuthConfigOptions' => 'applications/config/option/PhabricatorPhabricatorOAuthConfigOptions.php', 'PhabricatorPhabricatorOAuthConfigOptions' => 'applications/config/option/PhabricatorPhabricatorOAuthConfigOptions.php',
'PhabricatorPhameConfigOptions' => 'applications/phame/config/PhabricatorPhameConfigOptions.php', 'PhabricatorPhameConfigOptions' => 'applications/phame/config/PhabricatorPhameConfigOptions.php',
@ -3052,10 +3053,15 @@ phutil_register_library_map(array(
'PhabricatorPeopleEditController' => 'PhabricatorPeopleController', 'PhabricatorPeopleEditController' => 'PhabricatorPeopleController',
'PhabricatorPeopleHovercardEventListener' => 'PhutilEventListener', 'PhabricatorPeopleHovercardEventListener' => 'PhutilEventListener',
'PhabricatorPeopleLdapController' => 'PhabricatorPeopleController', 'PhabricatorPeopleLdapController' => 'PhabricatorPeopleController',
'PhabricatorPeopleListController' => 'PhabricatorPeopleController', 'PhabricatorPeopleListController' =>
array(
0 => 'PhabricatorPeopleController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController', 'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController',
'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController', 'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController',
'PhabricatorPeopleQuery' => 'PhabricatorOffsetPagedQuery', 'PhabricatorPeopleQuery' => 'PhabricatorPolicyAwareCursorPagedQuery',
'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorPeopleTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorPeopleTestDataGenerator' => 'PhabricatorTestDataGenerator',
'PhabricatorPhabricatorOAuthConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPhabricatorOAuthConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPhameConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPhameConfigOptions' => 'PhabricatorApplicationConfigOptions',
@ -3307,6 +3313,7 @@ phutil_register_library_map(array(
array( array(
0 => 'PhabricatorUserDAO', 0 => 'PhabricatorUserDAO',
1 => 'PhutilPerson', 1 => 'PhutilPerson',
2 => 'PhabricatorPolicyInterface',
), ),
'PhabricatorUserDAO' => 'PhabricatorLiskDAO', 'PhabricatorUserDAO' => 'PhabricatorLiskDAO',
'PhabricatorUserEditor' => 'PhabricatorEditor', 'PhabricatorUserEditor' => 'PhabricatorEditor',

View file

@ -285,9 +285,10 @@ EOBODY;
return null; return null;
} }
$user = head(id(new PhabricatorPeopleQuery()) $user = id(new PhabricatorPeopleQuery())
->withPhids(array($handle->getPHID())) ->setViewer(PhabricatorUser::getOmnipotentUser())
->execute()); ->withPHIDs(array($handle->getPHID()))
->executeOne();
$receiver = $this->getMailReceiver(); $receiver = $this->getMailReceiver();
$receiver_id = $receiver->getID(); $receiver_id = $receiver->getID();

View file

@ -23,7 +23,7 @@ final class PhabricatorApplicationPeople extends PhabricatorApplication {
} }
public function getApplicationGroup() { public function getApplicationGroup() {
return self::GROUP_ADMIN; return self::GROUP_ORGANIZATION;
} }
public function canUninstall() { public function canUninstall() {
@ -39,7 +39,7 @@ final class PhabricatorApplicationPeople extends PhabricatorApplication {
public function getRoutes() { public function getRoutes() {
return array( return array(
'/people/' => array( '/people/' => array(
'' => 'PhabricatorPeopleListController', '(query/(?P<key>[^/]+)/)?' => 'PhabricatorPeopleListController',
'logs/' => 'PhabricatorPeopleLogsController', 'logs/' => 'PhabricatorPeopleLogsController',
'edit/(?:(?P<id>[1-9]\d*)/(?:(?P<view>\w+)/)?)?' 'edit/(?:(?P<id>[1-9]\d*)/(?:(?P<view>\w+)/)?)?'
=> 'PhabricatorPeopleEditController', => 'PhabricatorPeopleEditController',

View file

@ -44,6 +44,8 @@ final class ConduitAPI_user_query_Method
$limit = $request->getValue('limit', 100); $limit = $request->getValue('limit', 100);
$query = new PhabricatorPeopleQuery(); $query = new PhabricatorPeopleQuery();
$query->setViewer($request->getUser());
if ($usernames) { if ($usernames) {
$query->withUsernames($usernames); $query->withUsernames($usernames);
} }

View file

@ -10,18 +10,21 @@ abstract class PhabricatorPeopleController extends PhabricatorController {
$nav = new AphrontSideNavFilterView(); $nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI($this->getApplicationURI())); $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
$nav->addLabel(pht('User Administration')); $viewer = $this->getRequest()->getUser();
$nav->addFilter('edit', pht('Create New User'));
if (PhabricatorEnv::getEnvConfig('ldap.auth-enabled') === true) { id(new PhabricatorPeopleSearchEngine())
$nav->addFilter('ldap', pht('Import from LDAP')); ->setViewer($viewer)
->addNavigationItems($nav->getMenu());
if ($viewer->getIsAdmin()) {
$nav->addLabel(pht('User Administration'));
if (PhabricatorEnv::getEnvConfig('ldap.auth-enabled') === true) {
$nav->addFilter('ldap', pht('Import from LDAP'));
}
$nav->addFilter('logs', pht('Activity Logs'));
} }
$nav->addFilter('people',
pht('User Directory'),
$this->getApplicationURI());
$nav->addFilter('logs', pht('Activity Logs'));
return $nav; return $nav;
} }
@ -32,11 +35,15 @@ abstract class PhabricatorPeopleController extends PhabricatorController {
public function buildApplicationCrumbs() { public function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs(); $crumbs = parent::buildApplicationCrumbs();
$crumbs->addAction( $viewer = $this->getRequest()->getUser();
id(new PhabricatorMenuItemView())
->setName(pht('Create New User')) if ($viewer->getIsAdmin()) {
->setHref($this->getApplicationURI('edit')) $crumbs->addAction(
->setIcon('create')); id(new PhabricatorMenuItemView())
->setName(pht('Create New User'))
->setHref($this->getApplicationURI('edit'))
->setIcon('create'));
}
return $crumbs; return $crumbs;
} }

View file

@ -1,29 +1,37 @@
<?php <?php
final class PhabricatorPeopleListController final class PhabricatorPeopleListController extends PhabricatorPeopleController
extends PhabricatorPeopleController { implements PhabricatorApplicationSearchResultsControllerInterface {
private $key;
public function shouldAllowPublic() {
return true;
}
public function shouldRequireAdmin() {
return false;
}
public function willProcessRequest(array $data) {
$this->key = idx($data, 'key', 'all');
}
public function processRequest() { public function processRequest() {
$request = $this->getRequest();
$controller = id(new PhabricatorApplicationSearchController($request))
->setQueryKey($this->key)
->setSearchEngine(new PhabricatorPeopleSearchEngine())
->setNavigation($this->buildSideNavView());
return $this->delegateToController($controller);
}
public function renderResultsList(array $users) {
assert_instances_of($users, 'PhabricatorUser');
$request = $this->getRequest(); $request = $this->getRequest();
$viewer = $request->getUser(); $viewer = $request->getUser();
$is_admin = $viewer->getIsAdmin();
$user = new PhabricatorUser();
$count = queryfx_one(
$user->establishConnection('r'),
'SELECT COUNT(*) N FROM %T',
$user->getTableName());
$count = idx($count, 'N', 0);
$pager = new AphrontPagerView();
$pager->setOffset($request->getInt('page', 0));
$pager->setCount($count);
$pager->setURI($request->getRequestURI(), 'page');
$users = id(new PhabricatorPeopleQuery())
->needPrimaryEmail(true)
->executeWithOffsetPager($pager);
$list = new PhabricatorObjectItemListView(); $list = new PhabricatorObjectItemListView();
@ -40,7 +48,7 @@ final class PhabricatorPeopleListController
$item = new PhabricatorObjectItemView(); $item = new PhabricatorObjectItemView();
$item->setHeader($user->getFullName()) $item->setHeader($user->getFullName())
->setHref('/people/edit/'.$user->getID().'/') ->setHref('/p/'.$user->getUsername().'/')
->addAttribute(hsprintf('%s %s', ->addAttribute(hsprintf('%s %s',
phabricator_date($user->getDateCreated(), $viewer), phabricator_date($user->getDateCreated(), $viewer),
phabricator_time($user->getDateCreated(), $viewer))) phabricator_time($user->getDateCreated(), $viewer)))
@ -58,31 +66,17 @@ final class PhabricatorPeopleListController
$item->addIcon('computer', pht('System Agent')); $item->addIcon('computer', pht('System Agent'));
} }
if ($viewer->getIsAdmin()) {
$uid = $user->getID();
$item->addAction(
id(new PhabricatorMenuItemView())
->setIcon('edit')
->setHref($this->getApplicationURI('edit/'.$uid.'/')));
}
$list->addItem($item); $list->addItem($item);
} }
$header = new PhabricatorHeaderView(); return $list;
$header->setHeader(pht('People (%d)', number_format($count)));
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('User Directory'))
->setHref('/people/'));
$nav = $this->buildSideNavView();
$nav->selectFilter('people');
$nav->appendChild($header);
$nav->appendChild($list);
$nav->appendChild($pager);
$nav->setCrumbs($crumbs);
return $this->buildApplicationPage(
$nav,
array(
'title' => pht('People'),
'device' => true,
'dust' => true,
));
} }
} }

View file

@ -1,37 +1,79 @@
<?php <?php
final class PhabricatorPeopleQuery extends PhabricatorOffsetPagedQuery { final class PhabricatorPeopleQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $usernames; private $usernames;
private $realnames; private $realnames;
private $emails; private $emails;
private $phids; private $phids;
private $ids; private $ids;
private $dateCreatedAfter;
private $dateCreatedBefore;
private $isAdmin;
private $isSystemAgent;
private $isDisabled;
private $nameLike;
private $needPrimaryEmail; private $needPrimaryEmail;
private $needProfile; private $needProfile;
private $needProfileImage; private $needProfileImage;
public function withIds(array $ids) { public function withIDs(array $ids) {
$this->ids = $ids; $this->ids = $ids;
return $this; return $this;
} }
public function withPhids(array $phids) {
public function withPHIDs(array $phids) {
$this->phids = $phids; $this->phids = $phids;
return $this; return $this;
} }
public function withEmails(array $emails) { public function withEmails(array $emails) {
$this->emails = $emails; $this->emails = $emails;
return $this; return $this;
} }
public function withRealnames(array $realnames) { public function withRealnames(array $realnames) {
$this->realnames = $realnames; $this->realnames = $realnames;
return $this; return $this;
} }
public function withUsernames(array $usernames) { public function withUsernames(array $usernames) {
$this->usernames = $usernames; $this->usernames = $usernames;
return $this; return $this;
} }
public function withDateCreatedBefore($date_created_before) {
$this->dateCreatedBefore = $date_created_before;
return $this;
}
public function withDateCreatedAfter($date_created_after) {
$this->dateCreatedAfter = $date_created_after;
return $this;
}
public function withIsAdmin($admin) {
$this->isAdmin = $admin;
return $this;
}
public function withIsSystemAgent($system_agent) {
$this->isSystemAgent = $system_agent;
return $this;
}
public function withIsDisabled($disabled) {
$this->isDisabled = $disabled;
return $this;
}
public function withNameLike($like) {
$this->nameLike = $like;
return $this;
}
public function needPrimaryEmail($need) { public function needPrimaryEmail($need) {
$this->needPrimaryEmail = $need; $this->needPrimaryEmail = $need;
return $this; return $this;
@ -47,21 +89,18 @@ final class PhabricatorPeopleQuery extends PhabricatorOffsetPagedQuery {
return $this; return $this;
} }
public function execute() { public function loadPage() {
$table = new PhabricatorUser(); $table = new PhabricatorUser();
$conn_r = $table->establishConnection('r'); $conn_r = $table->establishConnection('r');
$joins_clause = $this->buildJoinsClause($conn_r);
$where_clause = $this->buildWhereClause($conn_r);
$limit_clause = $this->buildLimitClause($conn_r);
$data = queryfx_all( $data = queryfx_all(
$conn_r, $conn_r,
'SELECT * FROM %T user %Q %Q %Q', 'SELECT * FROM %T user %Q %Q %Q %Q',
$table->getTableName(), $table->getTableName(),
$joins_clause, $this->buildJoinsClause($conn_r),
$where_clause, $this->buildWhereClause($conn_r),
$limit_clause); $this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
if ($this->needPrimaryEmail) { if ($this->needPrimaryEmail) {
$table->putInSet(new LiskDAOSet()); $table->putInSet(new LiskDAOSet());
@ -88,9 +127,10 @@ final class PhabricatorPeopleQuery extends PhabricatorOffsetPagedQuery {
} }
if ($this->needProfileImage) { if ($this->needProfileImage) {
// Change this once we migrate this to CursorPagedPolicyAwareQuery $files = id(new PhabricatorFileQuery())
$files = id(new PhabricatorFile()) ->setViewer($this->getViewer())
->loadAllWhere('phid IN (%Ls)', mpull($users, 'getProfileImagePHID')); ->withPHIDs(mpull($users, 'getProfileImagePHID'))
->execute();
$files = mpull($files, null, 'getPHID'); $files = mpull($files, null, 'getPHID');
foreach ($users as $user) { foreach ($users as $user) {
$image_phid = $user->getProfileImagePHID(); $image_phid = $user->getProfileImagePHID();
@ -125,29 +165,78 @@ final class PhabricatorPeopleQuery extends PhabricatorOffsetPagedQuery {
$where = array(); $where = array();
if ($this->usernames) { if ($this->usernames) {
$where[] = qsprintf($conn_r, $where[] = qsprintf(
'user.userName IN (%Ls)', $conn_r,
$this->usernames); 'user.userName IN (%Ls)',
$this->usernames);
} }
if ($this->emails) { if ($this->emails) {
$where[] = qsprintf($conn_r, $where[] = qsprintf(
'email.address IN (%Ls)', $conn_r,
$this->emails); 'email.address IN (%Ls)',
$this->emails);
} }
if ($this->realnames) { if ($this->realnames) {
$where[] = qsprintf($conn_r, $where[] = qsprintf(
'user.realName IN (%Ls)', $conn_r,
$this->realnames); 'user.realName IN (%Ls)',
$this->realnames);
} }
if ($this->phids) { if ($this->phids) {
$where[] = qsprintf($conn_r, $where[] = qsprintf(
'user.phid IN (%Ls)', $conn_r,
$this->phids); 'user.phid IN (%Ls)',
$this->phids);
} }
if ($this->ids) { if ($this->ids) {
$where[] = qsprintf($conn_r, $where[] = qsprintf(
'user.id IN (%Ld)', $conn_r,
$this->ids); 'user.id IN (%Ld)',
$this->ids);
}
if ($this->dateCreatedAfter) {
$where[] = qsprintf(
$conn_r,
'user.dateCreated >= %d',
$this->dateCreatedAfter);
}
if ($this->dateCreatedBefore) {
$where[] = qsprintf(
$conn_r,
'user.dateCreated <= %d',
$this->dateCreatedBefore);
}
if ($this->isAdmin) {
$where[] = qsprintf(
$conn_r,
'user.isAdmin = 1');
}
if ($this->isDisabled) {
$where[] = qsprintf(
$conn_r,
'user.isDisabled = 1');
}
if ($this->isSystemAgent) {
$where[] = qsprintf(
$conn_r,
'user.isSystemAgent = 1');
}
if (strlen($this->nameLike)) {
$where[] = qsprintf(
$conn_r,
'user.username LIKE %~ OR user.realname LIKE %~',
$this->nameLike,
$this->nameLike);
} }
return $this->formatWhereClause($where); return $this->formatWhereClause($where);

View file

@ -0,0 +1,137 @@
<?php
final class PhabricatorPeopleSearchEngine
extends PhabricatorApplicationSearchEngine {
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter('usernames', $request->getStrList('usernames'));
$saved->setParameter('nameLike', $request->getStr('nameLike'));
$saved->setParameter('isAdmin', $request->getStr('isAdmin'));
$saved->setParameter('isDisabled', $request->getStr('isDisabled'));
$saved->setParameter('isSystemAgent', $request->getStr('isSystemAgent'));
$saved->setParameter('createdStart', $request->getStr('createdStart'));
$saved->setParameter('createdEnd', $request->getStr('createdEnd'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhabricatorPeopleQuery())
->needPrimaryEmail(true);
$usernames = $saved->getParameter('usernames', array());
if ($usernames) {
$query->withUsernames($usernames);
}
$like = $saved->getParameter('nameLike');
if ($like) {
$query->withNameLike($like);
}
$is_admin = $saved->getParameter('isAdmin');
$is_disabled = $saved->getParameter('isDisabled');
$is_system_agent = $saved->getParameter('isSystemAgent');
if ($is_admin) {
$query->withIsAdmin(true);
}
if ($is_disabled) {
$query->withIsDisabled(true);
}
if ($is_system_agent) {
$query->withIsSystemAgent(true);
}
$start = $this->parseDateTime($saved->getParameter('createdStart'));
$end = $this->parseDateTime($saved->getParameter('createdEnd'));
if ($start) {
$query->withDateCreatedAfter($start);
}
if ($end) {
$query->withDateCreatedBefore($end);
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved) {
$usernames = $saved->getParameter('usernames', array());
$like = $saved->getParameter('nameLike');
$is_admin = $saved->getParameter('isAdmin');
$is_disabled = $saved->getParameter('isDisabled');
$is_system_agent = $saved->getParameter('isSystemAgent');
$form
->appendChild(
id(new AphrontFormTextControl())
->setName('usernames')
->setLabel(pht('Usernames'))
->setValue(implode(', ', $usernames)))
->appendChild(
id(new AphrontFormTextControl())
->setName('nameLike')
->setLabel(pht('Name Contains'))
->setValue($like))
->appendChild(
id(new AphrontFormCheckboxControl())
->setLabel('Role')
->addCheckbox(
'isAdmin',
1,
pht('Show only Administrators.'),
$is_admin)
->addCheckbox(
'isDisabled',
1,
pht('Show only disabled users.'),
$is_disabled)
->addCheckbox(
'isSystemAgent',
1,
pht('Show only System Agents.'),
$is_system_agent));
$this->buildDateRange(
$form,
$saved,
'createdStart',
pht('Joined After'),
'createdEnd',
pht('Joined Before'));
}
protected function getURI($path) {
return '/people/'.$path;
}
public function getBuiltinQueryNames() {
$names = array(
'all' => pht('All'),
);
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

@ -71,6 +71,7 @@ final class PhabricatorRemarkupRuleMention
$usernames = array_keys($metadata); $usernames = array_keys($metadata);
$users = id(new PhabricatorPeopleQuery()) $users = id(new PhabricatorPeopleQuery())
->setViewer($this->getEngine()->getConfig('viewer'))
->withUsernames($usernames) ->withUsernames($usernames)
->execute(); ->execute();

View file

@ -1,6 +1,8 @@
<?php <?php
final class PhabricatorUser extends PhabricatorUserDAO implements PhutilPerson { final class PhabricatorUser
extends PhabricatorUserDAO
implements PhutilPerson, PhabricatorPolicyInterface {
const SESSION_TABLE = 'phabricator_session'; const SESSION_TABLE = 'phabricator_session';
const NAMETOKEN_TABLE = 'user_nametoken'; const NAMETOKEN_TABLE = 'user_nametoken';
@ -729,4 +731,29 @@ EOBODY;
return $user; return $user;
} }
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return PhabricatorPolicies::POLICY_PUBLIC;
case PhabricatorPolicyCapability::CAN_EDIT:
return PhabricatorPolicies::POLICY_NOONE;
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return $this->getPHID() && ($viewer->getPHID() === $this->getPHID());
}
} }

View file

@ -142,7 +142,7 @@ final class PhabricatorApplicationSearchController
$submit = id(new AphrontFormSubmitControl()) $submit = id(new AphrontFormSubmitControl())
->setValue(pht('Execute Query')); ->setValue(pht('Execute Query'));
if ($run_query && !$named_query) { if ($run_query && !$named_query && $user->isLoggedIn()) {
$submit->addCancelButton( $submit->addCancelButton(
'/search/edit/'.$saved_query->getQueryKey().'/', '/search/edit/'.$saved_query->getQueryKey().'/',
pht('Save Custom Query...')); pht('Save Custom Query...'));

View file

@ -125,8 +125,10 @@ abstract class PhabricatorApplicationSearchEngine {
$menu->newLink($query->getQueryName(), $uri, 'query/'.$key); $menu->newLink($query->getQueryName(), $uri, 'query/'.$key);
} }
$manage_uri = $this->getQueryManagementURI(); if ($viewer->isLoggedIn()) {
$menu->newLink(pht('Edit Queries...'), $manage_uri, 'query/edit'); $manage_uri = $this->getQueryManagementURI();
$menu->newLink(pht('Edit Queries...'), $manage_uri, 'query/edit');
}
$menu->newLabel(pht('Search')); $menu->newLabel(pht('Search'));
$advanced_uri = $this->getQueryResultsPageURI('advanced'); $advanced_uri = $this->getQueryResultsPageURI('advanced');