app/Customize/Service/LmHelper.php line 931

Open in your IDE?
  1. <?php
  2. /**
  3.  * @version EC=CUBE4
  4.  * @copyright 株式会社 翔 kakeru.co.jp
  5.  * @author Kawai
  6.  * 2021年11月16日作成
  7.  * 2022年01月25日更新 都道府県、支払い方法等のマスタ情報取得用メソッドの追加 by worker_g
  8.  *
  9.  *
  10.  * ランドマークヘルパー
  11.  * twig
  12.  * {{% set hoge = Service('Customize\\Service\\LmHelper').hoge(Email) %}
  13.  *
  14.  *                               C= C= C= ┌(;・_・)┘トコトコ
  15.  ******************************************************/
  16. namespace Customize\Service;
  17. use Eccube\Common\EccubeConfig;
  18. use InvalidArgumentException;
  19. use Lm\Engine\EC\Entity\OrderHeaderExtended;
  20. use Lm\Entity\OrderHeader;
  21. use Lm\Service\Db\SqlService;
  22. use Lm\Service\Db\DbManager;
  23. use Symfony\Component\DependencyInjection\ContainerInterface;
  24. use Symfony\Component\HttpFoundation\Request;
  25. use Symfony\Component\HttpFoundation\RequestStack;
  26. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  27. use Customize\Service\MobileDetector as LmMobileDetector;
  28. class LmHelper
  29. {
  30.     const IS_NOT_NULLABLE 1;
  31.     /**
  32.      * @var EccubeConfig
  33.      */
  34.     protected $eccubeConfig;
  35.     /**
  36.      * @var PrefectureService
  37.      */
  38.     protected $PrefectureService;
  39.     /**
  40.      * @var CartHelper
  41.      */
  42.     protected $CartHelper;
  43.     /**
  44.      * @var Request|null
  45.      */
  46.     protected $Request;
  47.     protected $session;
  48.     protected $mobileDetector;
  49.     /**
  50.      * @param ContainerInterface $Container
  51.      * @param EccubeConfig $eccubeConfig
  52.      * @param PrefectureService $prefectureService
  53.      */
  54.     public function __construct(EccubeConfig      $eccubeConfig,
  55.                                 PrefectureService $prefectureService,
  56.                                 CartHelper        $CartHelper,
  57.                                 RequestStack      $requestStack,
  58.                                 SessionInterface  $session,
  59.                                 LmMobileDetector  $mobileDetector
  60.     )
  61.     {
  62.         $this->eccubeConfig $eccubeConfig;
  63.         $this->PrefectureService $prefectureService;
  64.         $this->CartHelper $CartHelper;
  65.         $this->Request $requestStack->getCurrentRequest();
  66.         $this->session $session;
  67.         $this->mobileDetector $mobileDetector;
  68.     }
  69.     /**
  70.      * @param $text
  71.      * @return string
  72.      */
  73.     public static function display_text($text)
  74.     {
  75.         return nl2br(str_replace(">""&gt;"str_replace("<""&lt;"stripslashes($text))));
  76.     }
  77.     /**
  78.      * @param $text
  79.      * @return string
  80.      */
  81.     public static function display_form_text($text)
  82.     {
  83.         return htmlspecialchars($textENT_QUOTES);
  84.     }
  85.     /**
  86.      * ページングリンクの生成を行う。
  87.      * 第2引数に数値を渡した場合、総レコード数として解釈。
  88.      * 第2引数に配列(全レコード)を渡した場合、配列より総レコード数を算出。
  89.      * 総レコード数と第3引数(1ページあたりの表示件数)より総ページ数を算出。
  90.      *
  91.      * TODO: 共通テンプレート(*.twig)の作成
  92.      *
  93.      * @param int $page
  94.      * @param int|array $pages
  95.      * @param int $items_per_page
  96.      * @param int $max_paging_links
  97.      * @param array $params
  98.      * @return array
  99.      */
  100.     public static function paging($page$pages$items_per_page 10$max_paging_links 10$params = [])
  101.     {
  102.         // 総レコード数の解釈
  103.         if (is_array($pages)) {
  104.             $total_count count($pages);
  105.         } else if (is_numeric($pages)) {
  106.             $total_count $pages;
  107.         } else {
  108.             throw new InvalidArgumentException();
  109.         }
  110.         // 総ページ数 = 総レコード数 / 1ページあたりの表示件数
  111.         $pages ceil($total_count $items_per_page);
  112.         // ページオフセット(当該ページの開始レコード位置)の算出
  113.         $page_offset = ($page 1) * $items_per_page;
  114.         // 返り値の用意
  115.         $ret = array(
  116.             'page' => $page,
  117.             'page_offset' => $page_offset,
  118.             'pages' => $pages,
  119.             'page_list' => array(),
  120.             'total_count' => $total_count,
  121.             'prev' => null,
  122.             'next' => null,
  123.             'params_url' => null,
  124.             'start_no' => $page_offset 1,
  125.             'end_no' => $items_per_page $page,
  126.         );
  127.         //$max_paging_linksはページ番号の表示数
  128.         $next $page 1;
  129.         $prev $page 1;
  130.         //ページ番号リンク用
  131.         $start = ($page floor($max_paging_links 2) > 0) ? ($page floor($max_paging_links 2)) : 1;//始点
  132.         $end = ($start 1) ? ($page floor($max_paging_links 2)) : $max_paging_links;//終点
  133.         $start = ($pages $end) ? $start - ($end $pages) : $start;//始点再計算
  134.         if ($page 1) {
  135.             $ret['prev'] = self::display_text($prev);
  136.         }
  137.         //最初のページへのリンク
  138.         if ($start >= floor($max_paging_links 2)) {
  139.             $ret['page_list'][] = self::display_text(1);
  140.             if ($start floor($max_paging_links 2)) $ret['page_list'][] = null//ドットの表示
  141.         }
  142.         for ($i $start$i <= $end$i++) {//ページリンク表示ループ
  143.             if ($i <= $pages && $i 0)//1以上最大ページ数以下の場合
  144.                 $ret['page_list'][] = self::display_text($i);//ページ番号リンク表示
  145.         }
  146.         //最後のページへのリンク
  147.         if ($pages $end) {
  148.             if ($pages $end$ret['page_list'][] = null;    //ドットの表示
  149.             $ret['page_list'][] = self::display_text($pages);
  150.         }
  151.         if ($page $pages) {
  152.             $ret['next'] = self::display_text($next);
  153.         }
  154.         // TODO: $params_url -> 改善の余地あり?
  155.         $params_url '';
  156.         if (!empty($params)) {
  157. //            if (isset($params['id']) && ctype_digit($params['id'])) {
  158. //                $params_url .= "id={$params['id']}&";
  159. //            }
  160. //            if (isset($params['category']) && ctype_digit($params['category'])) {
  161. //                $params_url .= "category={$params['category']}&";
  162. //            }
  163. //            if (isset($params['goods_id']) && ctype_digit($params['goods_id'])) {
  164. //                $params_url .= "goods_id={$params['goods_id']}&";
  165. //            }
  166.             $params_url http_build_query($params);
  167.             $params_url "?{$params_url}";
  168.         }
  169.         $ret['params_url'] = $params_url;
  170.         return $ret;
  171.     }
  172.     /**
  173.      * @param $goodsId
  174.      * @param $filename
  175.      * @return string
  176.      */
  177.     public function getGoodsImageUrl($goodsId$filename)
  178.     {
  179.         //
  180.         $url $this->getConfig('CFIMG_GOODS_URL');
  181.         //
  182.         $folder substr($goodsId, -11);
  183.         $folder "{$folder}/{$goodsId}";
  184.         //
  185.         $ret "{$url}/{$folder}/{$filename}";
  186.         //
  187.         return $ret;
  188.     }
  189.     /**
  190.      * @return PrefectureService
  191.      */
  192.     public function pref()
  193.     {
  194.         return $this->PrefectureService;
  195.     }
  196.     /**
  197.      * EC-CUBEコンフィグ項目の値を取得する
  198.      *
  199.      * @param array|string|int $key
  200.      * string|int ・・・ 指定されたキーのコンフィグ項目の値を取得する。
  201.      * array ・・・・・・ キーを階層構造で指定することで再帰的に走査し、任意の階層のコンフィグ項目を取得する。
  202.      * @param array|null $_config 指定不可。再帰処理用。
  203.      * @return mixed
  204.      */
  205.     public function getConfig($key$_config null)
  206.     {
  207.         //
  208.         if ($_config === null) {
  209.             //
  210.             $_config $this->eccubeConfig;
  211.         }
  212.         //
  213.         if (is_array($key)) {
  214.             //
  215.             if (count($key) !== 1) {
  216.                 //
  217.                 throw new \Exception('キーの階層構造が不正です');
  218.             }
  219.             //
  220.             $childKey key($key);
  221.             //
  222.             return $this->getConfig($key[$childKey], $_config[$childKey]);
  223.         } else {
  224.             return $_config[$key] ?? null;
  225.         }
  226.     }
  227.     /**
  228.      * @return mixed
  229.      */
  230.     public function getPaymentTypeList()
  231.     {
  232.         return $this->getConfig('PAYMENT_TYPE_LIST');
  233.     }
  234.     /**
  235.      * @return mixed
  236.      */
  237.     public function getSiteTypeList()
  238.     {
  239.         return $this->getConfig('SITE_TYPE_LIST');
  240.     }
  241.     /**
  242.      * カートタイプを返す
  243.      *  dtb_cart cart_typr
  244.      *
  245.      * @return int CrtType
  246.      */
  247.     public function getCartType()
  248.     {
  249.         return $this->CartHelper->GetCartType();
  250.     }
  251.     /**
  252.      * 全ての文字をHTML用に変換
  253.      *
  254.      * @param string
  255.      * @return string
  256.      */
  257.     public static function displayText($text)
  258.     {
  259.         return nl2br(str_replace(">""&gt;"str_replace("<""&lt;"stripslashes($text))));
  260.     }
  261.     /**
  262.      * TODO: キャッシュ使用可否判定
  263.      *
  264.      * @return bool
  265.      */
  266.     public function useCache()
  267.     {
  268.         return false;
  269.     }
  270.     /**
  271.      * TODO: キャッシュロード
  272.      *
  273.      * @param string $dataCacheId
  274.      * @param Request $request
  275.      * @return array
  276.      */
  277.     public function loadCache($dataCacheId$request)
  278.     {
  279.         return null;
  280.     }
  281.     /**
  282.      * TODO: キャッシュにデータ保存
  283.      *
  284.      * @param string $dataCacheId
  285.      * @param array $data
  286.      * @return なし
  287.      */
  288.     public function saveCache($dataCacheId$data)
  289.     {
  290.         return null;
  291.     }
  292.     /**
  293.      * キーワード分解
  294.      *
  295.      * @param string $keyword
  296.      * @param bool $trim
  297.      * @return array
  298.      */
  299.     public function getKeywords($keyword$trim true)
  300.     {
  301.         $searchtext str_replace(' '' '$keyword);
  302.         $tmpArray preg_split('/[ ]+/'$searchtext);
  303.         $keywords = array();
  304.         $searchSimilarWordsService = new SearchSimilarWordsService();
  305.         foreach ($tmpArray as $keyword) {
  306.             // 曖昧検索(search_similar_words)処理の経由
  307.             array_push($keywords$searchSimilarWordsService->getValidKeyword($keyword$trim));
  308.         }
  309.         return $keywords;
  310.     }
  311.     /**
  312.      * 指定した日時がLM休日かどうか判定する
  313.      *
  314.      * @param int $time
  315.      * @return bool
  316.      */
  317.     protected function getLmHoliday($time)
  318.     {
  319.         // 休日テーブルを照会
  320.         $sql = new SqlService();
  321.         $sql->Table('holiday_calendar_table');
  322.         $sql->Where(sprintf('holiday_year = 0 OR holiday_year = %d'intval(date("Y"$time))));
  323.         $sql->Where(sprintf('holiday_month = 0 OR holiday_month = %d'intval(date("m"$time))));
  324.         $sql->Where(sprintf('holiday_day = 0 OR holiday_day = %d'intval(date("d"$time))));
  325.         $sql->Where(sprintf('holiday_week = 0 OR holiday_week = %d', (date("w"$time) + 1)));
  326.         $sql->Where(sprintf('holiday_count = 0 OR holiday_count = %d', (intval((date("d"$time) - 1) / 7) + 1)));
  327.         $sql->Where('holiday_year = 0 AND holiday_month = 0 AND holiday_day = 0 AND holiday_count = 0 AND holiday_week = 0'"AND NOT");
  328.         /*
  329.         ※元クエリ内容
  330.                 $strSQL = "select * from holiday_calendar_table
  331.                         where ( holiday_year = 0 or holiday_year = " . intval(date("Y", $today)) . " )
  332.                         and ( holiday_month = 0 or holiday_month = " . intval(date("m", $today)) . " )
  333.                         and ( holiday_day = 0 or holiday_day = " . intval(date("d", $today)) . " )
  334.                         and ( holiday_week = 0 or holiday_week = " . (date("w", $today) + 1) . " )
  335.                         and ( holiday_count = 0 or holiday_count = " . (intval((date("d", $today) - 1) / 7) + 1) . " )
  336.                         and not ( holiday_year = 0 and holiday_month = 0 and holiday_day = 0 and holiday_count = 0 and holiday_week = 0 )"
  337.         */
  338.         $result $sql->Find();
  339.         return !empty($result);
  340.     }
  341.     /**
  342.      * 指定した日時が指定の仕入先の休日に該当するかどうか判定する
  343.      *
  344.      * @param int $time
  345.      * @param int array $shiiresakiList  仕入先コード(複数可能)
  346.      * @return bool
  347.      */
  348.     protected function getShiiresakiHoliday($time$shiiresakiList)
  349.     {
  350.         // 仕入先休日テーブルを照会
  351.         $sql = new SqlService();
  352.         $sql->Table('shiiresaki_yasumi_table');
  353.         if (count($shiiresakiList) === 1) {
  354.             $sql->Where(sprintf('shiiresaki_id = %d'$shiiresakiList[0]));
  355.         } else {
  356.             $sql->Where('shiiresaki_id IN (' join(','$shiiresakiList) . ')');
  357.         }
  358.         $sql->Where("holiday = '" date('Y-m-d'$time) . "'");
  359.         /*
  360.         ※元クエリ内容
  361.                     $strSQL = "SELECT * FROM shiiresaki_yasumi_table
  362.                     WHERE shiiresaki_id = $sid
  363.                     AND holiday = '$searchDate'";
  364.         */
  365.         $result $sql->Find();
  366.         return !empty($result);
  367.     }
  368.     /**
  369.      * LM休日及び仕入先休日を元に、指定した日時から指定営業日経過後の「営業日」を算出する
  370.      *
  371.      * @param int $time 基準日時
  372.      * @param int $days 指定営業日
  373.      * @param int array $shiiresakiList  仕入先コード(複数可能)デフォルトは 16=長瀞
  374.      * @return string Ymd  見つからない場合は null
  375.      */
  376.     public function getWorkingDate($time$days$shiiresakiList = [16])
  377.     {
  378.         $ret null;
  379.         $cnt 0;
  380.         $base date("Y-m-d"$time);
  381.         // 最大30日間内で検索し、見つからない場合はエラーとする
  382.         $max_date 30;
  383.         for ($i 0$i <= $days$i++) {
  384.             $find false;
  385.             for ($j 0$j $max_date$j++) {
  386.                 $targetDate strtotime($base " " $cnt " day");
  387.                 // LM休日判定
  388.                 $isLmHoliday $this->getLmHoliday($targetDate);
  389.                 if (!$isLmHoliday) {
  390.                     if ($shiiresakiList) {
  391.                         // 仕入先休日判定
  392.                         $isShiiresakiHoliday $this->getShiiresakiHoliday($targetDate$shiiresakiList);
  393.                         if (!$isShiiresakiHoliday) {
  394.                             $find true;
  395.                             break;
  396.                         }
  397.                     } else {
  398.                         // 仕入先判定なし
  399.                         $find true;
  400.                         break;
  401.                     }
  402.                 }
  403.                 $cnt++;
  404.             }
  405.             // 見つかった場合は次の日に進める
  406.             $cnt $find $cnt $cnt;
  407.         }
  408.         return $find date('Ymd'$targetDate) : null;
  409.     }
  410.     /**
  411.      * 都道府県IDを元に離島かどうか判断し配送日を返す
  412.      *
  413.      * @param int $prefectureId
  414.      * @return int
  415.      */
  416.     protected function getIslandByPrefecture($prefectureId)
  417.     {
  418.         $ret 1;
  419.         if ($prefectureId == or $prefectureId >= 36) {
  420.             $ret 2;
  421.         }
  422.         return $ret;
  423.     }
  424.     /**
  425.      * 郵便番号を元に離島かどうか判断し配送日を返す
  426.      *
  427.      * @param string $postcode
  428.      * @param int $prefectureId
  429.      * @return int
  430.      */
  431.     protected function getIslandByPostcode($postcode$prefectureId)
  432.     {
  433.         $ret 1;
  434.         // 郵便番号補正
  435.         if (!strstr($postcode'-')) {
  436.             $postcode preg_replace("/^(\d{3})(\d{4})$/""$1-$2"$postcode);
  437.         }
  438.         // 離島郵便番号テーブルを照会
  439.         $sql = new SqlService();
  440.         $sql->Table('island_table');
  441.         $sql->Where("island_postcode = '" $postcode "' OR island_postcode = '" substr($postcode03) . "-0000'");
  442.         /*
  443.         ※元クエリ内容
  444.                 $strSQL = "SELECT * FROM island_table WHERE island_postcode = '" . $post_code . "'";
  445.                 $strSQL = "SELECT * FROM island_table WHERE island_postcode = '" . substr(str_replace("-", "", $post_code), 0, 3) . "-0000'";
  446.         */
  447.         $result $sql->Find();
  448.         if (!empty($result)) {
  449.             $ret 2;
  450.         } else {
  451.             $ret $this->getIslandByPrefecture($prefectureId);
  452.         }
  453.         return $ret;
  454.     }
  455.     /**
  456.      * TODO: 商品IDを元に、仕入先毎のお届け予定日に関する情報を取得する
  457.      *
  458.      * @param int $goodsId
  459.      * @return array
  460.      */
  461.     protected function getShiiresakiSendDateByGoodsId($goodsId)
  462.     {
  463.         $ret = [
  464.             'shiiresaki_id' => -1,
  465.             'shiiresaki_senddate' => 0,
  466.             'send_limit' => 0,
  467.         ];
  468.         // 商品・仕入先テーブルを結合して情報取得
  469.         $sql = new SqlService();
  470.         $sql->Selects('shiiresaki_id');
  471.         $sql->Selects("DATE_FORMAT( T.shiiresaki_shimekiri_time, '%H%i' ) AS `sdate`");
  472.         $sql->Selects("shiiresaki_senddate");
  473.         $sql->Table('shiiresaki_table');
  474.         $sql->Join('goods_table''shiiresaki_id = goods_shiiresaki''INNER');
  475.         $sql->Where(sprintf('T1.goods_id = %d', (int)$goodsId));
  476.         /*
  477.         ※元クエリ内容
  478.                     $strSQL = "select shiiresaki_id, date_format( shiiresaki_shimekiri_time, '%H%i' ) as sdate, shiiresaki_senddate
  479.                             from goods_table
  480.                             inner join shiiresaki_table on goods_shiiresaki = shiiresaki_id
  481.                             where goods_id = " . $data_id;
  482.         */
  483.         $result $sql->Find();
  484.         if (!empty($result)) {
  485.             // 発注締切時間の後
  486.             $send_limit 0;
  487.             if (date("Hi") >= $result['sdate']) {
  488.                 $send_limit 1;
  489.             }
  490.             $ret = [
  491.                 'shiiresaki_id' => $result['shiiresaki_id'],
  492.                 'shiiresaki_senddate' => $result['shiiresaki_senddate'],
  493.                 'send_limit' => $send_limit,
  494.             ];
  495.         }
  496.         return $ret;
  497.     }
  498.     /**
  499.      * 商品IDを元に、指定した日時より直近の商品のお届け予定日を算出する
  500.      *
  501.      * @param int $time
  502.      * @param int $prefectureId
  503.      * @param string $postcode
  504.      * @param int $goodsId
  505.      * @return string Ymd  見つからない場合は null
  506.      */
  507.     public function getSendSchedule($time$prefectureId$postcode null$goodsId null)
  508.     {
  509.         // 起点日
  510.         $base $time $time time();
  511.         // 配送日数
  512.         $deliverDays 0;
  513.         // 仕入先配送日数
  514.         $deliverDaysShiiresaki 0;
  515.         // 休日判定対象の仕入先(デフォルトは物流業者=76)
  516.         $shiiresakiList = [76];
  517.         // 締切時間判定
  518.         $timeLimit false;
  519.         // 発注締切時間(12:00)を判定
  520.         if ($time && date("Hi"$base) >= 1200) {
  521.             $timeLimit true;
  522.         }
  523.         // 商品指定
  524.         if ($goodsId !== null) {
  525.             // 商品仕入先別の配送日を計算
  526.             $shiiresakiSendInfo $this->getShiiresakiSendDateByGoodsId($goodsId);
  527.             if ($shiiresakiSendInfo['shiiresaki_id'] !== -&& !$time) {
  528.                 $shiiresakiList[] = $shiiresakiSendInfo['shiiresaki_id'];
  529.             }
  530.             // 発送締切時間
  531.             $timeLimit = ($shiiresakiSendInfo['send_limit'] > 0) ? true false;
  532.             // 仕入先配送日数を加算
  533.             $deliverDaysShiiresaki $shiiresakiSendInfo['shiiresaki_senddate'];
  534.         }
  535.         // 発送締切時間を超える場合は日数加算
  536.         $deliverDays = ($timeLimit) ? $deliverDays $deliverDays;
  537.         // ここまででいったん休日判定計算する
  538.         $dt $this->getWorkingDate($base$deliverDays$shiiresakiList);
  539.         $base strtotime($dt);
  540.         // 曜日を判定
  541.         $week date("w"mktime(000date("m"$base), date("d"$base), date("Y"$base)));
  542.         if ($week == 5) {
  543.             // 計算した日付が金曜の場合は月曜まで進めて計算する
  544.             $deliverDays = ($deliverDaysShiiresaki 0) ? $deliverDaysShiiresaki 0;
  545.             $base mktime(000date("m"$base), date("d"$base) + $deliverDaysdate("Y"$base));
  546.             $dt $this->getWorkingDate($base$deliverDays$shiiresakiList);
  547.         } else {
  548.             $deliverDays $deliverDaysShiiresaki;
  549.             $deliverDays $deliverDays $deliverDays $deliverDays 1;
  550.             $dt $this->getWorkingDate($base$deliverDays$shiiresakiList);
  551.         }
  552.         // 都道府県別に配送日数を計算(郵便番号指定があれば離島テーブルより計算)
  553.         if ($postcode !== null) {
  554.             $deliverDays $this->getIslandByPostcode($postcode$prefectureId);
  555.         } else {
  556.             $deliverDays $this->getIslandByPrefecture($prefectureId);
  557.         }
  558.         // 配送日数を加算して返す(休日判定無し)
  559.         $base strtotime($dt);
  560.         $base mktime(000date("m"$base), date("d"$base) + $deliverDaysdate("Y"$base));
  561.         return date('Ymd'$base);
  562.     }
  563.     /**
  564.      * TODO: 曜日を取得
  565.      * @return mixed
  566.      */
  567.     public function getDayOfWeek()
  568.     {
  569.         return $this->getConfig('DOW_LIST');
  570.     }
  571.     /**
  572.      * TODO: その他手数料を取得
  573.      * @return mixed
  574.      */
  575.     public function getNewKakuninOtherAmounts()
  576.     {
  577.         return $this->getConfig('NEW_KAKUNIN_OTHER_AMOUNTS_LIST');
  578.     }
  579.     /**
  580.      * TODO: プリント種類を取得
  581.      * @return mixed
  582.      */
  583.     public function getPrintName()
  584.     {
  585.         return $this->getConfig('PRINT_NAME');
  586.     }
  587.     /**
  588.      * シークレットプレビュー中か否か
  589.      *
  590.      * @return bool
  591.      */
  592.     public static function isSecret()
  593.     {
  594.         return self::checkIsPermittedIpAddress();
  595.     }
  596.     /**
  597.      * アクセス元IPアドレスが、指定された権限において許可されたものか判定する
  598.      *
  599.      * TODO: $_SERVERの使用廃止
  600.      *
  601.      * @param array $permissionIdList
  602.      * @param $ipAddress
  603.      * @return bool
  604.      */
  605.     public static function checkIsPermittedIpAddress(array $permissionIdList = [
  606.         0// 0:CS
  607.         1// 1:管理者
  608.     ],                                                     $ipAddress null)
  609.     {
  610.         $ipAddress $ipAddress ?: $_SERVER['HTTP_X_FORWARDED_FOR'] ?: $_SERVER['REMOTE_ADDR'];
  611.         $ipAddress explode(', '$ipAddress);
  612.         $ipAddress $ipAddress[0];
  613.         $ip_range_list self::getIpRangeListByPermissionIdList($permissionIdList);
  614.         $client_ip ip2long($ipAddress);
  615.         $is_admin false;
  616.         foreach ($ip_range_list as $ip_range) {
  617.             list($ip_from$ip_to) = explode(' '$ip_range);
  618.             if ($client_ip ip2long($ip_from) || $client_ip ip2long($ip_to)) {
  619.                 continue;
  620.             }
  621.             $is_admin true;
  622.             break;
  623.         }
  624.         return $is_admin;
  625.     }
  626.     /**
  627.      * 指定された権限における許可IPリストを取得する
  628.      *
  629.      * @param $permissionIdList
  630.      * @return string[]
  631.      */
  632.     public static function getIpRangeListByPermissionIdList($permissionIdList)
  633.     {
  634.         //
  635.         $result = (new SqlService())
  636.             ->Select('T1.login_client_ip')
  637.             ->Table('auth_admin_table')
  638.             ->Join('login_table''aa_id = login_client_type''INNER')
  639.             ->Set('aa_id', (array)$permissionIdList'IN')
  640.             ->GroupBy('T1.login_client_ip')
  641.             ->Order('aa_id''ASC')
  642.             ->FindAll();
  643.         //
  644.         $result array_unique(explode(','implode(','array_filter(array_map(function ($item) {
  645.             return $item['login_client_ip'];
  646.         }, $result), function ($item) {
  647.             return !empty($item);
  648.         }))));
  649.         //
  650.         sort($result);
  651.         //
  652.         return $result;
  653.     }
  654.     /**
  655.      * 一時ファイルを作成する
  656.      *
  657.      * @param $fp
  658.      * @param $filename
  659.      * @return bool
  660.      */
  661.     public static function createTempfile(&$filename)
  662.     {
  663.         $fp tmpfile();
  664.         $meta stream_get_meta_data($fp);
  665.         $filename $meta['uri'];
  666.         return $fp;
  667.     }
  668.     public function getPageType()
  669.     {
  670.         //
  671.         $result = [
  672.             'type' => '',
  673.             'value' => '',
  674.         ];
  675.         //
  676.         $route $this->Request->get('_route');
  677.         //
  678.         if ($route === 'item/detail') {
  679.             //
  680.             $result['type'] = 'item';
  681.             $result['value'] = $this->Request->get('goodsId');
  682.         } else if ($route === 'page/main-category') {
  683.             //
  684.             $result['type'] = 'main-category';
  685.             $result['value'] = $this->Request->get('mc');
  686.         } else if ($route === 'page/sub-category') {
  687.             //
  688.             $result['type'] = 'category';
  689.             $result['value'] = $this->Request->get('ct');
  690.         } else if ($route === 'homepage') {
  691.             //
  692.             $result['type'] = 'top';
  693.             $result['value'] = null;
  694.         } else {
  695.             //
  696.             $result['type'] = 'other';
  697.             $result['value'] = null;
  698.         }
  699.         //
  700.         return $result;
  701.     }
  702.     static function hoge_dump($array$maxLevel 1$_level 0)
  703.     {
  704.         foreach ($array as $key => $value) {
  705.             $type gettype($value);
  706.             $type = ($type === 'object') ? get_class($value) : $type;
  707.             //
  708.             echo str_repeat('    '$_level) . "{$key}({$type}): " . (($type === 'DateTime' $value->format('Y-m-d H:i:s') : (is_object($value) ? '(Object)' : (is_array($value) ? '(Array)' $value)))), PHP_EOL;
  709.             if (($_level $maxLevel)) {
  710.                 //
  711.                 if (preg_match('/(?:Entity|PersistentCollection)/'$type)) {
  712.                     self::hoge_dump($value->toArray(), $maxLevel$_level 1);
  713.                 } else if (preg_match('/(?:array)/i'$type)) {
  714.                     self::hoge_dump($value$maxLevel$_level 1);
  715.                 } else {
  716.                     self::hoge_dump((array)($value), $maxLevel$_level 1);
  717.                 }
  718.             }
  719.         }
  720.     }
  721.     public function filterImagePathEnabled()
  722.     {
  723.         //
  724.         $config $this->eccubeConfig['Filter']['ImagePath'];
  725.         //
  726.         $configEnabled = !empty($config['Enabled']);
  727.         //
  728.         return $configEnabled;
  729.     }
  730.     public function filterSliderEnabled()
  731.     {
  732.         //
  733.         $config $this->eccubeConfig['Filter']['Slider'];
  734.         //
  735.         $configEnabled = !empty($config['Enabled']);
  736.         //
  737.         $requestDisabled $this->Request->get('slider') === 'false';
  738.         //
  739.         return $configEnabled && !$requestDisabled;
  740.     }
  741.     public function filterRemoveCommentEnabled()
  742.     {
  743.         //
  744.         $config $this->eccubeConfig['Filter']['RemoveComment'];
  745.         //
  746.         $configEnabled = !empty($config['Enabled']);
  747.         //
  748.         $requestDisabled $this->Request->get('cb') === 'true';
  749.         //
  750.         return $configEnabled && !$requestDisabled;
  751.     }
  752.     public function filterAjaxPriceEnabled()
  753.     {
  754.         //
  755.         $config $this->eccubeConfig['Filter']['AjaxPrice'];
  756.         //
  757.         $configEnabled = !empty($config['Enabled']);
  758.         //
  759.         $requestDisabled $this->Request->get('cb') === 'true';
  760.         //
  761.         return $configEnabled && !$requestDisabled;
  762.     }
  763.     public function filterWebpEnabled()
  764.     {
  765.         //
  766.         $config $this->eccubeConfig['Filter']['Webp'];
  767.         //
  768.         $configEnabled = !empty($config['Enabled']);
  769.         //
  770.         $requestDisabled $this->Request->get('webp') === 'false';
  771.         //
  772.         return $configEnabled && !$requestDisabled;
  773.     }
  774.     /**
  775.      * {[EC-CUBE]商品規格1ID} を {[LM]商品カラーID} に変換する
  776.      *
  777.      * @param $src
  778.      * @return int
  779.      * @throws \Exception
  780.      */
  781.     public function convClassCategory1IdToGclId($src)
  782.     {
  783.         //
  784.         $offset = (int)$this->getConfig([
  785.             'DbConvert' => [
  786.                 'ProductClassCategory' => [
  787.                     'offset' => '1'
  788.                 ]
  789.             ]
  790.         ]);
  791.         //
  792.         $dst $src $offset;
  793.         //
  794.         return $dst;
  795.     }
  796.     /**
  797.      * {[LM]商品カラーID} を {[EC-CUBE]商品規格1ID} に変換する
  798.      *
  799.      * @param $src
  800.      * @return int
  801.      * @throws \Exception
  802.      */
  803.     public function convGclIdToClassCategory1Id($src)
  804.     {
  805.         //
  806.         $offset = (int)$this->getConfig([
  807.             'DbConvert' => [
  808.                 'ProductClassCategory' => [
  809.                     'offset' => '1'
  810.                 ]
  811.             ]
  812.         ]);
  813.         //
  814.         $dst $src $offset;
  815.         //
  816.         return $dst;
  817.     }
  818.     /**
  819.      * {[EC-CUBE]商品規格2ID} を {[LM]商品サイズID} に変換する
  820.      *
  821.      * @param $src
  822.      * @return int
  823.      * @throws \Exception
  824.      */
  825.     public function convClassCategory2IdToGpId($src)
  826.     {
  827.         //
  828.         $offset = (int)$this->getConfig([
  829.             'DbConvert' => [
  830.                 'ProductClassCategory' => [
  831.                     'offset' => '2'
  832.                 ]
  833.             ]
  834.         ]);
  835.         //
  836.         $dst $src $offset;
  837.         //
  838.         return $dst;
  839.     }
  840.     public function convClassCategory2IdToGpIdRe($dst)
  841.     {
  842.         $offset = (int)$this->getConfig([
  843.             'DbConvert' => [
  844.                 'ProductClassCategory' => [
  845.                     'offset' => '2'
  846.                 ]
  847.             ]
  848.         ]);
  849.         $src $dst $offset;
  850.         return $src;
  851.     }
  852.     /**
  853.      * {[LM]商品サイズID} を {[EC-CUBE]商品規格2ID} に変換する
  854.      *
  855.      * @param $src
  856.      * @return int
  857.      * @throws \Exception
  858.      */
  859.     public function convGpIdToClassCategory2Id($src)
  860.     {
  861.         //
  862.         $offset = (int)$this->getConfig([
  863.             'DbConvert' => [
  864.                 'ProductClassCategory' => [
  865.                     'offset' => '2'
  866.                 ]
  867.             ]
  868.         ]);
  869.         //
  870.         $dst $src $offset;
  871.         //
  872.         return $dst;
  873.     }
  874.     public function getIntegerArray($array)
  875.     {
  876.         foreach ($array as $key => $item) {
  877.             if (!ctype_digit($item)) {
  878.                 unset($array[$key]);
  879.             }
  880.         }
  881.         return $array;
  882.     }
  883.     /**
  884.      * @param OrderHeaderExtended|OrderHeader|array|int $order
  885.      * @return string
  886.      * @throws \Exception
  887.      */
  888.     public function convertOrderToOrderId($order)
  889.     {
  890.         /**
  891.          * @var OrderHeaderExtended $orderHeaderEx
  892.          */
  893.         if ($orderHeaderEx OrderHeaderExtended::factory($order)) {
  894.             //
  895.             return $orderHeaderEx->getOrderNo();
  896.         } else {
  897.             //
  898.             return $order;
  899.         }
  900.     }
  901.     /**
  902.      * @param string $url
  903.      * @return string|null
  904.      */
  905.     public function getRedirectUrl($url)
  906.     {
  907.         //
  908.         $result = (new SqlService())
  909.             ->Select('ru_uri_after')
  910.             ->Table('redirect_url_table')
  911.             ->Set('ru_type''0')
  912.             ->Set('ru_uri_before'$url)
  913.             ->Limit(1)
  914.             ->Find();
  915.         //
  916.         if (!empty($result)) {
  917.             //
  918.             return $result['ru_uri_after'];
  919.         }
  920.         //
  921.         return null;
  922.     }
  923.     public function getBackUrl()
  924.     {
  925.         $domain $this->eccubeConfig['UT_URL'];
  926.         $referer $this->session->remove('referer');
  927.         if ($referer && strpos($referer$domain) !== false) {
  928.             return $referer;
  929.         }
  930.         return $domain;
  931.     }
  932.     public function isValidationPass($var$length$isNotNull$type$format)
  933.     {
  934.         $var mb_convert_encoding($var"EUC-JP""UTF-8");
  935.         //タグチェック
  936.         if (stristr($var">") || stristr($var"<")) {
  937.             return false;
  938.         }
  939.         //NULLチェック
  940.         if ($isNotNull == self::IS_NOT_NULLABLE && $var == "") {
  941.             return false;
  942.         } elseif ($isNotNull != self::IS_NOT_NULLABLE && $var == "") {
  943.             return true;
  944.         }
  945.         //型ごとのチェック処理
  946.         switch ($type) {
  947.             case 1:    //英数字
  948.                 for ($i 0$i strlen($var); $i++) {
  949.                     if (!(stristr("abcdefghijklmnopqrstuvwxyz_-@#1234567890./:?~:=&"substr($var$i1)))) {
  950.                         return false;
  951.                     }
  952.                 }
  953.                 return $length >= strlen($var);
  954.             case 2:    //数字
  955.                 for ($i 0$i strlen($var); $i++) {
  956.                     if (!(stristr("0123456789"substr($var$i1)))) {
  957.                         return false;
  958.                     }
  959.                 }
  960.                 return $length >= strlen($var);
  961.             case 3:    //日付
  962.                 switch ($format) {
  963.                     case "YYYY/MM/DD HH:MM:SS":
  964.                         if (substr($var101) != " ") {
  965.                             return false;
  966.                         }
  967.                         if (!(substr($var112) >= "00" && substr($var112) <= "23")) {
  968.                             return false;
  969.                         }
  970.                         if (substr($var131) != ":") {
  971.                             return false;
  972.                         }
  973.                         if (!(substr($var142) >= "00" && substr($var142) <= "59")) {
  974.                             return false;
  975.                         }
  976.                         if (substr($var161) != ":") {
  977.                             return false;
  978.                         }
  979.                         if (!(substr($var172) >= "00" && substr($var172) <= "59")) {
  980.                             return false;
  981.                         }
  982.                         if (!strtotime(substr($var118))) {
  983.                             return false;
  984.                         }
  985.                         if (strlen($var) != 19) {
  986.                             return false;
  987.                         }
  988.                     case "YYYY/MM/DD":
  989.                         if (!(substr($var82) >= "01" && substr($var82) <= "31")) {
  990.                             return false;
  991.                         }
  992.                         if (substr($var71) != "/") {
  993.                             return false;
  994.                         }
  995.                         if (strlen($var) != 10) {
  996.                             return false;
  997.                         }
  998.                     case "YYYY/MM":
  999.                         if (!(substr($var04) >= && substr($var04) <= 9999)) {
  1000.                             return false;
  1001.                         }
  1002.                         if (!(substr($var52) >= && substr($var52) <= 12)) {
  1003.                             return false;
  1004.                         }
  1005.                         if (substr($var41) != "/") {
  1006.                             return false;
  1007.                         }
  1008.                         if (strlen($var) != 7) {
  1009.                             return false;
  1010.                         }
  1011.                         break;
  1012.                     default:
  1013.                         return false;
  1014.                 }
  1015.                 if ($format == "YYYY/MM") {
  1016.                     $checkDay "$var/01";
  1017.                 } else {
  1018.                     $checkDay $var;
  1019.                 }
  1020.                 //日付の妥当性を確認
  1021.                 return checkdate(substr($checkDay52), substr($checkDay82), substr($checkDay04));
  1022.             case 4:    //電話、郵便番号
  1023.                 for ($i 0$i strlen($var); $i++) {
  1024.                     if (!(stristr("1234567890-"substr($var$i1)))) {
  1025.                         return false;
  1026.                     }
  1027.                 }
  1028.                 return $length >= strlen($var);
  1029.             case 5:    //分数
  1030.                 if (strlen($var) > $length) {
  1031.                     return false;
  1032.                 }
  1033.                 $check explode("/"$var2);
  1034.                 for ($i 0$i strlen($check[0]); $i++) {
  1035.                     if (!(stristr("0123456789"substr($check[0], $i1))) && $i == && substr($check[0], $i1) != "-") {
  1036.                         return false;
  1037.                     }
  1038.                 }
  1039.                 //文字に/が含まれている場合は、分母もチェック
  1040.                 if (strstr($var"/")) {
  1041.                     for ($i 0$i strlen($check[1]); $i++) {
  1042.                         if (!(stristr("0123456789"substr($check[1], $i1)))) {
  1043.                             return false;
  1044.                         }
  1045.                     }
  1046.                     //分母が0でないかチェック
  1047.                     if ($check[1] < 1) {
  1048.                         return false;
  1049.                     }
  1050.                 }
  1051.                 break;
  1052.             case 6:    //半角文字
  1053.                 for ($i 0$i strlen($var); $i++) {
  1054.                     if (!(stristr("abcdefghijklmnopqrstuvwxyz_-+*@1234567890./:?~:=ABCDEFGHIJKLMNOPQRSTUVWXYZ#&"substr($var$i1)))) {
  1055.                         return false;
  1056.                     }
  1057.                 }
  1058.                 return $length >= strlen($var);
  1059.             case 7:    //メール
  1060.                 return preg_match("/^[^@]+@[^.]+\..+/"$var);
  1061.             case 8:    //数字(小数)
  1062.                 for ($i 0$i strlen($var); $i++) {
  1063.                     if (!(stristr("0123456789."substr($var$i1)))) {
  1064.                         return false;
  1065.                     }
  1066.                 }
  1067.                 return (float)$var > (float)$length;
  1068.             default:
  1069.                 return $length >= strlen($var);
  1070.         }
  1071.         return true;
  1072.     }
  1073.     /***
  1074.      * @param $birthday
  1075.      * @return int
  1076.      */
  1077.     public function calculateAge($birthday): ?int
  1078.     {
  1079.         if (empty($birthday)) {
  1080.             return null;
  1081.         }
  1082.         $today = new \DateTime();
  1083.         $birthdate = new \DateTime($birthday);
  1084.         $age $today->diff($birthdate)->y;
  1085.         return $age;
  1086.     }
  1087.     public function getCacheKey($masterCacheKey$Datas)
  1088.     {
  1089.         $device $this->mobileDetector->isMobile() ? 'sp' 'pc';
  1090.         $suffix hash('sha256'base64_encode(serialize($Datas)));
  1091.         return "{$masterCacheKey}__{$device}__{$suffix}";
  1092.     }
  1093.     public function hasSusoage($Carts null)
  1094.     {
  1095.         //
  1096.         return GoodsService::isSusoageExistInJanIdList(array_map(function ($ProductClass) {
  1097.             //
  1098.             return $ProductClass->getId();
  1099.         }, $this->getEstimateProductClasses($Carts)));
  1100.     }
  1101.     public function hasKyouei($Carts null)
  1102.     {
  1103.         //
  1104.         return GoodsService::isKyoueiExistInJanIdList(array_map(function ($ProductClass) {
  1105.             //
  1106.             return $ProductClass->getId();
  1107.         }, $this->getAllProductClasses($Carts)));
  1108.     }
  1109.     public function hasShishu($Carts null)
  1110.     {
  1111.         if (!$Carts) {
  1112.             $Carts $this->CartHelper->getCarts();
  1113.         }
  1114.         $flag true;
  1115.         $hasProduct false;
  1116.         foreach ($Carts as $Cart) {
  1117.             //
  1118.             foreach ($Cart->getCartItems() as $CartItem) {
  1119.                 //
  1120.                 $options $CartItem->getOptions();
  1121.                 if ($CartItem->isProduct() && !empty($options)) {
  1122.                     $flagItem false;
  1123.                     $hasProduct true;
  1124.                     //
  1125.                     $options json_decode($optionstrue);
  1126.                     if (isset($options['print']) && is_array($options['print'])) {
  1127.                         $prints $options['print'];
  1128.                         foreach ($prints as $print) {
  1129.                             if ($print['position'] == 3) {
  1130.                                 $flagItem true;
  1131.                             }
  1132.                         }
  1133.                     }
  1134.                     $flag $flag && $flagItem;
  1135.                 }
  1136.             }
  1137.         }
  1138.         //
  1139.         return $flag && $hasProduct;
  1140.     }
  1141.     /**
  1142.      * @return ProductClass[]
  1143.      */
  1144.     public function getEstimateProductClasses($Carts null)
  1145.     {
  1146.         /**
  1147.          * @var ProductClass[] $ProductClasses
  1148.          */
  1149.         $ProductClasses = [];
  1150.         //
  1151.         if (!$Carts) {
  1152.             $Carts $this->CartHelper->getCarts();
  1153.         }
  1154.         foreach ($Carts as $Cart) {
  1155.             //
  1156.             foreach ($Cart->getCartItems() as $CartItem) {
  1157.                 //
  1158.                 if ($CartItem->isProduct() && !empty($CartItem->getOptions())) {
  1159.                     //
  1160.                     $ProductClasses[] = $CartItem->getProductClass();
  1161.                 }
  1162.             }
  1163.         }
  1164.         //
  1165.         return $ProductClasses;
  1166.     }
  1167.     public function hasNotEstimate($Carts null)
  1168.     {
  1169.         if (!$Carts) {
  1170.             $Carts $this->CartHelper->getCarts();
  1171.         }
  1172.         foreach ($Carts as $Cart) {
  1173.             //
  1174.             foreach ($Cart->getCartItems() as $CartItem) {
  1175.                 //
  1176.                 if ($CartItem->isProduct() && (!$CartItem->getEstimateId() || !$CartItem->getOptions())) {
  1177.                     //
  1178.                     return true;
  1179.                 }
  1180.             }
  1181.         }
  1182.         return false;
  1183.     }
  1184.     /**
  1185.      * @return ProductClass[]
  1186.      */
  1187.     public function getAllProductClasses($Carts null)
  1188.     {
  1189.         /**
  1190.          * @var ProductClass[] $ProductClasses
  1191.          */
  1192.         $ProductClasses = [];
  1193.         if (!$Carts) {
  1194.             $Carts $this->CartHelper->getCarts();
  1195.         }
  1196.         //
  1197.         foreach ($Carts as $Cart) {
  1198.             //
  1199.             foreach ($Cart->getCartItems() as $CartItem) {
  1200.                 //
  1201.                 if ($CartItem->isProduct()) {
  1202.                     //
  1203.                     $ProductClasses[] = $CartItem->getProductClass();
  1204.                 }
  1205.             }
  1206.         }
  1207.         //
  1208.         return $ProductClasses;
  1209.     }
  1210. }