Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
13532 anikendra 1
<?php
2
/**
3
 * DataSource base class
4
 *
5
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
6
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
7
 *
8
 * Licensed under The MIT License
9
 * For full copyright and license information, please see the LICENSE.txt
10
 * Redistributions of files must retain the above copyright notice.
11
 *
12
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
13
 * @link          http://cakephp.org CakePHP(tm) Project
14
 * @package       Cake.Model.Datasource
15
 * @since         CakePHP(tm) v 0.10.5.1790
16
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
17
 */
18
 
19
/**
20
 * DataSource base class
21
 *
22
 * DataSources are the link between models and the source of data that models represent.
23
 *
24
 * @link          http://book.cakephp.org/2.0/en/models/datasources.html#basic-api-for-datasources
25
 * @package       Cake.Model.Datasource
26
 */
27
class DataSource extends Object {
28
 
29
/**
30
 * Are we connected to the DataSource?
31
 *
32
 * @var boolean
33
 */
34
	public $connected = false;
35
 
36
/**
37
 * The default configuration of a specific DataSource
38
 *
39
 * @var array
40
 */
41
	protected $_baseConfig = array();
42
 
43
/**
44
 * Holds references to descriptions loaded by the DataSource
45
 *
46
 * @var array
47
 */
48
	protected $_descriptions = array();
49
 
50
/**
51
 * Holds a list of sources (tables) contained in the DataSource
52
 *
53
 * @var array
54
 */
55
	protected $_sources = null;
56
 
57
/**
58
 * The DataSource configuration
59
 *
60
 * @var array
61
 */
62
	public $config = array();
63
 
64
/**
65
 * Whether or not this DataSource is in the middle of a transaction
66
 *
67
 * @var boolean
68
 */
69
	protected $_transactionStarted = false;
70
 
71
/**
72
 * Whether or not source data like available tables and schema descriptions
73
 * should be cached
74
 *
75
 * @var boolean
76
 */
77
	public $cacheSources = true;
78
 
79
/**
80
 * Constructor.
81
 *
82
 * @param array $config Array of configuration information for the datasource.
83
 */
84
	public function __construct($config = array()) {
85
		parent::__construct();
86
		$this->setConfig($config);
87
	}
88
 
89
/**
90
 * Caches/returns cached results for child instances
91
 *
92
 * @param mixed $data
93
 * @return array Array of sources available in this datasource.
94
 */
95
	public function listSources($data = null) {
96
		if ($this->cacheSources === false) {
97
			return null;
98
		}
99
 
100
		if ($this->_sources !== null) {
101
			return $this->_sources;
102
		}
103
 
104
		$key = ConnectionManager::getSourceName($this) . '_' . $this->config['database'] . '_list';
105
		$key = preg_replace('/[^A-Za-z0-9_\-.+]/', '_', $key);
106
		$sources = Cache::read($key, '_cake_model_');
107
 
108
		if (empty($sources)) {
109
			$sources = $data;
110
			Cache::write($key, $data, '_cake_model_');
111
		}
112
 
113
		return $this->_sources = $sources;
114
	}
115
 
116
/**
117
 * Returns a Model description (metadata) or null if none found.
118
 *
119
 * @param Model|string $model
120
 * @return array Array of Metadata for the $model
121
 */
122
	public function describe($model) {
123
		if ($this->cacheSources === false) {
124
			return null;
125
		}
126
		if (is_string($model)) {
127
			$table = $model;
128
		} else {
129
			$table = $model->tablePrefix . $model->table;
130
		}
131
 
132
		if (isset($this->_descriptions[$table])) {
133
			return $this->_descriptions[$table];
134
		}
135
		$cache = $this->_cacheDescription($table);
136
 
137
		if ($cache !== null) {
138
			$this->_descriptions[$table] =& $cache;
139
			return $cache;
140
		}
141
		return null;
142
	}
143
 
144
/**
145
 * Begin a transaction
146
 *
147
 * @return boolean Returns true if a transaction is not in progress
148
 */
149
	public function begin() {
150
		return !$this->_transactionStarted;
151
	}
152
 
153
/**
154
 * Commit a transaction
155
 *
156
 * @return boolean Returns true if a transaction is in progress
157
 */
158
	public function commit() {
159
		return $this->_transactionStarted;
160
	}
161
 
162
/**
163
 * Rollback a transaction
164
 *
165
 * @return boolean Returns true if a transaction is in progress
166
 */
167
	public function rollback() {
168
		return $this->_transactionStarted;
169
	}
170
 
171
/**
172
 * Converts column types to basic types
173
 *
174
 * @param string $real Real column type (i.e. "varchar(255)")
175
 * @return string Abstract column type (i.e. "string")
176
 */
177
	public function column($real) {
178
		return false;
179
	}
180
 
181
/**
182
 * Used to create new records. The "C" CRUD.
183
 *
184
 * To-be-overridden in subclasses.
185
 *
186
 * @param Model $model The Model to be created.
187
 * @param array $fields An Array of fields to be saved.
188
 * @param array $values An Array of values to save.
189
 * @return boolean success
190
 */
191
	public function create(Model $model, $fields = null, $values = null) {
192
		return false;
193
	}
194
 
195
/**
196
 * Used to read records from the Datasource. The "R" in CRUD
197
 *
198
 * To-be-overridden in subclasses.
199
 *
200
 * @param Model $model The model being read.
201
 * @param array $queryData An array of query data used to find the data you want
202
 * @param integer $recursive Number of levels of association
203
 * @return mixed
204
 */
205
	public function read(Model $model, $queryData = array(), $recursive = null) {
206
		return false;
207
	}
208
 
209
/**
210
 * Update a record(s) in the datasource.
211
 *
212
 * To-be-overridden in subclasses.
213
 *
214
 * @param Model $model Instance of the model class being updated
215
 * @param array $fields Array of fields to be updated
216
 * @param array $values Array of values to be update $fields to.
217
 * @param mixed $conditions
218
 * @return boolean Success
219
 */
220
	public function update(Model $model, $fields = null, $values = null, $conditions = null) {
221
		return false;
222
	}
223
 
224
/**
225
 * Delete a record(s) in the datasource.
226
 *
227
 * To-be-overridden in subclasses.
228
 *
229
 * @param Model $model The model class having record(s) deleted
230
 * @param mixed $conditions The conditions to use for deleting.
231
 * @return boolean Success
232
 */
233
	public function delete(Model $model, $conditions = null) {
234
		return false;
235
	}
236
 
237
/**
238
 * Returns the ID generated from the previous INSERT operation.
239
 *
240
 * @param mixed $source
241
 * @return mixed Last ID key generated in previous INSERT
242
 */
243
	public function lastInsertId($source = null) {
244
		return false;
245
	}
246
 
247
/**
248
 * Returns the number of rows returned by last operation.
249
 *
250
 * @param mixed $source
251
 * @return integer Number of rows returned by last operation
252
 */
253
	public function lastNumRows($source = null) {
254
		return false;
255
	}
256
 
257
/**
258
 * Returns the number of rows affected by last query.
259
 *
260
 * @param mixed $source
261
 * @return integer Number of rows affected by last query.
262
 */
263
	public function lastAffected($source = null) {
264
		return false;
265
	}
266
 
267
/**
268
 * Check whether the conditions for the Datasource being available
269
 * are satisfied. Often used from connect() to check for support
270
 * before establishing a connection.
271
 *
272
 * @return boolean Whether or not the Datasources conditions for use are met.
273
 */
274
	public function enabled() {
275
		return true;
276
	}
277
 
278
/**
279
 * Sets the configuration for the DataSource.
280
 * Merges the $config information with the _baseConfig and the existing $config property.
281
 *
282
 * @param array $config The configuration array
283
 * @return void
284
 */
285
	public function setConfig($config = array()) {
286
		$this->config = array_merge($this->_baseConfig, $this->config, $config);
287
	}
288
 
289
/**
290
 * Cache the DataSource description
291
 *
292
 * @param string $object The name of the object (model) to cache
293
 * @param mixed $data The description of the model, usually a string or array
294
 * @return mixed
295
 */
296
	protected function _cacheDescription($object, $data = null) {
297
		if ($this->cacheSources === false) {
298
			return null;
299
		}
300
 
301
		if ($data !== null) {
302
			$this->_descriptions[$object] =& $data;
303
		}
304
 
305
		$key = ConnectionManager::getSourceName($this) . '_' . $object;
306
		$cache = Cache::read($key, '_cake_model_');
307
 
308
		if (empty($cache)) {
309
			$cache = $data;
310
			Cache::write($key, $cache, '_cake_model_');
311
		}
312
 
313
		return $cache;
314
	}
315
 
316
/**
317
 * Replaces `{$__cakeID__$}` and `{$__cakeForeignKey__$}` placeholders in query data.
318
 *
319
 * @param string $query Query string needing replacements done.
320
 * @param array $data Array of data with values that will be inserted in placeholders.
321
 * @param string $association Name of association model being replaced
322
 * @param array $assocData
323
 * @param Model $model Instance of the model to replace $__cakeID__$
324
 * @param Model $linkModel Instance of model to replace $__cakeForeignKey__$
325
 * @param array $stack
326
 * @return string String of query data with placeholders replaced.
327
 */
328
	public function insertQueryData($query, $data, $association, $assocData, Model $model, Model $linkModel, $stack) {
329
		$keys = array('{$__cakeID__$}', '{$__cakeForeignKey__$}');
330
 
331
		foreach ($keys as $key) {
332
			$val = null;
333
			$type = null;
334
 
335
			if (strpos($query, $key) !== false) {
336
				switch ($key) {
337
					case '{$__cakeID__$}':
338
						if (isset($data[$model->alias]) || isset($data[$association])) {
339
							if (isset($data[$model->alias][$model->primaryKey])) {
340
								$val = $data[$model->alias][$model->primaryKey];
341
							} elseif (isset($data[$association][$model->primaryKey])) {
342
								$val = $data[$association][$model->primaryKey];
343
							}
344
						} else {
345
							$found = false;
346
							foreach (array_reverse($stack) as $assoc) {
347
								if (isset($data[$assoc]) && isset($data[$assoc][$model->primaryKey])) {
348
									$val = $data[$assoc][$model->primaryKey];
349
									$found = true;
350
									break;
351
								}
352
							}
353
							if (!$found) {
354
								$val = '';
355
							}
356
						}
357
						$type = $model->getColumnType($model->primaryKey);
358
						break;
359
					case '{$__cakeForeignKey__$}':
360
						foreach ($model->associations() as $name) {
361
							foreach ($model->$name as $assocName => $assoc) {
362
								if ($assocName === $association) {
363
									if (isset($assoc['foreignKey'])) {
364
										$foreignKey = $assoc['foreignKey'];
365
										$assocModel = $model->$assocName;
366
										$type = $assocModel->getColumnType($assocModel->primaryKey);
367
 
368
										if (isset($data[$model->alias][$foreignKey])) {
369
											$val = $data[$model->alias][$foreignKey];
370
										} elseif (isset($data[$association][$foreignKey])) {
371
											$val = $data[$association][$foreignKey];
372
										} else {
373
											$found = false;
374
											foreach (array_reverse($stack) as $assoc) {
375
												if (isset($data[$assoc]) && isset($data[$assoc][$foreignKey])) {
376
													$val = $data[$assoc][$foreignKey];
377
													$found = true;
378
													break;
379
												}
380
											}
381
											if (!$found) {
382
												$val = '';
383
											}
384
										}
385
									}
386
									break 3;
387
								}
388
							}
389
						}
390
						break;
391
				}
392
				if (empty($val) && $val !== '0') {
393
					return false;
394
				}
395
				$query = str_replace($key, $this->value($val, $type), $query);
396
			}
397
		}
398
		return $query;
399
	}
400
 
401
/**
402
 * To-be-overridden in subclasses.
403
 *
404
 * @param Model $model Model instance
405
 * @param string $key Key name to make
406
 * @return string Key name for model.
407
 */
408
	public function resolveKey(Model $model, $key) {
409
		return $model->alias . $key;
410
	}
411
 
412
/**
413
 * Returns the schema name. Override this in subclasses.
414
 *
415
 * @return string schema name
416
 */
417
	public function getSchemaName() {
418
		return null;
419
	}
420
 
421
/**
422
 * Closes a connection. Override in subclasses
423
 *
424
 * @return boolean
425
 */
426
	public function close() {
427
		return $this->connected = false;
428
	}
429
 
430
/**
431
 * Closes the current datasource.
432
 */
433
	public function __destruct() {
434
		if ($this->_transactionStarted) {
435
			$this->rollback();
436
		}
437
		if ($this->connected) {
438
			$this->close();
439
		}
440
	}
441
 
442
}