統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Model / Datasource / DataSource.php @ 0b1b8047

履歴 | 表示 | アノテート | ダウンロード (10.239 KB)

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 bool
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 bool
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 bool
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 Unused in this class.
93
 * @return array|null 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 The model to describe.
120
 * @return array|null 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 bool 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 bool 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 bool 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 bool 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 int $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 The array of conditions to use.
218
 * @return bool 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 bool 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 The source name.
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 The source name.
251
 * @return int 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 The source name.
261
 * @return int 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 bool 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 Model $Model Model instance.
323
 * @param array $stack The context stack.
324
 * @return mixed String of query data with placeholders replaced, or false on failure.
325
 */
326
        public function insertQueryData($query, $data, $association, Model $Model, $stack) {
327
                $keys = array('{$__cakeID__$}', '{$__cakeForeignKey__$}');
328

    
329
                $modelAlias = $Model->alias;
330

    
331
                foreach ($keys as $key) {
332
                        if (strpos($query, $key) === false) {
333
                                continue;
334
                        }
335

    
336
                        $insertKey = $InsertModel = null;
337
                        switch ($key) {
338
                                case '{$__cakeID__$}':
339
                                        $InsertModel = $Model;
340
                                        $insertKey = $Model->primaryKey;
341

    
342
                                        break;
343
                                case '{$__cakeForeignKey__$}':
344
                                        foreach ($Model->associations() as $type) {
345
                                                foreach ($Model->{$type} as $assoc => $assocData) {
346
                                                        if ($assoc !== $association) {
347
                                                                continue;
348
                                                        }
349

    
350
                                                        if (isset($assocData['foreignKey'])) {
351
                                                                $InsertModel = $Model->{$assoc};
352
                                                                $insertKey = $assocData['foreignKey'];
353
                                                        }
354

    
355
                                                        break 3;
356
                                                }
357
                                        }
358

    
359
                                        break;
360
                        }
361

    
362
                        $val = $dataType = null;
363
                        if (!empty($insertKey) && !empty($InsertModel)) {
364
                                if (isset($data[$modelAlias][$insertKey])) {
365
                                        $val = $data[$modelAlias][$insertKey];
366
                                } elseif (isset($data[$association][$insertKey])) {
367
                                        $val = $data[$association][$insertKey];
368
                                } else {
369
                                        $found = false;
370
                                        foreach (array_reverse($stack) as $assocData) {
371
                                                if (isset($data[$assocData]) && isset($data[$assocData][$insertKey])) {
372
                                                        $val = $data[$assocData][$insertKey];
373
                                                        $found = true;
374
                                                        break;
375
                                                }
376
                                        }
377

    
378
                                        if (!$found) {
379
                                                $val = '';
380
                                        }
381
                                }
382

    
383
                                $dataType = $InsertModel->getColumnType($InsertModel->primaryKey);
384
                        }
385

    
386
                        if (empty($val) && $val !== '0') {
387
                                return false;
388
                        }
389

    
390
                        $query = str_replace($key, $this->value($val, $dataType), $query);
391
                }
392

    
393
                return $query;
394
        }
395

    
396
/**
397
 * To-be-overridden in subclasses.
398
 *
399
 * @param Model $Model Model instance
400
 * @param string $key Key name to make
401
 * @return string Key name for model.
402
 */
403
        public function resolveKey(Model $Model, $key) {
404
                return $Model->alias . $key;
405
        }
406

    
407
/**
408
 * Returns the schema name. Override this in subclasses.
409
 *
410
 * @return string|null The schema name
411
 */
412
        public function getSchemaName() {
413
                return null;
414
        }
415

    
416
/**
417
 * Closes a connection. Override in subclasses.
418
 *
419
 * @return bool
420
 */
421
        public function close() {
422
                return $this->connected = false;
423
        }
424

    
425
/**
426
 * Closes the current datasource.
427
 */
428
        public function __destruct() {
429
                if ($this->_transactionStarted) {
430
                        $this->rollback();
431
                }
432
                if ($this->connected) {
433
                        $this->close();
434
                }
435
        }
436

    
437
}