Mercurial > hg > Members > shoshi > webvirt
diff cake/libs/model/datasources/datasource.php @ 0:261e66bd5a0c
hg init
author | Shoshi TAMAKI <shoshi@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 24 Jul 2011 21:08:31 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cake/libs/model/datasources/datasource.php Sun Jul 24 21:08:31 2011 +0900 @@ -0,0 +1,601 @@ +<?php +/** + * DataSource base class + * + * PHP versions 4 and 5 + * + * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) + * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://cakephp.org CakePHP(tm) Project + * @package cake + * @subpackage cake.cake.libs.model.datasources + * @since CakePHP(tm) v 0.10.5.1790 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +/** + * DataSource base class + * + * @package cake + * @subpackage cake.cake.libs.model.datasources + */ +class DataSource extends Object { + +/** + * Are we connected to the DataSource? + * + * @var boolean + * @access public + */ + var $connected = false; + +/** + * Print full query debug info? + * + * @var boolean + * @access public + */ + var $fullDebug = false; + +/** + * Error description of last query + * + * @var unknown_type + * @access public + */ + var $error = null; + +/** + * String to hold how many rows were affected by the last SQL operation. + * + * @var string + * @access public + */ + var $affected = null; + +/** + * Number of rows in current resultset + * + * @var int + * @access public + */ + var $numRows = null; + +/** + * Time the last query took + * + * @var int + * @access public + */ + var $took = null; + +/** + * The starting character that this DataSource uses for quoted identifiers. + * + * @var string + * @access public + */ + var $startQuote = null; + +/** + * The ending character that this DataSource uses for quoted identifiers. + * + * @var string + * @access public + */ + var $endQuote = null; + +/** + * Result + * + * @var array + * @access protected + */ + var $_result = null; + +/** + * Queries count. + * + * @var int + * @access protected + */ + var $_queriesCnt = 0; + +/** + * Total duration of all queries. + * + * @var unknown_type + * @access protected + */ + var $_queriesTime = null; + +/** + * Log of queries executed by this DataSource + * + * @var unknown_type + * @access protected + */ + var $_queriesLog = array(); + +/** + * Maximum number of items in query log + * + * This is to prevent query log taking over too much memory. + * + * @var int Maximum number of queries in the queries log. + * @access protected + */ + var $_queriesLogMax = 200; + +/** + * Caches serialzed results of executed queries + * + * @var array Maximum number of queries in the queries log. + * @access protected + */ + var $_queryCache = array(); + +/** + * The default configuration of a specific DataSource + * + * @var array + * @access protected + */ + var $_baseConfig = array(); + +/** + * Holds references to descriptions loaded by the DataSource + * + * @var array + * @access private + */ + var $__descriptions = array(); + +/** + * Holds a list of sources (tables) contained in the DataSource + * + * @var array + * @access protected + */ + var $_sources = null; + +/** + * A reference to the physical connection of this DataSource + * + * @var array + * @access public + */ + var $connection = null; + +/** + * The DataSource configuration + * + * @var array + * @access public + */ + var $config = array(); + +/** + * The DataSource configuration key name + * + * @var string + * @access public + */ + var $configKeyName = null; + +/** + * Whether or not this DataSource is in the middle of a transaction + * + * @var boolean + * @access protected + */ + var $_transactionStarted = false; + +/** + * Whether or not source data like available tables and schema descriptions + * should be cached + * + * @var boolean + * @access public + */ + var $cacheSources = true; + +/** + * Constructor. + * + * @param array $config Array of configuration information for the datasource. + * @return void. + */ + function __construct($config = array()) { + parent::__construct(); + $this->setConfig($config); + } + +/** + * Caches/returns cached results for child instances + * + * @param mixed $data + * @return array Array of sources available in this datasource. + * @access public + */ + function listSources($data = null) { + if ($this->cacheSources === false) { + return null; + } + + if ($this->_sources !== null) { + return $this->_sources; + } + + $key = ConnectionManager::getSourceName($this) . '_' . $this->config['database'] . '_list'; + $key = preg_replace('/[^A-Za-z0-9_\-.+]/', '_', $key); + $sources = Cache::read($key, '_cake_model_'); + + if (empty($sources)) { + $sources = $data; + Cache::write($key, $data, '_cake_model_'); + } + + $this->_sources = $sources; + return $sources; + } + +/** + * Convenience method for DboSource::listSources(). Returns source names in lowercase. + * + * @param boolean $reset Whether or not the source list should be reset. + * @return array Array of sources available in this datasource + * @access public + */ + function sources($reset = false) { + if ($reset === true) { + $this->_sources = null; + } + return array_map('strtolower', $this->listSources()); + } + +/** + * Returns a Model description (metadata) or null if none found. + * + * @param Model $model + * @return array Array of Metadata for the $model + * @access public + */ + function describe(&$model) { + if ($this->cacheSources === false) { + return null; + } + $table = $model->tablePrefix . $model->table; + + if (isset($this->__descriptions[$table])) { + return $this->__descriptions[$table]; + } + $cache = $this->__cacheDescription($table); + + if ($cache !== null) { + $this->__descriptions[$table] =& $cache; + return $cache; + } + return null; + } + +/** + * Begin a transaction + * + * @return boolean Returns true if a transaction is not in progress + * @access public + */ + function begin(&$model) { + return !$this->_transactionStarted; + } + +/** + * Commit a transaction + * + * @return boolean Returns true if a transaction is in progress + * @access public + */ + function commit(&$model) { + return $this->_transactionStarted; + } + +/** + * Rollback a transaction + * + * @return boolean Returns true if a transaction is in progress + * @access public + */ + function rollback(&$model) { + return $this->_transactionStarted; + } + +/** + * Converts column types to basic types + * + * @param string $real Real column type (i.e. "varchar(255)") + * @return string Abstract column type (i.e. "string") + * @access public + */ + function column($real) { + return false; + } + +/** + * Used to create new records. The "C" CRUD. + * + * To-be-overridden in subclasses. + * + * @param Model $model The Model to be created. + * @param array $fields An Array of fields to be saved. + * @param array $values An Array of values to save. + * @return boolean success + * @access public + */ + function create(&$model, $fields = null, $values = null) { + return false; + } + +/** + * Used to read records from the Datasource. The "R" in CRUD + * + * To-be-overridden in subclasses. + * + * @param Model $model The model being read. + * @param array $queryData An array of query data used to find the data you want + * @return mixed + * @access public + */ + function read(&$model, $queryData = array()) { + return false; + } + +/** + * Update a record(s) in the datasource. + * + * To-be-overridden in subclasses. + * + * @param Model $model Instance of the model class being updated + * @param array $fields Array of fields to be updated + * @param array $values Array of values to be update $fields to. + * @return boolean Success + * @access public + */ + function update(&$model, $fields = null, $values = null) { + return false; + } + +/** + * Delete a record(s) in the datasource. + * + * To-be-overridden in subclasses. + * + * @param Model $model The model class having record(s) deleted + * @param mixed $id Primary key of the model + * @access public + */ + function delete(&$model, $id = null) { + if ($id == null) { + $id = $model->id; + } + } + +/** + * Returns the ID generated from the previous INSERT operation. + * + * @param unknown_type $source + * @return mixed Last ID key generated in previous INSERT + * @access public + */ + function lastInsertId($source = null) { + return false; + } + +/** + * Returns the number of rows returned by last operation. + * + * @param unknown_type $source + * @return integer Number of rows returned by last operation + * @access public + */ + function lastNumRows($source = null) { + return false; + } + +/** + * Returns the number of rows affected by last query. + * + * @param unknown_type $source + * @return integer Number of rows affected by last query. + * @access public + */ + function lastAffected($source = null) { + return false; + } + +/** + * Check whether the conditions for the Datasource being available + * are satisfied. Often used from connect() to check for support + * before establishing a connection. + * + * @return boolean Whether or not the Datasources conditions for use are met. + * @access public + */ + function enabled() { + return true; + } + +/** + * Returns true if the DataSource supports the given interface (method) + * + * @param string $interface The name of the interface (method) + * @return boolean True on success + * @access public + */ + function isInterfaceSupported($interface) { + static $methods = false; + if ($methods === false) { + $methods = array_map('strtolower', get_class_methods($this)); + } + return in_array(strtolower($interface), $methods); + } + +/** + * Sets the configuration for the DataSource. + * Merges the $config information with the _baseConfig and the existing $config property. + * + * @param array $config The configuration array + * @return void + * @access public + */ + function setConfig($config = array()) { + $this->config = array_merge($this->_baseConfig, $this->config, $config); + } + +/** + * Cache the DataSource description + * + * @param string $object The name of the object (model) to cache + * @param mixed $data The description of the model, usually a string or array + * @return mixed + * @access private + */ + function __cacheDescription($object, $data = null) { + if ($this->cacheSources === false) { + return null; + } + + if ($data !== null) { + $this->__descriptions[$object] =& $data; + } + + $key = ConnectionManager::getSourceName($this) . '_' . $object; + $cache = Cache::read($key, '_cake_model_'); + + if (empty($cache)) { + $cache = $data; + Cache::write($key, $cache, '_cake_model_'); + } + + return $cache; + } + +/** + * Replaces `{$__cakeID__$}` and `{$__cakeForeignKey__$}` placeholders in query data. + * + * @param string $query Query string needing replacements done. + * @param array $data Array of data with values that will be inserted in placeholders. + * @param string $association Name of association model being replaced + * @param unknown_type $assocData + * @param Model $model Instance of the model to replace $__cakeID__$ + * @param Model $linkModel Instance of model to replace $__cakeForeignKey__$ + * @param array $stack + * @return string String of query data with placeholders replaced. + * @access public + * @todo Remove and refactor $assocData, ensure uses of the method have the param removed too. + */ + function insertQueryData($query, $data, $association, $assocData, &$model, &$linkModel, $stack) { + $keys = array('{$__cakeID__$}', '{$__cakeForeignKey__$}'); + + foreach ($keys as $key) { + $val = null; + $type = null; + + if (strpos($query, $key) !== false) { + switch ($key) { + case '{$__cakeID__$}': + if (isset($data[$model->alias]) || isset($data[$association])) { + if (isset($data[$model->alias][$model->primaryKey])) { + $val = $data[$model->alias][$model->primaryKey]; + } elseif (isset($data[$association][$model->primaryKey])) { + $val = $data[$association][$model->primaryKey]; + } + } else { + $found = false; + foreach (array_reverse($stack) as $assoc) { + if (isset($data[$assoc]) && isset($data[$assoc][$model->primaryKey])) { + $val = $data[$assoc][$model->primaryKey]; + $found = true; + break; + } + } + if (!$found) { + $val = ''; + } + } + $type = $model->getColumnType($model->primaryKey); + break; + case '{$__cakeForeignKey__$}': + foreach ($model->__associations as $id => $name) { + foreach ($model->$name as $assocName => $assoc) { + if ($assocName === $association) { + if (isset($assoc['foreignKey'])) { + $foreignKey = $assoc['foreignKey']; + $assocModel = $model->$assocName; + $type = $assocModel->getColumnType($assocModel->primaryKey); + + if (isset($data[$model->alias][$foreignKey])) { + $val = $data[$model->alias][$foreignKey]; + } elseif (isset($data[$association][$foreignKey])) { + $val = $data[$association][$foreignKey]; + } else { + $found = false; + foreach (array_reverse($stack) as $assoc) { + if (isset($data[$assoc]) && isset($data[$assoc][$foreignKey])) { + $val = $data[$assoc][$foreignKey]; + $found = true; + break; + } + } + if (!$found) { + $val = ''; + } + } + } + break 3; + } + } + } + break; + } + if (empty($val) && $val !== '0') { + return false; + } + $query = str_replace($key, $this->value($val, $type), $query); + } + } + return $query; + } + +/** + * To-be-overridden in subclasses. + * + * @param Model $model Model instance + * @param string $key Key name to make + * @return string Key name for model. + * @access public + */ + function resolveKey(&$model, $key) { + return $model->alias . $key; + } + +/** + * Closes the current datasource. + * + * @return void + * @access public + */ + function __destruct() { + if ($this->_transactionStarted) { + $null = null; + $this->rollback($null); + } + if ($this->connected) { + $this->close(); + } + } +}