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

Revision 21441, 17.6 KB checked in by Seasoft, 12 years ago (diff)

#1613 (ソース整形・ソースコメントの改善)

  • Zend Framework PHP 標準コーディング規約への準拠を高めた
  • 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-2011 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 CLASS_EX_REALDIR . 'helper_extends/SC_Helper_CSV_Ex.php';
27require_once DATA_REALDIR. 'module/Tar.php';
28/**
29 * バックアップ のページクラス.
30 *
31 * @package Page
32 * @author LOCKON CO.,LTD.
33 * @version $Id$
34 */
35class LC_Page_Admin_System_Bkup extends LC_Page_Admin_Ex {
36
37    // }}}
38    // {{{ functions
39
40    /**
41     * Page を初期化する.
42     *
43     * @return void
44     */
45    function init() {
46        parent::init();
47        $this->tpl_mainpage = 'system/bkup.tpl';
48        $this->tpl_mainno = 'system';
49        $this->tpl_subno = 'bkup';
50        $this->tpl_maintitle = 'システム設定';
51        $this->tpl_subtitle = 'バックアップ管理';
52
53        $this->bkup_dir = DATA_REALDIR . "downloads/backup/";
54        $this->bkup_ext = '.tar.gz';
55    }
56
57    /**
58     * Page のプロセス.
59     *
60     * @return void
61     */
62    function process() {
63        $this->action();
64        $this->sendResponse();
65    }
66
67    /**
68     * Page のアクション.
69     *
70     * @return void
71     */
72    function action() {
73
74        $objFormParam = new SC_FormParam;
75
76        // パラメーターの初期化
77        $this->initParam($objFormParam, $_POST);
78
79        $arrErrTmp  = array();
80        $arrForm = array();
81
82        switch ($this->getMode()) {
83
84        // バックアップを作成する
85        case 'bkup':
86
87            // データ型エラーチェック
88            $arrErrTmp[1] = $objFormParam->checkError();
89
90            // データ型に問題がない場合
91            if (SC_Utils_Ex::isBlank($arrErrTmp[1])) {
92                // データ型以外のエラーチェック
93                $arrErrTmp[2] = $this->lfCheckError($objFormParam->getHashArray(), $this->getMode());
94            }
95
96            // エラーがなければバックアップ処理を行う
97            if (SC_Utils_Ex::isBlank($arrErrTmp[1]) && SC_Utils_Ex::isBlank($arrErrTmp[2])) {
98
99                $arrData = $objFormParam->getHashArray();
100
101                $work_dir = $this->bkup_dir . $arrData['bkup_name'] . "/";
102                // バックアップデータの事前削除
103                SC_Utils_Ex::sfDelFile($work_dir);
104                // バックアップファイル作成
105                $res = $this->lfCreateBkupData($arrData['bkup_name'], $work_dir);
106                // バックアップデータの事後削除
107                SC_Utils_Ex::sfDelFile($work_dir);
108
109                $arrErrTmp[3] = array();
110                if ($res !== true) {
111                    $arrErrTmp[3]['bkup_name'] = 'バックアップに失敗しました。(' . $res . ')';
112                }
113
114                // DBにデータ更新
115                if (SC_Utils_Ex::isBlank($arrErrTmp[3])) {
116                    $this->lfUpdBkupData($arrData);
117                } else {
118                    $arrForm = $arrData;
119                    $arrErr = $arrErrTmp[3];
120                }
121
122                $this->tpl_onload = "alert('バックアップ完了しました');";
123            } else {
124                $arrForm = $objFormParam->getHashArray();
125                $arrErr = array_merge((array)$arrErrTmp[1],(array)$arrErrTmp[2]);
126            }
127            break;
128
129        // リストア
130        case 'restore_config':
131            $this->mode = "restore_config";
132
133        case 'restore':
134            // データベースに存在するかどうかチェック
135            $arrErr = $this->lfCheckError($objFormParam->getHashArray(), $this->getMode());
136
137            // エラーがなければリストア処理を行う
138            if (SC_Utils_Ex::isBlank($arrErr)) {
139                $arrData = $objFormParam->getHashArray();
140                $this->lfRestore($arrData['list_name'], $this->bkup_dir, $this->bkup_ext, $this->mode);
141            }
142            break;
143
144        // 削除
145        case 'delete':
146
147            // データベースに存在するかどうかチェック
148            $arrErr = $this->lfCheckError($objFormParam->getHashArray(), $this->getMode());
149
150            // エラーがなければリストア処理を行う
151            if (SC_Utils_Ex::isBlank($arrErr)) {
152
153                $arrData = $objFormParam->getHashArray();
154
155                // DBとファイルを削除
156                $this->lfDeleteBackUp($arrData, $this->bkup_dir, $this->bkup_ext);
157            }
158
159            break;
160
161            // ダウンロード
162        case 'download' :
163
164            // データベースに存在するかどうかチェック
165            $arrErr = $this->lfCheckError($objFormParam->getHashArray(), $this->getMode());
166
167            // エラーがなければダウンロード処理を行う
168            if (SC_Utils_Ex::isBlank($arrErr)) {
169
170                $arrData = $objFormParam->getHashArray();
171
172                $filename = $arrData['list_name'] . $this->bkup_ext;
173                $dl_file = $this->bkup_dir.$arrData['list_name'] . $this->bkup_ext;
174
175                // ダウンロード開始
176                Header("Content-disposition: attachment; filename=${filename}");
177                Header("Content-type: application/octet-stream; name=${filename}");
178                header("Content-Length: " .filesize($dl_file));
179                readfile ($dl_file);
180                exit();
181                break;
182            }
183
184        default:
185            break;
186        }
187
188        // 不要になった変数を解放
189        unset($arrErrTmp);
190
191        // バックアップリストを取得する
192        $arrBkupList = $this->lfGetBkupData("ORDER BY create_date DESC");
193        // テンプレートファイルに渡すデータをセット
194        $this->arrErr = isset($arrErr) ? $arrErr : array();
195        $this->arrForm = isset($arrForm) ? $arrForm : array();
196        $this->arrBkupList = $arrBkupList;
197    }
198
199    /**
200     * デストラクタ.
201     *
202     * @return void
203     */
204    function destroy() {
205        parent::destroy();
206    }
207
208    /**
209     * パラメーター初期化.
210     *
211     * @param object $objFormParam
212     * @param array  $arrParams  $_POST値
213     * @return void
214     */
215    function initParam(&$objFormParam, &$arrParams) {
216
217        $objFormParam->addParam('バックアップ名', 'bkup_name', STEXT_LEN, 'a', array('EXIST_CHECK', 'MAX_LENGTH_CHECK', 'NO_SPTAB', 'ALNUM_CHECK'));
218        $objFormParam->addParam('バックアップメモ', 'bkup_memo', MTEXT_LEN, 'KVa', array('MAX_LENGTH_CHECK'));
219        $objFormParam->addParam('バックアップ名(リスト)', 'list_name', STEXT_LEN, 'a', array('MAX_LENGTH_CHECK', 'NO_SPTAB', 'ALNUM_CHECK'));
220        $objFormParam->setParam($arrParams);
221        $objFormParam->convParam();
222
223    }
224
225    /**
226     * データ型以外のエラーチェック.
227     *
228     * @param array  $arrForm
229     * @param string $mode
230     * @return $arrErr
231     */
232    function lfCheckError(&$arrForm, $mode){
233
234        $arrVal = array();
235
236        switch ($mode) {
237        case 'bkup':
238            $arrVal[] = $arrForm['bkup_name'];
239            break;
240
241        case 'restore_config':
242        case 'restore':
243        case 'download':
244        case 'delete':
245            $arrVal[] = $arrForm['list_name'];
246            break;
247
248        default:
249            break;
250
251        }
252
253        // 重複・存在チェック
254        $ret = $this->lfGetBkupData("WHERE bkup_name = ?", $arrVal);
255        if (count($ret) > 0 && $mode == 'bkup') {
256            $arrErr['bkup_name'] = "バックアップ名が重複しています。別名を入力してください。";
257        } elseif (count($ret) <= 0 && $mode != 'bkup') {
258            $arrErr['list_name'] = "選択されたデータがみつかりませんでした。既に削除されている可能性があります。";
259        }
260
261        return $arrErr;
262    }
263
264    /**
265     * バックアップファイル作成.
266     *
267     * @param string $bkup_name
268     * @return boolean|int 結果。true:成功 int:失敗 FIXME 本来は int ではなく、エラーメッセージを戻すべき
269     */
270    function lfCreateBkupData($bkup_name, $work_dir){
271        // 実行時間を制限しない
272        set_time_limit(0);
273
274        $objQuery =& SC_Query_Ex::getSingletonInstance();
275        $csv_autoinc = "";
276        $arrData = array();
277
278        $success = mkdir($work_dir, 0777, true);
279        if (!$success) {
280            return __LINE__;
281        }
282
283        // 全テーブル取得
284        $arrTableList = $objQuery->listTables();
285
286        // 各テーブル情報を取得する
287        foreach ($arrTableList as $table) {
288
289            if ($table == 'dtb_bkup' || $table == 'mtb_zip') {
290                continue;
291            }
292
293            // dataをCSV出力
294            $csv_file = $work_dir . $table . '.csv';
295            $fp = fopen($csv_file, 'w');
296            if (!$fp) {
297                return __LINE__;
298            }
299
300            // 全データを取得
301            $sql = "SELECT * FROM $table";
302
303            $this->fpOutput =& $fp;
304            $this->first_line = true;
305            $success = $objQuery->doCallbackAll(array(&$this, 'cbOutputCSV'), $sql);
306            unset($this->fpOutput);
307
308            if ($success === false) {
309                return __LINE__;
310            }
311
312            fclose($fp);
313
314            // タイムアウトを防ぐ
315            SC_Utils_Ex::sfFlush();
316        }
317
318        // 自動採番型の構成を取得する
319        $csv_autoinc = $this->lfGetAutoIncrement();
320
321        $csv_autoinc_file = $work_dir . "autoinc_data.csv";
322
323        // CSV出力
324
325        // 自動採番をCSV出力
326        $fp = fopen($csv_autoinc_file,'w');
327        if ($fp) {
328            if ($csv_autoinc != "") {
329                $success = fwrite($fp, $csv_autoinc);
330                if (!$success) {
331                    return __LINE__;
332                }
333            }
334            fclose($fp);
335        }
336
337        //圧縮フラグTRUEはgzip圧縮をおこなう
338        $tar = new Archive_Tar($this->bkup_dir . $bkup_name . $this->bkup_ext, TRUE);
339
340        //bkupフォルダに移動する
341        chdir($work_dir);
342
343        //圧縮をおこなう
344        $zip = $tar->create('./');
345
346        return true;
347    }
348
349    /**
350     * CSV作成 テンポラリファイル出力 コールバック関数
351     *
352     * @param mixed $data 出力データ
353     * @return boolean true (true:固定 false:中断)
354     */
355    function cbOutputCSV($data) {
356        $line = '';
357        if ($this->first_line) {
358            // カラム名
359            $line .= SC_Helper_CSV_Ex::sfArrayToCsv(array_keys($data)) . "\n";
360            $this->first_line = false;
361        }
362        $line .= SC_Helper_CSV_Ex::sfArrayToCsv($data);
363        $line .= "\n";
364        return fwrite($this->fpOutput, $line);
365    }
366
367    /**
368     * シーケンス一覧をCSV出力形式に変換する.
369     *
370     * シーケンス名,シーケンス値 の形式に出力する.
371     *
372     * @return string シーケンス一覧の文字列
373     * @return string $ret
374     */
375    function lfGetAutoIncrement() {
376        $objQuery =& SC_Query_Ex::getSingletonInstance();
377        $arrSequences = $objQuery->listSequences();
378
379        foreach ($arrSequences as $val) {
380            $seq = $objQuery->currVal($val);
381
382            $ret .= $val . ",";
383            $ret .= is_null($seq) ? "0" : $seq;
384            $ret .= "\r\n";
385        }
386        return $ret;
387    }
388
389    // バックアップテーブルにデータを更新する
390    function lfUpdBkupData($data){
391        $objQuery =& SC_Query_Ex::getSingletonInstance();
392
393        $arrVal = array();
394        $arrVal['bkup_name'] = $data['bkup_name'];
395        $arrVal['bkup_memo'] = $data['bkup_memo'];
396        $arrVal['create_date'] = 'CURRENT_TIMESTAMP';
397
398        $objQuery->insert('dtb_bkup', $arrVal);
399    }
400
401    // バックアップテーブルからデータを取得する
402    function lfGetBkupData($where = "", $data = array()){
403        $objQuery =& SC_Query_Ex::getSingletonInstance();
404
405        $sql = "SELECT bkup_name, bkup_memo, create_date FROM dtb_bkup ";
406        if ($where != "") {
407            $sql .= $where;
408        }
409
410        $ret = $objQuery->getAll($sql,$data);
411
412        return $ret;
413    }
414
415    /**
416     * バックアップファイルをリストアする
417     *
418     * @param string $bkup_name
419     * @param string $bkup_dir
420     * @param string $bkup_ext
421     * @return void
422     */
423    function lfRestore($bkup_name, $bkup_dir, $bkup_ext, $mode){
424        // 実行時間を制限しない
425        set_time_limit(0);
426
427        $objQuery =& SC_Query_Ex::getSingletonInstance();
428        $success = true;
429
430        $work_dir = $bkup_dir . $bkup_name . '/';
431
432        //圧縮フラグTRUEはgzip解凍をおこなう
433        $tar = new Archive_Tar($work_dir . $bkup_name . $bkup_ext, TRUE);
434
435        //指定されたフォルダ内に解凍する
436        $success = $tar->extract($work_dir . $bkup_name);
437
438        // 無事解凍できれば、リストアを行う
439        if ($success) {
440
441            // トランザクション開始
442            $objQuery->begin();
443
444            // DBをクリア
445            $success = $this->lfDeleteAll($objQuery);
446
447            // INSERT実行
448            if ($success) $success = $this->lfExeInsertSQL($objQuery, $work_dir, $mode);
449
450            // 自動採番の値をセット
451            if ($success) $this->lfSetAutoInc($objQuery, $work_dir . 'autoinc_data.csv');
452
453            // リストア成功ならコミット失敗ならロールバック
454            if ($success) {
455                $objQuery->commit();
456                $this->restore_msg = "リストア終了しました。";
457                $this->restore_err = true;
458            } else {
459                $objQuery->rollback();
460                $this->restore_msg = "リストアに失敗しました。";
461                $this->restore_name = $bkup_name;
462                $this->restore_err = false;
463            }
464        }
465
466        // FIXME この辺りで、バックアップ時と同等の一時ファイルの削除を実行すべきでは?
467    }
468
469    /**
470     * CSVファイルからインサート実行.
471     *
472     * @param object $objQuery
473     * @param string $dir
474     * @param string $mode
475     * @return void
476     */
477    function lfExeInsertSQL(&$objQuery, $dir, $mode){
478
479        $tbl_flg = false;
480        $col_flg = false;
481        $ret = true;
482        $pagelayout_flg = false;
483        $arrVal = array();
484        $arrCol = array();
485        $arrAllTableList = $objQuery->listTables();
486
487        $objDir = dir($dir);
488        while (false !== ($file_name = $objDir->read())) {
489            if (!preg_match('/^((dtb|mtb)_(\w+))\.csv$/', $file_name, $matches)) {
490                continue;
491            }
492            var_dump($matches);
493            $file_path = $dir . $file_name;
494            $table = $matches[1];
495
496            // テーブル存在チェック
497            if (!in_array($table, $arrAllTableList)) {
498                if ($mode === 'restore_config') {
499                    continue;
500                }
501                return false;
502            }
503
504            // csvファイルからデータの取得
505            $fp = fopen($file_path, 'r');
506            if ($fp === false) {
507                SC_Utils_Ex::sfDispException($file_name . ' のファイルオープンに失敗しました。');
508            }
509
510            $line = 0;
511            while (!feof($fp)) {
512                $line++;
513                $arrCsvLine = fgetcsv($fp, 1000000);
514
515                // 1行目: 列名
516                if ($line === 1) {
517                    $arrColName = $arrCsvLine;
518                    continue;
519                }
520
521                $arrVal = array_combine($arrColName, $arrCsvLine);
522                $objQuery->insert($table, $arrVal);
523
524                SC_Utils_Ex::extendTimeOut();
525            }
526
527            fclose($fp);
528        }
529
530        return $ret;
531    }
532
533    // 自動採番をセット
534    function lfSetAutoInc(&$objQuery, $csv){
535        // csvファイルからデータの取得
536        $arrCsvData = file($csv);
537
538        foreach ($arrCsvData as $val) {
539            $arrData = explode(",", trim($val));
540
541             $objQuery->setval($arrData[0], $arrData[1]);
542        }
543    }
544
545    // DBを全てクリアする
546    function lfDeleteAll(&$objQuery){
547        $ret = true;
548
549        $arrTableList = $objQuery->listTables();
550
551        foreach ($arrTableList as $val) {
552            // バックアップテーブルは削除しない
553            // XXX mtb_zip も削除不要では?
554            if ($val != "dtb_bkup") {
555                $ret = $objQuery->delete($val);
556                if (PEAR::isError($ret)) return false;
557            }
558        }
559        return true;
560    }
561
562    // 選択したバックアップをDBから削除
563    function lfDeleteBackUp(&$arrForm, $bkup_dir, $bkup_ext) {
564
565        $objQuery =& SC_Query_Ex::getSingletonInstance();
566
567        $del_file = $bkup_dir.$arrForm['list_name'] . $bkup_ext;
568        // ファイルの削除
569        if (is_file($del_file)) {
570            $ret = unlink($del_file);
571        }
572
573        $delsql = "DELETE FROM dtb_bkup WHERE bkup_name = ?";
574        $objQuery->delete("dtb_bkup", "bkup_name = ?", array($arrForm['list_name']));
575
576    }
577
578}
Note: See TracBrowser for help on using the repository browser.