@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+41 -34
+1 -1
src/applications/feed/query/PhabricatorFeedQuery.php
··· 112 112 ); 113 113 } 114 114 115 - protected function getPagingValue($item) { 115 + protected function getResultCursor($item) { 116 116 if ($item instanceof PhabricatorFeedStory) { 117 117 return $item->getChronologicalKey(); 118 118 }
+5 -11
src/applications/maniphest/query/ManiphestTaskQuery.php
··· 896 896 return array_mergev($phids); 897 897 } 898 898 899 - protected function getPagingValue($result) { 899 + protected function getResultCursor($result) { 900 900 $id = $result->getID(); 901 901 902 - switch ($this->groupBy) { 903 - case self::GROUP_NONE: 904 - case self::GROUP_STATUS: 905 - case self::GROUP_PRIORITY: 906 - case self::GROUP_OWNER: 907 - return $id; 908 - case self::GROUP_PROJECT: 909 - return rtrim($id.'.'.$result->getGroupByProjectPHID(), '.'); 910 - default: 911 - throw new Exception("Unknown group query '{$this->groupBy}'!"); 902 + if ($this->groupBy == self::GROUP_PROJECT) { 903 + return rtrim($id.'.'.$result->getGroupByProjectPHID(), '.');; 912 904 } 905 + 906 + return $id; 913 907 } 914 908 915 909 public function getOrderableColumns() {
+1 -1
src/applications/notification/query/PhabricatorNotificationQuery.php
··· 103 103 return $this->formatWhereClause($where); 104 104 } 105 105 106 - protected function getPagingValue($item) { 106 + protected function getResultCursor($item) { 107 107 return $item->getChronologicalKey(); 108 108 } 109 109
+2 -5
src/applications/project/query/PhabricatorProjectQuery.php
··· 112 112 } 113 113 114 114 protected function getPagingValueMap($cursor, array $keys) { 115 + $project = $this->loadCursorObject($cursor); 115 116 return array( 116 - 'name' => $cursor, 117 + 'name' => $project->getName(), 117 118 ); 118 - } 119 - 120 - protected function getPagingValue($result) { 121 - return $result->getName(); 122 119 } 123 120 124 121 protected function loadPage() {
+1 -1
src/applications/search/query/PhabricatorSearchDocumentQuery.php
··· 69 69 return 'PhabricatorSearchApplication'; 70 70 } 71 71 72 - protected function getPagingValue($result) { 72 + protected function getResultCursor($result) { 73 73 throw new Exception( 74 74 pht( 75 75 'This query does not support cursor paging; it must be offset '.
+31 -15
src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
··· 19 19 private $orderVector; 20 20 private $builtinOrder; 21 21 22 - protected function getPagingValue($result) { 23 - if (!is_object($result)) { 24 - // This interface can't be typehinted and PHP gets really angry if we 25 - // call a method on a non-object, so add an explicit check here. 26 - throw new Exception(pht('Expected object, got "%s"!', gettype($result))); 22 + protected function getPageCursors(array $page) { 23 + return array( 24 + $this->getResultCursor(head($page)), 25 + $this->getResultCursor(last($page)), 26 + ); 27 + } 28 + 29 + protected function getResultCursor($object) { 30 + if (!is_object($object)) { 31 + throw new Exception( 32 + pht( 33 + 'Expected object, got "%s".', 34 + gettype($object))); 27 35 } 28 - return $result->getID(); 36 + 37 + return $object->getID(); 29 38 } 30 39 31 40 protected function nextPage(array $page) { 32 41 // See getPagingViewer() for a description of this flag. 33 42 $this->internalPaging = true; 34 43 35 - if ($this->beforeID) { 36 - $this->beforeID = $this->getPagingValue(last($page)); 44 + if ($this->beforeID !== null) { 45 + $page = array_reverse($page, $preserve_keys = true); 46 + list($before, $after) = $this->getPageCursors($page); 47 + $this->beforeID = $before; 37 48 } else { 38 - $this->afterID = $this->getPagingValue(last($page)); 49 + list($before, $after) = $this->getPageCursors($page); 50 + $this->afterID = $after; 39 51 } 40 52 } 41 53 ··· 113 125 } 114 126 115 127 final public function executeWithCursorPager(AphrontCursorPagerView $pager) { 116 - $this->setLimit($pager->getPageSize() + 1); 128 + $limit = $pager->getPageSize(); 129 + 130 + $this->setLimit($limit + 1); 117 131 118 132 if ($pager->getAfterID()) { 119 133 $this->setAfterID($pager->getAfterID()); ··· 122 136 } 123 137 124 138 $results = $this->execute(); 139 + $count = count($results); 125 140 126 141 $sliced_results = $pager->sliceResults($results); 127 - 128 142 if ($sliced_results) { 129 - if ($pager->getBeforeID() || (count($results) > $pager->getPageSize())) { 130 - $pager->setNextPageID($this->getPagingValue(last($sliced_results))); 143 + list($before, $after) = $this->getPageCursors($sliced_results); 144 + 145 + if ($pager->getBeforeID() || ($count > $limit)) { 146 + $pager->setNextPageID($after); 131 147 } 132 148 133 149 if ($pager->getAfterID() || 134 - ($pager->getBeforeID() && (count($results) > $pager->getPageSize()))) { 135 - $pager->setPrevPageID($this->getPagingValue(head($sliced_results))); 150 + ($pager->getBeforeID() && ($count > $limit))) { 151 + $pager->setPrevPageID($before); 136 152 } 137 153 } 138 154