Commit abd269aa by Taylor Otwell

initial version of pagination library.

parent 2b132512
<?php namespace System\DB;
use System\DB;
use System\Config;
use System\Str;
use System\Config;
class Query {
......@@ -448,6 +448,25 @@ class Query {
}
/**
* Get paginated query results.
*
* @param int $per_page
* @return Paginator
*/
public function paginate($per_page)
{
$total = $this->count();
// Reset the SELECT clause so we can execute another query to get the results.
$this->select = null;
// Get the current page from the Paginator. The Paginator class will validate the page number.
$page = \System\Paginator::page(ceil($total / $per_page));
return new \System\Paginator($this->skip(($page - 1) * $per_page)->take($per_page)->get(), $total, $per_page);
}
/**
* Execute an INSERT statement.
*
* @param array $values
......
......@@ -36,6 +36,18 @@ class HTML {
}
/**
* Generate an HTML span tag.
*
* @param string $value
* @param array $attributes
* @return string
*/
public static function span($value, $attributes = array())
{
return '<span'.static::attributes($attributes).'>'.static::entities($value).'</span>';
}
/**
* Generate a HTML link.
*
* @param string $url
......
<?php namespace System;
class Paginator {
/**
* The results for the current page.
*
* @var array
*/
public $results;
/**
* The total number of results.
*
* @var int
*/
public $total;
/**
* The current page.
*
* @var int
*/
public $page;
/**
* The number of items per page.
*
* @var int
*/
public $per_page;
/**
* The last page number.
*
* @var int
*/
public $last_page;
/**
* Create a new Paginator instance.
*
* @param array $results
* @param int $total
* @param int $per_page
* @return void
*/
public function __construct($results, $total, $per_page)
{
$this->per_page = $per_page;
$this->results = $results;
$this->total = $total;
// Validate and set the current page. If the given page is greater than the last page, the
// current page will be set to the last page. If the given page is not an integer or is less
// than 1, the current page will be set to 1.
$this->page = static::page($this->last_page());
}
/**
* Get the current page from the request query string.
*
* @param int $last_page
* @return int
*/
public static function page($last_page)
{
$page = Input::get('page', 1);
if (is_numeric($page) and $page > $last_page)
{
return $last_page;
}
return (filter_var($page, FILTER_VALIDATE_INT) === false or $page < 1) ? 1 : $page;
}
/**
* Create the HTML pagination links.
*
* @param int $adjacent
* @return string
*/
public function links($adjacent = 3)
{
if ($this->last_page() > 1)
{
return '<div class="pagination">'.$this->previous().$this->numbers($adjacent).$this->next();
}
return '';
}
/**
* Generate the HTML numeric page links.
*
* @param int $adjacent
* @return string
*/
public function numbers($adjacent = 3)
{
// If there are not enough pages to make it worth sliding, we will show all of the pages.
//
// We add "7" for the constant elements in a slider: the first and last two links, the
// current page, and the two "..." strings.
return ($this->last_page() < 7 + ($adjacent * 2)) ? $this->range(1, $this->last_page()) : $this->slider($adjacent);
}
/**
* Build sliding list of HTML numeric page links.
*
* @param int $adjacent
* @return string
*/
protected function slider($adjacent)
{
$pagination = '';
if ($this->page <= $adjacent * 2)
{
// Buffer the current page with four pages to the right. Any more pages will interfere with hiding.
$pagination .= $this->range(1, 4 + ($adjacent * 2)).$this->ending();
}
elseif ($this->page >= $this->last_page() - ($adjacent * 2))
{
// Buffer with at least two pages to the left of the current page.
$pagination .= $this->beginning().$this->range($this->last_page() - 2 - ($adjacent * 2), $this->last_page());
}
else
{
$pagination .= $this->beginning().$this->range($this->page - $adjacent, $this->page + $adjacent).$this->ending();
}
return $pagination;
}
/**
* Generate the "previous" HTML link.
*
* @param string $value
* @return string
*/
public function previous($value = '&laquo; Previous')
{
if ($this->page > 1)
{
return HTML::link(Request::uri().'?page='.($this->page - 1), $value, array('class' => 'prev_page')).' ';
}
return HTML::span($value, array('class' => 'disabled prev_page')).' ';
}
/**
* Generate the "next" HTML link.
*
* @param string $value
* @return string
*/
public function next($value = 'Next &raquo;')
{
if ($this->page < $this->last_page())
{
return HTML::link(Request::uri().'?page='.($this->page + 1), $value, array('class' => 'next_page'));
}
return HTML::span($value, array('class' => 'disabled next_page'));
}
/**
* Build the first two page links for a sliding page range.
*
* @return string
*/
protected function beginning()
{
return $this->range(1, 2).' ... ';
}
/**
* Build the last two page links for a sliding page range.
*
* @return string
*/
protected function ending()
{
return ' ... '.$this->range($this->last_page() - 1, $this->last_page());
}
/**
* Calculate the last page based on the last page and the items per page.
*
* @return int
*/
protected function last_page()
{
return ceil($this->total / $this->per_page);
}
/**
* Build a range of page links.
*
* For the current page, an HTML span element will be generated instead of a link.
*
* @param int $start
* @param int $end
* @return string
*/
protected function range($start, $end)
{
$pages = '';
for ($i = $start; $i <= $end; $i++)
{
$pages .= ($this->page == $i) ? HTML::span($i, array('class' => 'current')).' ' : HTML::link(Request::uri().'?page='.$i, $i).' ';
}
return $pages;
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment