<?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-2009 Magic3 Project.
 * @license    http://www.gnu.org/copyleft/gpl.html  GPL License
 * @version    SVN: $Id: admin_ec_mainProductcsvWidgetContainer.php 1709 2009-04-06 03:10:13Z fishbone $
 * @link       http://www.magic3.org
 */
require_once($gEnvManager->getCurrentWidgetContainerPath() . '/admin_ec_mainBaseWidgetContainer.php');
require_once($gEnvManager->getCurrentWidgetDbPath() .	'/productDb.php');

class admin_ec_mainProductcsvWidgetContainer extends admin_ec_mainBaseWidgetContainer
{
	private $db;	// DB接続オブジェクト
	private $langId;			// 言語
	private $currency;			// 通貨
	private $taxType;			// 税種別
	private $ecObj;			// 共通ECオブジェクト
	private $csvData;		// CSV作成用
	const STANDARD_PRICE = 'selling';		// 通常価格
	const PRODUCT_IMAGE_MEDIUM = 'standard-product';		// 中サイズ商品画像ID
	const PRODUCT_IMAGE_SMALL = 'small-product';		// 小サイズ商品画像ID
	const PRODUCT_IMAGE_LARGE = 'large-product';		// 大サイズ商品画像ID
	const PRODUCT_STATUS_NEW = 'new';		// 商品ステータス新規
	const PRODUCT_STATUS_SUGGEST = 'suggest';		// 商品ステータスおすすめ
	const DEFAULT_TAX_TYPE = 'sales';			// デフォルト税種別
	const PRICE_OBJ_ID = "eclib";		// 価格計算オブジェクトID
	const CSV_FILE_HEAD = 'product_';		// CSVファイル名
	const CATEGORY_COUNT = 2;				// 商品カテゴリーの選択可能数
		
	/**
	 * コンストラクタ
	 */
	function __construct()
	{
		// 親クラスを呼び出す
		parent::__construct();
		
		// DBオブジェクト作成
		$this->db = new productDb();
		
		// EC用共通オブジェクト取得
		$this->ecObj = $this->gInstance->getObject(self::PRICE_OBJ_ID);
		$this->ecObj->initByDefault();		// デフォルト値で初期化
	}
	/**
	 * テンプレートファイルを設定
	 *
	 * _assign()でデータを埋め込むテンプレートファイルのファイル名を返す。
	 * 読み込むディレクトリは、「自ウィジェットディレクトリ/include/template」に固定。
	 *
	 * @param RequestManager $request		HTTPリクエスト処理クラス
	 * @param object         $param			任意使用パラメータ。そのまま_assign()に渡る
	 * @return string 						テンプレートファイル名。テンプレートライブラリを使用しない場合は空文字列「''」を返す。
	 */
	function _setTemplate($request, &$param)
	{
		return 'admin_product_csv.tmpl.html';
	}
	/**
	 * テンプレートにデータ埋め込む
	 *
	 * _setTemplate()で指定したテンプレートファイルにデータを埋め込む。
	 *
	 * @param RequestManager $request		HTTPリクエスト処理クラス
	 * @param object         $param			任意使用パラメータ。_setTemplate()と共有。
	 * @param								なし
	 */
	function _assign($request, &$param)
	{
		// ユーザ情報、表示言語
		$userId		= $this->gEnv->getCurrentUserId();
		$defaultLang	= $this->gEnv->getDefaultLanguage();
		$defaultLangName = $this->gEnv->getDefaultLanguageNameByCurrentLanguage();// デフォルト言語の現在の表示名を取得
		$this->langId = $defaultLang;		// 言語
		$this->currency	= $this->ecObj->getDefaultCurrency();		// 通貨
		$this->taxType	= self::DEFAULT_TAX_TYPE;		// 税種別
		
		$act = $request->trimValueOf('act');
		if ($act == 'upload'){		// CSVアップロード
			if (is_uploaded_file($_FILES['upfile']['tmp_name'])) {
				$uploadFilename = $_FILES['upfile']['name'];		// アップロードされたファイルのファイル名取得
				
				// ファイルを保存するサーバディレクトリを指定
				$tmpFile = tempnam($this->gEnv->getWorkDirPath(), M3_SYSTEM_WORK_UPLOAD_FILENAME_HEAD);

				// アップされたテンポラリファイルを保存ディレクトリにコピー
				$ret = move_uploaded_file($_FILES['upfile']['tmp_name'], $tmpFile);
				if ($ret){
					$addCount = 0;		// 追加項目数
					$updateCount = 0;	// 更新商品数
					$colCount = 0;		// カラム数

					// トランザクションスタート
					$this->db->startTransaction();
					
					// ファイルオープン
					$fp = fopen($tmpFile, "r");
					
					// データ読み込み
					$delimType = 0;
					if ($this->gEnv->getDefaultCsvDelimCode() == "\t") $delimType = 1;		// タブ区切り
					while (($data = fgetByCsv($fp, $delimType)) !== false){
						if ($colCount == 0) $colCount = count($data);		// カラム数
						
						// ヘッダ読み飛ばし
						if (trim($data[0]) == '商品コード') continue;
						if ($colCount != count($data)) continue;		// カラム数が合わない行も読み飛ばす
						
						// データをDBに格納する
						$code		= trim($data[0]);	// 商品コード
						$name		= trim($data[1]);	// 商品名
//						$unitTypeId = $this->db->getUnitTypeIdByName($defaultLang, trim($data[2]));	// 販売単位
						$price		= trim($data[2]);	// 販売価格(税抜)
						$priceWithTax		= trim($data[3]);	// 販売価格(税込)
//						$taxType	= $this->db->getTaxTypeIdByName($defaultLang, trim($data[5]));		// 税種別
						$description_short	= trim($data[4]);	// 簡易説明
						//$categoryId			= trim($data[7]);	// 商品カテゴリーID
						
						// 価格の計算、税抜価格を優先する
						if (empty($price)){
							// 税込価格から税抜価格を求める
							if (empty($priceWithTax)){
								$price = 0;
							} else {
								$rate = $this->ecObj->getTaxRate(self::DEFAULT_TAX_TYPE, $this->langId);
								if ($rate > 0) $price = $priceWithTax / (1 + $rate / 100);
							}
						}
						$price = $this->ecObj->getCurrencyPrice($price);	// 端数調整
						
						// その他の値
						$index = 0;
						$visible = 1;
						$new		= 0;		// 新規かどうか
						$suggest	= 0;		// お勧めかどうか
						$unitTypeId = '';	// 販売単位
						$unitQuantity = 1;		// 単位数量
						$stockCount = 0;		// 表示在庫数
						$taxType = self::DEFAULT_TAX_TYPE;			// 税種別
						$description = '';
						$keyword = '';
						$url = '';
						$adminNote = '';
						$delivType = '';		// 配送タイプ
						$delivPrice = 0;		// 配送単価
						$delivWeight = 0;		// 配送基準重量
						
						// データのエラーチェック
						// エラーなしの場合は、データを登録
						if ($this->getMsgCount() == 0){
							// 商品コードを見て、新規登録か更新かを判断
							$updateRecord = false;
							if ($this->db->isExistsProductCode($code)) $updateRecord = true;
							
							if ($updateRecord){		// 既存項目の更新のとき
								// 登録済み商品を取得
								$ret = $this->db->getProductByProductCode($code, $this->langId, $row, $row2, $row3, $row4, $row5);
								if ($ret){
									// 取得値を設定
									$serialNo = $row['pt_serial'];		// シリアル番号
									if (empty($name)) $name = $row['pt_name'];		// 名前
									
									$index = $row['pt_sort_order'];	// 表示順
									$visible = $row['pt_visible'];	// 表示状態
									$unitTypeId = $row['pt_unit_type_id'];	// 単位
									$unitQuantity = $row['pt_unit_quantity'];		// 数量
									$stockCount	= $row['pe_stock_count'];		// 表示在庫数
									if (empty($stockCount)) $stockCount = 0;
									$description = $row['pt_description'];			// 説明
									//$description_short = $row['pt_description_short'];		// 簡易説明
									$keyword = $row['pt_search_keyword'];					// 検索キーワード
									$url = $row['pt_site_url'];							// 詳細情報URL
									$taxType = $row['pt_tax_type_id'];					// 税種別
									$adminNote = $row['pt_admin_note'];		// 管理者用備考
									$delivType = $row['pt_deliv_type'];		// 配送タイプ
									$delivPrice = $row['pt_deliv_fee'];		// 配送単価
									$delivWeight = $row['pt_weight'];		// 配送基準重量
						
									// 通貨を取得
									$priceArray = $this->getPrice($row2, self::STANDARD_PRICE);
									$currency = $priceArray['pp_currency_id'];	// 通貨
				
									// 画像を取得
									$imageArray = $this->getImage($row3, self::PRODUCT_IMAGE_SMALL);// 商品画像小
									$imageUrl_s = $imageArray['im_url'];	// URL
									$imageArray = $this->getImage($row3, self::PRODUCT_IMAGE_MEDIUM);// 商品画像中
									$imageUrl_m = $imageArray['im_url'];	// URL
									$imageArray = $this->getImage($row3, self::PRODUCT_IMAGE_LARGE);// 商品画像大
									$imageUrl_l = $imageArray['im_url'];	// URL

									// 商品ステータスを取得
									$statusArray = $this->getStatus($row4, self::PRODUCT_STATUS_NEW);// 新規
									$new = $statusArray['ps_value'];
									$statusArray = $this->getStatus($row4, self::PRODUCT_STATUS_SUGGEST);// おすすめ
									$suggest = $statusArray['ps_value'];
									
									// ##### 格納値を作成 #####
									// 商品情報その他
									$otherParams = array();
									$otherParams['pt_name'] = $name;			// 商品名
									$otherParams['pt_code'] = $code;			// 商品コード
									$otherParams['pt_sort_order'] = $index;			// 表示順
									$otherParams['pt_visible'] = $visible;		// 表示するかどうか
									$otherParams['pt_product_type'] = 1;				// 商品種別(1=単品商品、2=セット商品、3=オプション商品)
									$otherParams['pt_unit_type_id'] = $unitTypeId;	// 選択単位
									$otherParams['pt_unit_quantity'] = $unitQuantity;		// 数量
									$otherParams['pt_description'] = $description;		// 説明
									$otherParams['pt_description_short'] = $description_short;	// 簡易説明
									$otherParams['pt_search_keyword'] = $keyword;		// 検索キーワード
									$otherParams['pt_site_url'] = $url;			// 詳細情報URL
									$otherParams['pt_tax_type_id'] = $taxType;	// 税種別
									$otherParams['pt_admin_note'] = $adminNote;		// 管理者用備考
									$otherParams['pt_deliv_type'] = $delivType;		// 配送タイプ
									$otherParams['pt_deliv_fee'] = $delivPrice;		// 配送単価
									$otherParams['pt_weight'] = $delivWeight;		// 配送基準重量
								
									// 価格情報の作成
									$priceArray = array();
									$startDt = $this->gEnv->getInitValueOfTimestamp();
									$endDt = $this->gEnv->getInitValueOfTimestamp();
									$priceArray[] = array(self::STANDARD_PRICE, $currency, $price, $startDt, $endDt);		// 単品商品で追加
				
									// 画像情報の作成
									$imageArray = array();
									if (!empty($imageUrl_s)) $imageArray[] = array(self::PRODUCT_IMAGE_SMALL, '', $imageUrl_s);		// 商品画像小追加
									if (!empty($imageUrl_m)) $imageArray[] = array(self::PRODUCT_IMAGE_MEDIUM, '', $imageUrl_m);		// 商品画像中追加
									if (!empty($imageUrl_l)) $imageArray[] = array(self::PRODUCT_IMAGE_LARGE, '', $imageUrl_l);		// 商品画像大追加
				
									// 商品ステータス情報の作成
									$statusArray = array();
									$statusArray[] = array(self::PRODUCT_STATUS_NEW, $new);		// 新着
									$statusArray[] = array(self::PRODUCT_STATUS_SUGGEST, $suggest);		// おすすめ
									
									// 商品カテゴリーの作成
									$categoryArray = $this->getCategory($row5);
									$ret = $this->db->updateProduct($serialNo, $row['pt_id'], $this->langId, $otherParams, 
																	$stockCount, $priceArray, $imageArray, $statusArray, $categoryArray, $newSerial);
									if ($ret) $updateCount++;	// 更新商品数
								} else {		// 該当の商品が存在しないとき
									$msg = 'この商品コードの商品が見つかりません(' . $code . ')';
									$this->setAppErrorMsg($msg);
								}
							} else {			// 新規商品の追加のとき
								// ##### 格納値を作成 #####
								// 商品情報その他
								$otherParams = array();
								$otherParams['pt_name'] = $name;			// 商品名
								$otherParams['pt_code'] = $code;			// 商品コード
								$otherParams['pt_sort_order'] = $index;			// 表示順
								$otherParams['pt_visible'] = $visible;		// 表示するかどうか
								$otherParams['pt_product_type'] = 1;				// 商品種別(1=単品商品、2=セット商品、3=オプション商品)
								$otherParams['pt_unit_type_id'] = $unitTypeId;	// 選択単位
								$otherParams['pt_unit_quantity'] = $unitQuantity;		// 数量
								$otherParams['pt_description'] = $description;		// 説明
								$otherParams['pt_description_short'] = $description_short;	// 簡易説明
								$otherParams['pt_search_keyword'] = $keyword;		// 検索キーワード
								$otherParams['pt_site_url'] = $url;			// 詳細情報URL
								$otherParams['pt_tax_type_id'] = $taxType;	// 税種別
								$otherParams['pt_admin_note'] = $adminNote;		// 管理者用備考
								$otherParams['pt_deliv_type'] = $delivType;		// 配送タイプ
								$otherParams['pt_deliv_fee'] = $delivPrice;		// 配送単価
								$otherParams['pt_weight'] = $delivWeight;		// 配送基準重量
				
								// 価格情報の作成
								$priceArray = array();
								$startDt = $this->gEnv->getInitValueOfTimestamp();
								$endDt = $this->gEnv->getInitValueOfTimestamp();
								$priceArray[] = array(self::STANDARD_PRICE, $this->currency, $price, $startDt, $endDt);		// 単品商品で追加
				
								// 画像情報の作成
								$imageArray = array();
								//if (!empty($imageUrl_s)) $imageArray[] = array(self::PRODUCT_IMAGE_SMALL, '', $imageUrl_s);		// 商品画像小追加
								//if (!empty($imageUrl_m)) $imageArray[] = array(self::PRODUCT_IMAGE_MEDIUM, '', $imageUrl_m);		// 商品画像中追加
								//if (!empty($imageUrl_l)) $imageArray[] = array(self::PRODUCT_IMAGE_LARGE, '', $imageUrl_l);		// 商品画像大追加
								
								// 商品ステータス情報の作成
								$statusArray = array();
								$statusArray[] = array(self::PRODUCT_STATUS_NEW, $new);		// 新着
								$statusArray[] = array(self::PRODUCT_STATUS_SUGGEST, $suggest);		// おすすめ
								
								// 商品カテゴリーの作成
								$categoryArray = array();
								$ret = $this->db->updateProduct(0/*新規追加*/, 0/*商品ID新規作成*/, $this->langId, $otherParams, 
																$stockCount, $priceArray, $imageArray, $statusArray, $categoryArray, $newSerial);
								if ($ret) $addCount++;
							}
						}
					}
					// ファイルを閉じる
					fclose($fp);
					
					// トランザクション終了
					$ret = $this->db->endTransaction();
					if ($ret && $this->getMsgCount() == 0){
						$this->setGuidanceMsg('データを' . $addCount . '件追加しました');
						$this->setGuidanceMsg('データを' . $updateCount . '件更新しました');
					} else {
						$this->setAppErrorMsg('データ追加に失敗しました');
					}
				}
				// テンポラリファイル削除
				unlink($tmpFile);
			} else {
				$msg = 'アップロードファイルが見つかりません(要因：アップロード可能なファイルのMaxサイズを超えている可能性があります - ' . $gSystemManager->getMaxFileSizeForUpload() . 'バイト)';
				$this->setAppErrorMsg($msg);
			}
		} else if ($act == 'download'){		// CSVダウンロード
			// ダウンロード時のデフォルトファイル名
			$down_file = self::CSV_FILE_HEAD . date("YmdHi") . $this->gEnv->getDefaultCsvFileSuffix();
			
			// ヘッダ部を作成
			$buf = array();
			$buf[] = '商品コード';
			$buf[] = '商品名';
//			$buf[] = '販売単位';
			$buf[] = '販売価格(税抜)';
			$buf[] = '販売価格(税込)';
//			$buf[] = '税種別';
			$buf[] = '簡易説明';
			//$buf[] = '商品カテゴリーID';
			$delim = $this->gEnv->getDefaultCsvDelimCode();		// CSV区切りコードを取得
			$this->csvData[] = implode($delim, $buf) . $this->gEnv->getDefaultCsvNLCode();
		
			// 商品リストを取得
			$this->db->getAllProduct(array($this, 'productCsvListLoop'));
			
			// CSVの出力
			ob_end_clean();
			header ("Content-Type: application/force-download");
			header ("Content-Disposition: attachment; filename=" . $down_file);
			header ("Content-Description: File Transfer");
			header ("Content-Length: " . strlen(join("", $this->csvData)));
			foreach ($this->csvData as $mval) {
			    echo mb_convert_encoding($mval, 'SJIS-win');
			    flush();
			    ob_flush();
			    usleep(10000);
			}
			ob_end_flush();
			exit();		// スクリプト終了
		}
		// パスの設定
		$this->tmpl->addVar("_widget", "root_url", $this->gEnv->getRootUrl());
	}
	/**
	 * 取得したデータをCSV形式で出力する
	 *
	 * @param int $index			行番号(0～)
	 * @param array $fetchedRow		フェッチ取得した行
	 * @param object $param			未使用
	 * @return bool					true=処理続行の場合、false=処理終了の場合
	 */
	function productCsvListLoop($index, $fetchedRow, $param)
	{
		// 価格取得
		$ret = $this->db->getProductBySerial($fetchedRow['pt_serial'], $row, $row2, $row3, $row4, $row5);
		if ($ret){
			// 価格を取得
			$priceArray = $this->getPrice($row2, self::STANDARD_PRICE);
			$price = $this->ecObj->getCurrencyPrice($priceArray['pp_price']);	// 価格
			$currency = $priceArray['pp_currency_id'];	// 通貨
			$taxType = $row['pt_tax_type_id'];					// 税種別			

			// 価格作成
			$this->ecObj->setCurrencyType($currency, $this->langId);		// 通貨設定
			$this->ecObj->setTaxType($taxType, $this->langId);		// 税種別設定
			$priceWithTax = $this->ecObj->getCurrencyPrice($this->ecObj->getPriceWithTax($price, $dispPrice));	// 税込み価格取得
		}
					
		$buf = array();
		$delim = $this->gEnv->getDefaultCsvDelimCode();		// CSV区切りコードを取得
		if ($delim == "\t"){	// タブ区切りのCSVフォーマットのとき
			$buf[] = $fetchedRow['pt_code'];			// 商品コード
			$buf[] = $fetchedRow['pt_name'];			// 商品名
//			$buf[] = $fetchedRow['ut_name'];			// 販売単位
			$buf[] = $price;							// 販売価格(税抜)
			$buf[] = $priceWithTax;							// 販売価格(税込)
//			$buf[] = $fetchedRow['tt_name'];				// 税種別
			$buf[] = $fetchedRow['pt_description_short'];	// 簡易説明
			//$buf[] = $fetchedRow['pt_category_id'];			// 商品カテゴリーID
		} else {
			$buf[] = $this->convertToEscapedCsv($fetchedRow['pt_code']);			// 商品コード
			$buf[] = $this->convertToEscapedCsv($fetchedRow['pt_name']);			// 商品名
//			$buf[] = $this->convertToEscapedCsv($fetchedRow['ut_name']);			// 販売単位
			$buf[] = $this->convertToEscapedCsv($price);							// 販売価格(税抜)
			$buf[] = $this->convertToEscapedCsv($priceWithTax);							// 販売価格(税込)
//			$buf[] = $this->convertToEscapedCsv($fetchedRow['tt_name']);				// 税種別
			$buf[] = $this->convertToEscapedCsv($fetchedRow['pt_description_short']);	// 簡易説明
			//$buf[] = $this->convertToEscapedCsv($fetchedRow['pt_category_id']);			// 商品カテゴリーID
		}
		$this->csvData[] = implode($delim, $buf) . $this->gEnv->getDefaultCsvNLCode();
		return true;
	}
	/**
	 * 価格取得
	 *
	 * @param array  	$srcRows			価格リスト
	 * @param string	$priceType			価格のタイプ
	 * @return array						取得した価格行
	 */
	function getPrice($srcRows, $priceType)
	{
		for ($i = 0; $i < count($srcRows); $i++){
			if ($srcRows[$i]['pp_price_type_id'] == $priceType){
				return $srcRows[$i];
			}
		}
		return array();
	}
	/**
	 * 画像取得
	 *
	 * @param array  	$srcRows			画像リスト
	 * @param string	$imageType			画像タイプ
	 * @return array						取得した行
	 */
	function getImage($srcRows, $sizeType)
	{
		for ($i = 0; $i < count($srcRows); $i++){
			if ($srcRows[$i]['im_size_id'] == $sizeType){
				return $srcRows[$i];
			}
		}
		return array();
	}
	/**
	 * 商品ステータス取得
	 *
	 * @param array  	$srcRows			取得行
	 * @param string	$type			商品ステータスタイプ
	 * @return array						取得した行
	 */
	function getStatus($srcRows, $type)
	{
		for ($i = 0; $i < count($srcRows); $i++){
			if ($srcRows[$i]['ps_type'] == $type){
				return $srcRows[$i];
			}
		}
		return array();
	}
	/**
	 * 商品カテゴリー取得
	 *
	 * @param array  	$srcRows			取得行
	 * @return array						取得した行
	 */
	function getCategory($srcRows)
	{
		$destArray = array();
		$itemCount = 0;
		for ($i = 0; $i < count($srcRows); $i++){
			if (!empty($srcRows[$i]['pw_category_id'])){
				$destArray[] = $srcRows[$i]['pw_category_id'];
			}
		}
		return $destArray;
	}
}
?>
