datasource.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: datasource_8php-source.html 675 2008-12-26 00:27:14Z gwoo $ */
00003 /**
00004  * DataSource base class
00005  *
00006  * Long description for file
00007  *
00008  * PHP versions 4 and 5
00009  *
00010  * CakePHP(tm) :  Rapid Development Framework <http://www.cakephp.org/>
00011  * Copyright 2005-2008, Cake Software Foundation, Inc.
00012  *                              1785 E. Sahara Avenue, Suite 490-204
00013  *                              Las Vegas, Nevada 89104
00014  *
00015  * Licensed under The MIT License
00016  * Redistributions of files must retain the above copyright notice.
00017  *
00018  * @filesource
00019  * @copyright       Copyright 2005-2008, Cake Software Foundation, Inc.
00020  * @link                http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00021  * @package         cake
00022  * @subpackage      cake.cake.libs.model.datasources
00023  * @since           CakePHP(tm) v 0.10.5.1790
00024  * @version         $Revision: 675 $
00025  * @modifiedby      $LastChangedBy: gwoo $
00026  * @lastmodified    $Date: 2008-12-25 16:27:14 -0800 (Thu, 25 Dec 2008) $
00027  * @license         http://www.opensource.org/licenses/mit-license.php The MIT License
00028  */
00029 /**
00030  * DataSource base class
00031  *
00032  * Long description for file
00033  *
00034  * @package     cake
00035  * @subpackage  cake.cake.libs.model.datasources
00036  */
00037 class DataSource extends Object {
00038 /**
00039  * Are we connected to the DataSource?
00040  *
00041  * @var boolean
00042  * @access public
00043  */
00044     var $connected = false;
00045 /**
00046  * Print debug info?
00047  *
00048  * @var boolean
00049  * @access public
00050  */
00051     var $debug = false;
00052 /**
00053  * Print full query debug info?
00054  *
00055  * @var boolean
00056  * @access public
00057  */
00058     var $fullDebug = false;
00059 /**
00060  * Error description of last query
00061  *
00062  * @var unknown_type
00063  * @access public
00064  */
00065     var $error = null;
00066 /**
00067  * String to hold how many rows were affected by the last SQL operation.
00068  *
00069  * @var string
00070  * @access public
00071  */
00072     var $affected = null;
00073 /**
00074  * Number of rows in current resultset
00075  *
00076  * @var int
00077  * @access public
00078  */
00079     var $numRows = null;
00080 /**
00081  * Time the last query took
00082  *
00083  * @var int
00084  * @access public
00085  */
00086     var $took = null;
00087 /**
00088  * Enter description here...
00089  *
00090  * @var array
00091  * @access private
00092  */
00093     var $_result = null;
00094 /**
00095  * Queries count.
00096  *
00097  * @var int
00098  * @access private
00099  */
00100     var $_queriesCnt = 0;
00101 /**
00102  * Total duration of all queries.
00103  *
00104  * @var unknown_type
00105  * @access private
00106  */
00107     var $_queriesTime = null;
00108 /**
00109  * Log of queries executed by this DataSource
00110  *
00111  * @var unknown_type
00112  * @access private
00113  */
00114     var $_queriesLog = array();
00115 /**
00116  * Maximum number of items in query log, to prevent query log taking over
00117  * too much memory on large amounts of queries -- I we've had problems at
00118  * >6000 queries on one system.
00119  *
00120  * @var int Maximum number of queries in the queries log.
00121  * @access private
00122  */
00123     var $_queriesLogMax = 200;
00124 /**
00125  * Caches serialzed results of executed queries
00126  *
00127  * @var array Maximum number of queries in the queries log.
00128  * @access private
00129  */
00130     var $_queryCache = array();
00131 /**
00132  * The default configuration of a specific DataSource
00133  *
00134  * @var array
00135  * @access public
00136  */
00137     var $_baseConfig = array();
00138 /**
00139  * Holds references to descriptions loaded by the DataSource
00140  *
00141  * @var array
00142  * @access private
00143  */
00144     var $__descriptions = array();
00145 /**
00146  * Holds a list of sources (tables) contained in the DataSource
00147  *
00148  * @var array
00149  * @access protected
00150  */
00151     var $_sources = null;
00152 /**
00153  * A reference to the physical connection of this DataSource
00154  *
00155  * @var array
00156  * @access public
00157  */
00158     var $connection = null;
00159 /**
00160  * The DataSource configuration
00161  *
00162  * @var array
00163  * @access public
00164  */
00165     var $config = array();
00166 /**
00167  * The DataSource configuration key name
00168  *
00169  * @var string
00170  * @access public
00171  */
00172     var $configKeyName = null;
00173 /**
00174  * Whether or not this DataSource is in the middle of a transaction
00175  *
00176  * @var boolean
00177  * @access protected
00178  */
00179     var $_transactionStarted = false;
00180 /**
00181  * Enter description here...
00182  *
00183  * @var boolean
00184  */
00185        var $cacheSources = true;
00186 /**
00187  * Constructor.
00188  */
00189     function __construct() {
00190         parent::__construct();
00191         if (func_num_args() > 0) {
00192             $this->setConfig(func_get_arg(0));
00193         }
00194     }
00195 /**
00196  * Caches/returns cached results for child instances
00197  *
00198  * @return array
00199  */
00200     function listSources($data = null) {
00201         if ($this->cacheSources === false) {
00202             return null;
00203         }
00204         if ($this->_sources != null) {
00205             return $this->_sources;
00206         }
00207 
00208         if (Configure::read() > 0) {
00209             $expires = "+30 seconds";
00210         } else {
00211             $expires = "+999 days";
00212         }
00213 
00214         if ($data != null) {
00215             $data = serialize($data);
00216         }
00217         $filename = ConnectionManager::getSourceName($this) . '_' . preg_replace("/[^A-Za-z0-9_-]/", "_", $this->config['database']) . '_list';
00218         $new = cache('models' . DS . $filename, $data, $expires);
00219 
00220         if ($new != null) {
00221             $new = unserialize($new);
00222             $this->_sources = $new;
00223         }
00224         return $new;
00225     }
00226 /**
00227  * Convenience method for DboSource::listSources().  Returns source names in lowercase.
00228  *
00229  * @return array
00230  */
00231     function sources() {
00232         $return = array_map('strtolower', $this->listSources());
00233         return $return;
00234     }
00235 /**
00236  * Returns a Model description (metadata) or null if none found.
00237  *
00238  * @param Model $model
00239  * @return mixed
00240  */
00241     function describe($model) {
00242         if ($this->cacheSources === false) {
00243             return null;
00244         }
00245         if (isset($this->__descriptions[$model->tablePrefix . $model->table])) {
00246             return $this->__descriptions[$model->tablePrefix . $model->table];
00247         }
00248         $cache = $this->__cacheDescription($model->tablePrefix . $model->table);
00249 
00250         if ($cache !== null) {
00251             $this->__descriptions[$model->tablePrefix . $model->table] =& $cache;
00252             return $cache;
00253         }
00254         return null;
00255     }
00256 /**
00257  * Begin a transaction to be overridden in subclasses
00258  *
00259  * @param unknown_type $model
00260  * @return boolean True
00261  */
00262     function begin(&$model) {
00263         return true;
00264     }
00265 /**
00266  * Commit a transaction to be overridden in subclasses
00267  *
00268  * @param unknown_type $model
00269  * @return boolean True
00270  */
00271     function commit(&$model) {
00272         return true;
00273     }
00274 /**
00275  * Rollback a transaction to be overridden in subclasses
00276  *
00277  * @param unknown_type $model
00278  * @return boolean True
00279  */
00280     function rollback(&$model) {
00281         return true;
00282     }
00283 /**
00284  * Converts column types to basic types
00285  *
00286  * @param string $real Real  column type (i.e. "varchar(255)")
00287  * @return string Abstract column type (i.e. "string")
00288  */
00289     function column($real) {
00290         return false;
00291     }
00292 /**
00293  * To-be-overridden in subclasses.
00294  *
00295  * @param unknown_type $model
00296  * @param unknown_type $fields
00297  * @param unknown_type $values
00298  * @return unknown
00299  */
00300     function create(&$model, $fields = null, $values = null) {
00301         return false;
00302     }
00303 /**
00304  * To-be-overridden in subclasses.
00305  *
00306  * @param unknown_type $model
00307  * @param unknown_type $queryData
00308  * @return unknown
00309  */
00310     function read(&$model, $queryData = array()) {
00311         return false;
00312     }
00313 /**
00314  * To-be-overridden in subclasses.
00315  *
00316  * @param unknown_type $model
00317  * @param unknown_type $fields
00318  * @param unknown_type $values
00319  * @return unknown
00320  */
00321     function update(&$model, $fields = null, $values = null) {
00322         return false;
00323     }
00324 /**
00325  * To-be-overridden in subclasses.
00326  *
00327  * @param unknown_type $model
00328  * @param unknown_type $id
00329  */
00330     function delete(&$model, $id = null) {
00331         if ($id == null) {
00332             $id = $model->id;
00333         }
00334     }
00335 /**
00336  * Returns the ID generated from the previous INSERT operation.
00337  *
00338  * @param unknown_type $source
00339  * @return in
00340  */
00341     function lastInsertId($source = null) {
00342         return false;
00343     }
00344 /**
00345  * Returns the ID generated from the previous INSERT operation.
00346  *
00347  * @param unknown_type $source
00348  * @return in
00349  */
00350     function lastNumRows($source = null) {
00351         return false;
00352     }
00353 /**
00354  * Returns the ID generated from the previous INSERT operation.
00355  *
00356  * @param unknown_type $source
00357  * @return in
00358  */
00359     function lastAffected($source = null) {
00360         return false;
00361     }
00362 /**
00363  * Returns true if the DataSource supports the given interface (method)
00364  *
00365  * @param string $interface The name of the interface (method)
00366  * @return boolean True on success
00367  */
00368     function isInterfaceSupported($interface) {
00369         $methods = get_class_methods(get_class($this));
00370         $methods = strtolower(implode('|', $methods));
00371         $methods = explode('|', $methods);
00372         $return = in_array(strtolower($interface), $methods);
00373         return $return;
00374     }
00375 /**
00376  * Sets the configuration for the DataSource
00377  *
00378  * @param array $config The configuration array
00379  * @return void
00380  */
00381     function setConfig($config) {
00382         if (is_array($this->_baseConfig)) {
00383             $this->config = $this->_baseConfig;
00384             foreach ($config as $key => $val) {
00385                 $this->config[$key] = $val;
00386             }
00387         }
00388     }
00389 /**
00390  * Cache the DataSource description
00391  *
00392  * @param string $object The name of the object (model) to cache
00393  * @param mixed $data The description of the model, usually a string or array
00394  * @return void
00395  */
00396     function __cacheDescription($object, $data = null) {
00397         if ($this->cacheSources === false) {
00398             return null;
00399         }
00400         if (Configure::read() > 0) {
00401             $expires = "+15 seconds";
00402         } else {
00403             $expires = "+999 days";
00404         }
00405 
00406         if ($data !== null) {
00407             $this->__descriptions[$object] =& $data;
00408             $cache = serialize($data);
00409         } else {
00410             $cache = null;
00411         }
00412         $new = cache('models' . DS . ConnectionManager::getSourceName($this) . '_' . $object, $cache, $expires);
00413 
00414         if ($new != null) {
00415             $new = unserialize($new);
00416         }
00417         return $new;
00418     }
00419 /**
00420  * Enter description here...
00421  *
00422  * @param unknown_type $query
00423  * @param unknown_type $data
00424  * @param unknown_type $association
00425  * @param unknown_type $assocData
00426  * @param Model $model
00427  * @param Model $linkModel
00428  * @param array $stack
00429  * @return unknown
00430  */
00431     function insertQueryData($query, $data, $association, $assocData, &$model, &$linkModel, $stack) {
00432         $keys = array('{$__cakeID__$}', '{$__cakeForeignKey__$}');
00433 
00434         foreach ($keys as $key) {
00435             $val = null;
00436 
00437             if (strpos($query, $key) !== false) {
00438                 switch($key) {
00439                     case '{$__cakeID__$}':
00440                         if (isset($data[$model->name]) || isset($data[$association])) {
00441                             if (isset($data[$model->name][$model->primaryKey])) {
00442                                 $val = $data[$model->name][$model->primaryKey];
00443                             } elseif (isset($data[$association][$model->primaryKey])) {
00444                                 $val = $data[$association][$model->primaryKey];
00445                             }
00446                         } else {
00447                             $found = false;
00448                             foreach (array_reverse($stack) as $assoc) {
00449                                 if (isset($data[$assoc]) && isset($data[$assoc][$model->primaryKey])) {
00450                                     $val = $data[$assoc][$model->primaryKey];
00451                                     $found = true;
00452                                     break;
00453                                 }
00454                             }
00455                             if (!$found) {
00456                                 $val = '';
00457                             }
00458                         }
00459                     break;
00460                     case '{$__cakeForeignKey__$}':
00461                         foreach ($model->__associations as $id => $name) {
00462                             foreach ($model->$name as $assocName => $assoc) {
00463                                 if ($assocName === $association) {
00464                                     if (isset($assoc['foreignKey'])) {
00465                                         $foreignKey = $assoc['foreignKey'];
00466 
00467                                         if (isset($data[$model->name][$foreignKey])) {
00468                                             $val = $data[$model->name][$foreignKey];
00469                                         } elseif (isset($data[$association][$foreignKey])) {
00470                                             $val = $data[$association][$foreignKey];
00471                                         } else {
00472                                             $found = false;
00473                                             foreach (array_reverse($stack) as $assoc) {
00474                                                 if (isset($data[$assoc]) && isset($data[$assoc][$foreignKey])) {
00475                                                     $val = $data[$assoc][$foreignKey];
00476                                                     $found = true;
00477                                                     break;
00478                                                 }
00479                                             }
00480                                             if (!$found) {
00481                                                 $val = '';
00482                                             }
00483                                         }
00484                                     }
00485                                     break 3;
00486                                 }
00487                             }
00488                         }
00489                     break;
00490                 }
00491                 if (empty($val) && $val !== '0') {
00492                     return false;
00493                 }
00494                 $query = r($key, $this->value($val, $model->getColumnType($model->primaryKey)), $query);
00495             }
00496         }
00497         return $query;
00498     }
00499 /**
00500  * To-be-overridden in subclasses.
00501  *
00502  * @param unknown_type $model
00503  * @param unknown_type $key
00504  * @return unknown
00505  */
00506     function resolveKey($model, $key) {
00507         return $model->name . $key;
00508     }
00509 /**
00510  * Closes the current datasource.
00511  *
00512  */
00513     function __destruct() {
00514         if ($this->connected) {
00515             $this->close();
00516         }
00517     }
00518 }
00519 ?>