<?php
/*
 * PHP version 5
 *
 * @copyright Copyright 2010, Cake. (http://trpgtools-onweb.sourceforge.jp/)
 * @category Model
 * @package  TRPG Data Bank
 * @version  beta
 * @author   Cake <cake_67@users.sourceforge.jp>
 * @license  http://www.opensource.org/licenses/mit-license.php The MIT License
 * @link     http://trpgtools-onweb.sourceforge.jp/
 */

app::import('Sanitize');
class AppModel extends Model {
	var $actsAs = array(
		'Collectionable.options',
		'Cakeplus.ValidationErrorI18n',
		'Cakeplus.AddValidationRule',
		'SanitizePlus',
		'Containable',
		'Cache',
		'Media.Transfer',
	);

	var $public_flag = array(
		'public' => 1,
		'private' => 2,
	);

	/* 
	 * DBフィールドごとの基本処理設定
	 * 例
	 * var $fields = array(
	 *	'field_name' => array( // field名
	 *		'auto' => false, // true:自動設定値 ユーザ設定不可(id, created, modified...)
	 *		'add' => true, // true: 追加画面でフォームを表示する項目
	 *		'edit' => false, // 編集画面でフォーム表示を表示する項目
	 *		'escape' => array( // escape処理
	 *			'html' => true, // true: Sanitize::html()を行なう
	 *			'all' => true, // true: Sanitize::stripAll()を行なう
	 *			'whitespace' => true, // true: Sanitize::stripWhitespace()を行なう
	 *			'images' => true, // true: Sanitize::stripImages()を行なう
	 *			'sctipts' => true, // true: Sanitize::stripScripts()を行なう
	 *			'tags' => true, // true: SanitizePlus::stripTags()を行なう
	 *		),
	 *	),
	 * $fields設定は個々のモデルで行なう
	*/
	var $fields = array();

	function __construct($id = false, $table = null, $ds = null) {
		parent::__construct($id, $table, $ds);

		// MySQLが非UTF-8設定のサーバ対策
		mysql_set_charset('utf8');
	}

	/* コールバックメソッド */
	function beforeValidate($options = array())
	{
		// i18n Error Messages
		// Working on the CakePlus
		$error_messages = array(
			'alphaNumeric' => __('Please input only alphanumeric characters.', true),
			'between' => __('Between %2$d and %3$d characters.', true),
			'betweenWrapper' => __('Too short or Too long.', true),
			'boolean' => __('Incorrect value.', true),
			'compare2fields' => __('Input same as avobe.', true),
			'comparison' => __('Please input number %2$s %3$d.', true),
			'date' => __('Invalid date.', true),
			'isAddress' => __('Invalid mail address.', true),
			'isPcMail' => __('Invalid PC-mail address.', true),
			'isUnique' => __('It was already registed.', true),
			'isUniquePcMail' => __('It was already registed.', true),
			'isUniqueRegistMail' => __('It is registering-mail.', true),
			'isUniqueKeyname4profile' => __('It was already registed.', true),
			'isUniqueKeyname4system' => __('It was already registed.', true),
			'keyName' => __('Please input number, small letter and underline only.', true),
			'keyNameNg' => __('Invalid Key Name.', true),
			'minLength' => __('More than %2$d characters', true),
			'maxLength' => __('Less than %2$d characters', true),
			'notEmpty' 	=> __('Please be sure to input.', true),
			'numeric' => __('Please input only number.', true),
			'onlyFuture' => __('You cannot set the Past date.', true),
			'orderNumeric' => __('Order must be only number.', true),
			'profileType' => __('Invalid Type.', true),
			'publicFlag' => __('Incorrect value.', true),
			'url' => __('Please input URL.', true),
			'validProfileId' => __('Invalid Profile.', true),
			'validProfileSelectId' => __('Invalid ProfileSelect.', true),
			'validProfiletableId' => __('Invalid ProfileTable.', true),
			'validSystemId' => __('Invalid System.', true),
			'validStatus' => __('Invalid Status.', true),
			'widthNumeric' => __('Width must be only number.', true),

			// mediaプラグイン
			'resource' => __('The file is invalid.', true),
			'access' => __('The file cannot be processed.', true),
			'location' => __('The file cannot be transferred from or to location.', true),
			'permission' => __('Executable files cannot be uploaded.', true),
			'size' => __('The file must be less than %2$s bytes.', true),
			'pixels' => __('The file must be within %2$s pixel.', true),
			'extension' => __('The file has the wrong extension.', true),
			'mimeType' => __('The file has the wrong MIME type.', true),

		);

		$error_messages['minLengthJP'] = $error_messages['minLength'];
		$error_messages['maxLengthJP'] = $error_messages['maxLength'];

		$this->setErrorMessageI18n($error_messages, false);

		$this->replaceValidationErrorMessagesI18n();

		return parent::beforeValidate($options);
	}

	function beforeSave($options = array())
	{
		// $fieldsの設定でSanitize
		if (isset($this->data[$this->name])) {
			$this->data[$this->name] = $this->_sanitizeByFields($this->data[$this->name]);
		}

		// Sanitize(不正コード、SQL Injection)
		if (isset($this->data)) {
			$this->data = $this->_sanitizeBasic($this->data);
		}

		return parent::beforeSave($options);
	}

	function _sanitizeByFields($data)
	{
		if (empty($data) || !is_array($data)) {
			return $data;
		}

		foreach($data as $field => $value) {
			$data[$field]  = $this->escapeByFields($field, $value);
		}

		return $data;
	}
	function _sanitizeBasic($data)
	{
		if (empty($data) || !is_array($data)) {
			return $data;
		}

		$data = Sanitize::clean(
			$data,
			array(
				'encode' => false,
			)
		);

		return $data;
	}

	/* Validation */
	/* alphaNumeric() */
	/** It Overwrites the original alphaNumeric() **/
	function alphaNumeric($data)
	{
		$check = is_array($data) ? array_shift($data) : $data;
		if (preg_match('/^[0-9a-z]+$/i',$check)) {
			return true;
		} else {
			return false;
		}
	}

	/* Wrapper to the origibal between() */
	function betweenWrapper($check, $min, $max)
	{
		return Validation::between($check, $min, $max);
	}

	/* check PublicFlag Setting */
	function publicFlag($data)
	{
		if (isset($data["public_flag"]) && in_array($data["public_flag"], $this->public_flag)) {
			return true;
		} else {
			return false;
		}
	}

	/* valid User Id */
	function validUserId($data, $is_active = true)
	{
		if (!isset($data['user_id']) || !$data['user_id']) {
			return false;
		}

		if (!isset($this->User)) {
			$this->User = CorePlus::set_model('User');
		}
		$user = $this->User->read(null, $data['user_id']);
		if (!$user['User']) {
			return false;
		}

		if ($is_active) {
			if (!isset($this->Group)) {
				$this->Group = CorePlus::set_model('Group');
			}
			if (!in_array($user['User']['group_id'], $this->Group->is_active)) {
				return false;
			}
		}

		return true;
	}

	/* valid System Id */
	function validSystemId($data, $is_public = true)
	{
		$this->System = CorePlus::set_model('System');

		$params =  array(
			'recursive' => -1,
			'fields' => 'System.id',
			'conditions' => array(
				'System.id' => $data["system_id"],
			),
		);
		
		if ($is_public === true) {
			$params['conditions']['System.public_flag'] = 1;
		} else {
			if (isset($params['conditions']['System.public_flag'])) {
				unset($params['conditions']['System.public_flag']);
			}
		}
		$system_id = $this->System->find('list', $params);

		return (bool)$system_id;
	}

	function validProfileId($data, $system_id)
	{
		return (bool)$this->Profile->find('count', array(
			'conditions' => array(
				'Profile.id'  => $data['profile_id'],
				'Profile.system_id'  => $system_id,
			),
			'recursive' => -1,
		));
	}

	function validProfileSelectId($data, $system_id)
	{
		return $this->Profile->ProfileSelect->find('count', array(
			'conditions' => array(
				'ProfileSelect.id'  => $data['profile_select_id'],
				'Profile.system_id'  => $system_id,
			),
		));
	}

	function validProfiletableId($data, $system_id)
	{
		return $this->Profile->ProfileTable->find('count', array(
			'conditions' => array(
				'ProfileTable.id'  => $data['profile_table_id'],
				'Profile.system_id'  => $system_id,
			),
		));
	}

	/* keyName (number, small letter and underline) */
	function keyName($data) 
	{
		$check = is_array($data) ? array_shift($data) : $data;

		return (bool)preg_match('/^[_0-9a-z]+$/', $check);
	}
	function keyNameNg($data) 
	{
		$check = is_array($data) ? array_shift($data) : $data;

		$ngNames = array(
			'no',
		);

		return !(bool)in_array($check, $ngNames);
	}

	/* アドレスチェック */
	function isUniqueRegistMail($data)
	{
		// regist_mailチェック
		$registId = $this->getRegistId4address($data);

		return (bool)$registId;
	}
	function getRegistId4address($data)
	{
		if (isset($data['pcmail'])) {
			$mail = $data['pcmail'];
		} elseif (isset($data['mail'])) {
			$mail = $data['mail'];
		} else {
			$mail = null;
		}

		if (!$mail) {
			return null;
		}

		// アドレス暗号化
		$encrypted_address = $this->getEncryptedAddress($mail);

		$this->RegistMail = CorePlus::set_model('RegistMail');
		$conditions = array(
			'RegistMail.mail' => $encrypted_address,
		);
		$fields = array(
			'RegistMail.id',
		);
		$user = $this->RegistMail->find('first', array(
			'conditions' => $conditions,
			'fields' => $fields,
			'recursive' => -1,
		));

		if (isset($user['RegistMail']['id'])) {
			return $user['RegistMail']['id'];
		} else {
			return null;
		}
	}

	function getRegistData4code($code)
	{
		if (!$code) {
			return array();
		}

		$this->RegistMail = CorePlus::set_model('RegistMail');
		$conditions = array(
			'RegistMail.key_code' => $code,
		);
		return  $this->RegistMail->find('first', array(
			'conditions' => $conditions,
			'recursive' => -1,
		));
	}
	function deleteRegistData4mail($mail)
	{
		if (!$mail) {
			return null;
		}

		$this->RegistMail = CorePlus::set_model('RegistMail');
		$conditions = array(
			'RegistMail.mail' => $mail,
		);
		return $this->RegistMail->deleteAll($conditions);
	}

	function deleteRegistData4user_id($user_id)
	{
		if (!$user_id) {
			return null;
		}

		$this->RegistMail = CorePlus::set_model('RegistMail');
		$conditions = array(
			'RegistMail.user_id' => $user_id,
		);

		return $this->RegistMail->deleteAll($conditions);
	}

	function isUniquePcMail($data)
	{
		// usersチェック
		$userId = $this->getUserId4address($data);

		return !(bool)$userId;
	}
	function getUserId4address($data)
	{
		if (isset($data['pcmail'])) {
			$mail = $data['pcmail'];
		} elseif (isset($data['mail'])) {
			$mail = $data['mail'];
		} else {
			$mail = null;
		}

		if (!$mail) {
			return null;
		}

		// アドレス暗号化
		$encrypted_address = $this->getEncryptedAddress($mail);

		$this->User = CorePlus::set_model('User');
		$conditions = array(
			'User.pcmail' => $encrypted_address,
		);
		$fields = array(
			'User.id',
		);
		$user = $this->User->find('first', array(
			'conditions' => $conditions,
			'fields' => $fields,
			'recursive' => -1,
		));

		if (isset($user['User']['id'])) {
			return $user['User']['id'];
		} else {
			return null;
		}
	}

	function getEncryptedAddress($mail)
	{
		if (!isset($this->Crypt)) {
			App::import('Component', 'Crypt');
			$this->Crypt = new CryptComponent;
		}
		return $this->Crypt->crypt($mail);
	}

	function isPcMail($data)
	{
		if (isset($data['pcmail'])) {
			$mail = $data['pcmail'];
		} elseif (isset($data['mail'])) {
			$mail = $data['mail'];
		} else {
			$mail = null;
		}

		if (!$mail) {
			return true;
		}

		if (!$this->isAddress($mail)) {
			return false;
		}

		return !$this->checkMobileDomain($mail);
	}
	function checkMobileDomain($data)
	{
		if (empty($data)) {
			return true;
		}
		if (!Configure::read('mobile.domain')) {
			return false;
		}

		$pieces = explode('@', $data);
		$domain = array_pop($pieces);

		return in_array($domain, Configure::read('mobile.domain'));
	}
	function isAddress($data)
	{
		if (empty($data)) {
			return true;
		}

		if (is_array($data)) {
			if (count($data) > 1) {
				return false;
			} else {
				$data = array_pop($data);
			}
		}

		if (preg_match('/^[^:;@,\s\x80-\xFF]+@\w[\w\-.]*\.[a-zA-Z]+$/', $data)) {
			return true;
		} else {
			return false;
		}
	}

	function find($type, $queryData = array()){
		return parent::find($type, $queryData);  // Memory Overのためparent使用
	
		$args = array($type, $queryData);
		if ($this->Behaviors->attached('Cache')) {
			if ($this->cacheEnabled()) {
				return $this->cacheMethod(__FUNCTION__, $args);
			}
		}
		$parent = get_parent_class($this);
		return call_user_func_array(array($parent, __FUNCTION__), $args);
	}


	/* キャッシュ削除 */
	// ホーム関連
	function deleteCacheHome($user_id = null)
	{
		$this->deleteCacheLastCharacters();
		$this->deleteCacheAnonymousHome();
		$this->deleteCacheMyData($user_id);
	}

	// 最近更新されたキャラクター
	function deleteCacheLastCharacters()
	{
		clearCache('element__character_picture_table', 'views', '');
	}

	// 未ログインホーム
	function deleteCacheAnonymousHome()
	{
		if (file_exists(CACHE.'views'.DS.'element_0_user_index')) {
			@unlink(CACHE.'views'.DS.'element_0_user_index');
		}
	}

	// 自セッション関連
	function deleteCacheMyData($user_id = null)
	{
		$Session = CorePlus::set_behavoir('Session');

		if (!empty($user_id) && file_exists(CACHE.'views'.DS.'element_'.$user_id.'_user_index')) {
			@unlink(CACHE.'views'.DS.'element_'.$user_id.'_user_index');
		}

		if (!$Session->id()) {
			return false;
		}
		if (file_exists(CACHE.'views'.DS.'element_'.$Session->id().'_character_picture_table')) {
			@unlink(CACHE.'views'.DS.'element_'.$Session->id().'_character_picture_table');
		}
		if (file_exists(CACHE.'views'.DS.'element_'.$Session->id().'_character_index')) {
			@unlink(CACHE.'views'.DS.'element_'.$Session->id().'_character_index');
		}
	}

	// キャラクター
	function deleteCacheCharacter($character_id = null, $deleteModelCache = false)
	{
		clearCache('_characters.php', 'views', '');
		clearCache('_characters_index');

		if (!empty($character_id)) {
			$this->deleteCacheCharacterView($character_id, $deleteModelCache);

			if (file_exists(CACHE.'views'.DS.'element_'.$character_id.'_character_picture_table')) {
				@unlink(CACHE.'views'.DS.'element_'.$character_id.'_character_picture_table');
			}
		}
	}
	function deleteCacheCharacterView($character_id = null, $deleteModelCache = false)
	{
		if (!empty($character_id)) {
			if (file_exists(CACHE.'views'.DS.'element_'.$character_id.'_character_view')) {
				@unlink(CACHE.'views'.DS.'element_'.$character_id.'_character_view');
			}

			$Session = CorePlus::set_behavoir('Session');
			if (file_exists(CACHE.'views'.DS.'element_'.$Session->id().'_'.$character_id.'_character_view')) {
				@unlink(CACHE.'views'.DS.'element_'.$Session->id().'_'.$character_id.'_character_view');
			}
		}

		if ($deleteModelCache) {
			$this->Character->cacheDelete();
		}
	}

	// キャラ画像
	function deleteCache4CharacterPicture($character_id)
	{
		if (!empty($character_id)) {
			if (file_exists(CACHE.'views'.DS.'element_'.$character_id.'_character_picture_index')) {
				@unlink(CACHE.'views'.DS.'element_'.$character_id.'_character_picture_index');
			}

			$Session = CorePlus::set_behavoir('Session');
			if (file_exists(CACHE.'views'.DS.'element_'.$Session->id().'_'.$character_id.'_character_picture_index')) {
				@unlink(CACHE.'views'.DS.'element_'.$Session->id().'_'.$character_id.'_character_picture_index');
			}
		}
	}

	// ユーザ
	function deleteCacheUser($user_id)
	{
		clearCache('_users_listview');

		if (!empty($user_id)) {
			clearCache('_users_view_'.$user_id);

			if (file_exists(CACHE.'views'.DS.'element_'.$user_id.'user_index')) {
				@unlink(CACHE.'views'.DS.'element_'.$user_id.'user_index');
			}
			if (file_exists(CACHE.'views'.DS.'element_'.$user_id.'_character_picture_table')) {
				@unlink(CACHE.'views'.DS.'element_'.$user_id.'_character_picture_table');
			}
			if (file_exists(CACHE.'views'.DS.'element_'.$user_id.'_character_view')) {
				@unlink(CACHE.'views'.DS.'element_'.$user_id.'_character_view');
			}
		}
	}

	// システム
	function deleteCacheSystem($system_id, $deleteModelCache = false)
	{
		clearCache('_systems.php', 'views', '');
		clearCache('_systems_index');
		if (!empty($system_id)) {
			clearCache('_systems_view_'.$system_id);
		}

		if ($deleteModelCache) {
			if (!isset($this->System)) {
				$this->System = CorePlus::set_model('System');
			}

			$this->System->cacheDelete();
		}
	}

	// プロフィール関連
	function deleteCache4ProfileChilds()
	{
		if (!isset($this->Profile)) {
			$this->Profile = CorePlus::set_model('Profile');
		}
		$this->Profile->cacheDelete();

		if (!isset($this->System)) {
			$this->System = CorePlus::set_model('System');
		}
		$this->System->cacheDelete();
	}

	// Archive
	function deleteCache4ProfileArchivesIndex($character_id)
	{
		if (empty($character_id)) {
			return null;
		}

		$Session = CorePlus::set_behavoir('Session');
		if (file_exists(CACHE.'views'.DS.'element_'.$character_id.'_character_profile_archive_index')) {
			@unlink(CACHE.'views'.DS.'element_'.$character_id.'_character_profile_archive_index');
		}
		if (file_exists(CACHE.'views'.DS.'element_'.$Session->id().'_'.$character_id.'_character_profile_archive_index')) {
			@unlink(CACHE.'views'.DS.'element_'.$Session->id().'_'.$character_id.'_character_profile_archive_index');
		}
	}


	// 全てのキャッシュ
	function deleteCacheAll($deleteCore = true)
	{
		// モデルキャッシュ
		$this->deleteAllFiles(CACHE);

		// ビューキャッシュ
		$this->deleteAllFiles(CACHE.'views');

		// cake core
		if ($deleteCore) {
			$this->deleteAllFiles(CACHE.'models');
			$this->deleteAllFiles(CACHE.'persistent');
		}
	}

	function deleteAllFiles($dir)
	{
		if ($handle = opendir($dir)) {
			while (false !== ($file = readdir($handle))) {
				if (is_file($dir. DS. $file) 
					 && $file != "." && $file != ".." && $file != "empty"
				) {
					@unlink($dir. DS. $file);
				}
			}
		}
		closedir($handle);
	}

}

