[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class AphrontPagerView extends AphrontView { 4 5 private $offset; 6 private $pageSize = 100; 7 8 private $count; 9 private $hasMorePages; 10 11 private $uri; 12 private $pagingParameter; 13 private $surroundingPages = 2; 14 private $enableKeyboardShortcuts; 15 16 final public function setPageSize($page_size) { 17 $this->pageSize = max(1, $page_size); 18 return $this; 19 } 20 21 final public function setOffset($offset) { 22 $this->offset = max(0, $offset); 23 return $this; 24 } 25 26 final public function getOffset() { 27 return $this->offset; 28 } 29 30 final public function getPageSize() { 31 return $this->pageSize; 32 } 33 34 final public function setCount($count) { 35 $this->count = $count; 36 return $this; 37 } 38 39 final public function setHasMorePages($has_more) { 40 $this->hasMorePages = $has_more; 41 return $this; 42 } 43 44 final public function setURI(PhutilURI $uri, $paging_parameter) { 45 $this->uri = $uri; 46 $this->pagingParameter = $paging_parameter; 47 return $this; 48 } 49 50 final public function readFromRequest(AphrontRequest $request) { 51 $this->uri = $request->getRequestURI(); 52 $this->pagingParameter = 'offset'; 53 $this->offset = $request->getInt($this->pagingParameter); 54 return $this; 55 } 56 57 final public function willShowPagingControls() { 58 return $this->hasMorePages; 59 } 60 61 final public function setSurroundingPages($pages) { 62 $this->surroundingPages = max(0, $pages); 63 return $this; 64 } 65 66 private function computeCount() { 67 if ($this->count !== null) { 68 return $this->count; 69 } 70 return $this->getOffset() 71 + $this->getPageSize() 72 + ($this->hasMorePages ? 1 : 0); 73 } 74 75 private function isExactCountKnown() { 76 return $this->count !== null; 77 } 78 79 /** 80 * A common paging strategy is to select one extra record and use that to 81 * indicate that there's an additional page (this doesn't give you a 82 * complete page count but is often faster than counting the total number 83 * of items). This method will take a result array, slice it down to the 84 * page size if necessary, and call setHasMorePages() if there are more than 85 * one page of results. 86 * 87 * $results = queryfx_all( 88 * $conn, 89 * 'SELECT ... LIMIT %d, %d', 90 * $pager->getOffset(), 91 * $pager->getPageSize() + 1); 92 * $results = $pager->sliceResults($results); 93 * 94 * @param list Result array. 95 * @return list One page of results. 96 */ 97 public function sliceResults(array $results) { 98 if (count($results) > $this->getPageSize()) { 99 $results = array_slice($results, 0, $this->getPageSize(), true); 100 $this->setHasMorePages(true); 101 } 102 return $results; 103 } 104 105 public function setEnableKeyboardShortcuts($enable) { 106 $this->enableKeyboardShortcuts = $enable; 107 return $this; 108 } 109 110 public function render() { 111 if (!$this->uri) { 112 throw new Exception( 113 pht('You must call setURI() before you can call render().')); 114 } 115 116 require_celerity_resource('aphront-pager-view-css'); 117 118 $page = (int)floor($this->getOffset() / $this->getPageSize()); 119 $last = ((int)ceil($this->computeCount() / $this->getPageSize())) - 1; 120 $near = $this->surroundingPages; 121 122 $min = $page - $near; 123 $max = $page + $near; 124 125 // Limit the window size to no larger than the number of available pages. 126 if ($max - $min > $last) { 127 $max = $min + $last; 128 if ($max == $min) { 129 return phutil_tag('div', array('class' => 'aphront-pager-view'), ''); 130 } 131 } 132 133 // Slide the window so it is entirely over displayable pages. 134 if ($min < 0) { 135 $max += 0 - $min; 136 $min += 0 - $min; 137 } 138 139 if ($max > $last) { 140 $min -= $max - $last; 141 $max -= $max - $last; 142 } 143 144 145 // Build up a list of <index, label, css-class> tuples which describe the 146 // links we'll display, then render them all at once. 147 148 $links = array(); 149 150 $prev_index = null; 151 $next_index = null; 152 153 if ($min > 0) { 154 $links[] = array(0, pht('First'), null); 155 } 156 157 if ($page > 0) { 158 $links[] = array($page - 1, pht('Prev'), null); 159 $prev_index = $page - 1; 160 } 161 162 for ($ii = $min; $ii <= $max; $ii++) { 163 $links[] = array($ii, $ii + 1, ($ii == $page) ? 'current' : null); 164 } 165 166 if ($page < $last && $last > 0) { 167 $links[] = array($page + 1, pht('Next'), null); 168 $next_index = $page + 1; 169 } 170 171 if ($max < ($last - 1)) { 172 $links[] = array($last, pht('Last'), null); 173 } 174 175 $base_uri = $this->uri; 176 $parameter = $this->pagingParameter; 177 178 if ($this->enableKeyboardShortcuts) { 179 $pager_links = array(); 180 $pager_index = array( 181 'prev' => $prev_index, 182 'next' => $next_index, 183 ); 184 foreach ($pager_index as $key => $index) { 185 if ($index !== null) { 186 $display_index = $this->getDisplayIndex($index); 187 $pager_links[$key] = (string)$base_uri->alter( 188 $parameter, 189 $display_index); 190 } 191 } 192 Javelin::initBehavior('phabricator-keyboard-pager', $pager_links); 193 } 194 195 // Convert tuples into rendered nodes. 196 $rendered_links = array(); 197 foreach ($links as $link) { 198 list($index, $label, $class) = $link; 199 $display_index = $this->getDisplayIndex($index); 200 $link = $base_uri->alter($parameter, $display_index); 201 $rendered_links[] = phutil_tag( 202 'a', 203 array( 204 'href' => $link, 205 'class' => $class, 206 ), 207 $label); 208 } 209 210 return phutil_tag( 211 'div', 212 array('class' => 'aphront-pager-view'), 213 $rendered_links); 214 } 215 216 private function getDisplayIndex($page_index) { 217 $page_size = $this->getPageSize(); 218 // Use a 1-based sequence for display so that the number in the URI is 219 // the same as the page number you're on. 220 if ($page_index == 0) { 221 // No need for the first page to say page=1. 222 $display_index = null; 223 } else { 224 $display_index = $page_index * $page_size; 225 } 226 return $display_index; 227 } 228 229 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |