/library/Zend/Db/Table/Rowset/Abstract.php
PHP | 435 lines | 171 code | 41 blank | 223 comment | 19 complexity | 0a27c9965ad2f6defdbfdbc141fd2a50 MD5 | raw file
Possible License(s): AGPL-1.0
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_Db
17 * @subpackage Table
18 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license http://framework.zend.com/license/new-bsd New BSD License
20 * @version $Id: Abstract.php 24594 2012-01-05 21:27:01Z matthew $
21 */
22
23/**
24 * @category Zend
25 * @package Zend_Db
26 * @subpackage Table
27 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
28 * @license http://framework.zend.com/license/new-bsd New BSD License
29 */
30abstract class Zend_Db_Table_Rowset_Abstract implements SeekableIterator, Countable, ArrayAccess
31{
32 /**
33 * The original data for each row.
34 *
35 * @var array
36 */
37 protected $_data = array();
38
39 /**
40 * Zend_Db_Table_Abstract object.
41 *
42 * @var Zend_Db_Table_Abstract
43 */
44 protected $_table;
45
46 /**
47 * Connected is true if we have a reference to a live
48 * Zend_Db_Table_Abstract object.
49 * This is false after the Rowset has been deserialized.
50 *
51 * @var boolean
52 */
53 protected $_connected = true;
54
55 /**
56 * Zend_Db_Table_Abstract class name.
57 *
58 * @var string
59 */
60 protected $_tableClass;
61
62 /**
63 * Zend_Db_Table_Row_Abstract class name.
64 *
65 * @var string
66 */
67 protected $_rowClass = 'Zend_Db_Table_Row';
68
69 /**
70 * Iterator pointer.
71 *
72 * @var integer
73 */
74 protected $_pointer = 0;
75
76 /**
77 * How many data rows there are.
78 *
79 * @var integer
80 */
81 protected $_count;
82
83 /**
84 * Collection of instantiated Zend_Db_Table_Row objects.
85 *
86 * @var array
87 */
88 protected $_rows = array();
89
90 /**
91 * @var boolean
92 */
93 protected $_stored = false;
94
95 /**
96 * @var boolean
97 */
98 protected $_readOnly = false;
99
100 /**
101 * Constructor.
102 *
103 * @param array $config
104 */
105 public function __construct(array $config)
106 {
107 if (isset($config['table'])) {
108 $this->_table = $config['table'];
109 $this->_tableClass = get_class($this->_table);
110 }
111 if (isset($config['rowClass'])) {
112 $this->_rowClass = $config['rowClass'];
113 }
114 if (!class_exists($this->_rowClass)) {
115 require_once 'Zend/Loader.php';
116 Zend_Loader::loadClass($this->_rowClass);
117 }
118 if (isset($config['data'])) {
119 $this->_data = $config['data'];
120 }
121 if (isset($config['readOnly'])) {
122 $this->_readOnly = $config['readOnly'];
123 }
124 if (isset($config['stored'])) {
125 $this->_stored = $config['stored'];
126 }
127
128 // set the count of rows
129 $this->_count = count($this->_data);
130
131 $this->init();
132 }
133
134 /**
135 * Store data, class names, and state in serialized object
136 *
137 * @return array
138 */
139 public function __sleep()
140 {
141 return array('_data', '_tableClass', '_rowClass', '_pointer', '_count', '_rows', '_stored',
142 '_readOnly');
143 }
144
145 /**
146 * Setup to do on wakeup.
147 * A de-serialized Rowset should not be assumed to have access to a live
148 * database connection, so set _connected = false.
149 *
150 * @return void
151 */
152 public function __wakeup()
153 {
154 $this->_connected = false;
155 }
156
157 /**
158 * Initialize object
159 *
160 * Called from {@link __construct()} as final step of object instantiation.
161 *
162 * @return void
163 */
164 public function init()
165 {
166 }
167
168 /**
169 * Return the connected state of the rowset.
170 *
171 * @return boolean
172 */
173 public function isConnected()
174 {
175 return $this->_connected;
176 }
177
178 /**
179 * Returns the table object, or null if this is disconnected rowset
180 *
181 * @return Zend_Db_Table_Abstract
182 */
183 public function getTable()
184 {
185 return $this->_table;
186 }
187
188 /**
189 * Set the table object, to re-establish a live connection
190 * to the database for a Rowset that has been de-serialized.
191 *
192 * @param Zend_Db_Table_Abstract $table
193 * @return boolean
194 * @throws Zend_Db_Table_Row_Exception
195 */
196 public function setTable(Zend_Db_Table_Abstract $table)
197 {
198 $this->_table = $table;
199 $this->_connected = false;
200 // @todo This works only if we have iterated through
201 // the result set once to instantiate the rows.
202 foreach ($this as $row) {
203 $connected = $row->setTable($table);
204 if ($connected == true) {
205 $this->_connected = true;
206 }
207 }
208 return $this->_connected;
209 }
210
211 /**
212 * Query the class name of the Table object for which this
213 * Rowset was created.
214 *
215 * @return string
216 */
217 public function getTableClass()
218 {
219 return $this->_tableClass;
220 }
221
222 /**
223 * Rewind the Iterator to the first element.
224 * Similar to the reset() function for arrays in PHP.
225 * Required by interface Iterator.
226 *
227 * @return Zend_Db_Table_Rowset_Abstract Fluent interface.
228 */
229 public function rewind()
230 {
231 $this->_pointer = 0;
232 return $this;
233 }
234
235 /**
236 * Return the current element.
237 * Similar to the current() function for arrays in PHP
238 * Required by interface Iterator.
239 *
240 * @return Zend_Db_Table_Row_Abstract current element from the collection
241 */
242 public function current()
243 {
244 if ($this->valid() === false) {
245 return null;
246 }
247
248 // return the row object
249 return $this->_loadAndReturnRow($this->_pointer);
250 }
251
252 /**
253 * Return the identifying key of the current element.
254 * Similar to the key() function for arrays in PHP.
255 * Required by interface Iterator.
256 *
257 * @return int
258 */
259 public function key()
260 {
261 return $this->_pointer;
262 }
263
264 /**
265 * Move forward to next element.
266 * Similar to the next() function for arrays in PHP.
267 * Required by interface Iterator.
268 *
269 * @return void
270 */
271 public function next()
272 {
273 ++$this->_pointer;
274 }
275
276 /**
277 * Check if there is a current element after calls to rewind() or next().
278 * Used to check if we've iterated to the end of the collection.
279 * Required by interface Iterator.
280 *
281 * @return bool False if there's nothing more to iterate over
282 */
283 public function valid()
284 {
285 return $this->_pointer >= 0 && $this->_pointer < $this->_count;
286 }
287
288 /**
289 * Returns the number of elements in the collection.
290 *
291 * Implements Countable::count()
292 *
293 * @return int
294 */
295 public function count()
296 {
297 return $this->_count;
298 }
299
300 /**
301 * Take the Iterator to position $position
302 * Required by interface SeekableIterator.
303 *
304 * @param int $position the position to seek to
305 * @return Zend_Db_Table_Rowset_Abstract
306 * @throws Zend_Db_Table_Rowset_Exception
307 */
308 public function seek($position)
309 {
310 $position = (int) $position;
311 if ($position < 0 || $position >= $this->_count) {
312 require_once 'Zend/Db/Table/Rowset/Exception.php';
313 throw new Zend_Db_Table_Rowset_Exception("Illegal index $position");
314 }
315 $this->_pointer = $position;
316 return $this;
317 }
318
319 /**
320 * Check if an offset exists
321 * Required by the ArrayAccess implementation
322 *
323 * @param string $offset
324 * @return boolean
325 */
326 public function offsetExists($offset)
327 {
328 return isset($this->_data[(int) $offset]);
329 }
330
331 /**
332 * Get the row for the given offset
333 * Required by the ArrayAccess implementation
334 *
335 * @param string $offset
336 * @return Zend_Db_Table_Row_Abstract
337 */
338 public function offsetGet($offset)
339 {
340 $offset = (int) $offset;
341 if ($offset < 0 || $offset >= $this->_count) {
342 require_once 'Zend/Db/Table/Rowset/Exception.php';
343 throw new Zend_Db_Table_Rowset_Exception("Illegal index $offset");
344 }
345 $this->_pointer = $offset;
346
347 return $this->current();
348 }
349
350 /**
351 * Does nothing
352 * Required by the ArrayAccess implementation
353 *
354 * @param string $offset
355 * @param mixed $value
356 */
357 public function offsetSet($offset, $value)
358 {
359 }
360
361 /**
362 * Does nothing
363 * Required by the ArrayAccess implementation
364 *
365 * @param string $offset
366 */
367 public function offsetUnset($offset)
368 {
369 }
370
371 /**
372 * Returns a Zend_Db_Table_Row from a known position into the Iterator
373 *
374 * @param int $position the position of the row expected
375 * @param bool $seek wether or not seek the iterator to that position after
376 * @return Zend_Db_Table_Row
377 * @throws Zend_Db_Table_Rowset_Exception
378 */
379 public function getRow($position, $seek = false)
380 {
381 try {
382 $row = $this->_loadAndReturnRow($position);
383 } catch (Zend_Db_Table_Rowset_Exception $e) {
384 require_once 'Zend/Db/Table/Rowset/Exception.php';
385 throw new Zend_Db_Table_Rowset_Exception('No row could be found at position ' . (int) $position, 0, $e);
386 }
387
388 if ($seek == true) {
389 $this->seek($position);
390 }
391
392 return $row;
393 }
394
395 /**
396 * Returns all data as an array.
397 *
398 * Updates the $_data property with current row object values.
399 *
400 * @return array
401 */
402 public function toArray()
403 {
404 // @todo This works only if we have iterated through
405 // the result set once to instantiate the rows.
406 foreach ($this->_rows as $i => $row) {
407 $this->_data[$i] = $row->toArray();
408 }
409 return $this->_data;
410 }
411
412 protected function _loadAndReturnRow($position)
413 {
414 if (!isset($this->_data[$position])) {
415 require_once 'Zend/Db/Table/Rowset/Exception.php';
416 throw new Zend_Db_Table_Rowset_Exception("Data for provided position does not exist");
417 }
418
419 // do we already have a row object for this position?
420 if (empty($this->_rows[$position])) {
421 $this->_rows[$position] = new $this->_rowClass(
422 array(
423 'table' => $this->_table,
424 'data' => $this->_data[$position],
425 'stored' => $this->_stored,
426 'readOnly' => $this->_readOnly
427 )
428 );
429 }
430
431 // return the row object
432 return $this->_rows[$position];
433 }
434
435}