00001 <?php
00026 require_once 'Zend/Db/Adapter/Abstract.php';
00027
00031 require_once 'Zend/Db/Select.php';
00032
00036 require_once 'Zend/Db.php';
00037
00047 abstract class Zend_Db_Table_Abstract
00048 {
00049
00050 const ADAPTER = 'db';
00051 const DEFINITION = 'definition';
00052 const DEFINITION_CONFIG_NAME = 'definitionConfigName';
00053 const SCHEMA = 'schema';
00054 const NAME = 'name';
00055 const PRIMARY = 'primary';
00056 const COLS = 'cols';
00057 const METADATA = 'metadata';
00058 const METADATA_CACHE = 'metadataCache';
00059 const METADATA_CACHE_IN_CLASS = 'metadataCacheInClass';
00060 const ROW_CLASS = 'rowClass';
00061 const ROWSET_CLASS = 'rowsetClass';
00062 const REFERENCE_MAP = 'referenceMap';
00063 const DEPENDENT_TABLES = 'dependentTables';
00064 const SEQUENCE = 'sequence';
00065
00066 const COLUMNS = 'columns';
00067 const REF_TABLE_CLASS = 'refTableClass';
00068 const REF_COLUMNS = 'refColumns';
00069 const ON_DELETE = 'onDelete';
00070 const ON_UPDATE = 'onUpdate';
00071
00072 const CASCADE = 'cascade';
00073 const RESTRICT = 'restrict';
00074 const SET_NULL = 'setNull';
00075
00076 const DEFAULT_NONE = 'defaultNone';
00077 const DEFAULT_CLASS = 'defaultClass';
00078 const DEFAULT_DB = 'defaultDb';
00079
00080 const SELECT_WITH_FROM_PART = true;
00081 const SELECT_WITHOUT_FROM_PART = false;
00082
00088 protected static $_defaultDb;
00089
00095 protected $_definition = null;
00096
00102 protected $_definitionConfigName = null;
00103
00109 protected static $_defaultMetadataCache = null;
00110
00116 protected $_db;
00117
00123 protected $_schema = null;
00124
00130 protected $_name = null;
00131
00137 protected $_cols;
00138
00147 protected $_primary = null;
00148
00159 protected $_identity = 1;
00160
00167 protected $_sequence = true;
00168
00174 protected $_metadata = array();
00175
00181 protected $_metadataCache = null;
00182
00187 protected $_metadataCacheInClass = true;
00188
00194 protected $_rowClass = 'Zend_Db_Table_Row';
00195
00201 protected $_rowsetClass = 'Zend_Db_Table_Rowset';
00202
00221 protected $_referenceMap = array();
00222
00231 protected $_dependentTables = array();
00232
00233
00234 protected $_defaultSource = self::DEFAULT_NONE;
00235 protected $_defaultValues = array();
00236
00255 public function __construct($config = array())
00256 {
00260 if (!is_array($config)) {
00261 $config = array(self::ADAPTER => $config);
00262 }
00263
00264 if ($config) {
00265 $this->setOptions($config);
00266 }
00267
00268 $this->_setup();
00269 $this->init();
00270 }
00271
00278 public function setOptions(Array $options)
00279 {
00280 foreach ($options as $key => $value) {
00281 switch ($key) {
00282 case self::ADAPTER:
00283 $this->_setAdapter($value);
00284 break;
00285 case self::DEFINITION:
00286 $this->setDefinition($value);
00287 break;
00288 case self::DEFINITION_CONFIG_NAME:
00289 $this->setDefinitionConfigName($value);
00290 break;
00291 case self::SCHEMA:
00292 $this->_schema = (string) $value;
00293 break;
00294 case self::NAME:
00295 $this->_name = (string) $value;
00296 break;
00297 case self::PRIMARY:
00298 $this->_primary = (array) $value;
00299 break;
00300 case self::ROW_CLASS:
00301 $this->setRowClass($value);
00302 break;
00303 case self::ROWSET_CLASS:
00304 $this->setRowsetClass($value);
00305 break;
00306 case self::REFERENCE_MAP:
00307 $this->setReferences($value);
00308 break;
00309 case self::DEPENDENT_TABLES:
00310 $this->setDependentTables($value);
00311 break;
00312 case self::METADATA_CACHE:
00313 $this->_setMetadataCache($value);
00314 break;
00315 case self::METADATA_CACHE_IN_CLASS:
00316 $this->setMetadataCacheInClass($value);
00317 break;
00318 case self::SEQUENCE:
00319 $this->_setSequence($value);
00320 break;
00321 default:
00322
00323 break;
00324 }
00325 }
00326
00327 return $this;
00328 }
00329
00336 public function setDefinition(Zend_Db_Table_Definition $definition)
00337 {
00338 $this->_definition = $definition;
00339 return $this;
00340 }
00341
00347 public function getDefinition()
00348 {
00349 return $this->_definition;
00350 }
00351
00358 public function setDefinitionConfigName($definitionConfigName)
00359 {
00360 $this->_definitionConfigName = $definitionConfigName;
00361 return $this;
00362 }
00363
00369 public function getDefinitionConfigName()
00370 {
00371 return $this->_definitionConfigName;
00372 }
00373
00378 public function setRowClass($classname)
00379 {
00380 $this->_rowClass = (string) $classname;
00381
00382 return $this;
00383 }
00384
00388 public function getRowClass()
00389 {
00390 return $this->_rowClass;
00391 }
00392
00397 public function setRowsetClass($classname)
00398 {
00399 $this->_rowsetClass = (string) $classname;
00400
00401 return $this;
00402 }
00403
00407 public function getRowsetClass()
00408 {
00409 return $this->_rowsetClass;
00410 }
00411
00423 public function addReference($ruleKey, $columns, $refTableClass, $refColumns,
00424 $onDelete = null, $onUpdate = null)
00425 {
00426 $reference = array(self::COLUMNS => (array) $columns,
00427 self::REF_TABLE_CLASS => $refTableClass,
00428 self::REF_COLUMNS => (array) $refColumns);
00429
00430 if (!empty($onDelete)) {
00431 $reference[self::ON_DELETE] = $onDelete;
00432 }
00433
00434 if (!empty($onUpdate)) {
00435 $reference[self::ON_UPDATE] = $onUpdate;
00436 }
00437
00438 $this->_referenceMap[$ruleKey] = $reference;
00439
00440 return $this;
00441 }
00442
00447 public function setReferences(array $referenceMap)
00448 {
00449 $this->_referenceMap = $referenceMap;
00450
00451 return $this;
00452 }
00453
00460 public function getReference($tableClassname, $ruleKey = null)
00461 {
00462 $thisClass = get_class($this);
00463 if ($thisClass === 'Zend_Db_Table') {
00464 $thisClass = $this->_definitionConfigName;
00465 }
00466 $refMap = $this->_getReferenceMapNormalized();
00467 if ($ruleKey !== null) {
00468 if (!isset($refMap[$ruleKey])) {
00469 require_once "Zend/Db/Table/Exception.php";
00470 throw new Zend_Db_Table_Exception("No reference rule \"$ruleKey\" from table $thisClass to table $tableClassname");
00471 }
00472 if ($refMap[$ruleKey][self::REF_TABLE_CLASS] != $tableClassname) {
00473 require_once "Zend/Db/Table/Exception.php";
00474 throw new Zend_Db_Table_Exception("Reference rule \"$ruleKey\" does not reference table $tableClassname");
00475 }
00476 return $refMap[$ruleKey];
00477 }
00478 foreach ($refMap as $reference) {
00479 if ($reference[self::REF_TABLE_CLASS] == $tableClassname) {
00480 return $reference;
00481 }
00482 }
00483 require_once "Zend/Db/Table/Exception.php";
00484 throw new Zend_Db_Table_Exception("No reference from table $thisClass to table $tableClassname");
00485 }
00486
00491 public function setDependentTables(array $dependentTables)
00492 {
00493 $this->_dependentTables = $dependentTables;
00494
00495 return $this;
00496 }
00497
00501 public function getDependentTables()
00502 {
00503 return $this->_dependentTables;
00504 }
00505
00512 public function setDefaultSource($defaultSource = self::DEFAULT_NONE)
00513 {
00514 if (!in_array($defaultSource, array(self::DEFAULT_CLASS, self::DEFAULT_DB, self::DEFAULT_NONE))) {
00515 $defaultSource = self::DEFAULT_NONE;
00516 }
00517
00518 $this->_defaultSource = $defaultSource;
00519 return $this;
00520 }
00521
00527 public function getDefaultSource()
00528 {
00529 return $this->_defaultSource;
00530 }
00531
00538 public function setDefaultValues(Array $defaultValues)
00539 {
00540 foreach ($defaultValues as $defaultName => $defaultValue) {
00541 if (array_key_exists($defaultName, $this->_metadata)) {
00542 $this->_defaultValues[$defaultName] = $defaultValue;
00543 }
00544 }
00545 return $this;
00546 }
00547
00548 public function getDefaultValues()
00549 {
00550 return $this->_defaultValues;
00551 }
00552
00553
00560 public static function setDefaultAdapter($db = null)
00561 {
00562 self::$_defaultDb = self::_setupAdapter($db);
00563 }
00564
00570 public static function getDefaultAdapter()
00571 {
00572 return self::$_defaultDb;
00573 }
00574
00579 protected function _setAdapter($db)
00580 {
00581 $this->_db = self::_setupAdapter($db);
00582 return $this;
00583 }
00584
00590 public function getAdapter()
00591 {
00592 return $this->_db;
00593 }
00594
00600 protected static function _setupAdapter($db)
00601 {
00602 if ($db === null) {
00603 return null;
00604 }
00605 if (is_string($db)) {
00606 require_once 'Zend/Registry.php';
00607 $db = Zend_Registry::get($db);
00608 }
00609 if (!$db instanceof Zend_Db_Adapter_Abstract) {
00610 require_once 'Zend/Db/Table/Exception.php';
00611 throw new Zend_Db_Table_Exception('Argument must be of type Zend_Db_Adapter_Abstract, or a Registry key where a Zend_Db_Adapter_Abstract object is stored');
00612 }
00613 return $db;
00614 }
00615
00624 public static function setDefaultMetadataCache($metadataCache = null)
00625 {
00626 self::$_defaultMetadataCache = self::_setupMetadataCache($metadataCache);
00627 }
00628
00634 public static function getDefaultMetadataCache()
00635 {
00636 return self::$_defaultMetadataCache;
00637 }
00638
00650 protected function _setMetadataCache($metadataCache)
00651 {
00652 $this->_metadataCache = self::_setupMetadataCache($metadataCache);
00653 return $this;
00654 }
00655
00661 public function getMetadataCache()
00662 {
00663 return $this->_metadataCache;
00664 }
00665
00673 public function setMetadataCacheInClass($flag)
00674 {
00675 $this->_metadataCacheInClass = (bool) $flag;
00676 return $this;
00677 }
00678
00685 public function metadataCacheInClass()
00686 {
00687 return $this->_metadataCacheInClass;
00688 }
00689
00695 protected static function _setupMetadataCache($metadataCache)
00696 {
00697 if ($metadataCache === null) {
00698 return null;
00699 }
00700 if (is_string($metadataCache)) {
00701 require_once 'Zend/Registry.php';
00702 $metadataCache = Zend_Registry::get($metadataCache);
00703 }
00704 if (!$metadataCache instanceof Zend_Cache_Core) {
00705 require_once 'Zend/Db/Table/Exception.php';
00706 throw new Zend_Db_Table_Exception('Argument must be of type Zend_Cache_Core, or a Registry key where a Zend_Cache_Core object is stored');
00707 }
00708 return $metadataCache;
00709 }
00710
00723 protected function _setSequence($sequence)
00724 {
00725 $this->_sequence = $sequence;
00726
00727 return $this;
00728 }
00729
00737 protected function _setup()
00738 {
00739 $this->_setupDatabaseAdapter();
00740 $this->_setupTableName();
00741 }
00742
00748 protected function _setupDatabaseAdapter()
00749 {
00750 if (! $this->_db) {
00751 $this->_db = self::getDefaultAdapter();
00752 if (!$this->_db instanceof Zend_Db_Adapter_Abstract) {
00753 require_once 'Zend/Db/Table/Exception.php';
00754 throw new Zend_Db_Table_Exception('No adapter found for ' . get_class($this));
00755 }
00756 }
00757 }
00758
00770 protected function _setupTableName()
00771 {
00772 if (! $this->_name) {
00773 $this->_name = get_class($this);
00774 } else if (strpos($this->_name, '.')) {
00775 list($this->_schema, $this->_name) = explode('.', $this->_name);
00776 }
00777 }
00778
00788 protected function _setupMetadata()
00789 {
00790 if ($this->metadataCacheInClass() && (count($this->_metadata) > 0)) {
00791 return true;
00792 }
00793
00794
00795 $isMetadataFromCache = true;
00796
00797
00798 if (null === $this->_metadataCache && null !== self::$_defaultMetadataCache) {
00799
00800 $this->_setMetadataCache(self::$_defaultMetadataCache);
00801 }
00802
00803
00804 if (null !== $this->_metadataCache) {
00805
00806
00807
00808 $dbConfig = $this->_db->getConfig();
00809
00810
00811 $cacheId = md5(
00812 (isset($dbConfig['options']['port']) ? ':'.$dbConfig['options']['port'] : null)
00813 . (isset($dbConfig['options']['host']) ? ':'.$dbConfig['options']['host'] : null)
00814 . '/'.$dbConfig['dbname'].':'.$this->_schema.'.'.$this->_name
00815 );
00816 }
00817
00818
00819 if (null === $this->_metadataCache || !($metadata = $this->_metadataCache->load($cacheId))) {
00820
00821 $isMetadataFromCache = false;
00822
00823 $metadata = $this->_db->describeTable($this->_name, $this->_schema);
00824
00825 if (null !== $this->_metadataCache && !$this->_metadataCache->save($metadata, $cacheId)) {
00829 require_once 'Zend/Db/Table/Exception.php';
00830 throw new Zend_Db_Table_Exception('Failed saving metadata to metadataCache');
00831 }
00832 }
00833
00834
00835 $this->_metadata = $metadata;
00836
00837
00838 return $isMetadataFromCache;
00839 }
00840
00846 protected function _getCols()
00847 {
00848 if (null === $this->_cols) {
00849 $this->_setupMetadata();
00850 $this->_cols = array_keys($this->_metadata);
00851 }
00852 return $this->_cols;
00853 }
00854
00863 protected function _setupPrimaryKey()
00864 {
00865 if (!$this->_primary) {
00866 $this->_setupMetadata();
00867 $this->_primary = array();
00868 foreach ($this->_metadata as $col) {
00869 if ($col['PRIMARY']) {
00870 $this->_primary[ $col['PRIMARY_POSITION'] ] = $col['COLUMN_NAME'];
00871 if ($col['IDENTITY']) {
00872 $this->_identity = $col['PRIMARY_POSITION'];
00873 }
00874 }
00875 }
00876
00877
00878 if (empty($this->_primary)) {
00879 require_once 'Zend/Db/Table/Exception.php';
00880 throw new Zend_Db_Table_Exception('A table must have a primary key, but none was found');
00881 }
00882 } else if (!is_array($this->_primary)) {
00883 $this->_primary = array(1 => $this->_primary);
00884 } else if (isset($this->_primary[0])) {
00885 array_unshift($this->_primary, null);
00886 unset($this->_primary[0]);
00887 }
00888
00889 $cols = $this->_getCols();
00890 if (! array_intersect((array) $this->_primary, $cols) == (array) $this->_primary) {
00891 require_once 'Zend/Db/Table/Exception.php';
00892 throw new Zend_Db_Table_Exception("Primary key column(s) ("
00893 . implode(',', (array) $this->_primary)
00894 . ") are not columns in this table ("
00895 . implode(',', $cols)
00896 . ")");
00897 }
00898
00899 $primary = (array) $this->_primary;
00900 $pkIdentity = $primary[(int) $this->_identity];
00901
00906 if ($this->_sequence === true && $this->_db instanceof Zend_Db_Adapter_Pdo_Pgsql) {
00907 $this->_sequence = $this->_db->quoteIdentifier("{$this->_name}_{$pkIdentity}_seq");
00908 if ($this->_schema) {
00909 $this->_sequence = $this->_db->quoteIdentifier($this->_schema) . '.' . $this->_sequence;
00910 }
00911 }
00912 }
00913
00919 protected function _getReferenceMapNormalized()
00920 {
00921 $referenceMapNormalized = array();
00922
00923 foreach ($this->_referenceMap as $rule => $map) {
00924
00925 $referenceMapNormalized[$rule] = array();
00926
00927 foreach ($map as $key => $value) {
00928 switch ($key) {
00929
00930
00931 case self::COLUMNS:
00932 case self::REF_COLUMNS:
00933 if (!is_array($value)) {
00934 $referenceMapNormalized[$rule][$key] = array($value);
00935 } else {
00936 $referenceMapNormalized[$rule][$key] = $value;
00937 }
00938 break;
00939
00940
00941 default:
00942 $referenceMapNormalized[$rule][$key] = $value;
00943 break;
00944 }
00945 }
00946 }
00947
00948 return $referenceMapNormalized;
00949 }
00950
00958 public function init()
00959 {
00960 }
00961
00971 public function info($key = null)
00972 {
00973 $this->_setupPrimaryKey();
00974
00975 $info = array(
00976 self::SCHEMA => $this->_schema,
00977 self::NAME => $this->_name,
00978 self::COLS => $this->_getCols(),
00979 self::PRIMARY => (array) $this->_primary,
00980 self::METADATA => $this->_metadata,
00981 self::ROW_CLASS => $this->getRowClass(),
00982 self::ROWSET_CLASS => $this->getRowsetClass(),
00983 self::REFERENCE_MAP => $this->_referenceMap,
00984 self::DEPENDENT_TABLES => $this->_dependentTables,
00985 self::SEQUENCE => $this->_sequence
00986 );
00987
00988 if ($key === null) {
00989 return $info;
00990 }
00991
00992 if (!array_key_exists($key, $info)) {
00993 require_once 'Zend/Db/Table/Exception.php';
00994 throw new Zend_Db_Table_Exception('There is no table information for the key "' . $key . '"');
00995 }
00996
00997 return $info[$key];
00998 }
00999
01006 public function select($withFromPart = self::SELECT_WITHOUT_FROM_PART)
01007 {
01008 require_once 'Zend/Db/Table/Select.php';
01009 $select = new Zend_Db_Table_Select($this);
01010 if ($withFromPart == self::SELECT_WITH_FROM_PART) {
01011 $select->from($this->info(self::NAME), Zend_Db_Table_Select::SQL_WILDCARD, $this->info(self::SCHEMA));
01012 }
01013 return $select;
01014 }
01015
01022 public function insert(array $data)
01023 {
01024 $this->_setupPrimaryKey();
01025
01031 $primary = (array) $this->_primary;
01032 $pkIdentity = $primary[(int)$this->_identity];
01033
01040 if (is_string($this->_sequence) && !isset($data[$pkIdentity])) {
01041 $data[$pkIdentity] = $this->_db->nextSequenceId($this->_sequence);
01042 }
01043
01048 if (array_key_exists($pkIdentity, $data) && $data[$pkIdentity] === null) {
01049 unset($data[$pkIdentity]);
01050 }
01051
01055 $tableSpec = ($this->_schema ? $this->_schema . '.' : '') . $this->_name;
01056 $this->_db->insert($tableSpec, $data);
01057
01063 if ($this->_sequence === true && !isset($data[$pkIdentity])) {
01064 $data[$pkIdentity] = $this->_db->lastInsertId();
01065 }
01066
01071 $pkData = array_intersect_key($data, array_flip($primary));
01072 if (count($primary) == 1) {
01073 reset($pkData);
01074 return current($pkData);
01075 }
01076
01077 return $pkData;
01078 }
01079
01087 public function isIdentity($column)
01088 {
01089 $this->_setupPrimaryKey();
01090
01091 if (!isset($this->_metadata[$column])) {
01095 require_once 'Zend/Db/Table/Exception.php';
01096
01097 throw new Zend_Db_Table_Exception('Column "' . $column . '" not found in table.');
01098 }
01099
01100 return (bool) $this->_metadata[$column]['IDENTITY'];
01101 }
01102
01110 public function update(array $data, $where)
01111 {
01112 $tableSpec = ($this->_schema ? $this->_schema . '.' : '') . $this->_name;
01113 return $this->_db->update($tableSpec, $data, $where);
01114 }
01115
01124 public function _cascadeUpdate($parentTableClassname, array $oldPrimaryKey, array $newPrimaryKey)
01125 {
01126 $this->_setupMetadata();
01127 $rowsAffected = 0;
01128 foreach ($this->_getReferenceMapNormalized() as $map) {
01129 if ($map[self::REF_TABLE_CLASS] == $parentTableClassname && isset($map[self::ON_UPDATE])) {
01130 switch ($map[self::ON_UPDATE]) {
01131 case self::CASCADE:
01132 $newRefs = array();
01133 $where = array();
01134 for ($i = 0; $i < count($map[self::COLUMNS]); ++$i) {
01135 $col = $this->_db->foldCase($map[self::COLUMNS][$i]);
01136 $refCol = $this->_db->foldCase($map[self::REF_COLUMNS][$i]);
01137 if (array_key_exists($refCol, $newPrimaryKey)) {
01138 $newRefs[$col] = $newPrimaryKey[$refCol];
01139 }
01140 $type = $this->_metadata[$col]['DATA_TYPE'];
01141 $where[] = $this->_db->quoteInto(
01142 $this->_db->quoteIdentifier($col, true) . ' = ?',
01143 $oldPrimaryKey[$refCol], $type);
01144 }
01145 $rowsAffected += $this->update($newRefs, $where);
01146 break;
01147 default:
01148
01149 break;
01150 }
01151 }
01152 }
01153 return $rowsAffected;
01154 }
01155
01162 public function delete($where)
01163 {
01164 $tableSpec = ($this->_schema ? $this->_schema . '.' : '') . $this->_name;
01165 return $this->_db->delete($tableSpec, $where);
01166 }
01167
01175 public function _cascadeDelete($parentTableClassname, array $primaryKey)
01176 {
01177 $this->_setupMetadata();
01178 $rowsAffected = 0;
01179 foreach ($this->_getReferenceMapNormalized() as $map) {
01180 if ($map[self::REF_TABLE_CLASS] == $parentTableClassname && isset($map[self::ON_DELETE])) {
01181 switch ($map[self::ON_DELETE]) {
01182 case self::CASCADE:
01183 $where = array();
01184 for ($i = 0; $i < count($map[self::COLUMNS]); ++$i) {
01185 $col = $this->_db->foldCase($map[self::COLUMNS][$i]);
01186 $refCol = $this->_db->foldCase($map[self::REF_COLUMNS][$i]);
01187 $type = $this->_metadata[$col]['DATA_TYPE'];
01188 $where[] = $this->_db->quoteInto(
01189 $this->_db->quoteIdentifier($col, true) . ' = ?',
01190 $primaryKey[$refCol], $type);
01191 }
01192 $rowsAffected += $this->delete($where);
01193 break;
01194 default:
01195
01196 break;
01197 }
01198 }
01199 }
01200 return $rowsAffected;
01201 }
01202
01221 public function find()
01222 {
01223 $this->_setupPrimaryKey();
01224 $args = func_get_args();
01225 $keyNames = array_values((array) $this->_primary);
01226
01227 if (count($args) < count($keyNames)) {
01228 require_once 'Zend/Db/Table/Exception.php';
01229 throw new Zend_Db_Table_Exception("Too few columns for the primary key");
01230 }
01231
01232 if (count($args) > count($keyNames)) {
01233 require_once 'Zend/Db/Table/Exception.php';
01234 throw new Zend_Db_Table_Exception("Too many columns for the primary key");
01235 }
01236
01237 $whereList = array();
01238 $numberTerms = 0;
01239 foreach ($args as $keyPosition => $keyValues) {
01240 $keyValuesCount = count($keyValues);
01241
01242
01243
01244 if (!is_array($keyValues)) {
01245 $keyValues = array($keyValues);
01246 }
01247 if ($numberTerms == 0) {
01248 $numberTerms = $keyValuesCount;
01249 } else if ($keyValuesCount != $numberTerms) {
01250 require_once 'Zend/Db/Table/Exception.php';
01251 throw new Zend_Db_Table_Exception("Missing value(s) for the primary key");
01252 }
01253 $keyValues = array_values($keyValues);
01254 for ($i = 0; $i < $keyValuesCount; ++$i) {
01255 if (!isset($whereList[$i])) {
01256 $whereList[$i] = array();
01257 }
01258 $whereList[$i][$keyPosition] = $keyValues[$i];
01259 }
01260 }
01261
01262 $whereClause = null;
01263 if (count($whereList)) {
01264 $whereOrTerms = array();
01265 $tableName = $this->_db->quoteTableAs($this->_name, null, true);
01266 foreach ($whereList as $keyValueSets) {
01267 $whereAndTerms = array();
01268 foreach ($keyValueSets as $keyPosition => $keyValue) {
01269 $type = $this->_metadata[$keyNames[$keyPosition]]['DATA_TYPE'];
01270 $columnName = $this->_db->quoteIdentifier($keyNames[$keyPosition], true);
01271 $whereAndTerms[] = $this->_db->quoteInto(
01272 $tableName . '.' . $columnName . ' = ?',
01273 $keyValue, $type);
01274 }
01275 $whereOrTerms[] = '(' . implode(' AND ', $whereAndTerms) . ')';
01276 }
01277 $whereClause = '(' . implode(' OR ', $whereOrTerms) . ')';
01278 }
01279
01280
01281 if ($whereClause == null) {
01282 $rowsetClass = $this->getRowsetClass();
01283 if (!class_exists($rowsetClass)) {
01284 require_once 'Zend/Loader.php';
01285 Zend_Loader::loadClass($rowsetClass);
01286 }
01287 return new $rowsetClass(array('table' => $this, 'rowClass' => $this->getRowClass(), 'stored' => true));
01288 }
01289
01290 return $this->fetchAll($whereClause);
01291 }
01292
01304 public function fetchAll($where = null, $order = null, $count = null, $offset = null)
01305 {
01306 if (!($where instanceof Zend_Db_Table_Select)) {
01307 $select = $this->select();
01308
01309 if ($where !== null) {
01310 $this->_where($select, $where);
01311 }
01312
01313 if ($order !== null) {
01314 $this->_order($select, $order);
01315 }
01316
01317 if ($count !== null || $offset !== null) {
01318 $select->limit($count, $offset);
01319 }
01320
01321 } else {
01322 $select = $where;
01323 }
01324
01325 $rows = $this->_fetch($select);
01326
01327 $data = array(
01328 'table' => $this,
01329 'data' => $rows,
01330 'readOnly' => $select->isReadOnly(),
01331 'rowClass' => $this->getRowClass(),
01332 'stored' => true
01333 );
01334
01335 $rowsetClass = $this->getRowsetClass();
01336 if (!class_exists($rowsetClass)) {
01337 require_once 'Zend/Loader.php';
01338 Zend_Loader::loadClass($rowsetClass);
01339 }
01340 return new $rowsetClass($data);
01341 }
01342
01352 public function fetchRow($where = null, $order = null)
01353 {
01354 if (!($where instanceof Zend_Db_Table_Select)) {
01355 $select = $this->select();
01356
01357 if ($where !== null) {
01358 $this->_where($select, $where);
01359 }
01360
01361 if ($order !== null) {
01362 $this->_order($select, $order);
01363 }
01364
01365 $select->limit(1);
01366
01367 } else {
01368 $select = $where->limit(1);
01369 }
01370
01371 $rows = $this->_fetch($select);
01372
01373 if (count($rows) == 0) {
01374 return null;
01375 }
01376
01377 $data = array(
01378 'table' => $this,
01379 'data' => $rows[0],
01380 'readOnly' => $select->isReadOnly(),
01381 'stored' => true
01382 );
01383
01384 $rowClass = $this->getRowClass();
01385 if (!class_exists($rowClass)) {
01386 require_once 'Zend/Loader.php';
01387 Zend_Loader::loadClass($rowClass);
01388 }
01389 return new $rowClass($data);
01390 }
01391
01398 public function fetchNew()
01399 {
01400 return $this->createRow();
01401 }
01402
01410 public function createRow(array $data = array(), $defaultSource = null)
01411 {
01412 $cols = $this->_getCols();
01413 $defaults = array_combine($cols, array_fill(0, count($cols), null));
01414
01415
01416 if ($defaultSource == null) {
01417 $defaultSource = $this->_defaultSource;
01418 }
01419
01420 if (!in_array($defaultSource, array(self::DEFAULT_CLASS, self::DEFAULT_DB, self::DEFAULT_NONE))) {
01421 $defaultSource = self::DEFAULT_NONE;
01422 }
01423
01424 if ($defaultSource == self::DEFAULT_DB) {
01425 foreach ($this->_metadata as $metadataName => $metadata) {
01426 if (($metadata['DEFAULT'] != null) &&
01427 ($metadata['NULLABLE'] !== true || ($metadata['NULLABLE'] === true && isset($this->_defaultValues[$metadataName]) && $this->_defaultValues[$metadataName] === true)) &&
01428 (!(isset($this->_defaultValues[$metadataName]) && $this->_defaultValues[$metadataName] === false))) {
01429 $defaults[$metadataName] = $metadata['DEFAULT'];
01430 }
01431 }
01432 } elseif ($defaultSource == self::DEFAULT_CLASS && $this->_defaultValues) {
01433 foreach ($this->_defaultValues as $defaultName => $defaultValue) {
01434 if (array_key_exists($defaultName, $defaults)) {
01435 $defaults[$defaultName] = $defaultValue;
01436 }
01437 }
01438 }
01439
01440 $config = array(
01441 'table' => $this,
01442 'data' => $defaults,
01443 'readOnly' => false,
01444 'stored' => false
01445 );
01446
01447 $rowClass = $this->getRowClass();
01448 if (!class_exists($rowClass)) {
01449 require_once 'Zend/Loader.php';
01450 Zend_Loader::loadClass($rowClass);
01451 }
01452 $row = new $rowClass($config);
01453 $row->setFromArray($data);
01454 return $row;
01455 }
01456
01463 protected function _where(Zend_Db_Table_Select $select, $where)
01464 {
01465 $where = (array) $where;
01466
01467 foreach ($where as $key => $val) {
01468
01469 if (is_int($key)) {
01470
01471 $select->where($val);
01472 } else {
01473
01474
01475 $select->where($key, $val);
01476 }
01477 }
01478
01479 return $select;
01480 }
01481
01488 protected function _order(Zend_Db_Table_Select $select, $order)
01489 {
01490 if (!is_array($order)) {
01491 $order = array($order);
01492 }
01493
01494 foreach ($order as $val) {
01495 $select->order($val);
01496 }
01497
01498 return $select;
01499 }
01500
01507 protected function _fetch(Zend_Db_Table_Select $select)
01508 {
01509 $stmt = $this->_db->query($select);
01510 $data = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
01511 return $data;
01512 }
01513
01514 }