Skip to content

Instantly share code, notes, and snippets.

@mcfog
Created January 3, 2015 03:32
Show Gist options
  • Save mcfog/2df96e37fc7fe3edbc6e to your computer and use it in GitHub Desktop.
Save mcfog/2df96e37fc7fe3edbc6e to your computer and use it in GitHub Desktop.
<?php
class Paginator implements \IteratorAggregate
{
const TPL_WRAPPER = 'wrapper';
const TPL_NUM = 'num';
const TPL_NUM_CURRENT = 'currentNum';
const TPL_TAG = 'tag';
const TPL_NEXT = 'next';
const TPL_PREV = 'prev';
const TPL_TEXT = 'text';
const CFG_FIELD_NAME = 'fieldName';
/**
* 当前页前后显示几页
*/
const CFG_NUM_MIDDLE = 'middleNum';
/**
* 末页前显示几页
*/
const CFG_NUM_TAIL = 'tailNum';
/**
* 首页后显示几页
*/
const CFG_NUM_HEAD = 'headNum';
protected $app;
protected $data;
/**
* @var IListProvider
*/
protected $list;
protected $config = [
self::CFG_NUM_HEAD => 1,
self::CFG_NUM_TAIL => 1,
self::CFG_NUM_MIDDLE => 2,
self::CFG_FIELD_NAME => 'page',
];
protected $template = [
self::TPL_WRAPPER => <<<'HTML'
<div class="page_right fontsize9 fontcolor3">%s</div>
HTML
,
self::TPL_NUM => <<<'HTML'
<a class="p_num" href="%2$s">%1$d</a>
HTML
,
self::TPL_NUM_CURRENT => <<<'HTML'
<a class="p_num selected">%1$d</a>
HTML
,
self::TPL_TAG => <<<'HTML'
<a class="p_num first_or_last" href="%2$s">%1$s</a>
HTML
,
self::TPL_TEXT => <<<'HTML'
<span class="page_dian">%s</span>
HTML
,
self::TPL_NEXT => <<<'HTML'
<a class="p_num next" href="%1$s">下一页</a>
HTML
,
self::TPL_PREV => <<<'HTML'
<a class="p_num previous" href="%1$s">上一页</a>
HTML
,
];
/**
* @var string
*/
protected $urlBase;
/**
* @param Site $app
* @param IListProvider $list
* @param string $urlBase
*/
public function __construct(Site $app, IListProvider $list, $urlBase = null)
{
if (is_null($urlBase)) {
$urlBase = $app->request->getPath();
}
$this->app = $app;
$this->list = $list;
$this->urlBase = $urlBase;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Retrieve an external iterator
* @link http://php.net/manual/en/iteratoraggregate.getiterator.php
* @return Traversable An instance of an object implementing <b>Iterator</b> or
* <b>Traversable</b>
*/
public function getIterator()
{
return new \ArrayIterator($this->getData());
}
public function renderPaginator()
{
$maxPage = $this->getMaxPage();
$curPage = $this->getCurrentPage();
if($maxPage <= 1) {
return '';
}
$contents = [];
// $contents[] = $this->renderTpl(self::TPL_TAG, '首页', $this->getUrlForPage(1));
if ($curPage !== 1) {
$contents[] = $this->renderTpl(self::TPL_PREV, $this->getUrlForPage($curPage - 1));
}
for ($i = 1; $i <= $maxPage; $i++) {
$middleCount = $this->config[self::CFG_NUM_MIDDLE];
switch (true) {
case $i === $curPage:
$contents[] = $this->renderTpl(self::TPL_NUM_CURRENT, $i);
break;
case $i >= $curPage - $middleCount && $i <= $curPage + $middleCount:
case $i <= $this->config[self::CFG_NUM_HEAD]:
case $i > $maxPage - $this->config[self::CFG_NUM_TAIL]:
$contents[] = $this->renderTpl(self::TPL_NUM, $i, $this->getUrlForPage($i));
break;
default:
if ($i < $curPage) {
$contents[] = $this->renderTpl(self::TPL_TEXT, '...');
$i = $curPage - $middleCount - 1;
} else {
$contents[] = $this->renderTpl(self::TPL_TEXT, '...');
$i = $maxPage - $this->config[self::CFG_NUM_TAIL];
}
}
}
if ($curPage !== $maxPage) {
$contents[] = $this->renderTpl(self::TPL_NEXT, $this->getUrlForPage($curPage + 1));
}
// $contents[] = $this->renderTpl(self::TPL_TAG, '末页', $this->getUrlForPage($maxPage));
return $this->renderTpl(self::TPL_WRAPPER, implode('', $contents));
}
public function getUrlForPage($page)
{
$part = parse_url($this->urlBase);
$query = [];
if (isset($part['query'])) {
parse_str($part['query'], $query);
}
$query[$this->config[self::CFG_FIELD_NAME]] = $page;
if (!isset($part['path'])) {
$part['path'] = '/';
}
return sprintf('%s?%s', $part['path'], http_build_query($query));
}
protected function renderTpl($tpl)
{
$args = func_get_args();
$args[0] = $this->template[$tpl];
return call_user_func_array('sprintf', $args);
}
/**
* @return int
*/
protected function getCurrentPage()
{
$page = intval($this->app->request->get($this->config[self::CFG_FIELD_NAME]));
return min(max($page, 1), $this->getMaxPage());
}
protected function getPager()
{
return $this->list->getPager();
}
public function getItemCount()
{
$pager = $this->getPager();
return intval($pager['count']);
}
public function getMaxPage()
{
$pager = $this->getPager();
return intval($pager['maxPage']);
}
/**
* @return array
*/
protected function getData()
{
if (!isset($this->data)) {
$this->data = $this->list->fetch($this->getCurrentPage());
}
return $this->data;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment