Pager.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  5. *
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. namespace Bundle\Sonata\BaseApplicationBundle\Tool;
  10. /**
  11. * sfPager class.
  12. *
  13. * @package symfony
  14. * @subpackage addon
  15. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  16. * @version SVN: $Id: sfPager.class.php 27747 2010-02-08 18:02:19Z Kris.Wallsmith $
  17. */
  18. abstract class Pager implements \Iterator, \Countable
  19. {
  20. protected
  21. $page = 1,
  22. $maxPerPage = 0,
  23. $lastPage = 1,
  24. $nbResults = 0,
  25. $class = '',
  26. $tableName = '',
  27. $objects = null,
  28. $cursor = 1,
  29. $parameters = array(),
  30. $currentMaxLink = 1,
  31. $parameterBag = null,
  32. $maxRecordLimit = false,
  33. // used by iterator interface
  34. $results = null,
  35. $resultsCounter = 0;
  36. /**
  37. * Constructor.
  38. *
  39. * @param string $class The model class
  40. * @param integer $maxPerPage Number of records to display per page
  41. */
  42. public function __construct($class, $maxPerPage = 10)
  43. {
  44. $this->setClass($class);
  45. $this->setMaxPerPage($maxPerPage);
  46. }
  47. /**
  48. * Initialize the pager.
  49. *
  50. * Function to be called after parameters have been set.
  51. */
  52. abstract public function init();
  53. /**
  54. * Returns an array of results on the given page.
  55. *
  56. * @return array
  57. */
  58. abstract public function getResults();
  59. /**
  60. * Returns an object at a certain offset.
  61. *
  62. * Used internally by {@link getCurrent()}.
  63. *
  64. * @return mixed
  65. */
  66. abstract protected function retrieveObject($offset);
  67. /**
  68. * Returns the current pager's max link.
  69. *
  70. * @return integer
  71. */
  72. public function getCurrentMaxLink()
  73. {
  74. return $this->currentMaxLink;
  75. }
  76. /**
  77. * Returns the current pager's max record limit.
  78. *
  79. * @return integer
  80. */
  81. public function getMaxRecordLimit()
  82. {
  83. return $this->maxRecordLimit;
  84. }
  85. /**
  86. * Sets the current pager's max record limit.
  87. *
  88. * @param integer $limit
  89. */
  90. public function setMaxRecordLimit($limit)
  91. {
  92. $this->maxRecordLimit = $limit;
  93. }
  94. /**
  95. * Returns an array of page numbers to use in pagination links.
  96. *
  97. * @param integer $nb_links The maximum number of page numbers to return
  98. *
  99. * @return array
  100. */
  101. public function getLinks($nb_links = 5)
  102. {
  103. $links = array();
  104. $tmp = $this->page - floor($nb_links / 2);
  105. $check = $this->lastPage - $nb_links + 1;
  106. $limit = $check > 0 ? $check : 1;
  107. $begin = $tmp > 0 ? ($tmp > $limit ? $limit : $tmp) : 1;
  108. $i = (int) $begin;
  109. while ($i < $begin + $nb_links && $i <= $this->lastPage)
  110. {
  111. $links[] = $i++;
  112. }
  113. $this->currentMaxLink = count($links) ? $links[count($links) - 1] : 1;
  114. return $links;
  115. }
  116. /**
  117. * Returns true if the current query requires pagination.
  118. *
  119. * @return boolean
  120. */
  121. public function haveToPaginate()
  122. {
  123. return $this->getMaxPerPage() && $this->getNbResults() > $this->getMaxPerPage();
  124. }
  125. /**
  126. * Returns the current cursor.
  127. *
  128. * @return integer
  129. */
  130. public function getCursor()
  131. {
  132. return $this->cursor;
  133. }
  134. /**
  135. * Sets the current cursor.
  136. *
  137. * @param integer $pos
  138. */
  139. public function setCursor($pos)
  140. {
  141. if ($pos < 1) {
  142. $this->cursor = 1;
  143. }
  144. else {
  145. if ($pos > $this->nbResults) {
  146. $this->cursor = $this->nbResults;
  147. }
  148. else
  149. {
  150. $this->cursor = $pos;
  151. }
  152. }
  153. }
  154. /**
  155. * Returns an object by cursor position.
  156. *
  157. * @param integer $pos
  158. *
  159. * @return mixed
  160. */
  161. public function getObjectByCursor($pos)
  162. {
  163. $this->setCursor($pos);
  164. return $this->getCurrent();
  165. }
  166. /**
  167. * Returns the current object.
  168. *
  169. * @return mixed
  170. */
  171. public function getCurrent()
  172. {
  173. return $this->retrieveObject($this->cursor);
  174. }
  175. /**
  176. * Returns the next object.
  177. *
  178. * @return mixed|null
  179. */
  180. public function getNext()
  181. {
  182. if ($this->cursor + 1 > $this->nbResults) {
  183. return null;
  184. }
  185. else
  186. {
  187. return $this->retrieveObject($this->cursor + 1);
  188. }
  189. }
  190. /**
  191. * Returns the previous object.
  192. *
  193. * @return mixed|null
  194. */
  195. public function getPrevious()
  196. {
  197. if ($this->cursor - 1 < 1) {
  198. return null;
  199. }
  200. else
  201. {
  202. return $this->retrieveObject($this->cursor - 1);
  203. }
  204. }
  205. /**
  206. * Returns the first index on the current page.
  207. *
  208. * @return integer
  209. */
  210. public function getFirstIndice()
  211. {
  212. if ($this->page == 0) {
  213. return 1;
  214. }
  215. else
  216. {
  217. return ($this->page - 1) * $this->maxPerPage + 1;
  218. }
  219. }
  220. /**
  221. * Returns the last index on the current page.
  222. *
  223. * @return integer
  224. */
  225. public function getLastIndice()
  226. {
  227. if ($this->page == 0) {
  228. return $this->nbResults;
  229. }
  230. else
  231. {
  232. if ($this->page * $this->maxPerPage >= $this->nbResults) {
  233. return $this->nbResults;
  234. }
  235. else
  236. {
  237. return $this->page * $this->maxPerPage;
  238. }
  239. }
  240. }
  241. /**
  242. * Returns the current class.
  243. *
  244. * @return string
  245. */
  246. public function getClass()
  247. {
  248. return $this->class;
  249. }
  250. /**
  251. * Sets the current class.
  252. *
  253. * @param string $class
  254. */
  255. public function setClass($class)
  256. {
  257. $this->class = $class;
  258. }
  259. /**
  260. * Returns the number of results.
  261. *
  262. * @return integer
  263. */
  264. public function getNbResults()
  265. {
  266. return $this->nbResults;
  267. }
  268. /**
  269. * Sets the number of results.
  270. *
  271. * @param integer $nb
  272. */
  273. protected function setNbResults($nb)
  274. {
  275. $this->nbResults = $nb;
  276. }
  277. /**
  278. * Returns the first page number.
  279. *
  280. * @return integer
  281. */
  282. public function getFirstPage()
  283. {
  284. return 1;
  285. }
  286. /**
  287. * Returns the last page number.
  288. *
  289. * @return integer
  290. */
  291. public function getLastPage()
  292. {
  293. return $this->lastPage;
  294. }
  295. /**
  296. * Sets the last page number.
  297. *
  298. * @param integer $page
  299. */
  300. protected function setLastPage($page)
  301. {
  302. $this->lastPage = $page;
  303. if ($this->getPage() > $page) {
  304. $this->setPage($page);
  305. }
  306. }
  307. /**
  308. * Returns the current page.
  309. *
  310. * @return integer
  311. */
  312. public function getPage()
  313. {
  314. return $this->page;
  315. }
  316. /**
  317. * Returns the next page.
  318. *
  319. * @return integer
  320. */
  321. public function getNextPage()
  322. {
  323. return min($this->getPage() + 1, $this->getLastPage());
  324. }
  325. /**
  326. * Returns the previous page.
  327. *
  328. * @return integer
  329. */
  330. public function getPreviousPage()
  331. {
  332. return max($this->getPage() - 1, $this->getFirstPage());
  333. }
  334. /**
  335. * Sets the current page.
  336. *
  337. * @param integer $page
  338. */
  339. public function setPage($page)
  340. {
  341. $this->page = intval($page);
  342. if ($this->page <= 0) {
  343. // set first page, which depends on a maximum set
  344. $this->page = $this->getMaxPerPage() ? 1 : 0;
  345. }
  346. }
  347. /**
  348. * Returns the maximum number of results per page.
  349. *
  350. * @return integer
  351. */
  352. public function getMaxPerPage()
  353. {
  354. return $this->maxPerPage;
  355. }
  356. /**
  357. * Sets the maximum number of results per page.
  358. *
  359. * @param integer $max
  360. */
  361. public function setMaxPerPage($max)
  362. {
  363. if ($max > 0) {
  364. $this->maxPerPage = $max;
  365. if ($this->page == 0) {
  366. $this->page = 1;
  367. }
  368. }
  369. else {
  370. if ($max == 0) {
  371. $this->maxPerPage = 0;
  372. $this->page = 0;
  373. }
  374. else
  375. {
  376. $this->maxPerPage = 1;
  377. if ($this->page == 0) {
  378. $this->page = 1;
  379. }
  380. }
  381. }
  382. }
  383. /**
  384. * Returns true if on the first page.
  385. *
  386. * @return boolean
  387. */
  388. public function isFirstPage()
  389. {
  390. return 1 == $this->page;
  391. }
  392. /**
  393. * Returns true if on the last page.
  394. *
  395. * @return boolean
  396. */
  397. public function isLastPage()
  398. {
  399. return $this->page == $this->lastPage;
  400. }
  401. /**
  402. * Returns the current pager's parameter holder.
  403. *
  404. * @return sfParameterHolder
  405. */
  406. public function getParameters()
  407. {
  408. return $this->parameters;
  409. }
  410. /**
  411. * Returns a parameter.
  412. *
  413. * @param string $name
  414. * @param mixed $default
  415. *
  416. * @return mixed
  417. */
  418. public function getParameter($name, $default = null)
  419. {
  420. return isset($this->parameters[$name]) ? $this->parameters[$name] : $default;
  421. }
  422. /**
  423. * Checks whether a parameter has been set.
  424. *
  425. * @param string $name
  426. *
  427. * @return boolean
  428. */
  429. public function hasParameter($name)
  430. {
  431. return isset($this->parameters[$name]);
  432. }
  433. /**
  434. * Sets a parameter.
  435. *
  436. * @param string $name
  437. * @param mixed $value
  438. */
  439. public function setParameter($name, $value)
  440. {
  441. $this->parameters[$name] = $value;
  442. }
  443. /**
  444. * Returns true if the properties used for iteration have been initialized.
  445. *
  446. * @return boolean
  447. */
  448. protected function isIteratorInitialized()
  449. {
  450. return null !== $this->results;
  451. }
  452. /**
  453. * Loads data into properties used for iteration.
  454. */
  455. protected function initializeIterator()
  456. {
  457. $this->results = $this->getResults();
  458. $this->resultsCounter = count($this->results);
  459. }
  460. /**
  461. * Empties properties used for iteration.
  462. */
  463. protected function resetIterator()
  464. {
  465. $this->results = null;
  466. $this->resultsCounter = 0;
  467. }
  468. /**
  469. * Returns the current result.
  470. *
  471. * @see Iterator
  472. */
  473. public function current()
  474. {
  475. if (!$this->isIteratorInitialized()) {
  476. $this->initializeIterator();
  477. }
  478. return current($this->results);
  479. }
  480. /**
  481. * Returns the current key.
  482. *
  483. * @see Iterator
  484. */
  485. public function key()
  486. {
  487. if (!$this->isIteratorInitialized()) {
  488. $this->initializeIterator();
  489. }
  490. return key($this->results);
  491. }
  492. /**
  493. * Advances the internal pointer and returns the current result.
  494. *
  495. * @see Iterator
  496. */
  497. public function next()
  498. {
  499. if (!$this->isIteratorInitialized()) {
  500. $this->initializeIterator();
  501. }
  502. --$this->resultsCounter;
  503. return next($this->results);
  504. }
  505. /**
  506. * Resets the internal pointer and returns the current result.
  507. *
  508. * @see Iterator
  509. */
  510. public function rewind()
  511. {
  512. if (!$this->isIteratorInitialized()) {
  513. $this->initializeIterator();
  514. }
  515. $this->resultsCounter = count($this->results);
  516. return reset($this->results);
  517. }
  518. /**
  519. * Returns true if pointer is within bounds.
  520. *
  521. * @see Iterator
  522. */
  523. public function valid()
  524. {
  525. if (!$this->isIteratorInitialized()) {
  526. $this->initializeIterator();
  527. }
  528. return $this->resultsCounter > 0;
  529. }
  530. /**
  531. * Returns the total number of results.
  532. *
  533. * @see Countable
  534. */
  535. public function count()
  536. {
  537. return $this->getNbResults();
  538. }
  539. }