Something went wrong. Try again.
@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
Something went wrong. Try again.
PHP
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244<?php
final class PHUIPagerView extends AphrontView {
private $offset; private $pageSize = 100;
private $count; private $hasMorePages;
private $uri; private $pagingParameter; private $surroundingPages = 2; private $enableKeyboardShortcuts;
public function setPageSize($page_size) { $this->pageSize = max(1, $page_size); return $this; }
public function setOffset($offset) { $this->offset = max(0, $offset); return $this; }
public function getOffset() { return $this->offset; }
public function getPageSize() { return $this->pageSize; }
public function setCount($count) { $this->count = $count; return $this; }
public function setHasMorePages($has_more) { $this->hasMorePages = $has_more; return $this; }
public function setURI(PhutilURI $uri, $paging_parameter) { $this->uri = $uri; $this->pagingParameter = $paging_parameter; return $this; }
public function readFromRequest(AphrontRequest $request) { $this->uri = $request->getRequestURI(); $this->pagingParameter = 'offset'; $this->offset = $request->getInt($this->pagingParameter); return $this; }
public function willShowPagingControls() { return $this->hasMorePages || $this->getOffset(); }
public function getHasMorePages() { return $this->hasMorePages; }
public function setSurroundingPages($pages) { $this->surroundingPages = max(0, $pages); return $this; }
private function computeCount() { if ($this->count !== null) { return $this->count; } return $this->getOffset() + $this->getPageSize() + ($this->hasMorePages ? 1 : 0); }
/** * A common paging strategy is to select one extra record and use that to * indicate that there's an additional page (this doesn't give you a * complete page count but is often faster than counting the total number * of items). This method will take a result array, slice it down to the * page size if necessary, and call setHasMorePages() if there are more than * one page of results. * * $results = queryfx_all( * $conn, * 'SELECT ... LIMIT %d, %d', * $pager->getOffset(), * $pager->getPageSize() + 1); * $results = $pager->sliceResults($results); * * @param list $results Result array. * @return list One page of results. */ public function sliceResults(array $results) { if (count($results) > $this->getPageSize()) { $results = array_slice($results, 0, $this->getPageSize(), true); $this->setHasMorePages(true); } return $results; }
public function setEnableKeyboardShortcuts($enable) { $this->enableKeyboardShortcuts = $enable; return $this; }
public function render() { if (!$this->uri) { throw new PhutilInvalidStateException('setURI'); }
require_celerity_resource('phui-pager-css');
$page = (int)floor($this->getOffset() / $this->getPageSize()); $last = ((int)ceil($this->computeCount() / $this->getPageSize())) - 1; $near = $this->surroundingPages;
$min = $page - $near; $max = $page + $near;
// Limit the window size to no larger than the number of available pages. if ($max - $min > $last) { $max = $min + $last; if ($max == $min) { return phutil_tag('div', array('class' => 'phui-pager-view'), ''); } }
// Slide the window so it is entirely over displayable pages. if ($min < 0) { $max += 0 - $min; $min += 0 - $min; }
if ($max > $last) { $min -= $max - $last; $max -= $max - $last; }
// Build up a list of <index, label, css-class> tuples which describe the // links we'll display, then render them all at once.
$links = array();
$prev_index = null; $next_index = null;
if ($min > 0) { $links[] = array(0, pht('First'), null); }
if ($page > 0) { $links[] = array($page - 1, pht('Prev'), null); $prev_index = $page - 1; }
for ($ii = $min; $ii <= $max; $ii++) { $links[] = array($ii, $ii + 1, ($ii == $page) ? 'current' : null); }
if ($page < $last && $last > 0) { $links[] = array($page + 1, pht('Next'), null); $next_index = $page + 1; }
if ($max < ($last - 1)) { $links[] = array($last, pht('Last'), null); }
$base_uri = $this->uri; $parameter = $this->pagingParameter;
if ($this->enableKeyboardShortcuts) { $pager_links = array(); $pager_index = array( 'prev' => $prev_index, 'next' => $next_index, ); foreach ($pager_index as $key => $index) { if ($index !== null) { $display_index = $this->getDisplayIndex($index);
$uri = id(clone $base_uri); if ($display_index === null) { $uri->removeQueryParam($parameter); } else { $uri->replaceQueryParam($parameter, $display_index); }
$pager_links[$key] = phutil_string_cast($uri); } } Javelin::initBehavior('phabricator-keyboard-pager', $pager_links); }
// Convert tuples into rendered nodes. $rendered_links = array(); foreach ($links as $link) { list($index, $label, $class) = $link; $display_index = $this->getDisplayIndex($index);
$uri = id(clone $base_uri); if ($display_index === null) { $uri->removeQueryParam($parameter); } else { $uri->replaceQueryParam($parameter, $display_index); }
$rendered_links[] = id(new PHUIButtonView()) ->setTag('a') ->setHref($uri) ->setColor(PHUIButtonView::GREY) ->addClass('mml') ->addClass($class) ->setText($label); }
return phutil_tag( 'div', array( 'class' => 'phui-pager-view', ), $rendered_links); }
private function getDisplayIndex($page_index) { $page_size = $this->getPageSize(); // Use a 1-based sequence for display so that the number in the URI is // the same as the page number you're on. if ($page_index == 0) { // No need for the first page to say page=1. $display_index = null; } else { $display_index = $page_index * $page_size; } return $display_index; }
}