paginator.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  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. public $page;
  15. /**
  16. * The last page available for the result set.
  17. *
  18. * @var int
  19. */
  20. public $last;
  21. /**
  22. * The total number of results.
  23. *
  24. * @var int
  25. */
  26. public $total;
  27. /**
  28. * The number of items per page.
  29. *
  30. * @var int
  31. */
  32. public $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. $page = static::page($total, $per_page);
  82. $last_page = ceil($total / $per_page);
  83. return new static($results, $page, $total, $per_page, $last_page);
  84. }
  85. /**
  86. * Get the current page from the request query string.
  87. *
  88. * @param int $total
  89. * @param int $per_page
  90. * @return int
  91. */
  92. public static function page($total, $per_page)
  93. {
  94. $page = Input::get('page', 1);
  95. // The page will be validated and adjusted if it is less than one or greater
  96. // than the last page. For example, if the current page is not an integer or
  97. // less than one, one will be returned. If the current page is greater than
  98. // the last page, the last page will be returned.
  99. if (is_numeric($page) and $page > $last = ceil($total / $per_page))
  100. {
  101. return ($last > 0) ? $last : 1;
  102. }
  103. return ($page < 1 or filter_var($page, FILTER_VALIDATE_INT) === false) ? 1 : $page;
  104. }
  105. /**
  106. * Create the HTML pagination links.
  107. *
  108. * @return string
  109. */
  110. public function links()
  111. {
  112. if ($this->last <= 1) return '';
  113. // Each pagination element is created by an element method. This allows
  114. // us to keep this class clean and simple, because pagination code can
  115. // become a mess. We would rather keep it simple and beautiful.
  116. foreach ($this->elements as $element)
  117. {
  118. $elements[] = $this->$element(Lang::line("pagination.{$element}")->get());
  119. }
  120. return '<div class="pagination">'.implode(' ', $elements).'</div>'.PHP_EOL;
  121. }
  122. /**
  123. * Get the "status" pagination element.
  124. *
  125. * @param string $text
  126. * @return string
  127. */
  128. public function status($text)
  129. {
  130. return str_replace(array(':current', ':last'), array($this->page, $this->last), $text);
  131. }
  132. /**
  133. * Create the "first" pagination element.
  134. *
  135. * @param string $text
  136. * @return string
  137. */
  138. public function first($text)
  139. {
  140. return $this->backwards(__FUNCTION__, $text, 1);
  141. }
  142. /**
  143. * Create the "previous" pagination element.
  144. *
  145. * @param string $text
  146. * @return string
  147. */
  148. public function previous($text)
  149. {
  150. return $this->backwards(__FUNCTION__, $text, $this->page - 1);
  151. }
  152. /**
  153. * Create the "next" pagination element.
  154. *
  155. * @param string $text
  156. * @return string
  157. */
  158. public function next($text)
  159. {
  160. return $this->forwards(__FUNCTION__, $text, $this->page + 1);
  161. }
  162. /**
  163. * Create the "last" pagination element.
  164. *
  165. * @param string $text
  166. * @return string
  167. */
  168. public function last($text)
  169. {
  170. return $this->forwards(__FUNCTION__, $text, $this->last);
  171. }
  172. /**
  173. * Create a "backwards" paginatino element.
  174. *
  175. * This function handles the creation of the first and previous elements.
  176. *
  177. * @param string $element
  178. * @param string $text
  179. * @param int $last
  180. * @return string
  181. */
  182. protected function backwards($element, $text, $last)
  183. {
  184. $disabler = function($page) { return $page <= 1; };
  185. return $this->element($element, $text, $last, $disabler);
  186. }
  187. /**
  188. * Create a "forwards" paginatino element.
  189. *
  190. * This function handles the creation of the next and last elements.
  191. *
  192. * @param string $element
  193. * @param string $text
  194. * @param int $last
  195. * @return string
  196. */
  197. protected function forwards($element, $text, $last)
  198. {
  199. $disabler = function($page, $last) { return $page >= $last; };
  200. return $this->element($element, $text, $last, $disabler);
  201. }
  202. /**
  203. * Create a chronological pagination element.
  204. *
  205. * @param string $element
  206. * @param string $text
  207. * @param int $page
  208. * @param Closure $disabler
  209. * @return string
  210. */
  211. protected function element($element, $text, $page, $disabler)
  212. {
  213. $class = "{$element}_page";
  214. if ($disabler($this->page, $this->last))
  215. {
  216. return HTML::span($text, array('class' => "disabled {$class}"));
  217. }
  218. else
  219. {
  220. // We will assume the page links should use HTTPS if the current request
  221. // is also using HTTPS. Since pagination links automatically point to
  222. // the current URI, this makes pretty good sense.
  223. list($uri, $secure) = array(Request::uri(), Request::secure());
  224. $appendage = $this->appendage($element, $page);
  225. return HTML::link($uri.$appendage, $text, array('class' => $class), $secure);
  226. }
  227. }
  228. /**
  229. * Create the pagination link "appendage" for an element.
  230. *
  231. * @param string $element
  232. * @param int $page
  233. * @return string
  234. */
  235. protected function appendage($element, $page)
  236. {
  237. $this->appendage = '?page=%s';
  238. if (count($this->appends) > 0)
  239. {
  240. $this->appendage .= '&'.http_build_query($this->appends);
  241. }
  242. return sprintf($this->appendage, $page);
  243. }
  244. /**
  245. * Set the items that should be appended to the link query strings.
  246. *
  247. * This provides a convenient method of maintaining sort or passing other information
  248. * to the route handling pagination.
  249. *
  250. * @param array $values
  251. * @return Paginator
  252. */
  253. public function appends($values)
  254. {
  255. $this->appends = $values;
  256. return $this;
  257. }
  258. /**
  259. * Set the elements that should be included when creating the pagination links.
  260. *
  261. * The available elements are "first", "previous", "status", "next", and "last".
  262. *
  263. * @param array $elements
  264. * @return string
  265. */
  266. public function elements($elements)
  267. {
  268. $this->elements = $elements;
  269. return $this;
  270. }
  271. }