source: branches/version-2_5-dev/data/class/pages/admin/system/LC_Page_Admin_System_Bkup.php @ 20363

Revision 20363, 16.6 KB checked in by homan, 11 years ago (diff)

#974 [管理画面]システム設定 バックアップのコミット(仮)
僕の環境でそもそもバックアップがうまく作動しないので、
大河内先生に診てもらうためのコミット・・(’’

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-httpd-php; charset=UTF-8
Line 
1<?php
2/*
3 * This file is part of EC-CUBE
4 *
5 * Copyright(c) 2000-2010 LOCKON CO.,LTD. All Rights Reserved.
6 *
7 * http://www.lockon.co.jp/
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 */
23
24// {{{ requires
25require_once(CLASS_EX_REALDIR . "page_extends/admin/LC_Page_Admin_Ex.php");
26require_once(DATA_REALDIR. "module/Tar.php");
27/**
28 * バックアップ のページクラス.
29 *
30 * @package Page
31 * @author LOCKON CO.,LTD.
32 * @version $Id$
33 */
34class LC_Page_Admin_System_Bkup extends LC_Page_Admin_Ex {
35
36    // }}}
37    // {{{ functions
38
39    /**
40     * Page を初期化する.
41     *
42     * @return void
43     */
44    function init() {
45        parent::init();
46        $this->tpl_mainpage = 'system/bkup.tpl';
47        $this->tpl_subnavi = 'system/subnavi.tpl';
48        $this->tpl_mainno = 'system';
49        $this->tpl_subno = 'bkup';
50        $this->tpl_subtitle = 'バックアップ管理';
51
52        $this->bkup_dir = DATA_REALDIR . "downloads/backup/";
53        $this->bkup_ext = '.tar.gz';
54    }
55
56    /**
57     * Page のプロセス.
58     *
59     * @return void
60     */
61    function process() {
62        $this->action();
63        $this->sendResponse();
64    }
65
66    /**
67     * Page のアクション.
68     *
69     * @return void
70     */
71    function action() {
72        $objQuery =& SC_Query::getSingletonInstance();
73
74
75        $objFormParam = new SC_FormParam;
76
77        // パラメータの初期化
78        $this->initParam($objFormParam, $_POST);
79
80        $arrErr  = array();
81        $arrForm = array();
82
83        switch($this->getMode()) {
84
85        // バックアップを作成する
86        case 'bkup':
87
88            // データ型エラーチェック
89            $arrErr[1] = $objFormParam->checkError();
90
91            // データ型に問題がない場合
92            if(SC_Utils_Ex::isBlank($arrErr[1])) {
93                // データ型以外のエラーチェック
94                $arrErr[2] = $this->lfCheckError($objFormParam->getHashArray());
95            }
96
97            // エラーがなければバックアップ処理を行う
98            if (SC_Utils_Ex::isBlank($arrErr[1]) && SC_Utils_Ex::isBlank($arrErr[2])) {
99           
100                $arrData = $objFormParam->getHashArray();
101           
102                // バックアップファイル作成
103                $arrErr[3] = $this->lfCreateBkupData($arrData['bkup_name'], $this->bkup_dir);
104
105                // DBにデータ更新
106                if (SC_Utils_Ex::isBlank($arrErr[3])) {
107                    $this->lfUpdBkupData($arrData);
108                }else{
109                    $arrForm = $arrData;
110                }
111
112                $this->tpl_onload = "alert('バックアップ完了しました');";
113            }else{
114                $arrForm = $objFormParam->getHashArray();
115            }
116
117            break;
118
119        // リストア
120        case 'restore_config':
121            $this->mode = "restore_config";
122
123        case 'restore':
124            $this->lfRestore($_POST['list_name'], $this->bkup_dir, $this->bkup_ext, $this->mode);
125            break;
126
127        // 削除
128        case 'delete':
129            $del_file = $this->bkup_dir.$_POST['list_name'] . $this->bkup_ext;
130            // ファイルの削除
131            if(is_file($del_file)){
132                $ret = unlink($del_file);
133            }
134
135            // DBから削除
136            $delsql = "DELETE FROM dtb_bkup WHERE bkup_name = ?";
137            $objQuery->query($delsql, array($_POST['list_name']));
138
139            break;
140
141            // ダウンロード
142        case 'download' :
143            $filename = $_POST['list_name'] . $this->bkup_ext;
144            $dl_file = $this->bkup_dir.$_POST['list_name'] . $this->bkup_ext;
145
146            // ダウンロード開始
147            Header("Content-disposition: attachment; filename=${filename}");
148            Header("Content-type: application/octet-stream; name=${filename}");
149            header("Content-Length: " .filesize($dl_file));
150            readfile ($dl_file);
151            exit();
152            break;
153
154        default:
155            break;
156        }
157
158        // バックアップリストを取得する
159        $arrBkupList = $this->lfGetBkupData("ORDER BY create_date DESC");
160        // テンプレートファイルに渡すデータをセット
161        $this->arrErr = isset($arrErr) ? $arrErr : array();
162        $this->arrForm = isset($arrForm) ? $arrForm : array();
163        $this->arrBkupList = $arrBkupList;
164    }
165
166    /**
167     * デストラクタ.
168     *
169     * @return void
170     */
171    function destroy() {
172        parent::destroy();
173    }
174
175
176    /**
177     * パラメータ初期化.
178     *
179     * @param object $objFormParam
180     * @param array  $arrParams  $_POST値
181     * @return void
182     */
183    function initParam(&$objFormParam, &$arrParams) {
184
185        $objFormParam->addParam('バックアップ名', 'bkup_name', STEXT_LEN, 'a', array('EXIST_CHECK', 'MAX_LENGTH_CHECK', 'NO_SPTAB', 'ALNUM_CHECK'));
186        $objFormParam->addParam('バックアップメモ', 'bkup_memo', MTEXT_LEN, 'KVa', array('MAX_LENGTH_CHECK'));
187        $objFormParam->setParam($arrParams);
188        $objFormParam->convParam();
189
190    }
191
192    /**
193     * データ型以外のエラーチェック.
194     *
195     * @param array $arrForm
196     * @return $arrErr
197     */
198    function lfCheckError(&$arrForm){
199
200        // 重複チェック
201        $ret = $this->lfGetBkupData("WHERE bkup_name = ?", array($arrForm['bkup_name']));
202        if (count($ret) > 0) {
203            $arrErr['bkup_name'] = "バックアップ名が重複しています。別名を入力してください。";
204        }
205
206        return $arrErr;
207    }
208
209    /**
210     * バックアップファイル作成.
211     *
212     * @param string $bkup_name
213     * @return array $arrErr
214     */
215    function lfCreateBkupData($bkup_name, $bkup_dir){
216        // 実行時間を制限しない
217        set_time_limit(0);
218
219        $objQuery =& SC_Query::getSingletonInstance();
220        $csv_data = "";
221        $csv_autoinc = "";
222        $arrData = array();
223        $success = true;
224
225        if (!is_dir(dirname($bkup_dir))) $success = mkdir(dirname($bkup_dir));
226        $bkup_dir = $bkup_dir . $bkup_name . "/";
227
228        // 全テーブル取得
229        $arrTableList = $objQuery->listTables();
230
231        // 各テーブル情報を取得する
232        foreach($arrTableList as $key => $val){
233
234            if (!($val == "dtb_bkup" || $val == "mtb_zip")) {
235
236                // 全データを取得
237                if ($val == "dtb_pagelayout"){
238                    $arrData = $objQuery->getAll("SELECT * FROM $val ORDER BY page_id");
239                }else{
240                    $arrData = $objQuery->getAll("SELECT * FROM $val");
241                }
242
243                // CSVデータ生成
244                if (count($arrData) > 0) {
245
246                    // カラムをCSV形式に整える
247                    $arrKyes = SC_Utils_Ex::sfGetCommaList(array_keys($arrData[0]), false);
248
249                    // データをCSV形式に整える
250                    $data = "";
251                    foreach($arrData as $data_key => $data_val){
252                        $data .= $this->lfGetCSVList($arrData[$data_key]);
253                    }
254                    // CSV出力データ生成
255                    $csv_data .= $val . "\r\n";
256                    $csv_data .= $arrKyes . "\r\n";
257                    $csv_data .= $data . "\r\n";
258                }
259
260                // タイムアウトを防ぐ
261                SC_Utils_Ex::sfFlush();
262            }
263        }
264
265        // 自動採番型の構成を取得する
266        $csv_autoinc = $this->lfGetAutoIncrement();
267
268        $csv_file = $bkup_dir . "bkup_data.csv";
269        $csv_autoinc_file = $bkup_dir . "autoinc_data.csv";
270        mb_internal_encoding(CHAR_CODE);
271        // CSV出力
272        // ディレクトリが存在していなければ作成する
273        if (!is_dir(dirname($csv_file))) {
274            $success = mkdir(dirname($csv_file));
275        }
276        if ($success) {
277            // dataをCSV出力
278            $fp = fopen($csv_file,"w");
279            if($fp) {
280                if($csv_data != ""){
281                    $success = fwrite($fp, $csv_data);
282                }
283                fclose($fp);
284            }
285
286            // 自動採番をCSV出力
287            $fp = fopen($csv_autoinc_file,"w");
288            if($fp) {
289                if($csv_autoinc != ""){
290                    $success = fwrite($fp, $csv_autoinc);
291                }
292                fclose($fp);
293            }
294        }
295
296        if ($success) {
297            //圧縮フラグTRUEはgzip圧縮をおこなう
298            $tar = new Archive_Tar($this->bkup_dir . $bkup_name . $this->bkup_ext, TRUE);
299
300            //bkupフォルダに移動する
301            chdir($this->bkup_dir);
302
303            //圧縮をおこなう
304            $zip = $tar->create("./" . $bkup_name . "/");
305
306            // バックアップデータの削除
307            if ($zip) SC_Utils_Ex::sfDelFile($bkup_dir);
308        }
309
310        if (!$success) {
311            $arrErr['bkup_name'] = "バックアップに失敗しました。";
312            // バックアップデータの削除
313            SC_Utils_Ex::sfDelFile($bkup_dir);
314        }
315
316        return isset($arrErr) ? $arrErr : array();
317    }
318
319    /* 配列の要素をCSVフォーマットで出力する。*/
320    function lfGetCSVList($array) {
321        $line = '';
322        if (count($array) > 0) {
323            foreach($array as $key => $val) {
324                $val = mb_convert_encoding($val, CHAR_CODE, CHAR_CODE);
325                $val = str_replace("\"", "\\\"", $val);
326                $line .= "\"".$val."\",";
327            }
328            $line = ereg_replace(",$", "\r\n", $line);
329        }else{
330            return false;
331        }
332        return $line;
333    }
334
335    /**
336     * シーケンス一覧をCSV出力形式に変換する.
337     *
338     * シーケンス名,シーケンス値 の形式に出力する.
339     *
340     * @return string シーケンス一覧の文字列
341     * @return string $ret
342     */
343    function lfGetAutoIncrement() {
344        $objQuery =& SC_Query::getSingletonInstance();
345        $arrSequences = $objQuery->listSequences();
346
347        foreach($arrSequences as $val){
348            $seq = $objQuery->currVal($val);
349
350            $ret .= $val . ",";
351            $ret .= is_null($seq) ? "0" : $seq;
352            $ret .= "\r\n";
353        }
354        return $ret;
355    }
356
357    // バックアップテーブルにデータを更新する
358    function lfUpdBkupData($data){
359        $objQuery =& SC_Query::getSingletonInstance();
360
361        $sql = "INSERT INTO dtb_bkup (bkup_name,bkup_memo,create_date) values (?,?,now())";
362        $objQuery->query($sql, array($data['bkup_name'],$data['bkup_memo']));
363    }
364
365    // バックアップテーブルからデータを取得する
366    function lfGetBkupData($where = "", $data = array()){
367        $objQuery =& SC_Query::getSingletonInstance();
368
369        $sql = "SELECT bkup_name, bkup_memo, create_date FROM dtb_bkup ";
370        if ($where != "")   $sql .= $where;
371
372        $ret = $objQuery->getAll($sql,$data);
373
374        return $ret;
375    }
376
377    /**
378     * バックアップファイルをリストアする
379     *
380     * @param string $bkup_name
381     * @param string $bkup_dir
382     * @param string $bkup_ext
383     * @return void
384     */
385    function lfRestore($bkup_name, $bkup_dir, $bkup_ext, $mode){
386        // 実行時間を制限しない
387        set_time_limit(0);
388
389        $objQuery =& SC_Query::getSingletonInstance();
390        $csv_data = "";
391        $success = true;
392
393        $bkup_dir = $bkup_dir . $bkup_name . "/";
394
395        //バックアップフォルダに移動する
396        chdir($bkup_dir);
397
398        //圧縮フラグTRUEはgzip解凍をおこなう
399        $tar = new Archive_Tar($bkup_name . $bkup_ext, TRUE);
400
401        //指定されたフォルダ内に解凍する
402        $success = $tar->extract("./");
403
404        // 無事解凍できれば、リストアを行う
405        if ($success) {
406
407            // トランザクション開始
408            $objQuery->begin();
409
410            // DBをクリア
411            $success = $this->lfDeleteAll($objQuery);
412
413            // INSERT実行
414            if ($success) $success = $this->lfExeInsertSQL($objQuery, $bkup_dir . "bkup_data.csv", $mode);
415
416            // 自動採番の値をセット
417            if ($success) $this->lfSetAutoInc($objQuery, $bkup_dir . "autoinc_data.csv");
418
419            // リストア成功ならコミット失敗ならロールバック
420            if ($success) {
421                $objQuery->commit();
422                $this->restore_msg = "リストア終了しました。";
423                $this->restore_err = true;
424            }else{
425                $objQuery->rollback();
426                $this->restore_msg = "リストアに失敗しました。";
427                $this->restore_name = $bkup_name;
428                $this->restore_err = false;
429            }
430        }
431    }
432
433    /**
434     * CSVファイルからインサート実行.
435     *
436     * @param object $objQuery
437     * @param string $csv
438     * @param string $mode
439     * @return void
440     */
441    function lfExeInsertSQL(&$objQuery, $csv, $mode){
442
443        $sql = "";
444        $base_sql = "";
445        $tbl_flg = false;
446        $col_flg = false;
447        $ret = true;
448        $pagelayout_flg = false;
449
450        // csvファイルからデータの取得
451        $fp = fopen($csv, "r");
452        while (!feof($fp)) {
453            $data = fgetcsv($fp, 1000000);
454
455            //空白行のときはテーブル変更
456            if (count($data) <= 1 and $data[0] == "") {
457                $base_sql = "";
458                $tbl_flg = false;
459                $col_flg = false;
460                continue;
461            }
462
463            // テーブルフラグがたっていない場合にはテーブル名セット
464            if (!$tbl_flg) {
465                $base_sql = "INSERT INTO $data[0] ";
466                $tbl_flg = true;
467
468                if($data[0] == "dtb_pagelayout"){
469                    $pagelayout_flg = true;
470                }
471
472                continue;
473            }
474
475            // カラムフラグがたっていない場合にはカラムセット
476            if (!$col_flg) {
477                if ($mode != "restore_config"){
478                    $base_sql .= " ( $data[0] ";
479                    for($i = 1; $i < count($data); $i++){
480                        $base_sql .= "," . $data[$i];
481                    }
482                    $base_sql .= " ) ";
483                }
484                $col_flg = true;
485                continue;
486            }
487
488            // インサートする値をセット
489            $sql = $base_sql . "VALUES ( ? ";
490            for($i = 1; $i < count($data); $i++){
491                $sql .= ", ?";
492            }
493            $sql .= " );";
494            $data = str_replace("\\\"", "\"", $data);
495            $err = $objQuery->query($sql, $data);
496
497            // エラーがあれば終了
498            if (PEAR::isError($err)){
499                SC_Utils_Ex::sfErrorHeader(">> " . $objQuery->getlastquery(false));
500                return false;
501            }
502
503            if ($pagelayout_flg) {
504                // dtb_pagelayoutの場合には最初のデータはpage_id = 0にする
505                $arrVal['page_id'] = '0';
506                $objQuery->update("dtb_pagelayout", $arrVal);
507                $pagelayout_flg = false;
508            }
509
510            // タイムアウトを防ぐ
511            SC_Utils_Ex::sfFlush();
512        }
513        fclose($fp);
514
515        return $ret;
516    }
517
518    // 自動採番をセット
519    function lfSetAutoInc(&$objQuery, $csv){
520        // csvファイルからデータの取得
521        $arrCsvData = file($csv);
522
523        foreach($arrCsvData as $val){
524            $arrData = split(",", trim($val));
525
526             $objQuery->setval($arrData[0], $arrData[1]);
527        }
528    }
529
530    // DBを全てクリアする
531    function lfDeleteAll(&$objQuery){
532        $ret = true;
533
534        $arrTableList = $objQuery->listTables();
535
536        foreach($arrTableList as $val){
537            // バックアップテーブルは削除しない
538            if ($val != "dtb_bkup") {
539                $ret = $objQuery->delete($val);
540                if (PEAR::isError($ret)) return false;
541            }
542        }
543        return true;
544    }
545}
546?>
Note: See TracBrowser for help on using the repository browser.