diff --git a/src/applications/maniphest/query/ManiphestTaskQuery.php b/src/applications/maniphest/query/ManiphestTaskQuery.php --- a/src/applications/maniphest/query/ManiphestTaskQuery.php +++ b/src/applications/maniphest/query/ManiphestTaskQuery.php @@ -403,23 +403,13 @@ $this->subpriorityMax); } - $where[] = $this->buildPagingClause($conn); + $where[] = $this->buildWhereClauseParts($conn); $where = $this->formatWhereClause($where); - $having = ''; $count = ''; - if (count($this->projectPHIDs) > 1) { - // We want to treat the query as an intersection query, not a union - // query. We sum the project count and require it be the same as the - // number of projects we're searching for. - $count = ', COUNT(project.dst) projectCount'; - $having = qsprintf( - $conn, - 'HAVING projectCount = %d', - count($this->projectPHIDs)); } $group_column = ''; @@ -433,14 +423,15 @@ $rows = queryfx_all( $conn, - 'SELECT task.* %Q %Q FROM %T task %Q %Q %Q %Q %Q %Q', + '%Q %Q %Q FROM %T task %Q %Q %Q %Q %Q %Q', + $this->buildSelectClause($conn), $count, $group_column, $task_dao->getTableName(), - $this->buildJoinsClause($conn), + $this->buildJoinClause($conn), $where, $this->buildGroupClause($conn), - $having, + $this->buildHavingClause($conn), $this->buildOrderClause($conn), $this->buildLimitClause($conn)); @@ -761,7 +752,7 @@ 'xproject.dst IS NULL'); } - private function buildJoinsClause(AphrontDatabaseConnection $conn_r) { + protected function buildJoinClauseParts(AphrontDatabaseConnection $conn_r) { $edge_table = PhabricatorEdgeConfig::TABLE_NAME_EDGE; $joins = array(); @@ -856,9 +847,9 @@ break; } - $joins[] = $this->buildApplicationSearchJoinClause($conn_r); + $joins[] = parent::buildJoinClauseParts($conn_r); - return implode(' ', $joins); + return $joins; } protected function buildGroupClause(AphrontDatabaseConnection $conn_r) { @@ -866,7 +857,7 @@ (count($this->anyProjectPHIDs) > 1) || $this->shouldJoinBlockingTasks() || $this->shouldJoinBlockedTasks() || - ($this->getApplicationSearchMayJoinMultipleRows()); + ($this->shouldGroupQueryResultRows()); $joined_project_name = ($this->groupBy == self::GROUP_PROJECT); @@ -920,6 +911,18 @@ return array_mergev($phids); } + // TODO: Remove this when moving fully to edge logic. + protected function buildHavingClauseParts(AphrontDatabaseConnection $conn) { + $having = parent::buildHavingClauseParts($conn); + if (count($this->projectPHIDs) > 1) { + $having[] = qsprintf( + $conn, + 'projectCount = %d', + count($this->projectPHIDs)); + } + return $having; + } + protected function getResultCursor($result) { $id = $result->getID(); 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 @@ -89,24 +89,8 @@ $saved->setParameter('fulltext', $request->getStr('fulltext')); $saved->setParameter( - 'allProjectPHIDs', - $this->readPHIDsFromRequest($request, 'allProjects')); - - $saved->setParameter( - 'withNoProject', - $request->getBool('withNoProject')); - - $saved->setParameter( - 'anyProjectPHIDs', - $this->readPHIDsFromRequest($request, 'anyProjects')); - - $saved->setParameter( - 'excludeProjectPHIDs', - $this->readPHIDsFromRequest($request, 'excludeProjects')); - - $saved->setParameter( - 'userProjectPHIDs', - $this->readUsersFromRequest($request, 'userProjects')); + 'projects', + $this->readProjectsFromRequest($request, 'projects')); $saved->setParameter('createdStart', $request->getStr('createdStart')); $saved->setParameter('createdEnd', $request->getStr('createdEnd')); @@ -183,30 +167,9 @@ $query->withFullTextSearch($fulltext); } - $with_no_project = $saved->getParameter('withNoProject'); - if ($with_no_project) { - $query->withAllProjects(array(ManiphestTaskOwner::PROJECT_NO_PROJECT)); - } else { - $project_phids = $saved->getParameter('allProjectPHIDs'); - if ($project_phids) { - $query->withAllProjects($project_phids); - } - } - - $any_project_phids = $saved->getParameter('anyProjectPHIDs'); - if ($any_project_phids) { - $query->withAnyProjects($any_project_phids); - } - - $exclude_project_phids = $saved->getParameter('excludeProjectPHIDs'); - if ($exclude_project_phids) { - $query->withoutProjects($exclude_project_phids); - } - - $user_project_phids = $saved->getParameter('userProjectPHIDs'); - if ($user_project_phids) { - $query->withAnyUserProjects($user_project_phids); - } + $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')); @@ -242,21 +205,9 @@ $assigned_phids = $this->readAssignedPHIDs($saved); $author_phids = $saved->getParameter('authorPHIDs', array()); - $all_project_phids = $saved->getParameter( - 'allProjectPHIDs', - array()); - $any_project_phids = $saved->getParameter( - 'anyProjectPHIDs', - array()); - $exclude_project_phids = $saved->getParameter( - 'excludeProjectPHIDs', - array()); - $user_project_phids = $saved->getParameter( - 'userProjectPHIDs', - array()); - $subscriber_phids = $saved->getParameter('subscriberPHIDs', array()); + $projects = $this->readProjectTokens($saved); - $with_no_projects = $saved->getParameter('withNoProject'); + $subscriber_phids = $saved->getParameter('subscriberPHIDs', array()); $statuses = $saved->getParameter('statuses', array()); $statuses = array_fuse($statuses); @@ -317,41 +268,10 @@ ->setValue($assigned_phids)) ->appendControl( id(new AphrontFormTokenizerControl()) - ->setDatasource(new PhabricatorProjectDatasource()) - ->setName('allProjects') - ->setLabel(pht('In All Projects')) - ->setValue($all_project_phids)); - - if (!$this->getIsBoardView()) { - $form - ->appendChild( - id(new AphrontFormCheckboxControl()) - ->addCheckbox( - 'withNoProject', - 1, - pht('Show only tasks with no projects.'), - $with_no_projects)); - } - - $form - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setDatasource(new PhabricatorProjectDatasource()) - ->setName('anyProjects') - ->setLabel(pht('In Any Project')) - ->setValue($any_project_phids)) - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setDatasource(new PhabricatorProjectDatasource()) - ->setName('excludeProjects') - ->setLabel(pht('Not In Projects')) - ->setValue($exclude_project_phids)) - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setDatasource(new PhabricatorPeopleDatasource()) - ->setName('userProjects') - ->setLabel(pht('In Users\' Projects')) - ->setValue($user_project_phids)) + ->setDatasource(new PhabricatorProjectLogicalDatasource()) + ->setName('projects') + ->setLabel(pht('Projects')) + ->setValue($projects)) ->appendControl( id(new AphrontFormTokenizerControl()) ->setDatasource(new PhabricatorPeopleDatasource()) @@ -566,4 +486,35 @@ return $assigned_phids; } + private function readProjectTokens(PhabricatorSavedQuery $saved) { + $projects = $saved->getParameter('projects', array()); + + $all = $saved->getParameter('allProjectPHIDs', array()); + foreach ($all as $phid) { + $projects[] = $phid; + } + + $any = $saved->getParameter('anyProjectPHIDs', array()); + foreach ($any as $phid) { + $projects[] = 'any('.$phid.')'; + } + + $not = $saved->getParameter('excludeProjectPHIDs', array()); + foreach ($not as $phid) { + $projects[] = 'not('.$phid.')'; + } + + $users = $saved->getParameter('userProjectPHIDs', array()); + foreach ($users as $phid) { + $projects[] = 'projects('.$phid.')'; + } + + $no = $saved->getParameter('withNoProject'); + if ($no) { + $projects[] = 'null()'; + } + + return $projects; + } + } diff --git a/src/applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php b/src/applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php --- a/src/applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php +++ b/src/applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php @@ -85,7 +85,8 @@ foreach ($results as $result) { $result ->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION) - ->setIcon('fa-asterisk'); + ->setIcon('fa-asterisk') + ->setColor(null); if ($return_any) { $return[] = id(clone $result) @@ -134,6 +135,7 @@ $tokens = $this->renderTokens($phids); foreach ($tokens as $token) { + $token->setColor(null); if ($token->isInvalid()) { if ($function == 'any') { $token->setValue(pht('In Any: Invalid Project')); diff --git a/src/applications/project/typeahead/PhabricatorProjectLogicalUserDatasource.php b/src/applications/project/typeahead/PhabricatorProjectLogicalUserDatasource.php --- a/src/applications/project/typeahead/PhabricatorProjectLogicalUserDatasource.php +++ b/src/applications/project/typeahead/PhabricatorProjectLogicalUserDatasource.php @@ -42,6 +42,7 @@ protected function didLoadResults(array $results) { foreach ($results as $result) { $result + ->setColor(null) ->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION) ->setIcon('fa-asterisk') ->setPHID('projects('.$result->getPHID().')') @@ -85,6 +86,7 @@ $tokens = $this->renderTokens($phids); foreach ($tokens as $token) { + $token->setColor(null); if ($token->isInvalid()) { $token ->setValue(pht("User's Projects: Invalid User"));