diff --git a/src/applications/maniphest/query/ManiphestTaskSearchEngine.php b/src/applications/maniphest/query/ManiphestTaskSearchEngine.php --- a/src/applications/maniphest/query/ManiphestTaskSearchEngine.php +++ b/src/applications/maniphest/query/ManiphestTaskSearchEngine.php @@ -43,129 +43,152 @@ ->needProjectPHIDs(true); } - public function buildSavedQueryFromRequest(AphrontRequest $request) { - $saved = new PhabricatorSavedQuery(); + public function buildCustomSearchFields() { + return array( + id(new PhabricatorSearchOwnersField()) + ->setLabel(pht('Assigned To')) + ->setKey('assignedPHIDs') + ->setAliases(array('assigned')), + id(new PhabricatorSearchUsersField()) + ->setLabel(pht('Authors')) + ->setKey('authorPHIDs') + ->setAliases(array('author', 'authors')), + id(new PhabricatorSearchDatasourceField()) + ->setLabel(pht('Statuses')) + ->setKey('statuses') + ->setAliases(array('status')) + ->setDatasource(new ManiphestTaskStatusFunctionDatasource()), + id(new PhabricatorSearchDatasourceField()) + ->setLabel(pht('Priorities')) + ->setKey('priorities') + ->setAliases(array('priority')) + ->setDatasource(new ManiphestTaskPriorityDatasource()), + id(new PhabricatorSearchTextField()) + ->setLabel(pht('Contains Words')) + ->setKey('fulltext'), + id(new PhabricatorSearchThreeStateField()) + ->setLabel(pht('Blocking')) + ->setKey('blocking') + ->setOptions( + pht('(Show All)'), + pht('Show Only Tasks Blocking Other Tasks'), + pht('Hide Tasks Blocking Other Tasks')), + id(new PhabricatorSearchThreeStateField()) + ->setLabel(pht('Blocked')) + ->setKey('blocked') + ->setOptions( + pht('(Show All)'), + pht('Show Only Task Blocked By Other Tasks'), + pht('Hide Tasks Blocked By Other Tasks')), + id(new PhabricatorSearchSelectField()) + ->setLabel(pht('Group By')) + ->setKey('group') + ->setOptions($this->getGroupOptions()), + id(new PhabricatorSearchStringListField()) + ->setLabel(pht('Task IDs')) + ->setKey('ids'), + id(new PhabricatorSearchDateField()) + ->setLabel(pht('Created After')) + ->setKey('createdStart'), + id(new PhabricatorSearchDateField()) + ->setLabel(pht('Created Before')) + ->setKey('createdEnd'), + id(new PhabricatorSearchDateField()) + ->setLabel(pht('Updated After')) + ->setKey('modifiedStart'), + id(new PhabricatorSearchDateField()) + ->setLabel(pht('Updated Before')) + ->setKey('modifiedEnd'), + id(new PhabricatorSearchTextField()) + ->setLabel(pht('Page Size')) + ->setKey('limit'), + ); + } - $saved->setParameter( + public function getDefaultFieldOrder() { + return array( 'assignedPHIDs', - $this->readUsersFromRequest($request, 'assigned')); - - $saved->setParameter( + 'projectPHIDs', 'authorPHIDs', - $this->readUsersFromRequest($request, 'authors')); - - $saved->setParameter( 'subscriberPHIDs', - $this->readSubscribersFromRequest($request, 'subscribers')); - - $saved->setParameter( 'statuses', - $this->readListFromRequest($request, 'statuses')); - - $saved->setParameter( 'priorities', - $this->readListFromRequest($request, 'priorities')); - - $saved->setParameter( + 'fulltext', 'blocking', - $this->readBoolFromRequest($request, 'blocking')); - $saved->setParameter( 'blocked', - $this->readBoolFromRequest($request, 'blocked')); - - $saved->setParameter('group', $request->getStr('group')); - $saved->setParameter('order', $request->getStr('order')); - - $ids = $request->getStrList('ids'); - foreach ($ids as $key => $id) { - $id = trim($id, ' Tt'); - if (!$id || !is_numeric($id)) { - unset($ids[$key]); - } else { - $ids[$key] = $id; - } - } - $saved->setParameter('ids', $ids); - - $saved->setParameter('fulltext', $request->getStr('fulltext')); - - $saved->setParameter( - 'projects', - $this->readProjectsFromRequest($request, 'projects')); + 'group', + 'order', + 'ids', + '...', + 'createdStart', + 'createdEnd', + 'modifiedStart', + 'modifiedEnd', + 'limit', + ); + } - $saved->setParameter('createdStart', $request->getStr('createdStart')); - $saved->setParameter('createdEnd', $request->getStr('createdEnd')); - $saved->setParameter('modifiedStart', $request->getStr('modifiedStart')); - $saved->setParameter('modifiedEnd', $request->getStr('modifiedEnd')); + public function getHiddenFields() { + $keys = array(); - $limit = $request->getInt('limit'); - if ($limit > 0) { - $saved->setParameter('limit', $limit); + if ($this->getIsBoardView()) { + $keys[] = 'group'; + $keys[] = 'order'; + $keys[] = 'limit'; } - $this->readCustomFieldsFromRequest($request, $saved); - - return $saved; + return $keys; } - public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { - $query = $this->newQuery(); + public function buildQueryFromParameters(array $map) { + $query = id(new ManiphestTaskQuery()) + ->needProjectPHIDs(true); - $viewer = $this->requireViewer(); + if ($map['assignedPHIDs']) { + $query->withOwners($map['assignedPHIDs']); + } - $datasource = id(new PhabricatorPeopleUserFunctionDatasource()) - ->setViewer($viewer); + if ($map['authorPHIDs']) { + $query->withAuthors($map['authorPHIDs']); + } - $author_phids = $saved->getParameter('authorPHIDs', array()); - $author_phids = $datasource->evaluateTokens($author_phids); - if ($author_phids) { - $query->withAuthors($author_phids); + if ($map['statuses']) { + $query->withStatuses($map['statuses']); } - $datasource = id(new PhabricatorMetaMTAMailableFunctionDatasource()) - ->setViewer($viewer); - $subscriber_phids = $saved->getParameter('subscriberPHIDs', array()); - $subscriber_phids = $datasource->evaluateTokens($subscriber_phids); - if ($subscriber_phids) { - $query->withSubscribers($subscriber_phids); + if ($map['priorities']) { + $query->withPriorities($map['priorities']); } - $datasource = id(new PhabricatorPeopleOwnerDatasource()) - ->setViewer($this->requireViewer()); + if ($map['createdStart']) { + $query->withDateCreatedAfter($map['createdStart']); + } - $assigned_phids = $this->readAssignedPHIDs($saved); - $assigned_phids = $datasource->evaluateTokens($assigned_phids); - if ($assigned_phids) { - $query->withOwners($assigned_phids); + if ($map['createdEnd']) { + $query->withDateCreatedBefore($map['createdEnd']); } - $datasource = id(new ManiphestTaskStatusFunctionDatasource()) - ->setViewer($this->requireViewer()); - $statuses = $saved->getParameter('statuses', array()); - $statuses = $datasource->evaluateTokens($statuses); - if ($statuses) { - $query->withStatuses($statuses); + if ($map['modifiedStart']) { + $query->withDateModifiedAfter($map['modifiedStart']); } - $priorities = $saved->getParameter('priorities', array()); - if ($priorities) { - $query->withPriorities($priorities); + if ($map['modifiedEnd']) { + $query->withDateModifiedBefore($map['modifiedEnd']); } + if ($map['blocking'] !== null) { + $query->withBlockingTasks($map['blocking']); + } - $query->withBlockingTasks($saved->getParameter('blocking')); - $query->withBlockedTasks($saved->getParameter('blocked')); + if ($map['blocked'] !== null) { + $query->withBlockedTasks($map['blocked']); + } - // TODO: This is glue that will be obsolete soon. - $order = $saved->getParameter('order'); - $builtin = $query->getBuiltinOrderAliasMap(); - if (strlen($order) && isset($builtin[$order])) { - $query->setOrder($order); - } else { - $query->setOrder(head_key($builtin)); + if (strlen($map['fulltext'])) { + $query->withFullTextSearch($map['fulltext']); } - $group = $saved->getParameter('group'); + $group = idx($map, 'group'); $group = idx($this->getGroupValues(), $group); if ($group) { $query->setGroupBy($group); @@ -173,181 +196,25 @@ $query->setGroupBy(head($this->getGroupValues())); } - $ids = $saved->getParameter('ids'); - if ($ids) { - $query->withIDs($ids); - } - - $fulltext = $saved->getParameter('fulltext'); - if (strlen($fulltext)) { - $query->withFullTextSearch($fulltext); - } - - $projects = $this->readProjectTokens($saved); - $adjusted = id(clone $saved)->setParameter('projects', $projects); - $this->setQueryProjects($query, $adjusted); - - $start = $this->parseDateTime($saved->getParameter('createdStart')); - $end = $this->parseDateTime($saved->getParameter('createdEnd')); - - if ($start) { - $query->withDateCreatedAfter($start); - } - - if ($end) { - $query->withDateCreatedBefore($end); - } - - $mod_start = $this->parseDateTime($saved->getParameter('modifiedStart')); - $mod_end = $this->parseDateTime($saved->getParameter('modifiedEnd')); - - if ($mod_start) { - $query->withDateModifiedAfter($mod_start); - } + if ($map['ids']) { + $ids = $map['ids']; + foreach ($ids as $key => $id) { + $id = trim($id, ' Tt'); + if (!$id || !is_numeric($id)) { + unset($ids[$key]); + } else { + $ids[$key] = $id; + } + } - if ($mod_end) { - $query->withDateModifiedBefore($mod_end); + if ($ids) { + $query->withIDs($ids); + } } - $this->applyCustomFieldsToQuery($query, $saved); - return $query; } - public function buildSearchForm( - AphrontFormView $form, - PhabricatorSavedQuery $saved) { - - $assigned_phids = $this->readAssignedPHIDs($saved); - - $author_phids = $saved->getParameter('authorPHIDs', array()); - $projects = $this->readProjectTokens($saved); - - $subscriber_phids = $saved->getParameter('subscriberPHIDs', array()); - - $statuses = $saved->getParameter('statuses', array()); - $priorities = $saved->getParameter('priorities', array()); - - $blocking_control = id(new AphrontFormSelectControl()) - ->setLabel(pht('Blocking')) - ->setName('blocking') - ->setValue($this->getBoolFromQuery($saved, 'blocking')) - ->setOptions(array( - '' => pht('Show All Tasks'), - 'true' => pht('Show Tasks Blocking Other Tasks'), - 'false' => pht('Show Tasks Not Blocking Other Tasks'), - )); - - $blocked_control = id(new AphrontFormSelectControl()) - ->setLabel(pht('Blocked')) - ->setName('blocked') - ->setValue($this->getBoolFromQuery($saved, 'blocked')) - ->setOptions(array( - '' => pht('Show All Tasks'), - 'true' => pht('Show Tasks Blocked By Other Tasks'), - 'false' => pht('Show Tasks Not Blocked By Other Tasks'), - )); - - $ids = $saved->getParameter('ids', array()); - - $all_orders = ipull($this->newQuery()->getBuiltinOrders(), 'name'); - - $form - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setDatasource(new PhabricatorPeopleOwnerDatasource()) - ->setName('assigned') - ->setLabel(pht('Assigned To')) - ->setValue($assigned_phids)) - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setDatasource(new PhabricatorProjectLogicalDatasource()) - ->setName('projects') - ->setLabel(pht('Projects')) - ->setValue($projects)) - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setDatasource(new PhabricatorPeopleUserFunctionDatasource()) - ->setName('authors') - ->setLabel(pht('Authors')) - ->setValue($author_phids)) - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setDatasource(new PhabricatorMetaMTAMailableFunctionDatasource()) - ->setName('subscribers') - ->setLabel(pht('Subscribers')) - ->setValue($subscriber_phids)) - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setDatasource(new ManiphestTaskStatusFunctionDatasource()) - ->setLabel(pht('Statuses')) - ->setName('statuses') - ->setValue($statuses)) - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setDatasource(new ManiphestTaskPriorityDatasource()) - ->setLabel(pht('Priorities')) - ->setName('priorities') - ->setValue($priorities)) - ->appendChild( - id(new AphrontFormTextControl()) - ->setName('fulltext') - ->setLabel(pht('Contains Words')) - ->setValue($saved->getParameter('fulltext'))) - ->appendChild($blocking_control) - ->appendChild($blocked_control); - - if (!$this->getIsBoardView()) { - $form - ->appendChild( - id(new AphrontFormSelectControl()) - ->setName('group') - ->setLabel(pht('Group By')) - ->setValue($saved->getParameter('group')) - ->setOptions($this->getGroupOptions())) - ->appendChild( - id(new AphrontFormSelectControl()) - ->setName('order') - ->setLabel(pht('Order By')) - ->setValue($saved->getParameter('order')) - ->setOptions($all_orders)); - } - - $form - ->appendChild( - id(new AphrontFormTextControl()) - ->setName('ids') - ->setLabel(pht('Task IDs')) - ->setValue(implode(', ', $ids))); - - $this->appendCustomFieldsToForm($form, $saved); - - $this->buildDateRange( - $form, - $saved, - 'createdStart', - pht('Created After'), - 'createdEnd', - pht('Created Before')); - - $this->buildDateRange( - $form, - $saved, - 'modifiedStart', - pht('Updated After'), - 'modifiedEnd', - pht('Updated Before')); - - if (!$this->getIsBoardView()) { - $form - ->appendChild( - id(new AphrontFormTextControl()) - ->setName('limit') - ->setLabel(pht('Page Size')) - ->setValue($saved->getParameter('limit', 100))); - } - } - protected function getURI($path) { if ($this->baseURI) { return $this->baseURI.$path; @@ -458,48 +325,52 @@ ->setShowBatchControls($this->showBatchControls); } - private function readAssignedPHIDs(PhabricatorSavedQuery $saved) { - $assigned_phids = $saved->getParameter('assignedPHIDs', array()); + protected function willUseSavedQuery(PhabricatorSavedQuery $saved) { - // This may be present in old saved queries from before parameterized - // typeaheads, and is retained for compatibility. We could remove it by - // migrating old saved queries. + // The 'withUnassigned' parameter may be present in old saved queries from + // before parameterized typeaheads, and is retained for compatibility. We + // could remove it by migrating old saved queries. + $assigned_phids = $saved->getParameter('assignedPHIDs', array()); if ($saved->getParameter('withUnassigned')) { $assigned_phids[] = PhabricatorPeopleNoOwnerDatasource::FUNCTION_TOKEN; } + $saved->setParameter('assignedPHIDs', $assigned_phids); - return $assigned_phids; - } + // The 'projects' and other parameters may be present in old saved queries + // from before parameterized typeaheads. + $project_phids = $saved->getParameter('projectPHIDs', array()); - private function readProjectTokens(PhabricatorSavedQuery $saved) { - $projects = $saved->getParameter('projects', array()); + $old = $saved->getParameter('projects', array()); + foreach ($old as $phid) { + $project_phids[] = $phid; + } $all = $saved->getParameter('allProjectPHIDs', array()); foreach ($all as $phid) { - $projects[] = $phid; + $project_phids[] = $phid; } $any = $saved->getParameter('anyProjectPHIDs', array()); foreach ($any as $phid) { - $projects[] = 'any('.$phid.')'; + $project_phids[] = 'any('.$phid.')'; } $not = $saved->getParameter('excludeProjectPHIDs', array()); foreach ($not as $phid) { - $projects[] = 'not('.$phid.')'; + $project_phids[] = 'not('.$phid.')'; } $users = $saved->getParameter('userProjectPHIDs', array()); foreach ($users as $phid) { - $projects[] = 'projects('.$phid.')'; + $project_phids[] = 'projects('.$phid.')'; } $no = $saved->getParameter('withNoProject'); if ($no) { - $projects[] = 'null()'; + $project_phids[] = 'null()'; } - return $projects; + $saved->setParameter('projectPHIDs', $project_phids); } } 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 @@ -205,6 +205,7 @@ $this->willUseSavedQuery($saved); $fields = $this->buildSearchFields(); + $fields = $this->adjustFieldsForDisplay($fields); $viewer = $this->requireViewer(); foreach ($fields as $field) { @@ -266,7 +267,7 @@ $orders = ipull($orders, 'name'); $fields[] = id(new PhabricatorSearchOrderField()) - ->setLabel(pht('Order')) + ->setLabel(pht('Order By')) ->setKey('order') ->setOptions($orders); } @@ -284,7 +285,7 @@ $field_map[$key] = $field; } - return $this->adjustFieldsForDisplay($field_map); + return $field_map; } private function adjustFieldsForDisplay(array $field_map) { @@ -310,7 +311,13 @@ $body = array_diff_key($field_map, array_fuse($tail_keys)); $tail = array_select_keys($field_map, $tail_keys); - return $head + $body + $tail; + $result = $head + $body + $tail; + + foreach ($this->getHiddenFields() as $hidden_key) { + unset($result[$hidden_key]); + } + + return $result; } protected function buildCustomSearchFields() { @@ -346,6 +353,15 @@ return array(); } + /** + * Return a list of field keys which should be hidden from the viewer. + * + * @return list Fields to hide. + */ + protected function getHiddenFields() { + return array(); + } + public function getErrors() { return $this->errors; } @@ -924,7 +940,13 @@ public function getPageSize(PhabricatorSavedQuery $saved) { - return $saved->getParameter('limit', 100); + $limit = (int)$saved->getParameter('limit'); + + if ($limit > 0) { + return $limit; + } + + return 100; } @@ -1062,33 +1084,6 @@ /** - * Moves data from the request into a saved query. - * - * @param AphrontRequest Request to read. - * @param PhabricatorSavedQuery Query to write to. - * @return void - * @task appsearch - */ - protected function readCustomFieldsFromRequest( - AphrontRequest $request, - PhabricatorSavedQuery $saved) { - - $list = $this->getCustomFieldList(); - if (!$list) { - return; - } - - foreach ($list->getFields() as $field) { - $key = $this->getKeyForCustomField($field); - $value = $field->readApplicationSearchValueFromRequest( - $this, - $request); - $saved->setParameter($key, $value); - } - } - - - /** * Applies data from a saved query to an executable query. * * @param PhabricatorCursorPagedPolicyAwareQuery Query to constrain. @@ -1105,24 +1100,13 @@ } foreach ($list->getFields() as $field) { - $key = $this->getKeyForCustomField($field); $value = $field->applyApplicationSearchConstraintToQuery( $this, $query, - $saved->getParameter($key)); + $saved->getParameter('custom:'.$field->getFieldIndex())); } } - /** - * Get a unique key identifying a field. - * - * @param PhabricatorCustomField Field to identify. - * @return string Unique identifier, suitable for use as an input name. - */ - public function getKeyForCustomField(PhabricatorCustomField $field) { - return 'custom:'.$field->getFieldIndex(); - } - private function buildCustomFieldSearchFields() { $list = $this->getCustomFieldList(); if (!$list) { @@ -1135,24 +1119,8 @@ ->setSearchEngine($this) ->setCustomField($field); } - return $fields; - } - - // TODO: Remove. - protected function appendCustomFieldsToForm( - AphrontFormView $form, - PhabricatorSavedQuery $saved) { - - $list = $this->getCustomFieldList(); - if (!$list) { - return; - } - foreach ($list->getFields() as $field) { - $key = $this->getKeyForCustomField($field); - $value = $saved->getParameter($key); - $field->appendToApplicationSearchForm($this, $form, $value); - } + return $fields; } }