File indexing completed on 2024-12-22 05:37:17
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Paginator 0017 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0018 * @license http://framework.zend.com/license/new-bsd New BSD License 0019 * @version $Id$ 0020 */ 0021 0022 /** 0023 * @see Zend_Loader_PluginLoader 0024 */ 0025 // require_once 'Zend/Loader/PluginLoader.php'; 0026 0027 /** 0028 * @see Zend_Json 0029 */ 0030 // require_once 'Zend/Json.php'; 0031 0032 /** 0033 * @category Zend 0034 * @package Zend_Paginator 0035 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0036 * @license http://framework.zend.com/license/new-bsd New BSD License 0037 */ 0038 class Zend_Paginator implements Countable, IteratorAggregate 0039 { 0040 /** 0041 * Specifies that the factory should try to detect the proper adapter type first 0042 * 0043 * @var string 0044 */ 0045 const INTERNAL_ADAPTER = 'Zend_Paginator_Adapter_Internal'; 0046 0047 /** 0048 * The cache tag prefix used to namespace Paginator results in the cache 0049 * 0050 */ 0051 const CACHE_TAG_PREFIX = 'Zend_Paginator_'; 0052 0053 /** 0054 * Adapter plugin loader 0055 * 0056 * @var Zend_Loader_PluginLoader 0057 */ 0058 protected static $_adapterLoader = null; 0059 0060 /** 0061 * Configuration file 0062 * 0063 * @var Zend_Config 0064 */ 0065 protected static $_config = null; 0066 0067 /** 0068 * Default scrolling style 0069 * 0070 * @var string 0071 */ 0072 protected static $_defaultScrollingStyle = 'Sliding'; 0073 0074 /** 0075 * Default item count per page 0076 * 0077 * @var int 0078 */ 0079 protected static $_defaultItemCountPerPage = 10; 0080 0081 /** 0082 * Default number of local pages (i.e., the number of discretes 0083 * page numbers that will be displayed, including the current 0084 * page number) 0085 * 0086 * @var int 0087 */ 0088 protected static $_defaultPageRange = 10; 0089 0090 /** 0091 * Scrolling style plugin loader 0092 * 0093 * @var Zend_Loader_PluginLoader 0094 */ 0095 protected static $_scrollingStyleLoader = null; 0096 0097 /** 0098 * Cache object 0099 * 0100 * @var Zend_Cache_Core 0101 */ 0102 protected static $_cache; 0103 0104 /** 0105 * Enable or disable the cache by Zend_Paginator instance 0106 * 0107 * @var bool 0108 */ 0109 protected $_cacheEnabled = true; 0110 0111 /** 0112 * Adapter 0113 * 0114 * @var Zend_Paginator_Adapter_Interface 0115 */ 0116 protected $_adapter = null; 0117 0118 /** 0119 * Number of items in the current page 0120 * 0121 * @var integer 0122 */ 0123 protected $_currentItemCount = null; 0124 0125 /** 0126 * Current page items 0127 * 0128 * @var Traversable 0129 */ 0130 protected $_currentItems = null; 0131 0132 /** 0133 * Current page number (starting from 1) 0134 * 0135 * @var integer 0136 */ 0137 protected $_currentPageNumber = 1; 0138 0139 /** 0140 * Result filter 0141 * 0142 * @var Zend_Filter_Interface 0143 */ 0144 protected $_filter = null; 0145 0146 /** 0147 * Number of items per page 0148 * 0149 * @var integer 0150 */ 0151 protected $_itemCountPerPage = null; 0152 0153 /** 0154 * Number of pages 0155 * 0156 * @var integer 0157 */ 0158 protected $_pageCount = null; 0159 0160 /** 0161 * Number of local pages (i.e., the number of discrete page numbers 0162 * that will be displayed, including the current page number) 0163 * 0164 * @var integer 0165 */ 0166 protected $_pageRange = null; 0167 0168 /** 0169 * Pages 0170 * 0171 * @var array 0172 */ 0173 protected $_pages = null; 0174 0175 /** 0176 * View instance used for self rendering 0177 * 0178 * @var Zend_View_Interface 0179 */ 0180 protected $_view = null; 0181 0182 /** 0183 * Adds an adapter prefix path to the plugin loader. 0184 * 0185 * @param string $prefix 0186 * @param string $path 0187 */ 0188 public static function addAdapterPrefixPath($prefix, $path) 0189 { 0190 self::getAdapterLoader()->addPrefixPath($prefix, $path); 0191 } 0192 0193 /** 0194 * Adds an array of adapter prefix paths to the plugin 0195 * loader. 0196 * 0197 * <code> 0198 * $prefixPaths = array( 0199 * 'My_Paginator_Adapter' => 'My/Paginator/Adapter/', 0200 * 'Your_Paginator_Adapter' => 'Your/Paginator/Adapter/' 0201 * ); 0202 * </code> 0203 * 0204 * @param array $prefixPaths 0205 */ 0206 public static function addAdapterPrefixPaths(array $prefixPaths) 0207 { 0208 if (isset($prefixPaths['prefix']) && isset($prefixPaths['path'])) { 0209 self::addAdapterPrefixPath($prefixPaths['prefix'], $prefixPaths['path']); 0210 } else { 0211 foreach ($prefixPaths as $prefix => $path) { 0212 if (is_array($path) && isset($path['prefix']) && isset($path['path'])) { 0213 $prefix = $path['prefix']; 0214 $path = $path['path']; 0215 } 0216 0217 self::addAdapterPrefixPath($prefix, $path); 0218 } 0219 } 0220 } 0221 0222 /** 0223 * Adds a scrolling style prefix path to the plugin loader. 0224 * 0225 * @param string $prefix 0226 * @param string $path 0227 */ 0228 public static function addScrollingStylePrefixPath($prefix, $path) 0229 { 0230 self::getScrollingStyleLoader()->addPrefixPath($prefix, $path); 0231 } 0232 0233 /** 0234 * Adds an array of scrolling style prefix paths to the plugin 0235 * loader. 0236 * 0237 * <code> 0238 * $prefixPaths = array( 0239 * 'My_Paginator_ScrollingStyle' => 'My/Paginator/ScrollingStyle/', 0240 * 'Your_Paginator_ScrollingStyle' => 'Your/Paginator/ScrollingStyle/' 0241 * ); 0242 * </code> 0243 * 0244 * @param array $prefixPaths 0245 */ 0246 public static function addScrollingStylePrefixPaths(array $prefixPaths) 0247 { 0248 if (isset($prefixPaths['prefix']) && isset($prefixPaths['path'])) { 0249 self::addScrollingStylePrefixPath($prefixPaths['prefix'], $prefixPaths['path']); 0250 } else { 0251 foreach ($prefixPaths as $prefix => $path) { 0252 if (is_array($path) && isset($path['prefix']) && isset($path['path'])) { 0253 $prefix = $path['prefix']; 0254 $path = $path['path']; 0255 } 0256 0257 self::addScrollingStylePrefixPath($prefix, $path); 0258 } 0259 } 0260 } 0261 0262 /** 0263 * Factory. 0264 * 0265 * @param mixed $data 0266 * @param string $adapter 0267 * @param array $prefixPaths 0268 * @return Zend_Paginator 0269 */ 0270 public static function factory($data, $adapter = self::INTERNAL_ADAPTER, 0271 array $prefixPaths = null) 0272 { 0273 if ($data instanceof Zend_Paginator_AdapterAggregate) { 0274 return new self($data->getPaginatorAdapter()); 0275 } else { 0276 if ($adapter == self::INTERNAL_ADAPTER) { 0277 if (is_array($data)) { 0278 $adapter = 'Array'; 0279 } else if ($data instanceof Zend_Db_Table_Select) { 0280 $adapter = 'DbTableSelect'; 0281 } else if ($data instanceof Zend_Db_Select) { 0282 $adapter = 'DbSelect'; 0283 } else if ($data instanceof Iterator) { 0284 $adapter = 'Iterator'; 0285 } else if (is_integer($data)) { 0286 $adapter = 'Null'; 0287 } else { 0288 $type = (is_object($data)) ? get_class($data) : gettype($data); 0289 0290 /** 0291 * @see Zend_Paginator_Exception 0292 */ 0293 // require_once 'Zend/Paginator/Exception.php'; 0294 0295 throw new Zend_Paginator_Exception('No adapter for type ' . $type); 0296 } 0297 } 0298 0299 $pluginLoader = self::getAdapterLoader(); 0300 0301 if (null !== $prefixPaths) { 0302 foreach ($prefixPaths as $prefix => $path) { 0303 $pluginLoader->addPrefixPath($prefix, $path); 0304 } 0305 } 0306 0307 $adapterClassName = $pluginLoader->load($adapter); 0308 0309 return new self(new $adapterClassName($data)); 0310 } 0311 } 0312 0313 /** 0314 * Returns the adapter loader. If it doesn't exist it's created. 0315 * 0316 * @return Zend_Loader_PluginLoader 0317 */ 0318 public static function getAdapterLoader() 0319 { 0320 if (self::$_adapterLoader === null) { 0321 self::$_adapterLoader = new Zend_Loader_PluginLoader( 0322 array('Zend_Paginator_Adapter' => 'Zend/Paginator/Adapter') 0323 ); 0324 } 0325 0326 return self::$_adapterLoader; 0327 } 0328 0329 /** 0330 * Set a global config 0331 * 0332 * @param Zend_Config $config 0333 */ 0334 public static function setConfig(Zend_Config $config) 0335 { 0336 self::$_config = $config; 0337 0338 $adapterPaths = $config->get('adapterpaths'); 0339 0340 if ($adapterPaths != null) { 0341 self::addAdapterPrefixPaths($adapterPaths->adapterpath->toArray()); 0342 } 0343 0344 $prefixPaths = $config->get('prefixpaths'); 0345 0346 if ($prefixPaths != null) { 0347 self::addScrollingStylePrefixPaths($prefixPaths->prefixpath->toArray()); 0348 } 0349 0350 $scrollingStyle = $config->get('scrollingstyle'); 0351 0352 if ($scrollingStyle != null) { 0353 self::setDefaultScrollingStyle($scrollingStyle); 0354 } 0355 } 0356 0357 /** 0358 * Returns the default scrolling style. 0359 * 0360 * @return string 0361 */ 0362 public static function getDefaultScrollingStyle() 0363 { 0364 return self::$_defaultScrollingStyle; 0365 } 0366 0367 /** 0368 * Get the default item count per page 0369 * 0370 * @return int 0371 */ 0372 public static function getDefaultItemCountPerPage() 0373 { 0374 return self::$_defaultItemCountPerPage; 0375 } 0376 0377 /** 0378 * Set the default item count per page 0379 * 0380 * @param int $count 0381 */ 0382 public static function setDefaultItemCountPerPage($count) 0383 { 0384 self::$_defaultItemCountPerPage = (int) $count; 0385 } 0386 0387 /** 0388 * Get the default page range 0389 * 0390 * @return int 0391 */ 0392 public static function getDefaultPageRange() 0393 { 0394 return self::$_defaultPageRange; 0395 } 0396 0397 /** 0398 * Set the default page range 0399 * 0400 * @param int $count 0401 */ 0402 public static function setDefaultPageRange($count) 0403 { 0404 self::$_defaultPageRange = (int) $count; 0405 } 0406 0407 /** 0408 * Sets a cache object 0409 * 0410 * @param Zend_Cache_Core $cache 0411 */ 0412 public static function setCache(Zend_Cache_Core $cache) 0413 { 0414 self::$_cache = $cache; 0415 } 0416 0417 /** 0418 * Sets the default scrolling style. 0419 * 0420 * @param string $scrollingStyle 0421 */ 0422 public static function setDefaultScrollingStyle($scrollingStyle = 'Sliding') 0423 { 0424 self::$_defaultScrollingStyle = $scrollingStyle; 0425 } 0426 0427 /** 0428 * Returns the scrolling style loader. If it doesn't exist it's 0429 * created. 0430 * 0431 * @return Zend_Loader_PluginLoader 0432 */ 0433 public static function getScrollingStyleLoader() 0434 { 0435 if (self::$_scrollingStyleLoader === null) { 0436 self::$_scrollingStyleLoader = new Zend_Loader_PluginLoader( 0437 array('Zend_Paginator_ScrollingStyle' => 'Zend/Paginator/ScrollingStyle') 0438 ); 0439 } 0440 0441 return self::$_scrollingStyleLoader; 0442 } 0443 0444 /** 0445 * Constructor. 0446 * 0447 * @param Zend_Paginator_Adapter_Interface|Zend_Paginator_AdapterAggregate $adapter 0448 */ 0449 public function __construct($adapter) 0450 { 0451 if ($adapter instanceof Zend_Paginator_Adapter_Interface) { 0452 $this->_adapter = $adapter; 0453 } else if ($adapter instanceof Zend_Paginator_AdapterAggregate) { 0454 $this->_adapter = $adapter->getPaginatorAdapter(); 0455 } else { 0456 /** 0457 * @see Zend_Paginator_Exception 0458 */ 0459 // require_once 'Zend/Paginator/Exception.php'; 0460 0461 throw new Zend_Paginator_Exception( 0462 'Zend_Paginator only accepts instances of the type ' . 0463 'Zend_Paginator_Adapter_Interface or Zend_Paginator_AdapterAggregate.' 0464 ); 0465 } 0466 0467 $config = self::$_config; 0468 0469 if ($config != null) { 0470 $setupMethods = array('ItemCountPerPage', 'PageRange'); 0471 0472 foreach ($setupMethods as $setupMethod) { 0473 $value = $config->get(strtolower($setupMethod)); 0474 0475 if ($value != null) { 0476 $setupMethod = 'set' . $setupMethod; 0477 $this->$setupMethod($value); 0478 } 0479 } 0480 } 0481 } 0482 0483 /** 0484 * Serializes the object as a string. Proxies to {@link render()}. 0485 * 0486 * @return string 0487 */ 0488 public function __toString() 0489 { 0490 try { 0491 $return = $this->render(); 0492 return $return; 0493 } catch (Exception $e) { 0494 trigger_error($e->getMessage(), E_USER_WARNING); 0495 } 0496 0497 return ''; 0498 } 0499 0500 /** 0501 * Enables/Disables the cache for this instance 0502 * 0503 * @param bool $enable 0504 * @return Zend_Paginator 0505 */ 0506 public function setCacheEnabled($enable) 0507 { 0508 $this->_cacheEnabled = (bool)$enable; 0509 return $this; 0510 } 0511 0512 /** 0513 * Returns the number of pages. 0514 * 0515 * @return integer 0516 */ 0517 public function count() 0518 { 0519 if (!$this->_pageCount) { 0520 $this->_pageCount = $this->_calculatePageCount(); 0521 } 0522 0523 return $this->_pageCount; 0524 } 0525 0526 /** 0527 * Returns the total number of items available. Uses cache if caching is enabled. 0528 * 0529 * @return integer 0530 */ 0531 public function getTotalItemCount() 0532 { 0533 if (!$this->_cacheEnabled()) { 0534 return count($this->getAdapter()); 0535 } else { 0536 $cacheId = md5($this->_getCacheInternalId(). '_itemCount'); 0537 $itemCount = self::$_cache->load($cacheId); 0538 0539 if ($itemCount === false) { 0540 $itemCount = count($this->getAdapter()); 0541 0542 self::$_cache->save($itemCount, $cacheId, array($this->_getCacheInternalId())); 0543 } 0544 0545 return $itemCount; 0546 } 0547 } 0548 0549 /** 0550 * Clear the page item cache. 0551 * 0552 * @param int $pageNumber 0553 * @return Zend_Paginator 0554 */ 0555 public function clearPageItemCache($pageNumber = null) 0556 { 0557 if (!$this->_cacheEnabled()) { 0558 return $this; 0559 } 0560 0561 if (null === $pageNumber) { 0562 foreach (self::$_cache->getIdsMatchingTags(array($this->_getCacheInternalId())) as $id) { 0563 if (preg_match('|'.self::CACHE_TAG_PREFIX."(\d+)_.*|", $id, $page)) { 0564 self::$_cache->remove($this->_getCacheId($page[1])); 0565 } 0566 } 0567 } else { 0568 $cleanId = $this->_getCacheId($pageNumber); 0569 self::$_cache->remove($cleanId); 0570 } 0571 return $this; 0572 } 0573 0574 /** 0575 * Returns the absolute item number for the specified item. 0576 * 0577 * @param integer $relativeItemNumber Relative item number 0578 * @param integer $pageNumber Page number 0579 * @return integer 0580 */ 0581 public function getAbsoluteItemNumber($relativeItemNumber, $pageNumber = null) 0582 { 0583 $relativeItemNumber = $this->normalizeItemNumber($relativeItemNumber); 0584 0585 if ($pageNumber == null) { 0586 $pageNumber = $this->getCurrentPageNumber(); 0587 } 0588 0589 $pageNumber = $this->normalizePageNumber($pageNumber); 0590 0591 return (($pageNumber - 1) * $this->getItemCountPerPage()) + $relativeItemNumber; 0592 } 0593 0594 /** 0595 * Returns the adapter. 0596 * 0597 * @return Zend_Paginator_Adapter_Interface 0598 */ 0599 public function getAdapter() 0600 { 0601 return $this->_adapter; 0602 } 0603 0604 /** 0605 * Returns the number of items for the current page. 0606 * 0607 * @return integer 0608 */ 0609 public function getCurrentItemCount() 0610 { 0611 if ($this->_currentItemCount === null) { 0612 $this->_currentItemCount = $this->getItemCount($this->getCurrentItems()); 0613 } 0614 0615 return $this->_currentItemCount; 0616 } 0617 0618 /** 0619 * Returns the items for the current page. 0620 * 0621 * @return Traversable 0622 */ 0623 public function getCurrentItems() 0624 { 0625 if ($this->_currentItems === null) { 0626 $this->_currentItems = $this->getItemsByPage($this->getCurrentPageNumber()); 0627 } 0628 0629 return $this->_currentItems; 0630 } 0631 0632 /** 0633 * Returns the current page number. 0634 * 0635 * @return integer 0636 */ 0637 public function getCurrentPageNumber() 0638 { 0639 return $this->normalizePageNumber($this->_currentPageNumber); 0640 } 0641 0642 /** 0643 * Sets the current page number. 0644 * 0645 * @param integer $pageNumber Page number 0646 * @return Zend_Paginator $this 0647 */ 0648 public function setCurrentPageNumber($pageNumber) 0649 { 0650 $this->_currentPageNumber = (integer) $pageNumber; 0651 $this->_currentItems = null; 0652 $this->_currentItemCount = null; 0653 0654 return $this; 0655 } 0656 0657 /** 0658 * Get the filter 0659 * 0660 * @return Zend_Filter_Interface 0661 */ 0662 public function getFilter() 0663 { 0664 return $this->_filter; 0665 } 0666 0667 /** 0668 * Set a filter chain 0669 * 0670 * @param Zend_Filter_Interface $filter 0671 * @return Zend_Paginator 0672 */ 0673 public function setFilter(Zend_Filter_Interface $filter) 0674 { 0675 $this->_filter = $filter; 0676 0677 return $this; 0678 } 0679 0680 /** 0681 * Returns an item from a page. The current page is used if there's no 0682 * page sepcified. 0683 * 0684 * @param integer $itemNumber Item number (1 to itemCountPerPage) 0685 * @param integer $pageNumber 0686 * @return mixed 0687 */ 0688 public function getItem($itemNumber, $pageNumber = null) 0689 { 0690 if ($pageNumber == null) { 0691 $pageNumber = $this->getCurrentPageNumber(); 0692 } else if ($pageNumber < 0) { 0693 $pageNumber = ($this->count() + 1) + $pageNumber; 0694 } 0695 0696 $page = $this->getItemsByPage($pageNumber); 0697 $itemCount = $this->getItemCount($page); 0698 0699 if ($itemCount == 0) { 0700 /** 0701 * @see Zend_Paginator_Exception 0702 */ 0703 // require_once 'Zend/Paginator/Exception.php'; 0704 0705 throw new Zend_Paginator_Exception('Page ' . $pageNumber . ' does not exist'); 0706 } 0707 0708 if ($itemNumber < 0) { 0709 $itemNumber = ($itemCount + 1) + $itemNumber; 0710 } 0711 0712 $itemNumber = $this->normalizeItemNumber($itemNumber); 0713 0714 if ($itemNumber > $itemCount) { 0715 /** 0716 * @see Zend_Paginator_Exception 0717 */ 0718 // require_once 'Zend/Paginator/Exception.php'; 0719 0720 throw new Zend_Paginator_Exception('Page ' . $pageNumber . ' does not' 0721 . ' contain item number ' . $itemNumber); 0722 } 0723 0724 return $page[$itemNumber - 1]; 0725 } 0726 0727 /** 0728 * Returns the number of items per page. 0729 * 0730 * @return integer 0731 */ 0732 public function getItemCountPerPage() 0733 { 0734 if (empty($this->_itemCountPerPage)) { 0735 $this->_itemCountPerPage = self::getDefaultItemCountPerPage(); 0736 } 0737 0738 return $this->_itemCountPerPage; 0739 } 0740 0741 /** 0742 * Sets the number of items per page. 0743 * 0744 * @param integer $itemCountPerPage 0745 * @return Zend_Paginator $this 0746 */ 0747 public function setItemCountPerPage($itemCountPerPage = -1) 0748 { 0749 $this->_itemCountPerPage = (integer) $itemCountPerPage; 0750 if ($this->_itemCountPerPage < 1) { 0751 $this->_itemCountPerPage = $this->getTotalItemCount(); 0752 } 0753 $this->_pageCount = $this->_calculatePageCount(); 0754 $this->_currentItems = null; 0755 $this->_currentItemCount = null; 0756 0757 return $this; 0758 } 0759 0760 /** 0761 * Returns the number of items in a collection. 0762 * 0763 * @param mixed $items Items 0764 * @return integer 0765 */ 0766 public function getItemCount($items) 0767 { 0768 $itemCount = 0; 0769 0770 if (is_array($items) || $items instanceof Countable) { 0771 $itemCount = count($items); 0772 } else { // $items is something like LimitIterator 0773 $itemCount = iterator_count($items); 0774 } 0775 0776 return $itemCount; 0777 } 0778 0779 /** 0780 * Returns the items for a given page. 0781 * 0782 * @return Traversable 0783 */ 0784 public function getItemsByPage($pageNumber) 0785 { 0786 $pageNumber = $this->normalizePageNumber($pageNumber); 0787 0788 if ($this->_cacheEnabled()) { 0789 $data = self::$_cache->load($this->_getCacheId($pageNumber)); 0790 if ($data !== false) { 0791 return $data; 0792 } 0793 } 0794 0795 $offset = ($pageNumber - 1) * $this->getItemCountPerPage(); 0796 0797 $items = $this->_adapter->getItems($offset, $this->getItemCountPerPage()); 0798 0799 $filter = $this->getFilter(); 0800 0801 if ($filter !== null) { 0802 $items = $filter->filter($items); 0803 } 0804 0805 if (!$items instanceof Traversable) { 0806 $items = new ArrayIterator($items); 0807 } 0808 0809 if ($this->_cacheEnabled()) { 0810 self::$_cache->save($items, $this->_getCacheId($pageNumber), array($this->_getCacheInternalId())); 0811 } 0812 0813 return $items; 0814 } 0815 0816 /** 0817 * Returns a foreach-compatible iterator. 0818 * 0819 * @return Traversable 0820 */ 0821 public function getIterator() 0822 { 0823 return $this->getCurrentItems(); 0824 } 0825 0826 /** 0827 * Returns the page range (see property declaration above). 0828 * 0829 * @return integer 0830 */ 0831 public function getPageRange() 0832 { 0833 if (null === $this->_pageRange) { 0834 $this->_pageRange = self::getDefaultPageRange(); 0835 } 0836 0837 return $this->_pageRange; 0838 } 0839 0840 /** 0841 * Sets the page range (see property declaration above). 0842 * 0843 * @param integer $pageRange 0844 * @return Zend_Paginator $this 0845 */ 0846 public function setPageRange($pageRange) 0847 { 0848 $this->_pageRange = (integer) $pageRange; 0849 0850 return $this; 0851 } 0852 0853 /** 0854 * Returns the page collection. 0855 * 0856 * @param string $scrollingStyle Scrolling style 0857 * @return array 0858 */ 0859 public function getPages($scrollingStyle = null) 0860 { 0861 if ($this->_pages === null) { 0862 $this->_pages = $this->_createPages($scrollingStyle); 0863 } 0864 0865 return $this->_pages; 0866 } 0867 0868 /** 0869 * Returns a subset of pages within a given range. 0870 * 0871 * @param integer $lowerBound Lower bound of the range 0872 * @param integer $upperBound Upper bound of the range 0873 * @return array 0874 */ 0875 public function getPagesInRange($lowerBound, $upperBound) 0876 { 0877 $lowerBound = $this->normalizePageNumber($lowerBound); 0878 $upperBound = $this->normalizePageNumber($upperBound); 0879 0880 $pages = array(); 0881 0882 for ($pageNumber = $lowerBound; $pageNumber <= $upperBound; $pageNumber++) { 0883 $pages[$pageNumber] = $pageNumber; 0884 } 0885 0886 return $pages; 0887 } 0888 0889 /** 0890 * Returns the page item cache. 0891 * 0892 * @return array 0893 */ 0894 public function getPageItemCache() 0895 { 0896 $data = array(); 0897 if ($this->_cacheEnabled()) { 0898 foreach (self::$_cache->getIdsMatchingTags(array($this->_getCacheInternalId())) as $id) { 0899 if (preg_match('|'.self::CACHE_TAG_PREFIX."(\d+)_.*|", $id, $page)) { 0900 $data[$page[1]] = self::$_cache->load($this->_getCacheId($page[1])); 0901 } 0902 } 0903 } 0904 return $data; 0905 } 0906 0907 /** 0908 * Retrieves the view instance. If none registered, attempts to pull f 0909 * rom ViewRenderer. 0910 * 0911 * @return Zend_View_Interface|null 0912 */ 0913 public function getView() 0914 { 0915 if ($this->_view === null) { 0916 /** 0917 * @see Zend_Controller_Action_HelperBroker 0918 */ 0919 // require_once 'Zend/Controller/Action/HelperBroker.php'; 0920 0921 $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); 0922 if ($viewRenderer->view === null) { 0923 $viewRenderer->initView(); 0924 } 0925 $this->_view = $viewRenderer->view; 0926 } 0927 0928 return $this->_view; 0929 } 0930 0931 /** 0932 * Sets the view object. 0933 * 0934 * @param Zend_View_Interface $view 0935 * @return Zend_Paginator 0936 */ 0937 public function setView(Zend_View_Interface $view = null) 0938 { 0939 $this->_view = $view; 0940 0941 return $this; 0942 } 0943 0944 /** 0945 * Brings the item number in range of the page. 0946 * 0947 * @param integer $itemNumber 0948 * @return integer 0949 */ 0950 public function normalizeItemNumber($itemNumber) 0951 { 0952 $itemNumber = (integer) $itemNumber; 0953 0954 if ($itemNumber < 1) { 0955 $itemNumber = 1; 0956 } 0957 0958 if ($itemNumber > $this->getItemCountPerPage()) { 0959 $itemNumber = $this->getItemCountPerPage(); 0960 } 0961 0962 return $itemNumber; 0963 } 0964 0965 /** 0966 * Brings the page number in range of the paginator. 0967 * 0968 * @param integer $pageNumber 0969 * @return integer 0970 */ 0971 public function normalizePageNumber($pageNumber) 0972 { 0973 $pageNumber = (integer) $pageNumber; 0974 0975 if ($pageNumber < 1) { 0976 $pageNumber = 1; 0977 } 0978 0979 $pageCount = $this->count(); 0980 0981 if ($pageCount > 0 && $pageNumber > $pageCount) { 0982 $pageNumber = $pageCount; 0983 } 0984 0985 return $pageNumber; 0986 } 0987 0988 /** 0989 * Renders the paginator. 0990 * 0991 * @param Zend_View_Interface $view 0992 * @return string 0993 */ 0994 public function render(Zend_View_Interface $view = null) 0995 { 0996 if (null !== $view) { 0997 $this->setView($view); 0998 } 0999 1000 $view = $this->getView(); 1001 1002 return $view->paginationControl($this); 1003 } 1004 1005 /** 1006 * Returns the items of the current page as JSON. 1007 * 1008 * @return string 1009 */ 1010 public function toJson() 1011 { 1012 $currentItems = $this->getCurrentItems(); 1013 1014 if ($currentItems instanceof Zend_Db_Table_Rowset_Abstract) { 1015 return Zend_Json::encode($currentItems->toArray()); 1016 } else { 1017 return Zend_Json::encode($currentItems); 1018 } 1019 } 1020 1021 /** 1022 * Tells if there is an active cache object 1023 * and if the cache has not been desabled 1024 * 1025 * @return bool 1026 */ 1027 protected function _cacheEnabled() 1028 { 1029 return ((self::$_cache !== null) && $this->_cacheEnabled); 1030 } 1031 1032 /** 1033 * Makes an Id for the cache 1034 * Depends on the adapter object and the page number 1035 * 1036 * Used to store item in cache from that Paginator instance 1037 * and that current page 1038 * 1039 * @param int $page 1040 * @return string 1041 */ 1042 protected function _getCacheId($page = null) 1043 { 1044 if ($page === null) { 1045 $page = $this->getCurrentPageNumber(); 1046 } 1047 return self::CACHE_TAG_PREFIX . $page . '_' . $this->_getCacheInternalId(); 1048 } 1049 1050 /** 1051 * Get the internal cache id 1052 * Depends on the adapter and the item count per page 1053 * 1054 * Used to tag that unique Paginator instance in cache 1055 * 1056 * @return string 1057 */ 1058 protected function _getCacheInternalId() 1059 { 1060 $adapter = $this->getAdapter(); 1061 1062 if (method_exists($adapter, 'getCacheIdentifier')) { 1063 return md5(serialize(array( 1064 $adapter->getCacheIdentifier(), $this->getItemCountPerPage() 1065 ))); 1066 } else { 1067 return md5(serialize(array( 1068 $adapter, 1069 $this->getItemCountPerPage() 1070 ))); 1071 } 1072 } 1073 1074 /** 1075 * Calculates the page count. 1076 * 1077 * @return integer 1078 */ 1079 protected function _calculatePageCount() 1080 { 1081 return (integer) ceil($this->getTotalItemCount() / $this->getItemCountPerPage()); 1082 } 1083 1084 /** 1085 * Creates the page collection. 1086 * 1087 * @param string $scrollingStyle Scrolling style 1088 * @return stdClass 1089 */ 1090 protected function _createPages($scrollingStyle = null) 1091 { 1092 $pageCount = $this->count(); 1093 $currentPageNumber = $this->getCurrentPageNumber(); 1094 1095 $pages = new stdClass(); 1096 $pages->pageCount = $pageCount; 1097 $pages->itemCountPerPage = $this->getItemCountPerPage(); 1098 $pages->first = 1; 1099 $pages->current = $currentPageNumber; 1100 $pages->last = $pageCount; 1101 1102 // Previous and next 1103 if ($currentPageNumber - 1 > 0) { 1104 $pages->previous = $currentPageNumber - 1; 1105 } 1106 1107 if ($currentPageNumber + 1 <= $pageCount) { 1108 $pages->next = $currentPageNumber + 1; 1109 } 1110 1111 // Pages in range 1112 $scrollingStyle = $this->_loadScrollingStyle($scrollingStyle); 1113 $pages->pagesInRange = $scrollingStyle->getPages($this); 1114 $pages->firstPageInRange = min($pages->pagesInRange); 1115 $pages->lastPageInRange = max($pages->pagesInRange); 1116 1117 // Item numbers 1118 if ($this->getCurrentItems() !== null) { 1119 $pages->currentItemCount = $this->getCurrentItemCount(); 1120 $pages->itemCountPerPage = $this->getItemCountPerPage(); 1121 $pages->totalItemCount = $this->getTotalItemCount(); 1122 $pages->firstItemNumber = (($currentPageNumber - 1) * $this->getItemCountPerPage()) + 1; 1123 $pages->lastItemNumber = $pages->firstItemNumber + $pages->currentItemCount - 1; 1124 } 1125 1126 return $pages; 1127 } 1128 1129 /** 1130 * Loads a scrolling style. 1131 * 1132 * @param string $scrollingStyle 1133 * @return Zend_Paginator_ScrollingStyle_Interface 1134 */ 1135 protected function _loadScrollingStyle($scrollingStyle = null) 1136 { 1137 if ($scrollingStyle === null) { 1138 $scrollingStyle = self::$_defaultScrollingStyle; 1139 } 1140 1141 switch (strtolower(gettype($scrollingStyle))) { 1142 case 'object': 1143 if (!$scrollingStyle instanceof Zend_Paginator_ScrollingStyle_Interface) { 1144 /** 1145 * @see Zend_View_Exception 1146 */ 1147 // require_once 'Zend/View/Exception.php'; 1148 1149 throw new Zend_View_Exception('Scrolling style must implement ' . 1150 'Zend_Paginator_ScrollingStyle_Interface'); 1151 } 1152 1153 return $scrollingStyle; 1154 1155 case 'string': 1156 $className = self::getScrollingStyleLoader()->load($scrollingStyle); 1157 1158 return new $className(); 1159 1160 case 'null': 1161 // Fall through to default case 1162 1163 default: 1164 /** 1165 * @see Zend_View_Exception 1166 */ 1167 // require_once 'Zend/View/Exception.php'; 1168 1169 throw new Zend_View_Exception('Scrolling style must be a class ' . 1170 'name or object implementing Zend_Paginator_ScrollingStyle_Interface'); 1171 } 1172 } 1173 }