@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.

Allow policy-aware queries to prefilter results

Summary:
Provides a simple way for policy-aware queries to pre-filter results without needing to maintain separate cursors, and fixes a bunch of filter-related edge cases.

- For reverse-paged cursor queries, we previously reversed each individual set of results. If the final result set is built out of multiple pages, it's in the wrong order overall, with each page in the correct order in sequence. Instead, reverse everything at the end. This also simplifies construction of queries.
- `AphrontCursorPagerView` would always render a "<< First" link when paging backward, even if we were on the first page of results.
- Add a filtering hook to let queries perform in-application pre-policy filtering as simply as possible (i.e., without maintaing their own cursors over the result sets).

Test Plan: Made feed randomly prefilter half the results, and paged forward and backward. Observed correct result ordering, pagination, and next/previous links.

Reviewers: btrahan, vrana

Reviewed By: btrahan

CC: aran

Differential Revision: https://secure.phabricator.com/D3787

+50 -13
+1 -1
src/applications/chatlog/PhabricatorChatLogQuery.php
··· 46 46 47 47 $logs = $table->loadAllFromArray($data); 48 48 49 - return $this->processResults($logs); 49 + return $logs; 50 50 } 51 51 52 52 private function buildWhereClause($conn_r) {
+8 -3
src/applications/feed/PhabricatorFeedQuery.php
··· 41 41 $this->buildOrderClause($conn), 42 42 $this->buildLimitClause($conn)); 43 43 44 - $results = PhabricatorFeedStory::loadAllFromRows($data); 44 + return $data; 45 + } 45 46 46 - return $this->processResults($results); 47 + protected function willFilterPage(array $data) { 48 + return PhabricatorFeedStory::loadAllFromRows($data); 47 49 } 48 50 49 51 private function buildJoinClause(AphrontDatabaseConnection $conn_r) { ··· 88 90 } 89 91 90 92 protected function getPagingValue($item) { 91 - return $item->getChronologicalKey(); 93 + if ($item instanceof PhabricatorFeedStory) { 94 + return $item->getChronologicalKey(); 95 + } 96 + return $item['chronologicalKey']; 92 97 } 93 98 94 99 }
+1 -1
src/applications/paste/query/PhabricatorPasteQuery.php
··· 81 81 } 82 82 } 83 83 84 - return $this->processResults($pastes); 84 + return $pastes; 85 85 } 86 86 87 87 protected function buildWhereClause($conn_r) {
+5 -6
src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
··· 40 40 41 41 protected function nextPage(array $page) { 42 42 if ($this->beforeID) { 43 - $this->beforeID = $this->getPagingValue(head($page)); 43 + $this->beforeID = $this->getPagingValue(last($page)); 44 44 } else { 45 45 $this->afterID = $this->getPagingValue(last($page)); 46 46 } ··· 102 102 } 103 103 } 104 104 105 - final protected function processResults(array $results) { 105 + final protected function didLoadResults(array $results) { 106 106 if ($this->beforeID) { 107 107 $results = array_reverse($results, $preserve_keys = true); 108 108 } 109 109 return $results; 110 110 } 111 - 112 111 113 112 final public function executeWithCursorPager(AphrontCursorPagerView $pager) { 114 113 $this->setLimit($pager->getPageSize() + 1); ··· 123 122 124 123 $sliced_results = $pager->sliceResults($results); 125 124 126 - if ($this->beforeID || (count($results) > $pager->getPageSize())) { 125 + if ($pager->getBeforeID() || (count($results) > $pager->getPageSize())) { 127 126 $pager->setNextPageID($this->getPagingValue(last($sliced_results))); 128 127 } 129 128 130 - if ($this->afterID || 131 - ($this->beforeID && (count($results) > $pager->getPageSize()))) { 129 + if ($pager->getAfterID() || 130 + ($pager->getBeforeID() && (count($results) > $pager->getPageSize()))) { 132 131 $pager->setPrevPageID($this->getPagingValue(head($sliced_results))); 133 132 } 134 133
+32 -1
src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php
··· 188 188 189 189 $page = $this->loadPage(); 190 190 191 - $visible = $filter->apply($page); 191 + $visible = $this->willFilterPage($page); 192 + $visible = $filter->apply($visible); 192 193 foreach ($visible as $key => $result) { 193 194 ++$count; 194 195 ··· 221 222 222 223 $this->nextPage($page); 223 224 } while (true); 225 + 226 + $results = $this->didLoadResults($results); 224 227 225 228 return $results; 226 229 } ··· 274 277 * @task policyimpl 275 278 */ 276 279 abstract protected function nextPage(array $page); 280 + 281 + 282 + /** 283 + * Hook for applying a page filter prior to the privacy filter. This allows 284 + * you to drop some items from the result set without creating problems with 285 + * pagination or cursor updates. 286 + * 287 + * @param list<wild> Results from `loadPage()`. 288 + * @return list<PhabricatorPolicyInterface> Objects for policy filtering. 289 + * @task policyimpl 290 + */ 291 + protected function willFilterPage(array $page) { 292 + return $page; 293 + } 294 + 295 + 296 + /** 297 + * Hook for applying final adjustments before results are returned. This is 298 + * used by @{class:PhabricatorCursorPagedPolicyAwareQuery} to reverse results 299 + * that are queried during reverse paging. 300 + * 301 + * @param list<PhabricatorPolicyInterface> Query results. 302 + * @return list<PhabricatorPolicyInterface> Final results. 303 + * @task policyimpl 304 + */ 305 + protected function didLoadResults(array $results) { 306 + return $results; 307 + } 277 308 278 309 }
+3 -1
src/view/control/AphrontCursorPagerView.php
··· 25 25 26 26 private $nextPageID; 27 27 private $prevPageID; 28 + private $moreResults; 28 29 29 30 private $uri; 30 31 ··· 89 90 if (count($results) > $this->getPageSize()) { 90 91 $offset = ($this->beforeID ? count($results) - $this->getPageSize() : 0); 91 92 $results = array_slice($results, $offset, $this->getPageSize(), true); 93 + $this->moreResults = true; 92 94 } 93 95 return $results; 94 96 } ··· 101 103 102 104 $links = array(); 103 105 104 - if ($this->beforeID || $this->afterID) { 106 + if ($this->afterID || ($this->beforeID && $this->moreResults)) { 105 107 $links[] = phutil_render_tag( 106 108 'a', 107 109 array(