1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-24 06:20:56 +01:00

Replace getPagingValue() with cursor methods

Summary:
Ref T7803. Prior to this change sequence, Query classes conflated paging values (the actual thing that goes in a "x > 3" clause) with cursor values (arbitrary identifiers which track where the user is in a result list).

Although the two can sometimes be the same, the vast majority of implementations are simpler and better when object IDs are used as cursors and paging values are derived from them.

The new stuff handles this in a consistent way, so we're free to separate getPagingValue() from paging. The new method is essentially getResultCursor().

This also implements getPageCursors(), which allows queries to return directional cursors. The inability to do this was a practical limitation blocking the implementation of T7803.

Test Plan:
  - Browsed a bunch of results and paged through queries.
  - Grepped for removed methods.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T7803

Differential Revision: https://secure.phabricator.com/D12383
This commit is contained in:
epriestley 2015-04-12 16:44:15 -07:00
parent 09ad69238e
commit 8efdc4aabf
6 changed files with 41 additions and 34 deletions

View file

@ -112,7 +112,7 @@ final class PhabricatorFeedQuery
); );
} }
protected function getPagingValue($item) { protected function getResultCursor($item) {
if ($item instanceof PhabricatorFeedStory) { if ($item instanceof PhabricatorFeedStory) {
return $item->getChronologicalKey(); return $item->getChronologicalKey();
} }

View file

@ -896,20 +896,14 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
return array_mergev($phids); return array_mergev($phids);
} }
protected function getPagingValue($result) { protected function getResultCursor($result) {
$id = $result->getID(); $id = $result->getID();
switch ($this->groupBy) { if ($this->groupBy == self::GROUP_PROJECT) {
case self::GROUP_NONE: return rtrim($id.'.'.$result->getGroupByProjectPHID(), '.');;
case self::GROUP_STATUS:
case self::GROUP_PRIORITY:
case self::GROUP_OWNER:
return $id;
case self::GROUP_PROJECT:
return rtrim($id.'.'.$result->getGroupByProjectPHID(), '.');
default:
throw new Exception("Unknown group query '{$this->groupBy}'!");
} }
return $id;
} }
public function getOrderableColumns() { public function getOrderableColumns() {

View file

@ -103,7 +103,7 @@ final class PhabricatorNotificationQuery
return $this->formatWhereClause($where); return $this->formatWhereClause($where);
} }
protected function getPagingValue($item) { protected function getResultCursor($item) {
return $item->getChronologicalKey(); return $item->getChronologicalKey();
} }

View file

@ -112,15 +112,12 @@ final class PhabricatorProjectQuery
} }
protected function getPagingValueMap($cursor, array $keys) { protected function getPagingValueMap($cursor, array $keys) {
$project = $this->loadCursorObject($cursor);
return array( return array(
'name' => $cursor, 'name' => $project->getName(),
); );
} }
protected function getPagingValue($result) {
return $result->getName();
}
protected function loadPage() { protected function loadPage() {
$table = new PhabricatorProject(); $table = new PhabricatorProject();
$conn_r = $table->establishConnection('r'); $conn_r = $table->establishConnection('r');

View file

@ -69,7 +69,7 @@ final class PhabricatorSearchDocumentQuery
return 'PhabricatorSearchApplication'; return 'PhabricatorSearchApplication';
} }
protected function getPagingValue($result) { protected function getResultCursor($result) {
throw new Exception( throw new Exception(
pht( pht(
'This query does not support cursor paging; it must be offset '. 'This query does not support cursor paging; it must be offset '.

View file

@ -19,23 +19,35 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
private $orderVector; private $orderVector;
private $builtinOrder; private $builtinOrder;
protected function getPagingValue($result) { protected function getPageCursors(array $page) {
if (!is_object($result)) { return array(
// This interface can't be typehinted and PHP gets really angry if we $this->getResultCursor(head($page)),
// call a method on a non-object, so add an explicit check here. $this->getResultCursor(last($page)),
throw new Exception(pht('Expected object, got "%s"!', gettype($result))); );
} }
return $result->getID();
protected function getResultCursor($object) {
if (!is_object($object)) {
throw new Exception(
pht(
'Expected object, got "%s".',
gettype($object)));
}
return $object->getID();
} }
protected function nextPage(array $page) { protected function nextPage(array $page) {
// See getPagingViewer() for a description of this flag. // See getPagingViewer() for a description of this flag.
$this->internalPaging = true; $this->internalPaging = true;
if ($this->beforeID) { if ($this->beforeID !== null) {
$this->beforeID = $this->getPagingValue(last($page)); $page = array_reverse($page, $preserve_keys = true);
list($before, $after) = $this->getPageCursors($page);
$this->beforeID = $before;
} else { } else {
$this->afterID = $this->getPagingValue(last($page)); list($before, $after) = $this->getPageCursors($page);
$this->afterID = $after;
} }
} }
@ -113,7 +125,9 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
} }
final public function executeWithCursorPager(AphrontCursorPagerView $pager) { final public function executeWithCursorPager(AphrontCursorPagerView $pager) {
$this->setLimit($pager->getPageSize() + 1); $limit = $pager->getPageSize();
$this->setLimit($limit + 1);
if ($pager->getAfterID()) { if ($pager->getAfterID()) {
$this->setAfterID($pager->getAfterID()); $this->setAfterID($pager->getAfterID());
@ -122,17 +136,19 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
} }
$results = $this->execute(); $results = $this->execute();
$count = count($results);
$sliced_results = $pager->sliceResults($results); $sliced_results = $pager->sliceResults($results);
if ($sliced_results) { if ($sliced_results) {
if ($pager->getBeforeID() || (count($results) > $pager->getPageSize())) { list($before, $after) = $this->getPageCursors($sliced_results);
$pager->setNextPageID($this->getPagingValue(last($sliced_results)));
if ($pager->getBeforeID() || ($count > $limit)) {
$pager->setNextPageID($after);
} }
if ($pager->getAfterID() || if ($pager->getAfterID() ||
($pager->getBeforeID() && (count($results) > $pager->getPageSize()))) { ($pager->getBeforeID() && ($count > $limit))) {
$pager->setPrevPageID($this->getPagingValue(head($sliced_results))); $pager->setPrevPageID($before);
} }
} }