CDataProviderIterator.php 4.21 KB
Newer Older
JULIO JARAMILLO's avatar
JULIO JARAMILLO committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
<?php
/**
 * CDataProviderIterator class file.
 *
 * @author Charles Pick <charles.pick@gmail.com>
 * @link http://www.yiiframework.com/
 * @copyright 2008-2013 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

/**
 * CDataProviderIterator allows iteration over large data sets without holding the entire set in memory.
 *
 * CDataProviderIterator iterates over the results of a data provider, starting at the first page
 * of results and ending at the last page. It is usually only suited for use with {@link CActiveDataProvider}.
 *
 * For example, the following code will iterate over all registered users (active record class User) without
 * running out of memory, even if there are millions of users in the database.
 * <pre>
 * $dataProvider = new CActiveDataProvider("User");
 * $iterator = new CDataProviderIterator($dataProvider);
 * foreach($iterator as $user) {
 *	 echo $user->name."\n";
 * }
 * </pre>
 *
 * @property CDataProvider $dataProvider the data provider to iterate over
 * @property integer $totalItemCount the total number of items in the iterator
 *
 * @author Charles Pick <charles.pick@gmail.com>
 * @author Carsten Brandt <mail@cebe.cc>
 * @package system.web
 * @since 1.1.13
 */
class CDataProviderIterator extends CComponent implements Iterator, Countable
{
	private $_dataProvider;
	private $_currentIndex=-1;
	private $_currentPage=0;
	private $_totalItemCount=-1;
	private $_items;

	/**
	 * Constructor.
	 * @param CDataProvider $dataProvider the data provider to iterate over
	 * @param integer $pageSize pageSize to use for iteration. This is the number of objects loaded into memory at the same time.
	 */
	public function __construct(CDataProvider $dataProvider, $pageSize=null)
	{
		$this->_dataProvider=$dataProvider;
		$this->_totalItemCount=$dataProvider->getTotalItemCount();

		if(($pagination=$this->_dataProvider->getPagination())===false)
			$this->_dataProvider->setPagination($pagination=new CPagination());

		if($pageSize!==null)
			$pagination->setPageSize($pageSize);
	}

	/**
	 * Returns the data provider to iterate over
	 * @return CDataProvider the data provider to iterate over
	 */
	public function getDataProvider()
	{
		return $this->_dataProvider;
	}

	/**
	 * Gets the total number of items to iterate over
	 * @return integer the total number of items to iterate over
	 */
	public function getTotalItemCount()
	{
		return $this->_totalItemCount;
	}

	/**
	 * Loads a page of items
	 * @return array the items from the next page of results
	 */
	protected function loadPage()
	{
		$this->_dataProvider->getPagination()->setCurrentPage($this->_currentPage);
		return $this->_items=$this->dataProvider->getData(true);
	}

	/**
	 * Gets the current item in the list.
	 * This method is required by the Iterator interface.
	 * @return mixed the current item in the list
	 */
	public function current()
	{
		return $this->_items[$this->_currentIndex];
	}

	/**
	 * Gets the key of the current item.
	 * This method is required by the Iterator interface.
	 * @return integer the key of the current item
	 */
	public function key()
	{
		$pageSize=$this->_dataProvider->getPagination()->getPageSize();
		return $this->_currentPage*$pageSize+$this->_currentIndex;
	}

	/**
	 * Moves the pointer to the next item in the list.
	 * This method is required by the Iterator interface.
	 */
	public function next()
	{
		$pageSize=$this->_dataProvider->getPagination()->getPageSize();
		$this->_currentIndex++;
		if($this->_currentIndex >= $pageSize)
		{
			$this->_currentPage++;
			$this->_currentIndex=0;
			$this->loadPage();
		}
	}

	/**
	 * Rewinds the iterator to the start of the list.
	 * This method is required by the Iterator interface.
	 */
	public function rewind()
	{
		$this->_currentIndex=0;
		$this->_currentPage=0;
		$this->loadPage();
	}

	/**
	 * Checks if the current position is valid or not.
	 * This method is required by the Iterator interface.
	 * @return boolean true if this index is valid
	 */
	public function valid()
	{
		return $this->key() < $this->_totalItemCount;
	}

	/**
	 * Gets the total number of items in the dataProvider.
	 * This method is required by the Countable interface.
	 * @return integer the total number of items
	 */
	public function count()
	{
		return $this->_totalItemCount;
	}
}