source: branches/version-2_13-dev/data/class/util/SC_Utils.php @ 23678

Revision 23678, 64.5 KB checked in by Seasoft, 9 years ago (diff)

#2648 (環境により SC_Utils::searchInstallerPath で無限ループ)

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • 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-2014 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/**
25 * 各種ユーティリティクラス.
26 *
27 * 主に static 参照するユーティリティ系の関数群
28 *
29 * :XXX: 内部でインスタンスを生成している関数は, Helper クラスへ移動するべき...
30 *
31 * @package Util
32 * @author LOCKON CO.,LTD.
33 * @version $Id:SC_Utils.php 15532 2007-08-31 14:39:46Z nanasess $
34 */
35class SC_Utils
36{
37    // インストール初期処理
38    public static function sfInitInstall()
39    {
40        if (
41            !defined('ECCUBE_INSTALL')              // インストール済みが定義されていない。
42            && !GC_Utils_Ex::isInstallFunction()    // インストール中でない。
43        ) {
44            $install_url = SC_Utils_Ex::getInstallerPath();
45            header('Location: ' . $install_url);
46            exit;
47        }
48        $path = HTML_REALDIR . 'install/' . DIR_INDEX_FILE;
49        if (file_exists($path)) {
50            SC_Utils_Ex::sfErrorHeader('&gt;&gt; /install/' . DIR_INDEX_FILE . ' は、インストール完了後にファイルを削除してください。');
51        }
52    }
53
54    /**
55     * インストーラーの URL を返す
56     *
57     * @return string インストーラーの URL
58     */
59    public static function getInstallerPath()
60    {
61        $netUrl = new Net_URL();
62
63        $installer = 'install/' . DIR_INDEX_PATH;
64        // XXX メソッド名は add で始まるが、実際には置換を行う
65        $netUrl->addRawQueryString('');
66        $current_url = $netUrl->getURL();
67        $current_url = dirname($current_url) . '/';
68        // XXX 先頭の / を含まない。
69        $urlpath = substr($_SERVER['SCRIPT_FILENAME'], strlen(HTML_REALDIR));
70        // / を 0、/foo/ を 1 としたディレクトリー階層数
71        $dir_level = substr_count($urlpath, '/');
72        $installer_url .= str_repeat('../', $dir_level) . $installer;
73
74        return $installer_url;
75    }
76
77    /**
78     * 相対パスで記述された URL から絶対パスの URL を取得する.
79     *
80     * この関数は, http(s):// から始まる URL を解析し, 相対パスで記述されていた
81     * 場合, 絶対パスに変換して返す
82     *
83     * 例)
84     * http://www.example.jp/aaa/../index.php
85     * ↓
86     * http://www.example.jp/index.php
87     *
88     * @param  string $url http(s):// から始まる URL
89     * @return string $url を絶対パスに変換した URL
90     */
91    public static function getRealURL($url)
92    {
93        $parse = parse_url($url);
94        $tmp = explode('/', $parse['path']);
95        $results = array();
96        foreach ($tmp as $v) {
97            if ($v == '' || $v == '.') {
98                // queit.
99            } elseif ($v == '..') {
100                array_pop($results);
101            } else {
102                array_push($results, $v);
103            }
104        }
105
106        $path = join('/', $results);
107
108        return $parse['scheme'] . '://' . $parse['host'] . ':' . $parse['port'] .'/' . $path;
109    }
110
111    // 装飾付きエラーメッセージの表示
112
113    /**
114     * @param string $mess
115     */
116    public static function sfErrorHeader($mess, $print = false)
117    {
118        global $GLOBAL_ERR;
119        $GLOBAL_ERR.= '<div id="errorHeader">';
120        $GLOBAL_ERR.= $mess;
121        $GLOBAL_ERR.= '</div>';
122        if ($print) {
123            echo $GLOBAL_ERR;
124        }
125    }
126
127    /* エラーページの表示 */
128    public static function sfDispError($type)
129    {
130        require_once CLASS_EX_REALDIR . 'page_extends/error/LC_Page_Error_DispError_Ex.php';
131
132        $objPage = new LC_Page_Error_DispError_Ex();
133        $objPage->init();
134        $objPage->type = $type;
135        $objPage->process();
136        exit;
137    }
138
139    /* サイトエラーページの表示 */
140    public static function sfDispSiteError($type, $objSiteSess = '', $return_top = false, $err_msg = '')
141    {
142        require_once CLASS_EX_REALDIR . 'page_extends/error/LC_Page_Error_Ex.php';
143
144        $objPage = new LC_Page_Error_Ex();
145        $objPage->init();
146        $objPage->type = $type;
147        $objPage->objSiteSess = $objSiteSess;
148        $objPage->return_top = $return_top;
149        $objPage->err_msg = $err_msg;
150        $objPage->is_mobile = SC_Display_Ex::detectDevice() == DEVICE_TYPE_MOBILE;
151        $objPage->process();
152        exit;
153    }
154
155    /**
156     * 前方互換用
157     *
158     * @deprecated 2.12.0 trigger_error($debugMsg, E_USER_ERROR) を使用すること
159     */
160    public function sfDispException($debugMsg = null)
161    {
162        trigger_error('前方互換用メソッドが使用されました。', E_USER_WARNING);
163        trigger_error($debugMsg, E_USER_ERROR);
164    }
165
166    /**
167     * 認証の可否判定
168     *
169     * @param SC_Session $objSess
170     * @param bool $disp_error
171     * @return bool
172     */
173    public static function sfIsSuccess(SC_Session $objSess, $disp_error = true)
174    {
175        $ret = $objSess->IsSuccess();
176        if ($ret != SUCCESS) {
177            if ($disp_error) {
178                // エラーページの表示
179                SC_Utils_Ex::sfDispError($ret);
180            }
181
182            return false;
183        }
184        // リファラーチェック(CSRFの暫定的な対策)
185        // 「リファラ無」 の場合はスルー
186        // 「リファラ有」 かつ 「管理画面からの遷移でない」 場合にエラー画面を表示する
187        if (empty($_SERVER['HTTP_REFERER'])) {
188            // TODO 警告表示させる?
189            // sfErrorHeader('>> referrerが無効になっています。');
190        } else {
191            $domain  = SC_Utils_Ex::sfIsHTTPS() ? HTTPS_URL : HTTP_URL;
192            $pattern = sprintf('|^%s.*|', $domain);
193            $referer = $_SERVER['HTTP_REFERER'];
194
195            // 管理画面から以外の遷移の場合はエラー画面を表示
196            if (!preg_match($pattern, $referer)) {
197                if ($disp_error) SC_Utils_Ex::sfDispError(INVALID_MOVE_ERRORR);
198                return false;
199            }
200        }
201
202        return true;
203    }
204
205    /**
206     * 文字列をアスタリスクへ変換する.
207     *
208     * @param  string $passlen 変換する文字列
209     * @return string アスタリスクへ変換した文字列
210     */
211    public static function sfPassLen($passlen)
212    {
213        $ret = '';
214        for ($i=0;$i<$passlen;true) {
215            $ret.='*';
216            $i++;
217        }
218
219        return $ret;
220    }
221
222    /**
223     * HTTPSかどうかを判定
224     *
225     * @return bool
226     */
227    public static function sfIsHTTPS()
228    {
229        // HTTPS時には$_SERVER['HTTPS']には空でない値が入る
230        // $_SERVER['HTTPS'] != 'off' はIIS用
231        if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
232            return true;
233        } else {
234            return false;
235        }
236    }
237
238    /**
239     *  正規の遷移がされているかを判定
240     *  前画面でuniqidを埋め込んでおく必要がある
241     *
242     *  使用されていない.
243     *
244     *  @param  obj  SC_Session, SC_SiteSession
245     *  @return bool
246     */
247    public function sfIsValidTransition($objSess)
248    {
249        // 前画面からPOSTされるuniqidが正しいものかどうかをチェック
250        $uniqid = $objSess->getUniqId();
251        if (!empty($_POST['uniqid']) && ($_POST['uniqid'] === $uniqid)) {
252            return true;
253        } else {
254            return false;
255        }
256    }
257
258    /* DB用日付文字列取得 */
259    public static function sfGetTimestamp($year, $month, $day, $last = false)
260    {
261        if ($year != '' && $month != '' && $day != '') {
262            if ($last) {
263                $time = '23:59:59';
264            } else {
265                $time = '00:00:00';
266            }
267            $date = $year.'-'.$month.'-'.$day.' '.$time;
268        } else {
269            $date = '';
270        }
271
272        return $date;
273    }
274
275    /* DB用日付日時文字列取得 */
276
277    /**
278     * @param string $month
279     * @param string $day
280     * @param string $hour
281     * @param string $minutes
282     */
283    public static function sfGetTimestampistime($year, $month, $day, $hour, $minutes, $last = false)
284    {
285        if ($year != '' && $month != '' && $day != '' && $hour != '' && $minutes != '') {
286            if ($last) {
287                $time = $hour.':'.$minutes.':59';
288            } else {
289                $time = $hour.':'.$minutes.':00';
290            }
291            $date = $year.'-'.$month.'-'.$day.' '.$time;
292        } else {
293            $date = '';
294        }
295
296        return $date;
297    }
298
299    /**
300     *  INT型の数値チェック
301     *  ・FIXME: マイナス値の扱いが不明確
302     *  ・XXX: INT_LENには収まるが、INT型の範囲を超えるケースに対応できないのでは?
303     *
304     *  @param mixed $value
305     *  @return bool
306     */
307    public static function sfIsInt($value)
308    {
309        if (strlen($value) >= 1 && strlen($value) <= INT_LEN && is_numeric($value)) {
310            return true;
311        }
312
313        return false;
314    }
315
316    /**
317     * 桁が0で埋められているかを判定する
318     *
319     * @param  string  $value 検査対象
320     * @return boolean 0で埋められている
321     */
322    public static function sfIsZeroFilling($value)
323    {
324        if (strlen($value) > 1 && $value{0} === '0')
325
326            return true;
327
328        return false;
329    }
330
331    /**
332     * @param string $data
333     */
334    public static function sfGetCSVData($data, $prefix = '')
335    {
336        if ($prefix == '') {
337            $dir_name = SC_Utils_Ex::sfUpDirName();
338            $file_name = $dir_name . date('ymdHis') .'.csv';
339        } else {
340            $file_name = $prefix . date('ymdHis') .'.csv';
341        }
342
343        if (mb_internal_encoding() == CHAR_CODE) {
344            $data = mb_convert_encoding($data, 'SJIS-Win', CHAR_CODE);
345        }
346
347        /* データを出力 */
348
349        return array($file_name, $data);
350    }
351
352    /* 1階層上のディレクトリ名を取得する */
353    public static function sfUpDirName()
354    {
355        $path = $_SERVER['SCRIPT_NAME'];
356        $arrVal = explode('/', $path);
357        $cnt = count($arrVal);
358
359        return $arrVal[($cnt - 2)];
360    }
361
362    // チェックボックスの値をマージ
363    /**
364     * @deprecated
365     */
366    public function sfMergeCBValue($keyname, $max)
367    {
368        $conv = '';
369        $cnt = 1;
370        for ($cnt = 1; $cnt <= $max; $cnt++) {
371            if ($_POST[$keyname . $cnt] == '1') {
372                $conv.= '1';
373            } else {
374                $conv.= '0';
375            }
376        }
377
378        return $conv;
379    }
380
381    // html_checkboxesの値をマージして2進数形式に変更する。
382    /**
383     * @deprecated
384     */
385    public function sfMergeCheckBoxes($array, $max)
386    {
387        $ret = '';
388        $arrTmp = array();
389        if (is_array($array)) {
390            foreach ($array as $val) {
391                $arrTmp[$val] = '1';
392            }
393        }
394        for ($i = 1; $i <= $max; $i++) {
395            if (isset($arrTmp[$i]) && $arrTmp[$i] == '1') {
396                $ret.= '1';
397            } else {
398                $ret.= '0';
399            }
400        }
401
402        return $ret;
403    }
404
405    // html_checkboxesの値をマージして「-」でつなげる。
406    /**
407     * @deprecated
408     */
409    public function sfMergeParamCheckBoxes($array)
410    {
411        $ret = '';
412        if (is_array($array)) {
413            foreach ($array as $val) {
414                if ($ret != '') {
415                    $ret.= "-$val";
416                } else {
417                    $ret = $val;
418                }
419            }
420        } else {
421            $ret = $array;
422        }
423
424        return $ret;
425    }
426
427    // html_checkboxesの値をマージしてSQL検索用に変更する。
428    /**
429     * @deprecated
430     */
431    public function sfSearchCheckBoxes($array)
432    {
433        $max = max($array);
434        $ret = '';
435        for ($i = 1; $i <= $max; $i++) {
436            $ret .= in_array($i, $array) ? '1' : '_';
437        }
438        if (strlen($ret) != 0) {
439            $ret .= '%';
440        }
441
442        return $ret;
443    }
444
445    // 2進数形式の値をhtml_checkboxes対応の値に切り替える
446    /**
447     * @deprecated
448     */
449    public function sfSplitCheckBoxes($val)
450    {
451        $arrRet = array();
452        $len = strlen($val);
453        for ($i = 0; $i < $len; $i++) {
454            if (substr($val, $i, 1) == '1') {
455                $arrRet[] = ($i + 1);
456            }
457        }
458
459        return $arrRet;
460    }
461
462    // チェックボックスの値をマージ
463    /**
464     * @deprecated
465     */
466    public function sfMergeCBSearchValue($keyname, $max)
467    {
468        $conv = '';
469        $cnt = 1;
470        for ($cnt = 1; $cnt <= $max; $cnt++) {
471            if ($_POST[$keyname . $cnt] == '1') {
472                $conv.= '1';
473            } else {
474                $conv.= '_';
475            }
476        }
477
478        return $conv;
479    }
480
481    // チェックボックスの値を分解
482    /**
483     * @deprecated
484     */
485    public function sfSplitCBValue($val, $keyname = '')
486    {
487        $arr = array();
488        $len = strlen($val);
489        $no = 1;
490        for ($cnt = 0; $cnt < $len; $cnt++) {
491            if ($keyname != '') {
492                $arr[$keyname . $no] = substr($val, $cnt, 1);
493            } else {
494                $arr[] = substr($val, $cnt, 1);
495            }
496            $no++;
497        }
498
499        return $arr;
500    }
501
502    // キーと値をセットした配列を取得
503
504    /**
505     * @param string $valname
506     * @param string $keyname
507     */
508    public static function sfArrKeyValue($arrList, $keyname, $valname, $len_max = '', $keysize = '')
509    {
510        $arrRet = array();
511        $max = count($arrList);
512
513        if ($len_max != '' && $max > $len_max) {
514            $max = $len_max;
515        }
516
517        for ($cnt = 0; $cnt < $max; $cnt++) {
518            if ($keysize != '') {
519                $key = SC_Utils_Ex::sfCutString($arrList[$cnt][$keyname], $keysize);
520            } else {
521                $key = $arrList[$cnt][$keyname];
522            }
523            $val = $arrList[$cnt][$valname];
524
525            if (!isset($arrRet[$key])) {
526                $arrRet[$key] = $val;
527            }
528
529        }
530
531        return $arrRet;
532    }
533
534    /**
535     * キーと値をセットした配列を取得(値が複数の場合)
536     * 使用されていない
537     */
538    public function sfArrKeyValues($arrList, $keyname, $valname, $len_max = '', $keysize = '', $connect = '')
539    {
540        $max = count($arrList);
541
542        if ($len_max != '' && $max > $len_max) {
543            $max = $len_max;
544        }
545
546        $keyValues = array();
547        for ($cnt = 0; $cnt < $max; $cnt++) {
548            if ($keysize != '') {
549                $key = SC_Utils_Ex::sfCutString($arrList[$cnt][$keyname], $keysize);
550            } else {
551                $key = $arrList[$cnt][$keyname];
552            }
553            $val = $arrList[$cnt][$valname];
554
555            if ($connect != '') {
556                $keyValues[$key].= "$val".$connect;
557            } else {
558                $keyValues[$key][] = $val;
559            }
560        }
561
562        return $keyValues;
563    }
564
565    // 配列の値をカンマ区切りで返す。
566    public static function sfGetCommaList($array, $space=true, $arrPop = array())
567    {
568        if (count($array) > 0) {
569            $line = '';
570            foreach ($array as $val) {
571                if (!in_array($val, $arrPop)) {
572                    if ($space) {
573                        $line .= $val . ', ';
574                    } else {
575                        $line .= $val . ',';
576                    }
577                }
578            }
579            if ($space) {
580                $line = preg_replace("/, $/", '', $line);
581            } else {
582                $line = preg_replace("/,$/", '', $line);
583            }
584
585            return $line;
586        } else {
587            return false;
588        }
589
590    }
591
592    /* 配列の要素をCSVフォーマットで出力する。*/
593    public static function sfGetCSVList($array)
594    {
595        $line = '';
596        if (count($array) > 0) {
597            foreach ($array as $val) {
598                $val = mb_convert_encoding($val, CHAR_CODE, CHAR_CODE);
599                $line .= '"' .$val. '",';
600            }
601            $line = preg_replace("/,$/", "\r\n", $line);
602        } else {
603            return false;
604        }
605
606        return $line;
607    }
608
609    /**
610     *    check_set_term
611     *    年月日に別れた2つの期間の妥当性をチェックし、整合性と期間を返す
612     * 引数 (開始年,開始月,開始日,終了年,終了月,終了日)
613     * 戻値 array(1,2,3)
614     *          1.開始年月日 (YYYY/MM/DD 000000)
615     *            2.終了年月日 (YYYY/MM/DD 235959)
616     *            3.エラー (0 = OK, 1 = NG)
617     *
618     * 使用されていない
619     */
620    public function sfCheckSetTerm($start_year, $start_month, $start_day, $end_year, $end_month, $end_day)
621    {
622        // 期間指定
623        $error = 0;
624        if ($start_month || $start_day || $start_year) {
625            if (! checkdate($start_month, $start_day, $start_year)) $error = 1;
626        } else {
627            $error = 1;
628        }
629        if ($end_month || $end_day || $end_year) {
630            if (! checkdate($end_month, $end_day, $end_year)) $error = 2;
631        }
632        if (! $error) {
633            $date1 = $start_year .'/'.sprintf('%02d', $start_month) .'/'.sprintf('%02d', $start_day) .' 000000';
634            $date2 = $end_year   .'/'.sprintf('%02d', $end_month)   .'/'.sprintf('%02d', $end_day)   .' 235959';
635            if ($date1 > $date2) $error = 3;
636        } else {
637            $error = 1;
638        }
639
640        return array($date1, $date2, $error);
641    }
642
643    // エラー箇所の背景色を変更するためのfunction SC_Viewで読み込む
644    public function sfSetErrorStyle()
645    {
646        return 'style="background-color:'.ERR_COLOR.'"';
647    }
648
649    // 一致した値のキー名を取得
650    public function sfSearchKey($array, $word, $default)
651    {
652        foreach ($array as $key => $val) {
653            if ($val == $word) {
654                return $key;
655            }
656        }
657
658        return $default;
659    }
660
661    public function sfGetErrorColor($val)
662    {
663        if ($val != '') {
664            return 'background-color:' . ERR_COLOR;
665        }
666
667        return '';
668    }
669
670    public function sfGetEnabled($val)
671    {
672        if (! $val) {
673            return ' disabled="disabled"';
674        }
675
676        return '';
677    }
678
679    public function sfGetChecked($param, $value)
680    {
681        if ((string) $param === (string) $value) {
682            return 'checked="checked"';
683        }
684
685        return '';
686    }
687
688    public function sfTrim($str)
689    {
690        $ret = preg_replace("/^[  \n\r]*/u", '', $str);
691        $ret = preg_replace("/[  \n\r]*$/u", '', $ret);
692
693        return $ret;
694    }
695
696    /**
697     * 税金額を返す
698     *
699     * ・店舗基本情報に基づいた計算は SC_Helper_DB::sfTax() を使用する
700     *
701     * @param integer $price 計算対象の金額
702     * @param integer $tax   税率(%単位)
703     *     XXX integer のみか不明
704     * @param  integer $tax_rule 端数処理
705     * @return double 税金額
706     */
707    public static function sfTax($price, $tax, $tax_rule)
708    {
709        $real_tax = $tax / 100;
710        $ret = $price * $real_tax;
711        $ret = SC_Helper_TaxRule_Ex::roundByCalcRule($ret, $tax_rule);
712
713        return $ret;
714    }
715
716    /**
717     * 税金付与した金額を返す
718     *
719     * ・店舗基本情報に基づいた計算は SC_Helper_DB::sfTax() を使用する
720     *
721     * @param integer $price 計算対象の金額
722     * @param integer $tax   税率(%単位)
723     *     XXX integer のみか不明
724     * @param  integer $tax_rule 端数処理
725     * @return double 税金付与した金額
726     */
727    public static function sfCalcIncTax($price, $tax, $tax_rule)
728    {
729        return $price + SC_Utils_Ex::sfTax($price, $tax, $tax_rule);
730    }
731
732    /**
733     * 桁数を指定して四捨五入
734     *
735     * 使用されていない
736     */
737    public function sfRound($value, $pow = 0)
738    {
739        $adjust = pow(10, $pow-1);
740
741        // 整数且つ0でなければ桁数指定を行う
742        if (SC_Utils_Ex::sfIsInt($adjust) and $pow > 1) {
743            $ret = (round($value * $adjust)/$adjust);
744        }
745
746        $ret = round($ret);
747
748        return $ret;
749    }
750
751    /**
752     * ポイント付与
753     * $product_id が使われていない。
754     * @param  int   $price
755     * @param  float $point_rate
756     * @param  int   $rule
757     * @return double
758     */
759    public static function sfPrePoint($price, $point_rate, $rule = POINT_RULE)
760    {
761        $real_point = $point_rate / 100;
762        $ret = $price * $real_point;
763        $ret = SC_Helper_TaxRule_Ex::roundByCalcRule($ret, $rule);
764
765        return $ret;
766    }
767
768    /* 規格分類の件数取得 */
769    public static function sfGetClassCatCount()
770    {
771        $sql = 'select count(dtb_class.class_id) as count, dtb_class.class_id ';
772        $sql.= 'from dtb_class inner join dtb_classcategory on dtb_class.class_id = dtb_classcategory.class_id ';
773        $sql.= 'where dtb_class.del_flg = 0 AND dtb_classcategory.del_flg = 0 ';
774        $sql.= 'group by dtb_class.class_id, dtb_class.name';
775        $objQuery =& SC_Query_Ex::getSingletonInstance();
776        $arrList = $objQuery->getAll($sql);
777        // キーと値をセットした配列を取得
778        $arrRet = SC_Utils_Ex::sfArrKeyValue($arrList, 'class_id', 'count');
779
780        return $arrRet;
781    }
782
783    /**
784     * 商品IDとカテゴリIDから商品規格IDを取得する
785     * @param  int $product_id
786     * @param  int $classcategory_id1 デフォルト値0
787     * @param  int $classcategory_id2 デフォルト値0
788     * @return int
789     */
790    public static function sfGetProductClassId($product_id, $classcategory_id1=0, $classcategory_id2=0)
791    {
792        $where = 'product_id = ? AND classcategory_id1 = ? AND classcategory_id2 = ?';
793        if (!$classcategory_id1) { //NULLが入ってきた場合への対策
794          $classcategory_id1 = 0;
795        }
796        if (!$classcategory_id2) {
797          $classcategory_id2 = 0;
798        }
799        $objQuery =& SC_Query_Ex::getSingletonInstance();
800        $ret = $objQuery->get('product_class_id', 'dtb_products_class', $where, Array($product_id, $classcategory_id1, $classcategory_id2));
801
802        return $ret;
803    }
804
805    /* 文末の「/」をなくす */
806    public static function sfTrimURL($url)
807    {
808        $ret = rtrim($url, '/');
809
810        return $ret;
811    }
812
813    /* DBから取り出した日付の文字列を調整する。*/
814    public function sfDispDBDate($dbdate, $time = true)
815    {
816        list($y, $m, $d, $H, $M) = preg_split('/[- :]/', $dbdate);
817
818        if (strlen($y) > 0 && strlen($m) > 0 && strlen($d) > 0) {
819            if ($time) {
820                $str = sprintf('%04d/%02d/%02d %02d:%02d', $y, $m, $d, $H, $M);
821            } else {
822                $str = sprintf('%04d/%02d/%02d', $y, $m, $d, $H, $M);
823            }
824        } else {
825            $str = '';
826        }
827
828        return $str;
829    }
830
831    /**
832     * 配列をキー名ごとの配列に変更する
833     *
834     * @param array $array
835     * @param bool $isColumnName
836     * @return array
837     */
838    public static function sfSwapArray($array, $isColumnName = true)
839    {
840        $arrRet = array();
841        foreach ($array as $key1 => $arr1) {
842            if (!is_array($arr1)) continue 1;
843            $index = 0;
844            foreach ($arr1 as $key2 => $val) {
845                if ($isColumnName) {
846                    $arrRet[$key2][$key1] = $val;
847                } else {
848                    $arrRet[$index++][$key1] = $val;
849                }
850            }
851        }
852
853        return $arrRet;
854    }
855
856    /**
857     * 連想配列から新たな配列を生成して返す.
858     *
859     * $requires が指定された場合, $requires に含まれるキーの値のみを返す.
860     *
861     * @param array $hash 連想配列
862     * @param array $requires 必須キーの配列
863     * @return array 連想配列の値のみの配列
864     */
865    public static function getHash2Array($hash, $requires = array())
866    {
867        $array = array();
868        $i = 0;
869        foreach ($hash as $key => $val) {
870            if (!empty($requires)) {
871                if (in_array($key, $requires)) {
872                    $array[$i] = $val;
873                    $i++;
874                }
875            } else {
876                $array[$i] = $val;
877                $i++;
878            }
879        }
880
881        return $array;
882    }
883
884    /* かけ算をする(Smarty用) */
885    public function sfMultiply($num1, $num2)
886    {
887        return $num1 * $num2;
888    }
889
890    /**
891     * 加算ポイントの計算
892     *
893     * ・店舗基本情報に基づいた計算は SC_Helper_DB::sfGetAddPoint() を使用する
894     *
895     * @param  integer $totalpoint
896     * @param  integer $use_point
897     * @param  integer $point_rate
898     * @return integer 加算ポイント
899     */
900    public static function sfGetAddPoint($totalpoint, $use_point, $point_rate)
901    {
902        // 購入商品の合計ポイントから利用したポイントのポイント換算価値を引く方式
903        $add_point = $totalpoint - intval($use_point * ($point_rate / 100));
904
905        if ($add_point < 0) {
906            $add_point = '0';
907        }
908
909        return $add_point;
910    }
911
912    /* 一意かつ予測されにくいID */
913    public static function sfGetUniqRandomId($head = '')
914    {
915        // 予測されないようにランダム文字列を付与する。
916        $random = GC_Utils_Ex::gfMakePassword(8);
917        // 同一ホスト内で一意なIDを生成
918        $id = uniqid($head);
919
920        return $id . $random;
921    }
922
923    /**
924     * 二回以上繰り返されているスラッシュ[/]を一つに変換する。
925     *
926     * @param string $istr
927     * @return string
928     */
929    public static function sfRmDupSlash($istr)
930    {
931        if (preg_match('|^http://|', $istr)) {
932            $str = substr($istr, 7);
933            $head = 'http://';
934        } elseif (preg_match('|^https://|', $istr)) {
935            $str = substr($istr, 8);
936            $head = 'https://';
937        } else {
938            $str = $istr;
939            $head = '';
940        }
941        $str = preg_replace('|[/]+|', '/', $str);
942        $ret = $head . $str;
943
944        return $ret;
945    }
946
947    /**
948     * テキストファイルの文字エンコーディングを変換する.
949     *
950     * $filepath に存在するテキストファイルの文字エンコーディングを変換する.
951     * 変換前の文字エンコーディングは, mb_detect_order で設定した順序で自動検出する.
952     * 変換後は, 変換前のファイル名に「enc_」というプレフィクスを付与し,
953     * $out_dir で指定したディレクトリへ出力する
954     *
955     * TODO $filepath のファイルがバイナリだった場合の扱い
956     * TODO fwrite などでのエラーハンドリング
957     *
958     * @access public
959     * @param  string $filepath 変換するテキストファイルのパス
960     * @param  string $enc_type 変換後のファイルエンコーディングの種類を表す文字列
961     * @param  string $out_dir  変換後のファイルを出力するディレクトリを表す文字列
962     * @return string 変換後のテキストファイルのパス
963     */
964    public static function sfEncodeFile($filepath, $enc_type, $out_dir)
965    {
966        $ifp = fopen($filepath, 'r');
967
968        // 正常にファイルオープンした場合
969        if ($ifp !== false) {
970            $basename = basename($filepath);
971            $outpath = $out_dir . 'enc_' . $basename;
972
973            $ofp = fopen($outpath, 'w+');
974
975            while (!feof($ifp)) {
976                $line = fgets($ifp);
977                $line = mb_convert_encoding($line, $enc_type, 'auto');
978                fwrite($ofp, $line);
979            }
980
981            fclose($ofp);
982            fclose($ifp);
983        // ファイルが開けなかった場合はエラーページを表示
984        } else {
985            SC_Utils_Ex::sfDispError('');
986            exit;
987        }
988
989        return $outpath;
990    }
991
992    public function sfCutString($str, $len, $byte = true, $commadisp = true)
993    {
994        if ($byte) {
995            if (strlen($str) > ($len + 2)) {
996                $ret =substr($str, 0, $len);
997                $cut = substr($str, $len);
998            } else {
999                $ret = $str;
1000                $commadisp = false;
1001            }
1002        } else {
1003            if (mb_strlen($str) > ($len + 1)) {
1004                $ret = mb_substr($str, 0, $len);
1005                $cut = mb_substr($str, $len);
1006            } else {
1007                $ret = $str;
1008                $commadisp = false;
1009            }
1010        }
1011
1012        // 絵文字タグの途中で分断されないようにする。
1013        if (isset($cut)) {
1014            // 分割位置より前の最後の [ 以降を取得する。
1015            $head = strrchr($ret, '[');
1016
1017            // 分割位置より後の最初の ] 以前を取得する。
1018            $tail_pos = strpos($cut, ']');
1019            if ($tail_pos !== false) {
1020                $tail = substr($cut, 0, $tail_pos + 1);
1021            }
1022
1023            // 分割位置より前に [、後に ] が見つかった場合は、[ から ] までを
1024            // 接続して絵文字タグ1個分になるかどうかをチェックする。
1025            if ($head !== false && $tail_pos !== false) {
1026                $subject = $head . $tail;
1027                if (preg_match('/^\[emoji:e?\d+\]$/', $subject)) {
1028                    // 絵文字タグが見つかったので削除する。
1029                    $ret = substr($ret, 0, -strlen($head));
1030                }
1031            }
1032        }
1033
1034        if ($commadisp) {
1035            $ret = $ret . '...';
1036        }
1037
1038        return $ret;
1039    }
1040
1041    // 年、月、締め日から、先月の締め日+1、今月の締め日を求める。
1042    public static function sfTermMonth($year, $month, $close_day)
1043    {
1044        $end_year = $year;
1045        $end_month = $month;
1046
1047        // 該当月の末日を求める。
1048        $end_last_day = date('d', mktime(0, 0, 0, $month + 1, 0, $year));
1049
1050        // 月の末日が締め日より少ない場合
1051        if ($end_last_day < $close_day) {
1052            // 締め日を月末日に合わせる
1053            $end_day = $end_last_day;
1054        } else {
1055            $end_day = $close_day;
1056        }
1057
1058        // 前月の取得
1059        $tmp_year = date('Y', mktime(0, 0, 0, $month, 0, $year));
1060        $tmp_month = date('m', mktime(0, 0, 0, $month, 0, $year));
1061        // 前月の末日を求める。
1062        $start_last_day = date('d', mktime(0, 0, 0, $month, 0, $year));
1063
1064        // 前月の末日が締め日より少ない場合
1065        if ($start_last_day < $close_day) {
1066            // 月末日に合わせる
1067            $tmp_day = $start_last_day;
1068        } else {
1069            $tmp_day = $close_day;
1070        }
1071
1072        // 先月の末日の翌日を取得する
1073        $start_year = date('Y', mktime(0, 0, 0, $tmp_month, $tmp_day + 1, $tmp_year));
1074        $start_month = date('m', mktime(0, 0, 0, $tmp_month, $tmp_day + 1, $tmp_year));
1075        $start_day = date('d', mktime(0, 0, 0, $tmp_month, $tmp_day + 1, $tmp_year));
1076
1077        // 日付の作成
1078        $start_date = sprintf('%d/%d/%d', $start_year, $start_month, $start_day);
1079        $end_date = sprintf('%d/%d/%d 23:59:59', $end_year, $end_month, $end_day);
1080
1081        return array($start_date, $end_date);
1082    }
1083
1084    // 再帰的に多段配列を検索して一次元配列(Hidden引渡し用配列)に変換する。
1085    public static function sfMakeHiddenArray($arrSrc, $arrDst = array(), $parent_key = '')
1086    {
1087        if (is_array($arrSrc)) {
1088            foreach ($arrSrc as $key => $val) {
1089                if ($parent_key != '') {
1090                    $keyname = $parent_key . '['. $key . ']';
1091                } else {
1092                    $keyname = $key;
1093                }
1094                if (is_array($val)) {
1095                    $arrDst = SC_Utils_Ex::sfMakeHiddenArray($val, $arrDst, $keyname);
1096                } else {
1097                    $arrDst[$keyname] = $val;
1098                }
1099            }
1100        }
1101
1102        return $arrDst;
1103    }
1104
1105    // DB取得日時をタイムに変換
1106    public static function sfDBDatetoTime($db_date)
1107    {
1108        $date = preg_replace("|\..*$|", '', $db_date);
1109        $time = strtotime($date);
1110
1111        return $time;
1112    }
1113
1114    /**
1115     * PHPのmb_convert_encoding関数をSmartyでも使えるようにする
1116     *
1117     * XXX この関数を使っている箇所は、ほぼ設計誤りと思われる。変数にフェッチするか、出力時のエンコーディングで対応すべきと見受ける。
1118     */
1119    public function sfMbConvertEncoding($str, $encode = CHAR_CODE)
1120    {
1121        return mb_convert_encoding($str, $encode);
1122    }
1123
1124    // 2つの配列を用いて連想配列を作成する
1125    public function sfArrCombine($arrKeys, $arrValues)
1126    {
1127        if (count($arrKeys) <= 0 and count($arrValues) <= 0) return array();
1128
1129        $keys = array_values($arrKeys);
1130        $vals = array_values($arrValues);
1131
1132        $max = max(count($keys), count($vals));
1133        $combine_ary = array();
1134        for ($i=0; $i<$max; $i++) {
1135            $combine_ary[$keys[$i]] = $vals[$i];
1136        }
1137        if (is_array($combine_ary)) return $combine_ary;
1138        return false;
1139    }
1140
1141    /* 階層構造のテーブルから与えられたIDの直属の子を取得する */
1142
1143    /**
1144     * @param string $pid_name
1145     * @param string $id_name
1146     */
1147    public static function sfGetUnderChildrenArray($arrData, $pid_name, $id_name, $parent)
1148    {
1149        $max = count($arrData);
1150
1151        $arrChildren = array();
1152        // 子IDを検索する
1153        for ($i = 0; $i < $max; $i++) {
1154            if ($arrData[$i][$pid_name] == $parent) {
1155                $arrChildren[] = $arrData[$i][$id_name];
1156            }
1157        }
1158
1159        return $arrChildren;
1160    }
1161
1162    /**
1163     * SQLシングルクォート対応
1164     * @deprecated SC_Query::quote() を使用すること
1165     */
1166    public static function sfQuoteSmart($in)
1167    {
1168        if (is_int($in) || is_double($in)) {
1169            return $in;
1170        } elseif (is_bool($in)) {
1171            return $in ? 1 : 0;
1172        } elseif (is_null($in)) {
1173            return 'NULL';
1174        } else {
1175            return "'" . str_replace("'", "''", $in) . "'";
1176        }
1177    }
1178
1179    // ディレクトリを再帰的に生成する
1180    public static function sfMakeDir($path)
1181    {
1182        static $count = 0;
1183        $count++;  // 無限ループ回避
1184        $dir = dirname($path);
1185        if (preg_match("|^[/]$|", $dir) || preg_match("|^[A-Z]:[\\]$|", $dir) || $count > 256) {
1186            // ルートディレクトリで終了
1187            return;
1188        } else {
1189            if (is_writable(dirname($dir))) {
1190                if (!file_exists($dir)) {
1191                    mkdir($dir);
1192                    GC_Utils_Ex::gfPrintLog("mkdir $dir");
1193                }
1194            } else {
1195                SC_Utils_Ex::sfMakeDir($dir);
1196                if (is_writable(dirname($dir))) {
1197                    if (!file_exists($dir)) {
1198                        mkdir($dir);
1199                        GC_Utils_Ex::gfPrintLog("mkdir $dir");
1200                    }
1201                }
1202            }
1203        }
1204
1205        return;
1206    }
1207
1208    // ディレクトリ以下のファイルを再帰的にコピー
1209
1210    /**
1211     * @param string $src
1212     * @param string $des
1213     */
1214    public static function sfCopyDir($src, $des, $mess = '', $override = false)
1215    {
1216        if (!is_dir($src)) {
1217            return false;
1218        }
1219
1220        $oldmask = umask(0);
1221        $mod= stat($src);
1222
1223        // ディレクトリがなければ作成する
1224        if (!file_exists($des)) {
1225            if (!mkdir($des, $mod[2])) {
1226                echo 'path:' . $des;
1227            }
1228        }
1229
1230        $fileArray=glob($src.'*');
1231        if (is_array($fileArray)) {
1232            foreach ($fileArray as $data_) {
1233                // CVS管理ファイルはコピーしない
1234                if (strpos($data_, '/CVS/Entries') !== false) {
1235                    break;
1236                }
1237                if (strpos($data_, '/CVS/Repository') !== false) {
1238                    break;
1239                }
1240                if (strpos($data_, '/CVS/Root') !== false) {
1241                    break;
1242                }
1243
1244                $matches = array();
1245                mb_ereg("^(.*[\/])(.*)", $data_, $matches);
1246                $data=$matches[2];
1247                if (is_dir($data_)) {
1248                    $mess = SC_Utils_Ex::sfCopyDir($data_.'/', $des.$data.'/', $mess);
1249                } else {
1250                    if (!$override && file_exists($des.$data)) {
1251                        $mess.= $des.$data . ":ファイルが存在します\n";
1252                    } else {
1253                        if (@copy($data_, $des.$data)) {
1254                            $mess.= $des.$data . ":コピー成功\n";
1255                        } else {
1256                            $mess.= $des.$data . ":コピー失敗\n";
1257                        }
1258                    }
1259                    $mod=stat($data_);
1260                }
1261            }
1262        }
1263        umask($oldmask);
1264
1265        return $mess;
1266    }
1267
1268    /**
1269     * ブラウザに強制的に送出する
1270     *
1271     * @param  boolean|string $output 半角スペース256文字+改行を出力するか。または、送信する文字列を指定。
1272     * @param int $sleep
1273     * @return void
1274     */
1275    public static function sfFlush($output = false, $sleep = 0)
1276    {
1277        // 出力をバッファリングしない(==日本語自動変換もしない)
1278        while (@ob_end_flush());
1279
1280        if ($output === true) {
1281            // IEのために半角スペース256文字+改行を出力
1282            //echo str_repeat(' ', 256) . "\n";
1283            echo str_pad('', 256) . "\n";
1284        } elseif ($output !== false) {
1285            echo $output;
1286        }
1287
1288        // 出力をフラッシュする
1289        flush();
1290
1291        ob_start();
1292
1293        // 時間のかかる処理
1294        sleep($sleep);
1295    }
1296
1297    /**
1298     * @versionの記載があるファイルからバージョンを取得する。
1299     *
1300     * 使用されていない
1301     */
1302    public function sfGetFileVersion($path)
1303    {
1304        if (file_exists($path)) {
1305            $src_fp = fopen($path, 'rb');
1306            if ($src_fp) {
1307                while (!feof($src_fp)) {
1308                    $line = fgets($src_fp);
1309                    if (strpos($line, '@version') !== false) {
1310                        $arrLine = explode(' ', $line);
1311                        $version = $arrLine[5];
1312                    }
1313                }
1314                fclose($src_fp);
1315            }
1316        }
1317
1318        return $version;
1319    }
1320
1321    /**
1322     * $array の要素を $arrConvList で指定した方式で mb_convert_kana を適用する.
1323     *
1324     * 使用されていない
1325     *
1326     * @param  array $array       変換する文字列の配列
1327     * @param  array $arrConvList mb_convert_kana の適用ルール
1328     * @return array 変換後の配列
1329     * @see mb_convert_kana
1330     */
1331    public function mbConvertKanaWithArray($array, $arrConvList)
1332    {
1333        foreach ($arrConvList as $key => $val) {
1334            if (isset($array[$key])) {
1335                $array[$key] = mb_convert_kana($array[$key], $val);
1336            }
1337        }
1338
1339        return $array;
1340    }
1341
1342    /**
1343     * 配列の添字が未定義の場合は空文字を代入して定義する.
1344     *
1345     * @param  array $array         添字をチェックする配列
1346     * @param  string[] $defineIndexes チェックする添字
1347     * @return array 添字を定義した配列
1348     */
1349    public static function arrayDefineIndexes($array, $defineIndexes)
1350    {
1351        foreach ($defineIndexes as $key) {
1352            if (!isset($array[$key])) $array[$key] = '';
1353        }
1354
1355        return $array;
1356    }
1357
1358    /**
1359     * $arrSrc のうち、キーが $arrKey に含まれるものを返す
1360     *
1361     * $arrSrc に含まない要素は返されない。
1362     *
1363     * @param  array $arrSrc
1364     * @param  array $arrKey
1365     * @return array
1366     */
1367    public static function sfArrayIntersectKeys($arrSrc, $arrKey)
1368    {
1369        $arrRet = array();
1370        foreach ($arrKey as $key) {
1371            if (isset($arrSrc[$key])) $arrRet[$key] = $arrSrc[$key];
1372        }
1373
1374        return $arrRet;
1375    }
1376
1377    /**
1378     * 前方互換用
1379     *
1380     * @deprecated 2.12.0 GC_Utils_Ex::printXMLDeclaration を使用すること
1381     */
1382    public function printXMLDeclaration()
1383    {
1384        trigger_error('前方互換用メソッドが使用されました。', E_USER_WARNING);
1385        GC_Utils_Ex::printXMLDeclaration();
1386    }
1387
1388    /**
1389     * 配列をテーブルタグで出力する。
1390     *
1391     * 使用されていない
1392     *
1393     * @param array $array
1394     * @return string
1395     */
1396    public function getTableTag($array)
1397    {
1398        $html = '<table>';
1399        $html.= '<tr>';
1400        foreach ($array[0] as $key => $val) {
1401            $html.="<th>$key</th>";
1402        }
1403        $html.= '</tr>';
1404
1405        $cnt = count($array);
1406
1407        for ($i = 0; $i < $cnt; $i++) {
1408            $html.= '<tr>';
1409            foreach ($array[$i] as $val) {
1410                $html.="<td>$val</td>";
1411            }
1412            $html.= '</tr>';
1413        }
1414
1415        return $html;
1416    }
1417
1418    /**
1419     * 指定の画像のパスを返す
1420     *
1421     * @param $filename
1422     * @return string $file 画像のパス、画像が存在しない場合、NO_IMAGE_REALFILEを返す
1423     */
1424    public static function getSaveImagePath($filename)
1425    {
1426        $file = NO_IMAGE_REALFILE;
1427
1428        // ファイル名が与えられており、ファイルが存在する場合だけ、$fileを設定
1429        if (!SC_Utils_Ex::isBlank($filename) && file_exists(IMAGE_SAVE_REALDIR . $filename)) {
1430            $file = IMAGE_SAVE_REALDIR . $filename;
1431        }
1432
1433        return $file;
1434    }
1435
1436    /**
1437     * 一覧-メイン画像のファイル指定がない場合、専用の画像ファイルに書き換える。
1438     *
1439     * @param string &$filename ファイル名
1440     * @return string
1441     */
1442    public function sfNoImageMainList($filename = '')
1443    {
1444        if (strlen($filename) == 0 || substr($filename, -1, 1) == '/') {
1445            $filename .= 'noimage_main_list.jpg';
1446        }
1447
1448        return $filename;
1449    }
1450
1451    /**
1452     * 詳細-メイン画像のファイル指定がない場合、専用の画像ファイルに書き換える。
1453     *
1454     * @param string &$filename ファイル名
1455     * @return string
1456     */
1457    public static function sfNoImageMain($filename = '')
1458    {
1459        if (strlen($filename) == 0 || substr($filename, -1, 1) == '/') {
1460            $filename .= 'noimage_main.png';
1461        }
1462
1463        return $filename;
1464    }
1465
1466    /**
1467     * デバッグ用
1468     *
1469     * @param mixed $obj
1470     * @return void
1471     */
1472    public static function sfPrintR($obj)
1473    {
1474        echo '<div style="font-size: 12px;color: #00FF00;">' . "\n";
1475        echo '<strong>**デバッグ中**</strong><br />' . "\n";
1476        echo '<pre>' . "\n";
1477        var_dump($obj);
1478        echo '</pre>' . "\n";
1479        echo '<strong>**デバッグ中**</strong></div>' . "\n";
1480    }
1481
1482    /**
1483     * ランダムな文字列を取得する
1484     *
1485     * @param  integer $length 文字数
1486     * @return string  ランダムな文字列
1487     */
1488    public static function sfGetRandomString($length = 1)
1489    {
1490        return Text_Password::create($length);
1491    }
1492
1493    /**
1494     * 前方互換用
1495     *
1496     * @deprecated 2.12.0 GC_Utils_Ex::getUrl を使用すること
1497     */
1498    public function sfGetUrl()
1499    {
1500        trigger_error('前方互換用メソッドが使用されました。', E_USER_WARNING);
1501
1502        return GC_Utils_Ex::getUrl();
1503    }
1504
1505    /**
1506     * 前方互換用
1507     *
1508     * @deprecated 2.12.0 GC_Utils_Ex::toStringBacktrace を使用すること
1509     */
1510    public function sfBacktraceToString($arrBacktrace)
1511    {
1512        trigger_error('前方互換用メソッドが使用されました。', E_USER_WARNING);
1513
1514        return GC_Utils_Ex::toStringBacktrace($arrBacktrace);
1515    }
1516
1517    /**
1518     * 前方互換用
1519     *
1520     * @deprecated 2.12.0 GC_Utils_Ex::isAdminFunction を使用すること
1521     */
1522    public function sfIsAdminFunction()
1523    {
1524        trigger_error('前方互換用メソッドが使用されました。', E_USER_WARNING);
1525
1526        return GC_Utils_Ex::isAdminFunction();
1527    }
1528
1529    /**
1530     * 前方互換用
1531     *
1532     * @deprecated 2.12.0 GC_Utils_Ex::isFrontFunction を使用すること
1533     */
1534    public function sfIsFrontFunction()
1535    {
1536        trigger_error('前方互換用メソッドが使用されました。', E_USER_WARNING);
1537
1538        return GC_Utils_Ex::isFrontFunction();
1539    }
1540
1541    /**
1542     * 前方互換用
1543     *
1544     * @deprecated 2.12.0 GC_Utils_Ex::isInstallFunction を使用すること
1545     */
1546    public function sfIsInstallFunction()
1547    {
1548        trigger_error('前方互換用メソッドが使用されました。', E_USER_WARNING);
1549
1550        return GC_Utils_Ex::isInstallFunction();
1551    }
1552
1553    // 郵便番号から住所の取得
1554
1555    /**
1556     * @param string $zipcode
1557     */
1558    public static function sfGetAddress($zipcode)
1559    {
1560        $objQuery =& SC_Query_Ex::getSingletonInstance();
1561
1562        $masterData = new SC_DB_MasterData_Ex();
1563        $arrPref = $masterData->getMasterData('mtb_pref');
1564        // インデックスと値を反転させる。
1565        $arrREV_PREF = array_flip($arrPref);
1566
1567        // 郵便番号検索文作成
1568        $zipcode = mb_convert_kana($zipcode, 'n');
1569        $sqlse = 'SELECT state, city, town FROM mtb_zip WHERE zipcode = ?';
1570
1571        $data_list = $objQuery->getAll($sqlse, array($zipcode));
1572        if (empty($data_list)) return array();
1573
1574        // $zip_cntが1より大きければtownを消す
1575        //(複数行HITしているので、どれに該当するか不明の為)
1576        $zip_cnt = count($data_list);
1577        if ($zip_cnt > 1) {
1578            $data_list[0]['town'] = '';
1579        }
1580        unset($zip_cnt);
1581
1582        /*
1583         * 総務省からダウンロードしたデータをそのままインポートすると
1584         * 以下のような文字列が入っているので 対策する。
1585         * ・(1・19丁目)
1586         * ・以下に掲載がない場合
1587         * ・●●の次に番地が来る場合
1588         */
1589        $town =  $data_list[0]['town'];
1590        $town = preg_replace("/(.*)$/", '', $town);
1591        $town = preg_replace('/以下に掲載がない場合/', '', $town);
1592        $town = preg_replace('/(.*?)の次に番地がくる場合/', '', $town);
1593        $data_list[0]['town'] = $town;
1594        $data_list[0]['state'] = $arrREV_PREF[$data_list[0]['state']];
1595
1596        return $data_list;
1597    }
1598
1599    /**
1600     * 前方互換用
1601     *
1602     * @deprecated 2.12.0 microtime(true) を使用する。
1603     */
1604    public function sfMicrotimeFloat()
1605    {
1606        trigger_error('前方互換用メソッドが使用されました。', E_USER_WARNING);
1607
1608        return microtime(true);
1609    }
1610
1611    /**
1612     * 変数が空白かどうかをチェックする.
1613     *
1614     * 引数 $val が空白かどうかをチェックする. 空白の場合は true.
1615     * 以下の文字は空白と判断する.
1616     * - ' ' (ASCII 32 (0x20)), 通常の空白
1617     * - "\t" (ASCII 9 (0x09)), タブ
1618     * - "\n" (ASCII 10 (0x0A)), リターン
1619     * - "\r" (ASCII 13 (0x0D)), 改行
1620     * - "\0" (ASCII 0 (0x00)), NULバイト
1621     * - "\x0B" (ASCII 11 (0x0B)), 垂直タブ
1622     *
1623     * 引数 $val が配列の場合は, 空の配列の場合 true を返す.
1624     *
1625     * 引数 $greedy が true の場合は, 全角スペース, ネストした空の配列も
1626     * 空白と判断する.
1627     *
1628     * @param  mixed   $val    チェック対象の変数
1629     * @param  boolean $greedy '貧欲'にチェックを行う場合 true
1630     * @return boolean $val が空白と判断された場合 true
1631     */
1632    public static function isBlank($val, $greedy = true)
1633    {
1634        if (is_array($val)) {
1635            if ($greedy) {
1636                if (empty($val)) {
1637                    return true;
1638                }
1639                $array_result = true;
1640                foreach ($val as $in) {
1641                    /*
1642                     * SC_Utils_Ex への再帰は無限ループやメモリリークの懸念
1643                     * 自クラスへ再帰する.
1644                     */
1645                    $array_result = SC_Utils::isBlank($in, $greedy);
1646                    if (!$array_result) {
1647                        return false;
1648                    }
1649                }
1650
1651                return $array_result;
1652            } else {
1653                return empty($val);
1654            }
1655        }
1656
1657        if ($greedy) {
1658            $val = preg_replace('/ /', '', $val);
1659        }
1660
1661        $val = trim($val);
1662        if (strlen($val) > 0) {
1663            return false;
1664        }
1665
1666        return true;
1667    }
1668
1669    /**
1670     * 指定されたURLのドメインが一致するかを返す
1671     *
1672     * 戻り値:一致(true) 不一致(false)
1673     *
1674     * @param  string  $url
1675     * @return boolean
1676     */
1677    public static function sfIsInternalDomain($url)
1678    {
1679        $netURL = new Net_URL(HTTP_URL);
1680        $host = $netURL->host;
1681        if (!$host) return false;
1682        $host = preg_quote($host, '#');
1683        if (!preg_match("#^(http|https)://{$host}#i", $url)) return false;
1684
1685        return true;
1686    }
1687
1688    /**
1689     * パスワードのハッシュ化
1690     *
1691     * @param  string $str  暗号化したい文言
1692     * @param  string $salt salt
1693     * @return string ハッシュ暗号化された文字列
1694     */
1695    public static function sfGetHashString($str, $salt)
1696    {
1697        if ($salt == '') {
1698            $salt = AUTH_MAGIC;
1699        }
1700        if (AUTH_TYPE == 'PLAIN') {
1701            $res = $str;
1702        } else {
1703            $res = hash_hmac(PASSWORD_HASH_ALGOS, $str . ':' . AUTH_MAGIC, $salt);
1704        }
1705
1706        return $res;
1707    }
1708
1709    /**
1710     * パスワード文字列のハッシュ一致判定
1711     *
1712     * @param  string  $pass     確認したいパスワード文字列
1713     * @param  string  $hashpass 確認したいパスワードハッシュ文字列
1714     * @param  string  $salt     salt
1715     * @return boolean 一致判定
1716     */
1717    public static function sfIsMatchHashPassword($pass, $hashpass, $salt)
1718    {
1719        $res = false;
1720        if ($hashpass != '') {
1721            if (AUTH_TYPE == 'PLAIN') {
1722                if ($pass === $hashpass) {
1723                    $res = true;
1724                }
1725            } else {
1726                if (empty($salt)) {
1727                    // 旧バージョン(2.11未満)からの移行を考慮
1728                    $hash = sha1($pass . ':' . AUTH_MAGIC);
1729                } else {
1730                    $hash = SC_Utils_Ex::sfGetHashString($pass, $salt);
1731                }
1732                if ($hash === $hashpass) {
1733                    $res = true;
1734                }
1735            }
1736        }
1737
1738        return $res;
1739    }
1740
1741    /**
1742     * 検索結果の1ページあたりの最大表示件数を取得する
1743     *
1744     * フォームの入力値から最大表示件数を取得する
1745     * 取得できなかった場合は, 定数 SEARCH_PMAX の値を返す
1746     *
1747     * @param  string  $search_page_max 表示件数の選択値
1748     * @return integer 1ページあたりの最大表示件数
1749     */
1750    public static function sfGetSearchPageMax($search_page_max)
1751    {
1752        if (SC_Utils_Ex::sfIsInt($search_page_max) && $search_page_max > 0) {
1753            $page_max = intval($search_page_max);
1754        } else {
1755            $page_max = SEARCH_PMAX;
1756        }
1757
1758        return $page_max;
1759    }
1760
1761    /**
1762     * 値を JSON 形式にして返す.
1763     *
1764     * この関数は, json_encode() 又は Services_JSON::encode() のラッパーです.
1765     * json_encode() 関数が使用可能な場合は json_encode() 関数を使用する.
1766     * 使用できない場合は, Services_JSON::encode() 関数を使用する.
1767     *
1768     * @param  mixed  $value JSON 形式にエンコードする値
1769     * @return string JSON 形式にした文字列
1770     * @see json_encode()
1771     * @see Services_JSON::encode()
1772     */
1773    public static function jsonEncode($value)
1774    {
1775        if (function_exists('json_encode')) {
1776            return json_encode($value);
1777        } else {
1778            GC_Utils_Ex::gfPrintLog(' *use Services_JSON::encode(). faster than using the json_encode!');
1779            $objJson = new Services_JSON();
1780
1781            return $objJson->encode($value);
1782        }
1783    }
1784
1785    /**
1786     * JSON 文字列をデコードする.
1787     *
1788     * この関数は, json_decode() 又は Services_JSON::decode() のラッパーです.
1789     * json_decode() 関数が使用可能な場合は json_decode() 関数を使用する.
1790     * 使用できない場合は, Services_JSON::decode() 関数を使用する.
1791     *
1792     * @param  string $json JSON 形式にエンコードされた文字列
1793     * @return mixed  デコードされた PHP の型
1794     * @see json_decode()
1795     * @see Services_JSON::decode()
1796     */
1797    public static function jsonDecode($json)
1798    {
1799        if (function_exists('json_decode')) {
1800            return json_decode($json);
1801        } else {
1802            GC_Utils_Ex::gfPrintLog(' *use Services_JSON::decode(). faster than using the json_decode!');
1803            $objJson = new Services_JSON();
1804
1805            return $objJson->decode($json);
1806        }
1807    }
1808
1809    /**
1810     * パスが絶対パスかどうかをチェックする.
1811     *
1812     * 引数のパスが絶対パスの場合は true を返す.
1813     * この関数は, パスの存在チェックを行なわないため注意すること.
1814     *
1815     * use File_Util::isAbsolute
1816     * http://pear.php.net/package/File_Util/
1817     *
1818     * @param string $path チェック対象のパス
1819     * @return boolean 絶対パスの場合 true
1820     */
1821    public static function isAbsoluteRealPath($path)
1822    {
1823        if (preg_match('/(?:\/|\\\)\.\.(?=\/|$)/', $path)) {
1824            return false;
1825        }
1826        if (DIRECTORY_SEPARATOR == '\\') {
1827            return (($path{0} == '/') ||  preg_match('/^[a-zA-Z]:(\\\|\/)/', $path));
1828        }
1829        return ($path{0} == '/') || ($path{0} == '~');
1830    }
1831
1832    /**
1833     * ディレクトリを再帰的に作成する.
1834     *
1835     * @param  integer $mode     作成するディレクトリのパーミッション
1836     * @param string $path
1837     * @return boolean 作成に成功した場合 true; 失敗した場合 false
1838     * @see http://jp.php.net/mkdir
1839     */
1840    public static function recursiveMkdir($path, $mode = 0777)
1841    {
1842        // Windows環境ではmodeは効かない
1843        return mkdir($path, $mode, true);
1844    }
1845
1846    public static function isAppInnerUrl($url)
1847    {
1848        $pattern = '/^(' . preg_quote(HTTP_URL, '/') . '|' . preg_quote(HTTPS_URL, '/') . ')/';
1849
1850        return preg_match($pattern, $url) >= 1;
1851    }
1852
1853    /**
1854     * PHP のタイムアウトを延長する
1855     *
1856     * ループの中で呼び出すことを意図している。
1857     * 暴走スレッドが残留する確率を軽減するため、set_time_limit(0) とはしていない。
1858     * @param  integer $seconds 最大実行時間を延長する秒数。
1859     * @return boolean 成功=true, 失敗=false
1860     */
1861    public static function extendTimeOut($seconds = null)
1862    {
1863        $safe_mode = (boolean) ini_get('safe_mode');
1864        if ($safe_mode) return false;
1865
1866        if (is_null($seconds)) {
1867            $seconds
1868                = is_numeric(ini_get('max_execution_time'))
1869                ? intval(ini_get('max_execution_time'))
1870                : intval(get_cfg_var('max_execution_time'));
1871        }
1872
1873        // タイムアウトをリセット
1874        set_time_limit($seconds);
1875
1876        return true;
1877    }
1878
1879    /**
1880     * コンパイルファイルを削除します.
1881     * @return void
1882     */
1883    public static function clearCompliedTemplate()
1884    {
1885        // コンパイルファイルの削除処理
1886        SC_Helper_FileManager_Ex::deleteFile(COMPILE_REALDIR, false);
1887        SC_Helper_FileManager_Ex::deleteFile(COMPILE_ADMIN_REALDIR, false);
1888        SC_Helper_FileManager_Ex::deleteFile(SMARTPHONE_COMPILE_REALDIR, false);
1889        SC_Helper_FileManager_Ex::deleteFile(MOBILE_COMPILE_REALDIR, false);
1890    }
1891
1892    /**
1893     * 指定されたパスの配下を再帰的にコピーします.
1894     * @param string $source_path コピー元ディレクトリのパス
1895     * @param string $dest_path コピー先ディレクトリのパス
1896     * @return void
1897     */
1898    public static function copyDirectory($source_path, $dest_path)
1899    {
1900        $handle=opendir($source_path);
1901        while ($filename = readdir($handle)) {
1902            if ($filename === '.' || $filename === '..') continue;
1903            $cur_path = $source_path . $filename;
1904            $dest_file_path = $dest_path . $filename;
1905            if (is_dir($cur_path)) {
1906                // ディレクトリの場合
1907                // コピー先に無いディレクトリの場合、ディレクトリ作成.
1908                if (!empty($filename) && !file_exists($dest_file_path)) mkdir($dest_file_path);
1909                SC_Utils_Ex::copyDirectory($cur_path . '/', $dest_file_path . '/');
1910            } else {
1911                if (file_exists($dest_file_path)) unlink($dest_file_path);
1912                copy($cur_path, $dest_file_path);
1913            }
1914        }
1915    }
1916
1917    /**
1918     * 文字列を区切り文字を挟み反復する
1919     * @param  string $input      繰り返す文字列。
1920     * @param  string $multiplier input を繰り返す回数。
1921     * @param  string $separator  区切り文字
1922     * @return string
1923     */
1924    public static function repeatStrWithSeparator($input, $multiplier, $separator = ',')
1925    {
1926        return implode($separator, array_fill(0, $multiplier, $input));
1927    }
1928
1929    /**
1930     * RFC3986に準拠したURIエンコード
1931     * MEMO: PHP5.3.0未満では、~のエンコードをしてしまうための処理
1932     *
1933     * @param  string $str 文字列
1934     * @return string RFC3986エンコード文字列
1935     */
1936    public static function encodeRFC3986($str)
1937    {
1938        return str_replace('%7E', '~', rawurlencode($str));
1939    }
1940
1941    /**
1942     * マルチバイト対応の trim
1943     *
1944     * @param  string $str      入力文字列
1945     * @param  string $charlist 削除する文字を指定
1946     * @return string 変更後の文字列
1947     */
1948    public static function trim($str, $charlist = null)
1949    {
1950        $re = SC_Utils_Ex::getTrimPregPattern($charlist);
1951
1952        return preg_replace('/(^' . $re . ')|(' . $re . '$)/us', '', $str);
1953    }
1954
1955    /**
1956     * マルチバイト対応の ltrim
1957     *
1958     * @param  string $str      入力文字列
1959     * @param  string $charlist 削除する文字を指定
1960     * @return string 変更後の文字列
1961     */
1962    public static function ltrim($str, $charlist = null)
1963    {
1964        $re = SC_Utils_Ex::getTrimPregPattern($charlist);
1965
1966        return preg_replace('/^' . $re . '/us', '', $str);
1967    }
1968
1969    /**
1970     * マルチバイト対応の rtrim
1971     *
1972     * @param  string $str      入力文字列
1973     * @param  string $charlist 削除する文字を指定
1974     * @return string 変更後の文字列
1975     */
1976    public static function rtrim($str, $charlist = null)
1977    {
1978        $re = SC_Utils_Ex::getTrimPregPattern($charlist);
1979
1980        return preg_replace('/' . $re . '$/us', '', $str);
1981    }
1982
1983    /**
1984     * 文字列のトリム処理で使用する PCRE のパターン
1985     *
1986     * @param  string $charlist 削除する文字を指定
1987     * @return string パターン
1988     */
1989    public static function getTrimPregPattern($charlist = null)
1990    {
1991        if (is_null($charlist)) {
1992            return '\s+';
1993        } else {
1994            return '[' . preg_quote($charlist, '/') . ']+';
1995        }
1996    }
1997
1998    /**
1999     * データ量の単位を付与する
2000     *
2001     * @param  int    $data
2002     * @return string
2003     */
2004    public static function getUnitDataSize($data)
2005    {
2006        if ($data < 1000) {
2007            $return = $data . "KB";
2008        } elseif ($data < 1000000) {
2009            $return = $data/1000 . "MB";
2010        } else {
2011            $return = $data/1000000 . "GB";
2012        }
2013
2014        return $return;
2015    }
2016
2017    /**
2018     * カテゴリーツリー状の配列を作成.
2019     *
2020     * @param  string  $primary_key
2021     * @param  string  $glue_key
2022     * @param  integer $max_depth
2023     * @param  array   $correction
2024     * @param  integer $root_id
2025     * @return array   ツリーの配列
2026     */
2027    public static function buildTree($primary_key, $glue_key, $max_depth, $correction = array(), $root_id = 0)
2028    {
2029        $children = array();
2030        foreach ($correction as $child) {
2031            $children[$child[$glue_key]][] = $child;
2032        }
2033        $arrTree = $children[$root_id];
2034        foreach ($arrTree as &$child) {
2035            SC_Utils_Ex::addChild($child, $primary_key, 1, $max_depth, $children);
2036        }
2037
2038        return $arrTree;
2039    }
2040
2041    /**
2042     * ツリーの親子をつなげるルーチン.
2043     *
2044     * @param  array   $target      親
2045     * @param  string  $primary_key 主キーの識別子
2046     * @param  integer $level       親の階層
2047     * @param  integer $max_depth   階層の深さの最大値
2048     * @param  array   $children    子の配列(キーが親ID)
2049     * @return void
2050     */
2051    public static function addChild(&$target, $primary_key, $level, $max_depth, &$children = array())
2052    {
2053        if (isset($children[$target[$primary_key]])) {
2054            $target['children'] = $children[$target[$primary_key]];
2055            if ($level + 1 < $max_depth) {
2056                foreach ($target['children'] as &$child) {
2057                    SC_Utils_Ex::addChild($child, $primary_key, $level+1, $max_depth, $children);
2058                }
2059            }
2060        }
2061    }
2062
2063    /**
2064     * 配列のキーをIDにした配列を作成.
2065     *
2066     * @param  string $ID_name    IDが格納されているキー名
2067     * @param  array  $correction 元の配列
2068     * @return array
2069     */
2070    public static function makeArrayIDToKey($ID_name, $correction = array())
2071    {
2072        $arrTmp = array();
2073        foreach ($correction as $item) {
2074            $arrTmp[$item[$ID_name]] = $item;
2075        }
2076        $return =& $arrTmp;
2077        unset($arrTmp);
2078
2079        return $return;
2080    }
2081
2082    /**
2083     * 階層情報が含まれている配列から親ID配列を取得する.
2084     *
2085     * @param  integer $start_id    取得起点
2086     * @param  string  $primary_key 主キー名
2087     * @param  string  $glue_key    親IDキー名
2088     * @param  array   $correction  階層構造が含まれている配列
2089     * @param  boolean $cid_is_key  キーがIDの配列の場合はtrue
2090     * @param  integer $root_id     ルートID
2091     * @param  boolean $id_only     IDだけの配列を返す場合はtrue
2092     * @return array   親ID配列
2093     */
2094    public static function getTreeTrail($start_id, $primary_key, $glue_key, $correction = array(), $cid_is_key = FALSE, $root_id = 0, $id_only = TRUE)
2095    {
2096        if ($cid_is_key) {
2097            $arrIDToKay = $correction;
2098        } else {
2099            $arrIDToKay = SC_Utils_Ex::makeArrayIDToKey($primary_key, $correction);
2100        }
2101        $id = $start_id;
2102        $arrTrail = array();
2103        while ($id != $root_id && !SC_Utils_Ex::isBlank($id)) {
2104            if ($id_only) {
2105                $arrTrail[] = $id;
2106            } else {
2107                $arrTrail[] = $arrIDToKay[$id];
2108            }
2109            if (isset($arrIDToKay[$id][$glue_key])) {
2110                $id = $arrIDToKay[$id][$glue_key];
2111            } else {
2112                $id = $root_id;
2113            }
2114        }
2115
2116        return array_reverse($arrTrail);
2117    }
2118
2119    /**
2120     * ベースとなるパスと相対パスを比較してファイルが存在する事をチェックする
2121     *
2122     * @param  string  $file
2123     * @param  string  $base_path
2124     * @return bool true = exists / false does not exist
2125     */
2126    public static function checkFileExistsWithInBasePath($file, $base_path)
2127    {
2128        $arrPath = explode('/', str_replace('\\', '/', $file));
2129        $arrBasePath = explode('/', str_replace('\\', '/', $base_path));
2130        $path_diff = implode("/", array_diff_assoc($arrPath, $arrBasePath));
2131        return file_exists(realpath(str_replace('..', '', $base_path . $path_diff))) ? true : false;
2132    }
2133
2134    /**
2135     * マイクロ秒付きの時間文字列を取得する.
2136     *
2137     * @return string
2138     */
2139    public static function getFormattedDateWithMicroSecond()
2140    {
2141        $micro = explode(" ", microtime());
2142        $micro_string = explode('.', $micro[0]);
2143        return date('Y-m-d H:i:s') . "." . substr($micro_string[1], 0, 5);
2144    }
2145}
Note: See TracBrowser for help on using the repository browser.