UrlWindow.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://hyperf.wiki
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
  10. */
  11. namespace Hyperf\Paginator;
  12. use Hyperf\Contract\LengthAwarePaginatorInterface;
  13. class UrlWindow
  14. {
  15. /**
  16. * @param AbstractPaginator&LengthAwarePaginatorInterface $paginator
  17. */
  18. public function __construct(protected LengthAwarePaginatorInterface $paginator)
  19. {
  20. }
  21. /**
  22. * Create a new URL window instance.
  23. */
  24. public static function make(LengthAwarePaginatorInterface $paginator): array
  25. {
  26. return (new static($paginator))->get();
  27. }
  28. /**
  29. * Get the window of URLs to be shown.
  30. */
  31. public function get(): array
  32. {
  33. $onEachSide = $this->paginator->onEachSide;
  34. if ($this->paginator->lastPage() < ($onEachSide * 2) + 6) {
  35. return $this->getSmallSlider();
  36. }
  37. return $this->getUrlSlider($onEachSide);
  38. }
  39. /**
  40. * Get the page range for the current page window.
  41. */
  42. public function getAdjacentUrlRange(int $onEachSide): array
  43. {
  44. return $this->paginator->getUrlRange(
  45. $this->currentPage() - $onEachSide,
  46. $this->currentPage() + $onEachSide
  47. );
  48. }
  49. /**
  50. * Get the starting URLs of a pagination slider.
  51. */
  52. public function getStart(): array
  53. {
  54. return $this->paginator->getUrlRange(1, 2);
  55. }
  56. /**
  57. * Get the ending URLs of a pagination slider.
  58. */
  59. public function getFinish(): array
  60. {
  61. return $this->paginator->getUrlRange(
  62. $this->lastPage() - 1,
  63. $this->lastPage()
  64. );
  65. }
  66. /**
  67. * Determine if the underlying paginator being presented has pages to show.
  68. */
  69. public function hasPages(): bool
  70. {
  71. return $this->paginator->lastPage() > 1;
  72. }
  73. /**
  74. * Get the slider of URLs there are not enough pages to slide.
  75. */
  76. protected function getSmallSlider(): array
  77. {
  78. return [
  79. 'first' => $this->paginator->getUrlRange(1, $this->lastPage()),
  80. 'slider' => null,
  81. 'last' => null,
  82. ];
  83. }
  84. /**
  85. * Create a URL slider links.
  86. */
  87. protected function getUrlSlider(int $onEachSide): array
  88. {
  89. $window = $onEachSide * 2;
  90. if (! $this->hasPages()) {
  91. return ['first' => null, 'slider' => null, 'last' => null];
  92. }
  93. // If the current page is very close to the beginning of the page range, we will
  94. // just render the beginning of the page range, followed by the last 2 of the
  95. // links in this list, since we will not have room to create a full slider.
  96. if ($this->currentPage() <= $window) {
  97. return $this->getSliderTooCloseToBeginning($window);
  98. }
  99. // If the current page is close to the ending of the page range we will just get
  100. // this first couple pages, followed by a larger window of these ending pages
  101. // since we're too close to the end of the list to create a full on slider.
  102. if ($this->currentPage() > ($this->lastPage() - $window)) {
  103. return $this->getSliderTooCloseToEnding($window);
  104. }
  105. // If we have enough room on both sides of the current page to build a slider we
  106. // will surround it with both the beginning and ending caps, with this window
  107. // of pages in the middle providing a Google style sliding paginator setup.
  108. return $this->getFullSlider($onEachSide);
  109. }
  110. /**
  111. * Get the slider of URLs when too close to beginning of window.
  112. */
  113. protected function getSliderTooCloseToBeginning(int $window): array
  114. {
  115. return [
  116. 'first' => $this->paginator->getUrlRange(1, $window + 2),
  117. 'slider' => null,
  118. 'last' => $this->getFinish(),
  119. ];
  120. }
  121. /**
  122. * Get the slider of URLs when too close to ending of window.
  123. */
  124. protected function getSliderTooCloseToEnding(int $window): array
  125. {
  126. $last = $this->paginator->getUrlRange(
  127. $this->lastPage() - ($window + 2),
  128. $this->lastPage()
  129. );
  130. return [
  131. 'first' => $this->getStart(),
  132. 'slider' => null,
  133. 'last' => $last,
  134. ];
  135. }
  136. /**
  137. * Get the slider of URLs when a full slider can be made.
  138. */
  139. protected function getFullSlider(int $onEachSide): array
  140. {
  141. return [
  142. 'first' => $this->getStart(),
  143. 'slider' => $this->getAdjacentUrlRange($onEachSide),
  144. 'last' => $this->getFinish(),
  145. ];
  146. }
  147. /**
  148. * Get the current page from the paginator.
  149. */
  150. protected function currentPage(): int
  151. {
  152. return $this->paginator->currentPage();
  153. }
  154. /**
  155. * Get the last page from the paginator.
  156. */
  157. protected function lastPage(): int
  158. {
  159. return $this->paginator->lastPage();
  160. }
  161. }