<?php 
 
/** 
 * CategoryContentsBlockMapModel.php 
 * @author: worker_h 
 */ 
 
namespace Lm\Engine\EC\Entity; 
 
use Lm\Service\Db\SqlService; 
 
class CategoryContentsBlockMapModel 
{ 
 
    const TEMPLATE_NAME_BLOCK = 'category-col-block'; 
    const TEMPLATE_NAME_ITEM_BLOCK_NORMAL = 'category-col-item-block-normal'; 
    const TEMPLATE_NAME_ITEM_BLOCK_MENS_LADIES = 'category-col-item-block-mens-ladies'; 
    const KIHON_IMAGE_PATH = '/item/kihon/%s/%s.jpg'; 
    const MODEL_IMAGE_PATH = '/item/kihon/%s/%s-%d-%dcol.jpg';    // バインドするのは「仕入先URL」「型番」「モデル番号」「カラム数」 
    const MODEL_PORTRAIT_IMAGE_PATH = '/item/kihon/%s/%s-portrait-%d-4col.jpg';    // バインドするのは「仕入先URL」「型番」「モデル縦長番号」(モデル縦長画像は4カラムのみ) 
    const MODEL_PORTRAIT_PAIR_IMAGE_PATH = '/item/kihon/%s/%s-portrait-pair-4col.jpg';    // バインドするのは「仕入先URL」「型番」(モデル縦長ペア画像は4カラムのみ) 
    const IMAGE_COORDINATE_PATH = '/item/kihon/%s/%s-%d-%dcol-coo%d.jpg';    // バインドするのは「仕入先URL」「型番」「モデル番号」「カラム数」「コーデ番号-」 
    const GOODS_BANNER_IMAGE_PATH = '/item/kihon/%s/%s-%d-1col.jpg';    // バインドするのは「仕入先URL」「型番」「バナー番号」 
 
    const HEADER_TYPE_MIDASHI           = 1;    // 見出し 
    const HEADER_TYPE_ONLY_IMAGE        = 2;    // 画像のみ 
    const HEADER_TYPE_MIDASHI_AND_IMAGE = 3;    // 見出し+画像 
    const HEADER_TYPE_HTML              = 4;    // 自由記述 
    const HEADER_TYPE_NO_HEADER         = 5;    // ヘッダーなし 
    const HEADER_TYPE_ITEM_BANNER       = 6;    // 商品バナー 
 
    const ITEM_IMAGE_TYPE_GOODS = 1;    // 商品 
    const ITEM_IMAGE_TYPE_MODEL = 2;    // モデル 
 
    const DESIGN_TYPE_NORMAL      = 1;    // 標準 
    const DESIGN_TYPE_MENS_LADIES = 2;    // メンズ・レディース系 
 
    const RANK_MARK_NORMAL = 1;        // 標準 
    const RANK_MARK_CROWN  = 2;        // 王冠 
 
    // もっと見る 表示タイプ 
    const MORE_TYPE_DISABLED = 0;        // ボタン 
    const MORE_TYPE_BUTTON = 1;            // ボタン 
    const MORE_TYPE_ONELINER_TEXT = 2;    // 1行テキスト 
     
    const BOOL_TRUE = 1; 
    const BOOL_FALSE = 0; 
 
    public function getContentsBlockMapById($main_category_id, $category_id=null){ 
 
        $map = array(); 
        $rows = (array)(new SqlService())->Sql(' 
            SELECT 
                main_category_id, 
                category_id, 
                block_position, 
                GROUP_CONCAT(contents_block_id ORDER BY block_order) AS contents_block_id_list 
            FROM 
                category_contents_block_map_table  
            WHERE 
                main_category_id = :main_category_id AND 
                IFNULL(category_id, 0) = :category_id 
            GROUP BY 
                main_category_id, category_id, block_position 
        ')->Params([ 
            'main_category_id' => $main_category_id, 
            'category_id' => (int)$category_id, 
        ])->FetchAll(); 
 
        $block_id_list = array(); 
        foreach($rows as $row){ 
            $block_id_list = array_merge($block_id_list, explode(',', $row['contents_block_id_list'])); 
        } 
 
        $block_id_list = array_unique($block_id_list); 
        $block_map = $this->getContentsBlockMap($block_id_list); 
 
        foreach($rows as $row){ 
            // ブロックidごとの処理 
            foreach( explode(',', $row['contents_block_id_list']) as $block_id ){ 
                if( !isset($block_map[$block_id]) ) continue; 
                $map[$row['block_position']][] = $block_map[$block_id]; 
            } 
        } 
 
        return $map; 
    } 
 
 
 
 
    private function getContentsBlockMap($id_list){ 
 
        if( !is_array($id_list) || empty($id_list) ) return array(); 
 
        // 必要なテンプレートがなければ抜ける。 
        $template = $this->getTemplate(); 
        if( 
            !isset($template[self::TEMPLATE_NAME_BLOCK]) || 
            !isset($template[self::TEMPLATE_NAME_ITEM_BLOCK_NORMAL]) || 
            !isset($template[self::TEMPLATE_NAME_ITEM_BLOCK_MENS_LADIES]) 
        ) return array(); 
 
        $block_tamplate = $template[self::TEMPLATE_NAME_BLOCK]; 
        $contents_block_list = $this->getContentsBlockList($id_list); 
         
        // ブロックコンテンツがなければ抜ける。 
        if( empty($contents_block_list) ) return array(); 
 
        // 最後のブロックID 
        $last_block_id = $id_list[ count($id_list) - 1 ]; 
 
        $contents_block_map = $goods_id_list = array(); 
        foreach($contents_block_list as $contents_block){ 
            // 「ヘッダーのみ」の場合goods_id_listがnullになっている 
            if( is_null($contents_block['goods_id_list']) ) continue; 
 
            $goods_id_list = array_merge($goods_id_list, explode(',', $contents_block['goods_id_list'])); 
        } 
 
        // 商品情報有無(ブロックの商品有無ではなく、全コンテンツブロックの商品有無) 
        if( !empty($goods_id_list) ){ 
            $goods_id_list = array_unique($goods_id_list); 
 
            // 商品情報取得 
            $item_data_map = $this->getItemDataMap($goods_id_list); 
            $kataban_map = $this->getGoodsKatabanMap(); 
        } 
 
        // 商品バナー情報 
        $goods_banner_option_map = $this->getGoodsBannerOptionMap(); 
 
        $map = array(); 
 
        // ブロックにデータを構築(ブロックごとの処理) 
        $column_number_before = null;        // ヘッダーなしの上のブロックとのマージン調整のため、前のカラム数を記録しておく。 
        foreach($contents_block_list as $block_idx => $contents_block){ 
             
            // 基本要素にあてるクラス 
            $base_block_class_list = array('managed-contents-block-'.(int)$contents_block['column_number'].'col'); 
 
            // 最後のブロッククラス 
            if( (int)$last_block_id === (int)$contents_block['contents_block_id'] ){ 
                $base_block_class_list[] = 'managed-contents-block-last'; 
            } 
             
            // 商品リストデザインによってクラスをわける 
            switch( (int)$contents_block['design_type'] ){ 
                // メンズ・レディース系 
                case self::DESIGN_TYPE_MENS_LADIES: 
                    $base_block_class_list[] = 'managed-contents-block-item-list-mens-ladies'; 
                    break; 
                default: 
                    break; 
            } 
             
            $block_part = $template[self::TEMPLATE_NAME_BLOCK]; 
 
            switch((int)$contents_block['header_type']){ 
                case self::HEADER_TYPE_MIDASHI: 
                    $this->setMidashiHeaderToContents($block_part, $contents_block); 
                    break; 
                case self::HEADER_TYPE_ONLY_IMAGE: 
                    $this->setImageHeaderToContents($block_part, $contents_block); 
                    break; 
                case self::HEADER_TYPE_MIDASHI_AND_IMAGE: 
                    $this->setMidashiImageHeaderToContents($block_part, $contents_block, $base_block_class_list); 
                    break; 
                case self::HEADER_TYPE_HTML: 
                    $this->setHtmlHeaderToContents($block_part, $contents_block); 
                    break; 
                case self::HEADER_TYPE_NO_HEADER: 
                    $this->setNoHeaderToContents($block_part, $contents_block, $column_number_before, $base_block_class_list); 
                    break; 
                case self::HEADER_TYPE_ITEM_BANNER: 
                    $this->setItemBannerHeaderToContents($block_part, $contents_block, $base_block_class_list, $goods_banner_option_map); 
                     
                    // 商品バナーの時のテキスト、リンクの上書き処理 
                    if( 
                        (int)$contents_block['more_button_type'] === self::MORE_TYPE_ONELINER_TEXT && 
                        isset($goods_banner_option_map[$contents_block['contents_block_id']]) 
                    ){ 
                        $goods_banner_data = $goods_banner_option_map[$contents_block['contents_block_id']]; 
                         
                        if( !empty($goods_banner_data['oneliner_text']) ) $contents_block['more_button_text'] = $goods_banner_data['oneliner_text']; 
                        if( !empty($goods_banner_data['url']) ) $contents_block['more_button_link_url'] = $goods_banner_data['url']; 
                    } 
 
                    break; 
            } 
 
            $column_number_before = (int)$contents_block['column_number']; 
 
            $this->setDescriptionToContents($block_part, $contents_block); 
 
            // もっと見る 
            if( 
                (int)$contents_block['more_button_type'] !== self::MORE_TYPE_DISABLED && 
                !empty($contents_block['more_button_text']) && 
                !empty($contents_block['more_button_link_url']) 
            ){ 
                $class_name = ''; 
                switch( (int)$contents_block['more_button_type'] ){ 
                    case self::MORE_TYPE_BUTTON: 
                        $class_name = 'managed-contents-block-more-link-button'; 
                        break; 
                    case self::MORE_TYPE_ONELINER_TEXT: 
                        $class_name = 'managed-contents-block-more-link-oneliner-text'; 
                        break; 
                } 
                $block_part = str_replace( 
                    '<div class="managed-contents-block-footer"></div>', 
                    '<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>', 
                    $block_part 
                ); 
            } 
            else{ 
                $block_part = str_replace('<div class="managed-contents-block-footer"></div>', '', $block_part); 
            } 
 
            // 色設定 
            $block_part = $this->setColor($block_part, $contents_block); 
 
            // 基本要素にクラスを当てる 
            $block_part = str_replace( 
                '<div class="managed-contents-block"', 
                '<div class="managed-contents-block '.implode(' ', $base_block_class_list).'"', 
                $block_part 
            ); 
 
 
            // ブロックに商品情報がなければ商品リスト箇所を削除してマップに入れて次のブロックへ 
            if( is_null($contents_block['goods_id_list']) ) { 
                $block_part = str_replace('<goods-list />', '', $block_part); 
                $map[$contents_block['contents_block_id']] = $block_part; 
                continue; 
            } 
 
 
            // 商品ごとの処理 
            $item_part_list = array(); 
            $goods_count = 1; 
            foreach( explode(',', $contents_block['goods_id_list']) as $idx => $goods_id ){ 
 
                // 商品情報がなければ次へ 
                if( !isset($item_data_map[$goods_id]) ) continue; 
 
                $goods_data = $item_data_map[$goods_id]; 
                $block_class = ''; 
 
                // 商品リストのデザインタイプ 
                switch( (int)$contents_block['design_type'] ){ 
                    case self::DESIGN_TYPE_NORMAL: 
                        $item_part = $template[self::TEMPLATE_NAME_ITEM_BLOCK_NORMAL]; 
                        break; 
                    case self::DESIGN_TYPE_MENS_LADIES: 
                        $item_part = $template[self::TEMPLATE_NAME_ITEM_BLOCK_MENS_LADIES]; 
                        $goods_data['color'] = array_slice($goods_data['color'], 0, 10);    // カラーチップは最大10個まで 
                        break; 
                } 
                 
                $item_part = $this->setItem( 
                    $item_part,  
                    $goods_data,  
                    $contents_block,  
                    $kataban_map,  
                    $idx, 
                    $goods_count++ 
                ); 
                 
                $item_part_list[] = $item_part; 
            } 
 
            // 商品リストデザインが「メンズ・レディース系」(space-betweenじゃないのでliを補完する必要なし) 
            if( (int)$contents_block['design_type'] === self::DESIGN_TYPE_MENS_LADIES ){ 
                // 2カラム画像として表示の時、非2colのliを隠す処理 
                $this->set2colLi( $item_part_list ); 
            } 
            // 不足分のliを埋める(間隔調整などspace-betweenの方が楽なので、space-between+不足分を埋める実装) 
            else{ 
                $item_part_list = $this->fillItemList( $item_part_list, $contents_block['column_number'] ); 
            } 
 
            $block_part = str_replace('<goods-list />', implode('', $item_part_list), $block_part); 
             
            // 補足説明テキストを追加 
            if( (int)$contents_block['design_type'] === self::DESIGN_TYPE_MENS_LADIES ){ 
                $block_part = $this->setAdditionalText($block_part, $contents_block); 
            } 
 
            $map[$contents_block['contents_block_id']] = $block_part; 
        } 
         
        return $map; 
    } 
 
 
 
 
    private function setNoHeaderToContents(&$block_part, $contents_block, $column_number_before, &$base_block_class_list){ 
        if( !is_null($column_number_before) ){ 
            $base_block_class_list[] = 'managed-contents-block-no-header'; 
        } 
        $block_part = str_replace('<div class="managed-contents-block-midashi-image"></div>', '', $block_part); 
        $block_part = preg_replace('!<div class="managed-contents-block-header-text-wrap">.*?</div>!s', '', $block_part); 
        $block_part = str_replace('<div class="managed-contents-block-header-html"></div>', '', $block_part); 
        $block_part = preg_replace('!<div class="managed-contents-block-header">.*?</div>!s', '', $block_part); 
    } 
 
 
 
 
    private function setHtmlHeaderToContents(&$block_part, $contents_block){ 
        $block_part = str_replace('<div class="managed-contents-block-midashi-image"></div>', '', $block_part); 
        $block_part = preg_replace('!<div class="managed-contents-block-header-text-wrap">.*?</div>!s', '', $block_part); 
        $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); 
    } 
 
 
 
 
    private function setMidashiImageHeaderToContents(&$block_part, $contents_block, &$base_block_class_list){ 
        $base_block_class_list[] = 'managed-contents-block-midashi-and-text'; 
        $this->setMidashiHeaderToContents($block_part, $contents_block); 
        $this->setImageHeaderToContents($block_part, $contents_block, false); 
         
        $style = sprintf('style="top: %dpx; left: %dpx"', $contents_block['header_text_pos_y'], $contents_block['header_text_pos_x']); 
        $block_part = str_replace('<div class="managed-contents-block-header-text-wrap">', '<div class="managed-contents-block-header-text-wrap" '.$style.'>', $block_part); 
        $block_part = str_replace('<midashi-header-description />', nl2br($contents_block['header_description']), $block_part); 
    } 
 
 
 
 
    private function setItemBannerHeaderToContents(&$block_part, $contents_block, &$base_block_class_list, $goods_banner_option_map){ 
         
        if( !isset($goods_banner_option_map[$contents_block['contents_block_id']]) ) return; 
 
        // バナーデータ 
        $goods_banner_data = $goods_banner_option_map[$contents_block['contents_block_id']]; 
        $base_block_class_list[] = 'managed-contents-block-goods-banner'; 
         
        // バナーデータで見出しなどのデータを上書き 
        $contents_block['header_image_url'] = $goods_banner_data['image_src']; 
        $contents_block['header_image_alt'] = $goods_banner_data['image_alt']; 
        if( !is_null($goods_banner_data['text_1']) ) $contents_block['midashi_large'] = $goods_banner_data['text_1']; 
        if( !is_null($goods_banner_data['text_2']) ) $contents_block['midashi_small'] = $goods_banner_data['text_2']; 
        if( !is_null($goods_banner_data['description']) ) $contents_block['header_description'] = $goods_banner_data['description']; 
        if( !is_null($goods_banner_data['pos_x']) ) $contents_block['header_text_pos_x'] = $goods_banner_data['pos_x']; 
        if( !is_null($goods_banner_data['pos_y']) ) $contents_block['header_text_pos_y'] = $goods_banner_data['pos_y']; 
 
        // 見出しと画像をセット 
        $this->setMidashiHeaderToContents($block_part, $contents_block); 
        $this->setItemBannerImageToHeaderContents($block_part, $contents_block); 
         
        // ブロックdom 
        // DOM修正が複雑になるためDOMDocumentを使用する。 
        $dom = self::getDomDocumentFromBlockPart($block_part); 
        if( !$dom ) return; 
         
        // バナーアンカーエレメント 
        $banner_a_elem = null; 
 
        // バナー全体に商品ページへのリンクを設置 
        foreach( $dom->getElementsByTagName('div') as $elem ){ 
            if( $elem->getAttribute('class') !== 'managed-contents-block-midashi-image' ) continue; 
 
            $banner_a_elem = $dom->createElement('a'); 
            $banner_a_elem->setAttribute('class', 'managed-contents-block-goods-banner-link'); 
            $banner_a_elem->setAttribute('href', $goods_banner_data['url']); 
            $elem->appendChild( $banner_a_elem ); 
            break; 
        } 
 
        // 画像をバナーに移す 
        $banner_img_elem = $dom->getElementsByTagName('img')->item(0); 
        if( !is_null($banner_img_elem) ){ 
            $banner_a_elem->appendChild($banner_img_elem); 
        } 
 
        // テキストエリアをバナーに移す 
        foreach( $dom->getElementsByTagName('div') as $elem ){ 
            if( $elem->getAttribute('class') !== 'managed-contents-block-header-text-wrap' ) continue; 
 
            // ポジションセット 
            $elem->setAttribute('style', sprintf( 
                'top: %dpx; left: %dpx', 
                $contents_block['header_text_pos_y'], 
                $contents_block['header_text_pos_x'] 
            )); 
 
            $banner_a_elem->appendChild($elem); 
            break; 
        } 
 
         
        $replace_elem = $banner_a_elem->getElementsByTagName('midashi-header-description')->item(0); 
        if( !is_null($replace_elem) ) $replace_elem->parentNode->removeChild($replace_elem); 
 
        // バナー説明文設置 
        foreach( $banner_a_elem->getElementsByTagName('p') as $p_elem ){ 
            if( $p_elem->getAttribute('class') !== 'managed-contents-block-header-description' ) continue; 
 
            $inner = $dom->createElement('span'); 
            $inner->setAttribute('class', 'managed-contents-block-header-description-inner'); 
            $text = nl2br( htmlspecialchars($contents_block['header_description']) ); 
            $inner->appendChild( $dom->createTextNode($text) ); 
            $p_elem->appendChild( $inner ); 
            break; 
        }; 
 
        // フォント設定を反映 
        if($goods_banner_data['text_1_size']) $contents_block['midashi_large_size'] = $goods_banner_data['text_1_size']; 
        if($goods_banner_data['text_1_color']) $contents_block['midashi_large_color'] = $goods_banner_data['text_1_color']; 
        if($goods_banner_data['text_1_bg_color']) $contents_block['midashi_large_bg_color'] = $goods_banner_data['text_1_bg_color']; 
        if($goods_banner_data['text_2_size']) $contents_block['midashi_small_size'] = $goods_banner_data['text_2_size']; 
        if($goods_banner_data['text_2_color']) $contents_block['midashi_small_color'] = $goods_banner_data['text_2_color']; 
        if($goods_banner_data['text_2_bg_color']) $contents_block['midashi_small_bg_color'] = $goods_banner_data['text_2_bg_color']; 
        if($goods_banner_data['description_size']) $contents_block['header_description_size'] = $goods_banner_data['description_size']; 
        if($goods_banner_data['description_color']) $contents_block['header_description_color'] = $goods_banner_data['description_color']; 
        if($goods_banner_data['description_bg_color']) $contents_block['header_description_bg_color'] = $goods_banner_data['description_bg_color']; 
 
        $has_bg_color_class = 'managed-contents-block-text-has-bg-color'; 
        $use_shadow_class = 'managed-contents-block-text-shadow'; 
 
        /** 
         * @var \DOMNode $elem 
         */ 
        foreach( $banner_a_elem->getElementsByTagName('*') as $elem ){ 
 
            if( !in_array( 
                $elem->getAttribute('class'), 
                [ 
                    'managed-contents-block-midashi-large', 
                    'managed-contents-block-midashi-small', 
                    'managed-contents-block-header-description-inner' 
                ] 
            )) continue; 
 
            $style = []; 
            $add_class = ''; 
            $style_text = ''; 
 
            switch( $elem->getAttribute('class') ){ 
                // 見出し1 
                case 'managed-contents-block-midashi-large': 
                    if( !empty($contents_block['midashi_large_size']) ) $style[] = "font-size: {$contents_block['midashi_large_size']}px;"; 
                    if( !empty($contents_block['midashi_large_color']) ) $style[] = "color: {$contents_block['midashi_large_color']};"; 
                    if( !empty($contents_block['midashi_large_bg_color']) && !empty($elem->textContent) ){ 
                        $style[] = "background: {$contents_block['midashi_large_bg_color']};"; 
                        $add_class = $has_bg_color_class; 
                    } 
                    if( (int)$contents_block['midashi_large_use_shadow'] === 1 ){ 
                        $add_class .= ' '.$use_shadow_class; 
                    } 
                    break; 
 
                // 見出し2 
                case 'managed-contents-block-midashi-small': 
                    if( !empty($contents_block['midashi_small_size']) ) $style[] = "font-size: {$contents_block['midashi_small_size']}px;"; 
                    if( !empty($contents_block['midashi_small_color']) ) $style[] = "color: {$contents_block['midashi_small_color']};"; 
                    if( !empty($contents_block['midashi_small_bg_color']) ){ 
                        $style[] = "background: {$contents_block['midashi_small_bg_color']};"; 
                        $add_class = $has_bg_color_class; 
                    } 
                    if( (int)$contents_block['midashi_small_use_shadow'] === 1 ){ 
                        $add_class .= ' '.$use_shadow_class; 
                    } 
                    break; 
 
                // 説明文 
                case 'managed-contents-block-header-description-inner': 
                    if( !empty($contents_block['header_description_size']) ) $style[] = "font-size: {$contents_block['header_description_size']}px;"; 
                    if( !empty($contents_block['header_description_color']) ) $style[] = "color: {$contents_block['header_description_color']};"; 
                    if( !empty($contents_block['header_description_bg_color']) ){ 
                        $style[] = "background: {$contents_block['header_description_bg_color']};"; 
                        $add_class = $has_bg_color_class; 
                    } 
                    break; 
            } 
 
            $style_text = empty($style) ? '' : implode(' ', $style); 
            $class = $elem->getAttribute('class').' '.$add_class; 
            $elem->setAttribute('class', $class); 
            $elem->setAttribute('style', $style_text); 
        } 
 
        // 価格表示 
        // 価格ajaxの実装に合わせるため、get-price-ajax、throughの位置を調整 
        // 価格ajaxの数字が基準になるため、パーセンテージアイコンはJSで出力する以外方法がない。 
        if( $goods_banner_data['show_price'] ){ 
            $banner_a_elem->appendChild( $dom->createTextNode(' 
                <span class="managed-contents-block-retail-prices">希望小売価格 <span class="through"></span></span> 
                <div class="managed-contents-block-price-box"> 
                    <div class="managed-contents-block-list-price through"></div> 
                    <div> 
                        <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> 
                    </div> 
                </div> 
            ')); 
        } 
 
        // SALEアイコン 
        if( $goods_banner_data['show_sale_icon'] ){ 
            $banner_a_elem->appendChild( $dom->createTextNode(' 
                <div class="managed-contents-block-sale-icon"> 
                    <img /> 
                </div> 
            ')); 
        } 
 
        $block_part = self::getBlockPartFromDomDocument($dom); 
 
        // DOMDocumentで整形された箇所を元に戻す 
        $block_part = str_replace('<description/>', '<description />', $block_part); 
        $block_part = str_replace('<goods-list/>', '<goods-list />', $block_part); 
        $block_part = str_replace('<div class="managed-contents-block-footer"/>', '<div class="managed-contents-block-footer"></div>', $block_part); 
 
        // 不要な要素を削除 
        $block_part = str_replace('<div class="managed-contents-block-header-html"/>', '', $block_part); 
         
    } 
 
 
 
 
    private function setImageHeaderToContents(&$block_part, $contents_block, $delete_other=true){ 
        $img = sprintf( 
            '<img src="%s" alt="%s">', 
            // CFIMG_URL . preg_replace('!^/+ut_img/!', '', $contents_block['header_image_url']), 
            $contents_block['header_image_url'], 
            htmlspecialchars($contents_block['header_image_alt']) 
        ); 
 
        $block_part = str_replace('<div class="managed-contents-block-midashi-image"></div>', '<div class="managed-contents-block-midashi-image">'.$img.'</div>', $block_part); 
 
        if(!$delete_other) return; 
        $block_part = preg_replace('!<div class="managed-contents-block-header-text-wrap">.+?</div>!s', '', $block_part); 
    } 
 
 
 
    /** 
     * @todo ヘッダーの画像操作を統一 
     */ 
    private function setItemBannerImageToHeaderContents(&$block_part, $contents_block){ 
        $img = sprintf( 
            '<img src="%s" alt="%s">', 
            $contents_block['header_image_url'], 
            htmlspecialchars($contents_block['header_image_alt']) 
        ); 
 
        $block_part = str_replace('<div class="managed-contents-block-midashi-image"></div>', '<div class="managed-contents-block-midashi-image">'.$img.'</div>', $block_part); 
    } 
 
 
 
 
    private function setDescriptionToContents(&$block_part, $contents_block){ 
        // 説明文非表示 
        if( (int)$contents_block['show_description'] === 0 ){ 
            $block_part = str_replace('<p class="managed-contents-block-description"><description /></p>', '', $block_part); 
            return; 
        } 
         
        // ボーダー非表示 
        if( (int)$contents_block['show_description_border'] === 0 ){ 
            $block_part = str_replace('class="managed-contents-block-description"', 'class="managed-contents-block-description managed-contents-block-description-no-border"', $block_part); 
        } 
 
        $block_part = str_replace('<description />', nl2br(htmlspecialchars($contents_block['description'])), $block_part); 
    } 
 
 
 
 
    private function setMidashiHeaderToContents(&$block_part, $contents_block){ 
        // 大見出し 
        $block_part = str_replace('<midashi-large />', htmlspecialchars($contents_block['midashi_large']), $block_part); 
 
        // 小見出し 
        if( empty($contents_block['midashi_small']) ){ 
            $block_part = str_replace('<p class="managed-contents-block-midashi-small"><midashi-small /></p>', '', $block_part); 
        } 
        else{ 
            $block_part = str_replace('<midashi-small />', htmlspecialchars($contents_block['midashi_small']), $block_part); 
        } 
    } 
 
 
 
 
    private function setItem($item_part, $goods_data, $contents_block, $kataban_map, $item_idx, $goods_count){ 
 
        // liにあてるクラスをためる 
        $li_class = array(); 
 
        // 商品URL 
        self::setLink($item_part, $goods_data); 
 
        // 価格 
        self::setPrice($item_part, $goods_data); 
 
        // 型番 
        self::setHinban($contents_block, $item_part, $goods_data, $item_idx); 
 
        // カラーチップ 
        self::setColorTip($item_part, $goods_data); 
 
        switch($contents_block['design_type']){ 
            case self::DESIGN_TYPE_NORMAL: 
 
                // ランキング 
                self::setRanking($contents_block, $item_part, $item_idx, $li_class); 
 
                // 商品画像 
                self::setMainImage($contents_block, $item_part, $goods_data, $item_idx); 
 
                // 即日配送画像 
                self::setDirectDeliveryImage($contents_block, $item_part, $goods_data, $item_idx); 
 
                // 説明文 
                self::setDescriptionText($contents_block, $item_part, $goods_data); 
 
                // コーディネート 
                self::setModelCoordinate($contents_block, $item_part, $goods_data, $item_idx, $kataban_map, $li_class); 
 
                break; 
            case self::DESIGN_TYPE_MENS_LADIES: 
                $this->setMensLadies($contents_block, $item_part, $goods_data, $item_idx); 
                break; 
        } 
 
        $item_part = str_replace( 
            '<li class=""', 
            '<li class="'.implode(' ', $li_class).'"' 
            , $item_part 
        ); 
        return $item_part; 
    } 
 
 
 
 
    private static function setRanking($contents_block, &$item_part, $item_idx, &$li_class){ 
        if( (int)$contents_block['show_ranking_number'] === 1 ){ 
            $rank_num = (int)$contents_block['ranking_start_number'] + (int)$item_idx; 
 
            $li_class[] = 'managed-contents-block-item-rank-list'; 
             
            switch($rank_num){ 
                case 1: 
                    $class = 'managed-contents-block-item-rank-gold'; 
                    break; 
                case 2: 
                    $class = 'managed-contents-block-item-rank-silver'; 
                    break; 
                default: 
                    $class = 'managed-contents-block-item-rank-bronze'; 
                    break; 
            } 
 
            if( (int)$contents_block['ranking_mark_type'] === self::RANK_MARK_CROWN ){ 
                $class .= ' managed-contents-block-item-rank-mark-crown'; 
            } 
 
            $item_part = str_replace('<span class="managed-contents-block-item-rank"', '<span class="managed-contents-block-item-rank '.$class.'"', $item_part); 
            $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); 
        } 
        else{ 
            $item_part = str_replace('<span class="managed-contents-block-item-rank"><span class="managed-contents-block-item-rank-label"></span></span>', '', $item_part); 
        } 
         
    } 
     
     
     
     
    private function setModelCoordinate($contents_block, &$item_part, $goods_data, $item_idx, $kataban_map, &$li_class){ 
        if( (int)$contents_block['show_coordinate_goods'] === 1 ){ 
            $model_num_list = explode(',', $contents_block['model_num_list']); 
            $model_num = (int)$model_num_list[$item_idx]; 
            $column_num = $contents_block['column_number']; 
            $coo_limit = 2; 
            $coo_count = 0; 
            for( $coo_num = 1; $coo_num <= $coo_limit; $coo_num++ ){ 
                // id 
                $field = "model_{$model_num}_{$column_num}col_coordinate_goods_{$coo_num}_id"; 
                $coo_goods_id = $goods_data[$field]; 
 
                if( empty($coo_goods_id) || !isset($kataban_map[$coo_goods_id]) ){ 
                    $item_part = preg_replace('!<li data-coo-li="'.$coo_num.'">.*?</li>!s', '', $item_part, 1); 
                    continue; 
                } 
 
                $coo_count++; 
 
                // src 
                $src = sprintf( 
                    self::IMAGE_COORDINATE_PATH, 
                    $goods_data['shiiresaki_url'], 
                    $goods_data['goods_main_kataban'], 
                    $model_num, 
                    $column_num, 
                    $coo_num 
                ); 
 
                // alt 
                $field = "model_{$model_num}_{$column_num}col_coordinate_goods_{$coo_num}_alt"; 
                $alt = $goods_data[$field]; 
                $img = sprintf('<img src="%s" alt="%s">', $src, $alt); 
                $item_part = preg_replace( 
                    '!<div class="managed-contents-block-item-model-coordinate-figure"></div>!', 
                    '<div class="managed-contents-block-item-model-coordinate-figure">'.$img.'</div>', 
                    $item_part, 
                    1 
                ); 
 
                // href 
                $href = '/item/'; 
                $href .= $kataban_map[$coo_goods_id]; 
                $href .= '.html'; 
 
                $item_part = preg_replace('!<a href="" data-coo-url>!', '<a href="'.$href.'">', $item_part, 1); 
 
                // 価格 
                $item_part = preg_replace('/data-item-id=""/', 'data-item-id="'.$coo_goods_id.'"', $item_part, 1); 
            } 
             
            if( $coo_count === 0 ){ 
                $item_part = preg_replace('!<div class="managed-contents-block-item-model-coordinate">.*</li>!s', '</li>', $item_part); 
            } 
            else{ 
                $li_class[] = 'has-coo'; 
                $item_part = str_replace( 
                    '<span class="managed-contents-block-item-model-coordinate-label"></span>', 
                    '<span class="managed-contents-block-item-model-coordinate-label">↓モデルの着用コーデ↓</span>', 
                    $item_part 
                ); 
            } 
        } 
        else{ 
            $item_part = preg_replace('!<div class="managed-contents-block-item-model-coordinate">.*</li>!s', '</li>', $item_part); 
        } 
    } 
 
 
 
 
    public function getGoodsKatabanMap(){ 
         
        $rows = (new SqlService())->Sql(' 
            SELECT 
                goods_id, 
                goods_canonical_hinban, 
                goods_main_kataban 
            FROM 
                goods_table 
            WHERE 
                goods_ddate IS NULL AND 
                goods_status = 1 
        ')->FetchAll(); 
        $map = array(); 
 
        foreach($rows as $row){ 
            $map[$row['goods_id']] = empty($row['goods_canonical_hinban']) ? $row['goods_main_kataban'] : $row['goods_canonical_hinban']; 
        } 
 
        return $map; 
    } 
     
     
     
     
    private function setColor($block_part, $contents_block_data){ 
        // 全体背景とフォント 
        $block_part = str_replace( 
            '<div class="managed-contents-block">', 
            '<div class="managed-contents-block" style="background: '.$contents_block_data['bg_color'].'; color: '.$contents_block_data['text_color'].'">', 
            $block_part 
        ); 
 
        // h2 
        $block_part = str_replace( 
            '<h2 class', 
            '<h2 style="background: '.$contents_block_data['element_bg_color'].'; color: '.$contents_block_data['element_text_color'].';" class', 
            $block_part 
        ); 
 
        // 画像上説明文 
        $block_part = str_replace( 
            '<p class="managed-contents-block-header-description">', 
            '<p class="managed-contents-block-header-description" style="color: '.$contents_block_data['element_text_color'].'">', 
            $block_part 
        ); 
 
        // コーディネート 
        $block_part = str_replace( 
            '<div class="managed-contents-block-item-model-coordinate">', 
            '<div class="managed-contents-block-item-model-coordinate" style="background: '.$contents_block_data['bg_color'].';">', 
            $block_part 
        ); 
 
        // フッター 
        // 1行テキストの場合は背景色設定無効 
        if( (int)$contents_block_data['more_button_type'] === self::MORE_TYPE_BUTTON ){ 
            $block_part = str_replace( 
                'managed-contents-block-footer"><a ', 
                'managed-contents-block-footer"><a style="background: '.$contents_block_data['element_bg_color'].'; color: '.$contents_block_data['element_text_color'].';" ', 
                $block_part 
            ); 
        } 
         
 
        return $block_part; 
    } 
 
 
 
 
    private function getItemDataMap($goods_id_list){ 
         
        if( !is_array($goods_id_list) || empty($goods_id_list) ) return []; 
 
        $map = array(); 
        $goods_id_list = array_map( function($goods_id){ 
            return (int)$goods_id; 
        }, $goods_id_list); 
 
        $in_clause = implode(',', $goods_id_list); 
         
        $color_map = $this->getGoodsColorMap($goods_id_list); 
 
        $rows = (new SqlService())->Sql(" 
            SELECT 
                g.goods_name, 
                g.goods_canonical_hinban, 
                g.goods_main_kataban, 
                g.goods_series_2column_caption, 
                g.goods_series_3column_caption, 
                g.goods_series_4column_caption, 
                g.goods_show_marks_above_model_banner_1, 
                g.goods_show_marks_above_model_banner_2, 
                g.goods_show_marks_above_model_banner_3, 
                g.goods_show_direct_mark_below_model_banner_1, 
                g.goods_show_direct_mark_below_model_banner_2, 
                g.goods_show_direct_mark_below_model_banner_3, 
                s.shiiresaki_id, 
                s.shiiresaki_url, 
                o.*, 
                g.goods_id 
            FROM 
                goods_table g 
            JOIN 
                shiiresaki_table s 
            ON 
                g.goods_shiiresaki = s.shiiresaki_id 
            LEFT JOIN 
                goods_contents_block_option_table o 
            USING(goods_id) 
            WHERE 
                g.goods_id IN({$in_clause}) AND 
                g.goods_ddate IS NULL AND 
                g.goods_status = 1 AND 
                s.shiiresaki_url IS NOT NULL 
        ")->FetchAll(); 
 
        foreach($rows as $row){ 
            $row['uri'] = '/item/'.($row['goods_canonical_hinban'] ? $row['goods_canonical_hinban'] : $row['goods_id']).'.html'; 
            if( isset($color_map[$row['goods_id']]) ) $row['color'] = $color_map[$row['goods_id']]; 
            $map[$row['goods_id']] = $row; 
        } 
 
        return $map; 
    } 
 
 
 
 
    private function getContentsBlockList($id_list){ 
        $in_clause = implode(',', array_map( function($id){ 
            return (int)$id; 
        }, $id_list)); 
 
        return (new SqlService())->Sql(" 
            SELECT 
                cb.*, 
                GROUP_CONCAT(cbi.goods_id ORDER BY order_num) AS goods_id_list, 
                GROUP_CONCAT(cbi.display_name ORDER BY order_num) AS display_name_list, 
                GROUP_CONCAT(cbi.display_name_color ORDER BY order_num) AS display_name_color_list, 
                GROUP_CONCAT(cbi.display_name_bg_color ORDER BY order_num) AS display_name_bg_color_list, 
                GROUP_CONCAT(cbi.model_num ORDER BY order_num) AS model_num_list, 
                GROUP_CONCAT(cbi.model_portrait_num ORDER BY order_num) AS model_portrait_num_list, 
                GROUP_CONCAT(cbi.model_portrait_pair_num ORDER BY order_num) AS model_portrait_pair_num_list, 
                GROUP_CONCAT(cbi.model_portrait_is_2col_image ORDER BY order_num) AS model_portrait_is_2col_image_list 
            FROM 
                contents_block_table cb 
            LEFT JOIN 
                contents_block_item_map_table cbi 
            USING(contents_block_id) 
            WHERE 
                cb.contents_block_id IN({$in_clause}) AND 
                cb.is_active = :is_active 
            GROUP BY 
                cb.contents_block_id 
        ")->Params([ 
            'is_active' => self::BOOL_TRUE, 
        ])->FetchAll(); 
    } 
 
 
 
 
    private function getTemplate(){ 
        $rows = (new SqlService())->Sql(" 
            SELECT 
                * 
            FROM 
                contents_block_template_table 
            WHERE 
                name LIKE 'category-col%' 
        ")->FetchAll(); 
 
        $map = array(); 
        foreach($rows as $row){ 
            $map[$row['name']] = $row['html']; 
        } 
         
        return $map; 
    } 
 
 
 
 
    private function getGoodsColorMap($goods_id_list){ 
 
        if( !is_array($goods_id_list) || empty($goods_id_list) ) return []; 
 
        $where_clause = 'AND g.goods_id IN(' . implode(',', $goods_id_list) . ')'; 
         
        $rows = (new SqlService())->Sql(" 
            SELECT DISTINCT 
                g.goods_id, 
                c.color_name, 
                c.color_rgb 
            FROM 
                goods_table g 
            JOIN 
                goods_color_table gc 
            ON 
                g.goods_id = gc.gcl_goods AND 
                gc.gcl_display_status = 1 
            LEFT JOIN 
                color_table c 
            ON 
                c.color_id = gc.gcl_color_id 
            WHERE 
                g.goods_ddate IS NULL AND 
                g.goods_status = 1 
                {$where_clause} 
            ORDER BY 
                COALESCE(gc.gcl_display, gc.gcl_display, 999), 
                COALESCE(c.color_display, c.color_display, 999) 
        ")->FetchAll(); 
 
        $map = array(); 
        foreach($rows as $row){ 
            $map[$row['goods_id']][] = $row['color_rgb']; 
        } 
 
        return $map; 
    } 
 
 
 
 
    private function fillItemList( $item_part_list, $column ){ 
        $goods_count = count($item_part_list); 
        $remainder = 0; 
         
        if($goods_count > (int)$column){ 
            if( $goods_count % $column !== 0 ){ 
                $remainder = $column - ($goods_count % $column); 
            } 
        } 
        else{ 
            $remainder = $column - $goods_count; 
        } 
        if( $remainder !== 0 ){ 
            for($i = 1; $i <= $remainder; $i++){ 
                $item_part_list[] = '<li style="visibility: hidden; order: 99;" />'; 
            } 
        } 
 
        return $item_part_list; 
    } 
 
 
 
 
    public function getGoodsBannerOptionMap(){ 
 
        // 菅画面で「フォントをカスタマイズ」してない場合のバナーデータ 
        $rows = (new SqlService())->Sql(' 
            SELECT 
                * 
            FROM 
                goods_banner_contents_block_option_mst_table 
        ')->FetchAll(); 
 
        // バナーのマスターデータ(サイズ、色、位置) 
        $mst_map = []; 
        foreach($rows as $row){ 
            $row['banner_no'] = (int)$row['banner_no']; 
            $row['text_1_size'] = (int)$row['text_1_size']; 
            $row['text_2_size'] = (int)$row['text_2_size']; 
            $row['description_size'] = (int)$row['description_size']; 
            $row['pos_x'] = (int)$row['pos_x']; 
            $row['pos_y'] = (int)$row['pos_y']; 
             
            $mst_map[$row['banner_no']] = $row; 
        } 
 
        // 商品ごとのテキストデータ(商品詳細で設定されるもの) 
        $rows = (new SqlService())->Sql(' 
            SELECT 
                * 
            FROM 
                goods_banner_contents_block_option_table 
        ')->FetchAll(); 
 
        $option_map = []; 
        foreach($rows as $row){ 
            if( !isset($option_map[(int)$row['goods_id']][(int)$row['banner_no']]) ) $option_map[(int)$row['goods_id']][(int)$row['banner_no']] = []; 
            $data = &$option_map[(int)$row['goods_id']][(int)$row['banner_no']]; 
            $data[$row['option_key']] = $row['option_value']; 
        } 
        unset($data); 
 
        $rows = (new SqlService())->Sql(' 
            SELECT 
                * 
            FROM 
                contents_block_goods_banner_map_table 
        ')->FetchAll(); 
 
        if( empty($rows) ) return []; 
 
 
        /** 
         * return するマップ生成 
         */ 
        $map = []; 
        $goods_id_list = []; 
        foreach($rows as $row){ 
            if (!empty($option_map[(int)$row['goods_id']])) { 
                $map[(int)$row['contents_block_id']] = []; 
                $data = &$map[(int)$row['contents_block_id']]; 
 
                $data['goods_id'] = (int)$row['goods_id']; 
                $data['banner_no'] = (int)$row['banner_no']; 
                $data['show_price'] = (int)$row['show_price'] === self::BOOL_TRUE; 
                $data['show_sale_icon'] = (int)$row['show_sale_icon'] === self::BOOL_TRUE; 
                $data['use_custom_text'] = (int)$row['use_custom_text'] === self::BOOL_TRUE; 
                $data['use_custom_font'] = (int)$row['use_custom_font'] === self::BOOL_TRUE; 
                $data['use_custom_more_text'] = (int)$row['use_custom_more_text'] === self::BOOL_TRUE; 
                $data['use_custom_more_link_url'] = (int)$row['use_custom_more_link_url'] === self::BOOL_TRUE; 
                $goods_id_list[] = (int)$row['goods_id']; 
            } 
        } 
        unset($data); 
         
        // 商品情報取得 
        $rows = (new SqlService())->Sql(' 
            SELECT 
                goods_id, 
                goods_name, 
                goods_sub_name, 
                goods_canonical_hinban, 
                goods_main_kataban, 
                shiiresaki_url 
            FROM 
                goods_table 
            JOIN 
                shiiresaki_table 
            ON 
                goods_shiiresaki = shiiresaki_id 
            WHERE 
                shiiresaki_url IS NOT NULL AND 
                goods_id IN('.implode(',', $goods_id_list).') 
        ')->FetchAll(); 
 
        $goods_map = []; 
        foreach($rows as $row){ 
            $goods_map[(int)$row['goods_id']] = [ 
                'name' => "{$row['goods_name']} {$row['goods_sub_name']}", 
                'kataban' => $row['goods_main_kataban'], 
                'shiiresaki_url' => $row['shiiresaki_url'], 
                'url' => '/item/'.( !empty($row['goods_canonical_hinban']) ? $row['goods_canonical_hinban'] : (!empty($row['goods_main_kataban']) ? $row['goods_main_kataban'] : $row['goods_id']) ).'.html' 
            ]; 
        } 
 
        // ここからデータを生成する。 
        foreach($map as $block_id => &$data){ 
            if( !isset($goods_map[$data['goods_id']]) ){ 
                unset($map[$block_id]); 
                continue; 
            } 
             
            $goods_data = $goods_map[$data['goods_id']]; 
 
            // バナー画像 
            $data['image_src'] = sprintf( 
                self::GOODS_BANNER_IMAGE_PATH, 
                $goods_data['shiiresaki_url'], 
                $goods_data['kataban'], 
                $data['banner_no'] 
            ); 
            $data['image_alt'] = $goods_data['name']; 
 
            // テキストデータ 
            $option_data = $option_map[$data['goods_id']][$data['banner_no']]; 
 
            // フォント、位置などのデータ 
            $mst_data = $mst_map[$data['banner_no']]; 
 
            // テキストをカスタマイズする(カスタマイズ時のデータはcontents_block_tableに入っているのでnullにする) 
            if( $data['use_custom_text'] ){ 
                $data['text_1']      = null; 
                $data['text_2']      = null; 
                $data['description'] = null; 
                $data['pos_x']       = null; 
                $data['pos_y']       = null; 
            } 
            else{ 
                $data['text_1'] = $option_data['text_1']; 
                $data['text_2'] = $option_data['text_2']; 
                $data['description'] = $option_data['description']; 
                $data['pos_x'] = $mst_data['pos_x']; 
                $data['pos_y'] = $mst_data['pos_y']; 
            } 
 
            // フォントをカスタマイズする(カスタマイズ時のデータはcontents_block_tableに入っているのでnullにする) 
            if( $data['use_custom_font'] ){ 
                $data['text_1_size']          = null; 
                $data['text_1_color']         = null; 
                $data['text_1_bg_color']      = null; 
                $data['text_2_size']          = null; 
                $data['text_2_color']         = null; 
                $data['text_2_bg_color']      = null; 
                $data['description_size']     = null; 
                $data['description_color']    = null; 
                $data['description_bg_color'] = null; 
            } 
            else{ 
                $data['text_1_size']          = $mst_data['text_1_size']; 
                $data['text_1_color']         = $mst_data['text_1_color']; 
                $data['text_1_bg_color']      = $mst_data['text_1_bg_color']; 
                $data['text_2_size']          = $mst_data['text_2_size']; 
                $data['text_2_color']         = $mst_data['text_2_color']; 
                $data['text_2_bg_color']      = $mst_data['text_2_bg_color']; 
                $data['description_size']     = $mst_data['description_size']; 
                $data['description_color']    = $mst_data['description_color']; 
                $data['description_bg_color'] = $mst_data['description_bg_color']; 
            } 
 
            // もっと見るをカスタマイズする(カスタマイズ時のデータはcontents_block_tableに入っているのでnullにする) 
            $data['oneliner_text'] = $data['use_custom_more_text'] ? null : $option_data['oneliner_text']; 
            $data['url'] = $data['use_custom_more_link_url'] ? null : $goods_data['url']; 
 
        } 
 
         
        return $map; 
    } 
 
 
 
 
    /** 
     * loadHTMLにすると許可されない要素配置が直されてしまう。 
     * <h2><span>text1</span><p>text2</p></h2> -> <h2><span>text1</span></h2><p>text2</p> 
     *  
     * そこでloadXMLを使いたいがそうすると<img>のとじタグがない、というエラーになるためimgを閉じる。 
     * recover = trueでロードすると閉じタグがないというエラーは出なくなるが、後の</div>などの閉じタグを巻き込んで修正してしまうので注意。 
     */ 
    private static function getDomDocumentFromBlockPart($block_part){ 
        $dom = new \DOMDocument('1.0', 'utf8'); 
         
        // 閉じタグ対応 
        $block_part = preg_replace('!(<img .+?)>!', '$1/>', $block_part); 
         
        $result = @$dom->loadXML( $block_part ); 
         
        return $result === false ? false : $dom; 
    } 
 
 
 
 
    private static function getBlockPartFromDomDocument(\DOMDocument $dom){ 
         
        @$block_part = $dom->saveXML(); 
        $block_part = preg_replace('!<\?xml .+?\?>!', '', $block_part); 
         
        return mb_convert_encoding($block_part, 'utf-8', 'HTML-ENTITIES'); 
    } 
 
 
 
 
    private static function convertHex2Rgba($hex){ 
        if( !preg_match('/^#([0-9a-f]{3}|[0-9a-f]{6})$/i', $hex) ) return $hex; 
         
        if( strlen( $hex ) == 3 ) $hex = substr( $hex, 0, 1 ) . substr( $hex, 0, 1 ) . substr( $hex, 1, 1 ) . substr( $hex, 1, 1 ) . substr( $hex, 2, 1 ) . substr( $hex, 2, 1 ); 
 
        $rgb = array_map( 
            'hexdec', 
            array( 
                substr( $hex, 0, 2 ), 
                substr( $hex, 2, 2 ), 
                substr( $hex, 4, 2 ) 
            ) 
        ); 
 
        return 'rgba('.implode(',', $rgb).', .5);'; 
    } 
 
 
 
 
    private function setMensLadies($contents_block, &$item_part, $goods_data, $item_idx){ 
 
        $model_portrait_num_list = explode(',', $contents_block['model_portrait_num_list']); 
        $model_portrait_pair_num_list = explode(',', $contents_block['model_portrait_pair_num_list']); 
        $model_portrait_is_2col_image_list = explode(',', $contents_block['model_portrait_is_2col_image_list']); 
         
        $model_portrait_num = (int)$model_portrait_num_list[$item_idx]; 
        $model_portrait_pair_num = (int)$model_portrait_pair_num_list[$item_idx]; 
        $model_portrait_is_2col_image = (int)$model_portrait_is_2col_image_list[$item_idx] === self::BOOL_TRUE; 
 
        $model_num_list = explode(',', $contents_block['model_num_list']); 
        $model_num = (int)$model_num_list[$item_idx]; 
 
        // モデル縦長ペア画像は1つだけしか登録されない 
        if( (int)$model_portrait_pair_num === 1 ){ 
            $main_src = sprintf( 
                self::MODEL_PORTRAIT_PAIR_IMAGE_PATH, 
                $goods_data['shiiresaki_url'], 
                $goods_data['goods_main_kataban'] 
            ); 
     
            $item_part = str_replace( 
                '<image-main class="managed-contents-block-item-figure-main" />', 
                '<img src="'.htmlspecialchars($main_src).'" class="managed-contents-block-item-figure-main" alt="'.htmlspecialchars($goods_data['goods_name']).'" />', 
                $item_part 
            ); 
        } 
 
        $list_line_idx = $item_idx === 0 ? 0 : floor($item_idx / 2);    // 商品2個で一列 
        $start_order_num = $list_line_idx === 0 ? $item_idx : ($list_line_idx * 2) + $item_idx; 
     
        $item_part = str_replace('<li class="">', '<li class="managed-contents-block-item-list-price-li" style="order: '.($start_order_num+2).';">', $item_part); 
         
        // 2カラム画像を使用している場合、もう片方のmodel_portrait_numは0が入っている 
        $src = $model_portrait_num === 0 
            ? null 
            : sprintf( 
                self::MODEL_PORTRAIT_IMAGE_PATH, 
                $goods_data['shiiresaki_url'], 
                $goods_data['goods_main_kataban'], 
                $model_portrait_num 
            ) 
        ; 
 
        $li_2col_class = ''; 
 
        // 「2カラム画像として表示」がチェックされている 
        if( $model_portrait_is_2col_image ){ 
            $li_2col_class = 'managed-contents-block-item-list-full-height-2col-li'; 
            if( $item_idx % 2 === 0 ){ 
                $li_2col_class .= ' managed-contents-block-item-list-hide-after-li'; 
            } 
            else{ 
                $li_2col_class .= ' managed-contents-block-item-list-hide-before-li'; 
            } 
        } 
 
        if( is_null($src) ){ 
            $pair_li = sprintf(' 
                    <li class="managed-contents-block-item-list-full-height-li %s" style="order: %d;"></li> 
                ', 
                $li_2col_class, 
                $start_order_num 
            ); 
        } 
        else{ 
            $pair_li = sprintf(' 
                    <li class="managed-contents-block-item-list-full-height-li %s" style="order: %d;"> 
                        <a href="%s"><img src="%s" alt="%s"></a> 
                    </li> 
                ', 
                $li_2col_class, 
                $start_order_num, 
                htmlspecialchars($goods_data['uri']), 
                htmlspecialchars($src), 
                htmlspecialchars($goods_data['goods_name']) 
            ); 
        } 
 
        $item_part = $pair_li.$item_part; 
    } 
 
 
 
 
    private function setAdditionalText($block_part, $contents_block){ 
        $additional_midashi = $contents_block['additional_midashi']; 
        $additional_description = $contents_block['additional_description']; 
 
        $additional_midashi_color = $contents_block['additional_midashi_color']; 
         
        $additional_description_color = $contents_block['additional_description_color']; 
 
        $midashi_style = ''; 
        $midashi_style .= !empty($additional_midashi_color) ? "color: {$additional_midashi_color}; " : ''; 
 
        $description_style = ''; 
        $description_style .= !empty($additional_description_color) ? "color: {$additional_description_color}; " : ''; 
 
        $html = sprintf(' 
                <div id="managed-contents-block-additional-text"> 
                    <h3 id="managed-contents-block-additional-midashi" style="%s">%s</h3> 
                    <span id="managed-contents-block-additional-description" style="%s">%s</span> 
                </div> 
            ', 
            $midashi_style, 
            htmlspecialchars($additional_midashi), 
            $description_style, 
            nl2br( htmlspecialchars($additional_description) ) 
        ); 
 
        return str_replace('<div class="managed-contents-block-body">', '<div class="managed-contents-block-body">'.$html, $block_part); 
    } 
 
 
 
 
    private function set2colLi(&$item_part_list){ 
        foreach($item_part_list as $idx => $item_part){ 
            unset($hide_li); 
            if( preg_match('/managed-contents-block-item-list-hide-before-li/', $item_part) ){ 
                if( isset($item_part_list[$idx - 1]) ) $hide_li = &$item_part_list[$idx - 1]; 
            } 
            else if( preg_match('/managed-contents-block-item-list-hide-after-li/', $item_part) ){ 
                if( isset($item_part_list[$idx + 1]) ) $hide_li = &$item_part_list[$idx + 1]; 
            } 
             
            // style="order: xx"を指定しているので必ずstyle=の定義がある 
            if( isset($hide_li) ) $hide_li = preg_replace( 
                '/^(.+?managed-contents-block-item-list-full-height-li.+?)style=".+?"(.+)$/s', 
                '$1 style="display: none;" $2', 
                $hide_li 
            ); 
             
        } 
    } 
 
 
 
 
    private static function setColorTip(&$item_part, $goods_data){ 
        // カラーチップ 
        if( empty($goods_data['color']) ){ 
            $item_part = preg_replace( 
                '!<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>!', 
                '', 
                $item_part 
            ); 
        } 
        else{ 
            $item_part = str_replace( 
                '<div class="managed-contents-block-item-description-color-tip-count"><span></span>COLOR</div>', 
                '<div class="managed-contents-block-item-description-color-tip-count"><span>'.count($goods_data['color']).'</span>COLOR</div>', 
                $item_part 
            ); 
            $item_part = str_replace( 
                '<goods_color_tip_list />', 
                implode('', array_map( function($rgb){ 
                    return '<li style="background: #'.htmlspecialchars($rgb).'"></li>'; 
                }, $goods_data['color'])), 
                $item_part 
            ); 
        } 
    } 
 
 
 
 
    private static function setHinban($contents_block, &$item_part, $goods_data, $item_idx){ 
        $display_name_list = explode(',', $contents_block['display_name_list']); 
        $display_name_color_list = explode(',', $contents_block['display_name_color_list']); 
        $display_name_bg_color_list = explode(',', $contents_block['display_name_bg_color_list']); 
 
        $display_name = $display_name_list[$item_idx]; 
        $display_name_color = isset($display_name_color_list[$item_idx]) ? $display_name_color_list[$item_idx] : null; 
        $display_name_bg_color = isset($display_name_bg_color_list[$item_idx]) ? $display_name_bg_color_list[$item_idx] : null; 
 
        // 型番 
        $item_part = str_replace( 
            '<goods-kataban />', 
            nl2br( htmlspecialchars( !empty($display_name) ? $display_name : $goods_data['goods_main_kataban'] ) ), 
            $item_part 
        ); 
        $kataban_style = ''; 
        if( !empty($display_name_color) ) $kataban_style .= "color: {$display_name_color}; "; 
        if( !empty($display_name_bg_color) )  $kataban_style .= "background-color: {$display_name_bg_color}; "; 
        if( $kataban_style !== '' ){ 
            $item_part = str_replace( 
                'managed-contents-block-item-description-kataban"', 
                'managed-contents-block-item-description-kataban" style="'.$kataban_style.'"', 
                $item_part 
            ); 
        } 
    } 
 
 
 
 
    private static function setPrice(&$item_part, $goods_data){ 
        // 価格(コーデの価格もあるのでlimit 1にする) 
        $item_part = preg_replace('/data-item-id=""/', 'data-item-id="'.$goods_data['goods_id'].'"', $item_part, 1); 
    } 
 
 
 
 
    private static function setLink(&$item_part, $goods_data){ 
        $item_part = str_replace( 
            '<a href="">', 
            '<a href="'.htmlspecialchars($goods_data['uri']).'">', 
            $item_part 
        ); 
    } 
 
 
 
 
    private static function setMainImage($contents_block, &$item_part, $goods_data, $item_idx){ 
        $model_num_list = explode(',', $contents_block['model_num_list']); 
        $model_num = (int)$model_num_list[$item_idx]; 
 
        if( (int)$model_num === 0 ){ 
            $main_src = sprintf( 
                self::KIHON_IMAGE_PATH, 
                $goods_data['shiiresaki_url'], 
                $goods_data['goods_main_kataban'] 
            ); 
        } 
        // モデル画像 
        else{ 
            $column_num = $contents_block['column_number']; 
            $main_src = sprintf( 
                self::MODEL_IMAGE_PATH, 
                $goods_data['shiiresaki_url'], 
                $goods_data['goods_main_kataban'], 
                $model_num, 
                $column_num 
            ); 
        } 
 
        $item_part = str_replace( 
            '<image-main class="managed-contents-block-item-figure-main" />', 
            '<img src="'.htmlspecialchars($main_src).'" class="managed-contents-block-item-figure-main" alt="'.htmlspecialchars($goods_data['goods_name']).'" />', 
            $item_part 
        ); 
 
        // 画像タイプ 
        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); 
        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); 
    } 
 
 
 
 
    private static function setDirectDeliveryImage($contents_block, &$item_part, $goods_data, $item_idx){ 
        $model_num_list = explode(',', $contents_block['model_num_list']); 
        $model_num = (int)$model_num_list[$item_idx]; 
 
        if( 
            $model_num > 0 && 
            0 === (int)($goods_data["goods_show_marks_above_model_banner_{$model_num}"]) && 
            1 === (int)$goods_data["goods_show_direct_mark_below_model_banner_{$model_num}"] 
        ){ 
            $column_num = $contents_block['column_number']; 
            $chokusou_src = '/images/itempage/chokusou/banner'.$goods_data['shiiresaki_id'].'_'.$column_num.'col.jpg'; 
            $item_part = str_replace( 
                '<image-sokujitsu class="managed-contents-block-item-figure-sokujitsu" />', 
                '<img src="'.htmlspecialchars($chokusou_src).'" class="managed-contents-block-item-figure-sokujitsu" alt="この商品は即日配送できます" />', 
                $item_part 
            ); 
        } 
        else{ 
            $item_part = str_replace( 
                '<image-sokujitsu class="managed-contents-block-item-figure-sokujitsu" />', 
                '', 
                $item_part 
            ); 
        } 
 
    } 
 
 
 
     
    private static function setDescriptionText($contents_block, &$item_part, $goods_data){ 
        $model_num_list = explode(',', $contents_block['model_num_list']); 
        $column_num = $contents_block['column_number']; 
 
        $item_part = str_replace( 
            '<goods-description-text />', 
            is_null($goods_data["goods_series_{$column_num}column_caption"]) ? '' : htmlspecialchars( $goods_data["goods_series_{$column_num}column_caption"] ), 
            $item_part 
        ); 
    } 
 
}