source: branches/comu-ver2/data/class/pages/admin/system/LC_Page_Admin_System_Bkup.php @ 17879

Revision 17879, 22.5 KB checked in by Seasoft, 15 years ago (diff)

・SC_Utils::sfFlush() が出力バッファを破棄している不具合を改善。
・SC_Utils::sfFlush() で行っていた実行時間を制限解除は、呼び出しもとのメソッドで一度のみ行うように変更。

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id Revision Date
  • Property svn:mime-type set to text/x-httpd-php
Line 
1<?php
2/*
3 * This file is part of EC-CUBE
4 *
5 * Copyright(c) 2000-2007 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_PATH . "pages/LC_Page.php");
26require_once(DATA_PATH. "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 {
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_PATH . "downloads/backup/";
53
54    }
55
56    /**
57     * Page のプロセス.
58     *
59     * @return void
60     */
61    function process() {
62        $objView = new SC_AdminView();
63        $objQuery = new SC_Query();
64
65        // セッションクラス
66        $objSess = new SC_Session();
67        // 認証可否の判定
68        SC_Utils_Ex::sfIsSuccess($objSess);
69
70        // バックアップテーブルがなければ作成する
71        $this->lfCreateBkupTable();
72
73        if (!isset($_POST['mode'])) $_POST['mode'] = "";
74
75        switch($_POST['mode']) {
76            // バックアップを作成する
77        case 'bkup':
78            // 入力文字列の変換
79            $arrData = $this->lfConvertParam($_POST);
80
81            // エラーチェック
82            $arrErr = $this->lfCheckError($arrData);
83
84            // エラーがなければバックアップ処理を行う
85            if (count($arrErr) <= 0) {
86                // バックアップファイル作成
87                $arrErr = $this->lfCreateBkupData($arrData['bkup_name']);
88
89                // DBにデータ更新
90                if (count($arrErr) <= 0) {
91                    $this->lfUpdBkupData($arrData);
92                }else{
93                    $arrForm = $arrData;
94                }
95
96                $this->tpl_onload = "alert('バックアップ完了しました');";
97            }else{
98                $arrForm = $arrData;
99            }
100
101            break;
102
103            // リストア
104        case 'restore':
105        case 'restore_config':
106            if ($_POST['mode'] == 'restore_config') {
107                $this->mode = "restore_config";
108            }
109
110            $this->lfRestore($_POST['list_name']);
111
112            break;
113
114            // 削除
115        case 'delete':
116            $del_file = $this->bkup_dir.$_POST['list_name'] . ".tar.gz";
117            // ファイルの削除
118            if(is_file($del_file)){
119                $ret = unlink($del_file);
120            }
121
122            // DBから削除
123            $delsql = "DELETE FROM dtb_bkup WHERE bkup_name = ?";
124            $objQuery->query($delsql, array($_POST['list_name']));
125
126            break;
127
128            // ダウンロード
129        case 'download' :
130            $filename = $_POST['list_name'] . ".tar.gz";
131            $dl_file = $this->bkup_dir.$_POST['list_name'] . ".tar.gz";
132
133            // ダウンロード開始
134            Header("Content-disposition: attachment; filename=${filename}");
135            Header("Content-type: application/octet-stream; name=${filename}");
136            header("Content-Length: " .filesize($dl_file));
137            readfile ($dl_file);
138            exit();
139            break;
140
141        default:
142            break;
143        }
144
145        // バックアップリストを取得する
146        $arrBkupList = $this->lfGetBkupData("ORDER BY create_date DESC");
147        // テンプレートファイルに渡すデータをセット
148        $this->arrErr = isset($arrErr) ? $arrErr : "";
149        $this->arrForm = isset($arrForm) ? $arrForm : "";
150        $this->arrBkupList = $arrBkupList;
151
152        $objView->assignobj($this);     //変数をテンプレートにアサインする
153        $objView->display(MAIN_FRAME);      //テンプレートの出力
154    }
155
156    /**
157     * デストラクタ.
158     *
159     * @return void
160     */
161    function destroy() {
162        parent::destroy();
163    }
164
165    /* 取得文字列の変換 */
166    function lfConvertParam($array) {
167        /*
168         *  文字列の変換
169         *  K :  「半角(ハンカク)片仮名」を「全角片仮名」に変換
170         *  C :  「全角ひら仮名」を「全角かた仮名」に変換
171         *  V :  濁点付きの文字を一文字に変換。"K","H"と共に使用します
172         *  n :  「全角」数字を「半角(ハンカク)」に変換
173         *  a :  全角英数字を半角英数字に変換する
174         */
175        $arrConvList['bkup_name'] = "a";
176        $arrConvList['bkup_memo'] = "KVa";
177
178        // 文字変換
179        foreach ($arrConvList as $key => $val) {
180            // POSTされてきた値のみ変換する。
181            if(isset($array[$key])) {
182                $array[$key] = mb_convert_kana($array[$key] ,$val);
183            }
184        }
185        return $array;
186    }
187
188    // エラーチェック
189    function lfCheckError($array){
190        $objErr = new SC_CheckError($array);
191
192        $objErr->doFunc(array("バックアップ名", "bkup_name", STEXT_LEN), array("EXIST_CHECK","MAX_LENGTH_CHECK","NO_SPTAB","ALNUM_CHECK"));
193        $objErr->doFunc(array("バックアップメモ", "bkup_memo", MTEXT_LEN), array("MAX_LENGTH_CHECK"));
194
195        // 重複チェック
196        $ret = $this->lfGetBkupData("WHERE bkup_name = ?", array($array['bkup_name']));
197        if (count($ret) > 0) {
198            $objErr->arrErr['bkup_name'] = "バックアップ名が重複しています。別名を入力してください。";
199        }
200
201        return $objErr->arrErr;
202    }
203
204    // バックアップファイル作成
205    function lfCreateBkupData($bkup_name){
206        // 実行時間を制限しない
207        set_time_limit(0);
208       
209        $objQuery = new SC_Query();
210        $csv_data = "";
211        $csv_autoinc = "";
212        $err = true;
213
214        $bkup_dir = $this->bkup_dir;
215        if (!is_dir(dirname($bkup_dir))) $err = mkdir(dirname($bkup_dir));
216        $bkup_dir = $bkup_dir . $bkup_name . "/";
217
218        // 全テーブル取得
219        $arrTableList = $this->lfGetTableList();
220
221        // 各テーブル情報を取得する
222        foreach($arrTableList as $key => $val){
223
224            if (!($val == "dtb_bkup" || $val == "mtb_zip")) {
225
226                // 自動採番型の構成を取得する
227                $csv_autoinc .= $this->lfGetAutoIncrement($val);
228
229                // 全データを取得
230                if ($val == "dtb_pagelayout"){
231                    $arrData = $objQuery->getAll("SELECT * FROM $val ORDER BY page_id");
232                }else{
233                    $arrData = $objQuery->getAll("SELECT * FROM $val");
234                }
235
236                // CSVデータ生成
237                if (count($arrData) > 0) {
238
239                    // カラムをCSV形式に整える
240                    $arrKyes = SC_Utils_Ex::sfGetCommaList(array_keys($arrData[0]), false);
241
242                    // データをCSV形式に整える
243                    $data = "";
244                    foreach($arrData as $data_key => $data_val){
245                        //$val = str_replace("\"", "\\\"", $val);
246                        $data .= $this->lfGetCSVList($arrData[$data_key]);
247
248                    }
249                    // CSV出力データ生成
250                    $csv_data .= $val . "\r\n";
251                    $csv_data .= $arrKyes . "\r\n";
252                    $csv_data .= $data;
253                    $csv_data .= "\r\n";
254                }
255
256                // タイムアウトを防ぐ
257                SC_Utils_Ex::sfFlush();
258            }
259        }
260
261        $csv_file = $bkup_dir . "bkup_data.csv";
262        $csv_autoinc_file = $bkup_dir . "autoinc_data.csv";
263        mb_internal_encoding(CHAR_CODE);
264        // CSV出力
265        // ディレクトリが存在していなければ作成する
266        if (!is_dir(dirname($csv_file))) {
267            $err = mkdir(dirname($csv_file));
268        }
269        if ($err) {
270            // dataをCSV出力
271            $fp = fopen($csv_file,"w");
272            if($fp) {
273                if($csv_data != ""){
274                    $err = fwrite($fp, $csv_data);
275                }
276                fclose($fp);
277            }
278
279            // 自動採番をCSV出力
280            $fp = fopen($csv_autoinc_file,"w");
281            if($fp) {
282                if($csv_autoinc != ""){
283                    $err = fwrite($fp, $csv_autoinc);
284                }
285                fclose($fp);
286            }
287        }
288
289        // 各種ファイルコピー
290        if ($err) {
291            /**
292            // 商品画像ファイルをコピー
293            // ディレクトリが存在していなければ作成する
294            $image_dir = $bkup_dir . "save_image/";
295            if (!is_dir(dirname($image_dir))) $err = mkdir(dirname($image_dir));
296            $copy_mess = "";
297            $copy_mess = SC_Utils_Ex::sfCopyDir("../../upload/save_image/",$image_dir, $copy_mess);
298
299            // テンプレートファイルをコピー
300            // ディレクトリが存在していなければ作成する
301            $templates_dir = $bkup_dir . "templates/";
302            if (!is_dir(dirname($templates_dir))) $err = mkdir(dirname($templates_dir));
303            $copy_mess = "";
304            $copy_mess = SC_Utils_Ex::sfCopyDir("../../user_data/templates/",$templates_dir, $copy_mess);
305
306            // インクルードファイルをコピー
307            // ディレクトリが存在していなければ作成する
308            $inc_dir = $bkup_dir . "include/";
309            if (!is_dir(dirname($inc_dir))) $err = mkdir(dirname($inc_dir));
310            $copy_mess = "";
311            $copy_mess = SC_Utils_Ex::sfCopyDir("../../user_data/include/",$inc_dir, $copy_mess);
312
313            // CSSファイルをコピー
314            // ディレクトリが存在していなければ作成する
315            $css_dir = $bkup_dir . "css/";
316            if (!is_dir(dirname($css_dir))) $err = mkdir(dirname($css_dir));
317            $copy_mess = "";
318            $copy_mess = SC_Utils_Ex::sfCopyDir("../../user_data/css/",$css_dir, $copy_mess);
319            **/
320            //圧縮フラグTRUEはgzip圧縮をおこなう
321            $tar = new Archive_Tar($this->bkup_dir . $bkup_name.".tar.gz", TRUE);
322
323            //bkupフォルダに移動する
324            chdir($this->bkup_dir);
325
326            //圧縮をおこなう
327            $zip = $tar->create("./" . $bkup_name . "/");
328
329            // バックアップデータの削除
330            if ($zip) SC_Utils_Ex::sfDelFile($bkup_dir);
331        }
332
333        if (!$err) {
334            $arrErr['bkup_name'] = "バックアップに失敗しました。";
335            // バックアップデータの削除
336            SC_Utils_Ex::sfDelFile($bkup_dir);
337        }
338
339        return isset($arrErr) ? $arrErr : array();
340    }
341
342    /* 配列の要素をCSVフォーマットで出力する。*/
343    function lfGetCSVList($array) {
344        $line = '';
345        if (count($array) > 0) {
346            foreach($array as $key => $val) {
347                $val = mb_convert_encoding($val, CHAR_CODE, CHAR_CODE);
348                $val = str_replace("\"", "\\\"", $val);
349                $line .= "\"".$val."\",";
350            }
351            $line = ereg_replace(",$", "\r\n", $line);
352        }else{
353            return false;
354        }
355        return $line;
356    }
357
358    // 全テーブルリストを取得する
359    function lfGetTableList(){
360        $objQuery = new SC_Query();
361
362        if(DB_TYPE == "pgsql"){
363            $sql = "SELECT tablename FROM pg_tables WHERE tableowner = ? ORDER BY tablename ; ";
364            $arrRet = $objQuery->getAll($sql, array(DB_USER));
365            $arrRet = SC_Utils_Ex::sfSwapArray($arrRet);
366            $arrRet = $arrRet['tablename'];
367        }else if(DB_TYPE == "mysql"){
368            $sql = "SHOW TABLES;";
369            $arrRet = $objQuery->getAll($sql);
370            $arrRet = SC_Utils_Ex::sfSwapArray($arrRet);
371
372            // キーを取得
373            $arrKey = array_keys($arrRet);
374
375            $arrRet = $arrRet[$arrKey[0]];
376        }
377        return $arrRet;
378    }
379
380    // 自動採番型をCSV出力形式に変換する
381    function lfGetAutoIncrement($table_name){
382        $arrColList = $this->lfGetColumnList($table_name);
383        $ret = "";
384
385        if(DB_TYPE == "pgsql"){
386            $match = 'nextval(\'';
387        }else if(DB_TYPE == "mysql"){
388            $match = "auto_incr";
389        }
390
391        foreach($arrColList['col_def'] as $key => $val){
392
393            if (substr($val,0,9) == $match) {
394                $col = $arrColList['col_name'][$key];
395                $autoVal = $this->lfGetAutoIncrementVal($table_name, $col);
396                $ret .= "$table_name,$col,$autoVal\n";
397            }
398        }
399
400        return $ret;
401    }
402
403    // テーブル構成を取得する
404    Function Lfgetcolumnlist($table_name){
405        $objQuery = new SC_Query();
406
407        if(DB_TYPE == "pgsql"){
408            $sql = "SELECT
409                    a.attname, t.typname, a.attnotnull, d.adsrc as defval, a.atttypmod, a.attnum as fldnum, e.description
410                FROM
411                    pg_class c,
412                    pg_type t,
413                    pg_attribute a left join pg_attrdef d on (a.attrelid=d.adrelid and a.attnum=d.adnum)
414                                   left join pg_description e on (a.attrelid=e.objoid and a.attnum=e.objsubid)
415                WHERE (c.relname=?) AND (c.oid=a.attrelid) AND (a.atttypid=t.oid) AND a.attnum > 0
416                ORDER BY fldnum";
417            $arrColList = $objQuery->getAll($sql, array($table_name));
418            $arrColList = SC_Utils_Ex::sfSwapArray($arrColList);
419
420            $arrRet['col_def'] = $arrColList['defval'];
421            $arrRet['col_name'] = $arrColList['attname'];
422        }else if(DB_TYPE == "mysql"){
423            $sql = "SHOW COLUMNS FROM $table_name";
424            $arrColList = $objQuery->getAll($sql);
425            $arrColList = SC_Utils_Ex::sfSwapArray($arrColList);
426
427            $arrRet['col_def'] = $arrColList['Extra'];
428            $arrRet['col_name'] = $arrColList['Field'];
429        }
430        return $arrRet;
431    }
432
433    // 自動採番型の値を取得する
434    function lfGetAutoIncrementVal($table_name , $colname = ""){
435        $objQuery = new SC_Query();
436        $ret = "";
437
438        if(DB_TYPE == "pgsql"){
439            $ret = $objQuery->nextval($table_name, $colname) - 1;
440        }else if(DB_TYPE == "mysql"){
441            $sql = "SHOW TABLE STATUS LIKE ?";
442            $arrData = $objQuery->getAll($sql, array($table_name));
443            $ret = $arrData[0]['Auto_increment'];
444        }
445        return $ret;
446    }
447
448    // バックアップテーブルにデータを更新する
449    function lfUpdBkupData($data){
450        $objQuery = new SC_Query();
451
452        $sql = "INSERT INTO dtb_bkup (bkup_name,bkup_memo,create_date) values (?,?,now())";
453        $objQuery->query($sql, array($data['bkup_name'],$data['bkup_memo']));
454    }
455
456    // バックアップテーブルからデータを取得する
457    function lfGetBkupData($where = "", $data = array()){
458        $objQuery = new SC_Query();
459
460        $sql = "SELECT bkup_name, bkup_memo, create_date FROM dtb_bkup ";
461        if ($where != "")   $sql .= $where;
462
463        $ret = $objQuery->getall($sql,$data);
464
465        return $ret;
466    }
467
468    // バックアップファイルをリストアする
469    function lfRestore($bkup_name){
470        // 実行時間を制限しない
471        set_time_limit(0);
472       
473        $objQuery = new SC_Query("", false);
474        $csv_data = "";
475        $err = true;
476
477        $bkup_dir = $this->bkup_dir . $bkup_name . "/";
478
479        //バックアップフォルダに移動する
480        chdir($this->bkup_dir);
481
482        //圧縮フラグTRUEはgzip解凍をおこなう
483        $tar = new Archive_Tar($bkup_name . ".tar.gz", TRUE);
484
485        //指定されたフォルダ内に解凍する
486        $err = $tar->extract("./");
487
488        // 無事解凍できれば、リストアを行う
489        if ($err) {
490
491            // トランザクション開始
492            $objQuery->begin();
493
494            // DBをクリア
495            $err = $this->lfDeleteAll($objQuery);
496
497            // INSERT実行
498            if ($err) $err = $this->lfExeInsertSQL($objQuery, $bkup_dir . "bkup_data.csv");
499
500            // 自動採番の値をセット
501            if ($err) $this->lfSetAutoInc($objQuery, $bkup_dir . "autoinc_data.csv");
502
503            // 各種ファイルのコピー
504            /**
505            if ($err) {
506                // 画像のコピー
507                $image_dir = $bkup_dir . "save_image/";
508                $copy_mess = "";
509                $copy_mess = SC_Utils_Ex::sfCopyDir($image_dir, "../../upload/save_image/", $copy_mess, true);
510
511                // テンプレートのコピー
512                $tmp_dir = $bkup_dir . "templates/";
513                $copy_mess = "";
514                $copy_mess = SC_Utils_Ex::sfCopyDir($tmp_dir, "../../user_data/templates/", $copy_mess, true);
515
516                // インクルードファイルのコピー
517                $inc_dir = $bkup_dir . "include/";
518                $copy_mess = "";
519                $copy_mess = SC_Utils_Ex::sfCopyDir($inc_dir, "../../user_data/include/", $copy_mess, true);
520
521                // CSSのコピー
522                $css_dir = $bkup_dir . "css/";
523                $copy_mess = "";
524                $copy_mess = SC_Utils_Ex::sfCopyDir($css_dir, "../../user_data/css/", $copy_mess, true);
525
526                // バックアップデータの削除
527                SC_Utils_Ex::sfDelFile($bkup_dir);
528            }**/
529
530            // リストア成功ならコミット失敗ならロールバック
531            if ($err) {
532                $objQuery->commit();
533                $this->restore_msg = "リストア終了しました。";
534                $this->restore_err = true;
535            }else{
536                $objQuery->rollback();
537                $this->restore_msg = "リストアに失敗しました。";
538                $this->restore_name = $bkup_name;
539                $this->restore_err = false;
540            }
541        }
542    }
543
544    // CSVファイルからインサート実行
545    function lfExeInsertSQL($objQuery, $csv){
546
547        $sql = "";
548        $base_sql = "";
549        $tbl_flg = false;
550        $col_flg = false;
551        $ret = true;
552        $pagelayout_flg = false;
553        $mode = $this->mode;
554
555        // csvファイルからデータの取得
556        $fp = fopen($csv, "r");
557        while (!feof($fp)) {
558            $data = fgetcsv($fp, 1000000);
559
560            //空白行のときはテーブル変更
561            if (count($data) <= 1 and $data[0] == "") {
562                $base_sql = "";
563                $tbl_flg = false;
564                $col_flg = false;
565                continue;
566            }
567
568            // テーブルフラグがたっていない場合にはテーブル名セット
569            if (!$tbl_flg) {
570                $base_sql = "INSERT INTO $data[0] ";
571                $tbl_flg = true;
572
573                if($data[0] == "dtb_pagelayout"){
574                    $pagelayout_flg = true;
575                }
576
577                continue;
578            }
579
580            // カラムフラグがたっていない場合にはカラムセット
581            if (!$col_flg) {
582                if ($mode != "restore_config"){
583                    $base_sql .= " ( $data[0] ";
584                    for($i = 1; $i < count($data); $i++){
585                        $base_sql .= "," . $data[$i];
586                    }
587                    $base_sql .= " ) ";
588                }
589                $col_flg = true;
590                continue;
591            }
592
593            // インサートする値をセット
594            $sql = $base_sql . "VALUES ( ? ";
595            for($i = 1; $i < count($data); $i++){
596                $sql .= ", ?";
597            }
598            $sql .= " );";
599            $data = str_replace("\\\"", "\"", $data);
600            $err = $objQuery->query($sql, $data);
601
602            // エラーがあれば終了
603            if ($err->message != ""){
604                SC_Utils_Ex::sfErrorHeader(">> " . $objQuery->getlastquery(false));
605                return false;
606            }
607
608            if ($pagelayout_flg) {
609                // dtb_pagelayoutの場合には最初のデータはpage_id = 0にする
610                $sql = "UPDATE dtb_pagelayout SET page_id = '0'";
611                $objQuery->query($sql);
612                $pagelayout_flg = false;
613            }
614
615            // タイムアウトを防ぐ
616            SC_Utils_Ex::sfFlush();
617        }
618        fclose($fp);
619
620        return $ret;
621    }
622
623    // 自動採番をセット
624    function lfSetAutoInc($objQuery, $csv){
625        // csvファイルからデータの取得
626        $arrCsvData = file($csv);
627
628        foreach($arrCsvData as $key => $val){
629            $arrData = split(",", trim($val));
630
631            if ($arrData[2] == 0)   $arrData[2] = 1;
632            $objQuery->setval($arrData[0], $arrData[1], $arrData[2]);
633        }
634    }
635
636    // DBを全てクリアする
637    function lfDeleteAll($objQuery){
638        $ret = true;
639
640        $arrTableList = $this->lfGetTableList();
641
642        foreach($arrTableList as $key => $val){
643            // バックアップテーブルは削除しない
644            if ($val != "dtb_bkup") {
645                $trun_sql = "DELETE FROM $val;";
646                $ret = $objQuery->query($trun_sql);
647
648                if (!$ret) return $ret;
649            }
650        }
651
652        return $ret;
653    }
654
655    // バックアップテーブルを作成する
656    function lfCreateBkupTable(){
657        $objQuery = new SC_Query();
658
659        // テーブルの存在チェック
660        $arrTableList = $this->lfGetTableList();
661
662        if(!in_array("dtb_bkup", $arrTableList)){
663            // 存在していなければ作成
664            $cre_sql = "
665            create table dtb_bkup
666            (
667                bkup_name   text,
668                bkup_memo   text,
669                create_date timestamp
670            );
671        ";
672
673            $objQuery->query($cre_sql);
674        }
675    }
676}
677?>
Note: See TracBrowser for help on using the repository browser.