PageRenderTime 48ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/baser/models/baser_app_model.php

https://github.com/hashing/basercms
PHP | 1484 lines | 912 code | 136 blank | 436 comment | 251 complexity | 7920107f9ac3f9f4233305057d90890f MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. /* SVN FILE: $Id$ */
  3. /**
  4. * Model 拡張クラス
  5. *
  6. * PHP versions 5
  7. *
  8. * baserCMS : Based Website Development Project <http://basercms.net>
  9. * Copyright 2008 - 2012, baserCMS Users Community <http://sites.google.com/site/baserusers/>
  10. *
  11. * @copyright Copyright 2008 - 2012, baserCMS Users Community
  12. * @link http://basercms.net baserCMS Project
  13. * @package baser.models
  14. * @since baserCMS v 0.1.0
  15. * @version $Revision$
  16. * @modifiedby $LastChangedBy$
  17. * @lastmodified $Date$
  18. * @license http://basercms.net/license/index.html
  19. */
  20. /**
  21. * Include files
  22. */
  23. uses('sanitize');
  24. /**
  25. * Model 拡張クラス
  26. *
  27. * 既存のCakePHPプロジェクトで、設置済のAppModelと共存できるように、AppModelとは別にした。
  28. *
  29. * @package baser.models
  30. */
  31. class BaserAppModel extends Model {
  32. /**
  33. * driver
  34. *
  35. * @var string
  36. * @access public
  37. */
  38. var $driver = '';
  39. /**
  40. * プラグイン名
  41. *
  42. * @var string
  43. * @access public
  44. */
  45. var $plugin = '';
  46. /**
  47. * DB接続設定名
  48. *
  49. * @var string
  50. * @access public
  51. */
  52. var $useDbConfig = 'baser';
  53. /**
  54. * ビヘイビア
  55. *
  56. * @var array
  57. * @access public
  58. */
  59. var $actsAs = array('BcPluginHook');
  60. /**
  61. * コンストラクタ
  62. *
  63. * @return void
  64. * @access private
  65. */
  66. function __construct($id = false, $table = null, $ds = null) {
  67. if($this->useDbConfig && ($this->name || !empty($id['name']))) {
  68. // DBの設定がない場合、存在しないURLをリクエストすると、エラーが繰り返されてしまい
  69. // Cakeの正常なエラーページが表示されないので、設定がある場合のみ親のコンストラクタを呼び出す。
  70. $cm =& ConnectionManager::getInstance();
  71. if(isset($cm->config->baser['driver'])) {
  72. if($cm->config->baser['driver'] != '') {
  73. parent::__construct($id, $table, $ds);
  74. }elseif($cm->config->baser['login']=='dummy' &&
  75. $cm->config->baser['password']=='dummy' &&
  76. $cm->config->baser['database'] == 'dummy' &&
  77. Configure::read('BcRequest.pureUrl')=='') {
  78. // データベース設定がインストール段階の状態でトップページへのアクセスの場合、
  79. // 初期化ページにリダイレクトする
  80. App::import('Controller','App');
  81. $AppController = new AppController();
  82. session_start();
  83. $_SESSION['Message']['flash'] = array('message'=>'インストールに失敗している可能性があります。<br />インストールを最初からやり直すにはbaserCMSを初期化してください。','layout'=>'default');
  84. $AppController->redirect(BC_BASE_URL.'installations/reset');
  85. }
  86. }
  87. }
  88. }
  89. /**
  90. * beforeSave
  91. *
  92. * @return boolean
  93. * @access public
  94. */
  95. function beforeSave($options) {
  96. $result = parent::beforeSave($options);
  97. // 日付フィールドが空の場合、nullを保存する
  98. foreach ($this->_schema as $key => $field) {
  99. if (('date' == $field['type'] ||
  100. 'datetime' == $field['type'] ||
  101. 'time' == $field['type']) &&
  102. isset($this->data[$this->name][$key])) {
  103. if ($this->data[$this->name][$key] == '') {
  104. $this->data[$this->name][$key] = null;
  105. }
  106. }
  107. }
  108. /* 内部文字コードをデータベース文字コードに変換 */
  109. // MySQL4.0 以下で動作
  110. if($this->driver == 'mysql' && mysql_get_server_info() <= 4.0) {
  111. $this->data = $this->convertEncodingByArray($this->data, Configure::read('Config.dbCharset'), mb_internal_encoding());
  112. }
  113. return $result;
  114. }
  115. /**
  116. * Saves model data to the database. By default, validation occurs before save.
  117. *
  118. * @param array $data Data to save.
  119. * @param boolean $validate If set, validation will be done before the save
  120. * @param array $fieldList List of fields to allow to be written
  121. * @return mixed On success Model::$data if its not empty or true, false on failure
  122. * @access public
  123. */
  124. function save($data = null, $validate = true, $fieldList = array()) {
  125. if(!$data)
  126. $data = $this->data;
  127. // created,modifiedが更新されないバグ?対応
  128. if (!$this->exists()) {
  129. if(isset($data[$this->alias])) {
  130. $data[$this->alias]['created']=null;
  131. }else {
  132. $data['created']=null;
  133. }
  134. }
  135. if(isset($data[$this->alias])) {
  136. $data[$this->alias]['modified']=null;
  137. }else {
  138. $data['modified']=null;
  139. }
  140. return parent::save($data, $validate, $fieldList);
  141. }
  142. /**
  143. * 配列の文字コードを変換する
  144. *
  145. * TODO GLOBAL グローバルな関数として再配置する必要あり
  146. *
  147. * @param array 変換前のデータ
  148. * @param string 変換元の文字コード
  149. * @param string 変換後の文字コード
  150. * @return array 変換後のデータ
  151. * @access public
  152. */
  153. function convertEncodingByArray($data, $outenc ,$inenc) {
  154. foreach($data as $key=>$value) {
  155. if(is_array($value)) {
  156. $data[$key] = $this->convertEncodingByArray($value, $outenc, $inenc);
  157. } else {
  158. if (mb_detect_encoding($value) <> $outenc) {
  159. $data[$key] = mb_convert_encoding($value, $outenc, $inenc);
  160. }
  161. }
  162. }
  163. return $data;
  164. }
  165. /**
  166. * データベースログを記録する
  167. *
  168. * @param string $message
  169. * @return boolean
  170. * @access public
  171. */
  172. function saveDbLog($message) {
  173. // ログを記録する
  174. App::import('Model', 'Dblog');
  175. $Dblog = new Dblog();
  176. $logdata['Dblog']['name'] = $message;
  177. $logdata['Dblog']['user_id'] = @$_SESSION['Auth']['User']['id'];
  178. return $Dblog->save($logdata);
  179. }
  180. /**
  181. * フォームの初期値を設定する
  182. *
  183. * 継承先でオーバーライドする事
  184. *
  185. * @return array
  186. * @access public
  187. */
  188. function getDefaultValue() {
  189. return array();
  190. }
  191. /**
  192. * コントロールソースを取得する
  193. *
  194. * 継承先でオーバーライドする事
  195. *
  196. * @return array
  197. * @access public
  198. */
  199. function getControlSources() {
  200. return array();
  201. }
  202. /**
  203. * 子カテゴリのIDリストを取得する
  204. *
  205. * treeビヘイビア要
  206. *
  207. * @param mixed $id
  208. * @return array
  209. * @access public
  210. */
  211. function getChildIdsList($id) {
  212. $ids = array();
  213. if($this->childcount($id)) {
  214. $children = $this->children($id);
  215. foreach($children as $child) {
  216. $ids[] = (int)$child[$this->name]['id'];
  217. }
  218. }
  219. return $ids;
  220. }
  221. /**
  222. * 機種依存文字の変換処理
  223. *
  224. * 内部文字コードがUTF-8である必要がある。
  225. * 多次元配列には対応していない。
  226. *
  227. * @param string 変換対象文字列
  228. * @return string 変換後文字列
  229. * @access public
  230. * TODO AppExModeに移行すべきかも
  231. */
  232. function replaceText($str) {
  233. $ret = $str;
  234. $arr = array(
  235. "\xE2\x85\xA0" => "I",
  236. "\xE2\x85\xA1" => "II",
  237. "\xE2\x85\xA2" => "III",
  238. "\xE2\x85\xA3" => "IV",
  239. "\xE2\x85\xA4" => "V",
  240. "\xE2\x85\xA5" => "VI",
  241. "\xE2\x85\xA6" => "VII",
  242. "\xE2\x85\xA7" => "VIII",
  243. "\xE2\x85\xA8" => "IX",
  244. "\xE2\x85\xA9" => "X",
  245. "\xE2\x85\xB0" => "i",
  246. "\xE2\x85\xB1" => "ii",
  247. "\xE2\x85\xB2" => "iii",
  248. "\xE2\x85\xB3" => "iv",
  249. "\xE2\x85\xB4" => "v",
  250. "\xE2\x85\xB5" => "vi",
  251. "\xE2\x85\xB6" => "vii",
  252. "\xE2\x85\xB7" => "viii",
  253. "\xE2\x85\xB8" => "ix",
  254. "\xE2\x85\xB9" => "x",
  255. "\xE2\x91\xA0" => "(1)",
  256. "\xE2\x91\xA1" => "(2)",
  257. "\xE2\x91\xA2" => "(3)",
  258. "\xE2\x91\xA3" => "(4)",
  259. "\xE2\x91\xA4" => "(5)",
  260. "\xE2\x91\xA5" => "(6)",
  261. "\xE2\x91\xA6" => "(7)",
  262. "\xE2\x91\xA7" => "(8)",
  263. "\xE2\x91\xA8" => "(9)",
  264. "\xE2\x91\xA9" => "(10)",
  265. "\xE2\x91\xAA" => "(11)",
  266. "\xE2\x91\xAB" => "(12)",
  267. "\xE2\x91\xAC" => "(13)",
  268. "\xE2\x91\xAD" => "(14)",
  269. "\xE2\x91\xAE" => "(15)",
  270. "\xE2\x91\xAF" => "(16)",
  271. "\xE2\x91\xB0" => "(17)",
  272. "\xE2\x91\xB1" => "(18)",
  273. "\xE2\x91\xB2" => "(19)",
  274. "\xE2\x91\xB3" => "(20)",
  275. "\xE3\x8A\xA4" => "(上)",
  276. "\xE3\x8A\xA5" => "(中)",
  277. "\xE3\x8A\xA6" => "(下)",
  278. "\xE3\x8A\xA7" => "(左)",
  279. "\xE3\x8A\xA8" => "(右)",
  280. "\xE3\x8D\x89" => "ミリ",
  281. "\xE3\x8D\x8D" => "メートル",
  282. "\xE3\x8C\x94" => "キロ",
  283. "\xE3\x8C\x98" => "グラム",
  284. "\xE3\x8C\xA7" => "トン",
  285. "\xE3\x8C\xA6" => "ドル",
  286. "\xE3\x8D\x91" => "リットル",
  287. "\xE3\x8C\xAB" => "パーセント",
  288. "\xE3\x8C\xA2" => "センチ",
  289. "\xE3\x8E\x9D" => "cm",
  290. "\xE3\x8E\x8F" => "kg",
  291. "\xE3\x8E\xA1" => "m2",
  292. "\xE3\x8F\x8D" => "K.K.",
  293. "\xE2\x84\xA1" => "TEL",
  294. "\xE2\x84\x96" => "No.",
  295. "\xE3\x8D\xBB" => "平成",
  296. "\xE3\x8D\xBC" => "昭和",
  297. "\xE3\x8D\xBD" => "大正",
  298. "\xE3\x8D\xBE" => "明治",
  299. "\xE3\x88\xB1" => "(株)",
  300. "\xE3\x88\xB2" => "(有)",
  301. "\xE3\x88\xB9" => "(代)",
  302. );
  303. return str_replace( array_keys( $arr), array_values( $arr), $str);
  304. }
  305. /**
  306. * データベースを初期化
  307. *
  308. * 既に存在するテーブルは上書きしない
  309. *
  310. * @param array データベース設定名
  311. * @param string プラグイン名
  312. * @return boolean
  313. * @access public
  314. */
  315. function initDb($dbConfigName, $pluginName = '', $loadCsv = true, $filterTable = '', $filterType = '') {
  316. // 初期データフォルダを走査
  317. if(!$pluginName) {
  318. $path = BASER_CONFIGS.'sql';
  319. } else {
  320. $appPath = APP.'plugins'.DS.$pluginName.DS.'config'.DS.'sql';
  321. $baserPath = BASER_PLUGINS.$pluginName.DS.'config'.DS.'sql';
  322. if(file_exists($appPath)) {
  323. $path = $appPath;
  324. } elseif (file_exists($baserPath)) {
  325. $path = $baserPath;
  326. } else {
  327. return true;
  328. }
  329. }
  330. if($this->loadSchema($dbConfigName, $path, $filterTable, $filterType, array(), $dropField = false)){
  331. if($loadCsv) {
  332. return $this->loadCsv($dbConfigName, $path);
  333. } else {
  334. return true;
  335. }
  336. } else {
  337. return false;
  338. }
  339. }
  340. /**
  341. * スキーマファイルを利用してデータベース構造を変更する
  342. *
  343. * @param array データベース設定名
  344. * @param string スキーマファイルのパス
  345. * @param string テーブル指定
  346. * @param string 更新タイプ指定
  347. * @return boolean
  348. * @access public
  349. */
  350. function loadSchema($dbConfigName, $path, $filterTable='', $filterType='', $excludePath = array(), $dropField = true) {
  351. // テーブルリストを取得
  352. $db =& ConnectionManager::getDataSource($dbConfigName);
  353. $db->cacheSources = false;
  354. $listSources = $db->listSources();
  355. $prefix = $db->config['prefix'];
  356. $Folder = new Folder($path);
  357. $files = $Folder->read(true, true);
  358. foreach($files[1] as $file) {
  359. if(in_array($file, $excludePath)) {
  360. continue;
  361. }
  362. if(preg_match('/^(.*?)\.php$/', $file, $matches)) {
  363. $type = 'create';
  364. $table = $matches[1];
  365. if(preg_match('/^create_(.*?)\.php$/', $file, $matches)) {
  366. $type = 'create';
  367. $table = $matches[1];
  368. if(in_array($prefix . $table, $listSources)) {
  369. continue;
  370. }
  371. } elseif (preg_match('/^alter_(.*?)\.php$/', $file, $matches)) {
  372. $type = 'alter';
  373. $table = $matches[1];
  374. if(!in_array($prefix . $table, $listSources)) {
  375. continue;
  376. }
  377. } elseif (preg_match('/^drop_(.*?)\.php$/', $file, $matches)) {
  378. $type = 'drop';
  379. $table = $matches[1];
  380. if(!in_array($prefix . $table, $listSources)) {
  381. continue;
  382. }
  383. } else {
  384. if(in_array($prefix . $table, $listSources)) {
  385. continue;
  386. }
  387. }
  388. if($filterTable && $filterTable != $table) {
  389. continue;
  390. }
  391. if($filterType && $filterType != $type) {
  392. continue;
  393. }
  394. $tmpdir = TMP.'schemas'.DS;
  395. copy($path.DS.$file,$tmpdir.$table.'.php');
  396. $result = $db->loadSchema(array('type'=>$type, 'path' => $tmpdir, 'file'=> $table.'.php', 'dropField' => $dropField));
  397. @unlink($tmpdir.$file);
  398. if(!$result) {
  399. return false;
  400. }
  401. }
  402. }
  403. $folder = new Folder(CACHE.'datas');
  404. $files = $folder->read(true, true, true);
  405. foreach($files[1] as $file) {
  406. @unlink($file);
  407. }
  408. return true;
  409. }
  410. /**
  411. * CSVを読み込む
  412. *
  413. * @param array データベース設定名
  414. * @param string CSVパス
  415. * @param string テーブル指定
  416. * @return boolean
  417. * @access public
  418. */
  419. function loadCsv($dbConfigName, $path, $filterTable='') {
  420. // テーブルリストを取得
  421. $db =& ConnectionManager::getDataSource($dbConfigName);
  422. $db->cacheSources = false;
  423. $listSources = $db->listSources();
  424. $prefix = $db->config['prefix'];
  425. $Folder = new Folder($path);
  426. $files = $Folder->read(true, true);
  427. foreach($files[1] as $file) {
  428. if (preg_match('/^(.*?)\.csv$/', $file, $matches)) {
  429. $table = $matches[1];
  430. if(in_array($prefix . $table, $listSources)) {
  431. if($filterTable && $filterTable != $table) {
  432. continue;
  433. }
  434. if(!$db->loadCsv(array('path'=>$path.DS.$file, 'encoding'=>'SJIS'))){
  435. return false;
  436. }
  437. }
  438. }
  439. }
  440. return true;
  441. }
  442. /**
  443. * データベースを復元する
  444. * 既にあるテーブルは上書きしない
  445. * @param array $config
  446. * @param string $source
  447. */
  448. function restoreDb($config, $source) {
  449. App::import('Vendor','DbRestore',array('file'=>'dbrestore.php'));
  450. $dbType = preg_replace('/^bc_/', '', $config['driver']);
  451. switch ($dbType) {
  452. case 'mysql':
  453. $connection = @mysql_connect($config['host'],$config['login'],$config['password']);
  454. $sql = "SET NAMES ".Configure::read('internalEncodingByMySql');
  455. mysql_query($sql);
  456. $dbRestore = new DbRestore('mysql');
  457. $dbRestore->connect($config['database'], $config['host'], $config['login'], $config['password'],$config['port']);
  458. return $dbRestore->doRestore($source);
  459. break;
  460. case 'postgres':
  461. $dbRestore = new DbRestore('postgres');
  462. $dbRestore->connect($config['database'], $config['host'], $config['login'], $config['password'],$config['port']);
  463. return $dbRestore->doRestore($source);
  464. break;
  465. case 'sqlite':
  466. case 'sqlite3':
  467. if($config['driver']=='bc_sqlite3') {
  468. $driver = 'sqlite3';
  469. }else {
  470. $driver = $config['driver'];
  471. }
  472. $dbRestore = new DbRestore($driver);
  473. $dbRestore->connect($config['database']);
  474. return $dbRestore->doRestore($source);
  475. break;
  476. case 'csv':
  477. $targetDir = APP.'db'.DS.'csv'.DS.'baser'.DS;
  478. $folder = new Folder($source);
  479. $files = $folder->read(true,true);
  480. $ret = true;
  481. foreach($files[1] as $file) {
  482. if($file != 'empty' && $ret) {
  483. if (!file_exists($targetDir.$config['prefix'].$file)) {
  484. $_ret = copy($source.$file,$targetDir.$config['prefix'].$file);
  485. if ($_ret) {
  486. chmod($targetDir.$config['prefix'].$file,0666);
  487. }else {
  488. $ret = $_ret;
  489. }
  490. }
  491. }
  492. }
  493. return $ret;
  494. break;
  495. }
  496. }
  497. /**
  498. * 最短の長さチェック
  499. *
  500. * @param mixed $check
  501. * @param int $min
  502. * @return boolean
  503. * @access public
  504. */
  505. function minLength($check, $min) {
  506. $check=(is_array($check))?current($check):$check;
  507. $length = mb_strlen($check,Configure::read('App.encoding'));
  508. return ($length >= $min);
  509. }
  510. /**
  511. * 最長の長さチェック
  512. *
  513. * @param mixed $check
  514. * @param int $max
  515. * @param boolean
  516. * @access public
  517. */
  518. function maxLength($check, $max) {
  519. $check=(is_array($check))?current($check):$check;
  520. $length = mb_strlen($check,Configure::read('App.encoding'));
  521. return ($length <= $max);
  522. }
  523. /**
  524. * 範囲を指定しての長さチェック
  525. *
  526. * @param mixed $check
  527. * @param int $min
  528. * @param int $max
  529. * @param boolean
  530. * @access public
  531. */
  532. function between($check, $min, $max) {
  533. $check=(is_array($check))?current($check):$check;
  534. $length = mb_strlen($check,Configure::read('App.encoding'));
  535. return ($length >= $min && $length <= $max);
  536. }
  537. /**
  538. * 指定フィールドのMAX値を取得する
  539. *
  540. * 現在数値フィールドのみ対応
  541. *
  542. * @param string $field
  543. * @param array $conditions
  544. * @return int
  545. */
  546. function getMax($field,$conditions=array()) {
  547. if(strpos($field,'.') === false) {
  548. $modelName = $this->alias;
  549. }else {
  550. list($modelName,$field) = split('\.',$field);
  551. }
  552. $db =& ConnectionManager::getDataSource($this->useDbConfig);
  553. $this->recursive = -1;
  554. if($db->config['driver']=='bc_csv') {
  555. // CSVDBの場合はMAX関数が利用できない為、プログラムで処理する
  556. // TODO dboでMAX関数の実装できたらここも変更する
  557. $this->cacheQueries=false;
  558. $dbDatas = $this->find('all',array('conditions'=>$conditions,'fields'=>array($modelName.'.'.$field)));
  559. $this->cacheQueries=true;
  560. $max = 0;
  561. if($dbDatas) {
  562. foreach($dbDatas as $dbData) {
  563. if($max < $dbData[$modelName][$field]) {
  564. $max = $dbData[$modelName][$field];
  565. }
  566. }
  567. }
  568. return $max;
  569. }else {
  570. $this->cacheQueries=false;
  571. // SQLiteの場合、Max関数にmodel名を含むと、戻り値の添字が崩れる(CakePHPのバグ)
  572. $dbData = $this->find('all',array('conditions'=>$conditions,'fields'=>array('MAX('.$field.')')));
  573. $this->cacheQueries=true;
  574. if(isset($dbData[0][0]['MAX('.$field.')'])) {
  575. return $dbData[0][0]['MAX('.$field.')'];
  576. }elseif(isset($dbData[0][0]['max'])) {
  577. return $dbData[0][0]['max'];
  578. }else {
  579. return 0;
  580. }
  581. }
  582. }
  583. /**
  584. * テーブルにフィールドを追加する
  585. *
  586. * @param array $options [ field / column / table ]
  587. * @return boolean
  588. * @access public
  589. */
  590. function addField($options) {
  591. extract($options);
  592. if(!isset($field) || !isset($column)) {
  593. return false;
  594. }
  595. if(!isset($table)) {
  596. $table = $this->useTable;
  597. }
  598. $this->_schema=null;
  599. $db =& ConnectionManager::getDataSource($this->useDbConfig);
  600. $options = array('field'=>$field, 'table'=>$table, 'column'=>$column);
  601. $ret = $db->addColumn($options);
  602. $this->deleteModelCache();
  603. return $ret;
  604. }
  605. /**
  606. * フィールド構造を変更する
  607. *
  608. * @param array $options [ field / column / table ]
  609. * @return boolean
  610. * @access public
  611. */
  612. function editField($options) {
  613. extract($options);
  614. if(!isset($field) || !isset($column)) {
  615. return false;
  616. }
  617. if(!isset($table)) {
  618. $table = $this->useTable;
  619. }
  620. $this->_schema = null;
  621. $db =& ConnectionManager::getDataSource($this->useDbConfig);
  622. $options = array('field'=>$field,'table'=>$table, 'column'=>$column);
  623. $ret = $db->changeColumn($options);
  624. $this->deleteModelCache();
  625. return $ret;
  626. }
  627. /**
  628. * フィールドを削除する
  629. *
  630. * @param array $options [ field / table ]
  631. * @return boolean
  632. * @access public
  633. */
  634. function delField($options) {
  635. extract($options);
  636. if(!isset($field)) {
  637. return false;
  638. }
  639. if(!isset($table)) {
  640. $table = $this->useTable;
  641. }
  642. $this->_schema=null;
  643. $db =& ConnectionManager::getDataSource($this->useDbConfig);
  644. $options = array('field'=>$field,'table'=>$table);
  645. $ret = $db->dropColumn($options);
  646. $this->deleteModelCache();
  647. return $ret;
  648. }
  649. /**
  650. * フィールド名を変更する
  651. *
  652. * @param array $options [ new / old / table ]
  653. * @param array $column
  654. * @return boolean
  655. * @access public
  656. */
  657. function renameField($options) {
  658. extract($options);
  659. if(!isset($new) || !isset($old)) {
  660. return false;
  661. }
  662. if(!isset($table)) {
  663. $table = $this->useTable;
  664. }
  665. $this->_schema=null;
  666. $db =& ConnectionManager::getDataSource($this->useDbConfig);
  667. $options = array('new'=>$new, 'old'=>$old, 'table'=>$table);
  668. $ret = $db->renameColumn($options);
  669. $this->deleteModelCache();
  670. return $ret;
  671. }
  672. /**
  673. * テーブルの存在チェックを行う
  674. * @param string $tableName
  675. * @return boolean
  676. */
  677. function tableExists ($tableName) {
  678. $db =& ConnectionManager::getDataSource($this->useDbConfig);
  679. $db->cacheSources = false;
  680. $tables = $db->listSources();
  681. return in_array($tableName, $tables);
  682. }
  683. /**
  684. * 英数チェック
  685. *
  686. * @param string チェック対象文字列
  687. * @return boolean
  688. * @access public
  689. */
  690. function alphaNumeric($check) {
  691. if(!$check[key($check)]) {
  692. return true;
  693. }
  694. if(preg_match("/^[a-zA-Z0-9]+$/",$check[key($check)])) {
  695. return true;
  696. }else {
  697. return false;
  698. }
  699. }
  700. /**
  701. * 英数チェックプラス
  702. *
  703. * ハイフンアンダースコアを許容
  704. *
  705. * @param string チェック対象文字列
  706. * @return boolean
  707. * @access public
  708. */
  709. function alphaNumericPlus($check) {
  710. if(!$check[key($check)]) {
  711. return true;
  712. }
  713. if(preg_match("/^[a-zA-Z0-9\-_]+$/",$check[key($check)])) {
  714. return true;
  715. }else {
  716. return false;
  717. }
  718. }
  719. /**
  720. * データの重複チェックを行う
  721. * @param array $check
  722. * @return boolean
  723. */
  724. function duplicate($check,$field) {
  725. $conditions = array($this->alias.'.'.key($check)=>$check[key($check)]);
  726. if($this->exists()) {
  727. $conditions['NOT'] = array($this->alias.'.id'=>$this->id);
  728. }
  729. $ret = $this->find($conditions);
  730. if($ret) {
  731. return false;
  732. }else {
  733. return true;
  734. }
  735. }
  736. /**
  737. * ファイルサイズチェック
  738. */
  739. function fileSize($check,$size) {
  740. $file = $check[key($check)];
  741. if(!empty($file['name'])) {
  742. // サイズが空の場合は、HTMLのMAX_FILE_SIZEの制限によりサイズオーバー
  743. if(!$file['size']) return false;
  744. if($file['size']>$size) return;
  745. }
  746. return true;
  747. }
  748. /**
  749. * 半角チェック
  750. * @param array $check
  751. * @return boolean
  752. */
  753. function halfText($check) {
  754. $value = $check[key($check)];
  755. $len = strlen($value);
  756. $mblen = mb_strlen($value,'UTF-8');
  757. if($len != $mblen) {
  758. return false;
  759. }
  760. return true;
  761. }
  762. /**
  763. * 一つ位置を上げる
  764. * @param string $id
  765. * @param array $conditions
  766. * @return boolean
  767. */
  768. function sortup($id,$conditions) {
  769. return $this->changeSort($id,-1,$conditions);
  770. }
  771. /**
  772. * 一つ位置を下げる
  773. * @param string $id
  774. * @param array $conditions
  775. * @return boolean
  776. */
  777. function sortdown($id,$conditions) {
  778. return $this->changeSort($id,1,$conditions);
  779. }
  780. /**
  781. * 並び順を変更する
  782. * @param string $id
  783. * @param int $offset
  784. * @param array $conditions
  785. * @return boolean
  786. */
  787. function changeSort($id,$offset,$conditions=array()) {
  788. if($conditions) {
  789. $_conditions = $conditions;
  790. } else {
  791. $_conditions = array();
  792. }
  793. // 一時的にキャッシュをOFFする
  794. $this->cacheQueries = false;
  795. $current = $this->find(array($this->alias.'.id'=>$id),array($this->alias.'.id',$this->alias.'.sort'));
  796. // 変更相手のデータを取得
  797. if($offset > 0) { // DOWN
  798. $order = array($this->alias.'.sort');
  799. $limit = $offset;
  800. $conditions[$this->alias.'.sort >'] = $current[$this->alias]['sort'];
  801. }elseif($offset < 0) { // UP
  802. $order = array($this->alias.'.sort DESC');
  803. $limit = $offset * -1;
  804. $conditions[$this->alias.'.sort <'] = $current[$this->alias]['sort'];
  805. }else {
  806. return true;
  807. }
  808. $conditions = am($conditions,$_conditions);
  809. $target = $this->find('all',array('conditions'=>$conditions,
  810. 'fields'=>array($this->alias.'.id',$this->alias.'.sort'),
  811. 'order'=>$order,
  812. 'limit'=>$limit,
  813. 'recursive'=>-1));
  814. if(!isset($target[count($target)-1])) {
  815. return false;
  816. }
  817. $currentSort = $current[$this->alias]['sort'];
  818. $targetSort = $target[count($target)-1][$this->alias]['sort'];
  819. // current から target までのデータをsortで範囲指定して取得
  820. $conditions = array();
  821. if($offset > 0) { // DOWN
  822. $conditions[$this->alias.'.sort >='] = $currentSort;
  823. $conditions[$this->alias.'.sort <='] = $targetSort;
  824. }elseif($offset < 0) { // UP
  825. $conditions[$this->alias.'.sort <='] = $currentSort;
  826. $conditions[$this->alias.'.sort >='] = $targetSort;
  827. }
  828. $conditions = am($conditions,$_conditions);
  829. $datas = $this->find('all',array('conditions'=>$conditions,
  830. 'fields'=>array($this->alias.'.id',$this->alias.'.sort'),
  831. 'order'=>$order,
  832. 'recursive'=>-1));
  833. // 全てのデータを更新
  834. foreach ($datas as $data) {
  835. if($data[$this->alias]['sort'] == $currentSort) {
  836. $data[$this->alias]['sort'] = $targetSort;
  837. } else {
  838. if($offset > 0) {
  839. $data[$this->alias]['sort']--;
  840. }elseif($offset < 0) {
  841. $data[$this->alias]['sort']++;
  842. }
  843. }
  844. if(!$this->save($data,false)){
  845. return false;
  846. }
  847. }
  848. return true;
  849. }
  850. /**
  851. * Modelキャッシュを削除する
  852. * @return void
  853. * @access public
  854. */
  855. function deleteModelCache() {
  856. $this->_schema = null;
  857. App::import('Core','Folder');
  858. $folder = new Folder(CACHE.'models'.DS);
  859. $caches = $folder->read(true,true);
  860. foreach($caches[1] as $cache) {
  861. if(basename($cache) != 'empty') {
  862. @unlink(CACHE.'models'.DS.$cache);
  863. }
  864. }
  865. }
  866. /**
  867. * Key Value 形式のテーブルよりデータを取得して
  868. * 1レコードとしてデータを展開する
  869. * @return array
  870. */
  871. function findExpanded() {
  872. $dbDatas = $this->find('all',array('fields'=>array('name','value')));
  873. $expandedData = array();
  874. if($dbDatas) {
  875. foreach($dbDatas as $dbData) {
  876. $expandedData[$dbData[$this->alias]['name']] = $dbData[$this->alias]['value'];
  877. }
  878. }
  879. return $expandedData;
  880. }
  881. /**
  882. * Key Value 形式のテーブルにデータを保存する
  883. * @param array $data
  884. * @return boolean
  885. */
  886. function saveKeyValue($data) {
  887. if(isset($data[$this->alias])) {
  888. $data = $data[$this->alias];
  889. }
  890. $result = true;
  891. foreach($data as $key => $value) {
  892. $dbData = $this->find('first', array('conditions'=>array('name'=>$key)));
  893. if(!$dbData) {
  894. $dbData = array();
  895. $dbData[$this->alias]['name'] = $key;
  896. $dbData[$this->alias]['value'] = $value;
  897. $this->create($dbData);
  898. }else {
  899. $dbData[$this->alias]['value'] = $value;
  900. $this->set($dbData);
  901. }
  902. // SQliteの場合、トランザクション用の関数をサポートしていない場合があるので、
  903. // 個別に保存するようにした。
  904. if(!$this->save(null,false)) {
  905. $result = false;
  906. }
  907. }
  908. return true;
  909. }
  910. /**
  911. * リストチェック
  912. * リストに含む場合はエラー
  913. *
  914. * @param string $check Value to check
  915. * @param array $list List to check against
  916. * @return boolean Succcess
  917. * @access public
  918. */
  919. function notInList($check, $list) {
  920. return !in_array($check[key($check)], $list);
  921. }
  922. /**
  923. * Deconstructs a complex data type (array or object) into a single field value.
  924. *
  925. * @param string $field The name of the field to be deconstructed
  926. * @param mixed $data An array or object to be deconstructed into a field
  927. * @return mixed The resulting data that should be assigned to a field
  928. * @access public
  929. */
  930. function deconstruct($field, $data) {
  931. if (!is_array($data)) {
  932. return $data;
  933. }
  934. $copy = $data;
  935. $type = $this->getColumnType($field);
  936. // >>> CUSTOMIZE MODIFY 2011/01/11 ryuring 和暦対応
  937. // メールフォームで生成するフィールドは全てテキストの為(暫定)
  938. //if (in_array($type, array('datetime', 'timestamp', 'date', 'time'))) {
  939. // ---
  940. if (in_array($type, array('string', 'text', 'datetime', 'timestamp', 'date', 'time'))) {
  941. // <<<
  942. $useNewDate = (isset($data['year']) || isset($data['month']) ||
  943. isset($data['day']) || isset($data['hour']) || isset($data['minute']));
  944. // >>> CUSTOMIZE MODIFY 2011/01/11 ryuring 和暦対応
  945. //$dateFields = array('Y' => 'year', 'm' => 'month', 'd' => 'day', 'H' => 'hour', 'i' => 'min', 's' => 'sec');
  946. // ---
  947. $dateFields = array('W'=>'wareki', 'Y' => 'year', 'm' => 'month', 'd' => 'day', 'H' => 'hour', 'i' => 'min', 's' => 'sec');
  948. // <<<
  949. $timeFields = array('H' => 'hour', 'i' => 'min', 's' => 'sec');
  950. // >>> CUSTOMIZE MODIFY 2011/01/11 ryuring 和暦対応
  951. // メールフォームで生成するフィールドは全てテキストの為(暫定)
  952. //$db =& ConnectionManager::getDataSource($this->useDbConfig);
  953. //$format = $db->columns[$type]['format'];
  954. // ---
  955. if($type != 'text' && $type != 'string') {
  956. $db =& ConnectionManager::getDataSource($this->useDbConfig);
  957. $format = $db->columns[$type]['format'];
  958. } else {
  959. $format = 'Y-m-d H:i:s';
  960. }
  961. // <<<
  962. $date = array();
  963. if (isset($data['hour']) && isset($data['meridian']) && $data['hour'] != 12 && 'pm' == $data['meridian']) {
  964. $data['hour'] = $data['hour'] + 12;
  965. }
  966. if (isset($data['hour']) && isset($data['meridian']) && $data['hour'] == 12 && 'am' == $data['meridian']) {
  967. $data['hour'] = '00';
  968. }
  969. if ($type == 'time') {
  970. foreach ($timeFields as $key => $val) {
  971. if (!isset($data[$val]) || $data[$val] === '0' || $data[$val] === '00') {
  972. $data[$val] = '00';
  973. } elseif ($data[$val] === '') {
  974. $data[$val] = '';
  975. } else {
  976. $data[$val] = sprintf('%02d', $data[$val]);
  977. }
  978. if (!empty($data[$val])) {
  979. $date[$key] = $data[$val];
  980. } else {
  981. return null;
  982. }
  983. }
  984. }
  985. // >>> CUSTOMIZE MODIFY 2011/01/11 ryuring 和暦対応
  986. // メールフォームで生成するフィールドは全てテキストの為(暫定)
  987. //if ($type == 'datetime' || $type == 'timestamp' || $type == 'date') {
  988. // ---
  989. if ($type == 'text' || $type == 'string' || $type == 'datetime' || $type == 'timestamp' || $type == 'date') {
  990. // <<<
  991. foreach ($dateFields as $key => $val) {
  992. if ($val == 'hour' || $val == 'min' || $val == 'sec') {
  993. if (!isset($data[$val]) || $data[$val] === '0' || $data[$val] === '00') {
  994. $data[$val] = '00';
  995. } else {
  996. $data[$val] = sprintf('%02d', $data[$val]);
  997. }
  998. }
  999. // >>> CUSTOMIZE ADD 2011/01/11 ryuring 和暦対応
  1000. if($val == 'wareki' && !empty($data['wareki'])) {
  1001. $warekis = array('m'=>1867, 't'=>1911, 's'=>1925, 'h'=>1988);
  1002. if(!empty($data['year'])) {
  1003. list($wareki, $year) = split('-', $data['year']);
  1004. $data['year'] = $year + $warekis[$wareki];
  1005. }
  1006. }
  1007. // <<<
  1008. // >>> CUSTOMIZE MODIFY 2011/02/17 ryuring 和暦対応
  1009. // if (!isset($data[$val]) || isset($data[$val]) && (empty($data[$val]) || $data[$val][0] === '-')) {
  1010. // return null;
  1011. // ---
  1012. if ($val != 'wareki' && (!isset($data[$val]) || isset($data[$val]) && (empty($data[$val]) || $data[$val][0] === '-'))) {
  1013. if($type != 'text' && $type != 'string') {
  1014. return null;
  1015. } else {
  1016. return $data;
  1017. }
  1018. // <<<
  1019. }
  1020. if (isset($data[$val]) && !empty($data[$val])) {
  1021. $date[$key] = $data[$val];
  1022. }
  1023. }
  1024. }
  1025. $date = str_replace(array_keys($date), array_values($date), $format);
  1026. if ($useNewDate && !empty($date)) {
  1027. return $date;
  1028. }
  1029. }
  1030. return $data;
  1031. }
  1032. /**
  1033. * 2つのフィールド値を確認する
  1034. *
  1035. * @param array $check
  1036. * @param mixed $fields
  1037. * @return boolean
  1038. * @access public
  1039. */
  1040. function confirm($check, $fields) {
  1041. $value1 = $value2 = '';
  1042. if(is_array($fields) && count($fields) > 1) {
  1043. if(isset($this->data[$this->alias][$fields[0]]) &&
  1044. isset($this->data[$this->alias][$fields[1]])) {
  1045. $value1 = $this->data[$this->alias][$fields[0]];
  1046. $value2 = $this->data[$this->alias][$fields[1]];
  1047. }
  1048. } elseif($fields) {
  1049. if(isset($check[key($check)]) && isset($this->data[$this->alias][$fields])) {
  1050. $value1 = $check[key($check)];
  1051. $value2 = $this->data[$this->alias][$fields];
  1052. }
  1053. } else {
  1054. return false;
  1055. }
  1056. if($value1 != $value2) {
  1057. return false;
  1058. }
  1059. return true;
  1060. }
  1061. /**
  1062. * afterFind
  1063. *
  1064. * @param mixed $results
  1065. * @return mixed $results
  1066. * @access public
  1067. */
  1068. function afterFind($results) {
  1069. /* データベース文字コードを内部文字コードに変換 */
  1070. // MySQL4.0 以下で動作
  1071. if($this->driver == 'mysql' && mysql_get_server_info() <= 4.0) {
  1072. $results = $this->convertEncodingByArray($results, mb_internal_encoding(), Configure::read('Config.dbCharset'));
  1073. }
  1074. return parent::afterFind($results);
  1075. }
  1076. /**
  1077. * Unbinds all relations from a model
  1078. *
  1079. * @param string unbinds all related models.
  1080. * @return void
  1081. * @access public
  1082. */
  1083. function expects($arguments, $reset = true) {
  1084. $models = array();
  1085. foreach($arguments as $index => $argument)
  1086. {
  1087. if (is_array($argument))
  1088. {
  1089. if (count($argument) > 0)
  1090. {
  1091. $arguments = am($arguments, $argument);
  1092. }
  1093. unset($arguments[$index]);
  1094. }
  1095. }
  1096. foreach($arguments as $index => $argument)
  1097. {
  1098. if (!is_string($argument))
  1099. {
  1100. unset($arguments[$index]);
  1101. }
  1102. }
  1103. if (count($arguments) == 0)
  1104. {
  1105. $models[$this->name] = array();
  1106. }
  1107. else
  1108. {
  1109. foreach($arguments as $argument)
  1110. {
  1111. if (strpos($argument, '.') !== false)
  1112. {
  1113. $model = substr($argument, 0, strpos($argument, '.'));
  1114. $child = substr($argument, strpos($argument, '.') + 1);
  1115. if ($child == $model)
  1116. {
  1117. $models[$model] = array();
  1118. }
  1119. else
  1120. {
  1121. $models[$model][] = $child;
  1122. }
  1123. }
  1124. else
  1125. {
  1126. $models[$this->name][] = $argument;
  1127. }
  1128. }
  1129. }
  1130. $relationTypes = array ('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
  1131. foreach($models as $bindingName => $children)
  1132. {
  1133. $model = null;
  1134. foreach($relationTypes as $relationType)
  1135. {
  1136. $currentRelation = (isset($this->$relationType) ? $this->$relationType : null);
  1137. if (isset($currentRelation) && isset($currentRelation[$bindingName]) && is_array($currentRelation[$bindingName]) && isset($currentRelation[$bindingName]['className']))
  1138. {
  1139. $model = $currentRelation[$bindingName]['className'];
  1140. break;
  1141. }
  1142. }
  1143. if (!isset($model))
  1144. {
  1145. $model = $bindingName;
  1146. }
  1147. if (isset($model) && $model != $this->name && isset($this->$model))
  1148. {
  1149. if (!isset($this->__backInnerAssociation))
  1150. {
  1151. $this->__backInnerAssociation = array();
  1152. }
  1153. $this->__backInnerAssociation[] = $model;
  1154. $this->$model->expects(true, $children);
  1155. }
  1156. }
  1157. if (isset($models[$this->name]))
  1158. {
  1159. foreach($models as $model => $children)
  1160. {
  1161. if ($model != $this->name)
  1162. {
  1163. $models[$this->name][] = $model;
  1164. }
  1165. }
  1166. $models = array_unique($models[$this->name]);
  1167. $unbind = array();
  1168. foreach($relationTypes as $relation)
  1169. {
  1170. if (isset($this->$relation))
  1171. {
  1172. foreach($this->$relation as $bindingName => $bindingData)
  1173. {
  1174. if (!in_array($bindingName, $models))
  1175. {
  1176. $unbind[$relation][] = $bindingName;
  1177. }
  1178. }
  1179. }
  1180. }
  1181. if (count($unbind) > 0)
  1182. {
  1183. $this->unbindModel($unbind, $reset);
  1184. }
  1185. }
  1186. }
  1187. /**
  1188. * 複数のEメールチェック(カンマ区切り)
  1189. *
  1190. * @param array $check
  1191. * @return boolean
  1192. */
  1193. function emails($check) {
  1194. $Validation =& Validation::getInstance();
  1195. $emails = array();
  1196. if(strpos($check[key($check)], ',') !== false) {
  1197. $emails = explode(',', $check[key($check)]);
  1198. }
  1199. if(!$emails) {
  1200. $emails = array($check[key($check)]);
  1201. }
  1202. $result = true;
  1203. foreach($emails as $email) {
  1204. if(!$Validation->email($email)) {
  1205. $result = false;
  1206. }
  1207. }
  1208. return $result;
  1209. }
  1210. /**
  1211. * find
  1212. *
  1213. * キャッシュビヘイビアが利用状態の場合、モデルデータキャッシュを読み込む
  1214. *
  1215. * 【AppModelではキャッシュを定義しない事】
  1216. * 自動的に生成されるクラス定義のない関連モデルの処理で勝手にキャッシュを利用されないようにする為
  1217. * (HABTMの更新がうまくいかなかったので)
  1218. *
  1219. * 【PHP5限定】
  1220. * PHP4では次のような処理ができない為
  1221. * Model ⇒ Behavior ⇒ call_user_func_array ⇒ Model ⇒ Behavior
  1222. * ※ ビヘイビア内で自モデルのメソッドを呼び出しそのメソッド内でさらにビヘイビアを使う
  1223. *
  1224. * @param mixed...
  1225. * @return type
  1226. * @access public
  1227. */
  1228. function find($conditions = null, $fields = array(), $order = null, $recursive = null) {
  1229. if (!is_string($conditions) || (is_string($conditions) && !array_key_exists($conditions, $this->_findMethods))) {
  1230. $type = 'first';
  1231. $query = array_merge(compact('conditions', 'fields', 'order', 'recursive'), array('limit' => 1));
  1232. } else {
  1233. list($type, $query) = array($conditions, $fields);
  1234. }
  1235. $this->findQueryType = $type;
  1236. $this->id = $this->getID();
  1237. $query = array_merge(
  1238. array(
  1239. 'conditions' => null, 'fields' => null, 'joins' => array(), 'limit' => null,
  1240. 'offset' => null, 'order' => null, 'page' => null, 'group' => null, 'callbacks' => true
  1241. ),
  1242. (array)$query
  1243. );
  1244. if ($type != 'all') {
  1245. if ($this->_findMethods[$type] === true) {
  1246. $query = $this->{'_find' . ucfirst($type)}('before', $query);
  1247. }
  1248. }
  1249. if (!is_numeric($query['page']) || intval($query['page']) < 1) {
  1250. $query['page'] = 1;
  1251. }
  1252. if ($query['page'] > 1 && !empty($query['limit'])) {
  1253. $query['offset'] = ($query['page'] - 1) * $query['limit'];
  1254. }
  1255. if ($query['order'] === null && $this->order !== null) {
  1256. $query['order'] = $this->order;
  1257. }
  1258. $query['order'] = array($query['order']);
  1259. if ($query['callbacks'] === true || $query['callbacks'] === 'before') {
  1260. $return = $this->Behaviors->trigger($this, 'beforeFind', array($query), array(
  1261. 'break' => true, 'breakOn' => false, 'modParams' => true
  1262. ));
  1263. $query = (is_array($return)) ? $return : $query;
  1264. if ($return === false) {
  1265. return null;
  1266. }
  1267. $return = $this->beforeFind($query);
  1268. $query = (is_array($return)) ? $return : $query;
  1269. if ($return === false) {
  1270. return null;
  1271. }
  1272. }
  1273. // CUSTOMIZE MODIFY 2012/04/23 ryuring
  1274. // データキャッシュ
  1275. // >>>
  1276. /*if (!$db =& ConnectionManager::getDataSource($this->useDbConfig)) {
  1277. return false;
  1278. }
  1279. $results = $db->read($this, $query);*/
  1280. // ---
  1281. $cache = true;
  1282. if(isset($query['cache']) && is_bool($query['cache'])) {
  1283. $cache = $query['cache'];
  1284. unset($query['cache']);
  1285. }
  1286. if (PHP5 && BC_INSTALLED && isset($this->Behaviors) && $this->Behaviors->attached('BcCache') &&
  1287. $this->Behaviors->enabled('BcCache') && Configure::read('debug') == 0 ) {
  1288. $results = $this->readCache($cache, $type, $query);
  1289. } else {
  1290. if (!$db =& ConnectionManager::getDataSource($this->useDbConfig)) {
  1291. return false;
  1292. }
  1293. $results = $db->read($this, $query);
  1294. }
  1295. // <<<
  1296. $this->resetAssociations();
  1297. $this->findQueryType = null;
  1298. if ($query['callbacks'] === true || $query['callbacks'] === 'after') {
  1299. $results = $this->__filterResults($results);
  1300. }
  1301. if ($type === 'all') {
  1302. return $results;
  1303. } else {
  1304. if ($this->_findMethods[$type] === true) {
  1305. return $this->{'_find' . ucfirst($type)}('after', $query, $results);
  1306. }
  1307. }
  1308. }
  1309. /**
  1310. * Deletes multiple model records based on a set of conditions.
  1311. *
  1312. * @param mixed $conditions Conditions to match
  1313. * @param boolean $cascade Set to true to delete records that depend on this record
  1314. * @param boolean $callbacks Run callbacks (not being used)
  1315. * @return boolean True on success, false on failure
  1316. * @access public
  1317. * @link http://book.cakephp.org/view/692/deleteAll
  1318. */
  1319. function deleteAll($conditions, $cascade = true, $callbacks = false) {
  1320. $result = parent::deleteAll($conditions, $cascade, $callbacks);
  1321. if($result) {
  1322. if ($this->Behaviors->attached('BcCache') && $this->Behaviors->enabled('BcCache')) {
  1323. $this->delCache($this);
  1324. }
  1325. }
  1326. return $result;
  1327. }
  1328. /**
  1329. * Updates multiple model records based on a set of conditions.
  1330. *
  1331. * @param array $fields Set of fields and values, indexed by fields.
  1332. * Fields are treated as SQL snippets, to insert literal values manually escape your data.
  1333. * @param mixed $conditions Conditions to match, true for all records
  1334. * @return boolean True on success, false on failure
  1335. * @access public
  1336. * @link http://book.cakephp.org/view/75/Saving-Your-Data
  1337. */
  1338. function updateAll($fields, $conditions = true) {
  1339. $result = parent::updateAll($fields, $conditions);
  1340. if($result) {
  1341. if ($this->Behaviors->attached('BcCache') && $this->Behaviors->enabled('BcCache')) {
  1342. $this->delCache($this);
  1343. }
  1344. }
  1345. return $result;
  1346. }
  1347. }
  1348. ?>