From dd21761df9e874ebf095014037755b591630487f Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 12 Jan 2016 06:09:36 -0800 Subject: [PATCH] Don't return any results for viewerprojects() if the viewer is in no projects Summary: Fixes T10135. When the viewer is a member of no projects, specify the constraint type as a new "EMPTY" type. When a query has an "EMPTY" constraint, fail fast with no results. Test Plan: - Viewed a viewerprojects() query result set as a user in no projects. - Before patch: got a lot of hits. After patch: no hits. - Viewed a normal result set, no changes. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10135 Differential Revision: https://secure.phabricator.com/D15003 --- .../PhabricatorProjectLogicalViewerDatasource.php | 12 +++++++++--- .../query/constraint/PhabricatorQueryConstraint.php | 1 + .../PhabricatorCursorPagedPolicyAwareQuery.php | 10 ++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/applications/project/typeahead/PhabricatorProjectLogicalViewerDatasource.php b/src/applications/project/typeahead/PhabricatorProjectLogicalViewerDatasource.php index e326dea254..1c472dc474 100644 --- a/src/applications/project/typeahead/PhabricatorProjectLogicalViewerDatasource.php +++ b/src/applications/project/typeahead/PhabricatorProjectLogicalViewerDatasource.php @@ -63,10 +63,16 @@ final class PhabricatorProjectLogicalViewerDatasource $phids = mpull($projects, 'getPHID'); $results = array(); - foreach ($phids as $phid) { + if ($phids) { + foreach ($phids as $phid) { + $results[] = new PhabricatorQueryConstraint( + PhabricatorQueryConstraint::OPERATOR_OR, + $phid); + } + } else { $results[] = new PhabricatorQueryConstraint( - PhabricatorQueryConstraint::OPERATOR_OR, - $phid); + PhabricatorQueryConstraint::OPERATOR_EMPTY, + null); } return $results; diff --git a/src/infrastructure/query/constraint/PhabricatorQueryConstraint.php b/src/infrastructure/query/constraint/PhabricatorQueryConstraint.php index 5b5702673b..74b3830676 100644 --- a/src/infrastructure/query/constraint/PhabricatorQueryConstraint.php +++ b/src/infrastructure/query/constraint/PhabricatorQueryConstraint.php @@ -7,6 +7,7 @@ final class PhabricatorQueryConstraint extends Phobject { const OPERATOR_NOT = 'not'; const OPERATOR_NULL = 'null'; const OPERATOR_ANCESTOR = 'ancestor'; + const OPERATOR_EMPTY = 'empty'; private $operator; private $value; diff --git a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php index 9996f03ae0..1892e53e7c 100644 --- a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php +++ b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php @@ -1872,6 +1872,16 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery return $this; } + foreach ($this->edgeLogicConstraints as $type => $constraints) { + foreach ($constraints as $operator => $list) { + switch ($operator) { + case PhabricatorQueryConstraint::OPERATOR_EMPTY: + throw new PhabricatorEmptyQueryException( + pht('This query specifies an empty constraint.')); + } + } + } + // This should probably be more modular, eventually, but we only do // project-based edge logic today.