PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/cake/libs/model/datasources/datasource.php

https://github.com/hardsshah/bookmarks
PHP | 509 lines | 204 code | 12 blank | 293 comment | 32 complexity | 59e82e88deac0a987dc8f3e80aa7023d MD5 | raw file
  1. <?php
  2. /* SVN FILE: $Id$ */
  3. /**
  4. * DataSource base class
  5. *
  6. * Long description for file
  7. *
  8. * PHP versions 4 and 5
  9. *
  10. * CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
  11. * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
  12. *
  13. * Licensed under The MIT License
  14. * Redistributions of files must retain the above copyright notice.
  15. *
  16. * @filesource
  17. * @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
  18. * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
  19. * @package cake
  20. * @subpackage cake.cake.libs.model.datasources
  21. * @since CakePHP(tm) v 0.10.5.1790
  22. * @version $Revision$
  23. * @modifiedby $LastChangedBy$
  24. * @lastmodified $Date$
  25. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
  26. */
  27. /**
  28. * DataSource base class
  29. *
  30. * Long description for file
  31. *
  32. * @package cake
  33. * @subpackage cake.cake.libs.model.datasources
  34. */
  35. class DataSource extends Object {
  36. /**
  37. * Are we connected to the DataSource?
  38. *
  39. * @var boolean
  40. * @access public
  41. */
  42. var $connected = false;
  43. /**
  44. * Print full query debug info?
  45. *
  46. * @var boolean
  47. * @access public
  48. */
  49. var $fullDebug = false;
  50. /**
  51. * Error description of last query
  52. *
  53. * @var unknown_type
  54. * @access public
  55. */
  56. var $error = null;
  57. /**
  58. * String to hold how many rows were affected by the last SQL operation.
  59. *
  60. * @var string
  61. * @access public
  62. */
  63. var $affected = null;
  64. /**
  65. * Number of rows in current resultset
  66. *
  67. * @var int
  68. * @access public
  69. */
  70. var $numRows = null;
  71. /**
  72. * Time the last query took
  73. *
  74. * @var int
  75. * @access public
  76. */
  77. var $took = null;
  78. /**
  79. * The starting character that this DataSource uses for quoted identifiers.
  80. *
  81. * @var string
  82. */
  83. var $startQuote = null;
  84. /**
  85. * The ending character that this DataSource uses for quoted identifiers.
  86. *
  87. * @var string
  88. */
  89. var $endQuote = null;
  90. /**
  91. * Enter description here...
  92. *
  93. * @var array
  94. * @access private
  95. */
  96. var $_result = null;
  97. /**
  98. * Queries count.
  99. *
  100. * @var int
  101. * @access private
  102. */
  103. var $_queriesCnt = 0;
  104. /**
  105. * Total duration of all queries.
  106. *
  107. * @var unknown_type
  108. * @access private
  109. */
  110. var $_queriesTime = null;
  111. /**
  112. * Log of queries executed by this DataSource
  113. *
  114. * @var unknown_type
  115. * @access private
  116. */
  117. var $_queriesLog = array();
  118. /**
  119. * Maximum number of items in query log, to prevent query log taking over
  120. * too much memory on large amounts of queries -- I we've had problems at
  121. * >6000 queries on one system.
  122. *
  123. * @var int Maximum number of queries in the queries log.
  124. * @access private
  125. */
  126. var $_queriesLogMax = 200;
  127. /**
  128. * Caches serialzed results of executed queries
  129. *
  130. * @var array Maximum number of queries in the queries log.
  131. * @access private
  132. */
  133. var $_queryCache = array();
  134. /**
  135. * The default configuration of a specific DataSource
  136. *
  137. * @var array
  138. * @access public
  139. */
  140. var $_baseConfig = array();
  141. /**
  142. * Holds references to descriptions loaded by the DataSource
  143. *
  144. * @var array
  145. * @access private
  146. */
  147. var $__descriptions = array();
  148. /**
  149. * Holds a list of sources (tables) contained in the DataSource
  150. *
  151. * @var array
  152. * @access protected
  153. */
  154. var $_sources = null;
  155. /**
  156. * A reference to the physical connection of this DataSource
  157. *
  158. * @var array
  159. * @access public
  160. */
  161. var $connection = null;
  162. /**
  163. * The DataSource configuration
  164. *
  165. * @var array
  166. * @access public
  167. */
  168. var $config = array();
  169. /**
  170. * The DataSource configuration key name
  171. *
  172. * @var string
  173. * @access public
  174. */
  175. var $configKeyName = null;
  176. /**
  177. * Whether or not this DataSource is in the middle of a transaction
  178. *
  179. * @var boolean
  180. * @access protected
  181. */
  182. var $_transactionStarted = false;
  183. /**
  184. * Whether or not source data like available tables and schema descriptions
  185. * should be cached
  186. *
  187. * @var boolean
  188. */
  189. var $cacheSources = true;
  190. /**
  191. * Constructor.
  192. */
  193. function __construct($config = array()) {
  194. parent::__construct();
  195. $this->setConfig($config);
  196. }
  197. /**
  198. * Caches/returns cached results for child instances
  199. *
  200. * @return array
  201. */
  202. function listSources($data = null) {
  203. if ($this->cacheSources === false) {
  204. return null;
  205. }
  206. if ($this->_sources !== null) {
  207. return $this->_sources;
  208. }
  209. $key = ConnectionManager::getSourceName($this) . '_' . $this->config['database'] . '_list';
  210. $key = preg_replace('/[^A-Za-z0-9_\-.+]/', '_', $key);
  211. $sources = Cache::read($key, '_cake_model_');
  212. if (empty($sources)) {
  213. $sources = $data;
  214. Cache::write($key, $data, '_cake_model_');
  215. }
  216. $this->_sources = $sources;
  217. return $sources;
  218. }
  219. /**
  220. * Convenience method for DboSource::listSources(). Returns source names in lowercase.
  221. *
  222. * @return array
  223. */
  224. function sources($reset = false) {
  225. if ($reset === true) {
  226. $this->_sources = null;
  227. }
  228. return array_map('strtolower', $this->listSources());
  229. }
  230. /**
  231. * Returns a Model description (metadata) or null if none found.
  232. *
  233. * @param Model $model
  234. * @return mixed
  235. */
  236. function describe($model) {
  237. if ($this->cacheSources === false) {
  238. return null;
  239. }
  240. if (isset($this->__descriptions[$model->tablePrefix . $model->table])) {
  241. return $this->__descriptions[$model->tablePrefix . $model->table];
  242. }
  243. $cache = $this->__cacheDescription($model->tablePrefix . $model->table);
  244. if ($cache !== null) {
  245. $this->__descriptions[$model->tablePrefix . $model->table] =& $cache;
  246. return $cache;
  247. }
  248. return null;
  249. }
  250. /**
  251. * Begin a transaction
  252. *
  253. * @return boolean Returns true if a transaction is not in progress
  254. */
  255. function begin(&$model) {
  256. return !$this->_transactionStarted;
  257. }
  258. /**
  259. * Commit a transaction
  260. *
  261. * @return boolean Returns true if a transaction is in progress
  262. */
  263. function commit(&$model) {
  264. return $this->_transactionStarted;
  265. }
  266. /**
  267. * Rollback a transaction
  268. *
  269. * @return boolean Returns true if a transaction is in progress
  270. */
  271. function rollback(&$model) {
  272. return $this->_transactionStarted;
  273. }
  274. /**
  275. * Converts column types to basic types
  276. *
  277. * @param string $real Real column type (i.e. "varchar(255)")
  278. * @return string Abstract column type (i.e. "string")
  279. */
  280. function column($real) {
  281. return false;
  282. }
  283. /**
  284. * To-be-overridden in subclasses.
  285. *
  286. * @param unknown_type $model
  287. * @param unknown_type $fields
  288. * @param unknown_type $values
  289. * @return unknown
  290. */
  291. function create(&$model, $fields = null, $values = null) {
  292. return false;
  293. }
  294. /**
  295. * To-be-overridden in subclasses.
  296. *
  297. * @param unknown_type $model
  298. * @param unknown_type $queryData
  299. * @return unknown
  300. */
  301. function read(&$model, $queryData = array()) {
  302. return false;
  303. }
  304. /**
  305. * To-be-overridden in subclasses.
  306. *
  307. * @param unknown_type $model
  308. * @param unknown_type $fields
  309. * @param unknown_type $values
  310. * @return unknown
  311. */
  312. function update(&$model, $fields = null, $values = null) {
  313. return false;
  314. }
  315. /**
  316. * To-be-overridden in subclasses.
  317. *
  318. * @param unknown_type $model
  319. * @param unknown_type $id
  320. */
  321. function delete(&$model, $id = null) {
  322. if ($id == null) {
  323. $id = $model->id;
  324. }
  325. }
  326. /**
  327. * Returns the ID generated from the previous INSERT operation.
  328. *
  329. * @param unknown_type $source
  330. * @return in
  331. */
  332. function lastInsertId($source = null) {
  333. return false;
  334. }
  335. /**
  336. * Returns the ID generated from the previous INSERT operation.
  337. *
  338. * @param unknown_type $source
  339. * @return in
  340. */
  341. function lastNumRows($source = null) {
  342. return false;
  343. }
  344. /**
  345. * Returns the ID generated from the previous INSERT operation.
  346. *
  347. * @param unknown_type $source
  348. * @return in
  349. */
  350. function lastAffected($source = null) {
  351. return false;
  352. }
  353. /**
  354. * Returns true if the DataSource supports the given interface (method)
  355. *
  356. * @param string $interface The name of the interface (method)
  357. * @return boolean True on success
  358. */
  359. function isInterfaceSupported($interface) {
  360. $methods = get_class_methods(get_class($this));
  361. $methods = strtolower(implode('|', $methods));
  362. $methods = explode('|', $methods);
  363. $return = in_array(strtolower($interface), $methods);
  364. return $return;
  365. }
  366. /**
  367. * Sets the configuration for the DataSource
  368. *
  369. * @param array $config The configuration array
  370. * @return void
  371. */
  372. function setConfig($config = array()) {
  373. $this->config = array_merge($this->_baseConfig, $this->config, $config);
  374. }
  375. /**
  376. * Cache the DataSource description
  377. *
  378. * @param string $object The name of the object (model) to cache
  379. * @param mixed $data The description of the model, usually a string or array
  380. */
  381. function __cacheDescription($object, $data = null) {
  382. if ($this->cacheSources === false) {
  383. return null;
  384. }
  385. if ($data !== null) {
  386. $this->__descriptions[$object] =& $data;
  387. }
  388. $key = ConnectionManager::getSourceName($this) . '_' . $object;
  389. $cache = Cache::read($key, '_cake_model_');
  390. if (empty($cache)) {
  391. $cache = $data;
  392. Cache::write($key, $cache, '_cake_model_');
  393. }
  394. return $cache;
  395. }
  396. /**
  397. * Enter description here...
  398. *
  399. * @param unknown_type $query
  400. * @param unknown_type $data
  401. * @param unknown_type $association
  402. * @param unknown_type $assocData
  403. * @param Model $model
  404. * @param Model $linkModel
  405. * @param array $stack
  406. * @return unknown
  407. */
  408. function insertQueryData($query, $data, $association, $assocData, &$model, &$linkModel, $stack) {
  409. $keys = array('{$__cakeID__$}', '{$__cakeForeignKey__$}');
  410. foreach ($keys as $key) {
  411. $val = null;
  412. if (strpos($query, $key) !== false) {
  413. switch ($key) {
  414. case '{$__cakeID__$}':
  415. if (isset($data[$model->alias]) || isset($data[$association])) {
  416. if (isset($data[$model->alias][$model->primaryKey])) {
  417. $val = $data[$model->alias][$model->primaryKey];
  418. } elseif (isset($data[$association][$model->primaryKey])) {
  419. $val = $data[$association][$model->primaryKey];
  420. }
  421. } else {
  422. $found = false;
  423. foreach (array_reverse($stack) as $assoc) {
  424. if (isset($data[$assoc]) && isset($data[$assoc][$model->primaryKey])) {
  425. $val = $data[$assoc][$model->primaryKey];
  426. $found = true;
  427. break;
  428. }
  429. }
  430. if (!$found) {
  431. $val = '';
  432. }
  433. }
  434. break;
  435. case '{$__cakeForeignKey__$}':
  436. foreach ($model->__associations as $id => $name) {
  437. foreach ($model->$name as $assocName => $assoc) {
  438. if ($assocName === $association) {
  439. if (isset($assoc['foreignKey'])) {
  440. $foreignKey = $assoc['foreignKey'];
  441. if (isset($data[$model->alias][$foreignKey])) {
  442. $val = $data[$model->alias][$foreignKey];
  443. } elseif (isset($data[$association][$foreignKey])) {
  444. $val = $data[$association][$foreignKey];
  445. } else {
  446. $found = false;
  447. foreach (array_reverse($stack) as $assoc) {
  448. if (isset($data[$assoc]) && isset($data[$assoc][$foreignKey])) {
  449. $val = $data[$assoc][$foreignKey];
  450. $found = true;
  451. break;
  452. }
  453. }
  454. if (!$found) {
  455. $val = '';
  456. }
  457. }
  458. }
  459. break 3;
  460. }
  461. }
  462. }
  463. break;
  464. }
  465. if (empty($val) && $val !== '0') {
  466. return false;
  467. }
  468. $query = str_replace($key, $this->value($val, $model->getColumnType($model->primaryKey)), $query);
  469. }
  470. }
  471. return $query;
  472. }
  473. /**
  474. * To-be-overridden in subclasses.
  475. *
  476. * @param unknown_type $model
  477. * @param unknown_type $key
  478. * @return unknown
  479. */
  480. function resolveKey($model, $key) {
  481. return $model->alias . $key;
  482. }
  483. /**
  484. * Closes the current datasource.
  485. *
  486. */
  487. function __destruct() {
  488. if ($this->_transactionStarted) {
  489. $null = null;
  490. $this->rollback($null);
  491. }
  492. if ($this->connected) {
  493. $this->close();
  494. }
  495. }
  496. }
  497. ?>