<?php
/**
 * コンテナクラス
 *
 * 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-2008 Magic3 Project.
 * @license    http://www.gnu.org/copyleft/gpl.html  GPL License
 * @version    SVN: $Id: admin_mainWidgetlistWidgetContainer.php 575 2008-05-04 06:14:43Z fishbone $
 * @link       http://www.magic3.org
 */
require_once($gEnvManager->getContainerPath()		. '/baseWidgetContainer.php');
require_once($gEnvManager->getCurrentWidgetDbPath() . '/admin_mainDb.php');
require_once($gEnvManager->getLibPath()				. '/pcl/pclzip.lib.php' );

class admin_mainWidgetlistWidgetContainer extends BaseWidgetContainer
{
	private $db;	// DB接続オブジェクト
	private $newWidget = array();		// 新規追加ウィジェット
	private $defaultImageSize = 32;		// ウィジェット画像サイズ
	
	/**
	 * コンストラクタ
	 */
	function __construct()
	{
		// 親クラスを呼び出す
		parent::__construct();
		
		// DB接続オブジェクト作成
		$this->db = new admin_mainDb();
	}
	/**
	 * テンプレートファイルを設定
	 *
	 * _assign()でデータを埋め込むテンプレートファイルのファイル名を返す。
	 * 読み込むディレクトリは、「自ウィジェットディレクトリ/include/template」に固定。
	 *
	 * @param RequestManager $request		HTTPリクエスト処理クラス
	 * @param object         $param			任意使用パラメータ。そのまま_assign()に渡る
	 * @return string 						テンプレートファイル名。テンプレートライブラリを使用しない場合は空文字列「''」を返す。
	 */
	function _setTemplate($request, &$param)
	{	
		if ($this->db->canDetailConfig()){		// 詳細設定可能なとき
			return 'widgetlist.tmpl.html';
		} else {
			return 'widgetlist_simple.tmpl.html';
		}
	}
	/**
	 * テンプレートにデータ埋め込む
	 *
	 * _setTemplate()で指定したテンプレートファイルにデータを埋め込む。
	 *
	 * @param RequestManager $request		HTTPリクエスト処理クラス
	 * @param object         $param			任意使用パラメータ。_setTemplate()と共有。
	 * @param								なし
	 */
	function _assign($request, &$param)
	{
		global $gEnvManager;
		global $gSystemManager;
		global $gLaunchManager;
		global $gMessageManager;
		
		$act = $request->trimValueOf('act');
		$selectedItemNo = $request->trimValueOf('no');		// 処理対象の項目番号
		$serial = $request->trimValueOf('serial');		// シリアルNo
		$widgetId = $request->trimValueOf('widget');		// 処理対象のウィジェット
		$userInfo = $gEnvManager->getCurrentUserInfo();
				
		if ($act == 'readnew'){		// ウィジェット再読み込みのとき
			$addWidgetCount = 0;
			// ウィジェット一覧取得
			if ($this->db->getAllWidgetIdList($rows)){
				// ウィジェットディレクトリチェック
				$searchPath = $gEnvManager->getWidgetsPath();
				if (is_dir($searchPath)){
					$dir = dir($searchPath);
					while (($file = $dir->read()) !== false){
						$filePath = $searchPath . '/' . $file;
						// ディレクトリかどうかチェック
						if (strncmp($file, '.', 1) != 0 && $file != '..' && is_dir($filePath)
								&& strncmp($file, '_', 1) != 0		// 「_」で始まる名前のディレクトリは読み込まない
								&& strcmp($file, 'm') != 0){		// 携帯用のディレクトリ「m」は読み込まない
							// DBに登録されていない場合は登録
							for ($i = 0; $i < count($rows); $i++){
								if ($file == $rows[$i]['wd_id']) break;
							}
							if ($i == count($rows)){
								$userInfo = $gEnvManager->getCurrentUserInfo();
								$this->db->addNewWidget($file, '(名称未設定)', $userInfo->userId);
								$this->newWidget[] = $file;			// 新規ウィジェットID保存
								$addWidgetCount++;		// ウィジェット追加
							}
						}
					}
					$dir->close();
				}
			} else {
			}
			// 終了メッセージを表示
			if ($addWidgetCount > 0){
				$msg = '新規ウィジェットを追加しました(追加数=' . $addWidgetCount . ')';
			} else {
				$msg = '新規ウィジェットはありません';
			}
			$this->setMsg(self::MSG_GUIDANCE, $msg);
		} else if ($act == 'updateline'){		// 行更新のとき
			// 変更可能値
			$updateName = $request->trimValueOf('item' . $selectedItemNo . '_name');				// 名前
			$updateHasScript = ($request->trimValueOf('item' . $selectedItemNo . '_has_script') == 'on') ? 1 : 0;		// スクリプトがあるかどうか
			$updateHasCss = ($request->trimValueOf('item' . $selectedItemNo . '_has_css') == 'on') ? 1 : 0;		// CSSがあるかどうか
			$updateHasAdmin = ($request->trimValueOf('item' . $selectedItemNo . '_has_admin') == 'on') ? 1 : 0;		// 管理画面があるかどうか
			$updateEnableOperation = ($request->trimValueOf('item' . $selectedItemNo . '_operation') == 'on') ? 1 : 0;		// 単体実行可能かどうか
			
			$ret = $this->db->updateWidget($serial, $updateName, $updateHasScript, $updateHasCss, $updateHasAdmin, $updateEnableOperation, $userInfo->userId);
			if ($ret){		// データ更新成功のとき
				$this->setMsg(self::MSG_GUIDANCE, 'データを更新しました');
			} else {
				$this->setMsg(self::MSG_APP_ERR, 'データ更新に失敗しました');
			}
		} else if ($act == 'deleteline'){		// ウィジェット削除のとき
			// ウィジェットが参照状況をチェック、参照されている場合は削除できない
			if ($this->db->getWidget($serial, $row)){
				// ウィジェットディレクトリ取得
				$widgetId = $row['wd_id'];
				$widgetPath = $gEnvManager->getWidgetsPath() . '/' . $widgetId;
				
				// ウィジェットのアンインストール処理
				$saveWidgetId = $gEnvManager->getCurrentWidgetId();// ウィジェットID保存
				$gEnvManager->setCurrentWidgetId($widgetId);// ウィジェットID一時設定
				$gLaunchManager->goInstallWidget(1);		// アンインストール
				$gEnvManager->setCurrentWidgetId($saveWidgetId);// ウィジェットID戻す
						
				// ディレクトリ削除
				if ((is_dir($widgetPath) && rmDirectory($widgetPath)) || !is_dir($widgetPath)){// 削除成功か、ディレクトリが存在しないとき
					$ret = $this->db->deleteWidget($serial, $userId);
					//if ($ret){		// データ更新成功のとき
						$this->setMsg(self::MSG_GUIDANCE, 'ウィジェットを削除しました');
					//} else {
					//	$this->setMsg(self::MSG_APP_ERR, 'ウィジェット削除に失敗しました');
					//}
				} else {
					$this->setMsg(self::MSG_APP_ERR, 'ウィジェットのディレクトリが削除できませんでした');
				}
			} else {
				$this->setMsg(self::MSG_APP_ERR, '削除対象のウィジェットが見つかりません');
			}
		} else if ($act == 'upload'){		// ファイルアップロードの場合
			$replaceWidget = ($request->trimValueOf('item_replace') == 'on') ? 1 : 0;		// ウィジェットを置き換えるかどうか

			// アップロードされたファイルか？セキュリティチェックする
			if (is_uploaded_file($_FILES['upfile']['tmp_name'])) {
				$uploadFilename = $_FILES['upfile']['name'];		// アップロードされたファイルのファイル名取得
				
				// ファイル名の解析
				$pathParts = pathinfo($uploadFilename);
				$ext = $pathParts['extension'];		// 拡張子
				$widgetName = basename($uploadFilename, '.' . $ext);		// 拡張子をはずす
				
				// ファイル拡張子のチェック
				if ($ext != 'zip'){
					$msg = 'zip圧縮のファイルのみアップロード可能です';
					$this->setAppErrorMsg($msg);
				}
				
				if ($this->getMsgCount() == 0){		// エラーが発生していないとき
					if (!$replaceWidget){		// ウィジェット置き換えないとき
						// 同名のウィジェットがないかチェック
						if ($this->db->getAllWidgetIdList($rows)){
							for ($i = 0; $i < count($rows); $i++){
								if ($widgetName == $rows[$i]['wd_id']) break;
							}
							if ($i < count($rows)){
								$msg = '同名のウィジェットがすでに存在します(ウィジェット名：' . $widgetName . ')';
								$this->setAppErrorMsg($msg);
							}
						}
					}
				}
				if ($this->getMsgCount() == 0){		// エラーが発生していないとき
					// ファイルを保存するサーバディレクトリを指定
					$tmpFile = tempnam(M3_SYSTEM_WORK_DIR_PATH, M3_SYSTEM_WORK_UPLOAD_FILENAME_HEAD);
		
					// アップされたテンポラリファイルを保存ディレクトリにコピー
					$ret = move_uploaded_file($_FILES['upfile']['tmp_name'], $tmpFile);
					if ($ret){
						// 解凍先ディレクトリ
						$extDir = $gEnvManager->getWidgetsPath();
					
						// zipファイルを解凍
						$zipFile = new PclZip($tmpFile);
						if (($zipList = $zipFile->listContent()) == 0){
							$msg = 'zipファイルの内容のリスト取得に失敗しました(要因: ' . $zipFile->errorName(true) . ')';
							$this->setAppErrorMsg($msg);							
						} else {
							// zipファイル名とディレクトリ名が同じであるかチェック
							$dirName = $widgetName . '/';
							if (strncmp($zipList[0]['filename'], $dirName, strlen($dirName)) == 0){
								if ($replaceWidget){		// ウィジェット置き換える場合
									// ディレクトリ削除
									$widgetPath = $gEnvManager->getWidgetsPath() . '/' . $widgetName;
									if ((is_dir($widgetPath) && rmDirectory($widgetPath)) || !is_dir($widgetPath)){// 削除成功か、ディレクトリが存在しないとき
									} else {
										$this->setMsg(self::MSG_APP_ERR, 'ウィジェットのディレクトリが削除できませんでした');
									}
								}
								
								if ($this->getMsgCount() == 0){		// エラーが発生していないとき					
									$ret = $zipFile->extract(PCLZIP_OPT_PATH, $extDir);
									if ($ret){
										$userInfo = $gEnvManager->getCurrentUserInfo();
										$ret = $this->db->addNewWidget($widgetName, $widgetName, $userInfo->userId);
								
										// ウィジェットのインストール処理
										$saveWidgetId = $gEnvManager->getCurrentWidgetId();// ウィジェットID保存
										$gEnvManager->setCurrentWidgetId($widgetName);// ウィジェットID一時設定
										$gLaunchManager->goInstallWidget(0);		// インストール
										$gEnvManager->setCurrentWidgetId($saveWidgetId);// ウィジェットID戻す
									
										// エラーメッセージを取得
										$this->addMsg($gMessageManager->getErrorMessage(), $gMessageManager->getWarningMessage(), $gMessageManager->getGuidanceMessage());
									
										$msg = 'ファイルのアップロードが完了しました(ウィジェット名：' . $widgetName . ')';
										$this->setGuidanceMsg($msg);
										$this->newWidget[] = $widgetName;			// 新規ウィジェットID保存
									} else {
										$msg = 'ファイルのアップロードに失敗しました(要因: ' . $zipFile->errorName(true) . ')';
										$this->setAppErrorMsg($msg);
									}
								}
							} else {
								$msg = 'zipファイルのファイル名とディレクトリ名が異なっているか、全角文字が含まれています';
								$this->setAppErrorMsg($msg);
							}
						}
					} else {
						$msg = 'ファイルのアップロードに失敗しました';
						$this->setAppErrorMsg($msg);
					}
					// テンポラリファイル削除
					unlink($tmpFile);
				}
			} else {
				$msg = 'アップロードファイルが見つかりません(要因：アップロード可能なファイルのMaxサイズを超えている可能性があります - ' . $gSystemManager->getMaxFileSizeForUpload() . 'バイト)';
				$this->setAppErrorMsg($msg);
			}
		} else if ($act == 'download'){		// ファイルダウンロードのとき
			$widgetsDir = $gEnvManager->getWidgetsPath();		// ウィジェットディレクトリ
			$widgetDir = $widgetsDir . '/' . $widgetId;			// ダウンロードするウィジェットのディレクトリ
			$downloadFilename = $widgetId . '.zip';		// ダウンロード時のファイル名
			$tmpFile = tempnam(M3_SYSTEM_WORK_DIR_PATH, M3_SYSTEM_WORK_DOWNLOAD_FILENAME_HEAD);		// zip処理用一時ファイル
			
			// zip圧縮
			$zipFile = new PclZip($tmpFile);
			$ret = $zipFile->create($widgetDir, PCLZIP_OPT_REMOVE_PATH, $widgetsDir);
			if ($ret){
				// ダウンロード処理
				ob_end_clean();
			    header('Content-disposition: attachment; filename=' . $downloadFilename);
			    header('Content-type: application/octet-stream; name=' . $downloadFilename);
			    $fp = fopen($tmpFile, "r");
			    echo fread($fp, filesize($tmpFile));
			    fclose($fp);
				ob_end_flush();
			
				// テンポラリファイル削除
				unlink($tmpFile);
				return;
			} else {
				$msg = 'ファイルのダウンロードに失敗しました(要因: ' . $zipFile->errorName(true) . ')';
				$this->setAppErrorMsg($msg);
				
				// テンポラリファイル削除
				unlink($tmpFile);
			}
		}
		// インストールディレクトリを設定
		$this->tmpl->addVar("_widget", "install_dir", $gEnvManager->getWidgetsPath());
		
		// ウィジェットリストを取得
		$this->db->getAllWidgetList(array($this, 'widgetListLoop'));
	}
	/**
	 * ウィジェットリスト、取得したデータをテンプレートに設定する
	 *
	 * @param int $index			行番号(0～)
	 * @param array $fetchedRow		フェッチ取得した行
	 * @param object $param			未使用
	 * @return bool					true=処理続行の場合、false=処理終了の場合
	 */
	function widgetListLoop($index, $fetchedRow, $param)
	{
		global $gDesignManager;
		
		$hasScript = '';
		if ($fetchedRow['wd_read_scripts']){
			$hasScript = 'checked';
		}
		$hasCss = '';
		if ($fetchedRow['wd_read_css']){
			$hasCss = 'checked';
		}
		$hasAdmin = '';
		if ($fetchedRow['wd_has_admin']){
			$hasAdmin = 'checked';
		}
		$enableOperation = '';			// 単体実行可能かどうか
		if ($fetchedRow['wd_enable_operation']){
			$enableOperation = 'checked';
		}
		
		// 編集不可項目のときは、ボタンを使用不可にする
		$buttonEnabled = '';
		$hasScriptDisabled = '';
		$hasCssDisabled = '';
		$hasAdminDisabled = '';
		$enableOperationDisabled = '';
		if (!$fetchedRow['wd_editable']){
			$buttonEnabled = 'disabled';
			$hasScriptDisabled = 'disabled';
			$hasCssDisabled = 'disabled';
			$hasAdminDisabled = 'disabled';
			$enableOperationDisabled = 'disabled';
		}
		
		// 管理画面がないときは、詳細ボタンを使用不可にする
		$detailButtonEnabled = '';
		if (!$fetchedRow['wd_has_admin']) $detailButtonEnabled = 'disabled';
		
		// 行カラーの設定
		$lineColor = '';
		if ($index % 2 != 0){
			$lineColor = 'class="even"';		// 偶数行
		}
		
		// 新規に追加されたウィジェットかチェック
		$id = $this->convertToDispString($fetchedRow['wd_id']);
		$idText = $id;
		for ($i = 0; $i < count($this->newWidget); $i++){
			if ($this->newWidget[$i] == $id){
				$idText = '<b><font color="green">' . $id . '</font></b>';
				break;
			}
		}
		// ウィジェットの画像を設定
		$image = $gDesignManager->getWidgetIconUrl($id, $this->defaultImageSize);
		$imageTag = '<img class="widget_obj" src="' . $image . '" ';
		$imageTag .= 'width="' . $this->defaultImageSize . '"';
		$imageTag .= ' height="' . $this->defaultImageSize . '"';
		$imageTag .= ' />';
		
		$row = array(
			'line_color' => $lineColor,											// 行のカラー
			'no' => $index + 1,													// 行番号
			'serial' => $this->convertToDispString($fetchedRow['wd_serial']),			// シリアル番号
			'id' => $id,			// ID
			'id_text' => $idText,
			'name' => $this->convertToDispString($fetchedRow['wd_name']),		// 名前
			'version' => $this->convertToDispString($fetchedRow['wd_version']),		// バージョン
			'update_dt' => $this->convertToDispDateTime($fetchedRow['wd_create_dt']),	// 更新日時
			'has_script' => $hasScript,											// スクリプトディレクトリがあるかどうか
			'has_css' => $hasCss,												// CSSディレクトリがあるかどうか
			'has_admin' => $hasAdmin,											// 管理画面があるかどうか
			'operation' => $enableOperation,											// 単体起動可能かどうか
			'has_script_disabled' => $hasScriptDisabled,						// スクリプトディレクトリがあるかどうか、使用制御
			'has_css_disabled' => $hasCssDisabled,								// CSSディレクトリがあるかどうか、使用制御
			'has_admin_disabled' => $hasAdminDisabled,							// 管理画面があるかどうか、使用制御
			'operation_disabled' => $enableOperationDisabled,					// 単体実行可能かどうか、使用制御	
			'update_button' => $buttonEnabled,									// 更新ボタンの使用制御
			'detail_button' => $detailButtonEnabled,							// 詳細ボタンの使用制御
			'image_tag' => $imageTag		// 画像
		);
		$this->tmpl->addVars('widgetlist', $row);
		$this->tmpl->parseTemplate('widgetlist', 'a');
		return true;
	}
}
?>
