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 App::import('Core', array('ClassRegistry', 'Overloadable', 'Validation', 'Behavior', 'ConnectionManager', 'Set', 'String'));
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 class Model extends Overloadable {
00044
00045
00046
00047
00048
00049
00050
00051 var $useDbConfig = 'default';
00052
00053
00054
00055
00056
00057
00058
00059 var $useTable = null;
00060
00061
00062
00063
00064
00065
00066
00067 var $displayField = null;
00068
00069
00070
00071
00072
00073
00074
00075 var $id = false;
00076
00077
00078
00079
00080
00081
00082
00083 var $data = array();
00084
00085
00086
00087
00088
00089
00090 var $table = false;
00091
00092
00093
00094
00095
00096
00097
00098 var $primaryKey = null;
00099
00100
00101
00102
00103
00104
00105
00106 var $_schema = null;
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 var $validate = array();
00117
00118
00119
00120
00121
00122
00123
00124 var $validationErrors = array();
00125
00126
00127
00128
00129
00130
00131
00132 var $tablePrefix = null;
00133
00134
00135
00136
00137
00138
00139
00140 var $name = null;
00141
00142
00143
00144
00145
00146
00147 var $alias = null;
00148
00149
00150
00151
00152
00153
00154 var $tableToModel = array();
00155
00156
00157
00158
00159
00160
00161 var $logTransactions = false;
00162
00163
00164
00165
00166
00167
00168 var $transactional = false;
00169
00170
00171
00172
00173
00174
00175
00176
00177 var $cacheQueries = false;
00178
00179
00180
00181
00182
00183
00184
00185 var $belongsTo = array();
00186
00187
00188
00189
00190
00191
00192
00193 var $hasOne = array();
00194
00195
00196
00197
00198
00199
00200
00201 var $hasMany = array();
00202
00203
00204
00205
00206
00207
00208
00209 var $hasAndBelongsToMany = array();
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 var $actsAs = null;
00221
00222
00223
00224
00225
00226
00227 var $Behaviors = null;
00228
00229
00230
00231
00232
00233
00234 var $whitelist = array();
00235
00236
00237
00238
00239
00240
00241 var $cacheSources = true;
00242
00243
00244
00245
00246
00247
00248 var $findQueryType = null;
00249
00250
00251
00252
00253
00254
00255
00256
00257 var $recursive = 1;
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 var $order = null;
00269
00270
00271
00272
00273
00274
00275 var $__exists = null;
00276
00277
00278
00279
00280
00281
00282 var $__associationKeys = array(
00283 'belongsTo' => array('className', 'foreignKey', 'conditions', 'fields', 'order', 'counterCache'),
00284 'hasOne' => array('className', 'foreignKey','conditions', 'fields','order', 'dependent'),
00285 'hasMany' => array('className', 'foreignKey', 'conditions', 'fields', 'order', 'limit', 'offset', 'dependent', 'exclusive', 'finderQuery', 'counterQuery'),
00286 'hasAndBelongsToMany' => array('className', 'joinTable', 'with', 'foreignKey', 'associationForeignKey', 'conditions', 'fields', 'order', 'limit', 'offset', 'unique', 'finderQuery', 'deleteQuery', 'insertQuery')
00287 );
00288
00289
00290
00291
00292
00293
00294 var $__associations = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
00295
00296
00297
00298
00299
00300
00301 var $__backAssociation = array();
00302
00303
00304
00305
00306
00307
00308 var $__insertID = null;
00309
00310
00311
00312
00313
00314
00315 var $__numRows = null;
00316
00317
00318
00319
00320
00321
00322 var $__affectedRows = null;
00323
00324
00325
00326
00327
00328
00329 var $_findMethods = array(
00330 'all' => true, 'first' => true, 'count' => true,
00331 'neighbors' => true, 'list' => true, 'threaded' => true
00332 );
00333
00334
00335
00336
00337
00338
00339
00340 function __construct($id = false, $table = null, $ds = null) {
00341 parent::__construct();
00342
00343 if (is_array($id)) {
00344 extract(array_merge(
00345 array(
00346 'id' => $this->id, 'table' => $this->useTable, 'ds' => $this->useDbConfig,
00347 'name' => $this->name, 'alias' => $this->alias
00348 ),
00349 $id
00350 ));
00351 }
00352
00353 if ($this->name === null) {
00354 $this->name = (isset($name) ? $name : get_class($this));
00355 }
00356
00357 if ($this->alias === null) {
00358 $this->alias = (isset($alias) ? $alias : $this->name);
00359 }
00360
00361 if ($this->primaryKey === null) {
00362 $this->primaryKey = 'id';
00363 }
00364
00365 ClassRegistry::addObject($this->alias, $this);
00366
00367 $this->id = $id;
00368 unset($id);
00369
00370 if ($table === false) {
00371 $this->useTable = false;
00372 } elseif ($table) {
00373 $this->useTable = $table;
00374 }
00375
00376 if ($ds !== null) {
00377 $this->useDbConfig = $ds;
00378 }
00379
00380 if (is_subclass_of($this, 'AppModel')) {
00381 $appVars = get_class_vars('AppModel');
00382 $merge = array('_findMethods');
00383
00384 if ($this->actsAs !== null || $this->actsAs !== false) {
00385 $merge[] = 'actsAs';
00386 }
00387 $parentClass = get_parent_class($this);
00388 if (strtolower($parentClass) !== 'appmodel') {
00389 $parentVars = get_class_vars($parentClass);
00390 foreach ($merge as $var) {
00391 if (isset($parentVars[$var]) && !empty($parentVars[$var])) {
00392 $appVars[$var] = Set::merge($appVars[$var], $parentVars[$var]);
00393 }
00394 }
00395 }
00396
00397 foreach ($merge as $var) {
00398 if (isset($appVars[$var]) && !empty($appVars[$var]) && is_array($this->{$var})) {
00399 $this->{$var} = Set::merge($appVars[$var], $this->{$var});
00400 }
00401 }
00402 }
00403 $this->Behaviors = new BehaviorCollection();
00404
00405 if ($this->useTable !== false) {
00406 $this->setDataSource($ds);
00407
00408 if ($this->useTable === null) {
00409 $this->useTable = Inflector::tableize($this->name);
00410 }
00411 if (method_exists($this, 'setTablePrefix')) {
00412 $this->setTablePrefix();
00413 }
00414 $this->setSource($this->useTable);
00415
00416 if ($this->displayField == null) {
00417 $this->displayField = $this->hasField(array('title', 'name', $this->primaryKey));
00418 }
00419 } elseif ($this->table === false) {
00420 $this->table = Inflector::tableize($this->name);
00421 }
00422 $this->__createLinks();
00423 $this->Behaviors->init($this->alias, $this->actsAs);
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 function call__($method, $params) {
00435 $result = $this->Behaviors->dispatchMethod($this, $method, $params);
00436
00437 if ($result !== array('unhandled')) {
00438 return $result;
00439 }
00440 $db =& ConnectionManager::getDataSource($this->useDbConfig);
00441 $return = $db->query($method, $params, $this);
00442
00443 if (!PHP5) {
00444 $this->resetAssociations();
00445 }
00446 return $return;
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 function bind($model, $options = array(), $permanent = true) {
00463 if (!is_array($model)) {
00464 $model = array($model => $options);
00465 }
00466
00467 foreach ($model as $name => $options) {
00468 if (isset($options['type'])) {
00469 $assoc = $options['type'];
00470 } elseif (isset($options[0])) {
00471 $assoc = $options[0];
00472 } else {
00473 $assoc = 'belongsTo';
00474 }
00475
00476 if (!$permanent) {
00477 $this->__backAssociation[$assoc] = $this->{$assoc};
00478 }
00479 foreach ($model as $key => $value) {
00480 $assocName = $modelName = $key;
00481
00482 if (isset($this->{$assoc}[$assocName])) {
00483 $this->{$assoc}[$assocName] = array_merge($this->{$assoc}[$assocName], $options);
00484 } else {
00485 if (isset($value['className'])) {
00486 $modelName = $value['className'];
00487 }
00488
00489 $this->__constructLinkedModel($assocName, $modelName);
00490 $this->{$assoc}[$assocName] = $model[$assocName];
00491 $this->__generateAssociation($assoc);
00492 }
00493 unset($this->{$assoc}[$assocName]['type'], $this->{$assoc}[$assocName][0]);
00494 }
00495 }
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 function bindModel($params, $reset = true) {
00516 foreach ($params as $assoc => $model) {
00517 if ($reset === true) {
00518 $this->__backAssociation[$assoc] = $this->{$assoc};
00519 }
00520
00521 foreach ($model as $key => $value) {
00522 $assocName = $key;
00523
00524 if (is_numeric($key)) {
00525 $assocName = $value;
00526 $value = array();
00527 }
00528 $modelName = $assocName;
00529 $this->{$assoc}[$assocName] = $value;
00530 }
00531 }
00532 $this->__createLinks();
00533 return true;
00534 }
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553 function unbindModel($params, $reset = true) {
00554 foreach ($params as $assoc => $models) {
00555 if ($reset === true) {
00556 $this->__backAssociation[$assoc] = $this->{$assoc};
00557 }
00558
00559 foreach ($models as $model) {
00560 $this->__backAssociation = array_merge($this->__backAssociation, $this->{$assoc});
00561 unset ($this->__backAssociation[$model]);
00562 unset ($this->{$assoc}[$model]);
00563 }
00564 }
00565 return true;
00566 }
00567
00568
00569
00570
00571
00572
00573 function __createLinks() {
00574 foreach ($this->__associations as $type) {
00575 if (!is_array($this->{$type})) {
00576 $this->{$type} = explode(',', $this->{$type});
00577
00578 foreach ($this->{$type} as $i => $className) {
00579 $className = trim($className);
00580 unset ($this->{$type}[$i]);
00581 $this->{$type}[$className] = array();
00582 }
00583 }
00584
00585 if (!empty($this->{$type})) {
00586 foreach ($this->{$type} as $assoc => $value) {
00587 $plugin = null;
00588
00589 if (is_numeric($assoc)) {
00590 unset ($this->{$type}[$assoc]);
00591 $assoc = $value;
00592 $value = array();
00593 $this->{$type}[$assoc] = $value;
00594
00595 if (strpos($assoc, '.') !== false) {
00596 $value = $this->{$type}[$assoc];
00597 unset($this->{$type}[$assoc]);
00598 list($plugin, $assoc) = explode('.', $assoc);
00599 $this->{$type}[$assoc] = $value;
00600 $plugin = $plugin . '.';
00601 }
00602 }
00603 $className = $assoc;
00604
00605 if (isset($value['className']) && !empty($value['className'])) {
00606 $className = $value['className'];
00607 if (strpos($className, '.') !== false) {
00608 list($plugin, $className) = explode('.', $className);
00609 $plugin = $plugin . '.';
00610 $this->{$type}[$assoc]['className'] = $className;
00611 }
00612 }
00613 $this->__constructLinkedModel($assoc, $plugin . $className);
00614 }
00615 $this->__generateAssociation($type);
00616 }
00617 }
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 function __constructLinkedModel($assoc, $className = null) {
00634 if (empty($className)) {
00635 $className = $assoc;
00636 }
00637
00638 if (!isset($this->{$assoc}) || $this->{$assoc}->name !== $className) {
00639 $model = array('class' => $className, 'alias' => $assoc);
00640 if (PHP5) {
00641 $this->{$assoc} = ClassRegistry::init($model);
00642 } else {
00643 $this->{$assoc} =& ClassRegistry::init($model);
00644 }
00645 if ($assoc) {
00646 $this->tableToModel[$this->{$assoc}->table] = $assoc;
00647 }
00648 }
00649 }
00650
00651
00652
00653
00654
00655
00656
00657 function __generateAssociation($type) {
00658 foreach ($this->{$type} as $assocKey => $assocData) {
00659 $class = $assocKey;
00660 $dynamicWith = false;
00661
00662 foreach ($this->__associationKeys[$type] as $key) {
00663
00664 if (!isset($this->{$type}[$assocKey][$key]) || $this->{$type}[$assocKey][$key] === null) {
00665 $data = '';
00666
00667 switch ($key) {
00668 case 'fields':
00669 $data = '';
00670 break;
00671
00672 case 'foreignKey':
00673 $data = (($type == 'belongsTo') ? Inflector::underscore($assocKey) : Inflector::singularize($this->table)) . '_id';
00674 break;
00675
00676 case 'associationForeignKey':
00677 $data = Inflector::singularize($this->{$class}->table) . '_id';
00678 break;
00679
00680 case 'with':
00681 $data = Inflector::camelize(Inflector::singularize($this->{$type}[$assocKey]['joinTable']));
00682 $dynamicWith = true;
00683 break;
00684
00685 case 'joinTable':
00686 $tables = array($this->table, $this->{$class}->table);
00687 sort ($tables);
00688 $data = $tables[0] . '_' . $tables[1];
00689 break;
00690
00691 case 'className':
00692 $data = $class;
00693 break;
00694
00695 case 'unique':
00696 $data = true;
00697 break;
00698 }
00699 $this->{$type}[$assocKey][$key] = $data;
00700 }
00701 }
00702
00703 if (!empty($this->{$type}[$assocKey]['with'])) {
00704 $joinClass = $this->{$type}[$assocKey]['with'];
00705 if (is_array($joinClass)) {
00706 $joinClass = key($joinClass);
00707 }
00708 $plugin = null;
00709
00710 if (strpos($joinClass, '.') !== false) {
00711 list($plugin, $joinClass) = explode('.', $joinClass);
00712 $plugin = $plugin . '.';
00713 $this->{$type}[$assocKey]['with'] = $joinClass;
00714 }
00715
00716 if (!ClassRegistry::isKeySet($joinClass) && $dynamicWith === true) {
00717 $this->{$joinClass} = new AppModel(array(
00718 'name' => $joinClass,
00719 'table' => $this->{$type}[$assocKey]['joinTable'],
00720 'ds' => $this->useDbConfig
00721 ));
00722 } else {
00723 $this->__constructLinkedModel($joinClass, $plugin . $joinClass);
00724 $this->{$type}[$assocKey]['joinTable'] = $this->{$joinClass}->table;
00725 }
00726
00727 if (count($this->{$joinClass}->schema()) <= 2 && $this->{$joinClass}->primaryKey !== false) {
00728 $this->{$joinClass}->primaryKey = $this->{$type}[$assocKey]['foreignKey'];
00729 }
00730 }
00731 }
00732 }
00733
00734
00735
00736
00737
00738
00739
00740 function setSource($tableName) {
00741 $this->setDataSource($this->useDbConfig);
00742 $db =& ConnectionManager::getDataSource($this->useDbConfig);
00743 $db->cacheSources = ($this->cacheSources && $db->cacheSources);
00744
00745 if ($db->isInterfaceSupported('listSources')) {
00746 $sources = $db->listSources();
00747 if (is_array($sources) && !in_array(strtolower($this->tablePrefix . $tableName), array_map('strtolower', $sources))) {
00748 return $this->cakeError('missingTable', array(array(
00749 'className' => $this->alias,
00750 'table' => $this->tablePrefix . $tableName
00751 )));
00752 }
00753 $this->_schema = null;
00754 }
00755 $this->table = $this->useTable = $tableName;
00756 $this->tableToModel[$this->table] = $this->alias;
00757 $this->schema();
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772 function set($one, $two = null) {
00773 if (!$one) {
00774 return;
00775 }
00776 if (is_object($one)) {
00777 $one = Set::reverse($one);
00778 }
00779
00780 if (is_array($one)) {
00781 $data = $one;
00782 if (empty($one[$this->alias])) {
00783 if ($this->getAssociated(key($one)) === null) {
00784 $data = array($this->alias => $one);
00785 }
00786 }
00787 } else {
00788 $data = array($this->alias => array($one => $two));
00789 }
00790
00791 foreach ($data as $modelName => $fieldSet) {
00792 if (is_array($fieldSet)) {
00793
00794 foreach ($fieldSet as $fieldName => $fieldValue) {
00795 if (isset($this->validationErrors[$fieldName])) {
00796 unset ($this->validationErrors[$fieldName]);
00797 }
00798
00799 if ($modelName === $this->alias) {
00800 if ($fieldName === $this->primaryKey) {
00801 $this->id = $fieldValue;
00802 }
00803 }
00804 if (is_array($fieldValue) || is_object($fieldValue)) {
00805 $fieldValue = $this->deconstruct($fieldName, $fieldValue);
00806 }
00807 $this->data[$modelName][$fieldName] = $fieldValue;
00808 }
00809 }
00810 }
00811 return $data;
00812 }
00813
00814
00815
00816
00817
00818
00819
00820
00821 function deconstruct($field, $data) {
00822 if (!is_array($data)) {
00823 return $data;
00824 }
00825
00826 $copy = $data;
00827 $type = $this->getColumnType($field);
00828
00829 if (in_array($type, array('datetime', 'timestamp', 'date', 'time'))) {
00830 $useNewDate = (isset($data['year']) || isset($data['month']) ||
00831 isset($data['day']) || isset($data['hour']) || isset($data['minute']));
00832
00833 $dateFields = array('Y' => 'year', 'm' => 'month', 'd' => 'day', 'H' => 'hour', 'i' => 'min', 's' => 'sec');
00834 $timeFields = array('H' => 'hour', 'i' => 'min', 's' => 'sec');
00835
00836 $db =& ConnectionManager::getDataSource($this->useDbConfig);
00837 $format = $db->columns[$type]['format'];
00838 $date = array();
00839
00840 if (isset($data['hour']) && isset($data['meridian']) && $data['hour'] != 12 && 'pm' == $data['meridian']) {
00841 $data['hour'] = $data['hour'] + 12;
00842 }
00843 if (isset($data['hour']) && isset($data['meridian']) && $data['hour'] == 12 && 'am' == $data['meridian']) {
00844 $data['hour'] = '00';
00845 }
00846 if ($type == 'time') {
00847 foreach ($timeFields as $key => $val) {
00848 if (!isset($data[$val]) || $data[$val] === '0' || $data[$val] === '00') {
00849 $data[$val] = '00';
00850 } elseif ($data[$val] === '') {
00851 $data[$val] = '';
00852 } else {
00853 $data[$val] = sprintf('%02d', $data[$val]);
00854 }
00855 if (!empty($data[$val])) {
00856 $date[$key] = $data[$val];
00857 } else {
00858 return null;
00859 }
00860 }
00861 }
00862
00863 if ($type == 'datetime' || $type == 'timestamp' || $type == 'date') {
00864 foreach ($dateFields as $key => $val) {
00865 if ($val == 'hour' || $val == 'min' || $val == 'sec') {
00866 if (!isset($data[$val]) || $data[$val] === '0' || $data[$val] === '00') {
00867 $data[$val] = '00';
00868 } else {
00869 $data[$val] = sprintf('%02d', $data[$val]);
00870 }
00871 }
00872 if (!isset($data[$val]) || isset($data[$val]) && (empty($data[$val]) || $data[$val][0] === '-')) {
00873 return null;
00874 }
00875 if (isset($data[$val]) && !empty($data[$val])) {
00876 $date[$key] = $data[$val];
00877 }
00878 }
00879 }
00880 $date = str_replace(array_keys($date), array_values($date), $format);
00881 if ($useNewDate && !empty($date)) {
00882 return $date;
00883 }
00884 }
00885 return $data;
00886 }
00887
00888
00889
00890
00891
00892
00893
00894
00895 function schema($field = false) {
00896 if (!is_array($this->_schema) || $field === true) {
00897 $db =& ConnectionManager::getDataSource($this->useDbConfig);
00898 $db->cacheSources = ($this->cacheSources && $db->cacheSources);
00899 if ($db->isInterfaceSupported('describe') && $this->useTable !== false) {
00900 $this->_schema = $db->describe($this, $field);
00901 } elseif ($this->useTable === false) {
00902 $this->_schema = array();
00903 }
00904 }
00905 if (is_string($field)) {
00906 if (isset($this->_schema[$field])) {
00907 return $this->_schema[$field];
00908 } else {
00909 return null;
00910 }
00911 }
00912 return $this->_schema;
00913 }
00914
00915
00916
00917
00918
00919
00920 function getColumnTypes() {
00921 $columns = $this->schema();
00922 if (empty($columns)) {
00923 trigger_error(__('(Model::getColumnTypes) Unable to build model field data. If you are using a model without a database table, try implementing schema()', true), E_USER_WARNING);
00924 }
00925 $cols = array();
00926 foreach ($columns as $field => $values) {
00927 $cols[$field] = $values['type'];
00928 }
00929 return $cols;
00930 }
00931
00932
00933
00934
00935
00936
00937
00938 function getColumnType($column) {
00939 $db =& ConnectionManager::getDataSource($this->useDbConfig);
00940 $cols = $this->schema();
00941 $model = null;
00942
00943 $column = str_replace(array($db->startQuote, $db->endQuote), '', $column);
00944
00945 if (strpos($column, '.')) {
00946 list($model, $column) = explode('.', $column);
00947 }
00948 if ($model != $this->alias && isset($this->{$model})) {
00949 return $this->{$model}->getColumnType($column);
00950 }
00951 if (isset($cols[$column]) && isset($cols[$column]['type'])) {
00952 return $cols[$column]['type'];
00953 }
00954 return null;
00955 }
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965 function hasField($name) {
00966 if (is_array($name)) {
00967 foreach ($name as $n) {
00968 if ($this->hasField($n)) {
00969 return $n;
00970 }
00971 }
00972 return false;
00973 }
00974
00975 if (empty($this->_schema)) {
00976 $this->schema();
00977 }
00978
00979 if ($this->_schema != null) {
00980 return isset($this->_schema[$name]);
00981 }
00982 return false;
00983 }
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996 function create($data = array(), $filterKey = false) {
00997 $defaults = array();
00998 $this->id = false;
00999 $this->data = array();
01000 $this->__exists = null;
01001 $this->validationErrors = array();
01002
01003 if ($data !== null && $data !== false) {
01004 foreach ($this->schema() as $field => $properties) {
01005 if ($this->primaryKey !== $field && isset($properties['default'])) {
01006 $defaults[$field] = $properties['default'];
01007 }
01008 }
01009 $this->set(Set::filter($defaults));
01010 $this->set($data);
01011 }
01012 if ($filterKey) {
01013 $this->set($this->primaryKey, false);
01014 }
01015 return $this->data;
01016 }
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026 function read($fields = null, $id = null) {
01027 $this->validationErrors = array();
01028
01029 if ($id != null) {
01030 $this->id = $id;
01031 }
01032
01033 $id = $this->id;
01034
01035 if (is_array($this->id)) {
01036 $id = $this->id[0];
01037 }
01038
01039 if ($id !== null && $id !== false) {
01040 $this->data = $this->find('first', array(
01041 'conditions' => array($this->alias . '.' . $this->primaryKey => $id),
01042 'fields' => $fields
01043 ));
01044 return $this->data;
01045 } else {
01046 return false;
01047 }
01048 }
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060 function field($name, $conditions = null, $order = null) {
01061 if ($conditions === null && $this->id !== false) {
01062 $conditions = array($this->alias . '.' . $this->primaryKey => $this->id);
01063 }
01064 if ($this->recursive >= 1) {
01065 $recursive = -1;
01066 } else {
01067 $recursive = $this->recursive;
01068 }
01069 if ($data = $this->find($conditions, $name, $order, $recursive)) {
01070 if (strpos($name, '.') === false) {
01071 if (isset($data[$this->alias][$name])) {
01072 return $data[$this->alias][$name];
01073 }
01074 } else {
01075 $name = explode('.', $name);
01076 if (isset($data[$name[0]][$name[1]])) {
01077 return $data[$name[0]][$name[1]];
01078 }
01079 }
01080 if (isset($data[0]) && count($data[0]) > 0) {
01081 $name = key($data[0]);
01082 return $data[0][$name];
01083 }
01084 } else {
01085 return false;
01086 }
01087 }
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100 function saveField($name, $value, $validate = false) {
01101 $id = $this->id;
01102 $this->create(false);
01103
01104 if (is_array($validate)) {
01105 $options = array_merge(array('validate' => false, 'fieldList' => array($name)), $validate);
01106 } else {
01107 $options = array('validate' => $validate, 'fieldList' => array($name));
01108 }
01109 return $this->save(array($this->alias => array($this->primaryKey => $id, $name => $value)), $options);
01110 }
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124 function save($data = null, $validate = true, $fieldList = array()) {
01125 $defaults = array('validate' => true, 'fieldList' => array(), 'callbacks' => true);
01126 $_whitelist = $this->whitelist;
01127 $fields = array();
01128
01129 if (!is_array($validate)) {
01130 $options = array_merge($defaults, compact('validate', 'fieldList', 'callbacks'));
01131 } else {
01132 $options = array_merge($defaults, $validate);
01133 }
01134
01135 if (!empty($options['fieldList'])) {
01136 $this->whitelist = $options['fieldList'];
01137 } elseif ($options['fieldList'] === null) {
01138 $this->whitelist = array();
01139 }
01140 $this->set($data);
01141
01142 if (empty($this->data) && !$this->hasField(array('created', 'updated', 'modified'))) {
01143 return false;
01144 }
01145
01146 foreach (array('created', 'updated', 'modified') as $field) {
01147 $keyPresentAndEmpty = (
01148 isset($this->data[$this->alias]) &&
01149 array_key_exists($field, $this->data[$this->alias]) &&
01150 $this->data[$this->alias][$field] === null
01151 );
01152 if ($keyPresentAndEmpty) {
01153 unset($this->data[$this->alias][$field]);
01154 }
01155 }
01156
01157 $this->exists();
01158 $dateFields = array('modified', 'updated');
01159
01160 if (!$this->__exists) {
01161 $dateFields[] = 'created';
01162 }
01163 if (isset($this->data[$this->alias])) {
01164 $fields = array_keys($this->data[$this->alias]);
01165 }
01166 if ($options['validate'] && !$this->validates($options)) {
01167 $this->whitelist = $_whitelist;
01168 return false;
01169 }
01170
01171 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01172
01173 foreach ($dateFields as $updateCol) {
01174 if ($this->hasField($updateCol) && !in_array($updateCol, $fields)) {
01175 $default = array('formatter' => 'date');
01176 $colType = array_merge($default, $db->columns[$this->getColumnType($updateCol)]);
01177 if (!array_key_exists('format', $colType)) {
01178 $time = strtotime('now');
01179 } else {
01180 $time = $colType['formatter']($colType['format']);
01181 }
01182 if (!empty($this->whitelist)) {
01183 $this->whitelist[] = $updateCol;
01184 }
01185 $this->set($updateCol, $time);
01186 }
01187 }
01188
01189 if ($options['callbacks'] === true || $options['callbacks'] === 'before') {
01190 $result = $this->Behaviors->trigger($this, 'beforeSave', array($options), array(
01191 'break' => true, 'breakOn' => false
01192 ));
01193 if (!$result || !$this->beforeSave($options)) {
01194 $this->whitelist = $_whitelist;
01195 return false;
01196 }
01197 }
01198 $fields = $values = array();
01199
01200 if (isset($this->data[$this->alias][$this->primaryKey]) && empty($this->data[$this->alias][$this->primaryKey])) {
01201 unset($this->data[$this->alias][$this->primaryKey]);
01202 }
01203
01204 foreach ($this->data as $n => $v) {
01205 if (isset($this->hasAndBelongsToMany[$n])) {
01206 if (isset($v[$n])) {
01207 $v = $v[$n];
01208 }
01209 $joined[$n] = $v;
01210 } else {
01211 if ($n === $this->alias) {
01212 foreach (array('created', 'updated', 'modified') as $field) {
01213 if (array_key_exists($field, $v) && empty($v[$field])) {
01214 unset($v[$field]);
01215 }
01216 }
01217
01218 foreach ($v as $x => $y) {
01219 if ($this->hasField($x) && (empty($this->whitelist) || in_array($x, $this->whitelist))) {
01220 list($fields[], $values[]) = array($x, $y);
01221 }
01222 }
01223 }
01224 }
01225 }
01226 $count = count($fields);
01227
01228 if (!$this->__exists && $count > 0) {
01229 $this->id = false;
01230 }
01231 $success = true;
01232 $created = false;
01233
01234 if ($count > 0) {
01235 $cache = $this->_prepareUpdateFields(array_combine($fields, $values));
01236
01237 if (!empty($this->id)) {
01238 $success = (bool)$db->update($this, $fields, $values);
01239 } else {
01240 foreach ($this->_schema as $field => $properties) {
01241 if ($this->primaryKey === $field) {
01242 $fInfo = $this->_schema[$field];
01243 $isUUID = ($fInfo['length'] == 36 &&
01244 ($fInfo['type'] === 'string' || $fInfo['type'] === 'binary')
01245 );
01246 if (empty($this->data[$this->alias][$this->primaryKey]) && $isUUID) {
01247 list($fields[], $values[]) = array($this->primaryKey, String::uuid());
01248 }
01249 break;
01250 }
01251 }
01252
01253 if (!$db->create($this, $fields, $values)) {
01254 $success = $created = false;
01255 } else {
01256 $created = true;
01257 }
01258 }
01259
01260 if ($success && !empty($this->belongsTo)) {
01261 $this->updateCounterCache($cache, $created);
01262 }
01263 }
01264
01265 if (!empty($joined) && $success === true) {
01266 $this->__saveMulti($joined, $this->id);
01267 }
01268
01269 if ($success && $count > 0) {
01270 if (!empty($this->data)) {
01271 $success = $this->data;
01272 }
01273 if ($options['callbacks'] === true || $options['callbacks'] === 'after') {
01274 $this->Behaviors->trigger($this, 'afterSave', array($created, $options));
01275 $this->afterSave($created);
01276 }
01277 if (!empty($this->data)) {
01278 $success = Set::merge($success, $this->data);
01279 }
01280 $this->data = false;
01281 $this->__exists = null;
01282 $this->_clearCache();
01283 $this->validationErrors = array();
01284 }
01285 $this->whitelist = $_whitelist;
01286 return $success;
01287 }
01288
01289
01290
01291
01292
01293
01294
01295 function __saveMulti($joined, $id) {
01296 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01297
01298 foreach ($joined as $assoc => $data) {
01299
01300 if (isset($this->hasAndBelongsToMany[$assoc])) {
01301 list($join) = $this->joinModel($this->hasAndBelongsToMany[$assoc]['with']);
01302
01303 $conditions = array($join . '.' . $this->hasAndBelongsToMany[$assoc]['foreignKey'] => $id);
01304
01305 $links = $this->{$join}->find('all', array(
01306 'conditions' => $conditions,
01307 'recursive' => -1,
01308 'fields' => $this->hasAndBelongsToMany[$assoc]['associationForeignKey']
01309 ));
01310
01311 $isUUID = !empty($this->{$join}->primaryKey) && (
01312 $this->{$join}->_schema[$this->{$join}->primaryKey]['length'] == 36 && (
01313 $this->{$join}->_schema[$this->{$join}->primaryKey]['type'] === 'string' ||
01314 $this->{$join}->_schema[$this->{$join}->primaryKey]['type'] === 'binary'
01315 )
01316 );
01317
01318 $newData = $newValues = array();
01319 $primaryAdded = false;
01320
01321 $fields = array(
01322 $db->name($this->hasAndBelongsToMany[$assoc]['foreignKey']),
01323 $db->name($this->hasAndBelongsToMany[$assoc]['associationForeignKey'])
01324 );
01325
01326 $idField = $db->name($this->{$join}->primaryKey);
01327 if ($isUUID && !in_array($idField, $fields)) {
01328 $fields[] = $idField;
01329 $primaryAdded = true;
01330 }
01331
01332 foreach ((array)$data as $row) {
01333 if ((is_string($row) && (strlen($row) == 36 || strlen($row) == 16)) || is_numeric($row)) {
01334 $values = array(
01335 $db->value($id, $this->getColumnType($this->primaryKey)),
01336 $db->value($row)
01337 );
01338 if ($isUUID && $primaryAdded) {
01339 $values[] = $db->value(String::uuid());
01340 }
01341 $values = join(',', $values);
01342 $newValues[] = "({$values})";
01343 unset($values);
01344 } elseif (isset($row[$this->hasAndBelongsToMany[$assoc]['associationForeignKey']])) {
01345 $newData[] = $row;
01346 } elseif (isset($row[$join]) && isset($row[$join][$this->hasAndBelongsToMany[$assoc]['associationForeignKey']])) {
01347 $newData[] = $row[$join];
01348 }
01349 }
01350
01351 if ($this->hasAndBelongsToMany[$assoc]['unique']) {
01352 $associationForeignKey = "{$join}." . $this->hasAndBelongsToMany[$assoc]['associationForeignKey'];
01353 $oldLinks = Set::extract($links, "{n}.{$associationForeignKey}");
01354 if (!empty($oldLinks)) {
01355 $conditions[$associationForeignKey] = $oldLinks;
01356 $db->delete($this->{$join}, $conditions);
01357 }
01358 }
01359
01360 if (!empty($newData)) {
01361 foreach ($newData as $data) {
01362 $data[$this->hasAndBelongsToMany[$assoc]['foreignKey']] = $id;
01363 $this->{$join}->create($data);
01364 $this->{$join}->save();
01365 }
01366 }
01367
01368 if (!empty($newValues)) {
01369 $fields = join(',', $fields);
01370 $db->insertMulti($this->{$join}, $fields, $newValues);
01371 }
01372 }
01373 }
01374 }
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384 function updateCounterCache($keys = array(), $created = false) {
01385 $keys = empty($keys) ? $this->data[$this->alias] : $keys;
01386 $keys['old'] = isset($keys['old']) ? $keys['old'] : array();
01387
01388 foreach ($this->belongsTo as $parent => $assoc) {
01389 $foreignKey = $assoc['foreignKey'];
01390 $fkQuoted = $this->escapeField($assoc['foreignKey']);
01391
01392 if (!empty($assoc['counterCache'])) {
01393 if ($assoc['counterCache'] === true) {
01394 $assoc['counterCache'] = Inflector::underscore($this->alias) . '_count';
01395 }
01396 if (!$this->{$parent}->hasField($assoc['counterCache'])) {
01397 continue;
01398 }
01399
01400 if (!array_key_exists($foreignKey, $keys)) {
01401 $keys[$foreignKey] = $this->field($foreignKey);
01402 }
01403 $recursive = (isset($assoc['counterScope']) ? 1 : -1);
01404 $conditions = ($recursive == 1) ? (array)$assoc['counterScope'] : array();
01405
01406 if (isset($keys['old'][$foreignKey])) {
01407 if ($keys['old'][$foreignKey] != $keys[$foreignKey]) {
01408 $conditions[$fkQuoted] = $keys['old'][$foreignKey];
01409 $count = intval($this->find('count', compact('conditions', 'recursive')));
01410
01411 $this->{$parent}->updateAll(
01412 array($assoc['counterCache'] => $count),
01413 array($this->{$parent}->escapeField() => $keys['old'][$foreignKey])
01414 );
01415 }
01416 }
01417 $conditions[$fkQuoted] = $keys[$foreignKey];
01418
01419 if ($recursive == 1) {
01420 $conditions = array_merge($conditions, (array)$assoc['counterScope']);
01421 }
01422 $count = intval($this->find('count', compact('conditions', 'recursive')));
01423
01424 $this->{$parent}->updateAll(
01425 array($assoc['counterCache'] => $count),
01426 array($this->{$parent}->escapeField() => $keys[$foreignKey])
01427 );
01428 }
01429 }
01430 }
01431
01432
01433
01434
01435
01436
01437
01438
01439 function _prepareUpdateFields($data) {
01440 $foreignKeys = array();
01441 foreach ($this->belongsTo as $assoc => $info) {
01442 if ($info['counterCache']) {
01443 $foreignKeys[$assoc] = $info['foreignKey'];
01444 }
01445 }
01446 $included = array_intersect($foreignKeys, array_keys($data));
01447
01448 if (empty($included) || empty($this->id)) {
01449 return array();
01450 }
01451 $old = $this->find('first', array(
01452 'conditions' => array($this->primaryKey => $this->id),
01453 'fields' => array_values($included),
01454 'recursive' => -1
01455 ));
01456 return array_merge($data, array('old' => $old[$this->alias]));
01457 }
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478 function saveAll($data = null, $options = array()) {
01479 if (empty($data)) {
01480 $data = $this->data;
01481 }
01482 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01483
01484 $options = array_merge(array('validate' => true, 'atomic' => true), $options);
01485 $this->validationErrors = $validationErrors = array();
01486 $validates = true;
01487 $return = array();
01488
01489 if ($options['atomic'] && $options['validate'] !== 'only') {
01490 $db->begin($this);
01491 }
01492
01493 if (Set::numeric(array_keys($data))) {
01494 while ($validates) {
01495 foreach ($data as $key => $record) {
01496 if (!$currentValidates = $this->__save($record, $options)) {
01497 $validationErrors[$key] = $this->validationErrors;
01498 }
01499
01500 if ($options['validate'] === 'only' || $options['validate'] === 'first') {
01501 $validating = true;
01502 if ($options['atomic']) {
01503 $validates = $validates && $currentValidates;
01504 } else {
01505 $validates = $currentValidates;
01506 }
01507 } else {
01508 $validating = false;
01509 $validates = $currentValidates;
01510 }
01511
01512 if (!$options['atomic']) {
01513 $return[] = $validates;
01514 } elseif (!$validates && !$validating) {
01515 break;
01516 }
01517 }
01518 $this->validationErrors = $validationErrors;
01519
01520 switch (true) {
01521 case ($options['validate'] === 'only'):
01522 return ($options['atomic'] ? $validates : $return);
01523 break;
01524 case ($options['validate'] === 'first'):
01525 $options['validate'] = true;
01526 continue;
01527 break;
01528 default:
01529 if ($options['atomic']) {
01530 if ($validates && ($db->commit($this) !== false)) {
01531 return true;
01532 }
01533 $db->rollback($this);
01534 return false;
01535 }
01536 return $return;
01537 break;
01538 }
01539 }
01540 return $return;
01541 }
01542 $associations = $this->getAssociated();
01543
01544 while ($validates) {
01545 foreach ($data as $association => $values) {
01546 if (isset($associations[$association])) {
01547 switch ($associations[$association]) {
01548 case 'belongsTo':
01549 if ($this->{$association}->__save($values, $options)) {
01550 $data[$this->alias][$this->belongsTo[$association]['foreignKey']] = $this->{$association}->id;
01551 } else {
01552 $validationErrors[$association] = $this->{$association}->validationErrors;
01553 $validates = false;
01554 }
01555 if (!$options['atomic']) {
01556 $return[$association][] = $validates;
01557 }
01558 break;
01559 }
01560 }
01561 }
01562 if (!$this->__save($data, $options)) {
01563 $validationErrors[$this->alias] = $this->validationErrors;
01564 $validates = false;
01565 }
01566 if (!$options['atomic']) {
01567 $return[$this->alias] = $validates;
01568 }
01569 $validating = ($options['validate'] === 'only' || $options['validate'] === 'first');
01570
01571 foreach ($data as $association => $values) {
01572 if (!$validates && !$validating) {
01573 break;
01574 }
01575 if (isset($associations[$association])) {
01576 $type = $associations[$association];
01577 switch ($type) {
01578 case 'hasOne':
01579 $values[$this->{$type}[$association]['foreignKey']] = $this->id;
01580 if (!$this->{$association}->__save($values, $options)) {
01581 $validationErrors[$association] = $this->{$association}->validationErrors;
01582 $validates = false;
01583 }
01584 if (!$options['atomic']) {
01585 $return[$association][] = $validates;
01586 }
01587 break;
01588 case 'hasMany':
01589 foreach ($values as $i => $value) {
01590 $values[$i][$this->{$type}[$association]['foreignKey']] = $this->id;
01591 }
01592 $_options = array_merge($options, array('atomic' => false));
01593
01594 if ($_options['validate'] === 'first') {
01595 $_options['validate'] = 'only';
01596 }
01597 $_return = $this->{$association}->saveAll($values, $_options);
01598
01599 if ($_return === false || (is_array($_return) && in_array(false, $_return, true))) {
01600 $validationErrors[$association] = $this->{$association}->validationErrors;
01601 $validates = false;
01602 }
01603 if (is_array($_return)) {
01604 foreach ($_return as $val) {
01605 if (!isset($return[$association])) {
01606 $return[$association] = array();
01607 } elseif (!is_array($return[$association])) {
01608 $return[$association] = array($return[$association]);
01609 }
01610 $return[$association][] = $val;
01611 }
01612 } else {
01613 $return[$association] = $_return;
01614 }
01615 break;
01616 }
01617 }
01618 }
01619 $this->validationErrors = $validationErrors;
01620
01621 if (isset($validationErrors[$this->alias])) {
01622 $this->validationErrors = $validationErrors[$this->alias];
01623 }
01624
01625 switch (true) {
01626 case ($options['validate'] === 'only'):
01627 return ($options['atomic'] ? $validates : $return);
01628 break;
01629 case ($options['validate'] === 'first'):
01630 $options['validate'] = true;
01631 continue;
01632 break;
01633 default:
01634 if ($options['atomic']) {
01635 if ($validates) {
01636 return ($db->commit($this) !== false);
01637 } else {
01638 $db->rollback($this);
01639 }
01640 }
01641 return $return;
01642 break;
01643 }
01644 }
01645 }
01646
01647
01648
01649
01650
01651
01652
01653 function __save($data, $options) {
01654 if ($options['validate'] === 'first' || $options['validate'] === 'only') {
01655 if (!($this->create($data) && $this->validates($options))) {
01656 return false;
01657 }
01658 } elseif (!($this->create(null) !== null && $this->save($data, $options))) {
01659 return false;
01660 }
01661 return true;
01662 }
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673 function updateAll($fields, $conditions = true) {
01674 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01675 return $db->update($this, $fields, null, $conditions);
01676 }
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687 function remove($id = null, $cascade = true) {
01688 return $this->del($id, $cascade);
01689 }
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699 function del($id = null, $cascade = true) {
01700 if (!empty($id)) {
01701 $this->id = $id;
01702 }
01703 $id = $this->id;
01704
01705 if ($this->exists() && $this->beforeDelete($cascade)) {
01706 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01707 if (!$this->Behaviors->trigger($this, 'beforeDelete', array($cascade), array('break' => true, 'breakOn' => false))) {
01708 return false;
01709 }
01710 $this->_deleteDependent($id, $cascade);
01711 $this->_deleteLinks($id);
01712 $this->id = $id;
01713
01714 if (!empty($this->belongsTo)) {
01715 $keys = $this->find('first', array('fields' => $this->__collectForeignKeys()));
01716 }
01717
01718 if ($db->delete($this)) {
01719 if (!empty($this->belongsTo)) {
01720 $this->updateCounterCache($keys[$this->alias]);
01721 }
01722 $this->Behaviors->trigger($this, 'afterDelete');
01723 $this->afterDelete();
01724 $this->_clearCache();
01725 $this->id = false;
01726 $this->__exists = null;
01727 return true;
01728 }
01729 }
01730 return false;
01731 }
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741 function delete($id = null, $cascade = true) {
01742 return $this->del($id, $cascade);
01743 }
01744
01745
01746
01747
01748
01749
01750
01751
01752 function _deleteDependent($id, $cascade) {
01753 if (!empty($this->__backAssociation)) {
01754 $savedAssociatons = $this->__backAssociation;
01755 $this->__backAssociation = array();
01756 }
01757 foreach (array_merge($this->hasMany, $this->hasOne) as $assoc => $data) {
01758 if ($data['dependent'] === true && $cascade === true) {
01759
01760 $model =& $this->{$assoc};
01761 $conditions = array($model->escapeField($data['foreignKey']) => $id);
01762 if ($data['conditions']) {
01763 $conditions = array_merge($data['conditions'], $conditions);
01764 }
01765 $model->recursive = -1;
01766
01767 if (isset($data['exclusive']) && $data['exclusive']) {
01768 $model->deleteAll($conditions);
01769 } else {
01770 $records = $model->find('all', array('conditions' => $conditions, 'fields' => $model->primaryKey));
01771
01772 if (!empty($records)) {
01773 foreach ($records as $record) {
01774 $model->delete($record[$model->alias][$model->primaryKey]);
01775 }
01776 }
01777 }
01778 }
01779 }
01780 if (isset($savedAssociatons)) {
01781 $this->__backAssociation = $savedAssociatons;
01782 }
01783 }
01784
01785
01786
01787
01788
01789
01790
01791 function _deleteLinks($id) {
01792 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01793
01794 foreach ($this->hasAndBelongsToMany as $assoc => $data) {
01795 $records = $this->{$data['with']}->find('all', array(
01796 'conditions' => array_merge(array($this->{$data['with']}->escapeField($data['foreignKey']) => $id)),
01797 'fields' => $this->{$data['with']}->primaryKey,
01798 'recursive' => -1
01799 ));
01800 if (!empty($records)) {
01801 foreach ($records as $record) {
01802 $this->{$data['with']}->delete($record[$this->{$data['with']}->alias][$this->{$data['with']}->primaryKey]);
01803 }
01804 }
01805 }
01806 }
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817 function deleteAll($conditions, $cascade = true, $callbacks = false) {
01818 if (empty($conditions)) {
01819 return false;
01820 }
01821 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01822
01823 if (!$cascade && !$callbacks) {
01824 return $db->delete($this, $conditions);
01825 } else {
01826 $ids = Set::extract(
01827 $this->find('all', array_merge(array('fields' => "{$this->alias}.{$this->primaryKey}", 'recursive' => 0), compact('conditions'))),
01828 "{n}.{$this->alias}.{$this->primaryKey}"
01829 );
01830
01831 if (empty($ids)) {
01832 return true;
01833 }
01834
01835 if ($callbacks) {
01836 $_id = $this->id;
01837 $result = true;
01838 foreach ($ids as $id) {
01839 $result = ($result && $this->delete($id, $cascade));
01840 }
01841 $this->id = $_id;
01842 return $result;
01843 } else {
01844 foreach ($ids as $id) {
01845 $this->_deleteLinks($id);
01846 if ($cascade) {
01847 $this->_deleteDependent($id, $cascade);
01848 }
01849 }
01850 return $db->delete($this, array($this->alias . '.' . $this->primaryKey => $ids));
01851 }
01852 }
01853 }
01854
01855
01856
01857
01858
01859
01860 function __collectForeignKeys($type = 'belongsTo') {
01861 $result = array();
01862
01863 foreach ($this->{$type} as $assoc => $data) {
01864 if (isset($data['foreignKey']) && is_string($data['foreignKey'])) {
01865 $result[$assoc] = $data['foreignKey'];
01866 }
01867 }
01868 return $result;
01869 }
01870
01871
01872
01873
01874
01875
01876
01877 function exists($reset = false) {
01878 if (is_array($reset)) {
01879 extract($reset, EXTR_OVERWRITE);
01880 }
01881
01882 if ($this->getID() === false || $this->useTable === false) {
01883 return false;
01884 }
01885 if (!empty($this->__exists) && $reset !== true) {
01886 return $this->__exists;
01887 }
01888 $conditions = array($this->alias . '.' . $this->primaryKey => $this->getID());
01889 $query = array('conditions' => $conditions, 'recursive' => -1, 'callbacks' => false);
01890
01891 if (is_array($reset)) {
01892 $query = array_merge($query, $reset);
01893 }
01894 return $this->__exists = ($this->find('count', $query) > 0);
01895 }
01896
01897
01898
01899
01900
01901
01902
01903 function hasAny($conditions = null) {
01904 return ($this->find('count', array('conditions' => $conditions, 'recursive' => -1)) != false);
01905 }
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935 function find($conditions = null, $fields = array(), $order = null, $recursive = null) {
01936 if (!is_string($conditions) || (is_string($conditions) && !array_key_exists($conditions, $this->_findMethods))) {
01937 $type = 'first';
01938 $query = array_merge(compact('conditions', 'fields', 'order', 'recursive'), array('limit' => 1));
01939 } else {
01940 list($type, $query) = array($conditions, $fields);
01941 }
01942
01943 $db =& ConnectionManager::getDataSource($this->useDbConfig);
01944 $this->findQueryType = $type;
01945 $this->id = $this->getID();
01946
01947 $query = array_merge(
01948 array(
01949 'conditions' => null, 'fields' => null, 'joins' => array(), 'limit' => null,
01950 'offset' => null, 'order' => null, 'page' => null, 'group' => null, 'callbacks' => true
01951 ),
01952 (array)$query
01953 );
01954
01955 if ($type != 'all') {
01956 if ($this->_findMethods[$type] === true) {
01957 $query = $this->{'_find' . ucfirst($type)}('before', $query);
01958 }
01959 }
01960
01961 if (!is_numeric($query['page']) || intval($query['page']) < 1) {
01962 $query['page'] = 1;
01963 }
01964 if ($query['page'] > 1 && !empty($query['limit'])) {
01965 $query['offset'] = ($query['page'] - 1) * $query['limit'];
01966 }
01967 if ($query['order'] === null && $this->order !== null) {
01968 $query['order'] = $this->order;
01969 }
01970 $query['order'] = array($query['order']);
01971
01972 if ($query['callbacks'] === true || $query['callbacks'] === 'before') {
01973 $return = $this->Behaviors->trigger($this, 'beforeFind', array($query), array(
01974 'break' => true, 'breakOn' => false, 'modParams' => true
01975 ));
01976 $query = (is_array($return)) ? $return : $query;
01977
01978 if ($return === false) {
01979 return null;
01980 }
01981
01982 $return = $this->beforeFind($query);
01983 $query = (is_array($return)) ? $return : $query;
01984
01985 if ($return === false) {
01986 return null;
01987 }
01988 }
01989
01990 $results = $db->read($this, $query);
01991 $this->resetAssociations();
01992 $this->findQueryType = null;
01993
01994 if ($query['callbacks'] === true || $query['callbacks'] === 'after') {
01995 $results = $this->__filterResults($results);
01996 }
01997
01998 if ($type === 'all') {
01999 return $results;
02000 } else {
02001 if ($this->_findMethods[$type] === true) {
02002 return $this->{'_find' . ucfirst($type)}('after', $query, $results);
02003 }
02004 }
02005 }
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016 function _findFirst($state, $query, $results = array()) {
02017 if ($state == 'before') {
02018 $query['limit'] = 1;
02019 if (empty($query['conditions']) && !empty($this->id)) {
02020 $query['conditions'] = array($this->escapeField() => $this->id);
02021 }
02022 return $query;
02023 } elseif ($state == 'after') {
02024 if (empty($results[0])) {
02025 return false;
02026 }
02027 return $results[0];
02028 }
02029 }
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040 function _findCount($state, $query, $results = array()) {
02041 if ($state == 'before') {
02042 $db =& ConnectionManager::getDataSource($this->useDbConfig);
02043 if (empty($query['fields'])) {
02044 $query['fields'] = $db->calculate($this, 'count');
02045 } elseif (is_string($query['fields']) && !preg_match('/count/i', $query['fields'])) {
02046 $query['fields'] = $db->calculate($this, 'count', array(
02047 $db->expression($query['fields']), 'count'
02048 ));
02049 }
02050 $query['order'] = false;
02051 return $query;
02052 } elseif ($state == 'after') {
02053 if (isset($results[0][0]['count'])) {
02054 return intval($results[0][0]['count']);
02055 } elseif (isset($results[0][$this->alias]['count'])) {
02056 return intval($results[0][$this->alias]['count']);
02057 }
02058 return false;
02059 }
02060 }
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071 function _findList($state, $query, $results = array()) {
02072 if ($state == 'before') {
02073 if (empty($query['fields'])) {
02074 $query['fields'] = array("{$this->alias}.{$this->primaryKey}", "{$this->alias}.{$this->displayField}");
02075 $list = array("{n}.{$this->alias}.{$this->primaryKey}", "{n}.{$this->alias}.{$this->displayField}", null);
02076 } else {
02077 if (!is_array($query['fields'])) {
02078 $query['fields'] = String::tokenize($query['fields']);
02079 }
02080
02081 if (count($query['fields']) == 1) {
02082 if (strpos($query['fields'][0], '.') === false) {
02083 $query['fields'][0] = $this->alias . '.' . $query['fields'][0];
02084 }
02085
02086 $list = array("{n}.{$this->alias}.{$this->primaryKey}", '{n}.' . $query['fields'][0], null);
02087 $query['fields'] = array("{$this->alias}.{$this->primaryKey}", $query['fields'][0]);
02088 } elseif (count($query['fields']) == 3) {
02089 for ($i = 0; $i < 3; $i++) {
02090 if (strpos($query['fields'][$i], '.') === false) {
02091 $query['fields'][$i] = $this->alias . '.' . $query['fields'][$i];
02092 }
02093 }
02094
02095 $list = array('{n}.' . $query['fields'][0], '{n}.' . $query['fields'][1], '{n}.' . $query['fields'][2]);
02096 } else {
02097 for ($i = 0; $i < 2; $i++) {
02098 if (strpos($query['fields'][$i], '.') === false) {
02099 $query['fields'][$i] = $this->alias . '.' . $query['fields'][$i];
02100 }
02101 }
02102
02103 $list = array('{n}.' . $query['fields'][0], '{n}.' . $query['fields'][1], null);
02104 }
02105 }
02106 if (!isset($query['recursive']) || $query['recursive'] === null) {
02107 $query['recursive'] = -1;
02108 }
02109 list($query['list']['keyPath'], $query['list']['valuePath'], $query['list']['groupPath']) = $list;
02110 return $query;
02111 } elseif ($state == 'after') {
02112 if (empty($results)) {
02113 return array();
02114 }
02115 $lst = $query['list'];
02116 return Set::combine($results, $lst['keyPath'], $lst['valuePath'], $lst['groupPath']);
02117 }
02118 }
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129 function _findNeighbors($state, $query, $results = array()) {
02130 if ($state == 'before') {
02131 $query = array_merge(array('recursive' => 0), $query);
02132 extract($query);
02133 $conditions = (array)$conditions;
02134 if (isset($field) && isset($value)) {
02135 if (strpos($field, '.') === false) {
02136 $field = $this->alias . '.' . $field;
02137 }
02138 } else {
02139 $field = $this->alias . '.' . $this->primaryKey;
02140 $value = $this->id;
02141 }
02142 $query['conditions'] = array_merge($conditions, array($field . ' <' => $value));
02143 $query['order'] = $field . ' DESC';
02144 $query['limit'] = 1;
02145 $query['field'] = $field;
02146 $query['value'] = $value;
02147 return $query;
02148 } elseif ($state == 'after') {
02149 extract($query);
02150 unset($query['conditions'][$field . ' <']);
02151 $return = array();
02152 if (isset($results[0])) {
02153 $prevVal = Set::extract('/' . str_replace('.', '/', $field), $results[0]);
02154 $query['conditions'][$field . ' >='] = $prevVal[0];
02155 $query['conditions'][$field . ' !='] = $value;
02156 $query['limit'] = 2;
02157 } else {
02158 $return['prev'] = null;
02159 $query['conditions'][$field . ' >'] = $value;
02160 $query['limit'] = 1;
02161 }
02162 $query['order'] = $field . ' ASC';
02163 $return2 = $this->find('all', $query);
02164 if (!array_key_exists('prev', $return)) {
02165 $return['prev'] = $return2[0];
02166 }
02167 if (count($return2) == 2) {
02168 $return['next'] = $return2[1];
02169 } elseif (count($return2) == 1 && !$return['prev']) {
02170 $return['next'] = $return2[0];
02171 } else {
02172 $return['next'] = null;
02173 }
02174 return $return;
02175 }
02176 }
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187 function _findThreaded($state, $query, $results = array()) {
02188 if ($state == 'before') {
02189 return $query;
02190 } elseif ($state == 'after') {
02191 $return = $idMap = array();
02192 $ids = Set::extract($results, '{n}.' . $this->alias . '.' . $this->primaryKey);
02193
02194 foreach ($results as $result) {
02195 $result['children'] = array();
02196 $id = $result[$this->alias][$this->primaryKey];
02197 $parentId = $result[$this->alias]['parent_id'];
02198 if (isset($idMap[$id]['children'])) {
02199 $idMap[$id] = array_merge($result, (array)$idMap[$id]);
02200 } else {
02201 $idMap[$id] = array_merge($result, array('children' => array()));
02202 }
02203 if (!$parentId || !in_array($parentId, $ids)) {
02204 $return[] =& $idMap[$id];
02205 } else {
02206 $idMap[$parentId]['children'][] =& $idMap[$id];
02207 }
02208 }
02209 if (count($return) > 1) {
02210 $ids = array_unique(Set::extract('/' . $this->alias . '/parent_id', $return));
02211 if (count($ids) > 1) {
02212 $root = $return[0][$this->alias]['parent_id'];
02213 foreach ($return as $key => $value) {
02214 if ($value[$this->alias]['parent_id'] != $root) {
02215 unset($return[$key]);
02216 }
02217 }
02218 }
02219 }
02220 return $return;
02221 }
02222 }
02223
02224
02225
02226
02227
02228
02229
02230
02231 function __filterResults($results, $primary = true) {
02232 $return = $this->Behaviors->trigger($this, 'afterFind', array($results, $primary), array('modParams' => true));
02233 if ($return !== true) {
02234 $results = $return;
02235 }
02236 return $this->afterFind($results, $primary);
02237 }
02238
02239
02240
02241
02242
02243
02244
02245
02246 function resetAssociations() {
02247 if (!empty($this->__backAssociation)) {
02248 foreach ($this->__associations as $type) {
02249 if (isset($this->__backAssociation[$type])) {
02250 $this->{$type} = $this->__backAssociation[$type];
02251 }
02252 }
02253 $this->__backAssociation = array();
02254 }
02255
02256 foreach ($this->__associations as $type) {
02257 foreach ($this->{$type} as $key => $name) {
02258 if (!empty($this->{$key}->__backAssociation)) {
02259 $this->{$key}->resetAssociations();
02260 }
02261 }
02262 }
02263 $this->__backAssociation = array();
02264 return true;
02265 }
02266
02267
02268
02269
02270
02271
02272
02273
02274 function isUnique($fields, $or = true) {
02275 if (!is_array($fields)) {
02276 $fields = func_get_args();
02277 if (is_bool($fields[count($fields) - 1])) {
02278 $or = $fields[count($fields) - 1];
02279 unset($fields[count($fields) - 1]);
02280 }
02281 }
02282
02283 foreach ($fields as $field => $value) {
02284 if (is_numeric($field)) {
02285 unset($fields[$field]);
02286
02287 $field = $value;
02288 if (isset($this->data[$this->alias][$field])) {
02289 $value = $this->data[$this->alias][$field];
02290 } else {
02291 $value = null;
02292 }
02293 }
02294
02295 if (strpos($field, '.') === false) {
02296 unset($fields[$field]);
02297 $fields[$this->alias . '.' . $field] = $value;
02298 }
02299 }
02300 if ($or) {
02301 $fields = array('or' => $fields);
02302 }
02303 if (!empty($this->id)) {
02304 $fields[$this->alias . '.' . $this->primaryKey . ' !='] = $this->id;
02305 }
02306 return ($this->find('count', array('conditions' => $fields, 'recursive' => -1)) == 0);
02307 }
02308
02309
02310
02311
02312
02313
02314
02315
02316 function query() {
02317 $params = func_get_args();
02318 $db =& ConnectionManager::getDataSource($this->useDbConfig);
02319 return call_user_func_array(array(&$db, 'query'), $params);
02320 }
02321
02322
02323
02324
02325
02326
02327
02328
02329 function validates($options = array()) {
02330 $errors = $this->invalidFields($options);
02331 if (is_array($errors)) {
02332 return count($errors) === 0;
02333 }
02334 return $errors;
02335 }
02336
02337
02338
02339
02340
02341
02342
02343
02344 function invalidFields($options = array()) {
02345 if (
02346 !$this->Behaviors->trigger(
02347 $this,
02348 'beforeValidate',
02349 array($options),
02350 array('break' => true, 'breakOn' => false)
02351 ) ||
02352 $this->beforeValidate($options) === false
02353 ) {
02354 return $this->validationErrors;
02355 }
02356
02357 if (!isset($this->validate) || empty($this->validate)) {
02358 return $this->validationErrors;
02359 }
02360
02361 $data = $this->data;
02362 $methods = array_map('strtolower', get_class_methods($this));
02363 $behaviorMethods = array_keys($this->Behaviors->methods());
02364
02365 if (isset($data[$this->alias])) {
02366 $data = $data[$this->alias];
02367 } elseif (!is_array($data)) {
02368 $data = array();
02369 }
02370
02371 $Validation =& Validation::getInstance();
02372 $this->exists();
02373
02374 $_validate = $this->validate;
02375 $whitelist = $this->whitelist;
02376
02377 if (array_key_exists('fieldList', $options)) {
02378 $whitelist = $options['fieldList'];
02379 }
02380
02381 if (!empty($whitelist)) {
02382 $validate = array();
02383 foreach ((array)$whitelist as $f) {
02384 if (!empty($this->validate[$f])) {
02385 $validate[$f] = $this->validate[$f];
02386 }
02387 }
02388 $this->validate = $validate;
02389 }
02390
02391 foreach ($this->validate as $fieldName => $ruleSet) {
02392 if (!is_array($ruleSet) || (is_array($ruleSet) && isset($ruleSet['rule']))) {
02393 $ruleSet = array($ruleSet);
02394 }
02395 $default = array(
02396 'allowEmpty' => null,
02397 'required' => null,
02398 'rule' => 'blank',
02399 'last' => false,
02400 'on' => null
02401 );
02402
02403 foreach ($ruleSet as $index => $validator) {
02404 if (!is_array($validator)) {
02405 $validator = array('rule' => $validator);
02406 }
02407 $validator = array_merge($default, $validator);
02408
02409 if (isset($validator['message'])) {
02410 $message = $validator['message'];
02411 } else {
02412 $message = __('This field cannot be left blank', true);
02413 }
02414
02415 if (
02416 empty($validator['on']) || ($validator['on'] == 'create' &&
02417 !$this->__exists) || ($validator['on'] == 'update' && $this->__exists
02418 )) {
02419 $required = (
02420 (!isset($data[$fieldName]) && $validator['required'] === true) ||
02421 (
02422 isset($data[$fieldName]) && (empty($data[$fieldName]) &&
02423 !is_numeric($data[$fieldName])) && $validator['allowEmpty'] === false
02424 )
02425 );
02426
02427 if ($required) {
02428 $this->invalidate($fieldName, $message);
02429 if ($validator['last']) {
02430 break;
02431 }
02432 } elseif (array_key_exists($fieldName, $data)) {
02433 if (empty($data[$fieldName]) && $data[$fieldName] != '0' && $validator['allowEmpty'] === true) {
02434 break;
02435 }
02436 if (is_array($validator['rule'])) {
02437 $rule = $validator['rule'][0];
02438 unset($validator['rule'][0]);
02439 $ruleParams = array_merge(array($data[$fieldName]), array_values($validator['rule']));
02440 } else {
02441 $rule = $validator['rule'];
02442 $ruleParams = array($data[$fieldName]);
02443 }
02444
02445 $valid = true;
02446
02447 if (in_array(strtolower($rule), $methods)) {
02448 $ruleParams[] = $validator;
02449 $ruleParams[0] = array($fieldName => $ruleParams[0]);
02450 $valid = $this->dispatchMethod($rule, $ruleParams);
02451 } elseif (in_array($rule, $behaviorMethods) || in_array(strtolower($rule), $behaviorMethods)) {
02452 $ruleParams[] = $validator;
02453 $ruleParams[0] = array($fieldName => $ruleParams[0]);
02454 $valid = $this->Behaviors->dispatchMethod($this, $rule, $ruleParams);
02455 } elseif (method_exists($Validation, $rule)) {
02456 $valid = $Validation->dispatchMethod($rule, $ruleParams);
02457 } elseif (!is_array($validator['rule'])) {
02458 $valid = preg_match($rule, $data[$fieldName]);
02459 }
02460
02461 if (!$valid || (is_string($valid) && strlen($valid) > 0)) {
02462 if (is_string($valid) && strlen($valid) > 0) {
02463 $validator['message'] = $valid;
02464 } elseif (!isset($validator['message'])) {
02465 if (is_string($index)) {
02466 $validator['message'] = $index;
02467 } elseif (is_numeric($index) && count($ruleSet) > 1) {
02468 $validator['message'] = $index + 1;
02469 } else {
02470 $validator['message'] = $message;
02471 }
02472 }
02473 $this->invalidate($fieldName, $validator['message']);
02474
02475 if ($validator['last']) {
02476 break;
02477 }
02478 }
02479 }
02480 }
02481 }
02482 }
02483 $this->validate = $_validate;
02484 return $this->validationErrors;
02485 }
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495 function invalidate($field, $value = true) {
02496 if (!is_array($this->validationErrors)) {
02497 $this->validationErrors = array();
02498 }
02499 $this->validationErrors[$field] = $value;
02500 }
02501
02502
02503
02504
02505
02506
02507
02508 function isForeignKey($field) {
02509 $foreignKeys = array();
02510 if (!empty($this->belongsTo)) {
02511 foreach ($this->belongsTo as $assoc => $data) {
02512 $foreignKeys[] = $data['foreignKey'];
02513 }
02514 }
02515 return in_array($field, $foreignKeys);
02516 }
02517
02518
02519
02520
02521
02522
02523
02524 function getDisplayField() {
02525 return $this->displayField;
02526 }
02527
02528
02529
02530
02531
02532
02533
02534
02535 function escapeField($field = null, $alias = null) {
02536 if (empty($alias)) {
02537 $alias = $this->alias;
02538 }
02539 if (empty($field)) {
02540 $field = $this->primaryKey;
02541 }
02542 $db =& ConnectionManager::getDataSource($this->useDbConfig);
02543 if (strpos($field, $db->name($alias)) === 0) {
02544 return $field;
02545 }
02546 return $db->name($alias . '.' . $field);
02547 }
02548
02549
02550
02551
02552
02553
02554
02555 function getID($list = 0) {
02556 if (empty($this->id) || (is_array($this->id) && isset($this->id[0]) && empty($this->id[0]))) {
02557 return false;
02558 }
02559
02560 if (!is_array($this->id)) {
02561 return $this->id;
02562 }
02563
02564 if (empty($this->id)) {
02565 return false;
02566 }
02567
02568 if (isset($this->id[$list]) && !empty($this->id[$list])) {
02569 return $this->id[$list];
02570 } elseif (isset($this->id[$list])) {
02571 return false;
02572 }
02573
02574 foreach ($this->id as $id) {
02575 return $id;
02576 }
02577
02578 return false;
02579 }
02580
02581
02582
02583
02584
02585
02586 function getLastInsertID() {
02587 return $this->getInsertID();
02588 }
02589
02590
02591
02592
02593
02594
02595 function getInsertID() {
02596 return $this->__insertID;
02597 }
02598
02599
02600
02601
02602
02603
02604 function setInsertID($id) {
02605 $this->__insertID = $id;
02606 }
02607
02608
02609
02610
02611
02612
02613 function getNumRows() {
02614 $db =& ConnectionManager::getDataSource($this->useDbConfig);
02615 return $db->lastNumRows();
02616 }
02617
02618
02619
02620
02621
02622
02623 function getAffectedRows() {
02624 $db =& ConnectionManager::getDataSource($this->useDbConfig);
02625 return $db->lastAffected();
02626 }
02627
02628
02629
02630
02631
02632
02633
02634 function setDataSource($dataSource = null) {
02635 $oldConfig = $this->useDbConfig;
02636
02637 if ($dataSource != null) {
02638 $this->useDbConfig = $dataSource;
02639 }
02640 $db =& ConnectionManager::getDataSource($this->useDbConfig);
02641 if (!empty($oldConfig) && isset($db->config['prefix'])) {
02642 $oldDb =& ConnectionManager::getDataSource($oldConfig);
02643
02644 if (!isset($this->tablePrefix) || (!isset($oldDb->config['prefix']) || $this->tablePrefix == $oldDb->config['prefix'])) {
02645 $this->tablePrefix = $db->config['prefix'];
02646 }
02647 } elseif (isset($db->config['prefix'])) {
02648 $this->tablePrefix = $db->config['prefix'];
02649 }
02650
02651 if (empty($db) || $db == null || !is_object($db)) {
02652 return $this->cakeError('missingConnection', array(array('className' => $this->alias)));
02653 }
02654 }
02655
02656
02657
02658
02659
02660
02661
02662 function &getDataSource() {
02663 $db =& ConnectionManager::getDataSource($this->useDbConfig);
02664 return $db;
02665 }
02666
02667
02668
02669
02670
02671
02672
02673 function getAssociated($type = null) {
02674 if ($type == null) {
02675 $associated = array();
02676 foreach ($this->__associations as $assoc) {
02677 if (!empty($this->{$assoc})) {
02678 $models = array_keys($this->{$assoc});
02679 foreach ($models as $m) {
02680 $associated[$m] = $assoc;
02681 }
02682 }
02683 }
02684 return $associated;
02685 } elseif (in_array($type, $this->__associations)) {
02686 if (empty($this->{$type})) {
02687 return array();
02688 }
02689 return array_keys($this->{$type});
02690 } else {
02691 $assoc = array_merge($this->hasOne, $this->hasMany, $this->belongsTo, $this->hasAndBelongsToMany);
02692 if (array_key_exists($type, $assoc)) {
02693 foreach ($this->__associations as $a) {
02694 if (isset($this->{$a}[$type])) {
02695 $assoc[$type]['association'] = $a;
02696 break;
02697 }
02698 }
02699 return $assoc[$type];
02700 }
02701 return null;
02702 }
02703 }
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713 function joinModel($assoc, $keys = array()) {
02714 if (is_string($assoc)) {
02715 return array($assoc, array_keys($this->{$assoc}->schema()));
02716 } elseif (is_array($assoc)) {
02717 $with = key($assoc);
02718 return array($with, array_unique(array_merge($assoc[$with], $keys)));
02719 } else {
02720 trigger_error(sprintf(__('Invalid join model settings in %s', true), $model->alias), E_USER_WARNING);
02721 }
02722 }
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732 function beforeFind($queryData) {
02733 return true;
02734 }
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745 function afterFind($results, $primary = false) {
02746 return $results;
02747 }
02748
02749
02750
02751
02752
02753
02754
02755
02756 function beforeSave($options = array()) {
02757 return true;
02758 }
02759
02760
02761
02762
02763
02764
02765
02766 function afterSave($created) {
02767 }
02768
02769
02770
02771
02772
02773
02774
02775
02776 function beforeDelete($cascade = true) {
02777 return true;
02778 }
02779
02780
02781
02782
02783
02784
02785 function afterDelete() {
02786 }
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796 function beforeValidate($options = array()) {
02797 return true;
02798 }
02799
02800
02801
02802
02803
02804
02805 function onError() {
02806 }
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816 function _clearCache($type = null) {
02817 if ($type === null) {
02818 if (Configure::read('Cache.check') === true) {
02819 $assoc[] = strtolower(Inflector::pluralize($this->alias));
02820 $assoc[] = strtolower(Inflector::underscore(Inflector::pluralize($this->alias)));
02821 foreach ($this->__associations as $key => $association) {
02822 foreach ($this->$association as $key => $className) {
02823 $check = strtolower(Inflector::pluralize($className['className']));
02824 if (!in_array($check, $assoc)) {
02825 $assoc[] = strtolower(Inflector::pluralize($className['className']));
02826 $assoc[] = strtolower(Inflector::underscore(Inflector::pluralize($className['className'])));
02827 }
02828 }
02829 }
02830 clearCache($assoc);
02831 return true;
02832 }
02833 } else {
02834
02835 }
02836 }
02837
02838
02839
02840
02841
02842
02843 function __sleep() {
02844 $return = array_keys(get_object_vars($this));
02845 return $return;
02846 }
02847
02848
02849
02850
02851
02852
02853 function __wakeup() {
02854 }
02855
02856
02857
02858
02859 function findAll($conditions = null, $fields = null, $order = null, $limit = null, $page = 1, $recursive = null) {
02860
02861 return $this->find('all', compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive'));
02862 }
02863
02864
02865
02866
02867 function findCount($conditions = null, $recursive = 0) {
02868
02869 return $this->find('count', compact('conditions', 'recursive'));
02870 }
02871
02872
02873
02874
02875 function findAllThreaded($conditions = null, $fields = null, $order = null) {
02876
02877 return $this->find('threaded', compact('conditions', 'fields', 'order'));
02878 }
02879
02880
02881
02882
02883 function findNeighbours($conditions = null, $field, $value) {
02884
02885 $query = compact('conditions', 'field', 'value');
02886 $query['fields'] = $field;
02887 if (is_array($field)) {
02888 $query['field'] = $field[0];
02889 }
02890 return $this->find('neighbors', $query);
02891 }
02892 }
02893 if (!defined('CAKEPHP_UNIT_TEST_EXECUTION')) {
02894 Overloadable::overload('Model');
02895 }
02896 ?>