mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-19 12:00:55 +01:00
Modernize ManiphestTask paging and ordering
Summary: Ref T7803. The ApplicationSearch integration is still a little rough here, but it seems to have the correct behavior. The rest of this is now at least relatively sane, cohesive, and properly behaved. Test Plan: - Used all grouping and ordering queries in Maniphest. Pagingated results. - Used custom field ordering in Maniphest. Paginated results. - Paginated through the `null` section of "Assigned" and "Projects" group-by queries. Pagingation now works correctly (it does not work at HEAD). - Ran unit tests covering priority changes. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T7803 Differential Revision: https://secure.phabricator.com/D12372
This commit is contained in:
parent
4114560844
commit
bdd1edea7a
3 changed files with 219 additions and 333 deletions
|
@ -612,12 +612,13 @@ final class ManiphestTransactionEditor
|
|||
|
||||
$query = id(new ManiphestTaskQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->setOrderBy(ManiphestTaskQuery::ORDER_PRIORITY)
|
||||
->withPriorities(array($priority))
|
||||
->setLimit(1);
|
||||
|
||||
if ($is_end) {
|
||||
$query->setReversePaging(true);
|
||||
$query->setOrderVector(array('-priority', '-subpriority', '-id'));
|
||||
} else {
|
||||
$query->setOrderVector(array('priority', 'subpriority', 'id'));
|
||||
}
|
||||
|
||||
$result = $query->executeOne();
|
||||
|
@ -675,13 +676,18 @@ final class ManiphestTransactionEditor
|
|||
// Get all of the tasks with the same subpriority as the adjacent
|
||||
// task, including the adjacent task itself.
|
||||
$shift_base = $adjacent->getSubpriority();
|
||||
$shift_all = id(new ManiphestTaskQuery())
|
||||
$query = id(new ManiphestTaskQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->setOrderBy(ManiphestTaskQuery::ORDER_PRIORITY)
|
||||
->withPriorities(array($adjacent->getPriority()))
|
||||
->withSubpriorities(array($shift_base))
|
||||
->setReversePaging(!$is_after)
|
||||
->execute();
|
||||
->withSubpriorities(array($shift_base));
|
||||
|
||||
if (!$is_after) {
|
||||
$query->setOrderVector(array('-priority', '-subpriority', '-id'));
|
||||
} else {
|
||||
$query->setOrderVector(array('priority', 'subpriority', 'id'));
|
||||
}
|
||||
|
||||
$shift_all = $query->execute();
|
||||
$shift_last = last($shift_all);
|
||||
|
||||
// Find the subpriority before or after the task at the end of the
|
||||
|
|
|
@ -21,7 +21,6 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
private $dateCreatedBefore;
|
||||
private $dateModifiedAfter;
|
||||
private $dateModifiedBefore;
|
||||
private $reversePaging;
|
||||
|
||||
private $fullTextSearch = '';
|
||||
|
||||
|
@ -54,14 +53,10 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
|
||||
private $needSubscriberPHIDs;
|
||||
private $needProjectPHIDs;
|
||||
|
||||
private $blockingTasks;
|
||||
private $blockedTasks;
|
||||
|
||||
private $projectPolicyCheckFailed = false;
|
||||
|
||||
const DEFAULT_PAGE_SIZE = 1000;
|
||||
|
||||
public function withAuthors(array $authors) {
|
||||
$this->authorPHIDs = $authors;
|
||||
return $this;
|
||||
|
@ -231,6 +226,10 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
return $this;
|
||||
}
|
||||
|
||||
protected function newResultObject() {
|
||||
return new ManiphestTask();
|
||||
}
|
||||
|
||||
protected function willExecute() {
|
||||
// Make sure the user can see any projects specified in this
|
||||
// query FIRST.
|
||||
|
@ -252,6 +251,67 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
}
|
||||
$this->projectPHIDs = array_values($this->projectPHIDs);
|
||||
}
|
||||
|
||||
// If we already have an order vector, use it as provided.
|
||||
// TODO: This is a messy hack to make setOrderVector() stronger than
|
||||
// setPriority().
|
||||
$vector = $this->getOrderVector();
|
||||
$keys = mpull(iterator_to_array($vector), 'getOrderKey');
|
||||
if (array_values($keys) !== array('id')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$parts = array();
|
||||
switch ($this->groupBy) {
|
||||
case self::GROUP_NONE:
|
||||
break;
|
||||
case self::GROUP_PRIORITY:
|
||||
$parts[] = array('priority');
|
||||
break;
|
||||
case self::GROUP_OWNER:
|
||||
$parts[] = array('owner');
|
||||
break;
|
||||
case self::GROUP_STATUS:
|
||||
$parts[] = array('status');
|
||||
break;
|
||||
case self::GROUP_PROJECT:
|
||||
$parts[] = array('project');
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->applicationSearchOrders) {
|
||||
$columns = array();
|
||||
foreach ($this->applicationSearchOrders as $order) {
|
||||
$part = 'custom:'.$order['key'];
|
||||
if ($order['ascending']) {
|
||||
$part = '-'.$part;
|
||||
}
|
||||
$columns[] = $part;
|
||||
}
|
||||
$columns[] = 'id';
|
||||
$parts[] = $columns;
|
||||
} else {
|
||||
switch ($this->orderBy) {
|
||||
case self::ORDER_PRIORITY:
|
||||
$parts[] = array('priority', 'subpriority', 'id');
|
||||
break;
|
||||
case self::ORDER_CREATED:
|
||||
$parts[] = array('id');
|
||||
break;
|
||||
case self::ORDER_MODIFIED:
|
||||
$parts[] = array('updated', 'id');
|
||||
break;
|
||||
case self::ORDER_TITLE:
|
||||
$parts[] = array('title', 'id');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$parts = array_mergev($parts);
|
||||
// We may have a duplicate column if we are both ordering and grouping
|
||||
// by priority.
|
||||
$parts = array_unique($parts);
|
||||
$this->setOrderVector($parts);
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
|
@ -268,7 +328,6 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
$where[] = $this->buildTaskPHIDsWhereClause($conn);
|
||||
$where[] = $this->buildStatusWhereClause($conn);
|
||||
$where[] = $this->buildStatusesWhereClause($conn);
|
||||
$where[] = $this->buildPrioritiesWhereClause($conn);
|
||||
$where[] = $this->buildDependenciesWhereClause($conn);
|
||||
$where[] = $this->buildAuthorWhereClause($conn);
|
||||
$where[] = $this->buildOwnerWhereClause($conn);
|
||||
|
@ -306,6 +365,20 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
$this->dateModifiedBefore);
|
||||
}
|
||||
|
||||
if ($this->priorities) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'task.priority IN (%Ld)',
|
||||
$this->priorities);
|
||||
}
|
||||
|
||||
if ($this->subpriorities) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'task.subpriority IN (%Lf)',
|
||||
$this->subpriorities);
|
||||
}
|
||||
|
||||
$where[] = $this->buildPagingClause($conn);
|
||||
|
||||
$where = $this->formatWhereClause($where);
|
||||
|
@ -325,13 +398,6 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
count($this->projectPHIDs));
|
||||
}
|
||||
|
||||
$order = $this->buildCustomOrderClause($conn);
|
||||
|
||||
// TODO: Clean up this nonstandardness.
|
||||
if (!$this->getLimit()) {
|
||||
$this->setLimit(self::DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
|
||||
$group_column = '';
|
||||
switch ($this->groupBy) {
|
||||
case self::GROUP_PROJECT:
|
||||
|
@ -351,7 +417,7 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
$where,
|
||||
$this->buildGroupClause($conn),
|
||||
$having,
|
||||
$order,
|
||||
$this->buildOrderClause($conn),
|
||||
$this->buildLimitClause($conn));
|
||||
|
||||
switch ($this->groupBy) {
|
||||
|
@ -504,24 +570,6 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
return null;
|
||||
}
|
||||
|
||||
private function buildPrioritiesWhereClause(AphrontDatabaseConnection $conn) {
|
||||
if ($this->priorities) {
|
||||
return qsprintf(
|
||||
$conn,
|
||||
'task.priority IN (%Ld)',
|
||||
$this->priorities);
|
||||
}
|
||||
|
||||
if ($this->subpriorities) {
|
||||
return qsprintf(
|
||||
$conn,
|
||||
'task.subpriority IN (%Lf)',
|
||||
$this->subpriorities);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function buildAuthorWhereClause(AphrontDatabaseConnection $conn) {
|
||||
if (!$this->authorPHIDs) {
|
||||
return null;
|
||||
|
@ -689,107 +737,6 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
'xproject.dst IS NULL');
|
||||
}
|
||||
|
||||
private function buildCustomOrderClause(AphrontDatabaseConnection $conn) {
|
||||
$reverse = ($this->getBeforeID() xor $this->getReversePaging());
|
||||
|
||||
$order = array();
|
||||
|
||||
switch ($this->groupBy) {
|
||||
case self::GROUP_NONE:
|
||||
break;
|
||||
case self::GROUP_PRIORITY:
|
||||
$order[] = 'task.priority';
|
||||
break;
|
||||
case self::GROUP_OWNER:
|
||||
$order[] = 'task.ownerOrdering';
|
||||
break;
|
||||
case self::GROUP_STATUS:
|
||||
$order[] = 'task.status';
|
||||
break;
|
||||
case self::GROUP_PROJECT:
|
||||
$order[] = '<group.project>';
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown group query '{$this->groupBy}'!");
|
||||
}
|
||||
|
||||
$app_order = $this->buildApplicationSearchOrders($conn, $reverse);
|
||||
|
||||
if (!$app_order) {
|
||||
switch ($this->orderBy) {
|
||||
case self::ORDER_PRIORITY:
|
||||
$order[] = 'task.priority';
|
||||
$order[] = 'task.subpriority';
|
||||
$order[] = 'task.dateModified';
|
||||
break;
|
||||
case self::ORDER_CREATED:
|
||||
$order[] = 'task.id';
|
||||
break;
|
||||
case self::ORDER_MODIFIED:
|
||||
$order[] = 'task.dateModified';
|
||||
break;
|
||||
case self::ORDER_TITLE:
|
||||
$order[] = 'task.title';
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown order query '{$this->orderBy}'!");
|
||||
}
|
||||
}
|
||||
|
||||
$order = array_unique($order);
|
||||
|
||||
if (empty($order) && empty($app_order)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($order as $k => $column) {
|
||||
switch ($column) {
|
||||
case 'subpriority':
|
||||
case 'ownerOrdering':
|
||||
case 'title':
|
||||
if ($reverse) {
|
||||
$order[$k] = "{$column} DESC";
|
||||
} else {
|
||||
$order[$k] = "{$column} ASC";
|
||||
}
|
||||
break;
|
||||
case '<group.project>':
|
||||
// Put "No Project" at the end of the list.
|
||||
if ($reverse) {
|
||||
$order[$k] =
|
||||
'projectGroupName.indexedObjectName IS NULL DESC, '.
|
||||
'projectGroupName.indexedObjectName DESC';
|
||||
} else {
|
||||
$order[$k] =
|
||||
'projectGroupName.indexedObjectName IS NULL ASC, '.
|
||||
'projectGroupName.indexedObjectName ASC';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if ($reverse) {
|
||||
$order[$k] = "{$column} ASC";
|
||||
} else {
|
||||
$order[$k] = "{$column} DESC";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($app_order) {
|
||||
foreach ($app_order as $order_by) {
|
||||
$order[] = $order_by;
|
||||
}
|
||||
}
|
||||
|
||||
if ($reverse) {
|
||||
$order[] = 'task.id ASC';
|
||||
} else {
|
||||
$order[] = 'task.id DESC';
|
||||
}
|
||||
|
||||
return 'ORDER BY '.implode(', ', $order);
|
||||
}
|
||||
|
||||
private function buildJoinsClause(AphrontDatabaseConnection $conn_r) {
|
||||
$edge_table = PhabricatorEdgeConfig::TABLE_NAME_EDGE;
|
||||
|
||||
|
@ -954,13 +901,10 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
|
||||
switch ($this->groupBy) {
|
||||
case self::GROUP_NONE:
|
||||
return $id;
|
||||
case self::GROUP_PRIORITY:
|
||||
return $id.'.'.$result->getPriority();
|
||||
case self::GROUP_OWNER:
|
||||
return rtrim($id.'.'.$result->getOwnerPHID(), '.');
|
||||
case self::GROUP_STATUS:
|
||||
return $id.'.'.$result->getStatus();
|
||||
case self::GROUP_PRIORITY:
|
||||
case self::GROUP_OWNER:
|
||||
return $id;
|
||||
case self::GROUP_PROJECT:
|
||||
return rtrim($id.'.'.$result->getGroupByProjectPHID(), '.');
|
||||
default:
|
||||
|
@ -968,156 +912,95 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
}
|
||||
}
|
||||
|
||||
protected function buildPagingClause(AphrontDatabaseConnection $conn_r) {
|
||||
$before_id = $this->getBeforeID();
|
||||
$after_id = $this->getAfterID();
|
||||
public function getOrderableColumns() {
|
||||
return parent::getOrderableColumns() + array(
|
||||
'priority' => array(
|
||||
'table' => 'task',
|
||||
'column' => 'priority',
|
||||
'type' => 'int',
|
||||
),
|
||||
'owner' => array(
|
||||
'table' => 'task',
|
||||
'column' => 'ownerOrdering',
|
||||
'null' => 'head',
|
||||
'reverse' => true,
|
||||
'type' => 'string',
|
||||
),
|
||||
'status' => array(
|
||||
'table' => 'task',
|
||||
'column' => 'status',
|
||||
'type' => 'string',
|
||||
'reverse' => true,
|
||||
),
|
||||
'project' => array(
|
||||
'table' => 'projectGroupName',
|
||||
'column' => 'indexedObjectName',
|
||||
'type' => 'string',
|
||||
'null' => 'head',
|
||||
'reverse' => true,
|
||||
),
|
||||
'title' => array(
|
||||
'table' => 'task',
|
||||
'column' => 'title',
|
||||
'type' => 'string',
|
||||
'reverse' => true,
|
||||
),
|
||||
'subpriority' => array(
|
||||
'table' => 'task',
|
||||
'column' => 'subpriority',
|
||||
'type' => 'float',
|
||||
),
|
||||
'updated' => array(
|
||||
'table' => 'task',
|
||||
'column' => 'dateModified',
|
||||
'type' => 'int',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (!$before_id && !$after_id) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$cursor_id = nonempty($before_id, $after_id);
|
||||
$cursor_parts = explode('.', $cursor_id, 2);
|
||||
protected function getPagingValueMap($cursor, array $keys) {
|
||||
$cursor_parts = explode('.', $cursor, 2);
|
||||
$task_id = $cursor_parts[0];
|
||||
$group_id = idx($cursor_parts, 1);
|
||||
|
||||
$cursor = $this->loadCursorObject($task_id);
|
||||
if (!$cursor) {
|
||||
// We may loop if we have a cursor and don't build a paging clause; fail
|
||||
// instead.
|
||||
throw new PhabricatorEmptyQueryException();
|
||||
}
|
||||
$task = $this->loadCursorObject($task_id);
|
||||
|
||||
$columns = array();
|
||||
$map = array(
|
||||
'id' => $task->getID(),
|
||||
'priority' => $task->getPriority(),
|
||||
'subpriority' => $task->getSubpriority(),
|
||||
'owner' => $task->getOwnerOrdering(),
|
||||
'status' => $task->getStatus(),
|
||||
'title' => $task->getTitle(),
|
||||
'updated' => $task->getDateModified(),
|
||||
);
|
||||
|
||||
switch ($this->groupBy) {
|
||||
case self::GROUP_NONE:
|
||||
break;
|
||||
case self::GROUP_PRIORITY:
|
||||
$columns[] = array(
|
||||
'table' => 'task',
|
||||
'column' => 'priority',
|
||||
'value' => (int)$group_id,
|
||||
'type' => 'int',
|
||||
);
|
||||
break;
|
||||
case self::GROUP_OWNER:
|
||||
$value = null;
|
||||
if ($group_id) {
|
||||
$paging_users = id(new PhabricatorPeopleQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs(array($group_id))
|
||||
->execute();
|
||||
if ($paging_users) {
|
||||
$value = head($paging_users)->getUsername();
|
||||
foreach ($keys as $key) {
|
||||
switch ($key) {
|
||||
case 'project':
|
||||
$value = null;
|
||||
if ($group_id) {
|
||||
$paging_projects = id(new PhabricatorProjectQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs(array($group_id))
|
||||
->execute();
|
||||
if ($paging_projects) {
|
||||
$value = head($paging_projects)->getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
$columns[] = array(
|
||||
'table' => 'task',
|
||||
'column' => 'ownerOrdering',
|
||||
'value' => $value,
|
||||
'type' => 'string',
|
||||
'null' => 'head',
|
||||
'reverse' => true,
|
||||
);
|
||||
break;
|
||||
case self::GROUP_STATUS:
|
||||
$columns[] = array(
|
||||
'table' => 'task',
|
||||
'column' => 'status',
|
||||
'value' => $group_id,
|
||||
'type' => 'string',
|
||||
);
|
||||
break;
|
||||
case self::GROUP_PROJECT:
|
||||
$value = null;
|
||||
if ($group_id) {
|
||||
$paging_projects = id(new PhabricatorProjectQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs(array($group_id))
|
||||
->execute();
|
||||
if ($paging_projects) {
|
||||
$value = head($paging_projects)->getName();
|
||||
}
|
||||
}
|
||||
|
||||
$columns[] = array(
|
||||
'table' => 'projectGroupName',
|
||||
'column' => 'indexedObjectName',
|
||||
'value' => $value,
|
||||
'type' => 'string',
|
||||
'null' => 'head',
|
||||
'reverse' => true,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown group query '{$this->groupBy}'!");
|
||||
}
|
||||
|
||||
$app_columns = $this->buildApplicationSearchPagination($conn_r, $cursor);
|
||||
if ($app_columns) {
|
||||
$columns = array_merge($columns, $app_columns);
|
||||
} else {
|
||||
switch ($this->orderBy) {
|
||||
case self::ORDER_PRIORITY:
|
||||
if ($this->groupBy != self::GROUP_PRIORITY) {
|
||||
$columns[] = array(
|
||||
'table' => 'task',
|
||||
'column' => 'priority',
|
||||
'value' => (int)$cursor->getPriority(),
|
||||
'type' => 'int',
|
||||
);
|
||||
}
|
||||
$columns[] = array(
|
||||
'table' => 'task',
|
||||
'column' => 'subpriority',
|
||||
'value' => $cursor->getSubpriority(),
|
||||
'type' => 'float',
|
||||
);
|
||||
$columns[] = array(
|
||||
'table' => 'task',
|
||||
'column' => 'dateModified',
|
||||
'value' => (int)$cursor->getDateModified(),
|
||||
'type' => 'int',
|
||||
);
|
||||
$map[$key] = $value;
|
||||
break;
|
||||
case self::ORDER_CREATED:
|
||||
// This just uses the ID column, below.
|
||||
break;
|
||||
case self::ORDER_MODIFIED:
|
||||
$columns[] = array(
|
||||
'table' => 'task',
|
||||
'column' => 'dateModified',
|
||||
'value' => (int)$cursor->getDateModified(),
|
||||
'type' => 'int',
|
||||
);
|
||||
break;
|
||||
case self::ORDER_TITLE:
|
||||
$columns[] = array(
|
||||
'table' => 'task',
|
||||
'column' => 'title',
|
||||
'value' => $cursor->getTitle(),
|
||||
'type' => 'string',
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown order query '{$this->orderBy}'!");
|
||||
}
|
||||
}
|
||||
|
||||
$columns[] = array(
|
||||
'table' => 'task',
|
||||
'column' => 'id',
|
||||
'value' => $cursor->getID(),
|
||||
'type' => 'int',
|
||||
);
|
||||
foreach ($keys as $key) {
|
||||
if ($this->isCustomFieldOrderKey($key)) {
|
||||
$map += $this->getPagingValueMapForCustomFields($task);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->buildPagingClauseFromMultipleColumns(
|
||||
$conn_r,
|
||||
$columns,
|
||||
array(
|
||||
'reversed' => (bool)($before_id xor $this->getReversePaging()),
|
||||
));
|
||||
return $map;
|
||||
}
|
||||
|
||||
protected function getPrimaryTableAlias() {
|
||||
|
@ -1128,13 +1011,4 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
return 'PhabricatorManiphestApplication';
|
||||
}
|
||||
|
||||
public function setReversePaging($reverse_paging) {
|
||||
$this->reversePaging = $reverse_paging;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getReversePaging() {
|
||||
return $this->reversePaging;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
|
|||
private $afterID;
|
||||
private $beforeID;
|
||||
private $applicationSearchConstraints = array();
|
||||
private $applicationSearchOrders = array();
|
||||
protected $applicationSearchOrders = array();
|
||||
private $internalPaging;
|
||||
private $orderVector;
|
||||
|
||||
|
@ -161,6 +161,10 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
|
|||
return null;
|
||||
}
|
||||
|
||||
protected function newResultObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/* -( Paging )------------------------------------------------------------- */
|
||||
|
||||
|
@ -546,7 +550,7 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
|
|||
return array();
|
||||
}
|
||||
|
||||
return array(
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'table' => $this->getPrimaryTableAlias(),
|
||||
'column' => 'id',
|
||||
|
@ -555,6 +559,32 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
|
|||
'unique' => true,
|
||||
),
|
||||
);
|
||||
|
||||
$object = $this->newResultObject();
|
||||
if ($object instanceof PhabricatorCustomFieldInterface) {
|
||||
$list = PhabricatorCustomField::getObjectFields(
|
||||
$object,
|
||||
PhabricatorCustomField::ROLE_APPLICATIONSEARCH);
|
||||
foreach ($list->getFields() as $field) {
|
||||
$index = $field->buildOrderIndex();
|
||||
if (!$index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = $field->getFieldKey();
|
||||
$digest = $field->getFieldIndex();
|
||||
|
||||
$full_key = 'custom:'.$key;
|
||||
$columns[$full_key] = array(
|
||||
'table' => 'appsearch_order_'.$digest,
|
||||
'column' => 'indexValue',
|
||||
'type' => $index->getIndexValueType(),
|
||||
'null' => 'tail',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
|
@ -961,8 +991,8 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
|
|||
|
||||
foreach ($this->applicationSearchOrders as $key => $order) {
|
||||
$table = $order['table'];
|
||||
$alias = 'appsearch_order_'.$key;
|
||||
$index = $order['index'];
|
||||
$alias = 'appsearch_order_'.$index;
|
||||
$phid_column = $this->getApplicationSearchObjectPHIDColumn();
|
||||
|
||||
$joins[] = qsprintf(
|
||||
|
@ -980,51 +1010,27 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
|
|||
return implode(' ', $joins);
|
||||
}
|
||||
|
||||
protected function buildApplicationSearchOrders(
|
||||
AphrontDatabaseConnection $conn_r,
|
||||
$reverse) {
|
||||
|
||||
$orders = array();
|
||||
foreach ($this->applicationSearchOrders as $key => $order) {
|
||||
$alias = 'appsearch_order_'.$key;
|
||||
|
||||
if ($order['ascending'] xor $reverse) {
|
||||
$orders[] = qsprintf($conn_r, '%T.indexValue ASC', $alias);
|
||||
} else {
|
||||
$orders[] = qsprintf($conn_r, '%T.indexValue DESC', $alias);
|
||||
}
|
||||
}
|
||||
|
||||
return $orders;
|
||||
}
|
||||
|
||||
protected function buildApplicationSearchPagination(
|
||||
AphrontDatabaseConnection $conn_r,
|
||||
$cursor) {
|
||||
protected function getPagingValueMapForCustomFields(
|
||||
PhabricatorCustomFieldInterface $object) {
|
||||
|
||||
// We have to get the current field values on the cursor object.
|
||||
$fields = PhabricatorCustomField::getObjectFields(
|
||||
$cursor,
|
||||
$object,
|
||||
PhabricatorCustomField::ROLE_APPLICATIONSEARCH);
|
||||
$fields->setViewer($this->getViewer());
|
||||
$fields->readFieldsFromStorage($cursor);
|
||||
$fields->readFieldsFromStorage($object);
|
||||
|
||||
$fields = mpull($fields->getFields(), null, 'getFieldKey');
|
||||
|
||||
$columns = array();
|
||||
foreach ($this->applicationSearchOrders as $key => $order) {
|
||||
$alias = 'appsearch_order_'.$key;
|
||||
|
||||
$field = idx($fields, $order['key']);
|
||||
|
||||
$columns[] = array(
|
||||
'name' => $alias.'.indexValue',
|
||||
'value' => $field->getValueForStorage(),
|
||||
'type' => $order['type'],
|
||||
);
|
||||
$map = array();
|
||||
foreach ($fields->getFields() as $field) {
|
||||
$map['custom:'.$field->getFieldKey()] = $field->getValueForStorage();
|
||||
}
|
||||
|
||||
return $columns;
|
||||
return $map;
|
||||
}
|
||||
|
||||
protected function isCustomFieldOrderKey($key) {
|
||||
$prefix = 'custom:';
|
||||
return !strncmp($key, $prefix, strlen($prefix));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue