/src/Widgets/Paginator.php

https://github.com/jqhph/swoft-admin · PHP · 427 lines · 229 code · 61 blank · 137 comment · 30 complexity · 5dab6303e022298b03c17a64c3cd044a MD5 · raw file

  1. <?php
  2. namespace Swoft\Admin\Widgets;
  3. use Swoft\Support\Collection;
  4. use Swoft\Support\Contracts\Renderable;
  5. use Swoft\Support\Input;
  6. use Swoft\Support\Url;
  7. class Paginator implements Renderable
  8. {
  9. /**
  10. * @var Collection
  11. */
  12. protected $data;
  13. /**
  14. * 列表每页显示行数
  15. *
  16. * @var int
  17. */
  18. protected $perPage;
  19. /**
  20. * 页数跳转时要带的参数
  21. *
  22. * @var string
  23. */
  24. protected $parameter;
  25. /**
  26. * 分页总页面数
  27. *
  28. * @var int
  29. */
  30. protected $totalPages;
  31. /**
  32. * 总行数
  33. *
  34. * @var int
  35. */
  36. protected $total;
  37. /**
  38. * 当前页数
  39. *
  40. * @var int
  41. */
  42. protected $currentPage = 1;
  43. /**
  44. * 分页的栏的总页数
  45. *
  46. * @var int
  47. */
  48. protected $coolPages;
  49. /**
  50. * 分页栏按钮显示数量
  51. *
  52. * @var int
  53. */
  54. protected $pageButtonNumber;
  55. /**
  56. * 分页显示定制
  57. *
  58. * @var array
  59. */
  60. protected $config;
  61. /**
  62. * 分页跳转url
  63. *
  64. * @var string
  65. */
  66. protected $url;
  67. /**
  68. * 分页栏每页显示的页数的中间数
  69. *
  70. * @var int
  71. */
  72. protected $centerNum;
  73. /**
  74. * 生成分页字符串
  75. *
  76. * @param int $total 总行数
  77. * @param int $perPage 列表每页显示的行数
  78. * @param int $rollNum 分页栏每页显示的页数
  79. * @param string|array $parameter url参数
  80. */
  81. public function __construct(int $total, int $perPage = 10, int $pageButtonNumber = 8, $parameter = '')
  82. {
  83. $this->config = [
  84. 'totalText' => '',
  85. 'prev' => '<',
  86. 'next' => '>',
  87. 'first' => '<<',
  88. 'last' => '>>',
  89. 'ele' => 'a',
  90. 'itemEle' => '<li class="paginate_button">',
  91. 'activeItemEle' => '<li class="paginate_button active">',
  92. 'itemEleEnd' => '</li>',
  93. 'class' => '',
  94. 'currentClass' => 'active',
  95. 'pagekey' => '_p',
  96. 'theme' => '%header%%pageinfo%%first%%upPage%%linkPage%%downPage%%end%'
  97. ];
  98. $this->total = $total;
  99. $this->parameter = $parameter;
  100. $this->pageButtonNumber = $pageButtonNumber;
  101. $this->perPage = $perPage;
  102. }
  103. /**
  104. * 当前页数据
  105. *
  106. * @param array $data
  107. * @return $this
  108. */
  109. public function setData(array $data)
  110. {
  111. $this->data = new Collection($data);
  112. }
  113. /**
  114. * 当前页数据
  115. *
  116. * @return Collection
  117. */
  118. public function getCollection()
  119. {
  120. return $this->data ?? new Collection();
  121. }
  122. /**
  123. * 每页显示数量
  124. *
  125. * @return int
  126. */
  127. public function getPerPage()
  128. {
  129. return $this->perPage;
  130. }
  131. /**
  132. * @param string $key
  133. * @return $this
  134. */
  135. public function setPageName(string $key)
  136. {
  137. return $this->set('pagekey', $key);
  138. }
  139. /**
  140. * @return string
  141. */
  142. public function getPageName()
  143. {
  144. return $this->config['pagekey'];
  145. }
  146. /**
  147. * @return int
  148. */
  149. public function lastPage()
  150. {
  151. return ceil($this->total / $this->perPage);
  152. }
  153. /**
  154. * @return int
  155. */
  156. public function currentPage()
  157. {
  158. return (int)Input::get($this->config['pagekey'], 1);
  159. }
  160. /**
  161. * @return int
  162. */
  163. public function total()
  164. {
  165. return $this->total;
  166. }
  167. /**
  168. * 生成分页字符串
  169. *
  170. * @return string
  171. */
  172. public function render()
  173. {
  174. $this->totalPages = $this->lastPage(); //总页数
  175. $this->currentPage = $this->currentPage();
  176. $this->coolPages = ceil($this->totalPages / $this->pageButtonNumber);
  177. if ($this->currentPage > $this->totalPages) {
  178. $this->currentPage = $this->totalPages;
  179. }
  180. if ($this->currentPage < 1) {
  181. $this->currentPage = 1;
  182. }
  183. // 计算分页栏每页显示的页数的中间数
  184. $temp = $this->pageButtonNumber % 2;
  185. if ($temp == 0) {
  186. $this->centerNum = $this->pageButtonNumber / 2;
  187. } else {
  188. $this->centerNum = ($this->pageButtonNumber - 1) / 2 + 1;
  189. }
  190. return $this->show();
  191. }
  192. /**
  193. * 设置配置参数
  194. *
  195. * @param string $name
  196. * @param mixed $value
  197. * @return $this
  198. */
  199. public function set($name, $value)
  200. {
  201. if (isset($this->config[$name])) {
  202. $this->config[$name] = &$value;
  203. }
  204. return $this;
  205. }
  206. /**
  207. * 获取url
  208. *
  209. * @return string
  210. */
  211. public function url()
  212. {
  213. if ($this->url) {
  214. return $this->url;
  215. }
  216. $params = &$this->parameter;
  217. if ($this->parameter && is_string($this->parameter)) {
  218. $params = parse_str($this->parameter);
  219. }
  220. $query = Url::query();
  221. if (is_array($params) && !empty($params)) {
  222. $query->add($params);
  223. }
  224. $query->delete($this->config['pagekey']);
  225. $query->delete('_pjax');
  226. $url = $query->build();
  227. return $this->url = strpos($url, '?') === false ? ($url.'?') : $url;
  228. }
  229. /**
  230. * @return string
  231. */
  232. protected function show()
  233. {
  234. if (0 == $this->total) return '';
  235. return str_replace(
  236. [
  237. '%header%',
  238. '%pageinfo%',
  239. '%first%',
  240. '%upPage%',
  241. '%linkPage%',
  242. '%downPage%',
  243. '%end%'
  244. ],
  245. [
  246. $this->header(),
  247. $this->pageinfo(),
  248. $this->first(),
  249. $this->prev(),
  250. $this->pageList(),
  251. $this->next(),
  252. $this->last()
  253. ],
  254. $this->config['theme']
  255. );
  256. }
  257. /**
  258. * @return string
  259. */
  260. protected function header()
  261. {
  262. return "{$this->config['itemEle']}<span class='{$this->config['class']}'> &nbsp;{$this->config['totalText']} {$this->total}";
  263. }
  264. protected function pageinfo()
  265. {
  266. return "&nbsp;&nbsp;&nbsp; {$this->currentPage}/{$this->totalPages} &nbsp;</span>{$this->config['itemEleEnd']}";
  267. }
  268. /**
  269. * 1 2 3 4 5
  270. *
  271. * @return string
  272. */
  273. protected function pageList()
  274. {
  275. $p = $this->config['pagekey'];
  276. $url = $this->url();
  277. $linkPage = '';
  278. for ($i = 1; $i <= $this->pageButtonNumber; $i++) {
  279. $_ = $this->currentPage - $this->centerNum;
  280. if ($_ <= 0) {
  281. $_ = 0;
  282. } elseif ($this->currentPage + $this->centerNum >= $this->totalPages) {
  283. $_ = $this->totalPages - $this->pageButtonNumber;
  284. $_ = $_ < 0 ? 0 : $_;
  285. }
  286. $page = $_ + $i;
  287. if ($page != $this->currentPage) {
  288. if ($page <= $this->totalPages) {
  289. $linkPage .= "{$this->config['itemEle']}<{$this->config['ele']} class='{$this->config['class']}'
  290. href='$url&$p=$page' data-page='$page'> $page </{$this->config['ele']}>{$this->config['itemEleEnd']}";
  291. } else {
  292. break;
  293. }
  294. } else {
  295. if ($this->totalPages != 1) {
  296. $linkPage .=
  297. "{$this->config['activeItemEle']}<span class='{$this->config['class']}'>$page</span>{$this->config['itemEleEnd']}";
  298. }
  299. }
  300. }
  301. return $linkPage;
  302. }
  303. /**
  304. * @return string
  305. */
  306. protected function prev()
  307. {
  308. $p = $this->config['pagekey'];
  309. $url = $this->url();
  310. //上下翻页字符串
  311. $upRow = $this->currentPage - 1;
  312. if ($upRow > 0) {
  313. $upPage = "{$this->config['itemEle']}<{$this->config['ele']} class='{$this->config['class']}'
  314. data-page='$upRow' href='$url&$p=$upRow'>{$this->config['prev']}</{$this->config['ele']}>{$this->config['itemEleEnd']}";
  315. } else {
  316. $upPage = '';
  317. }
  318. return $upPage;
  319. }
  320. /**
  321. * @return string
  322. */
  323. protected function next()
  324. {
  325. $p = $this->config['pagekey'];
  326. $url = $this->url();
  327. //上下翻页字符串
  328. $downRow = $this->currentPage + 1;
  329. if ($downRow <= $this->totalPages) {
  330. $downPage = "{$this->config['itemEle']}<{$this->config['ele']} class='{$this->config['class']}' data-page='$downRow' href='$url&$p=$downRow'>{$this->config['next']}</{$this->config['ele']}>{$this->config['itemEleEnd']}";
  331. } else {
  332. $downPage = '';
  333. }
  334. return $downPage;
  335. }
  336. /**
  337. * @return string
  338. */
  339. protected function first()
  340. {
  341. $p = $this->config['pagekey'];
  342. $url = $this->url();
  343. // << < > >>
  344. if ($this->currentPage - $this->centerNum <= 0) {
  345. $theFirst = '';
  346. } else {
  347. $theFirst = "{$this->config['itemEle']}<{$this->config['ele']} class='{$this->config['class']}' data-page='1' href='$url&$p=1' > {$this->config['first']}</{$this->config['ele']}>{$this->config['itemEleEnd']}";
  348. }
  349. return $theFirst;
  350. }
  351. /**
  352. * @return string
  353. */
  354. protected function last()
  355. {
  356. $p = $this->config['pagekey'];
  357. $url = $this->url();
  358. if ($this->centerNum + $this->currentPage >= $this->totalPages) {
  359. $theEnd = '';
  360. } else {
  361. $theEnd = "{$this->config['itemEle']}<{$this->config['ele']} class='{$this->config['class']}' data-page='{$this->totalPages}' href='$url&$p={$this->totalPages}' >
  362. {$this->config['last']}</{$this->config['ele']}>{$this->config['itemEle']}";
  363. }
  364. return $theEnd;
  365. }
  366. }