00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 uses('class_registry', 'validators', 'model' . DS . 'connection_manager', 'set');
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 class Model extends Object{
00046
00047
00048
00049
00050
00051
00052 var $useDbConfig = 'default';
00053
00054
00055
00056
00057
00058
00059 var $useTable = null;
00060
00061
00062
00063
00064
00065
00066 var $displayField = null;
00067
00068
00069
00070
00071
00072
00073
00074 var $id = false;
00075
00076
00077
00078
00079
00080
00081 var $data = array();
00082
00083
00084
00085
00086
00087
00088 var $table = false;
00089
00090
00091
00092
00093
00094
00095 var $primaryKey = null;
00096
00097
00098
00099
00100
00101
00102 var $_tableInfo = null;
00103
00104
00105
00106
00107
00108
00109
00110 var $validate = array();
00111
00112
00113
00114
00115
00116 var $validationErrors = array();
00117
00118
00119
00120
00121
00122
00123 var $tablePrefix = null;
00124
00125
00126
00127
00128
00129
00130 var $name = null;
00131
00132
00133
00134
00135
00136
00137 var $currentModel = null;
00138
00139
00140
00141
00142
00143
00144 var $tableToModel = array();
00145
00146
00147
00148
00149
00150
00151 var $modelToTable = array();
00152
00153
00154
00155
00156
00157
00158 var $keyToTable = array();
00159
00160
00161
00162
00163
00164
00165 var $alias = null;
00166
00167
00168
00169
00170
00171
00172 var $logTransactions = false;
00173
00174
00175
00176
00177
00178
00179 var $transactional = false;
00180
00181
00182
00183
00184
00185
00186
00187 var $cacheQueries = true;
00188
00189
00190
00191
00192
00193
00194 var $belongsTo = array();
00195
00196
00197
00198
00199
00200
00201 var $hasOne = array();
00202
00203
00204
00205
00206
00207
00208 var $hasMany = array();
00209
00210
00211
00212
00213
00214
00215 var $hasAndBelongsToMany = array();
00216
00217
00218
00219
00220
00221
00222 var $recursive = 1;
00223
00224
00225
00226
00227
00228 var $whitelist = array();
00229
00230
00231
00232
00233
00234 var $cacheSources = true;
00235
00236
00237
00238
00239
00240
00241 var $__associationKeys = array('belongsTo' => array('className', 'foreignKey', 'conditions', 'fields', 'order', 'counterCache'),
00242 'hasOne' => array('className', 'foreignKey','conditions', 'fields','order', 'dependent'),
00243 'hasMany' => array('className', 'foreignKey', 'conditions', 'fields', 'order', 'limit', 'offset', 'dependent', 'exclusive', 'finderQuery', 'counterQuery'),
00244 'hasAndBelongsToMany' => array('className', 'joinTable', 'foreignKey', 'associationForeignKey', 'conditions', 'fields', 'order', 'limit', 'offset', 'unique', 'finderQuery', 'deleteQuery', 'insertQuery'));
00245
00246
00247
00248
00249
00250
00251 var $__associations = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
00252
00253
00254
00255
00256
00257
00258 var $__insertID = null;
00259
00260
00261
00262
00263
00264
00265 var $__numRows = null;
00266
00267
00268
00269
00270
00271
00272 var $__affectedRows = null;
00273
00274
00275
00276
00277
00278
00279 var $__backAssociation = array();
00280
00281
00282
00283
00284
00285
00286
00287 function __construct($id = false, $table = null, $ds = null) {
00288 parent::__construct();
00289
00290 if (is_array($id) && isset($id['name'])) {
00291 $options = array_merge(array('id' => false, 'table' => null, 'ds' => null, 'alias' => null), $id);
00292 list($id, $table, $ds) = array($options['id'], $options['table'], $options['ds']);
00293 $this->name = $options['name'];
00294 }
00295
00296 if ($this->name === null) {
00297 $this->name = get_class($this);
00298 }
00299
00300 if ($this->primaryKey === null) {
00301 $this->primaryKey = 'id';
00302 }
00303
00304 if (isset($options['alias']) || !empty($options['alias'])) {
00305 $this->alias = $options['alias'];
00306 unset($options);
00307 } else {
00308 $this->alias = $this->name;
00309 }
00310 ClassRegistry::addObject($this->alias, $this);
00311
00312 $this->id = $id;
00313 unset($id);
00314
00315 if ($table === false) {
00316 $this->useTable = false;
00317 } elseif ($table) {
00318 $this->useTable = $table;
00319 }
00320
00321 if ($this->useTable !== false) {
00322 $this->setDataSource($ds);
00323
00324 if ($this->useTable === null) {
00325 $this->useTable = Inflector::tableize($this->name);
00326 }
00327
00328 if (in_array('settableprefix', get_class_methods($this))) {
00329 $this->setTablePrefix();
00330 }
00331
00332 $this->setSource($this->useTable);
00333 $this->__createLinks();
00334
00335 if ($this->displayField == null) {
00336 if ($this->hasField('title')) {
00337 $this->displayField = 'title';
00338 }
00339
00340 if ($this->hasField('name')) {
00341 $this->displayField = 'name';
00342 }
00343
00344 if ($this->displayField == null) {
00345 $this->displayField = $this->primaryKey;
00346 }
00347 }
00348 }
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 function __call($method, $params, &$return) {
00364 $db =& ConnectionManager::getDataSource($this->useDbConfig);
00365 $return = $db->query($method, $params, $this);
00366 if (isset($this->__backAssociation)) {
00367 $this->__resetAssociations();
00368 }
00369 return true;
00370 }
00371
00372
00373
00374
00375
00376
00377
00378 function bindModel($params) {
00379 foreach ($params as $assoc => $model) {
00380 if(!isset($this->__backAssociation[$assoc])) {
00381 $this->__backAssociation[$assoc] = $this->{$assoc};
00382 }
00383
00384 foreach ($model as $key => $value) {
00385 $assocName = $key;
00386
00387 if (is_numeric($key)) {
00388 $assocName = $value;
00389 $value = array();
00390 }
00391 $modelName = $assocName;
00392 $this->{$assoc}[$assocName] = $value;
00393 }
00394 }
00395 $this->__createLinks();
00396 return true;
00397 }
00398
00399
00400
00401
00402
00403
00404
00405 function unbindModel($params) {
00406 foreach ($params as $assoc => $models) {
00407 if(!isset($this->__backAssociation[$assoc])) {
00408 $this->__backAssociation[$assoc] = $this->{$assoc};
00409 }
00410
00411 foreach ($models as $model) {
00412 $this->__backAssociation = array_merge($this->__backAssociation, $this->{$assoc});
00413 unset ($this->{$assoc}[$model]);
00414 }
00415 }
00416 return true;
00417 }
00418
00419
00420
00421
00422
00423 function __createLinks() {
00424
00425 foreach ($this->__associations as $type) {
00426 if (!is_array($this->{$type})) {
00427 $this->{$type} = explode(',', $this->{$type});
00428
00429 foreach ($this->{$type} as $i => $className) {
00430 $className = trim($className);
00431 unset ($this->{$type}[$i]);
00432 $this->{$type}[$className] = array();
00433 }
00434 }
00435
00436 foreach ($this->{$type} as $assoc => $value) {
00437 if (is_numeric($assoc)) {
00438 unset ($this->{$type}[$assoc]);
00439 $assoc = $value;
00440 $value = array();
00441 $this->{$type}[$assoc] = $value;
00442 }
00443
00444 $className = $assoc;
00445
00446 if (isset($value['className']) && !empty($value['className'])) {
00447 $className = $value['className'];
00448 }
00449 $this->__constructLinkedModel($assoc, $className);
00450 }
00451 }
00452
00453 foreach ($this->__associations as $type) {
00454 $this->__generateAssociation($type);
00455 }
00456 }
00457
00458
00459
00460
00461
00462
00463
00464
00465 function __constructLinkedModel($assoc, $className) {
00466 if(empty($className)) {
00467 $className = $assoc;
00468 }
00469
00470 if (!class_exists($className)) {
00471 loadModel($className);
00472 }
00473 $colKey = Inflector::underscore($className);
00474 $model = array('name' => $className, 'alias' => $assoc);
00475
00476 if (ClassRegistry::isKeySet($colKey)) {
00477 $this->{$assoc} =& ClassRegistry::getObject($colKey);
00478 $this->{$className} =& $this->{$assoc};
00479 } else {
00480 $this->{$assoc} =& new $className($model);
00481 $this->{$className} =& $this->{$assoc};
00482 }
00483 $this->tableToModel[$this->{$assoc}->table] = $className;
00484 $this->modelToTable[$assoc] = $this->{$assoc}->table;
00485 }
00486
00487
00488
00489
00490
00491
00492 function __generateAssociation($type) {
00493 foreach ($this->{$type}as $assocKey => $assocData) {
00494 $class = $assocKey;
00495
00496 foreach ($this->__associationKeys[$type] as $key) {
00497 if (!isset($this->{$type}[$assocKey][$key]) || $this->{$type}[$assocKey][$key] == null) {
00498 $data = '';
00499
00500 switch($key) {
00501 case 'fields':
00502 $data = '';
00503 break;
00504
00505 case 'foreignKey':
00506 $data = Inflector::singularize($this->table) . '_id';
00507
00508 if ($type == 'belongsTo') {
00509 $data = Inflector::singularize($this->{$class}->table) . '_id';
00510 }
00511 break;
00512
00513 case 'associationForeignKey':
00514 $data = Inflector::singularize($this->{$class}->table) . '_id';
00515 break;
00516
00517 case 'joinTable':
00518 $tables = array($this->table, $this->{$class}->table);
00519 sort ($tables);
00520 $data = $tables[0] . '_' . $tables[1];
00521 break;
00522
00523 case 'className':
00524 $data = $class;
00525 break;
00526 }
00527
00528 $this->{$type}[$assocKey][$key] = $data;
00529 }
00530
00531 if ($key == 'foreignKey' && !isset($this->keyToTable[$this->{$type}[$assocKey][$key]])) {
00532 $this->keyToTable[$this->{$type}[$assocKey][$key]][0] = $this->{$class}->table;
00533 $this->keyToTable[$this->{$type}[$assocKey][$key]][1] = $this->{$class}->alias;
00534 }
00535 }
00536 }
00537 }
00538
00539
00540
00541
00542
00543
00544 function setSource($tableName) {
00545 $this->setDataSource($this->useDbConfig);
00546 $db =& ConnectionManager::getDataSource($this->useDbConfig);
00547 $db->cacheSources = $this->cacheSources;
00548
00549 if ($db->isInterfaceSupported('listSources')) {
00550 $sources = $db->listSources();
00551 if (is_array($sources) && !in_array(low($this->tablePrefix . $tableName), array_map('low', $sources))) {
00552 return $this->cakeError('missingTable', array(array(
00553 'className' => $this->alias,
00554 'table' => $this->tablePrefix . $tableName)));
00555
00556 }
00557 $this->_tableInfo = null;
00558 }
00559 $this->table = $this->useTable = $tableName;
00560 $this->tableToModel[$this->table] = $this->alias;
00561 $this->loadInfo();
00562 }
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 function set($one, $two = null) {
00577 if (is_array($one)) {
00578 if (countdim($one) == 1) {
00579 $data = array($this->alias => $one);
00580 } else {
00581 $data = $one;
00582 }
00583 } else {
00584 $data = array($this->alias => array($one => $two));
00585 }
00586
00587 foreach ($data as $n => $v) {
00588 if (is_array($v)) {
00589
00590 foreach ($v as $x => $y) {
00591 if (empty($this->whitelist) || (in_array($x, $this->whitelist) || $n !== $this->alias)) {
00592 if (isset($this->validationErrors[$x])) {
00593 unset ($this->validationErrors[$x]);
00594 }
00595
00596 if ($n == $this->name || is_array($y)) {
00597 if ($x === $this->primaryKey) {
00598 $this->id = $y;
00599 }
00600 $this->data[$n][$x] = $y;
00601 }
00602 }
00603 }
00604 }
00605 }
00606 return $data;
00607 }
00608
00609
00610
00611
00612
00613
00614 function loadInfo() {
00615 $db =& ConnectionManager::getDataSource($this->useDbConfig);
00616 $db->cacheSources = $this->cacheSources;
00617
00618 if (!is_object($this->_tableInfo) && $db->isInterfaceSupported('describe') && $this->useTable !== false) {
00619 $info = new Set($db->describe($this));
00620
00621 foreach($info->value as $field => $value) {
00622 $fields[] = am(array('name'=> $field), $value);
00623 }
00624 unset($info);
00625 $this->_tableInfo = new Set($fields);
00626 } elseif ($this->useTable === false) {
00627 $this->_tableInfo = new Set();
00628 }
00629 return $this->_tableInfo;
00630 }
00631
00632
00633
00634
00635
00636
00637 function getColumnTypes() {
00638 $columns = $this->loadInfo();
00639 $columns = $columns->value;
00640 $db =& ConnectionManager::getDataSource($this->useDbConfig);
00641 $cols = array();
00642
00643 foreach ($columns as $col) {
00644 $cols[$col['name']] = $col['type'];
00645 }
00646 return $cols;
00647 }
00648
00649
00650
00651
00652
00653
00654
00655 function getColumnType($column) {
00656 $columns = $this->loadInfo();
00657 $columns = $columns->value;
00658 $cols = array();
00659
00660 foreach ($columns as $col) {
00661 if ($col['name'] == $column) {
00662 return $col['type'];
00663 }
00664 }
00665 return null;
00666 }
00667
00668
00669
00670
00671
00672
00673
00674 function hasField($name) {
00675 if (is_array($name)) {
00676 foreach ($name as $n) {
00677 if ($this->hasField($n)) {
00678 return $n;
00679 }
00680 }
00681 return false;
00682 }
00683
00684 if (empty($this->_tableInfo)) {
00685 $this->loadInfo();
00686 }
00687
00688 if ($this->_tableInfo != null) {
00689 return in_array($name, $this->_tableInfo->extract('{n}.name'));
00690 }
00691 return false;
00692 }
00693
00694
00695
00696
00697
00698
00699 function create() {
00700 $this->id = false;
00701 unset ($this->data);
00702 $this->data = $this->validationErrors = array();
00703 return true;
00704 }
00705
00706
00707
00708 function setId($id) {
00709 $this->id = $id;
00710 }
00711
00712
00713
00714
00715 function findBySql($sql) {
00716 return $this->query($sql);
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726 function read($fields = null, $id = null) {
00727 $this->validationErrors = array();
00728
00729 if ($id != null) {
00730 $this->id = $id;
00731 }
00732
00733 $id = $this->id;
00734
00735 if (is_array($this->id)) {
00736 $id = $this->id[0];
00737 }
00738
00739 if ($this->id !== null && $this->id !== false) {
00740 $db =& ConnectionManager::getDataSource($this->useDbConfig);
00741 $field = $db->name($this->alias) . '.' . $db->name($this->primaryKey);
00742 return $this->find($field . ' = ' . $db->value($id, $this->getColumnType($this->primaryKey)), $fields);
00743 } else {
00744 return false;
00745 }
00746 }
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756 function field($name, $conditions = null, $order = null) {
00757 if ($conditions === null && $this->id !== false) {
00758 $conditions = array($this->alias . '.' . $this->primaryKey => $this->id);
00759 }
00760
00761 if ($data = $this->find($conditions, $name, $order, 0)) {
00762
00763 if (strpos($name, '.') === false) {
00764 if (isset($data[$this->alias][$name])) {
00765 return $data[$this->alias][$name];
00766 } else {
00767 return false;
00768 }
00769 } else {
00770 $name = explode('.', $name);
00771
00772 if (isset($data[$name[0]][$name[1]])) {
00773 return $data[$name[0]][$name[1]];
00774 } else {
00775 return false;
00776 }
00777 }
00778 } else {
00779 return false;
00780 }
00781 }
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791 function saveField($name, $value, $validate = false) {
00792 return $this->save(array($this->alias => array($name => $value)), $validate);
00793 }
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804 function save($data = null, $validate = true, $fieldList = array()) {
00805 $db =& ConnectionManager::getDataSource($this->useDbConfig);
00806 $_whitelist = $this->whitelist;
00807
00808 if (!empty($fieldList)) {
00809 $this->whitelist = $fieldList;
00810 } elseif ($fieldList === null) {
00811 $this->whitelist = array();
00812 }
00813
00814 if ($data) {
00815 if (countdim($data) == 1) {
00816 $this->set(array($this->alias => $data));
00817 } else {
00818 $this->set($data);
00819 }
00820 }
00821
00822 if ($validate && !$this->validates()) {
00823 $this->whitelist = $_whitelist;
00824 return false;
00825 }
00826
00827 if (!$this->beforeSave()) {
00828 $this->whitelist = $_whitelist;
00829 return false;
00830 }
00831 $fields = $values = array();
00832
00833 if (isset($this->data[$this->alias][$this->primaryKey]) && empty($this->data[$this->alias][$this->primaryKey])) {
00834 unset($this->data[$this->alias][$this->primaryKey]);
00835 }
00836
00837 if (count($this->data) > 1) {
00838 $weHaveMulti = true;
00839 $joined = false;
00840 } else {
00841 $weHaveMulti = false;
00842 }
00843
00844 foreach ($this->data as $n => $v) {
00845 if (isset($weHaveMulti) && isset($v[$n]) && in_array($n, array_keys($this->hasAndBelongsToMany))) {
00846 $joined[] = $v;
00847 } else {
00848 if ($n === $this->alias) {
00849 foreach (array('created', 'updated', 'modified') as $field) {
00850 if (array_key_exists($field, $v) && (empty($v[$field]) || $v[$field] === null)) {
00851 unset($v[$field]);
00852 }
00853 }
00854
00855 foreach ($v as $x => $y) {
00856 if ($this->hasField($x)) {
00857 $fields[] = $x;
00858 $values[] = $y;
00859 }
00860 }
00861 }
00862 }
00863 }
00864 $exists = $this->exists();
00865
00866 if (!$exists && $this->hasField('created') && !in_array('created', $fields)) {
00867 $fields[] = 'created';
00868 $values[] = date('Y-m-d H:i:s');
00869 }
00870
00871 if ($this->hasField('modified') && !in_array('modified', $fields)) {
00872 $fields[] = 'modified';
00873 $values[] = date('Y-m-d H:i:s');
00874 }
00875
00876 if ($this->hasField('updated') && !in_array('updated', $fields)) {
00877 $fields[] = 'updated';
00878 $values[] = date('Y-m-d H:i:s');
00879 }
00880
00881 if (!$exists) {
00882 $this->id = false;
00883 }
00884 $this->whitelist = $_whitelist;
00885
00886 if (count($fields)) {
00887 if (!empty($this->id)) {
00888 if ($db->update($this, $fields, $values)) {
00889 if (!empty($joined)) {
00890 $this->__saveMulti($joined, $this->id);
00891 }
00892
00893 $this->afterSave();
00894 $this->data = false;
00895 $this->_clearCache();
00896 return true;
00897 } else {
00898 return false;
00899 }
00900 } else {
00901 if ($db->create($this, $fields, $values)) {
00902 if (!empty($joined)) {
00903 $this->__saveMulti($joined, $this->id);
00904 }
00905
00906 $this->afterSave();
00907 $this->data = false;
00908 $this->_clearCache();
00909 $this->validationErrors = array();
00910 return true;
00911 } else {
00912 return false;
00913 }
00914 }
00915 } else {
00916 return false;
00917 }
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927 function __saveMulti($joined, $id) {
00928 $db =& ConnectionManager::getDataSource($this->useDbConfig);
00929 foreach ($joined as $x => $y) {
00930 foreach ($y as $assoc => $value) {
00931 if (isset($this->hasAndBelongsToMany[$assoc])) {
00932 $joinTable[$assoc] = $this->hasAndBelongsToMany[$assoc]['joinTable'];
00933 $mainKey[$assoc] = $this->hasAndBelongsToMany[$assoc]['foreignKey'];
00934 $keys[] = $this->hasAndBelongsToMany[$assoc]['foreignKey'];
00935 $keys[] = $this->hasAndBelongsToMany[$assoc]['associationForeignKey'];
00936 $fields[$assoc] = join(',', $keys);
00937 unset($keys);
00938
00939 foreach ($value as $update) {
00940 if (!empty($update)) {
00941 $values[] = $db->value($id, $this->getColumnType($this->primaryKey));
00942 $values[] = $db->value($update);
00943 $values = join(',', $values);
00944 $newValues[] = "({$values})";
00945 unset ($values);
00946 }
00947 }
00948
00949 if (!empty($newValues)) {
00950 $newValue[$assoc] = $newValues;
00951 unset($newValues);
00952 } else {
00953 $newValue[$assoc] = array();
00954 }
00955 }
00956 }
00957 }
00958
00959 if (isset($joinTable)) {
00960 $total = count($joinTable);
00961
00962 if (is_array($newValue)) {
00963 foreach ($newValue as $loopAssoc => $val) {
00964 $db =& ConnectionManager::getDataSource($this->useDbConfig);
00965 $table = $db->name($db->fullTableName($joinTable[$loopAssoc]));
00966 $db->query("DELETE FROM {$table} WHERE {$mainKey[$loopAssoc]} = '{$id}'");
00967
00968 if (!empty($newValue[$loopAssoc])) {
00969 $secondCount = count($newValue[$loopAssoc]);
00970 for ($x = 0; $x < $secondCount; $x++) {
00971 $db->query("INSERT INTO {$table} ({$fields[$loopAssoc]}) VALUES {$newValue[$loopAssoc][$x]}");
00972 }
00973 }
00974 }
00975 }
00976 }
00977 }
00978
00979
00980
00981
00982
00983
00984
00985
00986 function remove($id = null, $cascade = true) {
00987 return $this->del($id, $cascade);
00988 }
00989
00990
00991
00992
00993
00994
00995
00996 function del($id = null, $cascade = true) {
00997 if ($id) {
00998 $this->id = $id;
00999 }
01000 $id = $this->id;
01001
01002 if ($this->exists() && $this->beforeDelete()) {
01003 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01004
01005 $this->_deleteMulti($id);
01006 $this->_deleteHasMany($id, $cascade);
01007 $this->_deleteHasOne($id, $cascade);
01008 $this->id = $id;
01009
01010 if ($db->delete($this)) {
01011 $this->afterDelete();
01012 $this->_clearCache();
01013 $this->id = false;
01014 return true;
01015 }
01016 }
01017
01018 return false;
01019 }
01020
01021
01022
01023
01024
01025
01026
01027 function delete($id = null, $cascade = true) {
01028 return $this->del($id, $cascade);
01029 }
01030
01031
01032
01033
01034
01035
01036
01037 function _deleteHasMany($id, $cascade) {
01038 if (!empty($this->__backAssociation)) {
01039 $savedAssociatons = $this->__backAssociation;
01040 $this->__backAssociation = array();
01041 }
01042 foreach ($this->hasMany as $assoc => $data) {
01043 if ($data['dependent'] === true && $cascade === true) {
01044 $model =& $this->{$data['className']};
01045 $field = $model->escapeField($data['foreignKey']);
01046 $model->recursive = 0;
01047 $records = $model->findAll("$field = '$id'", $model->primaryKey, null, null);
01048
01049 if ($records != false) {
01050 foreach ($records as $record) {
01051 $model->del($record[$data['className']][$model->primaryKey]);
01052 }
01053 }
01054 }
01055 }
01056 if (isset($savedAssociatons)) {
01057 $this->__backAssociation = $savedAssociatons;
01058 }
01059 }
01060
01061
01062
01063
01064
01065
01066
01067 function _deleteHasOne($id, $cascade) {
01068 if (!empty($this->__backAssociation)) {
01069 $savedAssociatons = $this->__backAssociation;
01070 $this->__backAssociation = array();
01071 }
01072 foreach ($this->hasOne as $assoc => $data) {
01073 if ($data['dependent'] === true && $cascade === true) {
01074 $model =& $this->{$data['className']};
01075 $field = $model->escapeField($data['foreignKey']);
01076 $model->recursive = 0;
01077 $records = $model->findAll("$field = '$id'", $model->primaryKey, null, null);
01078
01079 if ($records != false) {
01080 foreach ($records as $record) {
01081 $model->del($record[$data['className']][$model->primaryKey]);
01082 }
01083 }
01084 }
01085 }
01086 if (isset($savedAssociatons)) {
01087 $this->__backAssociation = $savedAssociatons;
01088 }
01089 }
01090
01091
01092
01093
01094
01095
01096
01097 function _deleteMulti($id) {
01098 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01099 foreach ($this->hasAndBelongsToMany as $assoc => $data) {
01100 $db->execute("DELETE FROM " . $db->name($db->fullTableName($data['joinTable'])) . " WHERE " . $db->name($data['foreignKey']) . " = '{$id}'");
01101 }
01102 }
01103
01104
01105
01106
01107
01108
01109 function exists() {
01110 if ($this->id) {
01111 $id = $this->id;
01112
01113 if (is_array($id)) {
01114 $id = $id[0];
01115 }
01116
01117 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01118 return $db->hasAny($this, array($this->primaryKey => $id));
01119 }
01120 return false;
01121 }
01122
01123
01124
01125
01126
01127
01128
01129 function hasAny($conditions = null) {
01130 return ($this->findCount($conditions) != false);
01131 }
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144 function find($conditions = null, $fields = null, $order = null, $recursive = null) {
01145 $data = $this->findAll($conditions, $fields, $order, 1, null, $recursive);
01146
01147 if (empty($data[0])) {
01148 return false;
01149 }
01150
01151 return $data[0];
01152 }
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167 function findAll($conditions = null, $fields = null, $order = null, $limit = null, $page = 1, $recursive = null) {
01168
01169 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01170 $this->id = $this->getID();
01171 $offset = null;
01172
01173 if ($page > 1 && $limit != null) {
01174 $offset = ($page - 1) * $limit;
01175 }
01176
01177 if ($order == null) {
01178 $order = array();
01179 } else {
01180 $order = array($order);
01181 }
01182
01183 $queryData = array('conditions' => $conditions,
01184 'fields' => $fields,
01185 'joins' => array(),
01186 'limit' => $limit,
01187 'offset' => $offset,
01188 'order' => $order
01189 );
01190
01191 $ret = $this->beforeFind($queryData);
01192 if (is_array($ret)) {
01193 $queryData = $ret;
01194 } elseif ($ret === false) {
01195 return null;
01196 }
01197
01198 $return = $this->afterFind($db->read($this, $queryData, $recursive));
01199
01200 if (!empty($this->__backAssociation)) {
01201 $this->__resetAssociations();
01202 }
01203
01204 return $return;
01205 }
01206
01207
01208
01209
01210
01211
01212
01213
01214 function __resetAssociations() {
01215 foreach ($this->__associations as $type) {
01216 if (isset($this->__backAssociation[$type])) {
01217 $this->{$type} = $this->__backAssociation[$type];
01218 }
01219 }
01220
01221 $this->__backAssociation = array();
01222 return true;
01223 }
01224
01225
01226
01227
01228
01229
01230
01231 function execute($data) {
01232 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01233 $data = $db->fetchAll($data, $this->cacheQueries);
01234
01235 foreach ($data as $key => $value) {
01236 foreach ($this->tableToModel as $key1 => $value1) {
01237 if (isset($data[$key][$key1])) {
01238 $newData[$key][$value1] = $data[$key][$key1];
01239 }
01240 }
01241 }
01242
01243 if (!empty($newData)) {
01244 return $newData;
01245 }
01246
01247 return $data;
01248 }
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258 function findCount($conditions = null, $recursive = 0) {
01259 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01260
01261 list($data) = $this->findAll($conditions, 'COUNT(*) AS ' . $db->name('count'), null, null, 1, $recursive);
01262
01263 if (isset($data[0]['count'])) {
01264 return $data[0]['count'];
01265 } elseif (isset($data[$this->alias]['count'])) {
01266 return $data[$this->alias]['count'];
01267 }
01268
01269 return false;
01270 }
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282 function findAllThreaded($conditions = null, $fields = null, $sort = null) {
01283 return $this->__doThread(Model::findAll($conditions, $fields, $sort), null);
01284 }
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294 function __doThread($data, $root) {
01295 $out = array();
01296 $sizeOf = sizeof($data);
01297
01298 for ($ii = 0; $ii < $sizeOf; $ii++) {
01299 if (($data[$ii][$this->alias]['parent_id'] == $root) || (($root === null) && ($data[$ii][$this->alias]['parent_id'] == '0'))) {
01300 $tmp = $data[$ii];
01301
01302 if (isset($data[$ii][$this->alias][$this->primaryKey])) {
01303 $tmp['children'] = $this->__doThread($data, $data[$ii][$this->alias][$this->primaryKey]);
01304 } else {
01305 $tmp['children'] = null;
01306 }
01307
01308 $out[] = $tmp;
01309 }
01310 }
01311
01312 return $out;
01313 }
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324 function findNeighbours($conditions = null, $field, $value) {
01325 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01326
01327 if (!is_null($conditions)) {
01328 $conditions = $conditions . ' AND ';
01329 }
01330
01331 @list($prev) = Model::findAll($conditions . $field . ' < ' . $db->value($value), $field, $field . ' DESC', 1, null, 0);
01332 @list($next) = Model::findAll($conditions . $field . ' > ' . $db->value($value), $field, $field . ' ASC', 1, null, 0);
01333
01334 if (!isset($prev)) {
01335 $prev = null;
01336 }
01337
01338 if (!isset($next)) {
01339 $next = null;
01340 }
01341
01342 return array('prev' => $prev, 'next' => $next);
01343 }
01344
01345
01346
01347
01348
01349
01350
01351 function query() {
01352 $params = func_get_args();
01353 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01354 return call_user_func_array(array(&$db, 'query'), $params);
01355 }
01356
01357
01358
01359
01360
01361
01362
01363 function validates($data = array()) {
01364 $errors = $this->invalidFields($data);
01365 return count($errors) == 0;
01366 }
01367
01368
01369
01370
01371
01372
01373
01374 function invalidFields($data = array()) {
01375 if (empty($data)) {
01376 $data = $this->data;
01377 }
01378
01379 if (!$this->beforeValidate()) {
01380 return $this->validationErrors;
01381 }
01382
01383 if (!isset($this->validate)) {
01384 return $this->validationErrors;
01385 }
01386
01387 if (!empty($data)) {
01388 $data = $data;
01389 } elseif (isset($this->data)) {
01390 $data = $this->data;
01391 }
01392
01393 if (isset($data[$this->alias])) {
01394 $data = $data[$this->alias];
01395 }
01396
01397 foreach ($this->validate as $field_name => $validator) {
01398 if (isset($data[$field_name]) && !preg_match($validator, $data[$field_name])) {
01399 $this->invalidate($field_name);
01400 }
01401 }
01402 return $this->validationErrors;
01403 }
01404
01405
01406
01407
01408
01409
01410
01411 function invalidate($field) {
01412 if (!is_array($this->validationErrors)) {
01413 $this->validationErrors = array();
01414 }
01415 $this->validationErrors[$field] = 1;
01416 }
01417
01418
01419
01420
01421
01422
01423
01424 function isForeignKey($field) {
01425 $foreignKeys = array();
01426
01427 if (count($this->belongsTo)) {
01428 foreach ($this->belongsTo as $assoc => $data) {
01429 $foreignKeys[] = $data['foreignKey'];
01430 }
01431 }
01432 return (bool)(in_array($field, $foreignKeys));
01433 }
01434
01435
01436
01437
01438
01439
01440 function getDisplayField() {
01441 return $this->displayField;
01442 }
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455 function generateList($conditions = null, $order = null, $limit = null, $keyPath = null, $valuePath = null) {
01456 if ($keyPath == null && $valuePath == null && $this->hasField($this->displayField)) {
01457 $fields = array($this->primaryKey, $this->displayField);
01458 } else {
01459 $fields = null;
01460 }
01461 $recursive = $this->recursive;
01462
01463 if ($recursive >= 1) {
01464 $this->recursive = -1;
01465 }
01466 $result = $this->findAll($conditions, $fields, $order, $limit);
01467 $this->recursive = $recursive;
01468
01469 if (!$result) {
01470 return false;
01471 }
01472
01473 if ($keyPath == null) {
01474 $keyPath = '{n}.' . $this->alias . '.' . $this->primaryKey;
01475 }
01476
01477 if ($valuePath == null) {
01478 $valuePath = '{n}.' . $this->alias . '.' . $this->displayField;
01479 }
01480
01481 $keys = Set::extract($result, $keyPath);
01482 $vals = Set::extract($result, $valuePath);
01483
01484 if (!empty($keys) && !empty($vals)) {
01485 $return = array_combine($keys, $vals);
01486 return $return;
01487 }
01488 return null;
01489 }
01490
01491
01492
01493
01494
01495
01496
01497 function escapeField($field) {
01498 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01499 return $db->name($this->alias) . '.' . $db->name($field);
01500 }
01501
01502
01503
01504
01505
01506
01507
01508 function getID($list = 0) {
01509 if (!is_array($this->id)) {
01510 return $this->id;
01511 }
01512
01513 if (count($this->id) == 0) {
01514 return false;
01515 }
01516
01517 if (isset($this->id[$list])) {
01518 return $this->id[$list];
01519 }
01520
01521 foreach ($this->id as $id) {
01522 return $id;
01523 }
01524
01525 return false;
01526 }
01527
01528
01529
01530
01531
01532
01533 function getLastInsertID() {
01534 return $this->getInsertID();
01535 }
01536
01537
01538
01539
01540
01541
01542 function getInsertID() {
01543 return $this->__insertID;
01544 }
01545
01546
01547
01548
01549
01550
01551 function setInsertID($id) {
01552 $this->__insertID = $id;
01553 }
01554
01555
01556
01557
01558
01559
01560 function getNumRows() {
01561 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01562 return $db->lastNumRows();
01563 }
01564
01565
01566
01567
01568
01569
01570 function getAffectedRows() {
01571 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01572 return $db->lastAffected();
01573 }
01574
01575
01576
01577
01578
01579
01580
01581 function setDataSource($dataSource = null) {
01582 if ($dataSource != null) {
01583 $this->useDbConfig = $dataSource;
01584 }
01585 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01586
01587 if (!empty($db->config['prefix']) && $this->tablePrefix === null) {
01588 $this->tablePrefix = $db->config['prefix'];
01589 }
01590
01591 if (empty($db) || $db == null || !is_object($db)) {
01592 return $this->cakeError('missingConnection', array(array('className' => $this->alias)));
01593 }
01594 }
01595
01596
01597
01598
01599
01600
01601
01602 function beforeFind(&$queryData) {
01603 return true;
01604 }
01605
01606
01607
01608
01609
01610
01611
01612 function afterFind($results) {
01613 return $results;
01614 }
01615
01616
01617
01618
01619
01620
01621 function beforeSave() {
01622 return true;
01623 }
01624
01625
01626
01627
01628
01629
01630 function afterSave() {
01631 return true;
01632 }
01633
01634
01635
01636
01637
01638
01639 function beforeDelete() {
01640 return true;
01641 }
01642
01643
01644
01645
01646
01647
01648 function afterDelete() {
01649 return true;
01650 }
01651
01652
01653
01654
01655
01656
01657 function beforeValidate() {
01658 return true;
01659 }
01660
01661
01662
01663
01664
01665 function onError() {
01666 }
01667
01668
01669
01670
01671
01672
01673
01674
01675 function _clearCache($type = null) {
01676 if ($type === null) {
01677 if (defined('CACHE_CHECK') && CACHE_CHECK === true) {
01678 $assoc[] = strtolower(Inflector::pluralize($this->alias));
01679
01680 foreach ($this->__associations as $key => $association) {
01681 foreach ($this->$association as $key => $className) {
01682 $check = strtolower(Inflector::pluralize($className['className']));
01683
01684 if (!in_array($check, $assoc)) {
01685 $assoc[] = strtolower(Inflector::pluralize($className['className']));
01686 }
01687 }
01688 }
01689 clearCache($assoc);
01690 return true;
01691 }
01692 } else {
01693
01694 }
01695 }
01696
01697
01698
01699
01700
01701
01702 function __sleep() {
01703 $return = array_keys(get_object_vars($this));
01704 return $return;
01705 }
01706
01707
01708
01709
01710
01711
01712 function __wakeup() {
01713 }
01714 }
01715
01716 overload ('Model');
01717
01718
01719 ?>