Differential D12526 Diff 30086 src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
Changeset View
Changeset View
Standalone View
Standalone View
src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
Show All 16 Lines | abstract class PhabricatorCursorPagedPolicyAwareQuery | ||||
private $afterID; | private $afterID; | ||||
private $beforeID; | private $beforeID; | ||||
private $applicationSearchConstraints = array(); | private $applicationSearchConstraints = array(); | ||||
protected $applicationSearchOrders = array(); | protected $applicationSearchOrders = array(); | ||||
private $internalPaging; | private $internalPaging; | ||||
private $orderVector; | private $orderVector; | ||||
private $builtinOrder; | private $builtinOrder; | ||||
private $edgeLogicConstraints = array(); | private $edgeLogicConstraints = array(); | ||||
private $edgeLogicConstraintsAreValid = false; | |||||
protected function getPageCursors(array $page) { | protected function getPageCursors(array $page) { | ||||
return array( | return array( | ||||
$this->getResultCursor(head($page)), | $this->getResultCursor(head($page)), | ||||
$this->getResultCursor(last($page)), | $this->getResultCursor(last($page)), | ||||
); | ); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,223 Lines • ▼ Show 20 Lines | protected function isCustomFieldOrderKey($key) { | ||||
return !strncmp($key, $prefix, strlen($prefix)); | return !strncmp($key, $prefix, strlen($prefix)); | ||||
} | } | ||||
/* -( Edge Logic )--------------------------------------------------------- */ | /* -( Edge Logic )--------------------------------------------------------- */ | ||||
/** | /** | ||||
* Convenience method for specifying edge logic constraints with a list of | |||||
* PHIDs. | |||||
* | |||||
* @param const Edge constant. | |||||
* @param const Constraint operator. | |||||
* @param list<phid> List of PHIDs. | |||||
* @return this | |||||
* @task edgelogic | |||||
*/ | |||||
public function withEdgeLogicPHIDs($edge_type, $operator, array $phids) { | |||||
$constraints = array(); | |||||
foreach ($phids as $phid) { | |||||
$constraints[] = new PhabricatorQueryConstraint($operator, $phid); | |||||
} | |||||
return $this->withEdgeLogicConstraints($edge_type, $constraints); | |||||
} | |||||
/** | |||||
* @task edgelogic | * @task edgelogic | ||||
*/ | */ | ||||
public function withEdgeLogicConstraints($edge_type, array $constraints) { | public function withEdgeLogicConstraints($edge_type, array $constraints) { | ||||
assert_instances_of($constraints, 'PhabricatorQueryConstraint'); | assert_instances_of($constraints, 'PhabricatorQueryConstraint'); | ||||
$constraints = mgroup($constraints, 'getOperator'); | $constraints = mgroup($constraints, 'getOperator'); | ||||
foreach ($constraints as $operator => $list) { | foreach ($constraints as $operator => $list) { | ||||
foreach ($list as $item) { | foreach ($list as $item) { | ||||
$value = $item->getValue(); | $value = $item->getValue(); | ||||
$this->edgeLogicConstraints[$edge_type][$operator][$value] = $item; | $this->edgeLogicConstraints[$edge_type][$operator][$value] = $item; | ||||
} | } | ||||
} | } | ||||
$this->edgeLogicConstraintsAreValid = false; | |||||
return $this; | return $this; | ||||
} | } | ||||
/** | /** | ||||
* @task edgelogic | * @task edgelogic | ||||
*/ | */ | ||||
public function buildEdgeLogicSelectClause(AphrontDatabaseConnection $conn) { | public function buildEdgeLogicSelectClause(AphrontDatabaseConnection $conn) { | ||||
$select = array(); | $select = array(); | ||||
$this->validateEdgeLogicConstraints(); | |||||
foreach ($this->edgeLogicConstraints as $type => $constraints) { | foreach ($this->edgeLogicConstraints as $type => $constraints) { | ||||
foreach ($constraints as $operator => $list) { | foreach ($constraints as $operator => $list) { | ||||
$alias = $this->getEdgeLogicTableAlias($operator, $type); | $alias = $this->getEdgeLogicTableAlias($operator, $type); | ||||
switch ($operator) { | switch ($operator) { | ||||
case PhabricatorQueryConstraint::OPERATOR_AND: | case PhabricatorQueryConstraint::OPERATOR_AND: | ||||
if (count($list) > 1) { | if (count($list) > 1) { | ||||
$select[] = qsprintf( | $select[] = qsprintf( | ||||
$conn, | $conn, | ||||
▲ Show 20 Lines • Show All 208 Lines • ▼ Show 20 Lines | /* -( Edge Logic )--------------------------------------------------------- */ | ||||
/** | /** | ||||
* @task edgelogic | * @task edgelogic | ||||
*/ | */ | ||||
private function buildEdgeLogicTableAliasCount($alias) { | private function buildEdgeLogicTableAliasCount($alias) { | ||||
return $alias.'_count'; | return $alias.'_count'; | ||||
} | } | ||||
/** | |||||
* Select certain edge logic constraint values. | |||||
* | |||||
* @task edgelogic | |||||
*/ | |||||
protected function getEdgeLogicValues( | |||||
array $edge_types, | |||||
array $operators) { | |||||
$values = array(); | |||||
$constraint_lists = $this->edgeLogicConstraints; | |||||
if ($edge_types) { | |||||
$constraint_lists = array_select_keys($constraint_lists, $edge_types); | |||||
} | |||||
foreach ($constraint_lists as $type => $constraints) { | |||||
if ($operators) { | |||||
$constraints = array_select_keys($constraints, $operators); | |||||
} | |||||
foreach ($constraints as $operator => $list) { | |||||
foreach ($list as $constraint) { | |||||
$values[] = $constraint->getValue(); | |||||
} | |||||
} | |||||
} | |||||
return $values; | |||||
} | |||||
/** | |||||
* Validate edge logic constraints for the query. | |||||
* | |||||
* @return this | |||||
* @task edgelogic | |||||
*/ | |||||
private function validateEdgeLogicConstraints() { | |||||
if ($this->edgeLogicConstraintsAreValid) { | |||||
return $this; | |||||
} | |||||
// This should probably be more modular, eventually, but we only do | |||||
// project-based edge logic today. | |||||
$project_phids = $this->getEdgeLogicValues( | |||||
array( | |||||
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, | |||||
), | |||||
array( | |||||
PhabricatorQueryConstraint::OPERATOR_AND, | |||||
PhabricatorQueryConstraint::OPERATOR_OR, | |||||
PhabricatorQueryConstraint::OPERATOR_NOT, | |||||
)); | |||||
if ($project_phids) { | |||||
$projects = id(new PhabricatorProjectQuery()) | |||||
->setViewer($this->getViewer()) | |||||
->setParentQuery($this) | |||||
->withPHIDs($project_phids) | |||||
->execute(); | |||||
$projects = mpull($projects, null, 'getPHID'); | |||||
foreach ($project_phids as $phid) { | |||||
if (empty($projects[$phid])) { | |||||
throw new PhabricatorEmptyQueryException( | |||||
pht( | |||||
'This query is constrained by a project you do not have '. | |||||
'permission to see.')); | |||||
} | |||||
} | |||||
} | |||||
$this->edgeLogicConstraintsAreValid = true; | |||||
return $this; | |||||
} | |||||
} | } |