File indexing completed on 2024-04-28 06:00:03

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 }