vendor/lm/engine-ec/src/Entity/CategoryContentsBlockMapModel.php line 593

Open in your IDE?
  1. <?php
  2. /**
  3.  * CategoryContentsBlockMapModel.php
  4.  * @author: worker_h
  5.  */
  6. namespace Lm\Engine\EC\Entity;
  7. use Lm\Service\Db\SqlService;
  8. class CategoryContentsBlockMapModel
  9. {
  10.     const TEMPLATE_NAME_BLOCK 'category-col-block';
  11.     const TEMPLATE_NAME_ITEM_BLOCK_NORMAL 'category-col-item-block-normal';
  12.     const TEMPLATE_NAME_ITEM_BLOCK_MENS_LADIES 'category-col-item-block-mens-ladies';
  13.     const KIHON_IMAGE_PATH '/item/kihon/%s/%s.jpg';
  14.     const MODEL_IMAGE_PATH '/item/kihon/%s/%s-%d-%dcol.jpg';    // バインドするのは「仕入先URL」「型番」「モデル番号」「カラム数」
  15.     const MODEL_PORTRAIT_IMAGE_PATH '/item/kihon/%s/%s-portrait-%d-4col.jpg';    // バインドするのは「仕入先URL」「型番」「モデル縦長番号」(モデル縦長画像は4カラムのみ)
  16.     const MODEL_PORTRAIT_PAIR_IMAGE_PATH '/item/kihon/%s/%s-portrait-pair-4col.jpg';    // バインドするのは「仕入先URL」「型番」(モデル縦長ペア画像は4カラムのみ)
  17.     const IMAGE_COORDINATE_PATH '/item/kihon/%s/%s-%d-%dcol-coo%d.jpg';    // バインドするのは「仕入先URL」「型番」「モデル番号」「カラム数」「コーデ番号-」
  18.     const GOODS_BANNER_IMAGE_PATH '/item/kihon/%s/%s-%d-1col.jpg';    // バインドするのは「仕入先URL」「型番」「バナー番号」
  19.     const HEADER_TYPE_MIDASHI           1;    // 見出し
  20.     const HEADER_TYPE_ONLY_IMAGE        2;    // 画像のみ
  21.     const HEADER_TYPE_MIDASHI_AND_IMAGE 3;    // 見出し+画像
  22.     const HEADER_TYPE_HTML              4;    // 自由記述
  23.     const HEADER_TYPE_NO_HEADER         5;    // ヘッダーなし
  24.     const HEADER_TYPE_ITEM_BANNER       6;    // 商品バナー
  25.     const ITEM_IMAGE_TYPE_GOODS 1;    // 商品
  26.     const ITEM_IMAGE_TYPE_MODEL 2;    // モデル
  27.     const DESIGN_TYPE_NORMAL      1;    // 標準
  28.     const DESIGN_TYPE_MENS_LADIES 2;    // メンズ・レディース系
  29.     const RANK_MARK_NORMAL 1;        // 標準
  30.     const RANK_MARK_CROWN  2;        // 王冠
  31.     // もっと見る 表示タイプ
  32.     const MORE_TYPE_DISABLED 0;        // ボタン
  33.     const MORE_TYPE_BUTTON 1;            // ボタン
  34.     const MORE_TYPE_ONELINER_TEXT 2;    // 1行テキスト
  35.     
  36.     const BOOL_TRUE 1;
  37.     const BOOL_FALSE 0;
  38.     public function getContentsBlockMapById($main_category_id$category_id=null){
  39.         $map = array();
  40.         $rows = (array)(new SqlService())->Sql('
  41.             SELECT
  42.                 main_category_id,
  43.                 category_id,
  44.                 block_position,
  45.                 GROUP_CONCAT(contents_block_id ORDER BY block_order) AS contents_block_id_list
  46.             FROM
  47.                 category_contents_block_map_table 
  48.             WHERE
  49.                 main_category_id = :main_category_id AND
  50.                 IFNULL(category_id, 0) = :category_id
  51.             GROUP BY
  52.                 main_category_id, category_id, block_position
  53.         ')->Params([
  54.             'main_category_id' => $main_category_id,
  55.             'category_id' => (int)$category_id,
  56.         ])->FetchAll();
  57.         $block_id_list = array();
  58.         foreach($rows as $row){
  59.             $block_id_list array_merge($block_id_listexplode(','$row['contents_block_id_list']));
  60.         }
  61.         $block_id_list array_unique($block_id_list);
  62.         $block_map $this->getContentsBlockMap($block_id_list);
  63.         foreach($rows as $row){
  64.             // ブロックidごとの処理
  65.             foreach( explode(','$row['contents_block_id_list']) as $block_id ){
  66.                 if( !isset($block_map[$block_id]) ) continue;
  67.                 $map[$row['block_position']][] = $block_map[$block_id];
  68.             }
  69.         }
  70.         return $map;
  71.     }
  72.     private function getContentsBlockMap($id_list){
  73.         if( !is_array($id_list) || empty($id_list) ) return array();
  74.         // 必要なテンプレートがなければ抜ける。
  75.         $template $this->getTemplate();
  76.         if(
  77.             !isset($template[self::TEMPLATE_NAME_BLOCK]) ||
  78.             !isset($template[self::TEMPLATE_NAME_ITEM_BLOCK_NORMAL]) ||
  79.             !isset($template[self::TEMPLATE_NAME_ITEM_BLOCK_MENS_LADIES])
  80.         ) return array();
  81.         $block_tamplate $template[self::TEMPLATE_NAME_BLOCK];
  82.         $contents_block_list $this->getContentsBlockList($id_list);
  83.         
  84.         // ブロックコンテンツがなければ抜ける。
  85.         if( empty($contents_block_list) ) return array();
  86.         // 最後のブロックID
  87.         $last_block_id $id_listcount($id_list) - ];
  88.         $contents_block_map $goods_id_list = array();
  89.         foreach($contents_block_list as $contents_block){
  90.             // 「ヘッダーのみ」の場合goods_id_listがnullになっている
  91.             if( is_null($contents_block['goods_id_list']) ) continue;
  92.             $goods_id_list array_merge($goods_id_listexplode(','$contents_block['goods_id_list']));
  93.         }
  94.         // 商品情報有無(ブロックの商品有無ではなく、全コンテンツブロックの商品有無)
  95.         if( !empty($goods_id_list) ){
  96.             $goods_id_list array_unique($goods_id_list);
  97.             // 商品情報取得
  98.             $item_data_map $this->getItemDataMap($goods_id_list);
  99.             $kataban_map $this->getGoodsKatabanMap();
  100.         }
  101.         // 商品バナー情報
  102.         $goods_banner_option_map $this->getGoodsBannerOptionMap();
  103.         $map = array();
  104.         // ブロックにデータを構築(ブロックごとの処理)
  105.         $column_number_before null;        // ヘッダーなしの上のブロックとのマージン調整のため、前のカラム数を記録しておく。
  106.         foreach($contents_block_list as $block_idx => $contents_block){
  107.             
  108.             // 基本要素にあてるクラス
  109.             $base_block_class_list = array('managed-contents-block-'.(int)$contents_block['column_number'].'col');
  110.             // 最後のブロッククラス
  111.             if( (int)$last_block_id === (int)$contents_block['contents_block_id'] ){
  112.                 $base_block_class_list[] = 'managed-contents-block-last';
  113.             }
  114.             
  115.             // 商品リストデザインによってクラスをわける
  116.             switch( (int)$contents_block['design_type'] ){
  117.                 // メンズ・レディース系
  118.                 case self::DESIGN_TYPE_MENS_LADIES:
  119.                     $base_block_class_list[] = 'managed-contents-block-item-list-mens-ladies';
  120.                     break;
  121.                 default:
  122.                     break;
  123.             }
  124.             
  125.             $block_part $template[self::TEMPLATE_NAME_BLOCK];
  126.             switch((int)$contents_block['header_type']){
  127.                 case self::HEADER_TYPE_MIDASHI:
  128.                     $this->setMidashiHeaderToContents($block_part$contents_block);
  129.                     break;
  130.                 case self::HEADER_TYPE_ONLY_IMAGE:
  131.                     $this->setImageHeaderToContents($block_part$contents_block);
  132.                     break;
  133.                 case self::HEADER_TYPE_MIDASHI_AND_IMAGE:
  134.                     $this->setMidashiImageHeaderToContents($block_part$contents_block$base_block_class_list);
  135.                     break;
  136.                 case self::HEADER_TYPE_HTML:
  137.                     $this->setHtmlHeaderToContents($block_part$contents_block);
  138.                     break;
  139.                 case self::HEADER_TYPE_NO_HEADER:
  140.                     $this->setNoHeaderToContents($block_part$contents_block$column_number_before$base_block_class_list);
  141.                     break;
  142.                 case self::HEADER_TYPE_ITEM_BANNER:
  143.                     $this->setItemBannerHeaderToContents($block_part$contents_block$base_block_class_list$goods_banner_option_map);
  144.                     
  145.                     // 商品バナーの時のテキスト、リンクの上書き処理
  146.                     if(
  147.                         (int)$contents_block['more_button_type'] === self::MORE_TYPE_ONELINER_TEXT &&
  148.                         isset($goods_banner_option_map[$contents_block['contents_block_id']])
  149.                     ){
  150.                         $goods_banner_data $goods_banner_option_map[$contents_block['contents_block_id']];
  151.                         
  152.                         if( !empty($goods_banner_data['oneliner_text']) ) $contents_block['more_button_text'] = $goods_banner_data['oneliner_text'];
  153.                         if( !empty($goods_banner_data['url']) ) $contents_block['more_button_link_url'] = $goods_banner_data['url'];
  154.                     }
  155.                     break;
  156.             }
  157.             $column_number_before = (int)$contents_block['column_number'];
  158.             $this->setDescriptionToContents($block_part$contents_block);
  159.             // もっと見る
  160.             if(
  161.                 (int)$contents_block['more_button_type'] !== self::MORE_TYPE_DISABLED &&
  162.                 !empty($contents_block['more_button_text']) &&
  163.                 !empty($contents_block['more_button_link_url'])
  164.             ){
  165.                 $class_name '';
  166.                 switch( (int)$contents_block['more_button_type'] ){
  167.                     case self::MORE_TYPE_BUTTON:
  168.                         $class_name 'managed-contents-block-more-link-button';
  169.                         break;
  170.                     case self::MORE_TYPE_ONELINER_TEXT:
  171.                         $class_name 'managed-contents-block-more-link-oneliner-text';
  172.                         break;
  173.                 }
  174.                 $block_part str_replace(
  175.                     '<div class="managed-contents-block-footer"></div>',
  176.                     '<div class="'.$class_name.' managed-contents-block-footer"><a href="'.htmlspecialchars($contents_block['more_button_link_url']).'">'.htmlspecialchars($contents_block['more_button_text']).'</a></div>',
  177.                     $block_part
  178.                 );
  179.             }
  180.             else{
  181.                 $block_part str_replace('<div class="managed-contents-block-footer"></div>'''$block_part);
  182.             }
  183.             // 色設定
  184.             $block_part $this->setColor($block_part$contents_block);
  185.             // 基本要素にクラスを当てる
  186.             $block_part str_replace(
  187.                 '<div class="managed-contents-block"',
  188.                 '<div class="managed-contents-block '.implode(' '$base_block_class_list).'"',
  189.                 $block_part
  190.             );
  191.             // ブロックに商品情報がなければ商品リスト箇所を削除してマップに入れて次のブロックへ
  192.             if( is_null($contents_block['goods_id_list']) ) {
  193.                 $block_part str_replace('<goods-list />'''$block_part);
  194.                 $map[$contents_block['contents_block_id']] = $block_part;
  195.                 continue;
  196.             }
  197.             // 商品ごとの処理
  198.             $item_part_list = array();
  199.             $goods_count 1;
  200.             foreach( explode(','$contents_block['goods_id_list']) as $idx => $goods_id ){
  201.                 // 商品情報がなければ次へ
  202.                 if( !isset($item_data_map[$goods_id]) ) continue;
  203.                 $goods_data $item_data_map[$goods_id];
  204.                 $block_class '';
  205.                 // 商品リストのデザインタイプ
  206.                 switch( (int)$contents_block['design_type'] ){
  207.                     case self::DESIGN_TYPE_NORMAL:
  208.                         $item_part $template[self::TEMPLATE_NAME_ITEM_BLOCK_NORMAL];
  209.                         break;
  210.                     case self::DESIGN_TYPE_MENS_LADIES:
  211.                         $item_part $template[self::TEMPLATE_NAME_ITEM_BLOCK_MENS_LADIES];
  212.                         $goods_data['color'] = array_slice($goods_data['color'], 010);    // カラーチップは最大10個まで
  213.                         break;
  214.                 }
  215.                 
  216.                 $item_part $this->setItem(
  217.                     $item_part
  218.                     $goods_data
  219.                     $contents_block
  220.                     $kataban_map
  221.                     $idx,
  222.                     $goods_count++
  223.                 );
  224.                 
  225.                 $item_part_list[] = $item_part;
  226.             }
  227.             // 商品リストデザインが「メンズ・レディース系」(space-betweenじゃないのでliを補完する必要なし)
  228.             if( (int)$contents_block['design_type'] === self::DESIGN_TYPE_MENS_LADIES ){
  229.                 // 2カラム画像として表示の時、非2colのliを隠す処理
  230.                 $this->set2colLi$item_part_list );
  231.             }
  232.             // 不足分のliを埋める(間隔調整などspace-betweenの方が楽なので、space-between+不足分を埋める実装)
  233.             else{
  234.                 $item_part_list $this->fillItemList$item_part_list$contents_block['column_number'] );
  235.             }
  236.             $block_part str_replace('<goods-list />'implode(''$item_part_list), $block_part);
  237.             
  238.             // 補足説明テキストを追加
  239.             if( (int)$contents_block['design_type'] === self::DESIGN_TYPE_MENS_LADIES ){
  240.                 $block_part $this->setAdditionalText($block_part$contents_block);
  241.             }
  242.             $map[$contents_block['contents_block_id']] = $block_part;
  243.         }
  244.         
  245.         return $map;
  246.     }
  247.     private function setNoHeaderToContents(&$block_part$contents_block$column_number_before, &$base_block_class_list){
  248.         if( !is_null($column_number_before) ){
  249.             $base_block_class_list[] = 'managed-contents-block-no-header';
  250.         }
  251.         $block_part str_replace('<div class="managed-contents-block-midashi-image"></div>'''$block_part);
  252.         $block_part preg_replace('!<div class="managed-contents-block-header-text-wrap">.*?</div>!s'''$block_part);
  253.         $block_part str_replace('<div class="managed-contents-block-header-html"></div>'''$block_part);
  254.         $block_part preg_replace('!<div class="managed-contents-block-header">.*?</div>!s'''$block_part);
  255.     }
  256.     private function setHtmlHeaderToContents(&$block_part$contents_block){
  257.         $block_part str_replace('<div class="managed-contents-block-midashi-image"></div>'''$block_part);
  258.         $block_part preg_replace('!<div class="managed-contents-block-header-text-wrap">.*?</div>!s'''$block_part);
  259.         $block_part str_replace('<div class="managed-contents-block-header-html"></div>''<div class="managed-contents-block-header-html">'.$contents_block['header_html'].'</div>'$block_part);
  260.     }
  261.     private function setMidashiImageHeaderToContents(&$block_part$contents_block, &$base_block_class_list){
  262.         $base_block_class_list[] = 'managed-contents-block-midashi-and-text';
  263.         $this->setMidashiHeaderToContents($block_part$contents_block);
  264.         $this->setImageHeaderToContents($block_part$contents_blockfalse);
  265.         
  266.         $style sprintf('style="top: %dpx; left: %dpx"'$contents_block['header_text_pos_y'], $contents_block['header_text_pos_x']);
  267.         $block_part str_replace('<div class="managed-contents-block-header-text-wrap">''<div class="managed-contents-block-header-text-wrap" '.$style.'>'$block_part);
  268.         $block_part str_replace('<midashi-header-description />'nl2br($contents_block['header_description']), $block_part);
  269.     }
  270.     private function setItemBannerHeaderToContents(&$block_part$contents_block, &$base_block_class_list$goods_banner_option_map){
  271.         
  272.         if( !isset($goods_banner_option_map[$contents_block['contents_block_id']]) ) return;
  273.         // バナーデータ
  274.         $goods_banner_data $goods_banner_option_map[$contents_block['contents_block_id']];
  275.         $base_block_class_list[] = 'managed-contents-block-goods-banner';
  276.         
  277.         // バナーデータで見出しなどのデータを上書き
  278.         $contents_block['header_image_url'] = $goods_banner_data['image_src'];
  279.         $contents_block['header_image_alt'] = $goods_banner_data['image_alt'];
  280.         if( !is_null($goods_banner_data['text_1']) ) $contents_block['midashi_large'] = $goods_banner_data['text_1'];
  281.         if( !is_null($goods_banner_data['text_2']) ) $contents_block['midashi_small'] = $goods_banner_data['text_2'];
  282.         if( !is_null($goods_banner_data['description']) ) $contents_block['header_description'] = $goods_banner_data['description'];
  283.         if( !is_null($goods_banner_data['pos_x']) ) $contents_block['header_text_pos_x'] = $goods_banner_data['pos_x'];
  284.         if( !is_null($goods_banner_data['pos_y']) ) $contents_block['header_text_pos_y'] = $goods_banner_data['pos_y'];
  285.         // 見出しと画像をセット
  286.         $this->setMidashiHeaderToContents($block_part$contents_block);
  287.         $this->setItemBannerImageToHeaderContents($block_part$contents_block);
  288.         
  289.         // ブロックdom
  290.         // DOM修正が複雑になるためDOMDocumentを使用する。
  291.         $dom self::getDomDocumentFromBlockPart($block_part);
  292.         if( !$dom ) return;
  293.         
  294.         // バナーアンカーエレメント
  295.         $banner_a_elem null;
  296.         // バナー全体に商品ページへのリンクを設置
  297.         foreach( $dom->getElementsByTagName('div') as $elem ){
  298.             if( $elem->getAttribute('class') !== 'managed-contents-block-midashi-image' ) continue;
  299.             $banner_a_elem $dom->createElement('a');
  300.             $banner_a_elem->setAttribute('class''managed-contents-block-goods-banner-link');
  301.             $banner_a_elem->setAttribute('href'$goods_banner_data['url']);
  302.             $elem->appendChild$banner_a_elem );
  303.             break;
  304.         }
  305.         // 画像をバナーに移す
  306.         $banner_img_elem $dom->getElementsByTagName('img')->item(0);
  307.         if( !is_null($banner_img_elem) ){
  308.             $banner_a_elem->appendChild($banner_img_elem);
  309.         }
  310.         // テキストエリアをバナーに移す
  311.         foreach( $dom->getElementsByTagName('div') as $elem ){
  312.             if( $elem->getAttribute('class') !== 'managed-contents-block-header-text-wrap' ) continue;
  313.             // ポジションセット
  314.             $elem->setAttribute('style'sprintf(
  315.                 'top: %dpx; left: %dpx',
  316.                 $contents_block['header_text_pos_y'],
  317.                 $contents_block['header_text_pos_x']
  318.             ));
  319.             $banner_a_elem->appendChild($elem);
  320.             break;
  321.         }
  322.         
  323.         $replace_elem $banner_a_elem->getElementsByTagName('midashi-header-description')->item(0);
  324.         if( !is_null($replace_elem) ) $replace_elem->parentNode->removeChild($replace_elem);
  325.         // バナー説明文設置
  326.         foreach( $banner_a_elem->getElementsByTagName('p') as $p_elem ){
  327.             if( $p_elem->getAttribute('class') !== 'managed-contents-block-header-description' ) continue;
  328.             $inner $dom->createElement('span');
  329.             $inner->setAttribute('class''managed-contents-block-header-description-inner');
  330.             $text nl2brhtmlspecialchars($contents_block['header_description']) );
  331.             $inner->appendChild$dom->createTextNode($text) );
  332.             $p_elem->appendChild$inner );
  333.             break;
  334.         };
  335.         // フォント設定を反映
  336.         if($goods_banner_data['text_1_size']) $contents_block['midashi_large_size'] = $goods_banner_data['text_1_size'];
  337.         if($goods_banner_data['text_1_color']) $contents_block['midashi_large_color'] = $goods_banner_data['text_1_color'];
  338.         if($goods_banner_data['text_1_bg_color']) $contents_block['midashi_large_bg_color'] = $goods_banner_data['text_1_bg_color'];
  339.         if($goods_banner_data['text_2_size']) $contents_block['midashi_small_size'] = $goods_banner_data['text_2_size'];
  340.         if($goods_banner_data['text_2_color']) $contents_block['midashi_small_color'] = $goods_banner_data['text_2_color'];
  341.         if($goods_banner_data['text_2_bg_color']) $contents_block['midashi_small_bg_color'] = $goods_banner_data['text_2_bg_color'];
  342.         if($goods_banner_data['description_size']) $contents_block['header_description_size'] = $goods_banner_data['description_size'];
  343.         if($goods_banner_data['description_color']) $contents_block['header_description_color'] = $goods_banner_data['description_color'];
  344.         if($goods_banner_data['description_bg_color']) $contents_block['header_description_bg_color'] = $goods_banner_data['description_bg_color'];
  345.         $has_bg_color_class 'managed-contents-block-text-has-bg-color';
  346.         $use_shadow_class 'managed-contents-block-text-shadow';
  347.         /**
  348.          * @var \DOMNode $elem
  349.          */
  350.         foreach( $banner_a_elem->getElementsByTagName('*') as $elem ){
  351.             if( !in_array(
  352.                 $elem->getAttribute('class'),
  353.                 [
  354.                     'managed-contents-block-midashi-large',
  355.                     'managed-contents-block-midashi-small',
  356.                     'managed-contents-block-header-description-inner'
  357.                 ]
  358.             )) continue;
  359.             $style = [];
  360.             $add_class '';
  361.             $style_text '';
  362.             switch( $elem->getAttribute('class') ){
  363.                 // 見出し1
  364.                 case 'managed-contents-block-midashi-large':
  365.                     if( !empty($contents_block['midashi_large_size']) ) $style[] = "font-size: {$contents_block['midashi_large_size']}px;";
  366.                     if( !empty($contents_block['midashi_large_color']) ) $style[] = "color: {$contents_block['midashi_large_color']};";
  367.                     if( !empty($contents_block['midashi_large_bg_color']) && !empty($elem->textContent) ){
  368.                         $style[] = "background: {$contents_block['midashi_large_bg_color']};";
  369.                         $add_class $has_bg_color_class;
  370.                     }
  371.                     if( (int)$contents_block['midashi_large_use_shadow'] === ){
  372.                         $add_class .= ' '.$use_shadow_class;
  373.                     }
  374.                     break;
  375.                 // 見出し2
  376.                 case 'managed-contents-block-midashi-small':
  377.                     if( !empty($contents_block['midashi_small_size']) ) $style[] = "font-size: {$contents_block['midashi_small_size']}px;";
  378.                     if( !empty($contents_block['midashi_small_color']) ) $style[] = "color: {$contents_block['midashi_small_color']};";
  379.                     if( !empty($contents_block['midashi_small_bg_color']) ){
  380.                         $style[] = "background: {$contents_block['midashi_small_bg_color']};";
  381.                         $add_class $has_bg_color_class;
  382.                     }
  383.                     if( (int)$contents_block['midashi_small_use_shadow'] === ){
  384.                         $add_class .= ' '.$use_shadow_class;
  385.                     }
  386.                     break;
  387.                 // 説明文
  388.                 case 'managed-contents-block-header-description-inner':
  389.                     if( !empty($contents_block['header_description_size']) ) $style[] = "font-size: {$contents_block['header_description_size']}px;";
  390.                     if( !empty($contents_block['header_description_color']) ) $style[] = "color: {$contents_block['header_description_color']};";
  391.                     if( !empty($contents_block['header_description_bg_color']) ){
  392.                         $style[] = "background: {$contents_block['header_description_bg_color']};";
  393.                         $add_class $has_bg_color_class;
  394.                     }
  395.                     break;
  396.             }
  397.             $style_text = empty($style) ? '' implode(' '$style);
  398.             $class $elem->getAttribute('class').' '.$add_class;
  399.             $elem->setAttribute('class'$class);
  400.             $elem->setAttribute('style'$style_text);
  401.         }
  402.         // 価格表示
  403.         // 価格ajaxの実装に合わせるため、get-price-ajax、throughの位置を調整
  404.         // 価格ajaxの数字が基準になるため、パーセンテージアイコンはJSで出力する以外方法がない。
  405.         if( $goods_banner_data['show_price'] ){
  406.             $banner_a_elem->appendChild$dom->createTextNode('
  407.                 <span class="managed-contents-block-retail-prices">希望小売価格 <span class="through"></span></span>
  408.                 <div class="managed-contents-block-price-box">
  409.                     <div class="managed-contents-block-list-price through"></div>
  410.                     <div>
  411.                         <span class="managed-contents-block-list-price get-price-ajax formed" data-item-id="'.$goods_banner_data['goods_id'].'"></span><span class="yen"> 円</span><span class="zei">(税込)</span>
  412.                     </div>
  413.                 </div>
  414.             '));
  415.         }
  416.         // SALEアイコン
  417.         if( $goods_banner_data['show_sale_icon'] ){
  418.             $banner_a_elem->appendChild$dom->createTextNode('
  419.                 <div class="managed-contents-block-sale-icon">
  420.                     <img />
  421.                 </div>
  422.             '));
  423.         }
  424.         $block_part self::getBlockPartFromDomDocument($dom);
  425.         // DOMDocumentで整形された箇所を元に戻す
  426.         $block_part str_replace('<description/>''<description />'$block_part);
  427.         $block_part str_replace('<goods-list/>''<goods-list />'$block_part);
  428.         $block_part str_replace('<div class="managed-contents-block-footer"/>''<div class="managed-contents-block-footer"></div>'$block_part);
  429.         // 不要な要素を削除
  430.         $block_part str_replace('<div class="managed-contents-block-header-html"/>'''$block_part);
  431.         
  432.     }
  433.     private function setImageHeaderToContents(&$block_part$contents_block$delete_other=true){
  434.         $img sprintf(
  435.             '<img src="%s" alt="%s">',
  436.             // CFIMG_URL . preg_replace('!^/+ut_img/!', '', $contents_block['header_image_url']),
  437.             $contents_block['header_image_url'],
  438.             htmlspecialchars($contents_block['header_image_alt'])
  439.         );
  440.         $block_part str_replace('<div class="managed-contents-block-midashi-image"></div>''<div class="managed-contents-block-midashi-image">'.$img.'</div>'$block_part);
  441.         if(!$delete_other) return;
  442.         $block_part preg_replace('!<div class="managed-contents-block-header-text-wrap">.+?</div>!s'''$block_part);
  443.     }
  444.     /**
  445.      * @todo ヘッダーの画像操作を統一
  446.      */
  447.     private function setItemBannerImageToHeaderContents(&$block_part$contents_block){
  448.         $img sprintf(
  449.             '<img src="%s" alt="%s">',
  450.             $contents_block['header_image_url'],
  451.             htmlspecialchars($contents_block['header_image_alt'])
  452.         );
  453.         $block_part str_replace('<div class="managed-contents-block-midashi-image"></div>''<div class="managed-contents-block-midashi-image">'.$img.'</div>'$block_part);
  454.     }
  455.     private function setDescriptionToContents(&$block_part$contents_block){
  456.         // 説明文非表示
  457.         if( (int)$contents_block['show_description'] === ){
  458.             $block_part str_replace('<p class="managed-contents-block-description"><description /></p>'''$block_part);
  459.             return;
  460.         }
  461.         
  462.         // ボーダー非表示
  463.         if( (int)$contents_block['show_description_border'] === ){
  464.             $block_part str_replace('class="managed-contents-block-description"''class="managed-contents-block-description managed-contents-block-description-no-border"'$block_part);
  465.         }
  466.         $block_part str_replace('<description />'nl2br(htmlspecialchars($contents_block['description'])), $block_part);
  467.     }
  468.     private function setMidashiHeaderToContents(&$block_part$contents_block){
  469.         // 大見出し
  470.         $block_part str_replace('<midashi-large />'htmlspecialchars($contents_block['midashi_large']), $block_part);
  471.         // 小見出し
  472.         if( empty($contents_block['midashi_small']) ){
  473.             $block_part str_replace('<p class="managed-contents-block-midashi-small"><midashi-small /></p>'''$block_part);
  474.         }
  475.         else{
  476.             $block_part str_replace('<midashi-small />'htmlspecialchars($contents_block['midashi_small']), $block_part);
  477.         }
  478.     }
  479.     private function setItem($item_part$goods_data$contents_block$kataban_map$item_idx$goods_count){
  480.         // liにあてるクラスをためる
  481.         $li_class = array();
  482.         // 商品URL
  483.         self::setLink($item_part$goods_data);
  484.         // 価格
  485.         self::setPrice($item_part$goods_data);
  486.         // 型番
  487.         self::setHinban($contents_block$item_part$goods_data$item_idx);
  488.         // カラーチップ
  489.         self::setColorTip($item_part$goods_data);
  490.         switch($contents_block['design_type']){
  491.             case self::DESIGN_TYPE_NORMAL:
  492.                 // ランキング
  493.                 self::setRanking($contents_block$item_part$item_idx$li_class);
  494.                 // 商品画像
  495.                 self::setMainImage($contents_block$item_part$goods_data$item_idx);
  496.                 // 即日配送画像
  497.                 self::setDirectDeliveryImage($contents_block$item_part$goods_data$item_idx);
  498.                 // 説明文
  499.                 self::setDescriptionText($contents_block$item_part$goods_data);
  500.                 // コーディネート
  501.                 self::setModelCoordinate($contents_block$item_part$goods_data$item_idx$kataban_map$li_class);
  502.                 break;
  503.             case self::DESIGN_TYPE_MENS_LADIES:
  504.                 $this->setMensLadies($contents_block$item_part$goods_data$item_idx);
  505.                 break;
  506.         }
  507.         $item_part str_replace(
  508.             '<li class=""',
  509.             '<li class="'.implode(' '$li_class).'"'
  510.             $item_part
  511.         );
  512.         return $item_part;
  513.     }
  514.     private static function setRanking($contents_block, &$item_part$item_idx, &$li_class){
  515.         if( (int)$contents_block['show_ranking_number'] === ){
  516.             $rank_num = (int)$contents_block['ranking_start_number'] + (int)$item_idx;
  517.             $li_class[] = 'managed-contents-block-item-rank-list';
  518.             
  519.             switch($rank_num){
  520.                 case 1:
  521.                     $class 'managed-contents-block-item-rank-gold';
  522.                     break;
  523.                 case 2:
  524.                     $class 'managed-contents-block-item-rank-silver';
  525.                     break;
  526.                 default:
  527.                     $class 'managed-contents-block-item-rank-bronze';
  528.                     break;
  529.             }
  530.             if( (int)$contents_block['ranking_mark_type'] === self::RANK_MARK_CROWN ){
  531.                 $class .= ' managed-contents-block-item-rank-mark-crown';
  532.             }
  533.             $item_part str_replace('<span class="managed-contents-block-item-rank"''<span class="managed-contents-block-item-rank '.$class.'"'$item_part);
  534.             $item_part str_replace('<span class="managed-contents-block-item-rank-label"></span>''<span class="managed-contents-block-item-rank-label">第'.$rank_num.'位</span>'$item_part);
  535.         }
  536.         else{
  537.             $item_part str_replace('<span class="managed-contents-block-item-rank"><span class="managed-contents-block-item-rank-label"></span></span>'''$item_part);
  538.         }
  539.         
  540.     }
  541.     
  542.     
  543.     
  544.     
  545.     private function setModelCoordinate($contents_block, &$item_part$goods_data$item_idx$kataban_map, &$li_class){
  546.         if( (int)$contents_block['show_coordinate_goods'] === ){
  547.             $model_num_list explode(','$contents_block['model_num_list']);
  548.             $model_num = (int)$model_num_list[$item_idx];
  549.             $column_num $contents_block['column_number'];
  550.             $coo_limit 2;
  551.             $coo_count 0;
  552.             for( $coo_num 1$coo_num <= $coo_limit$coo_num++ ){
  553.                 // id
  554.                 $field "model_{$model_num}_{$column_num}col_coordinate_goods_{$coo_num}_id";
  555.                 $coo_goods_id $goods_data[$field];
  556.                 if( empty($coo_goods_id) || !isset($kataban_map[$coo_goods_id]) ){
  557.                     $item_part preg_replace('!<li data-coo-li="'.$coo_num.'">.*?</li>!s'''$item_part1);
  558.                     continue;
  559.                 }
  560.                 $coo_count++;
  561.                 // src
  562.                 $src sprintf(
  563.                     self::IMAGE_COORDINATE_PATH,
  564.                     $goods_data['shiiresaki_url'],
  565.                     $goods_data['goods_main_kataban'],
  566.                     $model_num,
  567.                     $column_num,
  568.                     $coo_num
  569.                 );
  570.                 // alt
  571.                 $field "model_{$model_num}_{$column_num}col_coordinate_goods_{$coo_num}_alt";
  572.                 $alt $goods_data[$field];
  573.                 $img sprintf('<img src="%s" alt="%s">'$src$alt);
  574.                 $item_part preg_replace(
  575.                     '!<div class="managed-contents-block-item-model-coordinate-figure"></div>!',
  576.                     '<div class="managed-contents-block-item-model-coordinate-figure">'.$img.'</div>',
  577.                     $item_part,
  578.                     1
  579.                 );
  580.                 // href
  581.                 $href '/item/';
  582.                 $href .= $kataban_map[$coo_goods_id];
  583.                 $href .= '.html';
  584.                 $item_part preg_replace('!<a href="" data-coo-url>!''<a href="'.$href.'">'$item_part1);
  585.                 // 価格
  586.                 $item_part preg_replace('/data-item-id=""/''data-item-id="'.$coo_goods_id.'"'$item_part1);
  587.             }
  588.             
  589.             if( $coo_count === ){
  590.                 $item_part preg_replace('!<div class="managed-contents-block-item-model-coordinate">.*</li>!s''</li>'$item_part);
  591.             }
  592.             else{
  593.                 $li_class[] = 'has-coo';
  594.                 $item_part str_replace(
  595.                     '<span class="managed-contents-block-item-model-coordinate-label"></span>',
  596.                     '<span class="managed-contents-block-item-model-coordinate-label">↓モデルの着用コーデ↓</span>',
  597.                     $item_part
  598.                 );
  599.             }
  600.         }
  601.         else{
  602.             $item_part preg_replace('!<div class="managed-contents-block-item-model-coordinate">.*</li>!s''</li>'$item_part);
  603.         }
  604.     }
  605.     public function getGoodsKatabanMap(){
  606.         
  607.         $rows = (new SqlService())->Sql('
  608.             SELECT
  609.                 goods_id,
  610.                 goods_canonical_hinban,
  611.                 goods_main_kataban
  612.             FROM
  613.                 goods_table
  614.             WHERE
  615.                 goods_ddate IS NULL AND
  616.                 goods_status = 1
  617.         ')->FetchAll();
  618.         $map = array();
  619.         foreach($rows as $row){
  620.             $map[$row['goods_id']] = empty($row['goods_canonical_hinban']) ? $row['goods_main_kataban'] : $row['goods_canonical_hinban'];
  621.         }
  622.         return $map;
  623.     }
  624.     
  625.     
  626.     
  627.     
  628.     private function setColor($block_part$contents_block_data){
  629.         // 全体背景とフォント
  630.         $block_part str_replace(
  631.             '<div class="managed-contents-block">',
  632.             '<div class="managed-contents-block" style="background: '.$contents_block_data['bg_color'].'; color: '.$contents_block_data['text_color'].'">',
  633.             $block_part
  634.         );
  635.         // h2
  636.         $block_part str_replace(
  637.             '<h2 class',
  638.             '<h2 style="background: '.$contents_block_data['element_bg_color'].'; color: '.$contents_block_data['element_text_color'].';" class',
  639.             $block_part
  640.         );
  641.         // 画像上説明文
  642.         $block_part str_replace(
  643.             '<p class="managed-contents-block-header-description">',
  644.             '<p class="managed-contents-block-header-description" style="color: '.$contents_block_data['element_text_color'].'">',
  645.             $block_part
  646.         );
  647.         // コーディネート
  648.         $block_part str_replace(
  649.             '<div class="managed-contents-block-item-model-coordinate">',
  650.             '<div class="managed-contents-block-item-model-coordinate" style="background: '.$contents_block_data['bg_color'].';">',
  651.             $block_part
  652.         );
  653.         // フッター
  654.         // 1行テキストの場合は背景色設定無効
  655.         if( (int)$contents_block_data['more_button_type'] === self::MORE_TYPE_BUTTON ){
  656.             $block_part str_replace(
  657.                 'managed-contents-block-footer"><a ',
  658.                 'managed-contents-block-footer"><a style="background: '.$contents_block_data['element_bg_color'].'; color: '.$contents_block_data['element_text_color'].';" ',
  659.                 $block_part
  660.             );
  661.         }
  662.         
  663.         return $block_part;
  664.     }
  665.     private function getItemDataMap($goods_id_list){
  666.         
  667.         if( !is_array($goods_id_list) || empty($goods_id_list) ) return [];
  668.         $map = array();
  669.         $goods_id_list array_map( function($goods_id){
  670.             return (int)$goods_id;
  671.         }, $goods_id_list);
  672.         $in_clause implode(','$goods_id_list);
  673.         
  674.         $color_map $this->getGoodsColorMap($goods_id_list);
  675.         $rows = (new SqlService())->Sql("
  676.             SELECT
  677.                 g.goods_name,
  678.                 g.goods_canonical_hinban,
  679.                 g.goods_main_kataban,
  680.                 g.goods_series_2column_caption,
  681.                 g.goods_series_3column_caption,
  682.                 g.goods_series_4column_caption,
  683.                 g.goods_show_marks_above_model_banner_1,
  684.                 g.goods_show_marks_above_model_banner_2,
  685.                 g.goods_show_marks_above_model_banner_3,
  686.                 g.goods_show_direct_mark_below_model_banner_1,
  687.                 g.goods_show_direct_mark_below_model_banner_2,
  688.                 g.goods_show_direct_mark_below_model_banner_3,
  689.                 s.shiiresaki_id,
  690.                 s.shiiresaki_url,
  691.                 o.*,
  692.                 g.goods_id
  693.             FROM
  694.                 goods_table g
  695.             JOIN
  696.                 shiiresaki_table s
  697.             ON
  698.                 g.goods_shiiresaki = s.shiiresaki_id
  699.             LEFT JOIN
  700.                 goods_contents_block_option_table o
  701.             USING(goods_id)
  702.             WHERE
  703.                 g.goods_id IN({$in_clause}) AND
  704.                 g.goods_ddate IS NULL AND
  705.                 g.goods_status = 1 AND
  706.                 s.shiiresaki_url IS NOT NULL
  707.         ")->FetchAll();
  708.         foreach($rows as $row){
  709.             $row['uri'] = '/item/'.($row['goods_canonical_hinban'] ? $row['goods_canonical_hinban'] : $row['goods_id']).'.html';
  710.             if( isset($color_map[$row['goods_id']]) ) $row['color'] = $color_map[$row['goods_id']];
  711.             $map[$row['goods_id']] = $row;
  712.         }
  713.         return $map;
  714.     }
  715.     private function getContentsBlockList($id_list){
  716.         $in_clause implode(','array_map( function($id){
  717.             return (int)$id;
  718.         }, $id_list));
  719.         return (new SqlService())->Sql("
  720.             SELECT
  721.                 cb.*,
  722.                 GROUP_CONCAT(cbi.goods_id ORDER BY order_num) AS goods_id_list,
  723.                 GROUP_CONCAT(cbi.display_name ORDER BY order_num) AS display_name_list,
  724.                 GROUP_CONCAT(cbi.display_name_color ORDER BY order_num) AS display_name_color_list,
  725.                 GROUP_CONCAT(cbi.display_name_bg_color ORDER BY order_num) AS display_name_bg_color_list,
  726.                 GROUP_CONCAT(cbi.model_num ORDER BY order_num) AS model_num_list,
  727.                 GROUP_CONCAT(cbi.model_portrait_num ORDER BY order_num) AS model_portrait_num_list,
  728.                 GROUP_CONCAT(cbi.model_portrait_pair_num ORDER BY order_num) AS model_portrait_pair_num_list,
  729.                 GROUP_CONCAT(cbi.model_portrait_is_2col_image ORDER BY order_num) AS model_portrait_is_2col_image_list
  730.             FROM
  731.                 contents_block_table cb
  732.             LEFT JOIN
  733.                 contents_block_item_map_table cbi
  734.             USING(contents_block_id)
  735.             WHERE
  736.                 cb.contents_block_id IN({$in_clause}) AND
  737.                 cb.is_active = :is_active
  738.             GROUP BY
  739.                 cb.contents_block_id
  740.         ")->Params([
  741.             'is_active' => self::BOOL_TRUE,
  742.         ])->FetchAll();
  743.     }
  744.     private function getTemplate(){
  745.         $rows = (new SqlService())->Sql("
  746.             SELECT
  747.                 *
  748.             FROM
  749.                 contents_block_template_table
  750.             WHERE
  751.                 name LIKE 'category-col%'
  752.         ")->FetchAll();
  753.         $map = array();
  754.         foreach($rows as $row){
  755.             $map[$row['name']] = $row['html'];
  756.         }
  757.         
  758.         return $map;
  759.     }
  760.     private function getGoodsColorMap($goods_id_list){
  761.         if( !is_array($goods_id_list) || empty($goods_id_list) ) return [];
  762.         $where_clause 'AND g.goods_id IN(' implode(','$goods_id_list) . ')';
  763.         
  764.         $rows = (new SqlService())->Sql("
  765.             SELECT DISTINCT
  766.                 g.goods_id,
  767.                 c.color_name,
  768.                 c.color_rgb
  769.             FROM
  770.                 goods_table g
  771.             JOIN
  772.                 goods_color_table gc
  773.             ON
  774.                 g.goods_id = gc.gcl_goods AND
  775.                 gc.gcl_display_status = 1
  776.             LEFT JOIN
  777.                 color_table c
  778.             ON
  779.                 c.color_id = gc.gcl_color_id
  780.             WHERE
  781.                 g.goods_ddate IS NULL AND
  782.                 g.goods_status = 1
  783.                 {$where_clause}
  784.             ORDER BY
  785.                 COALESCE(gc.gcl_display, gc.gcl_display, 999),
  786.                 COALESCE(c.color_display, c.color_display, 999)
  787.         ")->FetchAll();
  788.         $map = array();
  789.         foreach($rows as $row){
  790.             $map[$row['goods_id']][] = $row['color_rgb'];
  791.         }
  792.         return $map;
  793.     }
  794.     private function fillItemList$item_part_list$column ){
  795.         $goods_count count($item_part_list);
  796.         $remainder 0;
  797.         
  798.         if($goods_count > (int)$column){
  799.             if( $goods_count $column !== ){
  800.                 $remainder $column - ($goods_count $column);
  801.             }
  802.         }
  803.         else{
  804.             $remainder $column $goods_count;
  805.         }
  806.         if( $remainder !== ){
  807.             for($i 1$i <= $remainder$i++){
  808.                 $item_part_list[] = '<li style="visibility: hidden; order: 99;" />';
  809.             }
  810.         }
  811.         return $item_part_list;
  812.     }
  813.     public function getGoodsBannerOptionMap(){
  814.         // 菅画面で「フォントをカスタマイズ」してない場合のバナーデータ
  815.         $rows = (new SqlService())->Sql('
  816.             SELECT
  817.                 *
  818.             FROM
  819.                 goods_banner_contents_block_option_mst_table
  820.         ')->FetchAll();
  821.         // バナーのマスターデータ(サイズ、色、位置)
  822.         $mst_map = [];
  823.         foreach($rows as $row){
  824.             $row['banner_no'] = (int)$row['banner_no'];
  825.             $row['text_1_size'] = (int)$row['text_1_size'];
  826.             $row['text_2_size'] = (int)$row['text_2_size'];
  827.             $row['description_size'] = (int)$row['description_size'];
  828.             $row['pos_x'] = (int)$row['pos_x'];
  829.             $row['pos_y'] = (int)$row['pos_y'];
  830.             
  831.             $mst_map[$row['banner_no']] = $row;
  832.         }
  833.         // 商品ごとのテキストデータ(商品詳細で設定されるもの)
  834.         $rows = (new SqlService())->Sql('
  835.             SELECT
  836.                 *
  837.             FROM
  838.                 goods_banner_contents_block_option_table
  839.         ')->FetchAll();
  840.         $option_map = [];
  841.         foreach($rows as $row){
  842.             if( !isset($option_map[(int)$row['goods_id']][(int)$row['banner_no']]) ) $option_map[(int)$row['goods_id']][(int)$row['banner_no']] = [];
  843.             $data = &$option_map[(int)$row['goods_id']][(int)$row['banner_no']];
  844.             $data[$row['option_key']] = $row['option_value'];
  845.         }
  846.         unset($data);
  847.         $rows = (new SqlService())->Sql('
  848.             SELECT
  849.                 *
  850.             FROM
  851.                 contents_block_goods_banner_map_table
  852.         ')->FetchAll();
  853.         if( empty($rows) ) return [];
  854.         /**
  855.          * return するマップ生成
  856.          */
  857.         $map = [];
  858.         $goods_id_list = [];
  859.         foreach($rows as $row){
  860.             if (!empty($option_map[(int)$row['goods_id']])) {
  861.                 $map[(int)$row['contents_block_id']] = [];
  862.                 $data = &$map[(int)$row['contents_block_id']];
  863.                 $data['goods_id'] = (int)$row['goods_id'];
  864.                 $data['banner_no'] = (int)$row['banner_no'];
  865.                 $data['show_price'] = (int)$row['show_price'] === self::BOOL_TRUE;
  866.                 $data['show_sale_icon'] = (int)$row['show_sale_icon'] === self::BOOL_TRUE;
  867.                 $data['use_custom_text'] = (int)$row['use_custom_text'] === self::BOOL_TRUE;
  868.                 $data['use_custom_font'] = (int)$row['use_custom_font'] === self::BOOL_TRUE;
  869.                 $data['use_custom_more_text'] = (int)$row['use_custom_more_text'] === self::BOOL_TRUE;
  870.                 $data['use_custom_more_link_url'] = (int)$row['use_custom_more_link_url'] === self::BOOL_TRUE;
  871.                 $goods_id_list[] = (int)$row['goods_id'];
  872.             }
  873.         }
  874.         unset($data);
  875.         
  876.         // 商品情報取得
  877.         $rows = (new SqlService())->Sql('
  878.             SELECT
  879.                 goods_id,
  880.                 goods_name,
  881.                 goods_sub_name,
  882.                 goods_canonical_hinban,
  883.                 goods_main_kataban,
  884.                 shiiresaki_url
  885.             FROM
  886.                 goods_table
  887.             JOIN
  888.                 shiiresaki_table
  889.             ON
  890.                 goods_shiiresaki = shiiresaki_id
  891.             WHERE
  892.                 shiiresaki_url IS NOT NULL AND
  893.                 goods_id IN('.implode(','$goods_id_list).')
  894.         ')->FetchAll();
  895.         $goods_map = [];
  896.         foreach($rows as $row){
  897.             $goods_map[(int)$row['goods_id']] = [
  898.                 'name' => "{$row['goods_name']} {$row['goods_sub_name']}",
  899.                 'kataban' => $row['goods_main_kataban'],
  900.                 'shiiresaki_url' => $row['shiiresaki_url'],
  901.                 'url' => '/item/'.( !empty($row['goods_canonical_hinban']) ? $row['goods_canonical_hinban'] : (!empty($row['goods_main_kataban']) ? $row['goods_main_kataban'] : $row['goods_id']) ).'.html'
  902.             ];
  903.         }
  904.         // ここからデータを生成する。
  905.         foreach($map as $block_id => &$data){
  906.             if( !isset($goods_map[$data['goods_id']]) ){
  907.                 unset($map[$block_id]);
  908.                 continue;
  909.             }
  910.             
  911.             $goods_data $goods_map[$data['goods_id']];
  912.             // バナー画像
  913.             $data['image_src'] = sprintf(
  914.                 self::GOODS_BANNER_IMAGE_PATH,
  915.                 $goods_data['shiiresaki_url'],
  916.                 $goods_data['kataban'],
  917.                 $data['banner_no']
  918.             );
  919.             $data['image_alt'] = $goods_data['name'];
  920.             // テキストデータ
  921.             $option_data $option_map[$data['goods_id']][$data['banner_no']];
  922.             // フォント、位置などのデータ
  923.             $mst_data $mst_map[$data['banner_no']];
  924.             // テキストをカスタマイズする(カスタマイズ時のデータはcontents_block_tableに入っているのでnullにする)
  925.             if( $data['use_custom_text'] ){
  926.                 $data['text_1']      = null;
  927.                 $data['text_2']      = null;
  928.                 $data['description'] = null;
  929.                 $data['pos_x']       = null;
  930.                 $data['pos_y']       = null;
  931.             }
  932.             else{
  933.                 $data['text_1'] = $option_data['text_1'];
  934.                 $data['text_2'] = $option_data['text_2'];
  935.                 $data['description'] = $option_data['description'];
  936.                 $data['pos_x'] = $mst_data['pos_x'];
  937.                 $data['pos_y'] = $mst_data['pos_y'];
  938.             }
  939.             // フォントをカスタマイズする(カスタマイズ時のデータはcontents_block_tableに入っているのでnullにする)
  940.             if( $data['use_custom_font'] ){
  941.                 $data['text_1_size']          = null;
  942.                 $data['text_1_color']         = null;
  943.                 $data['text_1_bg_color']      = null;
  944.                 $data['text_2_size']          = null;
  945.                 $data['text_2_color']         = null;
  946.                 $data['text_2_bg_color']      = null;
  947.                 $data['description_size']     = null;
  948.                 $data['description_color']    = null;
  949.                 $data['description_bg_color'] = null;
  950.             }
  951.             else{
  952.                 $data['text_1_size']          = $mst_data['text_1_size'];
  953.                 $data['text_1_color']         = $mst_data['text_1_color'];
  954.                 $data['text_1_bg_color']      = $mst_data['text_1_bg_color'];
  955.                 $data['text_2_size']          = $mst_data['text_2_size'];
  956.                 $data['text_2_color']         = $mst_data['text_2_color'];
  957.                 $data['text_2_bg_color']      = $mst_data['text_2_bg_color'];
  958.                 $data['description_size']     = $mst_data['description_size'];
  959.                 $data['description_color']    = $mst_data['description_color'];
  960.                 $data['description_bg_color'] = $mst_data['description_bg_color'];
  961.             }
  962.             // もっと見るをカスタマイズする(カスタマイズ時のデータはcontents_block_tableに入っているのでnullにする)
  963.             $data['oneliner_text'] = $data['use_custom_more_text'] ? null $option_data['oneliner_text'];
  964.             $data['url'] = $data['use_custom_more_link_url'] ? null $goods_data['url'];
  965.         }
  966.         
  967.         return $map;
  968.     }
  969.     /**
  970.      * loadHTMLにすると許可されない要素配置が直されてしまう。
  971.      * <h2><span>text1</span><p>text2</p></h2> -> <h2><span>text1</span></h2><p>text2</p>
  972.      * 
  973.      * そこでloadXMLを使いたいがそうすると<img>のとじタグがない、というエラーになるためimgを閉じる。
  974.      * recover = trueでロードすると閉じタグがないというエラーは出なくなるが、後の</div>などの閉じタグを巻き込んで修正してしまうので注意。
  975.      */
  976.     private static function getDomDocumentFromBlockPart($block_part){
  977.         $dom = new \DOMDocument('1.0''utf8');
  978.         
  979.         // 閉じタグ対応
  980.         $block_part preg_replace('!(<img .+?)>!''$1/>'$block_part);
  981.         
  982.         $result = @$dom->loadXML$block_part );
  983.         
  984.         return $result === false false $dom;
  985.     }
  986.     private static function getBlockPartFromDomDocument(\DOMDocument $dom){
  987.         
  988.         @$block_part $dom->saveXML();
  989.         $block_part preg_replace('!<\?xml .+?\?>!'''$block_part);
  990.         
  991.         return mb_convert_encoding($block_part'utf-8''HTML-ENTITIES');
  992.     }
  993.     private static function convertHex2Rgba($hex){
  994.         if( !preg_match('/^#([0-9a-f]{3}|[0-9a-f]{6})$/i'$hex) ) return $hex;
  995.         
  996.         if( strlen$hex ) == $hex substr$hex0) . substr$hex0) . substr$hex1) . substr$hex1) . substr$hex2) . substr$hex2);
  997.         $rgb array_map(
  998.             'hexdec',
  999.             array(
  1000.                 substr$hex0),
  1001.                 substr$hex2),
  1002.                 substr$hex4)
  1003.             )
  1004.         );
  1005.         return 'rgba('.implode(','$rgb).', .5);';
  1006.     }
  1007.     private function setMensLadies($contents_block, &$item_part$goods_data$item_idx){
  1008.         $model_portrait_num_list explode(','$contents_block['model_portrait_num_list']);
  1009.         $model_portrait_pair_num_list explode(','$contents_block['model_portrait_pair_num_list']);
  1010.         $model_portrait_is_2col_image_list explode(','$contents_block['model_portrait_is_2col_image_list']);
  1011.         
  1012.         $model_portrait_num = (int)$model_portrait_num_list[$item_idx];
  1013.         $model_portrait_pair_num = (int)$model_portrait_pair_num_list[$item_idx];
  1014.         $model_portrait_is_2col_image = (int)$model_portrait_is_2col_image_list[$item_idx] === self::BOOL_TRUE;
  1015.         $model_num_list explode(','$contents_block['model_num_list']);
  1016.         $model_num = (int)$model_num_list[$item_idx];
  1017.         // モデル縦長ペア画像は1つだけしか登録されない
  1018.         if( (int)$model_portrait_pair_num === ){
  1019.             $main_src sprintf(
  1020.                 self::MODEL_PORTRAIT_PAIR_IMAGE_PATH,
  1021.                 $goods_data['shiiresaki_url'],
  1022.                 $goods_data['goods_main_kataban']
  1023.             );
  1024.     
  1025.             $item_part str_replace(
  1026.                 '<image-main class="managed-contents-block-item-figure-main" />',
  1027.                 '<img src="'.htmlspecialchars($main_src).'" class="managed-contents-block-item-figure-main" alt="'.htmlspecialchars($goods_data['goods_name']).'" />',
  1028.                 $item_part
  1029.             );
  1030.         }
  1031.         $list_line_idx $item_idx === floor($item_idx 2);    // 商品2個で一列
  1032.         $start_order_num $list_line_idx === $item_idx : ($list_line_idx 2) + $item_idx;
  1033.     
  1034.         $item_part str_replace('<li class="">''<li class="managed-contents-block-item-list-price-li" style="order: '.($start_order_num+2).';">'$item_part);
  1035.         
  1036.         // 2カラム画像を使用している場合、もう片方のmodel_portrait_numは0が入っている
  1037.         $src $model_portrait_num === 0
  1038.             null
  1039.             sprintf(
  1040.                 self::MODEL_PORTRAIT_IMAGE_PATH,
  1041.                 $goods_data['shiiresaki_url'],
  1042.                 $goods_data['goods_main_kataban'],
  1043.                 $model_portrait_num
  1044.             )
  1045.         ;
  1046.         $li_2col_class '';
  1047.         // 「2カラム画像として表示」がチェックされている
  1048.         if( $model_portrait_is_2col_image ){
  1049.             $li_2col_class 'managed-contents-block-item-list-full-height-2col-li';
  1050.             if( $item_idx === ){
  1051.                 $li_2col_class .= ' managed-contents-block-item-list-hide-after-li';
  1052.             }
  1053.             else{
  1054.                 $li_2col_class .= ' managed-contents-block-item-list-hide-before-li';
  1055.             }
  1056.         }
  1057.         if( is_null($src) ){
  1058.             $pair_li sprintf('
  1059.                     <li class="managed-contents-block-item-list-full-height-li %s" style="order: %d;"></li>
  1060.                 ',
  1061.                 $li_2col_class,
  1062.                 $start_order_num
  1063.             );
  1064.         }
  1065.         else{
  1066.             $pair_li sprintf('
  1067.                     <li class="managed-contents-block-item-list-full-height-li %s" style="order: %d;">
  1068.                         <a href="%s"><img src="%s" alt="%s"></a>
  1069.                     </li>
  1070.                 ',
  1071.                 $li_2col_class,
  1072.                 $start_order_num,
  1073.                 htmlspecialchars($goods_data['uri']),
  1074.                 htmlspecialchars($src),
  1075.                 htmlspecialchars($goods_data['goods_name'])
  1076.             );
  1077.         }
  1078.         $item_part $pair_li.$item_part;
  1079.     }
  1080.     private function setAdditionalText($block_part$contents_block){
  1081.         $additional_midashi $contents_block['additional_midashi'];
  1082.         $additional_description $contents_block['additional_description'];
  1083.         $additional_midashi_color $contents_block['additional_midashi_color'];
  1084.         
  1085.         $additional_description_color $contents_block['additional_description_color'];
  1086.         $midashi_style '';
  1087.         $midashi_style .= !empty($additional_midashi_color) ? "color: {$additional_midashi_color}; " '';
  1088.         $description_style '';
  1089.         $description_style .= !empty($additional_description_color) ? "color: {$additional_description_color}; " '';
  1090.         $html sprintf('
  1091.                 <div id="managed-contents-block-additional-text">
  1092.                     <h3 id="managed-contents-block-additional-midashi" style="%s">%s</h3>
  1093.                     <span id="managed-contents-block-additional-description" style="%s">%s</span>
  1094.                 </div>
  1095.             ',
  1096.             $midashi_style,
  1097.             htmlspecialchars($additional_midashi),
  1098.             $description_style,
  1099.             nl2brhtmlspecialchars($additional_description) )
  1100.         );
  1101.         return str_replace('<div class="managed-contents-block-body">''<div class="managed-contents-block-body">'.$html$block_part);
  1102.     }
  1103.     private function set2colLi(&$item_part_list){
  1104.         foreach($item_part_list as $idx => $item_part){
  1105.             unset($hide_li);
  1106.             if( preg_match('/managed-contents-block-item-list-hide-before-li/'$item_part) ){
  1107.                 if( isset($item_part_list[$idx 1]) ) $hide_li = &$item_part_list[$idx 1];
  1108.             }
  1109.             else if( preg_match('/managed-contents-block-item-list-hide-after-li/'$item_part) ){
  1110.                 if( isset($item_part_list[$idx 1]) ) $hide_li = &$item_part_list[$idx 1];
  1111.             }
  1112.             
  1113.             // style="order: xx"を指定しているので必ずstyle=の定義がある
  1114.             if( isset($hide_li) ) $hide_li preg_replace(
  1115.                 '/^(.+?managed-contents-block-item-list-full-height-li.+?)style=".+?"(.+)$/s',
  1116.                 '$1 style="display: none;" $2',
  1117.                 $hide_li
  1118.             );
  1119.             
  1120.         }
  1121.     }
  1122.     private static function setColorTip(&$item_part$goods_data){
  1123.         // カラーチップ
  1124.         if( empty($goods_data['color']) ){
  1125.             $item_part preg_replace(
  1126.                 '!<div class="managed-contents-block-item-description-color-tip">[\r\n\t]+<div class="managed-contents-block-item-description-color-tip-count"><span></span>COLOR</div>[\r\n\t]+<ul><goods_color_tip_list /></ul>[\r\n\t]+</div>!',
  1127.                 '',
  1128.                 $item_part
  1129.             );
  1130.         }
  1131.         else{
  1132.             $item_part str_replace(
  1133.                 '<div class="managed-contents-block-item-description-color-tip-count"><span></span>COLOR</div>',
  1134.                 '<div class="managed-contents-block-item-description-color-tip-count"><span>'.count($goods_data['color']).'</span>COLOR</div>',
  1135.                 $item_part
  1136.             );
  1137.             $item_part str_replace(
  1138.                 '<goods_color_tip_list />',
  1139.                 implode(''array_map( function($rgb){
  1140.                     return '<li style="background: #'.htmlspecialchars($rgb).'"></li>';
  1141.                 }, $goods_data['color'])),
  1142.                 $item_part
  1143.             );
  1144.         }
  1145.     }
  1146.     private static function setHinban($contents_block, &$item_part$goods_data$item_idx){
  1147.         $display_name_list explode(','$contents_block['display_name_list']);
  1148.         $display_name_color_list explode(','$contents_block['display_name_color_list']);
  1149.         $display_name_bg_color_list explode(','$contents_block['display_name_bg_color_list']);
  1150.         $display_name $display_name_list[$item_idx];
  1151.         $display_name_color = isset($display_name_color_list[$item_idx]) ? $display_name_color_list[$item_idx] : null;
  1152.         $display_name_bg_color = isset($display_name_bg_color_list[$item_idx]) ? $display_name_bg_color_list[$item_idx] : null;
  1153.         // 型番
  1154.         $item_part str_replace(
  1155.             '<goods-kataban />',
  1156.             nl2brhtmlspecialchars( !empty($display_name) ? $display_name $goods_data['goods_main_kataban'] ) ),
  1157.             $item_part
  1158.         );
  1159.         $kataban_style '';
  1160.         if( !empty($display_name_color) ) $kataban_style .= "color: {$display_name_color}; ";
  1161.         if( !empty($display_name_bg_color) )  $kataban_style .= "background-color: {$display_name_bg_color}; ";
  1162.         if( $kataban_style !== '' ){
  1163.             $item_part str_replace(
  1164.                 'managed-contents-block-item-description-kataban"',
  1165.                 'managed-contents-block-item-description-kataban" style="'.$kataban_style.'"',
  1166.                 $item_part
  1167.             );
  1168.         }
  1169.     }
  1170.     private static function setPrice(&$item_part$goods_data){
  1171.         // 価格(コーデの価格もあるのでlimit 1にする)
  1172.         $item_part preg_replace('/data-item-id=""/''data-item-id="'.$goods_data['goods_id'].'"'$item_part1);
  1173.     }
  1174.     private static function setLink(&$item_part$goods_data){
  1175.         $item_part str_replace(
  1176.             '<a href="">',
  1177.             '<a href="'.htmlspecialchars($goods_data['uri']).'">',
  1178.             $item_part
  1179.         );
  1180.     }
  1181.     private static function setMainImage($contents_block, &$item_part$goods_data$item_idx){
  1182.         $model_num_list explode(','$contents_block['model_num_list']);
  1183.         $model_num = (int)$model_num_list[$item_idx];
  1184.         if( (int)$model_num === ){
  1185.             $main_src sprintf(
  1186.                 self::KIHON_IMAGE_PATH,
  1187.                 $goods_data['shiiresaki_url'],
  1188.                 $goods_data['goods_main_kataban']
  1189.             );
  1190.         }
  1191.         // モデル画像
  1192.         else{
  1193.             $column_num $contents_block['column_number'];
  1194.             $main_src sprintf(
  1195.                 self::MODEL_IMAGE_PATH,
  1196.                 $goods_data['shiiresaki_url'],
  1197.                 $goods_data['goods_main_kataban'],
  1198.                 $model_num,
  1199.                 $column_num
  1200.             );
  1201.         }
  1202.         $item_part str_replace(
  1203.             '<image-main class="managed-contents-block-item-figure-main" />',
  1204.             '<img src="'.htmlspecialchars($main_src).'" class="managed-contents-block-item-figure-main" alt="'.htmlspecialchars($goods_data['goods_name']).'" />',
  1205.             $item_part
  1206.         );
  1207.         // 画像タイプ
  1208.         if( (int)$contents_block['item_image_type'] === self::ITEM_IMAGE_TYPE_GOODS $item_part str_replace('"managed-contents-block-item-figure"''"managed-contents-block-item-figure managed-contents-block-item-figure-goods"'$item_part);
  1209.         if( (int)$contents_block['item_image_type'] === self::ITEM_IMAGE_TYPE_MODEL $item_part str_replace('"managed-contents-block-item-figure"''"managed-contents-block-item-figure managed-contents-block-item-figure-model"'$item_part);
  1210.     }
  1211.     private static function setDirectDeliveryImage($contents_block, &$item_part$goods_data$item_idx){
  1212.         $model_num_list explode(','$contents_block['model_num_list']);
  1213.         $model_num = (int)$model_num_list[$item_idx];
  1214.         if(
  1215.             $model_num &&
  1216.             === (int)($goods_data["goods_show_marks_above_model_banner_{$model_num}"]) &&
  1217.             === (int)$goods_data["goods_show_direct_mark_below_model_banner_{$model_num}"]
  1218.         ){
  1219.             $column_num $contents_block['column_number'];
  1220.             $chokusou_src '/images/itempage/chokusou/banner'.$goods_data['shiiresaki_id'].'_'.$column_num.'col.jpg';
  1221.             $item_part str_replace(
  1222.                 '<image-sokujitsu class="managed-contents-block-item-figure-sokujitsu" />',
  1223.                 '<img src="'.htmlspecialchars($chokusou_src).'" class="managed-contents-block-item-figure-sokujitsu" alt="この商品は即日配送できます" />',
  1224.                 $item_part
  1225.             );
  1226.         }
  1227.         else{
  1228.             $item_part str_replace(
  1229.                 '<image-sokujitsu class="managed-contents-block-item-figure-sokujitsu" />',
  1230.                 '',
  1231.                 $item_part
  1232.             );
  1233.         }
  1234.     }
  1235.     
  1236.     private static function setDescriptionText($contents_block, &$item_part$goods_data){
  1237.         $model_num_list explode(','$contents_block['model_num_list']);
  1238.         $column_num $contents_block['column_number'];
  1239.         $item_part str_replace(
  1240.             '<goods-description-text />',
  1241.             is_null($goods_data["goods_series_{$column_num}column_caption"]) ? '' htmlspecialchars$goods_data["goods_series_{$column_num}column_caption"] ),
  1242.             $item_part
  1243.         );
  1244.     }
  1245. }