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

Revision 22567, 13.8 KB checked in by shutta, 11 years ago (diff)

#2043 (typo修正・ソース整形・ソースコメントの改善 for 2.12.4)
Zend Framework PHP 標準コーディング規約のコーディングスタイルへ準拠。
classおよびfunctionの開始波括弧「{」のスタイルを修正。

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