Paginator.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Paginator
  17. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id$
  20. */
  21. /**
  22. * @see Zend_Loader_PluginLoader
  23. */
  24. require_once 'Zend/Loader/PluginLoader.php';
  25. /**
  26. * @see Zend_Json
  27. */
  28. require_once 'Zend/Json.php';
  29. /**
  30. * @category Zend
  31. * @package Zend_Paginator
  32. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. */
  35. class Zend_Paginator implements Countable, IteratorAggregate
  36. {
  37. /**
  38. * Specifies that the factory should try to detect the proper adapter type first
  39. *
  40. * @var string
  41. */
  42. const INTERNAL_ADAPTER = 'Zend_Paginator_Adapter_Internal';
  43. /**
  44. * The cache tag prefix used to namespace Paginator results in the cache
  45. *
  46. */
  47. const CACHE_TAG_PREFIX = 'Zend_Paginator_';
  48. /**
  49. * Adapter plugin loader
  50. *
  51. * @var Zend_Loader_PluginLoader
  52. */
  53. protected static $_adapterLoader = null;
  54. /**
  55. * Configuration file
  56. *
  57. * @var Zend_Config
  58. */
  59. protected static $_config = null;
  60. /**
  61. * Default scrolling style
  62. *
  63. * @var string
  64. */
  65. protected static $_defaultScrollingStyle = 'Sliding';
  66. /**
  67. * Scrolling style plugin loader
  68. *
  69. * @var Zend_Loader_PluginLoader
  70. */
  71. protected static $_scrollingStyleLoader = null;
  72. /**
  73. * Cache object
  74. *
  75. * @var Zend_Cache_Core
  76. */
  77. protected static $_cache;
  78. /**
  79. * Enable or desable the cache by Zend_Paginator instance
  80. *
  81. * @var bool
  82. */
  83. protected $_cacheEnabled = true;
  84. /**
  85. * Adapter
  86. *
  87. * @var Zend_Paginator_Adapter_Interface
  88. */
  89. protected $_adapter = null;
  90. /**
  91. * Number of items in the current page
  92. *
  93. * @var integer
  94. */
  95. protected $_currentItemCount = null;
  96. /**
  97. * Current page items
  98. *
  99. * @var Traversable
  100. */
  101. protected $_currentItems = null;
  102. /**
  103. * Current page number (starting from 1)
  104. *
  105. * @var integer
  106. */
  107. protected $_currentPageNumber = 1;
  108. /**
  109. * Result filter
  110. *
  111. * @var Zend_Filter_Interface
  112. */
  113. protected $_filter = null;
  114. /**
  115. * Number of items per page
  116. *
  117. * @var integer
  118. */
  119. protected $_itemCountPerPage = 10;
  120. /**
  121. * Number of pages
  122. *
  123. * @var integer
  124. */
  125. protected $_pageCount = null;
  126. /**
  127. * Number of local pages (i.e., the number of discrete page numbers
  128. * that will be displayed, including the current page number)
  129. *
  130. * @var integer
  131. */
  132. protected $_pageRange = 10;
  133. /**
  134. * Pages
  135. *
  136. * @var array
  137. */
  138. protected $_pages = null;
  139. /**
  140. * View instance used for self rendering
  141. *
  142. * @var Zend_View_Interface
  143. */
  144. protected $_view = null;
  145. /**
  146. * Adds an adapter prefix path to the plugin loader.
  147. *
  148. * @param string $prefix
  149. * @param string $path
  150. */
  151. public static function addAdapterPrefixPath($prefix, $path)
  152. {
  153. self::getAdapterLoader()->addPrefixPath($prefix, $path);
  154. }
  155. /**
  156. * Adds an array of adapter prefix paths to the plugin
  157. * loader.
  158. *
  159. * <code>
  160. * $prefixPaths = array(
  161. * 'My_Paginator_Adapter' => 'My/Paginator/Adapter/',
  162. * 'Your_Paginator_Adapter' => 'Your/Paginator/Adapter/'
  163. * );
  164. * </code>
  165. *
  166. * @param array $prefixPaths
  167. */
  168. public static function addAdapterPrefixPaths(array $prefixPaths)
  169. {
  170. if (isset($prefixPaths['prefix']) and isset($prefixPaths['path'])) {
  171. self::addAdapterPrefixPath($prefixPaths['prefix'], $prefixPaths['path']);
  172. } else {
  173. foreach ($prefixPaths as $prefix => $path) {
  174. if (is_array($path) and isset($path['prefix']) and isset($path['path'])) {
  175. $prefix = $path['prefix'];
  176. $path = $path['path'];
  177. }
  178. self::addAdapterPrefixPath($prefix, $path);
  179. }
  180. }
  181. }
  182. /**
  183. * Adds a scrolling style prefix path to the plugin loader.
  184. *
  185. * @param string $prefix
  186. * @param string $path
  187. */
  188. public static function addScrollingStylePrefixPath($prefix, $path)
  189. {
  190. self::getScrollingStyleLoader()->addPrefixPath($prefix, $path);
  191. }
  192. /**
  193. * Adds an array of scrolling style prefix paths to the plugin
  194. * loader.
  195. *
  196. * <code>
  197. * $prefixPaths = array(
  198. * 'My_Paginator_ScrollingStyle' => 'My/Paginator/ScrollingStyle/',
  199. * 'Your_Paginator_ScrollingStyle' => 'Your/Paginator/ScrollingStyle/'
  200. * );
  201. * </code>
  202. *
  203. * @param array $prefixPaths
  204. */
  205. public static function addScrollingStylePrefixPaths(array $prefixPaths)
  206. {
  207. if (isset($prefixPaths['prefix']) and isset($prefixPaths['path'])) {
  208. self::addScrollingStylePrefixPath($prefixPaths['prefix'], $prefixPaths['path']);
  209. } else {
  210. foreach ($prefixPaths as $prefix => $path) {
  211. if (is_array($path) and isset($path['prefix']) and isset($path['path'])) {
  212. $prefix = $path['prefix'];
  213. $path = $path['path'];
  214. }
  215. self::addScrollingStylePrefixPath($prefix, $path);
  216. }
  217. }
  218. }
  219. /**
  220. * Factory.
  221. *
  222. * @param mixed $data
  223. * @param string $adapter
  224. * @param array $prefixPaths
  225. * @return Zend_Paginator
  226. */
  227. public static function factory($data, $adapter = self::INTERNAL_ADAPTER,
  228. array $prefixPaths = null)
  229. {
  230. if ($adapter == self::INTERNAL_ADAPTER) {
  231. if (is_array($data)) {
  232. $adapter = 'Array';
  233. } else if ($data instanceof Zend_Db_Table_Select) {
  234. $adapter = 'DbTableSelect';
  235. } else if ($data instanceof Zend_Db_Select) {
  236. $adapter = 'DbSelect';
  237. } else if ($data instanceof Iterator) {
  238. $adapter = 'Iterator';
  239. } else if (is_integer($data)) {
  240. $adapter = 'Null';
  241. } else {
  242. $type = (is_object($data)) ? get_class($data) : gettype($data);
  243. /**
  244. * @see Zend_Paginator_Exception
  245. */
  246. require_once 'Zend/Paginator/Exception.php';
  247. throw new Zend_Paginator_Exception('No adapter for type ' . $type);
  248. }
  249. }
  250. $pluginLoader = self::getAdapterLoader();
  251. if (null !== $prefixPaths) {
  252. foreach ($prefixPaths as $prefix => $path) {
  253. $pluginLoader->addPrefixPath($prefix, $path);
  254. }
  255. }
  256. $adapterClassName = $pluginLoader->load($adapter);
  257. return new self(new $adapterClassName($data));
  258. }
  259. /**
  260. * Returns the adapter loader. If it doesn't exist it's created.
  261. *
  262. * @return Zend_Loader_PluginLoader
  263. */
  264. public static function getAdapterLoader()
  265. {
  266. if (self::$_adapterLoader === null) {
  267. self::$_adapterLoader = new Zend_Loader_PluginLoader(
  268. array('Zend_Paginator_Adapter' => 'Zend/Paginator/Adapter')
  269. );
  270. }
  271. return self::$_adapterLoader;
  272. }
  273. /**
  274. * Set a global config
  275. *
  276. * @param Zend_Config $config
  277. */
  278. public static function setConfig(Zend_Config $config)
  279. {
  280. self::$_config = $config;
  281. $adapterPaths = $config->get('adapterpaths');
  282. if ($adapterPaths != null) {
  283. self::addAdapterPrefixPaths($adapterPaths->adapterpath->toArray());
  284. }
  285. $prefixPaths = $config->get('prefixpaths');
  286. if ($prefixPaths != null) {
  287. self::addScrollingStylePrefixPaths($prefixPaths->prefixpath->toArray());
  288. }
  289. $scrollingStyle = $config->get('scrollingstyle');
  290. if ($scrollingStyle != null) {
  291. self::setDefaultScrollingStyle($scrollingStyle);
  292. }
  293. }
  294. /**
  295. * Returns the default scrolling style.
  296. *
  297. * @return string
  298. */
  299. public static function getDefaultScrollingStyle()
  300. {
  301. return self::$_defaultScrollingStyle;
  302. }
  303. /**
  304. * Sets a cache object
  305. *
  306. * @param Zend_Cache_Core $cache
  307. */
  308. public static function setCache(Zend_Cache_Core $cache)
  309. {
  310. self::$_cache = $cache;
  311. }
  312. /**
  313. * Sets the default scrolling style.
  314. *
  315. * @param string $scrollingStyle
  316. */
  317. public static function setDefaultScrollingStyle($scrollingStyle = 'Sliding')
  318. {
  319. self::$_defaultScrollingStyle = $scrollingStyle;
  320. }
  321. /**
  322. * Returns the scrolling style loader. If it doesn't exist it's
  323. * created.
  324. *
  325. * @return Zend_Loader_PluginLoader
  326. */
  327. public static function getScrollingStyleLoader()
  328. {
  329. if (self::$_scrollingStyleLoader === null) {
  330. self::$_scrollingStyleLoader = new Zend_Loader_PluginLoader(
  331. array('Zend_Paginator_ScrollingStyle' => 'Zend/Paginator/ScrollingStyle')
  332. );
  333. }
  334. return self::$_scrollingStyleLoader;
  335. }
  336. /**
  337. * Constructor.
  338. */
  339. public function __construct(Zend_Paginator_Adapter_Interface $adapter)
  340. {
  341. $this->_adapter = $adapter;
  342. $config = self::$_config;
  343. if ($config != null) {
  344. $setupMethods = array('ItemCountPerPage', 'PageRange');
  345. foreach ($setupMethods as $setupMethod) {
  346. $value = $config->get(strtolower($setupMethod));
  347. if ($value != null) {
  348. $setupMethod = 'set' . $setupMethod;
  349. $this->$setupMethod($value);
  350. }
  351. }
  352. }
  353. }
  354. /**
  355. * Serializes the object as a string. Proxies to {@link render()}.
  356. *
  357. * @return string
  358. */
  359. public function __toString()
  360. {
  361. try {
  362. $return = $this->render();
  363. return $return;
  364. } catch (Exception $e) {
  365. trigger_error($e->getMessage(), E_USER_WARNING);
  366. }
  367. return '';
  368. }
  369. /**
  370. * Enables/Disables the cache for this instance
  371. *
  372. * @param bool $enable
  373. * @return Zend_Paginator
  374. */
  375. public function setCacheEnabled($enable)
  376. {
  377. $this->_cacheEnabled = (bool)$enable;
  378. return $this;
  379. }
  380. /**
  381. * Returns the number of pages.
  382. *
  383. * @return integer
  384. */
  385. public function count()
  386. {
  387. if (!$this->_pageCount) {
  388. $this->_pageCount = $this->_calculatePageCount();
  389. }
  390. return $this->_pageCount;
  391. }
  392. /**
  393. * Returns the total number of items available.
  394. *
  395. * @return integer
  396. */
  397. public function getTotalItemCount()
  398. {
  399. return count($this->_adapter);
  400. }
  401. /**
  402. * Clear the page item cache.
  403. *
  404. * @param int $pageNumber
  405. * @return Zend_Paginator
  406. */
  407. public function clearPageItemCache($pageNumber = null)
  408. {
  409. if (!$this->_cacheEnabled()) {
  410. return $this;
  411. }
  412. if (null === $pageNumber) {
  413. $cleanTags = self::CACHE_TAG_PREFIX;
  414. foreach (self::$_cache->getIdsMatchingTags(array($this->_getCacheInternalId())) as $id) {
  415. if (preg_match('|'.self::CACHE_TAG_PREFIX."(\d+)_.*|", $id, $page)) {
  416. self::$_cache->remove($this->_getCacheId($page[1]));
  417. }
  418. }
  419. } else {
  420. $cleanId = $this->_getCacheId($pageNumber);
  421. self::$_cache->remove($cleanId);
  422. }
  423. return $this;
  424. }
  425. /**
  426. * Returns the absolute item number for the specified item.
  427. *
  428. * @param integer $relativeItemNumber Relative item number
  429. * @param integer $pageNumber Page number
  430. * @return integer
  431. */
  432. public function getAbsoluteItemNumber($relativeItemNumber, $pageNumber = null)
  433. {
  434. $relativeItemNumber = $this->normalizeItemNumber($relativeItemNumber);
  435. if ($pageNumber == null) {
  436. $pageNumber = $this->getCurrentPageNumber();
  437. }
  438. $pageNumber = $this->normalizePageNumber($pageNumber);
  439. return (($pageNumber - 1) * $this->getItemCountPerPage()) + $relativeItemNumber;
  440. }
  441. /**
  442. * Returns the adapter.
  443. *
  444. * @return Zend_Paginator_Adapter_Interface
  445. */
  446. public function getAdapter()
  447. {
  448. return $this->_adapter;
  449. }
  450. /**
  451. * Returns the number of items for the current page.
  452. *
  453. * @return integer
  454. */
  455. public function getCurrentItemCount()
  456. {
  457. if ($this->_currentItemCount === null) {
  458. $this->_currentItemCount = $this->getItemCount($this->getCurrentItems());
  459. }
  460. return $this->_currentItemCount;
  461. }
  462. /**
  463. * Returns the items for the current page.
  464. *
  465. * @return Traversable
  466. */
  467. public function getCurrentItems()
  468. {
  469. if ($this->_currentItems === null) {
  470. $this->_currentItems = $this->getItemsByPage($this->getCurrentPageNumber());
  471. }
  472. return $this->_currentItems;
  473. }
  474. /**
  475. * Returns the current page number.
  476. *
  477. * @return integer
  478. */
  479. public function getCurrentPageNumber()
  480. {
  481. return $this->normalizePageNumber($this->_currentPageNumber);
  482. }
  483. /**
  484. * Sets the current page number.
  485. *
  486. * @param integer $pageNumber Page number
  487. * @return Zend_Paginator $this
  488. */
  489. public function setCurrentPageNumber($pageNumber)
  490. {
  491. $this->_currentPageNumber = (integer) $pageNumber;
  492. $this->_currentItems = null;
  493. $this->_currentItemCount = null;
  494. return $this;
  495. }
  496. /**
  497. * Get the filter
  498. *
  499. * @return Zend_Filter_Interface
  500. */
  501. public function getFilter()
  502. {
  503. return $this->_filter;
  504. }
  505. /**
  506. * Set a filter chain
  507. *
  508. * @param Zend_Filter_Interface $filter
  509. * @return Zend_Paginator
  510. */
  511. public function setFilter(Zend_Filter_Interface $filter)
  512. {
  513. $this->_filter = $filter;
  514. return $this;
  515. }
  516. /**
  517. * Returns an item from a page. The current page is used if there's no
  518. * page sepcified.
  519. *
  520. * @param integer $itemNumber Item number (1 to itemCountPerPage)
  521. * @param integer $pageNumber
  522. * @return mixed
  523. */
  524. public function getItem($itemNumber, $pageNumber = null)
  525. {
  526. $itemNumber = $this->normalizeItemNumber($itemNumber);
  527. if ($pageNumber == null) {
  528. $pageNumber = $this->getCurrentPageNumber();
  529. }
  530. $page = $this->getItemsByPage($pageNumber);
  531. $itemCount = $this->getItemCount($page);
  532. if ($itemCount == 0) {
  533. /**
  534. * @see Zend_Paginator_Exception
  535. */
  536. require_once 'Zend/Paginator/Exception.php';
  537. throw new Zend_Paginator_Exception('Page ' . $pageNumber . ' does not exist');
  538. }
  539. if ($itemNumber > $itemCount) {
  540. /**
  541. * @see Zend_Paginator_Exception
  542. */
  543. require_once 'Zend/Paginator/Exception.php';
  544. throw new Zend_Paginator_Exception('Page ' . $pageNumber . ' does not'
  545. . ' contain item number ' . $itemNumber);
  546. }
  547. return $page[$itemNumber - 1];
  548. }
  549. /**
  550. * Returns the number of items per page.
  551. *
  552. * @return integer
  553. */
  554. public function getItemCountPerPage()
  555. {
  556. return $this->_itemCountPerPage;
  557. }
  558. /**
  559. * Sets the number of items per page.
  560. *
  561. * @param integer $itemCountPerPage
  562. * @return Zend_Paginator $this
  563. */
  564. public function setItemCountPerPage($itemCountPerPage)
  565. {
  566. $this->_itemCountPerPage = (integer) $itemCountPerPage;
  567. if ($this->_itemCountPerPage == 0) {
  568. $this->_itemCountPerPage = 1;
  569. }
  570. $this->_pageCount = $this->_calculatePageCount();
  571. $this->_currentItems = null;
  572. $this->_currentItemCount = null;
  573. return $this;
  574. }
  575. /**
  576. * Returns the number of items in a collection.
  577. *
  578. * @param mixed $items Items
  579. * @return integer
  580. */
  581. public function getItemCount($items)
  582. {
  583. $itemCount = 0;
  584. if (is_array($items) or $items instanceof Countable) {
  585. $itemCount = count($items);
  586. } else { // $items is something like LimitIterator
  587. $itemCount = iterator_count($items);
  588. }
  589. return $itemCount;
  590. }
  591. /**
  592. * Returns the items for a given page.
  593. *
  594. * @return Traversable
  595. */
  596. public function getItemsByPage($pageNumber)
  597. {
  598. $pageNumber = $this->normalizePageNumber($pageNumber);
  599. if ($this->_cacheEnabled()) {
  600. $data = self::$_cache->load($this->_getCacheId($pageNumber));
  601. if ($data !== false) {
  602. return $data;
  603. }
  604. }
  605. $offset = ($pageNumber - 1) * $this->_itemCountPerPage;
  606. $items = $this->_adapter->getItems($offset, $this->_itemCountPerPage);
  607. $filter = $this->getFilter();
  608. if ($filter !== null) {
  609. $items = $filter->filter($items);
  610. }
  611. if (!$items instanceof Traversable) {
  612. $items = new ArrayIterator($items);
  613. }
  614. if ($this->_cacheEnabled()) {
  615. self::$_cache->save($items, $this->_getCacheId($pageNumber), array($this->_getCacheInternalId()));
  616. }
  617. return $items;
  618. }
  619. /**
  620. * Returns a foreach-compatible iterator.
  621. *
  622. * @return Traversable
  623. */
  624. public function getIterator()
  625. {
  626. return $this->getCurrentItems();
  627. }
  628. /**
  629. * Returns the page range (see property declaration above).
  630. *
  631. * @return integer
  632. */
  633. public function getPageRange()
  634. {
  635. return $this->_pageRange;
  636. }
  637. /**
  638. * Sets the page range (see property declaration above).
  639. *
  640. * @param integer $pageRange
  641. * @return Zend_Paginator $this
  642. */
  643. public function setPageRange($pageRange)
  644. {
  645. $this->_pageRange = (integer) $pageRange;
  646. return $this;
  647. }
  648. /**
  649. * Returns the page collection.
  650. *
  651. * @param string $scrollingStyle Scrolling style
  652. * @return array
  653. */
  654. public function getPages($scrollingStyle = null)
  655. {
  656. if ($this->_pages === null) {
  657. $this->_pages = $this->_createPages($scrollingStyle);
  658. }
  659. return $this->_pages;
  660. }
  661. /**
  662. * Returns a subset of pages within a given range.
  663. *
  664. * @param integer $lowerBound Lower bound of the range
  665. * @param integer $upperBound Upper bound of the range
  666. * @return array
  667. */
  668. public function getPagesInRange($lowerBound, $upperBound)
  669. {
  670. $lowerBound = $this->normalizePageNumber($lowerBound);
  671. $upperBound = $this->normalizePageNumber($upperBound);
  672. $pages = array();
  673. for ($pageNumber = $lowerBound; $pageNumber <= $upperBound; $pageNumber++) {
  674. $pages[$pageNumber] = $pageNumber;
  675. }
  676. return $pages;
  677. }
  678. /**
  679. * Returns the page item cache.
  680. *
  681. * @return array
  682. */
  683. public function getPageItemCache()
  684. {
  685. $data = array();
  686. if ($this->_cacheEnabled()) {
  687. foreach (self::$_cache->getIdsMatchingTags(array($this->_getCacheInternalId())) as $id) {
  688. if (preg_match('|'.self::CACHE_TAG_PREFIX."(\d+)_.*|", $id, $page)) {
  689. $data[$page[1]] = self::$_cache->load($this->_getCacheId($page[1]));
  690. }
  691. }
  692. }
  693. return $data;
  694. }
  695. /**
  696. * Retrieves the view instance. If none registered, attempts to pull f
  697. * rom ViewRenderer.
  698. *
  699. * @return Zend_View_Interface|null
  700. */
  701. public function getView()
  702. {
  703. if ($this->_view === null) {
  704. /**
  705. * @see Zend_Controller_Action_HelperBroker
  706. */
  707. require_once 'Zend/Controller/Action/HelperBroker.php';
  708. $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
  709. if ($viewRenderer->view === null) {
  710. $viewRenderer->initView();
  711. }
  712. $this->_view = $viewRenderer->view;
  713. }
  714. return $this->_view;
  715. }
  716. /**
  717. * Sets the view object.
  718. *
  719. * @param Zend_View_Interface $view
  720. * @return Zend_Paginator
  721. */
  722. public function setView(Zend_View_Interface $view = null)
  723. {
  724. $this->_view = $view;
  725. return $this;
  726. }
  727. /**
  728. * Brings the item number in range of the page.
  729. *
  730. * @param integer $itemNumber
  731. * @return integer
  732. */
  733. public function normalizeItemNumber($itemNumber)
  734. {
  735. if ($itemNumber < 1) {
  736. $itemNumber = 1;
  737. }
  738. if ($itemNumber > $this->_itemCountPerPage) {
  739. $itemNumber = $this->_itemCountPerPage;
  740. }
  741. return $itemNumber;
  742. }
  743. /**
  744. * Brings the page number in range of the paginator.
  745. *
  746. * @param integer $pageNumber
  747. * @return integer
  748. */
  749. public function normalizePageNumber($pageNumber)
  750. {
  751. if ($pageNumber < 1) {
  752. $pageNumber = 1;
  753. }
  754. $pageCount = $this->count();
  755. if ($pageCount > 0 and $pageNumber > $pageCount) {
  756. $pageNumber = $pageCount;
  757. }
  758. return $pageNumber;
  759. }
  760. /**
  761. * Renders the paginator.
  762. *
  763. * @param Zend_View_Interface $view
  764. * @return string
  765. */
  766. public function render(Zend_View_Interface $view = null)
  767. {
  768. if (null !== $view) {
  769. $this->setView($view);
  770. }
  771. $view = $this->getView();
  772. return $view->paginationControl($this);
  773. }
  774. /**
  775. * Returns the items of the current page as JSON.
  776. *
  777. * @return string
  778. */
  779. public function toJson()
  780. {
  781. $currentItems = $this->getCurrentItems();
  782. if ($currentItems instanceof Zend_Db_Table_Rowset_Abstract) {
  783. return Zend_Json::encode($currentItems->toArray());
  784. } else {
  785. return Zend_Json::encode($currentItems);
  786. }
  787. }
  788. /**
  789. * Tells if there is an active cache object
  790. * and if the cache has not been desabled
  791. *
  792. * @return bool
  793. */
  794. protected function _cacheEnabled()
  795. {
  796. return ((self::$_cache !== null) && $this->_cacheEnabled);
  797. }
  798. /**
  799. * Makes an Id for the cache
  800. * Depends on the adapter object and the page number
  801. *
  802. * Used to store item in cache from that Paginator instance
  803. * and that current page
  804. *
  805. * @param int $page
  806. * @return string
  807. */
  808. protected function _getCacheId($page = null)
  809. {
  810. if ($page === null) {
  811. $page = $this->getCurrentPageNumber();
  812. }
  813. return self::CACHE_TAG_PREFIX . $page . '_' . $this->_getCacheInternalId();
  814. }
  815. /**
  816. * Get the internal cache id
  817. * Depends on the adapter and the item count per page
  818. *
  819. * Used to tag that unique Paginator instance in cache
  820. *
  821. * @return string
  822. */
  823. protected function _getCacheInternalId()
  824. {
  825. return md5(serialize($this->_adapter).$this->_itemCountPerPage);
  826. }
  827. /**
  828. * Calculates the page count.
  829. *
  830. * @return integer
  831. */
  832. protected function _calculatePageCount()
  833. {
  834. return (integer) ceil($this->_adapter->count() / $this->_itemCountPerPage);
  835. }
  836. /**
  837. * Creates the page collection.
  838. *
  839. * @param string $scrollingStyle Scrolling style
  840. * @return stdClass
  841. */
  842. protected function _createPages($scrollingStyle = null)
  843. {
  844. $pageCount = $this->count();
  845. $currentPageNumber = $this->getCurrentPageNumber();
  846. $pages = new stdClass();
  847. $pages->pageCount = $pageCount;
  848. $pages->itemCountPerPage = $this->getItemCountPerPage();
  849. $pages->first = 1;
  850. $pages->current = $currentPageNumber;
  851. $pages->last = $pageCount;
  852. // Previous and next
  853. if ($currentPageNumber - 1 > 0) {
  854. $pages->previous = $currentPageNumber - 1;
  855. }
  856. if ($currentPageNumber + 1 <= $pageCount) {
  857. $pages->next = $currentPageNumber + 1;
  858. }
  859. // Pages in range
  860. $scrollingStyle = $this->_loadScrollingStyle($scrollingStyle);
  861. $pages->pagesInRange = $scrollingStyle->getPages($this);
  862. $pages->firstPageInRange = min($pages->pagesInRange);
  863. $pages->lastPageInRange = max($pages->pagesInRange);
  864. // Item numbers
  865. if ($this->getCurrentItems() !== null) {
  866. $pages->currentItemCount = $this->getCurrentItemCount();
  867. $pages->itemCountPerPage = $this->getItemCountPerPage();
  868. $pages->totalItemCount = $this->getTotalItemCount();
  869. $pages->firstItemNumber = (($currentPageNumber - 1) * $this->_itemCountPerPage) + 1;
  870. $pages->lastItemNumber = $pages->firstItemNumber + $pages->currentItemCount - 1;
  871. }
  872. return $pages;
  873. }
  874. /**
  875. * Loads a scrolling style.
  876. *
  877. * @param string $scrollingStyle
  878. * @return Zend_Paginator_ScrollingStyle_Interface
  879. */
  880. protected function _loadScrollingStyle($scrollingStyle = null)
  881. {
  882. if ($scrollingStyle === null) {
  883. $scrollingStyle = self::$_defaultScrollingStyle;
  884. }
  885. switch (strtolower(gettype($scrollingStyle))) {
  886. case 'object':
  887. if (!$scrollingStyle instanceof Zend_Paginator_ScrollingStyle_Interface) {
  888. /**
  889. * @see Zend_View_Exception
  890. */
  891. require_once 'Zend/View/Exception.php';
  892. throw new Zend_View_Exception('Scrolling style must implement ' .
  893. 'Zend_Paginator_ScrollingStyle_Interface');
  894. }
  895. return $scrollingStyle;
  896. case 'string':
  897. $className = self::getScrollingStyleLoader()->load($scrollingStyle);
  898. return new $className();
  899. case 'null':
  900. // Fall through to default case
  901. default:
  902. /**
  903. * @see Zend_View_Exception
  904. */
  905. require_once 'Zend/View/Exception.php';
  906. throw new Zend_View_Exception('Scrolling style must be a class ' .
  907. 'name or object implementing Zend_Paginator_ScrollingStyle_Interface');
  908. }
  909. }
  910. }