/Datagrid/Pager.php

https://github.com/tobiasstrebitzer/SonataAdminBundle · PHP · 611 lines · 297 code · 71 blank · 243 comment · 37 complexity · ac4812b7b2ec87233e2e3090eb689575 MD5 · raw file

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