<?php
/**
 * DBクラス
 *
 * PHP versions 5
 *
 * LICENSE: This source file is licensed under the terms of the GNU General Public License.
 *
 * @package    Magic3 Framework
 * @author     平田直毅(Naoki Hirata) <naoki@aplo.co.jp>
 * @copyright  Copyright 2006-2010 Magic3 Project.
 * @license    http://www.gnu.org/copyleft/gpl.html  GPL License
 * @version    SVN: $Id: admin_mainDb.php 3723 2010-10-23 06:45:50Z fishbone $
 * @link       http://www.magic3.org
 */
require_once($gEnvManager->getDbPath() . '/baseDb.php');
require_once($gEnvManager->getIncludePath() . '/common/userInfo.php');		// ユーザ情報クラス

class admin_mainDb extends BaseDb
{	
	private $now;		// 現在日時
	private $userId;		// ログイン中のユーザ
	private $maxNo;		// 最大管理番号
//	const CF_DEFAULT_TEMPLATE			= 'default_template';			// システム定義値取得用キー(PC用デフォルトテンプレート)
//	const CF_DEFAULT_TEMPLATE_MOBILE	= 'mobile_default_template';	// システム定義値取得用キー(携帯用デフォルトテンプレート)
	
	// 取得値
	const CAN_DETAIL_CONFIG = 'permit_detail_config';				// 詳細設定が可能かどうか
		
	/**
	 * システム定義値を取得
	 *
	 * @param string $key		キーとなる項目値
	 * @return string $value	値
	 */
	function getSystemConfig($key)
	{
		$retValue = '';
		$queryStr = 'SELECT sc_value FROM _system_config ';
		$queryStr .=  'WHERE sc_id  = ?';
		$ret = $this->selectRecord($queryStr, array($key), $row);
		if ($ret) $retValue = $row['sc_value'];
		return $retValue;
	}
	/**
	 * システム定義値を更新
	 *
	 * @param string $key		キーとなる項目値
	 * @param string $value		値
	 * @return					true = 正常、false=異常
	 */
	function updateSystemConfig($key, $value)
	{
		// トランザクションスタート
		$this->startTransaction();
		
		$queryStr = 'SELECT sc_value FROM _system_config ';
		$queryStr .=  'WHERE sc_id  = ?';
		$ret = $this->selectRecord($queryStr, array($key), $row);
		if ($ret){
			$queryStr  = 'UPDATE _system_config ';
			$queryStr .=   'SET sc_value = ? ';
			$queryStr .=   'WHERE sc_id = ?';
			$ret = $this->execStatement($queryStr, array($value, $key));			
		} else {
			$queryStr = 'INSERT INTO _system_config (';
			$queryStr .=  'sc_id, ';
			$queryStr .=  'sc_value ';
			$queryStr .=  ') VALUES (';
			$queryStr .=  '?, ?';
			$queryStr .=  ')';
			$ret = $this->execStatement($queryStr, array($key, $value));	
		}
		// トランザクション終了
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * サイト定義値を更新
	 *
	 * @param string $lang		言語
	 * @param string $key		キーとなる項目値
	 * @param string $value		値
	 * @param int $user			ユーザID
	 * @return					true = 正常、false=異常
	 */
	function updateSiteDef($lang, $key, $value)
	{
		$now = date("Y/m/d H:i:s");	// 現在日時
		$user = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		
		// トランザクション開始
		$this->startTransaction();
		
		// 指定のレコードの履歴インデックス取得
		$historyIndex = 0;		// 履歴番号
		$queryStr  = 'SELECT * FROM _site_def ';
		$queryStr .=   'WHERE sd_id = ? ';
		$queryStr .=     'AND sd_language_id = ? ';
		$queryStr .=  'ORDER BY sd_history_index desc ';
		$queryStr .=    'LIMIT 1';
		$ret = $this->selectRecord($queryStr, array($key, $lang), $row);
		if ($ret){
			$historyIndex = $row['sd_history_index'] + 1;
		
			// レコードが削除されていない場合は削除
			if (!$row['sd_deleted']){
				// 古いレコードを削除
				$queryStr  = 'UPDATE _site_def ';
				$queryStr .=   'SET sd_deleted = true, ';	// 削除
				$queryStr .=     'sd_update_user_id = ?, ';
				$queryStr .=     'sd_update_dt = ? ';
				$queryStr .=   'WHERE sd_serial = ?';
				$ret = $this->execStatement($queryStr, array($user, $now, $row['sd_serial']));
				if (!$ret) return false;
			}
		}
		
		// 新規レコード追加
		$queryStr = 'INSERT INTO _site_def ';
		$queryStr .=  '(';
		$queryStr .=  'sd_id, ';
		$queryStr .=  'sd_language_id, ';
		$queryStr .=  'sd_history_index, ';
		$queryStr .=  'sd_value, ';
		$queryStr .=  'sd_create_user_id, ';
		$queryStr .=  'sd_create_dt) ';
		$queryStr .=  'VALUES ';
		$queryStr .=  '(?, ?, ?, ?, ?, ?)';
		$ret =$this->execStatement($queryStr, array($key, $lang, $historyIndex, $value, $user, $now));
			
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * サイト定義値を取得
	 *
	 * @param string $lang		言語
	 * @param string $key		キーとなる項目値
	 * @return string			値
	 */
	function getSiteDef($lang, $key)
	{
		$queryStr  = 'SELECT * FROM _site_def ';
		$queryStr .=   'WHERE sd_deleted = false ';
		$queryStr .=     'AND sd_id = ? ';
		$queryStr .=     'AND sd_language_id = ? ';
		$ret = $this->selectRecord($queryStr, array($key, $lang), $row);
		if ($ret){
			return $row['sd_value'];
		} else {
			return '';
		}
	}
	/**
	 * システムの詳細設定が可能かどうか
	 *
	 * @return bool					true=可能、false=不可
	 */
	function canDetailConfig()
	{
		$retValue = $this->getSystemConfig(self::CAN_DETAIL_CONFIG);
		return $retValue;
	}
	/**
	 * ウィジェットリスト取得
	 *
	 * @param int      $type		テンプレートのタイプ(0=PC用、1=携帯用、2=スマートフォン)
	 * @param function $callback	コールバック関数
	 * @return						なし
	 */
	function getAllWidgetList($type, $callback)
	{
		// wd_device_typeは後で追加したため、wd_mobileを残しておく
		$queryStr  = 'SELECT * FROM _widgets ';
		$queryStr .=  'WHERE wd_deleted = false ';// 削除されていない
		$params = array();
		switch ($type){
			case 0:		// PC用テンプレート
			case 2:		// スマートフォン用テンプレート
			default:
				$queryStr .=    'AND wd_mobile = false ';		// 携帯用以外
				$queryStr .=    'AND wd_device_type = ? '; $params[] = $type;
				break;
			case 1:		// 携帯用のとき
				$queryStr .=    'AND wd_mobile = true ';		// 携帯用
				break;
		}
		$queryStr .=  'ORDER BY wd_id';
		$this->selectLoop($queryStr, $params, $callback);
	}
	/**
	 * 管理メニュー項目用ウィジェットリスト(管理画面ありでPC携帯両方)取得
	 *
	 * @param function $callback	コールバック関数
	 * @return						なし
	 */
	function getAvailableWidgetListForEditMenu($callback)
	{
		$queryStr  = 'select * from _widgets ';
		$queryStr .=   'where wd_deleted = false ';// 削除されていない
		$queryStr .=     'and wd_available = true ';		// メニューから選択可能なもの
		$queryStr .=     'and wd_has_admin = true ';		// 管理機能あり
		$queryStr .=   'order by wd_sort_order,wd_id';
		$this->selectLoop($queryStr, array(), $callback);
	}
	/**
	 * ウィジェットリスト(メニューから選択可能なもの)取得
	 *
	 * @param function $callback	コールバック関数
	 * @return						なし
	 */
	/*function getAvailableWidgetList($callback)
	{
		$queryStr  = 'select * from _widgets ';
		$queryStr .=   'where wd_deleted = false ';// 削除されていない
		$queryStr .=     'and wd_available = true ';		// メニューから選択可能なもの
		$queryStr .=     'and wd_mobile = false ';		// 携帯用ウィジェット以外
		$queryStr .=   'order by wd_id';
		$this->selectLoop($queryStr, array(), $callback);
	}*/
	/**
	 * 携帯用のウィジェットリスト(メニューから選択可能なもの)取得
	 *
	 * @param function $callback	コールバック関数
	 * @return						なし
	 */
	/*function getAvailableMobileWidgetList($callback)
	{
		$queryStr  = 'select * from _widgets ';
		$queryStr .=   'where wd_deleted = false ';// 削除されていない
		$queryStr .=     'and wd_available = true ';		// メニューから選択可能なもの
		$queryStr .=     'and wd_mobile = true ';		// 携帯用ウィジェット
		$queryStr .=   'order by wd_id';
		$this->selectLoop($queryStr, array(), $callback);
	}*/
	/**
	 * ウィジェットIDリスト取得
	 *
	 * @param array  $rows			取得レコード
	 * @return						true=取得、false=取得せず
	 */
	function getAllWidgetIdList(&$rows)
	{
		$queryStr = 'select * from _widgets ';
		$queryStr .=  'where wd_deleted = false ';// 削除されていない
		$queryStr .=  'order by wd_id';
		
		$retValue = $this->selectRecords($queryStr, array(), $rows);
		return $retValue;
	}
	/**
	 * ウィジェットIDの存在チェック
	 *
	 * @param string  $id			ウィジェットID
	 * @return bool					true=存在する、false=存在しない
	 */
	function isExistsWidgetId($id)
	{
		$queryStr = 'SELECT * FROM _widgets ';
		$queryStr .=  'WHERE wd_deleted = false ';// 削除されていない
		$queryStr .=  'AND wd_id = ? ';
		return $this->isRecordExists($queryStr, array($id));
	}
	/**
	 * ウィジェットの追加
	 *
	 * @param string  $id				ウィジェットID
	 * @param string  $name				ウィジェット名
	 * @param int     $deviceType	端末タイプ(0=PC用、1=携帯用、2=スマートフォン)
	 * @param bool    $readScripts		スクリプトディレクトリを自動読み込みするかどうか
	 * @param bool    $readCss			cssディレクトリを自動読み込みするかどうか
	 * @param bool    $hasAdmin			管理画面があるかどうか
	 * @return							なし
	 */
	function addNewWidget($id, $name, $deviceType = 0, $readScripts = false, $readCss = false, $hasAdmin = false)
	{
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		$now = date("Y/m/d H:i:s");	// 現在日時
		$historyIndex = 0;
		$mobile = 0;				// 携帯端末かどうか
		if ($deviceType == 1) $mobile = 1;
		
		// トランザクション開始
		$this->startTransaction();
		
		// 同じIDが登録済みかどうかチェック
		$queryStr = 'select * from _widgets ';
		$queryStr .=  'where wd_id = ? ';
		$queryStr .=  'order by wd_history_index desc ';
		$ret = $this->selectRecord($queryStr, array($id), $row);
		if ($ret){
			if (!$row['wd_deleted']){		// レコードが削除されていなければ、削除
				// 古いレコードを削除
				$queryStr  = 'UPDATE _widgets ';
				$queryStr .=   'SET wd_deleted = true, ';	// 削除
				$queryStr .=     'wd_update_user_id = ?, ';
				$queryStr .=     'wd_update_dt = ? ';
				$queryStr .=   'WHERE wd_serial = ?';
				$this->execStatement($queryStr, array($userId, $now, $row['wd_serial']));
			}
			$historyIndex = $row['wd_history_index'] + 1;
		}

		$queryStr = 'INSERT INTO _widgets ';
		$queryStr .=  '(wd_id, wd_history_index, wd_name, wd_device_type, wd_mobile, wd_read_scripts, wd_read_css, wd_has_admin, wd_create_user_id, wd_create_dt) ';
		$queryStr .=  'VALUES ';
		$queryStr .=  '(?, ?, ?, ?, ?, ?, ?, ?, ?, now())';
		$this->execStatement($queryStr, array($id, $historyIndex, $name, intval($deviceType), intval($mobile), intval($readScripts), intval($readCss), intval($hasAdmin), $userId));
		
		// トランザクション確定
		$ret = $this->endTransaction();
	}
	/**
	 * ウィジェットの更新
	 *
	 * @param int $serial			シリアル番号
	 * @param string  $name			ウィジェット名
	 * @param bool $available		利用可能かどうか
	 * @param bool $active	ウィジェット実行可能かどうか
	 * @return bool					true=成功、false=失敗
	 */
	function updateWidget($serial, $name, $available, $active)
	{
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		$now = date("Y/m/d H:i:s");	// 現在日時
		$updateFields = array();	// 更新するフィールド名
		$updateFields[] = 'wd_language';			// 対応言語ID(「,」区切りで複数指定可)
		$updateFields[] = 'wd_name';				// ウィジェット名称
		$updateFields[] = 'wd_type';				// ウィジェット種別(content=コンテンツ表示)
		$updateFields[] = 'wd_version';				// バージョン文字列
		$updateFields[] = 'wd_fingerprint';			// ソースコードレベルでウィジェットを識別するためのID
		$updateFields[] = 'wd_group_id';			// ウィジェットグループ(管理用)
		$updateFields[] = 'wd_compatible_id';		// 互換ウィジェットID
		$updateFields[] = 'wd_joomla_class';		// Joomla!テンプレート用のクラス名
		$updateFields[] = 'wd_suffix';				// HTMLタグのクラス名に付けるサフィックス文字列
		$updateFields[] = 'wd_params';				// 各種パラメータ
		$updateFields[] = 'wd_author';				// 作者名
		$updateFields[] = 'wd_copyright';			// 著作権
		$updateFields[] = 'wd_license';				// ライセンス
		$updateFields[] = 'wd_official_level';		// 公認レベル(0=非公認、1=準公認、10=正規公認)
		$updateFields[] = 'wd_status';				// 状態(0=通常,1=テスト中,-1=廃止予定,-10=廃止)
		$updateFields[] = 'wd_cache_type';			// キャッシュタイプ(0=不可、1=可、2=非ログイン時可, 3=ページキャッシュのみ可)
		$updateFields[] = 'wd_cache_lifetime';		// キャッシュの保持時間(分)
		$updateFields[] = 'wd_view_control_type';	// 表示出力の制御タイプ(-1=固定、0=可変、1=ウィジェットパラメータ可変、2=URLパラメータ可変)
		$updateFields[] = 'wd_description';			// 説明
		$updateFields[] = 'wd_url';					// 取得先URL
		$updateFields[] = 'wd_add_script_lib';		// 追加する共通スクリプトライブラリ(ライブラリ名で指定、「,」区切りで複数指定可)
		$updateFields[] = 'wd_add_scripts';			// 追加スクリプトファイル(相対パス表記、「,」区切りで複数指定可)
		$updateFields[] = 'wd_add_css';				// 追加CSSファイル(相対パス表記、「,」区切りで複数指定可)
		$updateFields[] = 'wd_add_script_lib_a';	// (管理機能用)追加する共通スクリプトライブラリ(ライブラリ名で指定、「,」区切りで複数指定可)
		$updateFields[] = 'wd_add_scripts_a';		// (管理機能用)追加スクリプトファイル(相対パス表記、「,」区切りで複数指定可)
		$updateFields[] = 'wd_add_css_a';			// (管理機能用)追加CSSファイル(相対パス表記、「,」区切りで複数指定可)
		$updateFields[] = 'wd_device_type';			// 端末タイプ(0=PC、1=携帯、2=スマートフォン)
		$updateFields[] = 'wd_mobile';				// 携帯対応かどうか
		$updateFields[] = 'wd_show_name';			// ウィジェット名称を表示するかどうか
		$updateFields[] = 'wd_read_scripts';		// スクリプトディレクトリを自動読み込みするかどうか
		$updateFields[] = 'wd_read_css';			// cssディレクトリを自動読み込みするかどうか
		$updateFields[] = 'wd_use_ajax';			// Ajax共通ライブラリを読み込むかどうか
		$updateFields[] = 'wd_active';				// 一般ユーザが実行可能かどうか
		$updateFields[] = 'wd_available';			// メニューから選択可能かどうか
		$updateFields[] = 'wd_editable';			// データ編集可能かどうか
		$updateFields[] = 'wd_has_admin';			// 管理画面があるかどうか
		$updateFields[] = 'wd_has_log';				// ログ参照画面があるかどうか
		$updateFields[] = 'wd_enable_operation';	// 単体起動可能かどうか
		$updateFields[] = 'wd_use_instance_def';	// インスタンス定義が必要かどうか
		$updateFields[] = 'wd_initialized';			// 初期化完了かどうか
		$updateFields[] = 'wd_use_cache';			// キャッシュ機能を使用するかどうか
		$updateFields[] = 'wd_has_rss';				// RSS機能があるかどうか
		$updateFields[] = 'wd_sort_order';			// ソート順
		$updateFields[] = 'wd_launch_index';		// 遅延実行制御が必要な場合の実行順(0=未設定、0以上=実行順)
		$updateFields[] = 'wd_install_dt';			// インストール日時
		$updateFields[] = 'wd_index_file';			// 起動クラスのファイル名
		$updateFields[] = 'wd_index_class';			// 起動クラス名
		$updateFields[] = 'wd_admin_file';			// 管理機能起動クラスのファイル名
		$updateFields[] = 'wd_admin_class';			// 管理機能起動クラス名
		$updateFields[] = 'wd_db';					// 対応DB種(mysql,pgsql等を「,」区切りで指定)
		$updateFields[] = 'wd_table_access_type';	// テーブルのアクセス範囲(0=テーブル未使用、1=共通テーブルのみ、2=独自テーブル)
		
		// トランザクション開始
		$this->startTransaction();
		
		// 指定のシリアルNoのレコードが削除状態でないかチェック
		$historyIndex = 0;		// 履歴番号
		$queryStr  = 'select * from _widgets ';
		$queryStr .=   'where wd_serial = ? ';
		$ret = $this->selectRecord($queryStr, array($serial), $row);
		if ($ret){		// 既に登録レコードがあるとき
			if ($row['wd_deleted']){		// レコードが削除されていれば終了
				$this->endTransaction();
				return false;
			}
			$historyIndex = $row['wd_history_index'] + 1;
		} else {		// 存在しない場合は終了
			$this->endTransaction();
			return false;
		}
		
		// 古いレコードを削除
		$queryStr  = 'UPDATE _widgets ';
		$queryStr .=   'SET wd_deleted = true, ';	// 削除
		$queryStr .=     'wd_update_user_id = ?, ';
		$queryStr .=     'wd_update_dt = ? ';
		$queryStr .=   'WHERE wd_serial = ?';
		$this->execStatement($queryStr, array($userId, $now, $serial));
		
		// ##### データ更新処理 #####
		// 呼び出しパラメータから取得値
		$newParams = array();
		$newParams['wd_name'] = $name;
		$newParams['wd_available'] = intval($available);
		$newParams['wd_active'] = intval($active);
		$keys = array_keys($newParams);// キーを取得
		
		// クエリー作成
		$queryStr  = 'INSERT INTO _widgets (';
		$queryStr .=   'wd_id, ';
		$queryStr .=   'wd_history_index, ';
		$valueStr = '(?, ?, ';
		$values = array($row['wd_id'], $historyIndex);
		// 呼び出しパラメータから取得値を連結
		for ($i = 0; $i < count($keys); $i++){
			$queryStr .= $keys[$i] . ', ';
			$valueStr .= '?, ';
			$values[] = $newParams[$keys[$i]];
		}
		
		// 更新値を設定
		for ($i = 0; $i < count($updateFields); $i++){
			$fieldName = $updateFields[$i];
			if (!in_array($fieldName, $keys)){		// フィールドがないとき
				$queryStr .= $fieldName . ', ';
				$valueStr .= '?, ';
				$values[] = $row[$fieldName];
			}
		}

		// レコードを追加
		$queryStr .= 'wd_create_user_id, wd_create_dt) ';
		$valueStr .= '?, ?)';
		$values = array_merge($values, array($userId, $now));
		$queryStr .=  'VALUES ';
		$queryStr .=  $valueStr;
		$this->execStatement($queryStr, $values);

		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * ウィジェットの削除
	 *
	 * @param string  $serial		シリアル番号
	 * @return						true=成功、false=失敗
	 */
	function deleteWidget($serial)
	{
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		$now = date("Y/m/d H:i:s");	// 現在日時
		
		// トランザクション開始
		$this->startTransaction();
		
		// 指定のシリアルNoのレコードが削除状態でないかチェック
		$queryStr  = 'select * from _widgets ';
		$queryStr .=   'WHERE wd_serial = ? ';
		$queryStr .=    'and wd_deleted = false';
		$ret = $this->selectRecord($queryStr, array($serial), $row);
		if (!$ret){		// 登録レコードがないとき
			$this->endTransaction();
			return false;
		}
		
		// 古いレコードを削除
		$queryStr  = 'UPDATE _widgets ';
		$queryStr .=   'SET wd_deleted = true, ';	// 削除
		$queryStr .=     'wd_update_user_id = ?, ';
		$queryStr .=     'wd_update_dt = ? ';
		$queryStr .=   'WHERE wd_serial = ?';
		$this->execStatement($queryStr, array($userId, $now, $serial));
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;		
	}
	/**
	 * ウィジェットの取得
	 *
	 * @param string  $serial		シリアル番号
	 * @param array $row			取得データ
	 * @return						true=正常、false=異常
	 */
	function getWidget($serial, &$row)
	{
		$queryStr  = 'select * from _widgets ';
		$queryStr .=   'where wd_serial = ? ';
		$ret = $this->selectRecord($queryStr, array($serial), $row);
		return $ret;
	}
	/**
	 * ウィジェットの初期化状態を取得
	 *
	 * @param string  $id				ウィジェットID
	 * @return bool						true=初期済み、false=未初期化
	 */
	function isWidgetInitialized($id)
	{
		$queryStr = 'SELECT * from _widgets ';
		$queryStr .=  'WHERE wd_deleted = false ';// 削除されていない
		$queryStr .=  'AND wd_id = ?';
		$ret = $this->selectRecord($queryStr, array($id), $row);
		if ($ret && $row['wd_initialized']){
			return true;
		} else {
			return false;
		}
	}
	/**
	 * ウィジェットの初期化状態を更新
	 *
	 * @param string  $id				ウィジェットID
	 * @param bool $init				初期化状態
	 * @return bool						true=成功、false=失敗
	 */
	function updateIsWidgetInitialized($id, $init)
	{
		$now = date("Y/m/d H:i:s");	// 現在日時
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		
		// トランザクション開始
		$this->startTransaction();
		
		$queryStr = 'SELECT * from _widgets ';
		$queryStr .=  'WHERE wd_deleted = false ';// 削除されていない
		$queryStr .=  'AND wd_id = ?';
		$ret = $this->selectRecord($queryStr, array($id), $row);
		if (!$ret){		// 登録レコードがないとき
			$this->endTransaction();
			return false;
		}
		
		// レコードを更新
		$queryStr  = 'UPDATE _widgets ';
		$queryStr .=   'SET wd_initialized = ?, ';	// 初期化状態
		$queryStr .=     'wd_update_user_id = ?, ';
		$queryStr .=     'wd_update_dt = ? ';
		$queryStr .=   'WHERE wd_serial = ?';
		$this->execStatement($queryStr, array(intval($init), $userId, $now, $row['wd_serial']));
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * ページIDのリストを取得
	 *
	 * @param function $callback	コールバック関数
	 * @param int $type				リストの種別
	 * @param int $filter			データのフィルタリング(-1=PC携帯スマートフォンに関係なく取得、0=PC用のみ、1=携帯用のみ、2=スマートフォン用のみ)
	 * @return						なし
	 */
	function getPageIdList($callback, $type, $filter = -1)
	{
		$params = array($type);
		$queryStr = 'SELECT * FROM _page_id ';
		$queryStr .=  'WHERE pg_type = ? ';
		if ($filter != -1){
			// pg_device_typeは後で追加したため、pg_mobileを残しておく
			if ($filter != 1){			// 携帯以外のとき
				$queryStr .=    'AND pg_device_type = ? '; $params[] = $filter;
			}

			$queryStr .=  'AND pg_mobile = ? ';
			$mobile = 0;
			if ($filter == 1) $mobile = 1;			// 携帯のとき
			$params[] = $mobile;
		}
		$queryStr .=  'ORDER BY pg_priority';
		$this->selectLoop($queryStr, $params, $callback);
	}
	/**
	 * ページIDのリストを取得
	 *
	 * @param int $type				リストの種別
	 * @param string $pageId		ページID
	 * @param array $row			取得データ
	 * @return bool					true=成功、false=失敗
	 */
	function getPageIdRecord($type, $pageId, &$row)
	{
		$queryStr = 'SELECT * FROM _page_id ';
		$queryStr .=  'WHERE pg_type = ? ';
		$queryStr .=  'AND pg_id = ?';
		return $this->selectRecord($queryStr, array($type, $pageId), $row);
	}
	/**
	 * ページIDのリストを取得
	 *
	 * @param int $type				リストの種別
	 * @param array $row			取得データ
	 * @return bool					true=成功、false=失敗
	 */
	function getPageIdRecords($type, &$row)
	{
		$queryStr = 'select * from _page_id ';
		$queryStr .=  'where pg_type = ? ';
		$queryStr .=  'order by pg_priority';
		return $this->selectRecords($queryStr, array($type), $row);
	}
	/**
	 * サブページIDのリストを取得
	 *
	 * @param string $pageId		ページID
	 * @param string $langId		言語ID
	 * @param function $callback	コールバック関数
	 * @return						なし
	 */
	function getPageSubIdList($pageId, $langId, $callback)
	{
		//$queryStr = 'SELECT * FROM _page_info RIGHT JOIN _page_id ON pn_sub_id = pg_id AND pg_type = 1 AND pn_deleted = false AND pn_id = ? ';
		$queryStr = 'SELECT * FROM _page_info RIGHT JOIN _page_id ON pn_sub_id = pg_id AND pg_type = 1 AND pn_deleted = false AND pn_id = ? AND pn_language_id = ? ';// 2010/2/23更新
		$queryStr .=  'WHERE (pn_deleted IS NULL ';
		$queryStr .=    'AND pg_type = 1) ';		// サブページID
		$queryStr .=    'OR pn_deleted = false ';
		$queryStr .=  'ORDER BY pg_priority';
		$this->selectLoop($queryStr, array($pageId, $langId), $callback);
	}
	/**
	 * ページ情報の取得
	 *
	 * @param string $pageId		ページID
	 * @param string $pageSubId		ページサブID
	 * @param array $row			取得データ
	 * @param string $langId		言語ID
	 * @return						true=正常、false=異常
	 */
	function getPageInfo($pageId, $pageSubId, &$row, $langId = '')
	{
		$queryStr = 'SELECT * FROM _page_info RIGHT JOIN _page_id ON pn_sub_id = pg_id AND pg_type = 1 AND pn_deleted = false AND pn_id = ? AND pn_language_id = ? ';// 2010/2/23更新
		$queryStr .=  'WHERE (pn_deleted IS NULL ';
		$queryStr .=    'AND pg_type = 1 AND pg_id = ?) ';		// サブページID
		$queryStr .=    'OR (pn_deleted = false ';
		$queryStr .=    'AND pn_sub_id = ?) ';		// サブページID
		$ret = $this->selectRecord($queryStr, array($pageId, $langId, $pageSubId, $pageSubId), $row);
		return $ret;
	}
	/**
	 * ページ情報を更新
	 *
	 * @param string $pageId		ページID
	 * @param string $pageSubId		ページサブID
	 * @param string $contentType	コンテンツタイプ
	 * @param string $template		テンプレートID
	 * @param int $authType			アクセス制御タイプ(0=管理者のみ、1=制限なし、2=ログインユーザ)
	 * @param bool $ssl				SSLを使用するかどうか
	 * @param bool $userLimited		ユーザ制限するかどうか
	 * @return					true = 正常、false=異常
	 */
	function updatePageInfo($pageId, $pageSubId, $contentType='', $template='', $authType=0, $ssl = false, $userLimited = false)
	{
		$now = date("Y/m/d H:i:s");	// 現在日時
		$user = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		$metaTitle = '';
		$metaDesc = '';
		$metaKeyword = '';
		
		// トランザクション開始
		$this->startTransaction();
		
		// コンテンツタイプが指定されている場合は、他のデータのコンテンツタイプをクリア
		if (!empty($contentType)){
			$queryStr  = 'UPDATE _page_info ';
			$queryStr .=   'SET pn_content_type = \'\', ';		// コンテンツタイプをクリア
			$queryStr .=     'pn_update_user_id = ?, ';
			$queryStr .=     'pn_update_dt = ? ';
			$queryStr .=   'WHERE pn_deleted = false ';
			$queryStr .=     'AND pn_id = ? ';					// ページID
			$queryStr .=     'AND pn_content_type = ? ';		// コンテンツタイプ
			$queryStr .=     'AND pn_language_id = ? ';		// 言語ID(2010/2/23追加)
			$this->execStatement($queryStr, array($user, $now, $pageId, $contentType, ''/*言語なし*/));
		}
		
		// 指定のレコードの履歴インデックス取得
		$historyIndex = 0;		// 履歴番号
		$queryStr  = 'SELECT * FROM _page_info ';
		$queryStr .=   'WHERE pn_id = ? ';
		$queryStr .=     'AND pn_sub_id = ? ';
		$queryStr .=     'AND pn_language_id = ? ';		// 言語ID(2010/2/23追加)
		$queryStr .=  'ORDER BY pn_history_index DESC ';
		$ret = $this->selectRecord($queryStr, array($pageId, $pageSubId, ''/*言語なし*/), $row);
		if ($ret){
			$historyIndex = $row['pn_history_index'] + 1;
			$metaTitle = $row['pn_meta_title'];
			$metaDesc = $row['pn_meta_description'];
			$metaKeyword = $row['pn_meta_keywords'];
		
			// レコードが削除されていない場合は削除
			if (!$row['pn_deleted']){
				// 古いレコードを削除
				$queryStr  = 'UPDATE _page_info ';
				$queryStr .=   'SET pn_deleted = true, ';	// 削除
				$queryStr .=     'pn_update_user_id = ?, ';
				$queryStr .=     'pn_update_dt = ? ';
				$queryStr .=   'WHERE pn_serial = ?';
				$ret = $this->execStatement($queryStr, array($user, $now, $row['pn_serial']));
				if (!$ret){
					$this->endTransaction();
					return false;
				}
			}
		}
		
		// 新規レコード追加
		$queryStr = 'INSERT INTO _page_info ';
		$queryStr .=  '(';
		$queryStr .=  'pn_id, ';
		$queryStr .=  'pn_sub_id, ';
		$queryStr .=  'pn_language_id, ';// 言語ID(2010/2/23追加)
		$queryStr .=  'pn_history_index, ';
		$queryStr .=  'pn_template_id, ';
		$queryStr .=  'pn_meta_title, ';
		$queryStr .=  'pn_meta_description, ';
		$queryStr .=  'pn_meta_keywords, ';
		$queryStr .=  'pn_content_type, ';
		$queryStr .=  'pn_auth_type, ';
		$queryStr .=  'pn_use_ssl, ';
		$queryStr .=  'pn_user_limited, ';
		$queryStr .=  'pn_create_user_id, ';
		$queryStr .=  'pn_create_dt) ';
		$queryStr .=  'VALUES ';
		$queryStr .=  '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
		$ret =$this->execStatement($queryStr, array($pageId, $pageSubId, ''/*言語なし*/, $historyIndex, $template, $metaTitle, $metaDesc, $metaKeyword, $contentType, $authType, intval($ssl), intval($userLimited), $user, $now));
			
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * ページヘッダ情報を更新
	 *
	 * @param string $pageId		ページID
	 * @param string $pageSubId		ページサブID
	 * @param string $langId		言語ID
	 * @param string $metaTitle		METAタグ、タイトル
	 * @param string $metaDesc		METAタグ、ページ要約
	 * @param string $metaKeyword	METAタグ、検索用キーワード
	 * @return					true = 正常、false=異常
	 */
	function updatePageHead($pageId, $pageSubId, $langId, $metaTitle='', $metaDesc='', $metaKeyword='')
	{
		$now = date("Y/m/d H:i:s");	// 現在日時
		$user = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		$template = '';			// テンプレートID
		$contentType = '';
		$authType = 0;
		$ssl = false;
		$userLimited = false;
		
		// トランザクション開始
		$this->startTransaction();
		
		// 指定のレコードの履歴インデックス取得
		$historyIndex = 0;		// 履歴番号
		$queryStr  = 'SELECT * FROM _page_info ';
		$queryStr .=   'WHERE pn_id = ? ';
		$queryStr .=     'AND pn_sub_id = ? ';
		$queryStr .=     'AND pn_language_id = ? ';		// 言語ID(2010/2/23追加)
		$queryStr .=  'ORDER BY pn_history_index DESC ';
		$ret = $this->selectRecord($queryStr, array($pageId, $pageSubId, $langId), $row);
		if ($ret){
			$historyIndex = $row['pn_history_index'] + 1;
			$template = $row['pn_template_id'];			// テンプレートID
			$contentType = $row['pn_content_type'];
			$authType = $row['pn_auth_type'];
			$ssl = $row['pn_use_ssl'];
			$userLimited = $row['pn_user_limited'];
			
			// レコードが削除されていない場合は削除
			if (!$row['pn_deleted']){
				// 古いレコードを削除
				$queryStr  = 'UPDATE _page_info ';
				$queryStr .=   'SET pn_deleted = true, ';	// 削除
				$queryStr .=     'pn_update_user_id = ?, ';
				$queryStr .=     'pn_update_dt = ? ';
				$queryStr .=   'WHERE pn_serial = ?';
				$ret = $this->execStatement($queryStr, array($user, $now, $row['pn_serial']));
				if (!$ret){
					$this->endTransaction();
					return false;
				}
			}
		}
		
		// 新規レコード追加
		$queryStr = 'INSERT INTO _page_info ';
		$queryStr .=  '(';
		$queryStr .=  'pn_id, ';
		$queryStr .=  'pn_sub_id, ';
		$queryStr .=  'pn_language_id, ';// 言語ID(2010/2/23追加)
		$queryStr .=  'pn_history_index, ';
		$queryStr .=  'pn_template_id, ';
		$queryStr .=  'pn_meta_title, ';
		$queryStr .=  'pn_meta_description, ';
		$queryStr .=  'pn_meta_keywords, ';
		$queryStr .=  'pn_content_type, ';
		$queryStr .=  'pn_auth_type, ';
		$queryStr .=  'pn_use_ssl, ';
		$queryStr .=  'pn_user_limited, ';
		$queryStr .=  'pn_create_user_id, ';
		$queryStr .=  'pn_create_dt) ';
		$queryStr .=  'VALUES ';
		$queryStr .=  '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
		$ret =$this->execStatement($queryStr, array($pageId, $pageSubId, $langId, $historyIndex, $template, $metaTitle, $metaDesc, $metaKeyword, $contentType, $authType, intval($ssl), intval($userLimited), $user, $now));
			
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * ページIDの更新
	 *
	 * @param int $type				ページタイプ(0=ページID,1=ページサブID)
	 * @param string  $id			ID
	 * @param string  $name			名前
	 * @param string  $desc			説明
	 * @param int  $priority		優先度
	 * @param bool  $active			有効かどうか
	 * @return						true=成功、false=失敗
	 */
	function updatePageId($type, $id, $name, $desc, $priority, $active)
	{
		// トランザクション開始
		$this->startTransaction();
		
		$ret = $this->isExistsPageId($type, $id);
		if ($ret){		// データが存在する場合
			// 既存項目を更新
			$queryStr  = 'UPDATE _page_id ';
			$queryStr .=   'SET ';
			$queryStr .=     'pg_name = ?, ';
			$queryStr .=     'pg_description = ?, ';
			$queryStr .=     'pg_priority = ?, ';
			$queryStr .=     'pg_active = ? ';
			$queryStr .=   'WHERE pg_id = ? ';
			$queryStr .=     'AND pg_type = ? ';
			$this->execStatement($queryStr, array($name, $desc, $priority, intval($active), $id, $type));
		} else {
			// 新規レコードを追加
			$queryStr  = 'INSERT INTO _page_id (';
			$queryStr .=   'pg_id, ';
			$queryStr .=   'pg_type, ';
			$queryStr .=   'pg_name, ';
			$queryStr .=   'pg_description, ';
			$queryStr .=   'pg_priority, ';
			$queryStr .=   'pg_active ';
			$queryStr .= ') VALUES (';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?) ';
			$this->execStatement($queryStr, array($id, $type, $name, $desc, $priority, intval($active)));
		}

		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * ページIDの存在チェック
	 *
	 * @param int $type				リストの種別
	 * @param string  $id			ID
	 * @return bool					true=存在する、false=存在しない
	 */
	function isExistsPageId($type, $id)
	{
		$queryStr = 'SELECT * FROM _page_id ';
		$queryStr .=  'WHERE pg_type = ? ';
		$queryStr .=  'AND pg_id = ? ';
		return $this->isRecordExists($queryStr, array($type, $id));
	}
	/**
	 * ページIDの削除
	 *
	 * @param int $type				リストの種別
	 * @param string  $id			ID
	 * @return bool					true=存在する、false=存在しない
	 */
	function deletePageId($type, $id)
	{
		// トランザクション開始
		$this->startTransaction();
		
		$queryStr = 'DELETE FROM _page_id ';
		$queryStr .=  'WHERE pg_type = ? ';
		$queryStr .=  'AND pg_id = ? ';
		$this->execStatement($queryStr, array($type, $id));
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * ページポジションのリストを取得
	 *
	 * @param function $callback	コールバック関数
	 * @return						なし
	 */
	function getPagePositionList($callback)
	{
		$queryStr = 'select * from _template_position ';
		$queryStr .=  'order by tp_sort_order';
		$this->selectLoop($queryStr, array(), $callback);
	}
	/**
	 * ページ定義のリスト取得
	 *
	 * @param function $callback	コールバック関数
	 * @param string $pageId		ページID
	 * @param string $pageSubId		ページサブID
	 * @param string $position		表示位置。空文字列のときはすべて取得。
	 * @param int    $setId			定義セットID
	 * @return						なし
	 */
	function getPageDefList($callback, $pageId, $pageSubId, $position = '', $setId = 0)
	{
		$queryStr  = 'select * from _page_def left join _widgets on pd_widget_id = wd_id and wd_deleted = false ';
		$queryStr .=   'where pd_id = ? ';
		$queryStr .=     'and (pd_sub_id = ? or pd_sub_id = \'\') ';	// 空の場合は共通項目
		$queryStr .=     'and pd_set_id = ? ';
		if (empty($position)){
			$queryStr .=   'order by pd_position_id, pd_index';
			$this->selectLoop($queryStr, array($pageId, $pageSubId, $setId), $callback);
		} else {
			$queryStr .=     'and pd_position_id = ? ';
			$queryStr .=   'order by pd_position_id, pd_index';
			$this->selectLoop($queryStr, array($pageId, $pageSubId, $setId, $position), $callback);
		}
	}
	/**
	 * ページ定義があるか確認
	 *
	 * @param string $pageId		ページID
	 * @param string $pageSubId		ページサブID
	 * @param string $position	表示位置
	 * @param int $index		表示インデックス
	 * @param int    $setId			定義セットID
	 * @return bool				true=存在する、false=存在しない
	 */
	 /*
	function isPageDefExists($pageId, $pageSubId, $position, $index, $setId = 0)
	{
		$queryStr  = 'select * from _page_def ';
		$queryStr .=   'where pd_id = ? ';
		$queryStr .=     'and pd_sub_id = ? ';
		$queryStr .=     'and pd_position_id = ? ';
		$queryStr .=     'and pd_index = ? ';
		return $this->isRecordExists($queryStr, array($pageId, $pageSubId, $position, $index));
	}*/
	/**
	 * ページ定義を取得
	 *
	 * @param int $serialNo			シリアルNo
	 * @param array  $rows			更新データ
	 * @return bool				true=存在する、false=存在しない
	 */
	function getPageDef($serialNo, &$row)
	{
		$queryStr  = 'SELECT * FROM _page_def LEFT JOIN _widgets on pd_widget_id = wd_id AND wd_deleted = false ';
		$queryStr .=   'WHERE pd_serial = ?';
		return $this->selectRecord($queryStr, array($serialNo), $row);
	}
	/**
	 * ページ定義項目の更新
	 *
	 * @param int $serialNo			シリアルNo(0のとき新規追加)
	 * @param string $pageId		ページID
	 * @param string $pageSubId		ページサブID
	 * @param string $position		表示位置
	 * @param int $index			表示インデックスNo
	 * @param string $widgetId		ウィジェットID
	 * @param int $configId			定義ID
	 * @param string $suffix		サフィックス
	 * @param string $style			css
	 * @param bool $visible			表示状態
	 * @param int $userId			ユーザID(データ更新者)
	 * @param int    $setId			定義セットID
	 * @return						true=成功、false=失敗
	 */
	function updatePageDef($serialNo, $pageId, $pageSubId, $position, $index, $widgetId, $configId, $suffix, $style, $visible, $userId, $setId = 0)
	{
		// 更新ユーザ、日時設定
		$this->now = date("Y/m/d H:i:s");	// 現在日時
		$this->userId = $userId;
		$editable = 1;		// 編集可能
		
		// トランザクション開始
		$this->startTransaction();

		if ($serialNo == 0){		// 新規追加
			// 新規データを追加
			$queryStr  = 'INSERT INTO _page_def (';
			$queryStr .=   'pd_id, ';
			$queryStr .=   'pd_sub_id, ';
			$queryStr .=   'pd_set_id, ';
			$queryStr .=   'pd_position_id, ';
			$queryStr .=   'pd_index, ';
			$queryStr .=   'pd_widget_id, ';
			$queryStr .=   'pd_config_id, ';
			$queryStr .=   'pd_suffix, ';
			$queryStr .=   'pd_style, ';
			$queryStr .=   'pd_visible, ';
			$queryStr .=   'pd_editable, ';
			$queryStr .=   'pd_update_user_id, ';
			$queryStr .=   'pd_update_dt) ';
			$queryStr .= 'VALUES (';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?, ';
			$queryStr .=   '?)';
			$this->execStatement($queryStr, array($pageId, $pageSubId, $setId, $position, $index, 
								$widgetId, $configId, $suffix, $style, $visible, $editable, $this->userId, $this->now));
		} else {			// 更新
			$queryStr  = 'select * from _page_def ';
			$queryStr .=   'where pd_serial = ? ';
			$ret = $this->selectRecord($queryStr, array($serialNo), $row);
			if ($ret){
				if ($row['pd_id'] != $pageId || $row['pd_sub_id'] != $pageSubId){			// 表示ページが変更された
					// 新規に追加して、古いレコードを削除
					// 新規データを追加
					$queryStr  = 'INSERT INTO _page_def (';
					$queryStr .=   'pd_id, ';
					$queryStr .=   'pd_sub_id, ';
					$queryStr .=   'pd_set_id, ';
					$queryStr .=   'pd_position_id, ';
					$queryStr .=   'pd_index, ';
					$queryStr .=   'pd_widget_id, ';
					$queryStr .=   'pd_config_id, ';
					$queryStr .=   'pd_suffix, ';
					$queryStr .=   'pd_style, ';
					$queryStr .=   'pd_visible, ';
					$queryStr .=   'pd_editable, ';
					$queryStr .=   'pd_update_user_id, ';
					$queryStr .=   'pd_update_dt) ';
					$queryStr .= 'VALUES (';
					$queryStr .=   '?, ';
					$queryStr .=   '?, ';
					$queryStr .=   '?, ';
					$queryStr .=   '?, ';
					$queryStr .=   '?, ';
					$queryStr .=   '?, ';
					$queryStr .=   '?, ';
					$queryStr .=   '?, ';
					$queryStr .=   '?, ';
					$queryStr .=   '?, ';
					$queryStr .=   '?, ';
					$queryStr .=   '?, ';
					$queryStr .=   '?)';
					$this->execStatement($queryStr, array($pageId, $pageSubId, $row['pd_set_id'], $position, $index, 
										$widgetId, $configId, $suffix, $style, $visible, $editable, $this->userId, $this->now));
										
					// 旧データ削除
					$queryStr  = 'DELETE FROM _page_def WHERE pd_serial = ?';
					$this->execStatement($queryStr, array($serialNo));
				} else {
					// 既存項目を更新
					$queryStr  = 'UPDATE _page_def ';
					$queryStr .=   'SET ';
					$queryStr .=     'pd_position_id = ?, ';
					$queryStr .=     'pd_index = ?, ';
					$queryStr .=     'pd_widget_id = ?, ';
					$queryStr .=     'pd_config_id = ?, ';
					$queryStr .=     'pd_suffix = ?, ';
					$queryStr .=     'pd_style = ?, ';
					$queryStr .=     'pd_visible = ?, ';
					$queryStr .=     'pd_editable = ?, ';
					$queryStr .=     'pd_update_user_id = ?, ';
					$queryStr .=     'pd_update_dt = ? ';
					$queryStr .=   'WHERE pd_serial = ? ';
					$this->execStatement($queryStr, array($position, $index, 
										$widgetId, $configId, $suffix, $style, $visible, $editable, $this->userId, $this->now, $serialNo));
				}
			}
		}

		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * ページ定義項目のスタイル値の変更
	 *
	 * @param int $serialNo			シリアルNo
	 * @param string $style			スタイル値
	 * @param string $title			タイトル
	 * @param bool $titleVisible	タイトルを表示するかどうか
	 * @param bool $useRender		Joomla!の描画処理を使用するかどうか
	 * @return						true=成功、false=失敗
	 */
	function updatePageDefInfo($serialNo, $style, $title, $titleVisible, $useRender)
	{
		$now = date("Y/m/d H:i:s");	// 現在日時
		$user = $this->gEnv->getCurrentUserId();	// 現在のユーザ

		// トランザクション開始
		$this->startTransaction();
		
		// 既存項目を更新
		$queryStr  = 'UPDATE _page_def ';
		$queryStr .=   'SET ';
		$queryStr .=     'pd_style = ?, ';
		$queryStr .=     'pd_title = ?, ';
		$queryStr .=     'pd_title_visible = ?, ';
		$queryStr .=     'pd_use_render = ?, ';
		$queryStr .=     'pd_update_user_id = ?, ';
		$queryStr .=     'pd_update_dt = ? ';
		$queryStr .=   'WHERE pd_serial = ? ';
		$ret = $this->execStatement($queryStr, array($style, $title, intval($titleVisible), intval($useRender), $user, $now, $serialNo));

		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * ページ定義項目の削除
	 *
	 * @param int $serialNo			シリアルNo
	 * @param int $userId			ユーザID(データ更新者)
	 * @return						true=成功、false=失敗
	 */
	function delPageDef($serialNo, $userId)
	{
		// 更新ユーザ、日時設定
		$this->now = date("Y/m/d H:i:s");	// 現在日時
		$this->userId = $userId;
		
		// トランザクション開始
		$this->startTransaction();
		
		$queryStr  = 'DELETE FROM _page_def WHERE pd_serial = ?';
		$this->execStatement($queryStr, array($serialNo));
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	
	/**
	 * ページ定義項目をすべて削除
	 *
	 * @param string  $pageId			ページID
	 * @param string  $pageSubId		ページサブID
	 * @param string  $position			表示ポジション
	 * @param bool $withCommon			共通項目も削除するかどうか
	 * @param int    $setId			定義セットID
	 * @return						true=成功、false=失敗
	 */
	function delPageDefAll($pageId, $pageSubId, $position, $withCommon, $setId = 0)
	{
		// トランザクション開始
		$this->startTransaction();
		
		if (empty($position)){
			$queryStr  = 'DELETE FROM _page_def ';
			$queryStr .=   'WHERE pd_id = ? ';
			if ($withCommon){
				$queryStr .=     'and (pd_sub_id = ? or pd_sub_id = \'\') ';	// 空の場合は共通項目
			} else {
				$queryStr .=     'and pd_sub_id = ? ';	// 空の場合は共通項目
			}
			$queryStr .=     'and pd_set_id = ? ';
			$this->execStatement($queryStr, array($pageId, $pageSubId, $setId));
		} else {
			$queryStr  = 'DELETE FROM _page_def ';
			$queryStr .=   'WHERE pd_id = ? ';
			if ($withCommon){
				$queryStr .=     'and (pd_sub_id = ? or pd_sub_id = \'\') ';	// 空の場合は共通項目
			} else {
				$queryStr .=     'and pd_sub_id = ? ';	// 空の場合は共通項目
			}
			$queryStr .=     'and pd_position_id = ? ';
			$queryStr .=     'and pd_set_id = ? ';
			$this->execStatement($queryStr, array($pageId, $pageSubId, $position, $setId));
		}
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * ユーザリスト取得
	 *
	 * @param int		$limit				取得する項目数
	 * @param int		$page				取得するページ(1～)
	 * @param function $callback	コールバック関数
	 * @return						なし
	 */
	function getAllUserList($limit, $page, $callback)
	{
		$offset = $limit * ($page -1);
		if ($offset < 0) $offset = 0;
		
		$queryStr = 'SELECT * FROM _login_user ';
		$queryStr .=  'WHERE lu_deleted = false ';// 削除されていない
		$queryStr .=  'ORDER BY lu_user_type, lu_account limit ' . $limit . ' offset ' . $offset;
		$this->selectLoop($queryStr, array(), $callback);
	}
	/**
	 * ユーザ総数取得
	 *
	 * @return int					総数
	 */
	function getAllUserListCount()
	{
		$queryStr = 'select * from _login_user ';
		$queryStr .=  'where lu_deleted = false ';// 削除されていない
		return $this->selectRecordCount($queryStr, array());
	}
	/**
	 * ログイン状況取得
	 *
	 * @param int		$limit				取得する項目数
	 * @param int		$page				取得するページ(1～)
	 * @param function $callback	コールバック関数
	 * @return						なし
	 */
	function getUserLoginStatusList($limit, $page, $callback)
	{
		$offset = $limit * ($page -1);
		if ($offset < 0) $offset = 0;
		
		$queryStr = 'SELECT lu_id,lu_account,lu_name,lu_user_type,lu_user_status,ll_login_count,ll_access_log_serial,ll_pre_login_dt,ll_last_login_dt, ';
		$queryStr .=    'CASE WHEN ll_last_login_dt IS NULL THEN 1 ELSE 0 ';
		$queryStr .=    'END AS ord ';
		$queryStr .=    'FROM _login_user LEFT JOIN _login_log on lu_id = ll_user_id ';
		$queryStr .=  'WHERE lu_deleted = false ';// 削除されていない
		$queryStr .=  'ORDER BY ord, ll_last_login_dt desc limit ' . $limit . ' offset ' . $offset;
		$this->selectLoop($queryStr, array(), $callback);
	}
	/**
	 * ログイン状況数取得
	 *
	 * @return int					総数
	 */
	function getUserLoginStatusListCount()
	{
		$queryStr = 'SELECT * FROM _login_user LEFT JOIN _login_log on lu_id = ll_user_id ';
		$queryStr .=  'WHERE lu_deleted = false ';// 削除されていない
		return $this->selectRecordCount($queryStr, array());
	}
	/**
	 * 新規ユーザの追加
	 *
	 * @param string  $name			名前
	 * @param string  $account		アカウント
	 * @param string  $password		パスワード
	 * @param int     $userType		ユーザ種別
	 * @param bool    $canLogin		ログインできるかどうか
	 * @param int     $newSerial	新規シリアル番号
	 * @return						true=成功、false=失敗
	 */
	function addNewUser($name, $account, $password, $userType, $canLogin, &$newSerial)
	{
		$now = date("Y/m/d H:i:s");	// 現在日時
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		
		// トランザクション開始
		$this->startTransaction();
		
		// 新規IDを作成
		$newId = 1;
		$queryStr = 'select max(lu_id) as ms from _login_user ';
		$ret = $this->selectRecord($queryStr, array(), $row);
		if ($ret) $newId = $row['ms'] + 1;
		
		// 新規レコードを追加
		$queryStr  = 'INSERT INTO _login_user (';
		$queryStr .=   'lu_id, ';
		$queryStr .=   'lu_history_index, ';
		$queryStr .=   'lu_name, ';
		$queryStr .=   'lu_account, ';
		$queryStr .=   'lu_password, ';
		$queryStr .=   'lu_user_type, ';
		$queryStr .=   'lu_enable_login, ';
		$queryStr .=   'lu_create_user_id, ';
		$queryStr .=   'lu_create_dt ';
		$queryStr .= ') VALUES (';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?) ';
		$this->execStatement($queryStr, array($newId, 0, $name, $account, $password, $userType, $canLogin, $userId, $now));
		
		// 新規のシリアル番号取得
		$queryStr = 'select max(lu_serial) as ns from _login_user ';
		$ret = $this->selectRecord($queryStr, array(), $row);
		if ($ret) $newSerial = $row['ns'];
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * ユーザの削除
	 *
	 * @param int $serialNo			シリアルNo
	 * @param int $userId			ユーザID(データ更新者)
	 * @return						true=成功、false=失敗
	 */
	/*function delUser($serialNo, $userId)
	{
		// トランザクション開始
		$this->startTransaction();
		
		// 指定のシリアルNoのレコードが削除状態でないかチェック
		$queryStr  = 'select * from _login_user ';
		$queryStr .=   'where lu_deleted = false ';		// 未削除
		$queryStr .=     'and lu_serial = ? ';
		$ret = $this->isRecordExists($queryStr, array($serialNo));
		// 存在しない場合は、既に削除されたとして終了
		if (!$ret){
			$this->endTransaction();
			return false;
		}
		
		// レコードを削除
		$queryStr  = 'UPDATE _login_user ';
		$queryStr .=   'SET lu_deleted = true, ';	// 削除
		$queryStr .=     'lu_update_user_id = ?, ';
		$queryStr .=     'lu_update_dt = now() ';
		$queryStr .=   'WHERE lu_serial = ?';
		$this->execStatement($queryStr, array($userId, $serialNo));
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}*/
	/**
	 * ユーザの削除
	 *
	 * @param array $serial			シリアルNo
	 * @return						true=成功、false=失敗
	 */
	function delUserBySerial($serial)
	{
		// 引数のエラーチェック
		if (!is_array($serial)) return false;
		if (count($serial) <= 0) return true;
		
		$now = date("Y/m/d H:i:s");	// 現在日時
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		
		// トランザクション開始
		$this->startTransaction();
		
		// 指定のシリアルNoのレコードが削除状態でないかチェック
		for ($i = 0; $i < count($serial); $i++){
			$queryStr  = 'SELECT * FROM _login_user ';
			$queryStr .=   'WHERE lu_deleted = false ';		// 未削除
			$queryStr .=     'AND lu_serial = ? ';
			$ret = $this->isRecordExists($queryStr, array($serial[$i]));
			// 存在しない場合は、既に削除されたとして終了
			if (!$ret){
				$this->endTransaction();
				return false;
			}
		}
		
		// レコードを削除
		$queryStr  = 'UPDATE _login_user ';
		$queryStr .=   'SET lu_deleted = true, ';	// 削除
		$queryStr .=     'lu_update_user_id = ?, ';
		$queryStr .=     'lu_update_dt = ? ';
		$queryStr .=   'WHERE lu_serial in (' . implode($serial, ',') . ') ';
		$this->execStatement($queryStr, array($userId, $now));
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * ユーザの更新
	 *
	 * @param int $serial			シリアル番号
	 * @param string  $name			ユーザ名
	 * @param string  $account		アカウント
	 * @param string  $password		パスワード(空のときは更新しない)
	 * @param int     $userType		ユーザ種別
	 * @param string $canLogin		ログイン可能かどうか
	 * @param int     $newSerial	新規シリアル番号
	 * @return						true=成功、false=失敗
	 */
	function updateUser($serial, $name, $account, $password, $userType, $canLogin, &$newSerial)
	{
		$now = date("Y/m/d H:i:s");	// 現在日時
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
				
		// トランザクション開始
		$this->startTransaction();
		
		// 指定のシリアルNoのレコードが削除状態でないかチェック
		$historyIndex = 0;		// 履歴番号
		$queryStr  = 'select * from _login_user ';
		$queryStr .=   'where lu_serial = ? ';
		$ret = $this->selectRecord($queryStr, array($serial), $row);
		if ($ret){		// 既に登録レコードがあるとき
			if ($row['lu_deleted']){		// レコードが削除されていれば終了
				$this->endTransaction();
				return false;
			}
			$historyIndex = $row['lu_history_index'] + 1;
		} else {		// 存在しない場合は終了
			$this->endTransaction();
			return false;
		}
		
		// パスワードが設定されているときは更新
		$pwd = $row['lu_password'];
		if (!empty($password)) $pwd = $password;
		
		// 古いレコードを削除
		$queryStr  = 'UPDATE _login_user ';
		$queryStr .=   'SET lu_deleted = true, ';	// 削除
		$queryStr .=     'lu_update_user_id = ?, ';
		$queryStr .=     'lu_update_dt = ? ';
		$queryStr .=   'WHERE lu_serial = ?';
		$this->execStatement($queryStr, array($userId, $now, $serial));

		// 新規レコード追加
		$queryStr  = 'INSERT INTO _login_user (';
		$queryStr .=   'lu_id, ';
		$queryStr .=   'lu_history_index, ';
		$queryStr .=   'lu_name, ';
		$queryStr .=   'lu_account, ';
		$queryStr .=   'lu_password, ';
		$queryStr .=   'lu_user_type, ';
		$queryStr .=   'lu_assign, ';
		$queryStr .=   'lu_widget_id, ';
		$queryStr .=   'lu_enable_login, ';
		$queryStr .=   'lu_create_user_id, ';
		$queryStr .=   'lu_create_dt ';
		$queryStr .= ') VALUES (';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?) ';
		$this->execStatement($queryStr, array($row['lu_id'], $historyIndex, $name, $account, $pwd, $userType, $row['lu_assign'], $row['lu_widget_id'], $canLogin, $userId, $now));

		// 新規のシリアル番号取得
		$queryStr = 'select max(lu_serial) as ns from _login_user ';
		$ret = $this->selectRecord($queryStr, array(), $row);
		if ($ret) $newSerial = $row['ns'];
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * ユーザ情報をシリアル番号で取得
	 *
	 * @param string	$serial				シリアル番号
	 * @param array     $row				レコード
	 * @return bool							取得 = true, 取得なし= false
	 */
	function getUserBySerial($serial, &$row)
	{
		$queryStr  = 'select * from _login_user ';
		$queryStr .=   'WHERE lu_serial = ? ';
		$ret = $this->selectRecord($queryStr, array($serial), $row);
		return $ret;
	}
	/**
	 * ユーザアカウントが存在するかチェック
	 *
	 * @param string $account	アカウント
	 * @return					true=存在する、false=存在しない
	 */
	 /*
	function isExistsAccount($account)
	{
		$queryStr = 'SELECT * from _login_user ';
		$queryStr .=  'WHERE lu_account = ? ';
		$queryStr .=    'AND lu_deleted = false';
		return $this->isRecordExists($queryStr, array($account));
	}*/
	/**
	 * テンプレートリスト取得
	 *
	 * @param int      $type			テンプレートのタイプ(0=PC用、1=携帯用、2=スマートフォン)
	 * @param function $callback		コールバック関数
	 * @param bool     $availableOnly	利用可能なテンプレートに制限するかどうか
	 * @return							なし
	 */
	function getAllTemplateList($type, $callback, $availableOnly = true)
	{
		// tm_device_typeは後で追加したため、tm_mobileを残しておく
		$queryStr = 'SELECT * FROM _templates ';
		$queryStr .=  'WHERE tm_deleted = false ';// 削除されていない
		if ($availableOnly) $queryStr .=    'AND tm_available = true ';		// 利用可能
		$params = array();
		switch ($type){
			case 0:		// PC用テンプレート
			case 2:		// スマートフォン用テンプレート
			default:
				$queryStr .=    'AND tm_mobile = false ';		// 携帯用以外
				$queryStr .=    'AND tm_device_type = ? '; $params[] = $type;
				break;
			case 1:		// 携帯用のとき
				$queryStr .=    'AND tm_mobile = true ';		// 携帯用
				break;
		}
		$queryStr .=  'ORDER BY tm_id';
		$this->selectLoop($queryStr, $params, $callback);
	}
	/**
	 * テンプレートIDリスト取得
	 *
	 * @param array  $rows			取得レコード
	 * @return						true=取得、false=取得せず
	 */
	function getAllTemplateIdList(&$rows)
	{
		$queryStr = 'SELECT * FROM _templates ';
		$queryStr .=  'WHERE tm_deleted = false ';// 削除されていない
		$queryStr .=  'ORDER BY tm_id';
		$retValue = $this->selectRecords($queryStr, array(), $rows);
		return $retValue;
	}
	/**
	 * 携帯用テンプレートIDリスト取得
	 *
	 * @param array  $rows			取得レコード
	 * @return						true=取得、false=取得せず
	 */
	function getAllMobileTemplateIdList(&$rows)
	{
		$queryStr = 'SELECT * FROM _templates ';
		$queryStr .=  'WHERE tm_deleted = false ';// 削除されていない
		$queryStr .=  'AND tm_mobile = true ';// 携帯
		$queryStr .=  'ORDER BY tm_id';
		$retValue = $this->selectRecords($queryStr, array(), $rows);
		return $retValue;
	}
	/**
	 * テンプレートの追加
	 *
	 * @param string  $id			テンプレートID
	 * @param string  $name			テンプレート名
	 * @param int     $type			テンプレートのタイプ
	 * @param int     $deviceType	端末タイプ(0=PC用、1=携帯用、2=スマートフォン)
	 * @param int     $cleanType	クリーン処理タイプ
	 * @return						なし
	 */
	function addNewTemplate($id, $name, $type, $deviceType = 0, $cleanType = 0)
	{
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		$now = date("Y/m/d H:i:s");	// 現在日時
		$historyIndex = 0;
		$mobile = 0;				// 携帯端末かどうか
		if ($deviceType == 1) $mobile = 1;
		
		// トランザクション開始
		$this->startTransaction();
		
		// 同じIDが登録済みかどうかチェック
		$queryStr = 'SELECT * FROM _templates ';
		$queryStr .=  'WHERE tm_id = ? ';
		$queryStr .=  'ORDER BY tm_history_index DESC ';
		$ret = $this->selectRecord($queryStr, array($id), $row);
		if ($ret){
			if (!$row['tm_deleted']){		// レコードが削除されていなければ、削除
				// 古いレコードを削除
				$queryStr  = 'UPDATE _templates ';
				$queryStr .=   'SET tm_deleted = true, ';	// 削除
				$queryStr .=     'tm_update_user_id = ?, ';
				$queryStr .=     'tm_update_dt = ? ';
				$queryStr .=   'WHERE tm_serial = ?';
				$this->execStatement($queryStr, array($userId, $now, $row['tm_serial']));			
			}
			$historyIndex = $row['tm_history_index'] + 1;
		}
		
		$queryStr = 'INSERT INTO _templates ';
		$queryStr .=  '(tm_id, tm_history_index, tm_name, tm_type, tm_device_type, tm_mobile, tm_clean_type, tm_create_dt, tm_create_user_id) ';
		$queryStr .=  'VALUES ';
		$queryStr .=  '(?, ?, ?, ?, ?, ?, ?, ?, ?)';
		$this->execStatement($queryStr, array($id, $historyIndex, $name, $type, $deviceType, $mobile, $cleanType, $now, $userId));
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * テンプレートの更新
	 *
	 * @param string $templateId	テンプレートID
	 * @param string  $name			ウィジェット名
	 * @return						true=成功、false=失敗
	 */
	function updateTemplate($templateId, $name)
	{
		$now = date("Y/m/d H:i:s");	// 現在日時
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
				
		// トランザクション開始
		$this->startTransaction();
		
		// 既存データを取得
		$historyIndex = 0;		// 履歴番号
		$queryStr = 'SELECT * FROM _templates ';
		$queryStr .=  'WHERE tm_id = ? ';
		$queryStr .=  'ORDER BY tm_history_index DESC ';
		$ret = $this->selectRecord($queryStr, array($templateId), $row);
		if ($ret){
			if ($row['tm_deleted']){		// レコードが削除されていれば終了
				$this->endTransaction();
				return false;
			} else {		// レコードが削除されていなければ、削除
				// 古いレコードを削除
				$queryStr  = 'UPDATE _templates ';
				$queryStr .=   'SET tm_deleted = true, ';	// 削除
				$queryStr .=     'tm_update_user_id = ?, ';
				$queryStr .=     'tm_update_dt = ? ';
				$queryStr .=   'WHERE tm_serial = ?';
				$this->execStatement($queryStr, array($userId, $now, $row['tm_serial']));			
			}
			$historyIndex = $row['tm_history_index'] + 1;
		} else {
			$this->endTransaction();
			return false;
		}
		
		// 新規レコード追加
		$queryStr  = 'INSERT INTO _templates (';
		$queryStr .=   'tm_id, ';
		$queryStr .=   'tm_history_index, ';
		$queryStr .=   'tm_name, ';
		$queryStr .=   'tm_type, ';
		$queryStr .=   'tm_device_type, ';
		$queryStr .=   'tm_mobile, ';
		$queryStr .=   'tm_clean_type, ';
		$queryStr .=   'tm_available, ';
		$queryStr .=   'tm_create_user_id, ';
		$queryStr .=   'tm_create_dt ';
		$queryStr .= ') VALUES (';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?)';
		$this->execStatement($queryStr, array($row['tm_id'], $historyIndex, $name, $row['tm_type'], intval($row['tm_device_type']), intval($row['tm_mobile']), $row['tm_clean_type'], intval($row['tm_available']), $userId, $now));

		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * テンプレートの削除
	 *
	 * @param string $templateId	テンプレートID
	 * @return						true=成功、false=失敗
	 */
	function deleteTemplate($templateId)
	{
		$now = date("Y/m/d H:i:s");	// 現在日時
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		
		// トランザクション開始
		$this->startTransaction();
		
		// 既存データを取得
		$queryStr = 'SELECT * FROM _templates ';
		$queryStr .=  'WHERE tm_deleted = false ';
		$queryStr .=  'AND tm_id = ? ';
		$ret = $this->selectRecord($queryStr, array($templateId), $row);
		if (!$ret){
			$this->endTransaction();
			return false;
		}
		// レコードを削除
		$queryStr  = 'UPDATE _templates ';
		$queryStr .=   'SET tm_deleted = true, ';	// 削除
		$queryStr .=     'tm_update_user_id = ?, ';
		$queryStr .=     'tm_update_dt = ? ';
		$queryStr .=   'WHERE tm_serial = ?';
		$this->execStatement($queryStr, array($userId, $now, $row['tm_serial']));
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;		
	}
	/**
	 * 通貨一覧を取得
	 *
	 * @param string	$lang				言語
	 * @param function	$callback			コールバック関数
	 * @return 			なし
	 */
	 /*
	function getCurrency($lang, $callback)
	{
		$queryStr = 'SELECT * FROM _currency ';
		$queryStr .=  'WHERE cu_language_id = ? ';
		$queryStr .=  'ORDER BY cu_index';
		$this->selectLoop($queryStr, array($lang), $callback, null);
	}*/
	/**
	 * すべての言語を取得
	 *
	 * @param function	$callback			コールバック関数
	 * @return			true=取得、false=取得せず
	 */
	function getAllLang($callback)
	{
		$queryStr = 'SELECT * FROM _language ORDER BY ln_priority';
		$this->selectLoop($queryStr, array(), $callback, null);
	}
	/**
	 * メニュー項目の表示状態を更新
	 *
	 * @param string $groupId	更新対象グループID
	 * @param bool $visible		表示状態
	 * @return					true = 正常、false=異常
	 */
	function updateMenuVisible($groupId, $visible)
	{
		$sql = "UPDATE _nav_item SET ni_visible = ? WHERE ni_group_id = ?";
		$params = array($visible, $groupId);
		return $this->execStatement($sql, $params);
	}
	/**
	 * トップ画面表示項目を取得
	 *
	 * @param string $navId			ナビゲーションバー識別ID
	 * @param array  $rows			取得レコード
	 * @return						true=取得、false=取得せず
	 */
	/*function getTopPageItems($navId, &$rows)
	{
		$queryStr  = 'SELECT * FROM _nav_item ';
		$queryStr .=   'WHERE ni_nav_id = ? ';
		$queryStr .=     'AND ni_top_page_index != 0 ';		// 0以外を表示
		$queryStr .=     'AND ni_visible = true ';
		$queryStr .=   'ORDER BY ni_top_page_index';
		$retValue = $this->selectRecords($queryStr, array($navId), $rows);
		return $retValue;
	}*/
	/**
	 * ナビゲーションバー項目を取得
	 *
	 * @param string $navId			ナビゲーションバー識別ID
	 * @param string $parentId		親項目ID
	 * @param array  $rows			取得レコード
	 * @return						true=取得、false=取得せず
	 */
	function getNavItems($navId, $parentId, &$rows)
	{
		$queryStr  = 'SELECT * FROM _nav_item ';
		$queryStr .=   'WHERE ni_nav_id = ? ';
		$queryStr .=     'AND ni_parent_id = ? ';
		$queryStr .=     'AND ni_visible = true ';
		$queryStr .=   'ORDER BY ni_index';
		
		$retValue = $this->selectRecords($queryStr, array($navId, $parentId), $rows);
		return $retValue;
	}
	/**
	 * ナビゲーションバー項目をすべて取得
	 *
	 * @param string 	$navId			ナビゲーションバー識別ID
	 * @param function	$callback		コールバック関数
	 * @return 			なし
	 */
	function getNavItemsAll($navId, $callback)
	{
		$queryStr  = 'SELECT * FROM _nav_item ';
		$queryStr .=   'WHERE ni_nav_id = ? ';
		$queryStr .=   'ORDER BY ni_id';
		$this->selectLoop($queryStr, array($navId), $callback, null);
	}
	/**
	 * ナビゲーションバー項目をすべて取得
	 *
	 * @param string 	$navId			ナビゲーションバー識別ID
	 * @param array  	$rows			取得レコード
	 * @return 			なし
	 */
	function getNavItemsAllRecords($navId, &$rows)
	{
		$queryStr  = 'SELECT * FROM _nav_item ';
		$queryStr .=   'WHERE ni_nav_id = ? ';
		$queryStr .=   'ORDER BY ni_id';
		$retValue = $this->selectRecords($queryStr, array($navId), $rows);
		return $retValue;
	}
	/**
	 * ナビゲーションバー項目を削除
	 *
	 * @param string $menuId		メニュー識別ID
	 * @return						true=成功、false=失敗
	 */
	function delNavItems($menuId)
	{
		$sql = "DELETE FROM _nav_item WHERE ni_nav_id = ?";
		$params = array($menuId);
		$this->execStatement($sql, $params);
	}
	/**
	 * ナビゲーションバー項目の最大IDを取得
	 *
	 * @return int			最大ID
	 */
	function getNavItemsMaxId()
	{
		$max = 0;
		$queryStr = 'SELECT max(ni_id) as mid FROM _nav_item ';
		$ret = $this->selectRecord($queryStr, array(), $row);
		if ($ret) $max = $row['mid'];
		return $max;
	}
	/**
	 * ナビゲーションバー項目キー存在チェック
	 *
	 * @param string $menuId		メニュー識別ID
	 * @param string $taskId		タスクID
	 * @param string $param			追加パラメータ
	 * @return bool					true=存在する、false=存在しない
	 */
	function isExistsNavItemKey($menuId, $taskId, $param)
	{
		$queryStr = 'SELECT * FROM _nav_item ';
		$queryStr .=  'WHERE ni_nav_id = ? ';
		$queryStr .=  'AND ni_task_id = ? ';
		$queryStr .=  'AND ni_param = ? ';
		return $this->isRecordExists($queryStr, array($menuId, $taskId, $param));
	}
	/**
	 * ナビゲーションバー項目を更新
	 *
	 * @param string $navId			ナビゲーションバー識別ID
	 * @param int $id				項目ID
	 * @param int $parentId			項目親項目ID
	 * @param int $index			インデックス番号起動
	 * @param string $taskId		タスクID
	 * @param string $param			追加パラメータ
	 * @param int $control			改行指示(0=改行しない、1=改行)
	 * @param string $name			項目名
	 * @param string $helpTitle		ヘルプタイトル
	 * @param string $helpBody		ヘルプ本体
	 * @return						true=成功、false=失敗
	 */
	function addNavItems($navId, $id, $parentId, $index, $taskId, $param, $control, $name, $helpTitle, $helpBody)
	{
		// 新規レコード追加
		$groupId = '';
		$queryStr  = 'INSERT INTO _nav_item (';
		$queryStr .=   'ni_id, ';
		$queryStr .=   'ni_parent_id, ';
		$queryStr .=   'ni_index, ';
		$queryStr .=   'ni_nav_id, ';
		$queryStr .=   'ni_task_id, ';
		$queryStr .=   'ni_param, ';
		$queryStr .=   'ni_group_id, ';
		$queryStr .=   'ni_view_control, ';
		$queryStr .=   'ni_name, ';
		$queryStr .=   'ni_help_title, ';
		$queryStr .=   'ni_help_body ';
		$queryStr .= ') VALUES (';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?, ';
		$queryStr .=   '?)';
		$ret = $this->execStatement($queryStr, array($id, $parentId, $index, $navId, $taskId, $param, $groupId, $control, $name, $helpTitle, $helpBody));
		return $ret;
	}
	/**
	 * 変換キーテーブルを取得
	 *
	 * @param string	$key				キー文字列
	 * @param string	$group				グループID
	 * @param function	$callback			コールバック関数
	 * @return 			なし
	 */
	function getAllKey($key, $group, $callback)
	{
		$queryStr = 'SELECT * FROM _key_value ';
		$queryStr .=  'WHERE kv_deleted = false ';
		$queryStr .=    'AND kv_id LIKE \'' . $key . '%\' ';
		$queryStr .=    'AND kv_group_id = ? ';
		$queryStr .=  'ORDER BY kv_id';
		$this->selectLoop($queryStr, array($group), $callback, null);
	}
	/**
	 * 運用ログ取得
	 *
	 * @param int		$level		取得ログのレベル(0すべて、1=注意以上、10=要確認)
	 * @param int		$status		取得するデータの状況(0=すべて、1=未参照のみ、2=参照済みのみ)
	 * @param int		$limit		取得する項目数
	 * @param int		$page		取得するページ(1～)
	 * @param function	$callback	コールバック関数
	 * @return						なし
	 */
	function getOpeLogList($level, $status, $limit, $page, $callback)
	{
		// メッセージ種別
		// 通常メッセージ: info=情報,warn=警告,user_info=ユーザ操作
		// 参照必須メッセージ: error=通常エラー,fatal=致命的エラー,user_err=ユーザ操作エラー,user_access=不正アクセス,user_data=不正データ
		$offset = $limit * ($page -1);
		if ($offset < 0) $offset = 0;
		
		$queryStr = 'SELECT * FROM _operation_log LEFT JOIN _operation_type ON ol_type = ot_id ';
		$queryStr .= 'LEFT JOIN _access_log ON ol_access_log_serial = al_serial ';
		
		// 必須参照項目のみに限定
		$params = array();
		$addWhere = '';
		if ($level > 0){
			$addWhere .= 'WHERE ot_level >= ? ';
			$params[] = $level;
		}
		// 参照状況を制限
		if ($status == 1){		// 未参照
			if (empty($addWhere)){
				$addWhere .= 'WHERE ';
			} else {
				$addWhere .= 'AND ';
			}
			$addWhere .= 'ol_checked = false ';
		} else if ($status == 2){	// 参照済み
			if (empty($addWhere)){
				$addWhere .= 'WHERE ';
			} else {
				$addWhere .= 'AND ';
			}
			$addWhere .= 'ol_checked = true ';
		}
		$queryStr .= $addWhere;
		$queryStr .=  'ORDER BY ol_serial DESC limit ' . $limit . ' offset ' . $offset;
		$this->selectLoop($queryStr, $params, $callback);
	}
	/**
	 * 運用ログ総数取得
	 *
	 * @param int		$level		取得ログのレベル(0すべて、1=参照必須)
	 * @param int		$status		取得するデータの状況(0=すべて、1=未参照のみ、2=参照済みのみ)
	 * @return int					総数
	 */
	function getOpeLogCount($level, $status)
	{
		$queryStr = 'SELECT * FROM _operation_log LEFT JOIN _operation_type ON ol_type = ot_id ';
		
		// 必須参照項目のみに限定
		$params = array();
		$addWhere = '';
		if ($level > 0){
			$addWhere .= 'WHERE ot_level >= ? ';
			$params[] = $level;
		}
		// 参照状況を制限
		if ($status == 1){		// 未参照
			if (empty($addWhere)){
				$addWhere .= 'WHERE ';
			} else {
				$addWhere .= 'AND ';
			}
			$addWhere .= 'ol_checked = false ';
		} else if ($status == 2){	// 参照済み
			if (empty($addWhere)){
				$addWhere .= 'WHERE ';
			} else {
				$addWhere .= 'AND ';
			}
			$addWhere .= 'ol_checked = true ';
		}
		$queryStr .= $addWhere;
		return $this->selectRecordCount($queryStr, $params);
	}
	/**
	 * 運用ログの取得
	 *
	 * @param string  $serial		シリアル番号
	 * @return						true=正常、false=異常
	 */
	function getOpeLog($serial, &$row)
	{
		$queryStr = 'SELECT * FROM _operation_log LEFT JOIN _operation_type ON ol_type = ot_id ';
		$queryStr .=   'WHERE ol_serial = ? ';
		$ret = $this->selectRecord($queryStr, array($serial), $row);
		return $ret;
	}
	/**
	 * 運用ログの確認状況を更新
	 *
	 * @param string  $serial		シリアル番号
	 * @param bool    $checked		確認状況
	 * @return						true=正常、false=異常
	 */
	function updateOpeLogChecked($serial, $checked)
	{
		$queryStr = "UPDATE _operation_log SET ol_checked = ? WHERE ol_serial = ?";
		$params = array(intval($checked), $serial);
		return $this->execStatement($queryStr, $params);
	}
	/**
	 * アクセスログ取得
	 *
	 * @param int		$limit		取得する項目数
	 * @param int		$page		取得するページ(1～)
	 * @param string	$path		アクセスパス
	 * @param function	$callback	コールバック関数
	 * @param timestamp	$startDt	期間(開始日)
	 * @param timestamp	$endDt		期間(終了日)
	 * @return						なし
	 */
	function getAccessLogList($limit, $page, $path, $callback, $startDt, $endDt)
	{
		$offset = $limit * ($page -1);
		if ($offset < 0) $offset = 0;
		
		$params = array();
		$queryStr = 'SELECT * FROM _access_log LEFT JOIN _login_user on al_user_id = lu_id ';
		if (!is_null($path)){
			$queryStr .=  'WHERE al_path = ? ';
			$params[] = $path;
		}
		// 日付範囲
		if (!empty($startDt)){
			if (count($params) > 0){
				$queryStr .=    'AND ? <= al_dt ';
			} else {
				$queryStr .=    'WHERE ? <= al_dt ';
			}
			$params[] = $startDt;
		}
		if (!empty($endDt)){
			if (count($params) > 0){
				$queryStr .=    'AND al_dt < ? ';
			} else {
				$queryStr .=    'WHERE al_dt < ? ';
			}
			$params[] = $endDt;
		}
		$queryStr .=  'ORDER BY al_serial DESC limit ' . $limit . ' offset ' . $offset;
		$this->selectLoop($queryStr, $params, $callback);
	}
	/**
	 * アクセスログ総数取得
	 *
	 * @param string	$path		アクセスパス
	 * @param timestamp	$startDt	期間(開始日)
	 * @param timestamp	$endDt		期間(終了日)
	 * @return int					総数
	 */
	function getAccessLogCount($path, $startDt, $endDt)
	{
		$params = array();
		$queryStr = 'SELECT * FROM _access_log ';
		if (!is_null($path)){
			$queryStr .=  'WHERE al_path = ? ';
			$params[] = $path;
		}
		// 日付範囲
		if (!empty($startDt)){
			if (count($params) > 0){
				$queryStr .=    'AND ? <= al_dt ';
			} else {
				$queryStr .=    'WHERE ? <= al_dt ';
			}
			$params[] = $startDt;
		}
		if (!empty($endDt)){
			if (count($params) > 0){
				$queryStr .=    'AND al_dt < ? ';
			} else {
				$queryStr .=    'WHERE al_dt < ? ';
			}
			$params[] = $endDt;
		}
		return $this->selectRecordCount($queryStr, $params);
	}
	/**
	 * アクセスログの取得
	 *
	 * @param string  $serial		シリアル番号
	 * @return						true=正常、false=異常
	 */
	function getAccessLog($serial, &$row)
	{
		$queryStr = 'SELECT * FROM _access_log LEFT JOIN _login_user on al_user_id = lu_id ';
		$queryStr .=   'WHERE al_serial = ? ';
		$ret = $this->selectRecord($queryStr, array($serial), $row);
		return $ret;
	}
	/**
	 * 検索語ログ取得
	 *
	 * @param int		$limit		取得する項目数
	 * @param int		$page		取得するページ(1～)
	 * @param string	$path		アクセスパス
	 * @param function	$callback	コールバック関数
	 * @return						なし
	 */
	function getSearchWordLogList($limit, $page, $path, $callback)
	{
		$offset = $limit * ($page -1);
		if ($offset < 0) $offset = 0;
		
		$params = array();
		$queryStr  = 'SELECT * FROM _search_word  ';
		$queryStr .=   'LEFT JOIN _access_log ON sw_access_log_serial = al_serial ';
		$queryStr .=   'LEFT JOIN _login_user on al_user_id = lu_id ';
		if (!is_null($path)){
			$queryStr .=  'WHERE sw_path = ? ';
			$params[] = $path;
		}
		$queryStr .=  'ORDER BY sw_serial DESC limit ' . $limit . ' offset ' . $offset;
		$this->selectLoop($queryStr, $params, $callback);
	}
	/**
	 * 検索語ログ総数取得
	 *
	 * @param string	$path		アクセスパス
	 * @return int					総数
	 */
	function getSearchWordLogCount($path)
	{
		$params = array();
		$queryStr = 'SELECT * FROM _search_word ';
		if (!is_null($path)){
			$queryStr .=  'WHERE sw_path = ? ';
			$params[] = $path;
		}
		return $this->selectRecordCount($queryStr, $params);
	}
	/**
	 * 比較語から検索語ログ取得
	 *
	 * @param string    $word		比較語
	 * @param int		$limit		取得する項目数
	 * @param int		$page		取得するページ(1～)
	 * @param string	$path		アクセスパス
	 * @param function	$callback	コールバック関数
	 * @return						なし
	 */
	function getSearchWordLogListByWord($word, $limit, $page, $path, $callback)
	{
		$offset = $limit * ($page -1);
		if ($offset < 0) $offset = 0;
		
		$params = array();
		$queryStr  = 'SELECT * FROM _search_word  ';
		$queryStr .=   'LEFT JOIN _access_log ON sw_access_log_serial = al_serial ';
		$queryStr .=   'LEFT JOIN _login_user on al_user_id = lu_id ';
		$queryStr .=   'WHERE sw_basic_word = ? '; $params[] = $word;
		if (!is_null($path)){
			$queryStr .=  'AND sw_path = ? ';
			$params[] = $path;
		}
		$queryStr .=  'ORDER BY sw_serial DESC limit ' . $limit . ' offset ' . $offset;
		$this->selectLoop($queryStr, $params, $callback);
	}
	/**
	 * 比較語から検索語ログ総数取得
	 *
	 * @param string    $word		比較語
	 * @param string	$path		アクセスパス
	 * @return int					総数
	 */
	function getSearchWordLogCountByWord($word, $path)
	{
		$params = array();
		$queryStr  = 'SELECT * FROM _search_word ';
		$queryStr .=   'WHERE sw_basic_word = ? '; $params[] = $word;
		if (!is_null($path)){
			$queryStr .=  'AND sw_path = ? ';
			$params[] = $path;
		}
		return $this->selectRecordCount($queryStr, $params);
	}
	/**
	 * 検索語検索数リスト取得
	 *
	 * @param int		$limit		取得する項目数
	 * @param int		$page		取得するページ(1～)
	 * @param string	$path		アクセスパス
	 * @param function	$callback	コールバック関数
	 * @return						なし
	 */
	function getSearchWordSumList($limit, $page, $path, $callback)
	{
		$offset = $limit * ($page -1);
		if ($offset < 0) $offset = 0;
		
		$params = array();
		$queryStr  = 'SELECT count(*) AS ct, sw_basic_word FROM _search_word ';
		if (!is_null($path)){
			$queryStr .=  'WHERE sw_path = ? ';
			$params[] = $path;
		}
		$queryStr .=  'GROUP BY sw_basic_word ';
		$queryStr .=  'ORDER BY ct DESC limit ' . $limit . ' offset ' . $offset;
		$this->selectLoop($queryStr, $params, $callback);
	}
	/**
	 * 検索語検索数総数取得
	 *
	 * @param string	$path		アクセスパス
	 * @return int					総数
	 */
	function getSearchWordSumCount($path)
	{
		$params = array();
		$queryStr  = 'SELECT count(*) AS ct FROM _search_word ';
		if (!is_null($path)){
			$queryStr .=  'WHERE sw_path = ? ';
			$params[] = $path;
		}
		$queryStr .=   'GROUP BY sw_basic_word';
		return $this->selectRecordCount($queryStr, $params);
	}
	/**
	 * 検索語ログの取得
	 *
	 * @param int  $serial		シリアル番号
	 * @return						true=正常、false=異常
	 */
	function getSearchWordLog($serial, &$row)
	{
		$queryStr  = 'SELECT * FROM _search_word  ';
		$queryStr .=   'LEFT JOIN _access_log ON sw_access_log_serial = al_serial ';
		$queryStr .=   'LEFT JOIN _login_user on al_user_id = lu_id ';
		$queryStr .=   'WHERE sw_serial = ? ';
		$ret = $this->selectRecord($queryStr, array($serial), $row);
		return $ret;
	}
	/**
	 * 比較語から検索語ログの取得
	 *
	 * @param string  $word		比較語
	 * @return					true=正常、false=異常
	 */
	function getSearchWordLogByCompareWord($word, &$row)
	{
		$queryStr  = 'SELECT * FROM _search_word  ';
		$queryStr .=   'LEFT JOIN _access_log ON sw_access_log_serial = al_serial ';
		$queryStr .=   'LEFT JOIN _login_user on al_user_id = lu_id ';
		$queryStr .=   'WHERE sw_basic_word = ? ';
		$queryStr .=   'ORDER BY sw_serial DESC ';
		$ret = $this->selectRecord($queryStr, array($word), $row);
		return $ret;
	}
	/**
	 * メニュー項目の追加
	 *
	 * @param string  $menuId		メニューID
	 * @param string  $parentId		親メニュー項目ID
	 * @param string  $name			メニュー名
	 * @param string  $desc			説明
	 * @param int     $index		インデックス番号(0のときは最大値を設定)
	 * @param int     $type			項目タイプ
	 * @param int     $linkType		リンクタイプ
	 * @param string  $url			URL
	 * @param bool    $visible		表示状態
	 * @param int     $newId		新規ID
	 * @param string  $contentType	リンク先コンテンツタイプ
	 * @param string  $contentId	リンク先コンテンツID
	 * @return bool					true = 成功、false = 失敗
	 */
	function addMenuItem($menuId, $parentId, $name, $desc, $index, $type, $linkType, $url, $visible, &$newId, $contentType, $contentId)
	{
		$now = date("Y/m/d H:i:s");	// 現在日時
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		
		// トランザクション開始
		$this->startTransaction();
		
		// IDを求める
		$id = 1;
		$queryStr = 'SELECT max(md_id) as ms FROM _menu_def ';
		$ret = $this->selectRecord($queryStr, array(), $maxRow);
		if ($ret) $id = $maxRow['ms'] + 1;
			
		// インデックスが0のときは、最大値を格納
		if (empty($index)){
			$index = 1;
			$queryStr = 'SELECT max(md_index) as ms FROM _menu_def ';
			$queryStr .=  'WHERE md_menu_id = ? ';
			$ret = $this->selectRecord($queryStr, array($menuId), $maxRow);
			if ($ret) $index = $maxRow['ms'] + 1;
		}
		$queryStr = 'INSERT INTO _menu_def ';
		$queryStr .=  '(md_id, md_parent_id, md_index, md_menu_id, md_name, md_description, md_type, md_link_type, md_link_url, md_visible, md_content_type, md_content_id, md_update_user_id, md_update_dt) ';
		$queryStr .=  'VALUES ';
		$queryStr .=  '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
		$this->execStatement($queryStr, array($id, $parentId, $index, $menuId, $name, $desc, $type, $linkType, $url, intval($visible), $contentType, $contentId, $userId, $now));
		
		// 新規のシリアル番号取得
		$queryStr = 'select max(md_id) as ns from _menu_def ';
		$ret = $this->selectRecord($queryStr, array(), $row);
		if ($ret) $newId = $row['ns'];
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * メニュー項目の更新
	 *
	 * @param int     $id			メニュー項目ID
	 * @param string  $name			メニュー名
	 * @param string  $desc			説明
	 * @param int     $type			項目タイプ
	 * @param int     $linkType		リンクタイプ
	 * @param string  $url			URL
	 * @param bool    $visible		表示状態
	 * @param string  $contentType	リンク先コンテンツタイプ
	 * @param string  $contentId	リンク先コンテンツID
	 * @return bool					true = 成功、false = 失敗
	 */
	function updateMenuItem($id, $name, $desc, $type, $linkType, $url, $visible, $contentType, $contentId)
	{
		$now = date("Y/m/d H:i:s");	// 現在日時
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		
		// トランザクション開始
		$this->startTransaction();

		$params = array();
		$queryStr = 'UPDATE _menu_def ';
		$queryStr .=  'SET md_name = ?, ';			$params[] = $name;
		$queryStr .=    'md_description = ?, ';		$params[] = $desc;
		$queryStr .=    'md_type = ?, ';			$params[] = $type;
		$queryStr .=    'md_link_type = ?, ';		$params[] = $linkType;
		$queryStr .=    'md_link_url = ?, ';		$params[] = $url;
		$queryStr .=    'md_visible = ?, ';			$params[] = $visible;
		$queryStr .=    'md_content_type = ?, ';	$params[] = $contentType;
		$queryStr .=    'md_content_id = ?, ';		$params[] = $contentId;
		$queryStr .=    'md_update_user_id = ?, ';	$params[] = $userId;
		$queryStr .=    'md_update_dt = ? ';		$params[] = $now;
		$queryStr .=  'WHERE md_id = ? ';			$params[] = $id;
		$this->execStatement($queryStr, $params);

		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * メニュー項目の削除
	 *
	 * @param string $id			複数シリアルNoをカンマ区切り
	 * @return						true=成功、false=失敗
	 */
	function delMenuItems($id)
	{
		// トランザクション開始
		$this->startTransaction();
		
		// レコードを削除
		$queryStr  = 'DELETE FROM _menu_def ';
		$queryStr .=   'WHERE md_id in (' . $id . ') ';
		$this->execStatement($queryStr, array());
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * メニュー項目をIDで取得
	 *
	 * @param int     $id			メニュー項目ID
	 * @param array   $row			レコード
	 * @return bool					取得 = true, 取得なし= false
	 */
	function getMenuItem($id, &$row)
	{
		$queryStr  = 'SELECT * FROM _menu_def ';
		$queryStr .=   'WHERE md_id = ? ';
		$ret = $this->selectRecord($queryStr, array($id), $row);
		return $ret;
	}
	/**
	 * メニュー項目を取得
	 *
	 * @param string $menuId		メニュー識別ID
	 * @param string $parentId		親項目ID
	 * @param array  $rows			取得レコード
	 * @return						true=取得、false=取得せず
	 */
	function getChildMenuItems($menuId, $parentId, &$rows)
	{
		$queryStr  = 'SELECT * FROM _menu_def ';
		$queryStr .=   'WHERE md_menu_id = ? ';
		$queryStr .=     'AND md_parent_id = ? ';
		$queryStr .=   'ORDER BY md_index';
		$retValue = $this->selectRecords($queryStr, array($menuId, $parentId), $rows);
		return $retValue;
	}
	/**
	 * メニューの項目を取得(管理用)
	 *
	 * @param string $menuId		メニューID
	 * @param function $callback	コールバック関数
	 * @return 						なし
	 */
	function getAllMenuItems($menuId, $callback)
	{
		$queryStr  = 'SELECT * FROM _menu_def ';
		$queryStr .=   'WHERE md_menu_id = ? ';
		$queryStr .=   'ORDER BY md_parent_id, md_index';
		$this->selectLoop($queryStr, array($menuId), $callback);
	}
	/**
	 * メニュー項目順序を変更
	 *
	 * @param string $menuId		メニュー識別ID
	 * @param int $parentId			親項目ID
	 * @param int $id				項目ID
	 * @param int $pos				新規の位置
	 * @return						true=成功、false=失敗
	 */
	function reorderMenuItem($menuId, $parentId, $id, $pos)
	{
		$now = date("Y/m/d H:i:s");	// 現在日時
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		
		// トランザクション開始
		$this->startTransaction();
		
		$queryStr  = 'SELECT * FROM _menu_def ';
		$queryStr .=   'WHERE md_menu_id = ? ';
		$queryStr .=     'AND md_parent_id = ? ';
		$queryStr .=   'ORDER BY md_index';
		$retValue = $this->selectRecords($queryStr, array($menuId, $parentId), $rows);
		
		// 同階層内かどうかチェック
		$insPos = $pos;			// 項目挿入位置
		for ($i = 0; $i < count($rows); $i++){
			if ($id == $rows[$i]['md_id']){
				if ($i < $pos) $insPos++;
				break;
			}
		}
		$index = 0;
		for ($i = 0; $i < $insPos; $i++){
			$itemId = $rows[$i]['md_id'];
			if ($itemId != $id){
				$queryStr  = 'UPDATE _menu_def ';
				$queryStr .=   'SET md_index = ?, ';	// インデックス
				$queryStr .=     'md_update_user_id = ?, ';
				$queryStr .=     'md_update_dt = ? ';
				$queryStr .=   'WHERE md_id = ?';
				$ret = $this->execStatement($queryStr, array($index, $userId, $now, $itemId));
				$index++;
			}
		}
		$queryStr  = 'UPDATE _menu_def ';
		$queryStr .=   'SET md_index = ?, ';	// インデックス
		$queryStr .=     'md_parent_id = ?, ';
		$queryStr .=     'md_update_user_id = ?, ';
		$queryStr .=     'md_update_dt = ? ';
		$queryStr .=   'WHERE md_id = ?';
		$ret = $this->execStatement($queryStr, array($index, $parentId, $userId, $now, $id));
		$index++;
		for ($i = $insPos; $i < count($rows); $i++){
			$itemId = $rows[$i]['md_id'];
			if ($itemId != $id){
				$queryStr  = 'UPDATE _menu_def ';
				$queryStr .=   'SET md_index = ?, ';	// インデックス
				$queryStr .=     'md_update_user_id = ?, ';
				$queryStr .=     'md_update_dt = ? ';
				$queryStr .=   'WHERE md_id = ?';
				$ret = $this->execStatement($queryStr, array($index, $userId, $now, $itemId));
				$index++;
			}
		}
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * メニュー項目の表示順を変更する
	 *
	 * @param string  $menuId			メニューID
	 * @param int $parentId				親項目ID
	 * @param bool $visibleOnly			表示項目だけかどうか
	 * @param array $menuItemNoArray	並び順
	 * @return bool					true = 成功、false = 失敗
	 */
	function orderMenuItems($menuId, $parentId, $visibleOnly, $menuItemNoArray)
	{
		// メニュー項目をすべて取得
		$queryStr  = 'SELECT * FROM _menu_def ';
		$queryStr .=   'WHERE md_menu_id = ? ';
		$queryStr .=     'AND md_parent_id = ? ';
		if ($visibleOnly) $queryStr .= 'AND md_visible = true ';		// 表示中の項目
		$queryStr .=   'ORDER BY md_index';
		$ret = $this->selectRecords($queryStr, array($menuId, $parentId), $rows);
		if (!$ret) return false;
	
		// メニュー数をチェックし、異なっている場合はエラー
		$menuItemCount = count($rows);
		if ($menuItemCount != count($menuItemNoArray)) return false;
		
		$now = date("Y/m/d H:i:s");	// 現在日時
		$userId = $this->gEnv->getCurrentUserId();	// 現在のユーザ
		
		// トランザクション開始
		$this->startTransaction();

		for ($i = 0; $i < $menuItemCount; $i++){
			$id = $rows[$menuItemNoArray[$i]]['md_id'];
			$index = $rows[$i]['md_index'];

			// 既存項目を更新
			$queryStr  = 'UPDATE _menu_def ';
			$queryStr .=   'SET ';
			$queryStr .=     'md_index = ?, ';
			$queryStr .=     'md_update_user_id = ?, ';
			$queryStr .=     'md_update_dt = ? ';
			$queryStr .=   'WHERE md_id = ? ';
			$this->execStatement($queryStr, array($index, $userId, $now, $id));
		}
										
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * コンテンツ項目一覧を取得
	 *
	 * @param string	$lang				言語
	 * @param string	$contentType		コンテンツタイプ
	 * @param function	$callback			コールバック関数
	 * @return 			なし
	 */
	function getVisibleAllContents($lang, $contentType, $callback)
	{
		$queryStr = 'SELECT * FROM content ';
		$queryStr .=  'WHERE cn_type = ? ';
		$queryStr .=    'AND cn_language_id = ? ';
		$queryStr .=    'AND cn_visible = true ';		// 画面に表示可能
		$queryStr .=    'AND cn_deleted = false ';		// 削除されていない
		$queryStr .=  'ORDER BY cn_id';
		$this->selectLoop($queryStr, array($contentType, $lang), $callback, null);
	}
	/**
	 * 汎用コンテンツを外部キーで取得
	 *
	 * @param string	$contentType		コンテンツタイプ
	 * @param string	$langId				言語ID
	 * @param string	$key				外部キー
	 * @param array     $row				レコード
	 * @return bool							取得 = true, 取得なし= false
	 */
	function getContentByKey($contentType, $langId, $key, &$row)
	{
		$queryStr  = 'SELECT * FROM content ';
		$queryStr .=   'WHERE cn_deleted = false ';	// 削除されていない
		$queryStr .=     'AND cn_type = ? ';
		$queryStr .=     'AND cn_language_id = ? ';
		$queryStr .=     'AND cn_key = ? ';
		$queryStr .=   'ORDER BY cn_id';
		$ret = $this->selectRecord($queryStr, array($contentType, $langId, $key), $row);
		return $ret;
	}
	/**
	 * メニューIDのリストを取得
	 *
	 * @param function $callback	コールバック関数
	 * @return						なし
	 */
	function getMenuIdList($callback)
	{
		$queryStr = 'SELECT * FROM _menu_id ';
		$queryStr .=  'ORDER BY mn_sort_order';
		$this->selectLoop($queryStr, array(), $callback);
	}
	/**
	 * メニューIDのレコードを取得
	 *
	 * @param string  $id			メニューID
	 * @param array   $row			レコード
	 * @return bool					取得 = true, 取得なし= false
	 */
	function getMenuId($id, &$row)
	{
		$retValue = '';
		$queryStr = 'SELECT * FROM _menu_id ';
		$queryStr .=  'WHERE mn_id  = ?';
		$ret = $this->selectRecord($queryStr, array($id), $row);
		return $ret;
	}
	/**
	 * メニューIDのレコードを更新
	 *
	 * @param string $id	メニューID(存在しない場合は新規追加)
	 * @param string $name	名前
	 * @param string $desc	説明
	 * @param int    $order	ソート順
	 * @return bool			true=更新成功、false=更新失敗
	 */
	function updateMenuId($id, $name, $desc, $order)
	{
		// トランザクション開始
		$this->startTransaction();
		
		$queryStr = 'SELECT * FROM _menu_id ';
		$queryStr .=  'WHERE mn_id  = ?';
		$ret = $this->selectRecord($queryStr, array($id), $row);
		if ($ret){
			$queryStr  = 'UPDATE _menu_id ';
			$queryStr .=   'SET mn_name = ?, ';
			$queryStr .=     'mn_description = ?, ';
			$queryStr .=     'mn_sort_order = ? ';
			$queryStr .=   'WHERE mn_id = ?';
			$ret = $this->execStatement($queryStr, array($name, $desc, $order, $id));			
		} else {
			$queryStr = 'INSERT INTO _menu_id (';
			$queryStr .=  'mn_id, ';
			$queryStr .=  'mn_name, ';
			$queryStr .=  'mn_description, ';
			$queryStr .=  'mn_sort_order ';
			$queryStr .=  ') VALUES (';
			$queryStr .=  '?, ?, ?, ?';
			$queryStr .=  ')';
			$ret = $this->execStatement($queryStr, array($id, $name, $desc, $order));	
		}
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * メニューIDの削除
	 *
	 * @param array $serial			メニューIDの配列
	 * @return						true=成功、false=失敗
	 */
	function delMenuId($serial)
	{
		// 引数のエラーチェック
		if (!is_array($serial)) return false;
		if (count($serial) <= 0) return true;
		
		// トランザクション開始
		$this->startTransaction();
		
		// 指定のシリアルNoのレコードが削除状態でないかチェック
		$delId = '';
		for ($i = 0; $i < count($serial); $i++){
			$queryStr  = 'SELECT * FROM _menu_id ';
			$queryStr .=   'WHERE mn_id = ? ';
			$ret = $this->isRecordExists($queryStr, array($serial[$i]));
			// 存在しない場合は、既に削除されたとして終了
			if (!$ret){
				$this->endTransaction();
				return false;
			}
			$delId .= '\'' . addslashes($serial[$i]) . '\',';
		}
		$delId = rtrim($delId, ',');
		
		// データ削除
		$queryStr  = 'DELETE FROM _menu_id ';
		$queryStr .=   'WHERE mn_id in (' . $delId . ') ';
		$this->execStatement($queryStr, array());
		
		// トランザクション確定
		$ret = $this->endTransaction();
		return $ret;
	}
	/**
	 * メニューIDの存在チェック
	 *
	 * @param string  $id			メニューID
	 * @return bool					true=存在する、false=存在しない
	 */
	function isExistsMenuId($id)
	{
		$queryStr = 'SELECT * FROM _menu_id ';
		$queryStr .=  'WHERE mn_id = ? ';
		return $this->isRecordExists($queryStr, array($id));
	}
}
?>
