paginator.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. <?php namespace Laravel;
  2. class Paginator {
  3. /**
  4. * The results for the current page.
  5. *
  6. * @var array
  7. */
  8. public $results;
  9. /**
  10. * The current page.
  11. *
  12. * @var int
  13. */
  14. protected $page;
  15. /**
  16. * The last page available for the result set.
  17. *
  18. * @var int
  19. */
  20. protected $last;
  21. /**
  22. * The total number of results.
  23. *
  24. * @var int
  25. */
  26. protected $total;
  27. /**
  28. * The number of items per page.
  29. *
  30. * @var int
  31. */
  32. protected $per_page;
  33. /**
  34. * The values that should be appended to the end of the link query strings.
  35. *
  36. * @var array
  37. */
  38. protected $appends;
  39. /**
  40. * The compiled appendage that will be appended to the links.
  41. *
  42. * This consists of a sprintf format with a page place-holder and query string.
  43. *
  44. * @var string
  45. */
  46. protected $appendage;
  47. /**
  48. * The pagination elements that will be generated.
  49. *
  50. * @var array
  51. */
  52. protected $elements = array('first', 'previous', 'status', 'next', 'last');
  53. /**
  54. * Create a new Paginator instance.
  55. *
  56. * @param array $results
  57. * @param int $last
  58. * @param int $page
  59. * @param int $total
  60. * @param int $per_page
  61. * @return void
  62. */
  63. protected function __construct($results, $page, $total, $per_page, $last)
  64. {
  65. $this->page = $page;
  66. $this->last = $last;
  67. $this->total = $total;
  68. $this->results = $results;
  69. $this->per_page = $per_page;
  70. }
  71. /**
  72. * Create a new Paginator instance.
  73. *
  74. * @param array $results
  75. * @param int $total
  76. * @param int $per_page
  77. * @return Paginator
  78. */
  79. public static function make($results, $total, $per_page)
  80. {
  81. return new static($results, static::page($total, $per_page), $total, $per_page, ceil($total / $per_page));
  82. }
  83. /**
  84. * Get the current page from the request query string.
  85. *
  86. * @param int $total
  87. * @param int $per_page
  88. * @return int
  89. */
  90. public static function page($total, $per_page)
  91. {
  92. $page = Input::get('page', 1);
  93. // The page will be validated and adjusted if it is less than one or greater
  94. // than the last page. For example, if the current page is not an integer or
  95. // less than one, one will be returned. If the current page is greater than
  96. // the last page, the last page will be returned.
  97. if (is_numeric($page) and $page > $last = ceil($total / $per_page))
  98. {
  99. return ($last > 0) ? $last : 1;
  100. }
  101. return ($page < 1 or filter_var($page, FILTER_VALIDATE_INT) === false) ? 1 : $page;
  102. }
  103. /**
  104. * Create the HTML pagination links.
  105. *
  106. * @return string
  107. */
  108. public function links()
  109. {
  110. if ($this->last <= 1) return '';
  111. // Each pagination element is created by an element method. This allows
  112. // us to keep this class clean and simple, because pagination code can
  113. // become a mess. We would rather keep it simple and beautiful.
  114. foreach ($this->elements as $element)
  115. {
  116. $elements[] = $this->$element(Lang::line("pagination.{$element}")->get());
  117. }
  118. return '<div class="pagination">'.implode(' ', $elements).'</div>'.PHP_EOL;
  119. }
  120. /**
  121. * Get the "status" pagination element.
  122. *
  123. * @param string $text
  124. * @return string
  125. */
  126. protected function status($text)
  127. {
  128. return str_replace(array(':current', ':last'), array($this->page, $this->last), $text);
  129. }
  130. /**
  131. * Create the "first" pagination element.
  132. *
  133. * @param string $text
  134. * @return string
  135. */
  136. protected function first($text)
  137. {
  138. return $this->backwards(__FUNCTION__, $text, 1);
  139. }
  140. /**
  141. * Create the "previous" pagination element.
  142. *
  143. * @param string $text
  144. * @return string
  145. */
  146. protected function previous($text)
  147. {
  148. return $this->backwards(__FUNCTION__, $text, $this->page - 1);
  149. }
  150. /**
  151. * Create the "next" pagination element.
  152. *
  153. * @param string $text
  154. * @return string
  155. */
  156. protected function next($text)
  157. {
  158. return $this->forwards(__FUNCTION__, $text, $this->page + 1);
  159. }
  160. /**
  161. * Create the "last" pagination element.
  162. *
  163. * @param string $text
  164. * @return string
  165. */
  166. protected function last($text)
  167. {
  168. return $this->forwards(__FUNCTION__, $text, $this->last);
  169. }
  170. /**
  171. * Create a "backwards" paginatino element.
  172. *
  173. * This function handles the creation of the first and previous elements.
  174. *
  175. * @param string $element
  176. * @param string $text
  177. * @param int $last
  178. * @return string
  179. */
  180. protected function backwards($element, $text, $last)
  181. {
  182. return $this->element($element, $text, $last, function($page) { return $page <= 1; });
  183. }
  184. /**
  185. * Create a "forwards" paginatino element.
  186. *
  187. * This function handles the creation of the next and last elements.
  188. *
  189. * @param string $element
  190. * @param string $text
  191. * @param int $last
  192. * @return string
  193. */
  194. protected function forwards($element, $text, $last)
  195. {
  196. return $this->element($element, $text, $last, function($page, $last) { return $page >= $last; });
  197. }
  198. /**
  199. * Create a chronological pagination element.
  200. *
  201. * @param string $element
  202. * @param string $text
  203. * @param int $page
  204. * @param Closure $disabler
  205. * @return string
  206. */
  207. protected function element($element, $text, $page, $disabler)
  208. {
  209. $class = "{$element}_page";
  210. if ($disabler($this->page, $this->last))
  211. {
  212. return HTML::span($text, array('class' => "disabled {$class}"));
  213. }
  214. else
  215. {
  216. // We will assume the page links should use HTTPS if the current request
  217. // is also using HTTPS. Since pagination links automatically point to
  218. // the current URI, this makes pretty good sense.
  219. list($uri, $secure) = array(URI::get(), Request::secure());
  220. return HTML::link($uri.$this->appendage($element, $page), $text, array('class' => $class), $secure);
  221. }
  222. }
  223. /**
  224. * Create the pagination link "appendage" for an element.
  225. *
  226. * @param string $element
  227. * @param int $page
  228. * @return string
  229. */
  230. protected function appendage($element, $page)
  231. {
  232. // The appendage string contains the query string, but it also contains a
  233. // place-holder for the page number. This will be used to insert the
  234. // correct page number based on the element being created.
  235. if (is_null($this->appendage))
  236. {
  237. $this->appendage = '?page=%s'.http_build_query((array) $this->appends);
  238. }
  239. return sprintf($this->appendage, $page);
  240. }
  241. /**
  242. * Set the items that should be appended to the link query strings.
  243. *
  244. * This provides a convenient method of maintaining sort or passing other information
  245. * to the route handling pagination.
  246. *
  247. * @param array $values
  248. * @return Paginator
  249. */
  250. public function appends($values)
  251. {
  252. $this->appends = $values;
  253. return $this;
  254. }
  255. /**
  256. * Set the elements that should be included when creating the pagination links.
  257. *
  258. * The available elements are "first", "previous", "status", "next", and "last".
  259. *
  260. * @param array $elements
  261. * @return string
  262. */
  263. public function elements($elements)
  264. {
  265. $this->elements = $elements;
  266. return $this;
  267. }
  268. }