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