| <?php |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| namespace think; |
|
|
| use ArrayAccess; |
| use ArrayIterator; |
| use Countable; |
| use IteratorAggregate; |
| use JsonSerializable; |
| use Traversable; |
|
|
| abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable |
| { |
| |
| protected $simple = false; |
|
|
| |
| protected $items; |
|
|
| |
| protected $currentPage; |
|
|
| |
| protected $lastPage; |
|
|
| |
| protected $total; |
|
|
| |
| protected $listRows; |
|
|
| |
| protected $hasMore; |
|
|
| |
| protected $options = [ |
| 'var_page' => 'page', |
| 'path' => '/', |
| 'query' => [], |
| 'fragment' => '', |
| ]; |
|
|
| |
| protected $nextItem; |
|
|
| public function __construct($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = []) |
| { |
| $this->options = array_merge($this->options, $options); |
|
|
| $this->options['path'] = '/' != $this->options['path'] ? rtrim($this->options['path'], '/') : $this->options['path']; |
|
|
| $this->simple = $simple; |
| $this->listRows = $listRows; |
|
|
| if (!$items instanceof Collection) { |
| $items = Collection::make($items); |
| } |
|
|
| if ($simple) { |
| $this->currentPage = $this->setCurrentPage($currentPage); |
| $this->hasMore = count($items) > ($this->listRows); |
| if ($this->hasMore) { |
| $this->nextItem = $items->slice($this->listRows, 1); |
| } |
| $items = $items->slice(0, $this->listRows); |
| } else { |
| $this->total = $total; |
| $this->lastPage = (int) ceil($total / $listRows); |
| $this->currentPage = $this->setCurrentPage($currentPage); |
| $this->hasMore = $this->currentPage < $this->lastPage; |
| } |
| $this->items = $items; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public static function make($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = []) |
| { |
| return new static($items, $listRows, $currentPage, $total, $simple, $options); |
| } |
|
|
| protected function setCurrentPage($currentPage) |
| { |
| if (!$this->simple && $currentPage > $this->lastPage) { |
| return $this->lastPage > 0 ? $this->lastPage : 1; |
| } |
|
|
| return $currentPage; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| protected function url($page) |
| { |
| if ($page <= 0) { |
| $page = 1; |
| } |
|
|
| if (strpos($this->options['path'], '[PAGE]') === false) { |
| $parameters = [$this->options['var_page'] => $page]; |
| $path = $this->options['path']; |
| } else { |
| $parameters = []; |
| $path = str_replace('[PAGE]', $page, $this->options['path']); |
| } |
| if (count($this->options['query']) > 0) { |
| $parameters = array_merge($this->options['query'], $parameters); |
| } |
| $url = $path; |
| if (!empty($parameters)) { |
| $url .= '?' . http_build_query($parameters, null, '&'); |
| } |
| return $url . $this->buildFragment(); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public static function getCurrentPage($varPage = 'page', $default = 1) |
| { |
| $page = (int) Request::instance()->param($varPage); |
|
|
| if (filter_var($page, FILTER_VALIDATE_INT) !== false && $page >= 1) { |
| return $page; |
| } |
|
|
| return $default; |
| } |
|
|
| |
| |
| |
| |
| public static function getCurrentPath() |
| { |
| return Request::instance()->baseUrl(); |
| } |
|
|
| public function total() |
| { |
| if ($this->simple) { |
| throw new \DomainException('not support total'); |
| } |
| return $this->total; |
| } |
|
|
| public function listRows() |
| { |
| return $this->listRows; |
| } |
|
|
| public function currentPage() |
| { |
| return $this->currentPage; |
| } |
|
|
| public function lastPage() |
| { |
| if ($this->simple) { |
| throw new \DomainException('not support last'); |
| } |
| return $this->lastPage; |
| } |
|
|
| |
| |
| |
| |
| public function hasPages() |
| { |
| return !(1 == $this->currentPage && !$this->hasMore); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public function getUrlRange($start, $end) |
| { |
| $urls = []; |
|
|
| for ($page = $start; $page <= $end; $page++) { |
| $urls[$page] = $this->url($page); |
| } |
|
|
| return $urls; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function fragment($fragment) |
| { |
| $this->options['fragment'] = $fragment; |
| return $this; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public function appends($key, $value = null) |
| { |
| if (!is_array($key)) { |
| $queries = [$key => $value]; |
| } else { |
| $queries = $key; |
| } |
|
|
| foreach ($queries as $k => $v) { |
| if ($k !== $this->options['var_page']) { |
| $this->options['query'][$k] = $v; |
| } |
| } |
|
|
| return $this; |
| } |
|
|
| |
| |
| |
| |
| |
| protected function buildFragment() |
| { |
| return $this->options['fragment'] ? '#' . $this->options['fragment'] : ''; |
| } |
|
|
| |
| |
| |
| |
| abstract public function render(); |
|
|
| public function items() |
| { |
| return $this->items->all(); |
| } |
|
|
| public function getCollection() |
| { |
| return $this->items; |
| } |
|
|
| public function isEmpty() |
| { |
| return $this->items->isEmpty(); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function each(callable $callback) |
| { |
| foreach ($this->items as $key => $item) { |
| $result = $callback($item, $key); |
| if (false === $result) { |
| break; |
| } elseif (!is_object($item)) { |
| $this->items[$key] = $result; |
| } |
| } |
|
|
| return $this; |
| } |
|
|
| |
| |
| |
| |
| |
| public function getIterator() |
| { |
| return new ArrayIterator($this->items->all()); |
| } |
|
|
| |
| |
| |
| |
| |
| public function offsetExists($offset) |
| { |
| return $this->items->offsetExists($offset); |
| } |
|
|
| |
| |
| |
| |
| |
| public function offsetGet($offset) |
| { |
| return $this->items->offsetGet($offset); |
| } |
|
|
| |
| |
| |
| |
| |
| public function offsetSet($offset, $value) |
| { |
| $this->items->offsetSet($offset, $value); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function offsetUnset($offset) |
| { |
| $this->items->offsetUnset($offset); |
| } |
|
|
| |
| |
| |
| public function count() |
| { |
| return $this->items->count(); |
| } |
|
|
| public function __toString() |
| { |
| return (string) $this->render(); |
| } |
|
|
| public function toArray() |
| { |
| if ($this->simple) { |
| return [ |
| 'per_page' => $this->listRows, |
| 'current_page' => $this->currentPage, |
| 'has_more' => $this->hasMore, |
| 'next_item' => $this->nextItem, |
| 'data' => $this->items->toArray(), |
| ]; |
| } else { |
| return [ |
| 'total' => $this->total, |
| 'per_page' => $this->listRows, |
| 'current_page' => $this->currentPage, |
| 'last_page' => $this->lastPage, |
| 'data' => $this->items->toArray(), |
| ]; |
| } |
|
|
| } |
|
|
| |
| |
| |
| public function jsonSerialize() |
| { |
| return $this->toArray(); |
| } |
|
|
| public function __call($name, $arguments) |
| { |
| $collection = $this->getCollection(); |
|
|
| $result = call_user_func_array([$collection, $name], $arguments); |
|
|
| if ($result === $collection) { |
| return $this; |
| } |
|
|
| return $result; |
| } |
|
|
| } |
|
|