page = $page; $this->last = $last; $this->total = $total; $this->results = $results; $this->per_page = $per_page; } /** * Create a new Paginator instance. * * @param array $results * @param int $total * @param int $per_page * @return Paginator */ public static function make($results, $total, $per_page) { $page = static::page($total, $per_page); $last_page = ceil($total / $per_page); return new static($results, $page, $total, $per_page, $last_page); } /** * Get the current page from the request query string. * * @param int $total * @param int $per_page * @return int */ public static function page($total, $per_page) { $page = Input::get('page', 1); // The page will be validated and adjusted if it is less than one or greater // than the last page. For example, if the current page is not an integer or // less than one, one will be returned. If the current page is greater than // the last page, the last page will be returned. if (is_numeric($page) and $page > $last = ceil($total / $per_page)) { return ($last > 0) ? $last : 1; } return ($page < 1 or filter_var($page, FILTER_VALIDATE_INT) === false) ? 1 : $page; } /** * Create the HTML pagination links. * * @return string */ public function links() { if ($this->last <= 1) return ''; // Each pagination element is created by an element method. This allows // us to keep this class clean and simple, because pagination code can // become a mess. We would rather keep it simple and beautiful. // // If the page is greater the one, we will render the first and previous // links, otherwise we skip them since we are already on the first page. if ($this->page > 1) { $elements[] = $this->first(); $elements[] = $this->previous(); } // The status is always rendered regardless of the current page. So we // can simply add it to the array of pagination elements. $elements[] = $this->status(); // If the current page is not the last page, we will render the next // and last links. Otherwise we will skip them since we are already // on the last page and can't go any further. if ($this->page < $this->last) { $elements[] = $this->next(); $elements[] = $this->last(); } return ''.PHP_EOL; } /** * Get the "status" pagination element. * * @param string $text * @return string */ public function status($text = null) { if (is_null($text)) $text = Lang::line('pagination.status')->get(); return str_replace(array(':current', ':last'), array($this->page, $this->last), $text); } /** * Create the "first" pagination element. * * @param string $text * @return string */ public function first($text = null) { return $this->backwards(__FUNCTION__, $text, 1); } /** * Create the "previous" pagination element. * * @param string $text * @return string */ public function previous($text = null) { return $this->backwards(__FUNCTION__, $text, $this->page - 1); } /** * Create the "next" pagination element. * * @param string $text * @return string */ public function next($text = null) { return $this->forwards(__FUNCTION__, $text, $this->page + 1); } /** * Create the "last" pagination element. * * @param string $text * @return string */ public function last($text = null) { return $this->forwards(__FUNCTION__, $text, $this->last); } /** * Create a "backwards" paginatino element. * * This function handles the creation of the first and previous elements. * * @param string $element * @param string $text * @param int $last * @return string */ protected function backwards($element, $text, $last) { $disabler = function($page) { return $page <= 1; }; return $this->element($element, $text, $last, $disabler); } /** * Create a "forwards" paginatino element. * * This function handles the creation of the next and last elements. * * @param string $element * @param string $text * @param int $last * @return string */ protected function forwards($element, $text, $last) { $disabler = function($page, $last) { return $page >= $last; }; return $this->element($element, $text, $last, $disabler); } /** * Create a chronological pagination element. * * @param string $element * @param string $text * @param int $page * @param Closure $disabler * @return string */ protected function element($element, $text, $page, $disabler) { $class = "{$element}_page"; if (is_null($text)) $text = Lang::line("pagination.{$element}")->get(); if ($disabler($this->page, $this->last)) { return HTML::span($text, array('class' => "disabled {$class}")); } else { // We will assume the page links should use HTTPS if the current request // is also using HTTPS. Since pagination links automatically point to // the current URI, this makes pretty good sense. list($uri, $secure) = array(Request::uri(), Request::secure()); $appendage = '?page='.$page.$this->appendage($element, $page); return HTML::link($uri.$appendage, $text, array('class' => $class), $secure); } } /** * Create the pagination link "appendage" for an element. * * @param string $element * @param int $page * @return string */ protected function appendage($element, $page) { if ( ! is_null($this->appendage)) return $this->appendage; $appendage = ''; if (count($this->appends) > 0) { $appendage .= '&'.http_build_query($this->appends); } return $this->appendage = $appendage; } /** * Set the items that should be appended to the link query strings. * * This provides a convenient method of maintaining sort or passing other * information to the route handling pagination. * * @param array $values * @return Paginator */ public function appends($values) { $this->appends = $values; return $this; } /** * Set the elements that should be included when creating the pagination links. * * The available elements are "first", "previous", "status", "next", and "last". * * @param array $elements * @return string */ public function elements($elements) { $this->elements = $elements; return $this; } }