Mercurial > hg > Members > shoshi > webvirt
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:261e66bd5a0c |
---|---|
1 <?php | |
2 /** | |
3 * DataSource base class | |
4 * | |
5 * PHP versions 4 and 5 | |
6 * | |
7 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) | |
8 * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) | |
9 * | |
10 * Licensed under The MIT License | |
11 * Redistributions of files must retain the above copyright notice. | |
12 * | |
13 * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) | |
14 * @link http://cakephp.org CakePHP(tm) Project | |
15 * @package cake | |
16 * @subpackage cake.cake.libs.model.datasources | |
17 * @since CakePHP(tm) v 0.10.5.1790 | |
18 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) | |
19 */ | |
20 | |
21 /** | |
22 * DataSource base class | |
23 * | |
24 * @package cake | |
25 * @subpackage cake.cake.libs.model.datasources | |
26 */ | |
27 class DataSource extends Object { | |
28 | |
29 /** | |
30 * Are we connected to the DataSource? | |
31 * | |
32 * @var boolean | |
33 * @access public | |
34 */ | |
35 var $connected = false; | |
36 | |
37 /** | |
38 * Print full query debug info? | |
39 * | |
40 * @var boolean | |
41 * @access public | |
42 */ | |
43 var $fullDebug = false; | |
44 | |
45 /** | |
46 * Error description of last query | |
47 * | |
48 * @var unknown_type | |
49 * @access public | |
50 */ | |
51 var $error = null; | |
52 | |
53 /** | |
54 * String to hold how many rows were affected by the last SQL operation. | |
55 * | |
56 * @var string | |
57 * @access public | |
58 */ | |
59 var $affected = null; | |
60 | |
61 /** | |
62 * Number of rows in current resultset | |
63 * | |
64 * @var int | |
65 * @access public | |
66 */ | |
67 var $numRows = null; | |
68 | |
69 /** | |
70 * Time the last query took | |
71 * | |
72 * @var int | |
73 * @access public | |
74 */ | |
75 var $took = null; | |
76 | |
77 /** | |
78 * The starting character that this DataSource uses for quoted identifiers. | |
79 * | |
80 * @var string | |
81 * @access public | |
82 */ | |
83 var $startQuote = null; | |
84 | |
85 /** | |
86 * The ending character that this DataSource uses for quoted identifiers. | |
87 * | |
88 * @var string | |
89 * @access public | |
90 */ | |
91 var $endQuote = null; | |
92 | |
93 /** | |
94 * Result | |
95 * | |
96 * @var array | |
97 * @access protected | |
98 */ | |
99 var $_result = null; | |
100 | |
101 /** | |
102 * Queries count. | |
103 * | |
104 * @var int | |
105 * @access protected | |
106 */ | |
107 var $_queriesCnt = 0; | |
108 | |
109 /** | |
110 * Total duration of all queries. | |
111 * | |
112 * @var unknown_type | |
113 * @access protected | |
114 */ | |
115 var $_queriesTime = null; | |
116 | |
117 /** | |
118 * Log of queries executed by this DataSource | |
119 * | |
120 * @var unknown_type | |
121 * @access protected | |
122 */ | |
123 var $_queriesLog = array(); | |
124 | |
125 /** | |
126 * Maximum number of items in query log | |
127 * | |
128 * This is to prevent query log taking over too much memory. | |
129 * | |
130 * @var int Maximum number of queries in the queries log. | |
131 * @access protected | |
132 */ | |
133 var $_queriesLogMax = 200; | |
134 | |
135 /** | |
136 * Caches serialzed results of executed queries | |
137 * | |
138 * @var array Maximum number of queries in the queries log. | |
139 * @access protected | |
140 */ | |
141 var $_queryCache = array(); | |
142 | |
143 /** | |
144 * The default configuration of a specific DataSource | |
145 * | |
146 * @var array | |
147 * @access protected | |
148 */ | |
149 var $_baseConfig = array(); | |
150 | |
151 /** | |
152 * Holds references to descriptions loaded by the DataSource | |
153 * | |
154 * @var array | |
155 * @access private | |
156 */ | |
157 var $__descriptions = array(); | |
158 | |
159 /** | |
160 * Holds a list of sources (tables) contained in the DataSource | |
161 * | |
162 * @var array | |
163 * @access protected | |
164 */ | |
165 var $_sources = null; | |
166 | |
167 /** | |
168 * A reference to the physical connection of this DataSource | |
169 * | |
170 * @var array | |
171 * @access public | |
172 */ | |
173 var $connection = null; | |
174 | |
175 /** | |
176 * The DataSource configuration | |
177 * | |
178 * @var array | |
179 * @access public | |
180 */ | |
181 var $config = array(); | |
182 | |
183 /** | |
184 * The DataSource configuration key name | |
185 * | |
186 * @var string | |
187 * @access public | |
188 */ | |
189 var $configKeyName = null; | |
190 | |
191 /** | |
192 * Whether or not this DataSource is in the middle of a transaction | |
193 * | |
194 * @var boolean | |
195 * @access protected | |
196 */ | |
197 var $_transactionStarted = false; | |
198 | |
199 /** | |
200 * Whether or not source data like available tables and schema descriptions | |
201 * should be cached | |
202 * | |
203 * @var boolean | |
204 * @access public | |
205 */ | |
206 var $cacheSources = true; | |
207 | |
208 /** | |
209 * Constructor. | |
210 * | |
211 * @param array $config Array of configuration information for the datasource. | |
212 * @return void. | |
213 */ | |
214 function __construct($config = array()) { | |
215 parent::__construct(); | |
216 $this->setConfig($config); | |
217 } | |
218 | |
219 /** | |
220 * Caches/returns cached results for child instances | |
221 * | |
222 * @param mixed $data | |
223 * @return array Array of sources available in this datasource. | |
224 * @access public | |
225 */ | |
226 function listSources($data = null) { | |
227 if ($this->cacheSources === false) { | |
228 return null; | |
229 } | |
230 | |
231 if ($this->_sources !== null) { | |
232 return $this->_sources; | |
233 } | |
234 | |
235 $key = ConnectionManager::getSourceName($this) . '_' . $this->config['database'] . '_list'; | |
236 $key = preg_replace('/[^A-Za-z0-9_\-.+]/', '_', $key); | |
237 $sources = Cache::read($key, '_cake_model_'); | |
238 | |
239 if (empty($sources)) { | |
240 $sources = $data; | |
241 Cache::write($key, $data, '_cake_model_'); | |
242 } | |
243 | |
244 $this->_sources = $sources; | |
245 return $sources; | |
246 } | |
247 | |
248 /** | |
249 * Convenience method for DboSource::listSources(). Returns source names in lowercase. | |
250 * | |
251 * @param boolean $reset Whether or not the source list should be reset. | |
252 * @return array Array of sources available in this datasource | |
253 * @access public | |
254 */ | |
255 function sources($reset = false) { | |
256 if ($reset === true) { | |
257 $this->_sources = null; | |
258 } | |
259 return array_map('strtolower', $this->listSources()); | |
260 } | |
261 | |
262 /** | |
263 * Returns a Model description (metadata) or null if none found. | |
264 * | |
265 * @param Model $model | |
266 * @return array Array of Metadata for the $model | |
267 * @access public | |
268 */ | |
269 function describe(&$model) { | |
270 if ($this->cacheSources === false) { | |
271 return null; | |
272 } | |
273 $table = $model->tablePrefix . $model->table; | |
274 | |
275 if (isset($this->__descriptions[$table])) { | |
276 return $this->__descriptions[$table]; | |
277 } | |
278 $cache = $this->__cacheDescription($table); | |
279 | |
280 if ($cache !== null) { | |
281 $this->__descriptions[$table] =& $cache; | |
282 return $cache; | |
283 } | |
284 return null; | |
285 } | |
286 | |
287 /** | |
288 * Begin a transaction | |
289 * | |
290 * @return boolean Returns true if a transaction is not in progress | |
291 * @access public | |
292 */ | |
293 function begin(&$model) { | |
294 return !$this->_transactionStarted; | |
295 } | |
296 | |
297 /** | |
298 * Commit a transaction | |
299 * | |
300 * @return boolean Returns true if a transaction is in progress | |
301 * @access public | |
302 */ | |
303 function commit(&$model) { | |
304 return $this->_transactionStarted; | |
305 } | |
306 | |
307 /** | |
308 * Rollback a transaction | |
309 * | |
310 * @return boolean Returns true if a transaction is in progress | |
311 * @access public | |
312 */ | |
313 function rollback(&$model) { | |
314 return $this->_transactionStarted; | |
315 } | |
316 | |
317 /** | |
318 * Converts column types to basic types | |
319 * | |
320 * @param string $real Real column type (i.e. "varchar(255)") | |
321 * @return string Abstract column type (i.e. "string") | |
322 * @access public | |
323 */ | |
324 function column($real) { | |
325 return false; | |
326 } | |
327 | |
328 /** | |
329 * Used to create new records. The "C" CRUD. | |
330 * | |
331 * To-be-overridden in subclasses. | |
332 * | |
333 * @param Model $model The Model to be created. | |
334 * @param array $fields An Array of fields to be saved. | |
335 * @param array $values An Array of values to save. | |
336 * @return boolean success | |
337 * @access public | |
338 */ | |
339 function create(&$model, $fields = null, $values = null) { | |
340 return false; | |
341 } | |
342 | |
343 /** | |
344 * Used to read records from the Datasource. The "R" in CRUD | |
345 * | |
346 * To-be-overridden in subclasses. | |
347 * | |
348 * @param Model $model The model being read. | |
349 * @param array $queryData An array of query data used to find the data you want | |
350 * @return mixed | |
351 * @access public | |
352 */ | |
353 function read(&$model, $queryData = array()) { | |
354 return false; | |
355 } | |
356 | |
357 /** | |
358 * Update a record(s) in the datasource. | |
359 * | |
360 * To-be-overridden in subclasses. | |
361 * | |
362 * @param Model $model Instance of the model class being updated | |
363 * @param array $fields Array of fields to be updated | |
364 * @param array $values Array of values to be update $fields to. | |
365 * @return boolean Success | |
366 * @access public | |
367 */ | |
368 function update(&$model, $fields = null, $values = null) { | |
369 return false; | |
370 } | |
371 | |
372 /** | |
373 * Delete a record(s) in the datasource. | |
374 * | |
375 * To-be-overridden in subclasses. | |
376 * | |
377 * @param Model $model The model class having record(s) deleted | |
378 * @param mixed $id Primary key of the model | |
379 * @access public | |
380 */ | |
381 function delete(&$model, $id = null) { | |
382 if ($id == null) { | |
383 $id = $model->id; | |
384 } | |
385 } | |
386 | |
387 /** | |
388 * Returns the ID generated from the previous INSERT operation. | |
389 * | |
390 * @param unknown_type $source | |
391 * @return mixed Last ID key generated in previous INSERT | |
392 * @access public | |
393 */ | |
394 function lastInsertId($source = null) { | |
395 return false; | |
396 } | |
397 | |
398 /** | |
399 * Returns the number of rows returned by last operation. | |
400 * | |
401 * @param unknown_type $source | |
402 * @return integer Number of rows returned by last operation | |
403 * @access public | |
404 */ | |
405 function lastNumRows($source = null) { | |
406 return false; | |
407 } | |
408 | |
409 /** | |
410 * Returns the number of rows affected by last query. | |
411 * | |
412 * @param unknown_type $source | |
413 * @return integer Number of rows affected by last query. | |
414 * @access public | |
415 */ | |
416 function lastAffected($source = null) { | |
417 return false; | |
418 } | |
419 | |
420 /** | |
421 * Check whether the conditions for the Datasource being available | |
422 * are satisfied. Often used from connect() to check for support | |
423 * before establishing a connection. | |
424 * | |
425 * @return boolean Whether or not the Datasources conditions for use are met. | |
426 * @access public | |
427 */ | |
428 function enabled() { | |
429 return true; | |
430 } | |
431 | |
432 /** | |
433 * Returns true if the DataSource supports the given interface (method) | |
434 * | |
435 * @param string $interface The name of the interface (method) | |
436 * @return boolean True on success | |
437 * @access public | |
438 */ | |
439 function isInterfaceSupported($interface) { | |
440 static $methods = false; | |
441 if ($methods === false) { | |
442 $methods = array_map('strtolower', get_class_methods($this)); | |
443 } | |
444 return in_array(strtolower($interface), $methods); | |
445 } | |
446 | |
447 /** | |
448 * Sets the configuration for the DataSource. | |
449 * Merges the $config information with the _baseConfig and the existing $config property. | |
450 * | |
451 * @param array $config The configuration array | |
452 * @return void | |
453 * @access public | |
454 */ | |
455 function setConfig($config = array()) { | |
456 $this->config = array_merge($this->_baseConfig, $this->config, $config); | |
457 } | |
458 | |
459 /** | |
460 * Cache the DataSource description | |
461 * | |
462 * @param string $object The name of the object (model) to cache | |
463 * @param mixed $data The description of the model, usually a string or array | |
464 * @return mixed | |
465 * @access private | |
466 */ | |
467 function __cacheDescription($object, $data = null) { | |
468 if ($this->cacheSources === false) { | |
469 return null; | |
470 } | |
471 | |
472 if ($data !== null) { | |
473 $this->__descriptions[$object] =& $data; | |
474 } | |
475 | |
476 $key = ConnectionManager::getSourceName($this) . '_' . $object; | |
477 $cache = Cache::read($key, '_cake_model_'); | |
478 | |
479 if (empty($cache)) { | |
480 $cache = $data; | |
481 Cache::write($key, $cache, '_cake_model_'); | |
482 } | |
483 | |
484 return $cache; | |
485 } | |
486 | |
487 /** | |
488 * Replaces `{$__cakeID__$}` and `{$__cakeForeignKey__$}` placeholders in query data. | |
489 * | |
490 * @param string $query Query string needing replacements done. | |
491 * @param array $data Array of data with values that will be inserted in placeholders. | |
492 * @param string $association Name of association model being replaced | |
493 * @param unknown_type $assocData | |
494 * @param Model $model Instance of the model to replace $__cakeID__$ | |
495 * @param Model $linkModel Instance of model to replace $__cakeForeignKey__$ | |
496 * @param array $stack | |
497 * @return string String of query data with placeholders replaced. | |
498 * @access public | |
499 * @todo Remove and refactor $assocData, ensure uses of the method have the param removed too. | |
500 */ | |
501 function insertQueryData($query, $data, $association, $assocData, &$model, &$linkModel, $stack) { | |
502 $keys = array('{$__cakeID__$}', '{$__cakeForeignKey__$}'); | |
503 | |
504 foreach ($keys as $key) { | |
505 $val = null; | |
506 $type = null; | |
507 | |
508 if (strpos($query, $key) !== false) { | |
509 switch ($key) { | |
510 case '{$__cakeID__$}': | |
511 if (isset($data[$model->alias]) || isset($data[$association])) { | |
512 if (isset($data[$model->alias][$model->primaryKey])) { | |
513 $val = $data[$model->alias][$model->primaryKey]; | |
514 } elseif (isset($data[$association][$model->primaryKey])) { | |
515 $val = $data[$association][$model->primaryKey]; | |
516 } | |
517 } else { | |
518 $found = false; | |
519 foreach (array_reverse($stack) as $assoc) { | |
520 if (isset($data[$assoc]) && isset($data[$assoc][$model->primaryKey])) { | |
521 $val = $data[$assoc][$model->primaryKey]; | |
522 $found = true; | |
523 break; | |
524 } | |
525 } | |
526 if (!$found) { | |
527 $val = ''; | |
528 } | |
529 } | |
530 $type = $model->getColumnType($model->primaryKey); | |
531 break; | |
532 case '{$__cakeForeignKey__$}': | |
533 foreach ($model->__associations as $id => $name) { | |
534 foreach ($model->$name as $assocName => $assoc) { | |
535 if ($assocName === $association) { | |
536 if (isset($assoc['foreignKey'])) { | |
537 $foreignKey = $assoc['foreignKey']; | |
538 $assocModel = $model->$assocName; | |
539 $type = $assocModel->getColumnType($assocModel->primaryKey); | |
540 | |
541 if (isset($data[$model->alias][$foreignKey])) { | |
542 $val = $data[$model->alias][$foreignKey]; | |
543 } elseif (isset($data[$association][$foreignKey])) { | |
544 $val = $data[$association][$foreignKey]; | |
545 } else { | |
546 $found = false; | |
547 foreach (array_reverse($stack) as $assoc) { | |
548 if (isset($data[$assoc]) && isset($data[$assoc][$foreignKey])) { | |
549 $val = $data[$assoc][$foreignKey]; | |
550 $found = true; | |
551 break; | |
552 } | |
553 } | |
554 if (!$found) { | |
555 $val = ''; | |
556 } | |
557 } | |
558 } | |
559 break 3; | |
560 } | |
561 } | |
562 } | |
563 break; | |
564 } | |
565 if (empty($val) && $val !== '0') { | |
566 return false; | |
567 } | |
568 $query = str_replace($key, $this->value($val, $type), $query); | |
569 } | |
570 } | |
571 return $query; | |
572 } | |
573 | |
574 /** | |
575 * To-be-overridden in subclasses. | |
576 * | |
577 * @param Model $model Model instance | |
578 * @param string $key Key name to make | |
579 * @return string Key name for model. | |
580 * @access public | |
581 */ | |
582 function resolveKey(&$model, $key) { | |
583 return $model->alias . $key; | |
584 } | |
585 | |
586 /** | |
587 * Closes the current datasource. | |
588 * | |
589 * @return void | |
590 * @access public | |
591 */ | |
592 function __destruct() { | |
593 if ($this->_transactionStarted) { | |
594 $null = null; | |
595 $this->rollback($null); | |
596 } | |
597 if ($this->connected) { | |
598 $this->close(); | |
599 } | |
600 } | |
601 } |