Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15453653
D18426.id44277.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
18 KB
Referenced Files
None
Subscribers
None
D18426.id44277.diff
View Options
diff --git a/src/applications/search/application/PhabricatorSearchApplication.php b/src/applications/search/application/PhabricatorSearchApplication.php
--- a/src/applications/search/application/PhabricatorSearchApplication.php
+++ b/src/applications/search/application/PhabricatorSearchApplication.php
@@ -33,11 +33,18 @@
'index/(?P<phid>[^/]+)/' => 'PhabricatorSearchIndexController',
'hovercard/'
=> 'PhabricatorSearchHovercardController',
- 'edit/(?P<queryKey>[^/]+)/' => 'PhabricatorSearchEditController',
+ 'edit/' => array(
+ 'key/(?P<queryKey>[^/]+)/' => 'PhabricatorSearchEditController',
+ 'id/(?P<id>[^/]+)/' => 'PhabricatorSearchEditController',
+ ),
'default/(?P<queryKey>[^/]+)/(?P<engine>[^/]+)/'
=> 'PhabricatorSearchDefaultController',
- 'delete/(?P<queryKey>[^/]+)/(?P<engine>[^/]+)/'
- => 'PhabricatorSearchDeleteController',
+ 'delete/' => array(
+ 'key/(?P<queryKey>[^/]+)/(?P<engine>[^/]+)/'
+ => 'PhabricatorSearchDeleteController',
+ 'id/(?P<id>[^/]+)/'
+ => 'PhabricatorSearchDeleteController',
+ ),
'order/(?P<engine>[^/]+)/' => 'PhabricatorSearchOrderController',
'rel/(?P<relationshipKey>[^/]+)/(?P<sourcePHID>[^/]+)/'
=> 'PhabricatorSearchRelationshipController',
diff --git a/src/applications/search/controller/PhabricatorApplicationSearchController.php b/src/applications/search/controller/PhabricatorApplicationSearchController.php
--- a/src/applications/search/controller/PhabricatorApplicationSearchController.php
+++ b/src/applications/search/controller/PhabricatorApplicationSearchController.php
@@ -174,7 +174,7 @@
if ($run_query && !$named_query && $user->isLoggedIn()) {
$save_button = id(new PHUIButtonView())
->setTag('a')
- ->setHref('/search/edit/'.$saved_query->getQueryKey().'/')
+ ->setHref('/search/edit/key/'.$saved_query->getQueryKey().'/')
->setText(pht('Save Query'))
->setIcon('fa-floppy-o');
$submit->addButton($save_button);
@@ -377,7 +377,7 @@
private function processEditRequest() {
$parent = $this->getDelegatingController();
$request = $this->getRequest();
- $user = $request->getUser();
+ $viewer = $request->getUser();
$engine = $this->getSearchEngine();
$nav = $this->getNavigation();
@@ -387,21 +387,89 @@
$named_queries = $engine->loadAllNamedQueries();
- $list_id = celerity_generate_unique_node_id();
+ $can_global = $viewer->getIsAdmin();
+
+ $groups = array(
+ 'personal' => array(
+ 'name' => pht('Personal Saved Queries'),
+ 'items' => array(),
+ 'edit' => true,
+ ),
+ 'global' => array(
+ 'name' => pht('Global Saved Queries'),
+ 'items' => array(),
+ 'edit' => $can_global,
+ ),
+ );
- $list = new PHUIObjectItemListView();
- $list->setUser($user);
- $list->setID($list_id);
+ foreach ($named_queries as $named_query) {
+ if ($named_query->isGlobal()) {
+ $group = 'global';
+ } else {
+ $group = 'personal';
+ }
- Javelin::initBehavior(
- 'search-reorder-queries',
- array(
- 'listID' => $list_id,
- 'orderURI' => '/search/order/'.get_class($engine).'/',
- ));
+ $groups[$group]['items'][] = $named_query;
+ }
$default_key = $engine->getDefaultQueryKey();
+ $lists = array();
+ foreach ($groups as $group) {
+ $lists[] = $this->newQueryListView(
+ $group['name'],
+ $group['items'],
+ $default_key,
+ $group['edit']);
+ }
+
+ $crumbs = $parent
+ ->buildApplicationCrumbs()
+ ->addTextCrumb(pht('Saved Queries'), $engine->getQueryManagementURI())
+ ->setBorder(true);
+
+ $nav->selectFilter('query/edit');
+
+ $header = id(new PHUIHeaderView())
+ ->setHeader(pht('Saved Queries'))
+ ->setProfileHeader(true);
+
+ $view = id(new PHUITwoColumnView())
+ ->setHeader($header)
+ ->setFooter($lists);
+
+ return $this->newPage()
+ ->setApplicationMenu($this->buildApplicationMenu())
+ ->setTitle(pht('Saved Queries'))
+ ->setCrumbs($crumbs)
+ ->setNavigation($nav)
+ ->appendChild($view);
+ }
+
+ private function newQueryListView(
+ $list_name,
+ array $named_queries,
+ $default_key,
+ $can_edit) {
+
+ $engine = $this->getSearchEngine();
+ $viewer = $this->getViewer();
+
+ $list = id(new PHUIObjectItemListView())
+ ->setViewer($viewer);
+
+ if ($can_edit) {
+ $list_id = celerity_generate_unique_node_id();
+ $list->setID($list_id);
+
+ Javelin::initBehavior(
+ 'search-reorder-queries',
+ array(
+ 'listID' => $list_id,
+ 'orderURI' => '/search/order/'.get_class($engine).'/',
+ ));
+ }
+
foreach ($named_queries as $named_query) {
$class = get_class($engine);
$key = $named_query->getQueryKey();
@@ -410,25 +478,43 @@
->setHeader($named_query->getQueryName())
->setHref($engine->getQueryResultsPageURI($key));
- if ($named_query->getIsBuiltin() && $named_query->getIsDisabled()) {
- $icon = 'fa-plus';
- $disable_name = pht('Enable');
- } else {
- $icon = 'fa-times';
- if ($named_query->getIsBuiltin()) {
- $disable_name = pht('Disable');
+ if ($named_query->getIsDisabled()) {
+ if ($can_edit) {
+ $item->setDisabled(true);
} else {
- $disable_name = pht('Delete');
+ // If an item is disabled and you don't have permission to edit it,
+ // just skip it.
+ continue;
}
}
- $item->addAction(
- id(new PHUIListItemView())
- ->setIcon($icon)
- ->setHref('/search/delete/'.$key.'/'.$class.'/')
- ->setRenderNameAsTooltip(true)
- ->setName($disable_name)
- ->setWorkflow(true));
+ if ($can_edit) {
+ if ($named_query->getIsBuiltin() && $named_query->getIsDisabled()) {
+ $icon = 'fa-plus';
+ $disable_name = pht('Enable');
+ } else {
+ $icon = 'fa-times';
+ if ($named_query->getIsBuiltin()) {
+ $disable_name = pht('Disable');
+ } else {
+ $disable_name = pht('Delete');
+ }
+ }
+
+ if ($named_query->getID()) {
+ $disable_href = '/search/delete/id/'.$named_query->getID().'/';
+ } else {
+ $disable_href = '/search/delete/key/'.$key.'/'.$class.'/';
+ }
+
+ $item->addAction(
+ id(new PHUIListItemView())
+ ->setIcon($icon)
+ ->setHref($disable_href)
+ ->setRenderNameAsTooltip(true)
+ ->setName($disable_name)
+ ->setWorkflow(true));
+ }
$default_disabled = $named_query->getIsDisabled();
$default_icon = 'fa-thumb-tack';
@@ -448,31 +534,29 @@
->setWorkflow(true)
->setDisabled($default_disabled));
- if ($named_query->getIsBuiltin()) {
- $edit_icon = 'fa-lock lightgreytext';
- $edit_disabled = true;
- $edit_name = pht('Builtin');
- $edit_href = null;
- } else {
- $edit_icon = 'fa-pencil';
- $edit_disabled = false;
- $edit_name = pht('Edit');
- $edit_href = '/search/edit/'.$key.'/';
- }
-
- $item->addAction(
- id(new PHUIListItemView())
- ->setIcon($edit_icon)
- ->setHref($edit_href)
- ->setRenderNameAsTooltip(true)
- ->setName($edit_name)
- ->setDisabled($edit_disabled));
+ if ($can_edit) {
+ if ($named_query->getIsBuiltin()) {
+ $edit_icon = 'fa-lock lightgreytext';
+ $edit_disabled = true;
+ $edit_name = pht('Builtin');
+ $edit_href = null;
+ } else {
+ $edit_icon = 'fa-pencil';
+ $edit_disabled = false;
+ $edit_name = pht('Edit');
+ $edit_href = '/search/edit/id/'.$named_query->getID().'/';
+ }
- if ($named_query->getIsDisabled()) {
- $item->setDisabled(true);
+ $item->addAction(
+ id(new PHUIListItemView())
+ ->setIcon($edit_icon)
+ ->setHref($edit_href)
+ ->setRenderNameAsTooltip(true)
+ ->setName($edit_name)
+ ->setDisabled($edit_disabled));
}
- $item->setGrippable(true);
+ $item->setGrippable($can_edit);
$item->addSigil('named-query');
$item->setMetadata(
array(
@@ -484,31 +568,10 @@
$list->setNoDataString(pht('No saved queries.'));
- $crumbs = $parent
- ->buildApplicationCrumbs()
- ->addTextCrumb(pht('Saved Queries'), $engine->getQueryManagementURI())
- ->setBorder(true);
-
- $nav->selectFilter('query/edit');
-
- $header = id(new PHUIHeaderView())
- ->setHeader(pht('Saved Queries'))
- ->setProfileHeader(true);
-
- $box = id(new PHUIObjectBoxView())
- ->setHeader($header)
- ->setObjectList($list)
- ->addClass('application-search-results');
-
- $nav->addClass('application-search-view');
- require_celerity_resource('application-search-view-css');
-
- return $this->newPage()
- ->setApplicationMenu($this->buildApplicationMenu())
- ->setTitle(pht('Saved Queries'))
- ->setCrumbs($crumbs)
- ->setNavigation($nav)
- ->appendChild($box);
+ return id(new PHUIObjectBoxView())
+ ->setHeaderText($list_name)
+ ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
+ ->setObjectList($list);
}
public function buildApplicationMenu() {
diff --git a/src/applications/search/controller/PhabricatorSearchDefaultController.php b/src/applications/search/controller/PhabricatorSearchDefaultController.php
--- a/src/applications/search/controller/PhabricatorSearchDefaultController.php
+++ b/src/applications/search/controller/PhabricatorSearchDefaultController.php
@@ -21,7 +21,11 @@
->setViewer($viewer)
->withEngineClassNames(array($engine_class))
->withQueryKeys(array($key))
- ->withUserPHIDs(array($viewer->getPHID()))
+ ->withUserPHIDs(
+ array(
+ $viewer->getPHID(),
+ PhabricatorNamedQuery::SCOPE_GLOBAL,
+ ))
->executeOne();
if (!$named_query && $engine->isBuiltinQuery($key)) {
diff --git a/src/applications/search/controller/PhabricatorSearchDeleteController.php b/src/applications/search/controller/PhabricatorSearchDeleteController.php
--- a/src/applications/search/controller/PhabricatorSearchDeleteController.php
+++ b/src/applications/search/controller/PhabricatorSearchDeleteController.php
@@ -5,30 +5,43 @@
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
- $key = $request->getURIData('queryKey');
- $engine_class = $request->getURIData('engine');
- $base_class = 'PhabricatorApplicationSearchEngine';
- if (!is_subclass_of($engine_class, $base_class)) {
- return new Aphront400Response();
- }
+ $id = $request->getURIData('id');
+ if ($id) {
+ $named_query = id(new PhabricatorNamedQueryQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$named_query) {
+ return new Aphront404Response();
+ }
- $engine = newv($engine_class, array());
- $engine->setViewer($viewer);
+ $engine = newv($named_query->getEngineClassName(), array());
+ $engine->setViewer($viewer);
- $named_query = id(new PhabricatorNamedQueryQuery())
- ->setViewer($viewer)
- ->withEngineClassNames(array($engine_class))
- ->withQueryKeys(array($key))
- ->withUserPHIDs(array($viewer->getPHID()))
- ->executeOne();
+ $key = $named_query->getQueryKey();
+ } else {
+ $key = $request->getURIData('queryKey');
+ $engine_class = $request->getURIData('engine');
- if (!$named_query && $engine->isBuiltinQuery($key)) {
- $named_query = $engine->getBuiltinQuery($key);
- }
+ $base_class = 'PhabricatorApplicationSearchEngine';
+ if (!is_subclass_of($engine_class, $base_class)) {
+ return new Aphront400Response();
+ }
+
+ $engine = newv($engine_class, array());
+ $engine->setViewer($viewer);
- if (!$named_query) {
- return new Aphront404Response();
+ if (!$engine->isBuiltinQuery($key)) {
+ return new Aphront404Response();
+ }
+
+ $named_query = $engine->getBuiltinQuery($key);
}
$builtin = null;
diff --git a/src/applications/search/controller/PhabricatorSearchEditController.php b/src/applications/search/controller/PhabricatorSearchEditController.php
--- a/src/applications/search/controller/PhabricatorSearchEditController.php
+++ b/src/applications/search/controller/PhabricatorSearchEditController.php
@@ -6,9 +6,30 @@
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
+ $id = $request->getURIData('id');
+ if ($id) {
+ $named_query = id(new PhabricatorNamedQueryQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$named_query) {
+ return new Aphront404Response();
+ }
+
+ $query_key = $named_query->getQueryKey();
+ } else {
+ $query_key = $request->getURIData('queryKey');
+ $named_query = null;
+ }
+
$saved_query = id(new PhabricatorSavedQueryQuery())
->setViewer($viewer)
- ->withQueryKeys(array($request->getURIData('queryKey')))
+ ->withQueryKeys(array($query_key))
->executeOne();
if (!$saved_query) {
return new Aphront404Response();
@@ -19,11 +40,6 @@
$complete_uri = $engine->getQueryManagementURI();
$cancel_uri = $complete_uri;
- $named_query = id(new PhabricatorNamedQueryQuery())
- ->setViewer($viewer)
- ->withQueryKeys(array($saved_query->getQueryKey()))
- ->withUserPHIDs(array($viewer->getPHID()))
- ->executeOne();
if (!$named_query) {
$named_query = id(new PhabricatorNamedQuery())
->setUserPHID($viewer->getPHID())
@@ -35,12 +51,27 @@
// management interface.
$cancel_uri = $engine->getQueryResultsPageURI(
$saved_query->getQueryKey());
+
+ $is_new = true;
+ } else {
+ $is_new = false;
}
+ $can_global = ($viewer->getIsAdmin() && $is_new);
+
+ $v_global = false;
+
$e_name = true;
$errors = array();
if ($request->isFormPost()) {
+ if ($can_global) {
+ $v_global = $request->getBool('global');
+ if ($v_global) {
+ $named_query->setUserPHID(PhabricatorNamedQuery::SCOPE_GLOBAL);
+ }
+ }
+
$named_query->setQueryName($request->getStr('name'));
if (!strlen($named_query->getQueryName())) {
$e_name = pht('Required');
@@ -50,6 +81,7 @@
}
if (!$errors) {
+
$named_query->save();
return id(new AphrontRedirectResponse())->setURI($complete_uri);
}
@@ -65,6 +97,18 @@
->setValue($named_query->getQueryName())
->setError($e_name));
+ if ($can_global) {
+ $form->appendChild(
+ id(new AphrontFormCheckboxControl())
+ ->addCheckbox(
+ 'global',
+ '1',
+ pht(
+ 'Save this query as a global query, making it visible to '.
+ 'all users.'),
+ $v_global));
+ }
+
$form->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Save Query'))
diff --git a/src/applications/search/engine/PhabricatorApplicationSearchEngine.php b/src/applications/search/engine/PhabricatorApplicationSearchEngine.php
--- a/src/applications/search/engine/PhabricatorApplicationSearchEngine.php
+++ b/src/applications/search/engine/PhabricatorApplicationSearchEngine.php
@@ -474,8 +474,12 @@
if ($this->namedQueries === null) {
$named_queries = id(new PhabricatorNamedQueryQuery())
->setViewer($viewer)
- ->withUserPHIDs(array($viewer->getPHID()))
->withEngineClassNames(array(get_class($this)))
+ ->withUserPHIDs(
+ array(
+ $viewer->getPHID(),
+ PhabricatorNamedQuery::SCOPE_GLOBAL,
+ ))
->execute();
$named_queries = mpull($named_queries, null, 'getQueryKey');
@@ -494,7 +498,7 @@
unset($builtin[$key]);
}
- $named_queries = msort($named_queries, 'getSortKey');
+ $named_queries = msortv($named_queries, 'getNamedQuerySortVector');
$this->namedQueries = $named_queries;
}
@@ -631,7 +635,7 @@
$sequence = 0;
foreach ($names as $key => $name) {
$queries[$key] = id(new PhabricatorNamedQuery())
- ->setUserPHID($this->requireViewer()->getPHID())
+ ->setUserPHID(PhabricatorNamedQuery::SCOPE_GLOBAL)
->setEngineClassName(get_class($this))
->setQueryName($name)
->setQueryKey($key)
diff --git a/src/applications/search/storage/PhabricatorNamedQuery.php b/src/applications/search/storage/PhabricatorNamedQuery.php
--- a/src/applications/search/storage/PhabricatorNamedQuery.php
+++ b/src/applications/search/storage/PhabricatorNamedQuery.php
@@ -12,6 +12,8 @@
protected $isDisabled = 0;
protected $sequence = 0;
+ const SCOPE_GLOBAL = 'scope.global';
+
protected function getConfiguration() {
return array(
self::CONFIG_COLUMN_SCHEMA => array(
@@ -31,8 +33,29 @@
) + parent::getConfiguration();
}
- public function getSortKey() {
- return sprintf('~%010d%010d', $this->sequence, $this->getID());
+ public function isGlobal() {
+ if ($this->getIsBuiltin()) {
+ return true;
+ }
+
+ if ($this->getUserPHID() === self::SCOPE_GLOBAL) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public function getNamedQuerySortVector() {
+ if (!$this->isGlobal()) {
+ $phase = 0;
+ } else {
+ $phase = 1;
+ }
+
+ return id(new PhutilSortVector())
+ ->addInt($phase)
+ ->addInt($this->sequence)
+ ->addInt($this->getID());
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
@@ -41,6 +64,7 @@
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
);
}
@@ -49,9 +73,19 @@
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
- if ($viewer->getPHID() == $this->userPHID) {
+ if ($viewer->getPHID() == $this->getUserPHID()) {
return true;
}
+
+ if ($this->isGlobal()) {
+ switch ($capability) {
+ case PhabricatorPolicyCapability::CAN_VIEW:
+ return true;
+ case PhabricatorPolicyCapability::CAN_EDIT:
+ return $viewer->getIsAdmin();
+ }
+ }
+
return false;
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 30, 1:25 PM (3 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7725229
Default Alt Text
D18426.id44277.diff (18 KB)
Attached To
Mode
D18426: Separate saved queries in applications into "personal" and "global" queries
Attached
Detach File
Event Timeline
Log In to Comment