source: branches/version-2_13-dev/data/class/pages/admin/basis/LC_Page_Admin_Basis_ZipInstall.php @ 22856

Revision 22856, 13.8 KB checked in by Seasoft, 11 years ago (diff)

#2043 (typo修正・ソース整形・ソースコメントの改善 for 2.13.0)

  • 主に空白・空白行の調整。もう少し整えたいが、一旦現状コミット。
  • 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-2013 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
24require_once CLASS_EX_REALDIR . 'page_extends/admin/LC_Page_Admin_Ex.php';
25
26/** CSV ファイルの最大行数 */
27define('ZIP_CSV_LINE_MAX', 8192);
28
29/** 画像の表示数量 */
30define('IMAGE_MAX', 680);
31
32/** 郵便番号CSV ファイルのパス */
33define('ZIP_CSV_REALFILE', DATA_REALDIR . 'downloads/KEN_ALL.CSV');
34
35/** UTF-8 変換済みの郵便番号CSV ファイルのパス */
36define('ZIP_CSV_UTF8_REALFILE', DATA_REALDIR . 'downloads/KEN_ALL_utf-8.CSV');
37
38/**
39 * 郵便番号DB登録 のページクラス.
40 *
41 * @package Page
42 * @author LOCKON CO.,LTD.
43 * @version $Id:LC_Page_Admin_Basis_ZipInstall.php 16741 2007-11-08 00:43:24Z adachi $
44 */
45class LC_Page_Admin_Basis_ZipInstall extends LC_Page_Admin_Ex
46{
47    /** CSVの行数 */
48    var $tpl_line = 0;
49    var $tpl_mode;
50    var $exec;
51    var $tpl_count_mtb_zip;
52
53    /** CSV の更新日時 */
54    var $tpl_csv_datetime;
55
56    /** 日本郵便から取得した ZIP アーカイブファイルの保管パス */
57    var $zip_csv_temp_realfile;
58
59
60    /**
61     * Page を初期化する.
62     *
63     * @return void
64     */
65    function init()
66    {
67        parent::init();
68        $this->tpl_mainpage = 'basis/zip_install.tpl';
69        $this->tpl_subno = 'zip_install';
70        $this->tpl_maintitle = '基本情報管理';
71        $this->tpl_subtitle = '郵便番号DB登録';
72        $this->tpl_mainno = 'basis';
73
74        $this->tpl_mode = $this->getMode();
75        $this->exec = (boolean)$_GET['exec'];
76        $this->zip_csv_temp_realfile = DATA_REALDIR . 'downloads/tmp/ken_all.zip';
77    }
78
79    /**
80     * Page のプロセス.
81     *
82     * @return void
83     */
84    function process()
85    {
86        $this->action();
87        $this->sendResponse();
88    }
89
90    /**
91     * Page のアクション.
92     *
93     * @return void
94     */
95    function action()
96    {
97        // パラメーター管理クラス
98        $objFormParam = new SC_FormParam_Ex();
99        // パラメーター情報の初期化
100        $this->lfInitParam($this->tpl_mode, $objFormParam);
101        $objFormParam->setParam($_GET);
102        $this->arrErr = $objFormParam->checkError();
103        $this->arrForm = $objFormParam->getHashArray();
104        $this->tpl_zip_download_url_empty = !defined('ZIP_DOWNLOAD_URL') || strlen(ZIP_DOWNLOAD_URL) === 0 || ZIP_DOWNLOAD_URL === false;
105        $this->tpl_zip_function_not_exists = !function_exists('zip_open');
106        $this->tpl_skip_update_csv = $this->tpl_zip_download_url_empty || $this->tpl_zip_function_not_exists;
107
108        if ($this->exec) {
109            if (!empty($this->arrErr)) {
110                trigger_error('', E_USER_ERROR);
111            }
112            switch ($this->tpl_mode) {
113                // 自動登録
114                case 'auto':
115                    $this->lfAutoCommitZip();
116                    break;
117                // DB手動登録
118                case 'manual':
119                    $this->insertMtbZip($this->arrForm['startRowNum']);
120                    break;
121            }
122            SC_Response_Ex::actionExit();
123        }
124
125        switch ($this->tpl_mode) {
126            // 削除
127            case 'delete':
128                $this->lfDeleteZip();
129
130                // 進捗・完了画面を表示しない
131                $this->tpl_mode = null;
132                break;
133
134            // 郵便番号CSV更新
135            case 'update_csv';
136                $this->lfDownloadZipFileFromJp();
137                $this->lfExtractZipFile();
138
139                // 進捗・完了画面を表示しない
140                $this->tpl_mode = null;
141                break;
142
143            // 自動登録時の郵便番号CSV更新
144            // XXX iframe内にエラー表示しない様、ここでlfDownloadZipFileFromJp()を呼ぶ。
145            case 'auto';
146                if (!$this->tpl_skip_update_csv) {
147                    $this->lfDownloadZipFileFromJp();
148                    $this->lfExtractZipFile();
149                }
150                break;
151        }
152
153        $this->tpl_line = $this->countZipCsv();
154        $this->tpl_count_mtb_zip = $this->countMtbZip();
155        $this->tpl_csv_datetime = $this->lfGetCsvDatetime();
156        // XXX PHP4 を切捨てたら、ダウンロードの必要性チェックなども行いたい
157        // $arrHeader = get_headers(ZIP_DOWNLOAD_URL, 1);
158
159    }
160
161    /**
162     * デストラクタ.
163     *
164     * @return void
165     */
166    function destroy()
167    {
168        parent::destroy();
169    }
170
171    function lfAutoCommitZip()
172    {
173        $objQuery =& SC_Query_Ex::getSingletonInstance();
174
175        // DB更新
176        $objQuery->begin();
177        $this->lfDeleteZip();
178        $this->insertMtbZip();
179        $objQuery->commit();
180    }
181
182    /**
183     * テーブルデータと UTF-8 変換済みの郵便番号 CSV を削除
184     *
185     * @return void
186     */
187    function lfDeleteZip()
188    {
189        $objQuery =& SC_Query_Ex::getSingletonInstance();
190
191        // DB
192        $objQuery->delete('mtb_zip');
193
194        // UTF-8 変換済みの郵便番号 CSV
195        unlink(ZIP_CSV_UTF8_REALFILE);
196    }
197
198    /**
199     * パラメーター情報の初期化
200     *
201     * @return void
202     */
203    function lfInitParam($tpl_mode, &$objFormParam)
204    {
205        if ($tpl_mode == 'manual') {
206            $objFormParam->addParam('開始行', 'startRowNum', INT_LEN, 'n', array('EXIST_CHECK', 'MAX_LENGTH_CHECK', 'NUM_CHECK'));
207        }
208    }
209
210    /**
211     * DB登録
212     *
213     * @return void
214     */
215    function insertMtbZip($start = 1)
216    {
217        $objQuery =& SC_Query_Ex::getSingletonInstance();
218
219        $img_path = USER_URL . USER_PACKAGE_DIR . 'admin/img/basis/'; // 画像パスは admin 固定
220
221        ?>
222        <html xmlns='http://www.w3.org/1999/xhtml' lang='ja' xml:lang='ja'>
223        <head>
224            <meta http-equiv='Content-Type' content='text/html; charset=<?php echo CHAR_CODE ?>' />
225        </head>
226        <body>
227        <p>DB 登録進捗状況</p>
228        <div style='background-color: #494E5F;'>
229        <?php
230        // 一部のIEは256バイト以上受け取ってから表示を開始する。
231        SC_Utils_Ex::sfFlush(true);
232
233        echo '<img src="' . $img_path . 'zip_install_progress.gif"><br />';
234        echo '<img src="' . $img_path . 'space_w.gif">';
235        SC_Utils_Ex::sfFlush();
236
237        // 画像を一個表示する件数を求める。
238        $line_all = $this->countZipCsv();
239        $disp_line = intval($line_all / IMAGE_MAX);
240
241        /** 現在行(CSV形式。空行は除く。) */
242        $cntCurrentLine = 0;
243        /** 挿入した行数 */
244        $cntInsert = 0;
245        $img_cnt = 0;
246
247        $fp = $this->openZipCsv();
248        while (!feof($fp)) {
249            $arrCSV = fgetcsv($fp, ZIP_CSV_LINE_MAX);
250            if (empty($arrCSV)) continue;
251            $cntCurrentLine++;
252            if ($cntCurrentLine >= $start) {
253                $sqlval = array();
254                $sqlval['zip_id'] = $cntCurrentLine;
255                $sqlval['zipcode'] = $arrCSV[2];
256                $sqlval['state'] = $arrCSV[6];
257                $sqlval['city'] = $arrCSV[7];
258                $sqlval['town'] = $arrCSV[8];
259                $objQuery->insert('mtb_zip', $sqlval);
260                $cntInsert++;
261            }
262
263            // $disp_line件ごとに進捗表示する
264            if ($cntCurrentLine % $disp_line == 0 && $img_cnt < IMAGE_MAX) {
265                echo '<img src="' . $img_path . 'graph_1_w.gif">';
266                SC_Utils_Ex::sfFlush();
267                $img_cnt++;
268            }
269            SC_Utils_Ex::extendTimeOut();
270        }
271        fclose($fp);
272
273        echo '<img src="' . $img_path . 'space_w.gif">';
274
275        ?>
276        </div>
277        <script type='text/javascript' language='javascript'>
278            <!--
279                // 完了画面
280                function complete()
281                {
282                    document.open('text/html','replace');
283                    document.clear();
284                    document.write('<p>完了しました。<br />');
285                    document.write("<?php echo $cntInsert ?> 件を追加しました。</p>");
286                    document.write("<p><a href='?' target='_top'>戻る</a></p>");
287                    document.close();
288                }
289                // コンテンツを削除するため、タイムアウトで呼び出し。
290                setTimeout('complete()', 0);
291            // -->
292        </script>
293        </body>
294        </html>
295        <?php
296    }
297
298    function openZipCsv()
299    {
300        $this->convertZipCsv();
301        $fp = fopen(ZIP_CSV_UTF8_REALFILE, 'r');
302        if (!$fp) {
303            trigger_error(ZIP_CSV_UTF8_REALFILE . ' の読み込みに失敗しました。', E_USER_ERROR);
304        }
305
306        return $fp;
307    }
308
309    function convertZipCsv()
310    {
311        if (file_exists(ZIP_CSV_UTF8_REALFILE)) return;
312
313        $fpr = fopen(ZIP_CSV_REALFILE, 'r');
314        if (!$fpr) {
315            trigger_error(ZIP_CSV_REALFILE . ' の読み込みに失敗しました。', E_USER_ERROR);
316        }
317
318        $fpw = fopen(ZIP_CSV_UTF8_REALFILE, 'w');
319        if (!$fpw) {
320            trigger_error(ZIP_CSV_UTF8_REALFILE . ' を開けません。', E_USER_ERROR);
321        }
322
323        while (!feof($fpr)) {
324            fwrite($fpw, mb_convert_encoding(fgets($fpr, ZIP_CSV_LINE_MAX), CHAR_CODE, 'sjis-win'));
325        }
326
327        fclose($fpw);
328        fclose($fpr);
329    }
330
331    function countMtbZip()
332    {
333        $objQuery =& SC_Query_Ex::getSingletonInstance();
334
335        return $objQuery->count('mtb_zip');
336    }
337
338    function countZipCsv()
339    {
340        $line = 0;
341        $fp = $this->openZipCsv();
342
343        // CSVの行数を数える
344        while (!feof($fp)) {
345            /*
346            // 正確にカウントする
347            $tmp = fgetcsv($fp, ZIP_CSV_LINE_MAX);
348            */
349            // 推測でカウントする
350            $tmp = fgets($fp, ZIP_CSV_LINE_MAX);
351            if (empty($tmp)) continue;
352            $line++;
353        }
354        fclose($fp);
355
356        return $line;
357    }
358
359    /**
360     * 日本郵便から郵便番号 CSV の ZIP アーカイブファイルを取得
361     *
362     * @return void
363     */
364    function lfDownloadZipFileFromJp()
365    {
366        // Proxy経由を可能とする。
367        // TODO Proxyの設定は「data/module/HTTP/Request.php」内の「function HTTP_Request」へ記述する。いずれは、外部設定としたい。
368        $req = new HTTP_Request();
369
370        $req->setURL(ZIP_DOWNLOAD_URL);
371
372        // 郵便番号CSVをdownloadする。
373        $res = $req->sendRequest();
374        if (!$res || strlen($res) > 1) {
375            trigger_error(ZIP_DOWNLOAD_URL . ' の取得に失敗しました。', E_USER_ERROR);
376        }
377
378        // 郵便番号CSV(zip file)を保存する。
379        $fp = fopen($this->zip_csv_temp_realfile, 'w');
380        if (!$fp) {
381            trigger_error($this->zip_csv_temp_realfile . ' を開けません。', E_USER_ERROR);
382        }
383        $res = fwrite($fp, $req->getResponseBody());
384        if (!$res) {
385            trigger_error($this->zip_csv_temp_realfile . ' への書き込みに失敗しました。', E_USER_ERROR);
386        }
387    }
388
389    /**
390     * ZIP アーカイブファイルを展開して、郵便番号 CSV を上書き
391     *
392     * @return void
393     */
394    function lfExtractZipFile()
395    {
396        $zip = zip_open($this->zip_csv_temp_realfile);
397        if (!is_resource($zip)) {
398            trigger_error($this->zip_csv_temp_realfile . ' をオープンできません。', E_USER_ERROR);
399        }
400
401        do {
402            $entry = zip_read($zip);
403        } while ($entry && zip_entry_name($entry) != 'KEN_ALL.CSV');
404
405        if (!$entry) {
406            trigger_error($this->zip_csv_temp_realfile . ' に対象ファイルが見つかりません。', E_USER_ERROR);
407        }
408
409        // 展開時の破損を考慮し、別名で一旦展開する。
410        $tmp_csv_realfile = ZIP_CSV_REALFILE . '.tmp';
411
412        $res = zip_entry_open($zip, $entry, 'rb');
413        if (!$res) {
414            trigger_error($this->zip_csv_temp_realfile . ' の展開に失敗しました。', E_USER_ERROR);
415        }
416
417        $fp = fopen($tmp_csv_realfile, 'w');
418        if (!$fp) {
419            trigger_error($tmp_csv_realfile . ' を開けません。', E_USER_ERROR);
420        }
421
422        $res = fwrite($fp, zip_entry_read($entry, zip_entry_filesize($entry)));
423        if ($res === FALSE) {
424            trigger_error($tmp_csv_realfile . ' の書き込みに失敗しました。', E_USER_ERROR);
425        }
426
427        fclose($fp);
428        zip_close($zip);
429
430        // CSV 削除
431        $res = unlink(ZIP_CSV_REALFILE);
432        if (!$res) {
433            trigger_error(ZIP_CSV_REALFILE . ' を削除できません。', E_USER_ERROR);
434        }
435
436        // CSV ファイル名変更
437        $res = rename($tmp_csv_realfile, ZIP_CSV_REALFILE);
438        if (!$res) {
439            trigger_error('ファイル名を変更できません。: ' . $tmp_csv_realfile . ' -> ' . ZIP_CSV_REALFILE, E_USER_ERROR);
440        }
441    }
442
443    /**
444     * CSV の更新日時を取得
445     *
446     * @return string CSV の更新日時 (整形済みテキスト)
447     */
448    function lfGetCsvDatetime()
449    {
450        return date('Y/m/d H:i:s', filemtime(ZIP_CSV_REALFILE));
451    }
452}
Note: See TracBrowser for help on using the repository browser.