File indexing completed on 2025-01-19 05:21: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_Db
0017  * @subpackage Table
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  * @version    $Id$
0021  */
0022 
0023 /**
0024  * @category   Zend
0025  * @package    Zend_Db
0026  * @subpackage Table
0027  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0028  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0029  */
0030 abstract class Zend_Db_Table_Rowset_Abstract implements SeekableIterator, Countable, ArrayAccess
0031 {
0032     /**
0033      * The original data for each row.
0034      *
0035      * @var array
0036      */
0037     protected $_data = array();
0038 
0039     /**
0040      * Zend_Db_Table_Abstract object.
0041      *
0042      * @var Zend_Db_Table_Abstract
0043      */
0044     protected $_table;
0045 
0046     /**
0047      * Connected is true if we have a reference to a live
0048      * Zend_Db_Table_Abstract object.
0049      * This is false after the Rowset has been deserialized.
0050      *
0051      * @var boolean
0052      */
0053     protected $_connected = true;
0054 
0055     /**
0056      * Zend_Db_Table_Abstract class name.
0057      *
0058      * @var string
0059      */
0060     protected $_tableClass;
0061 
0062     /**
0063      * Zend_Db_Table_Row_Abstract class name.
0064      *
0065      * @var string
0066      */
0067     protected $_rowClass = 'Zend_Db_Table_Row';
0068 
0069     /**
0070      * Iterator pointer.
0071      *
0072      * @var integer
0073      */
0074     protected $_pointer = 0;
0075 
0076     /**
0077      * How many data rows there are.
0078      *
0079      * @var integer
0080      */
0081     protected $_count;
0082 
0083     /**
0084      * Collection of instantiated Zend_Db_Table_Row objects.
0085      *
0086      * @var array
0087      */
0088     protected $_rows = array();
0089 
0090     /**
0091      * @var boolean
0092      */
0093     protected $_stored = false;
0094 
0095     /**
0096      * @var boolean
0097      */
0098     protected $_readOnly = false;
0099 
0100     /**
0101      * Constructor.
0102      *
0103      * @param array $config
0104      */
0105     public function __construct(array $config)
0106     {
0107         if (isset($config['table'])) {
0108             $this->_table      = $config['table'];
0109             $this->_tableClass = get_class($this->_table);
0110         }
0111         if (isset($config['rowClass'])) {
0112             $this->_rowClass   = $config['rowClass'];
0113         }
0114         if (!class_exists($this->_rowClass)) {
0115             // require_once 'Zend/Loader.php';
0116             Zend_Loader::loadClass($this->_rowClass);
0117         }
0118         if (isset($config['data'])) {
0119             $this->_data       = $config['data'];
0120         }
0121         if (isset($config['readOnly'])) {
0122             $this->_readOnly   = $config['readOnly'];
0123         }
0124         if (isset($config['stored'])) {
0125             $this->_stored     = $config['stored'];
0126         }
0127 
0128         // set the count of rows
0129         $this->_count = count($this->_data);
0130 
0131         $this->init();
0132     }
0133 
0134     /**
0135      * Store data, class names, and state in serialized object
0136      *
0137      * @return array
0138      */
0139     public function __sleep()
0140     {
0141         return array('_data', '_tableClass', '_rowClass', '_pointer', '_count', '_rows', '_stored',
0142                      '_readOnly');
0143     }
0144 
0145     /**
0146      * Setup to do on wakeup.
0147      * A de-serialized Rowset should not be assumed to have access to a live
0148      * database connection, so set _connected = false.
0149      *
0150      * @return void
0151      */
0152     public function __wakeup()
0153     {
0154         $this->_connected = false;
0155     }
0156 
0157     /**
0158      * Initialize object
0159      *
0160      * Called from {@link __construct()} as final step of object instantiation.
0161      *
0162      * @return void
0163      */
0164     public function init()
0165     {
0166     }
0167 
0168     /**
0169      * Return the connected state of the rowset.
0170      *
0171      * @return boolean
0172      */
0173     public function isConnected()
0174     {
0175         return $this->_connected;
0176     }
0177 
0178     /**
0179      * Returns the table object, or null if this is disconnected rowset
0180      *
0181      * @return Zend_Db_Table_Abstract
0182      */
0183     public function getTable()
0184     {
0185         return $this->_table;
0186     }
0187 
0188     /**
0189      * Set the table object, to re-establish a live connection
0190      * to the database for a Rowset that has been de-serialized.
0191      *
0192      * @param Zend_Db_Table_Abstract $table
0193      * @return boolean
0194      * @throws Zend_Db_Table_Row_Exception
0195      */
0196     public function setTable(Zend_Db_Table_Abstract $table)
0197     {
0198         $this->_table = $table;
0199         $this->_connected = false;
0200         // @todo This works only if we have iterated through
0201         // the result set once to instantiate the rows.
0202         foreach ($this as $row) {
0203             $connected = $row->setTable($table);
0204             if ($connected == true) {
0205                 $this->_connected = true;
0206             }
0207         }
0208         $this->rewind();
0209         return $this->_connected;
0210     }
0211 
0212     /**
0213      * Query the class name of the Table object for which this
0214      * Rowset was created.
0215      *
0216      * @return string
0217      */
0218     public function getTableClass()
0219     {
0220         return $this->_tableClass;
0221     }
0222 
0223     /**
0224      * Rewind the Iterator to the first element.
0225      * Similar to the reset() function for arrays in PHP.
0226      * Required by interface Iterator.
0227      *
0228      * @return Zend_Db_Table_Rowset_Abstract Fluent interface.
0229      */
0230     public function rewind()
0231     {
0232         $this->_pointer = 0;
0233         return $this;
0234     }
0235 
0236     /**
0237      * Return the current element.
0238      * Similar to the current() function for arrays in PHP
0239      * Required by interface Iterator.
0240      *
0241      * @return Zend_Db_Table_Row_Abstract current element from the collection
0242      */
0243     public function current()
0244     {
0245         if ($this->valid() === false) {
0246             return null;
0247         }
0248 
0249         // return the row object
0250         return $this->_loadAndReturnRow($this->_pointer);
0251     }
0252 
0253     /**
0254      * Return the identifying key of the current element.
0255      * Similar to the key() function for arrays in PHP.
0256      * Required by interface Iterator.
0257      *
0258      * @return int
0259      */
0260     public function key()
0261     {
0262         return $this->_pointer;
0263     }
0264 
0265     /**
0266      * Move forward to next element.
0267      * Similar to the next() function for arrays in PHP.
0268      * Required by interface Iterator.
0269      *
0270      * @return void
0271      */
0272     public function next()
0273     {
0274         ++$this->_pointer;
0275     }
0276 
0277     /**
0278      * Check if there is a current element after calls to rewind() or next().
0279      * Used to check if we've iterated to the end of the collection.
0280      * Required by interface Iterator.
0281      *
0282      * @return bool False if there's nothing more to iterate over
0283      */
0284     public function valid()
0285     {
0286         return $this->_pointer >= 0 && $this->_pointer < $this->_count;
0287     }
0288 
0289     /**
0290      * Returns the number of elements in the collection.
0291      *
0292      * Implements Countable::count()
0293      *
0294      * @return int
0295      */
0296     public function count()
0297     {
0298         return $this->_count;
0299     }
0300 
0301     /**
0302      * Take the Iterator to position $position
0303      * Required by interface SeekableIterator.
0304      *
0305      * @param int $position the position to seek to
0306      * @return Zend_Db_Table_Rowset_Abstract
0307      * @throws Zend_Db_Table_Rowset_Exception
0308      */
0309     public function seek($position)
0310     {
0311         $position = (int) $position;
0312         if ($position < 0 || $position >= $this->_count) {
0313             // require_once 'Zend/Db/Table/Rowset/Exception.php';
0314             throw new Zend_Db_Table_Rowset_Exception("Illegal index $position");
0315         }
0316         $this->_pointer = $position;
0317         return $this;
0318     }
0319 
0320     /**
0321      * Check if an offset exists
0322      * Required by the ArrayAccess implementation
0323      *
0324      * @param string $offset
0325      * @return boolean
0326      */
0327     public function offsetExists($offset)
0328     {
0329         return isset($this->_data[(int) $offset]);
0330     }
0331 
0332     /**
0333      * Get the row for the given offset
0334      * Required by the ArrayAccess implementation
0335      *
0336      * @param string $offset
0337      * @return Zend_Db_Table_Row_Abstract
0338      */
0339     public function offsetGet($offset)
0340     {
0341         $offset = (int) $offset;
0342         if ($offset < 0 || $offset >= $this->_count) {
0343             // require_once 'Zend/Db/Table/Rowset/Exception.php';
0344             throw new Zend_Db_Table_Rowset_Exception("Illegal index $offset");
0345         }
0346         $this->_pointer = $offset;
0347 
0348         return $this->current();
0349     }
0350 
0351     /**
0352      * Does nothing
0353      * Required by the ArrayAccess implementation
0354      *
0355      * @param string $offset
0356      * @param mixed $value
0357      */
0358     public function offsetSet($offset, $value)
0359     {
0360     }
0361 
0362     /**
0363      * Does nothing
0364      * Required by the ArrayAccess implementation
0365      *
0366      * @param string $offset
0367      */
0368     public function offsetUnset($offset)
0369     {
0370     }
0371 
0372     /**
0373      * Returns a Zend_Db_Table_Row from a known position into the Iterator
0374      *
0375      * @param int $position the position of the row expected
0376      * @param bool $seek wether or not seek the iterator to that position after
0377      * @return Zend_Db_Table_Row
0378      * @throws Zend_Db_Table_Rowset_Exception
0379      */
0380     public function getRow($position, $seek = false)
0381     {
0382         try {
0383             $row = $this->_loadAndReturnRow($position);
0384         } catch (Zend_Db_Table_Rowset_Exception $e) {
0385             // require_once 'Zend/Db/Table/Rowset/Exception.php';
0386             throw new Zend_Db_Table_Rowset_Exception('No row could be found at position ' . (int) $position, 0, $e);
0387         }
0388 
0389         if ($seek == true) {
0390             $this->seek($position);
0391         }
0392 
0393         return $row;
0394     }
0395 
0396     /**
0397      * Returns all data as an array.
0398      *
0399      * Updates the $_data property with current row object values.
0400      *
0401      * @return array
0402      */
0403     public function toArray()
0404     {
0405         // @todo This works only if we have iterated through
0406         // the result set once to instantiate the rows.
0407         foreach ($this->_rows as $i => $row) {
0408             $this->_data[$i] = $row->toArray();
0409         }
0410         return $this->_data;
0411     }
0412 
0413     protected function _loadAndReturnRow($position)
0414     {
0415         if (!isset($this->_data[$position])) {
0416             // require_once 'Zend/Db/Table/Rowset/Exception.php';
0417             throw new Zend_Db_Table_Rowset_Exception("Data for provided position does not exist");
0418         }
0419 
0420         // do we already have a row object for this position?
0421         if (empty($this->_rows[$position])) {
0422             $this->_rows[$position] = new $this->_rowClass(
0423                 array(
0424                     'table'    => $this->_table,
0425                     'data'     => $this->_data[$position],
0426                     'stored'   => $this->_stored,
0427                     'readOnly' => $this->_readOnly
0428                 )
0429             );
0430 
0431             if ( $this->_table instanceof Zend_Db_Table_Abstract ) {
0432                 $info = $this->_table->info();
0433 
0434                 if ( $this->_rows[$position] instanceof Zend_Db_Table_Row_Abstract ) {
0435                     if ($info['cols'] == array_keys($this->_data[$position])) {
0436                         $this->_rows[$position]->setTable($this->getTable());
0437                     }
0438                 }
0439             } else {
0440                 $this->_rows[$position]->setTable(null);
0441             }
0442         }
0443 
0444         // return the row object
0445         return $this->_rows[$position];
0446     }
0447 
0448 }