tips

WPの外部画像URLをhttps対応

SSL対応時にどうしても混在コンテンツを回避できない場合に

WP+SSL化で検索すると、自作ブログのSSL化ばかりが話題になりますが、
実際のクライアントワークでは、SSL対応時にどうしても混在コンテンツを回避できないケースがままあります。
SSLやめるのは本末転倒ですし、外部画像のURLを変えてもらうように言えず、コピペしがちなケースが多い現場に細かい注意点を引き継いでいただくのは至難の技です。

そこで、外部画像URLをphpで擬似イメージプロキシして、ちょっと強引に表示を実現します。
例えば、googleのロゴを非SSLで読み込むと以下のようなURLになります。

WPの外部画像URLをhttps対応
<img src="http://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />

これをフィルターを通すと、こう加工されて出力されます。

<img src="https://web.contempo.jp/imageproxy?src=www.google.com%2Fimages%2Fbranding%2Fgooglelogo%2F2x%2Fgooglelogo_color_272x92dp.png" />

専用のphpを用意するとか嫌なんで、wpフックでimageproxyというurlを読み込んだ場合にphpで画像を取得して吐き出すようにしています。処理的にどうかと思う部分がないでもないですが、個人的には保守性の高さの方が重要だと思う。 第三者に利用されないように HTTP_REFERER で判定を入れています。

フック先は画像を貼り付けてそうなメインエディタ、コメント、ウィジェットの三つのテキストに引っ掛けてあります。

if ( $_SERVER['HTTPS'] == 'on' ){

add_filter( 'the_content', 'change_image_src_for_proxy', 99 );
add_filter( 'comment_text', 'change_image_src_for_proxy', 99 );
add_filter( 'widget_text', 'change_image_src_for_proxy', 99 );

function change_image_src_for_proxy( $content ){
  preg_match_all('/<img[^>]*src=[\'"]http:\/\/(.*?)[\'"][^>]*>/i', $content, $matches, PREG_SET_ORDER);
  foreach ($matches as $match):
    $homeurl = str_replace( 'https://', '', home_url() );
    if ( stripos( $match[2], $homeurl ) === 0 ){
      $img = str_replace( 'http://', 'https://', $match[0] );
    } else {
      $img = str_replace( 'http://'.$match[1], add_query_arg( 'src' => $match[1], home_url('imageproxy') ), $match[0] );
    }
    $content = str_replace( $match[0], $img, $content );
  endforeach;
  return $content;
}

add_filter('send_headers', function () {
  global $wp;
  if ( $wp->request !== "imageproxy" || empty( $_GET['src'] ) ) return;
  if ( strpos(($_SERVER['HTTP_REFERER'] ?? ''),home_url()) !== 0 ) return;
  $context = stream_context_create( array( 'http' => array('ignore_errors' => true, 'timeout' => 5, ) ) );
  $response = file_get_contents( 'http://'.$_GET['src'], false, $context);
  if( $response ){
    if ( preg_match( '/.*?\.(jpeg|jpg|gif|svg|png|bmp)/i', $_GET['src'], $ext ) ) {
      $ext = 'Content-type: image/'.str_replace( 'jpg', 'jpeg', mb_strtolower($ext[1]) );
      header( $ext );
    }
    echo $response;
  }
  exit;
}, -1 );

}

「WelcartのSKU内にオリジナル入力項目を追加する。」への5件の返信

  1. はじめまして。

    こちらの情報で新規にSKU入力項目を加えることが出来ました。
    有難うございます。

    そこで質問なのですが、上記の入力内容を商品マスターの一覧表に表示させたいのですが、ご教授いただけますでしょうか?
    宜しくお願い致します。

    1. order-list.php内にusces_filter_order_list_header と usces_filter_order_list_detail というフィルターがあるようです。

      そちらで追加すれば何とかなりそうな気がします。

      ちなみにこの記事の方法は公式拡張プラグインであるオートデリバリーとバッティングするため、あまりお奨めしておりません。(オートデリバリーを使わない場合、動作に問題はありませんが。)現在私は、sku_advanceの値を配列にしてストアする方法で運用しています。近日公開するつもりだったのですが、多忙のためなかなか時間が取れません。ご要望の内容も、そちらの記事を公開するときにあわせて検証・紹介したいと思います。

    2. …書いてから気がついたのですが、order-listは受注リストで、商品マスターはusces_item_master_list.php ですね。

      そして残念ながら都合のよいフックはパッと見なさそうなので、直書きするとか、かなり強引に修正するしかなさそうな気がします。何かよい方法を見つけたら逆に教えてください^^;

  2. はじめまして。

    こちらの記事を参考に、SKUに項目追加できました。
    大変参考になる情報をありがとうございます!

    追加項目に説明用ページのURLを入力しておりまして、
    メンバーページ内の購入履歴で表示したいと考えています。
    色々と触っておりますが、どうもうまく表示することができない状況です。

    大変恐れ入りますが、ご教授いただけますでしょうか。
    面倒なお願いで申し訳ありません。どうぞよろしくお願いいたします。

    1. 申し訳ありません。

      以前質問された方↓を参考にしたところ、表示されました。
      無駄にご連絡して申し訳ありません!

      ありがとうございました。

  3. はじめまして、sku項目追加の検索でここにたどりつきました。

    希望とする記事だったので参考にさせていただいております。
    記事通り「カスタム項目」を追加できましたが、カートに入れた時「カートの中」のページに、追加した「カスタム項目」の内容を表示する事ができません。
    表示させるにはどのようにすればよいでしょうか?
    PHP等勉強中でしてご教授いただければ幸いです。
    よろしくお願いいたします。

    1. 追加

      こちらで使用したのは上記「CODE : Adding a new field to SKUs of welcart」の内容のものです。

    2. カートの中(確認画面・購入画面)で表示するには、usces_filter_confirm_rowおよびusces_filter_cart_rowというフィルターフックを使って、出力されるデータを置き換える必要があります。

      welcartのtemplate_funcの該当箇所を見て、どの値が何に対応しているかさえ理解できればフィルターを作ることは難しくありません。動作や、安全性は保証し兼ねますが、以下参考コードを書いておきます。

      /////////////////////// カートテーブルの変更 /////////////////////// 
      function my_usces_filter_cart_row( $row, $cart, $materials ){
      	global $usces;
      	$post_id = $materials['post_id'];
      	$cartItemName = esc_html( $materials['cartItemName'] );
      	$skus = $usces->get_skus( $post_id );
      	$advance = $skus[0]['advance'];
      	$row = str_replace( $cartItemName, $cartItemName.'<br/>'.$advance, $row);
          return $row;
      }
      add_filter( 'usces_filter_cart_row', 'my_usces_filter_cart_row',10,3); 
      add_filter( 'usces_filter_confirm_row', 'my_usces_filter_cart_row',10,3); 
    3. 返信ありがとうございます。

      参考コードで表示できました。
      追加したSKU項目を最終は注文時のメールにも反映させたいと思っています。template_funcを見て研究をしてみます。
      親切な対応ありがとうございました。

    4. 注文メールに反映させるのは、該当フックがないので難しそうですね。

      直接template_funcを触るか、でなければ、usces_admin_order_item_name_filterにフックしてgetCartItemName関数をすべて書き換えてしまって、処理中でis_singleとis_categoryとかだけ除外する、とかですかね。

    5. おせになっております。

      返信ありがとうございます。とても難しそうですね。
      注文メールをどの部分で処理しているの解らず困っていました。
      全体の構造、仕組みをもっと理解する必要がありそうです。
      教えて頂いた部分を詳しく見てみたいとおもいます。

      ※まだ実装するかは決めていないのですが
      【例】10000円以上で送料無料 の設定がありますが。
      この送料無料設定を除外したい商品があるとします。
      この場合、除外したい商品の編集画面で、カスタムフィールドを使い送料無料設定を除外する設定の様な、仕組みを作る事は可能でしょうか?

    6. カスタマイズすれば可能だと思います。

      ここが参考になりそうです。welcartカスタマイズブログ
      http://welcustom.net/free-shipping-campaign/
      このブログは現場目線で役立つ情報がたくさん載ってますので、welcartをお使いになる際は目を通されることをお勧めします。

    7. おせわになっております。

      良い情報ありがとうございます。
      サイトを参考にカスタマイズがんばってみたいと思います。
      また、よろしくお願いいたします。

  4. はじめまして、大変興味深く拝読させていただき、見よう見まねでskuに項目を追加したのですが、メンバーページ内の購入履歴で追加した項目を表示させることができません。

    functions内
    template_func.php
    を編集すれば実現するのかと思い、あれこれ試しましたが、どうにもお手上げの状況です。
    ご教示いただけますと非常に助かります、どうぞよろしくお願いいたします。

    1. template_func内だったら、2579行目から2631行目までのループ内で$advance = $cart_row[‘advance’];としたら呼び出せそうに見えます。

      ただ、個人的にはusces_member_history 関数を直接弄るのはお奨めできません。プラグインの更新のときに面倒ですから。はなさんがどこにSKUを放り込みたいのか分からないのですが、ぱっと見た感じ、usces_filter_history_cart_headとusces_filter_history_cart_rowのフィルターでフックできそうに思います。

      ただ、それらの関数を見てみると結構挿入しにくそうな作りになってますね。特にusces_filter_history_cart_rowの方。長々と再処理するか、いっそpreg_replaceで置き換えたほうが効率よさそうかな。フックを使うなら以下のような感じで。

      add_filter( 'usces_filter_history_cart_head', 'my_usces_filter_history_cart_head',10,2); 
      function my_usces_filter_history_cart_head( $history_cart_head, $umhs ){
      	global $usces;
      	$history_cart_head = 
      		'<tr>
      		<th scope="row" class="num">No.</th>
      		<th class="thumbnail"> </th>
      		<th>' . __('Items', 'usces') . '</th>
      		<th class="price ">' . __('Unit price', 'usces') . '</th>
      		<th class="quantity">' . __('Quantity', 'usces') . '</th>
      		<th class="subtotal">' . __('Amount', 'usces') . '</th>
      		</tr>';
          return $history_cart_head;
      }
      
      
      add_filter( 'usces_filter_history_cart_row', 'my_usces_filter_history_cart_row',10,5); 
      function my_usces_filter_history_cart_row( $history_cart_row, $umhs, $cart_row, $i, $materials  ){
      
      	$advance = $cart_row['advance']; // ←これで呼び出せんのとちゃうやろか??
      
      	$history_cart_row = preg_replace(パターン, リプレースメント, $history_cart_row); // ←$history_cart_rowにtableのtdが収まってるので
          return $history_cart_row;
      }

      以上すべて未検証です。

    2. はなです、ご連絡ありがとうございます。

      早速の御回答、まことにありがとうございます。
      さっそく施策させていただきましたところ、商品の情報ではなく、購入した際の付随情報(購入の際に生じたポイントなど)の情報がでてきました。

      例えば、現在の在庫状況(在庫あり:など)だけを追加できればと思っていたのですが、現在の商品の情報は取得できないのでしょうか。

      勝ってばかりで申し訳ありませんが、 ご教示いただけますと非常に助かります、どうぞよろしくお願いいたします。

    3. 今ひとつ、どこに何を取得するのか分からないですが…

      $post_id = $cart_row[‘post_id’];というのがあるので、以下のようにループを作成したら普通になんでも取得できるはずです。

      $usces->itemskus = $usces->get_skus($post_id, 'sort'); // usces_the_item()と同じ処理
      
      if( usces_sku_num() ) : while ( usces_have_skus() ):
      	if ( esc_attr(urlencode($usces->itemsku['code'])) !== $sku ) continue; // 購入履歴内のSKU以外を弾く
      	 // $usces->itemsku['stock']が返す数値でコンディションの判定 0→在庫有り、1→在庫僅少、2→売切れ、3→入荷待ち、4→廃盤
      	if ( (int)$usces->itemsku['stock'] <= 1 ){//たとえば在庫ありの場合
      		// wc_item_single.phpのループ内を参照して適当に関数を拾ってくる。たとえば・・・
      		echo 'ねだん:' .$usces->itemsku['price'];
      		if( $zaikonum = $usces->itemsku['stocknum'] ): echo '残り<b>'.$zaikonum.'</b>点'; 
      	} else {//在庫なし
      
      	}
      
      endwhile; endif;

      勘で書いてます。未検証ですので誤表記に気をつけてください。

    4. はなです。

      ご教示いただきました通り、記述しても実現できませんでした。

      そもそもと思い、最終的にfunctions内template_func.phpの
      2628行あたりに

      $usces->itemskus = $usces->get_skus($post_id, 'sort'); 

      2628行あたりに

      <td class="aleft">' . $itemsku['stock']  . '<a href="' . get_permalink($post_id) . '">' . esc_html($cartItemName) .

      これだけで、購入履歴の商品名の前に”在庫あり”などの表示が出るかとおもいましたが何も表示できませんでした。
      購入履歴では現在の商品の(SKU)情報が取得できないのかもわかりません。

      どうしようもなく力量の問題だと思います。
      基本からやり直さないとと猛省しております、お忙しい中、お手を煩わせ誠に申し訳ありません。
      ただただ感謝の上、失礼いたします。
      PS.今後も拝読させていただきます。

    5. プラグイン内の関数を書き直すのは私のポリシーに反するのでfunctions.phpからフックで書き換える方法を書いておきます。

      あとのカスタマイズはご自由にどうぞ。

      /////////////////////// 購入履歴テーブルの変更 /////////////////////// 
      add_filter( 'usces_filter_history_cart_head', 'my_usces_filter_history_cart_head',10,2); 
      function my_usces_filter_history_cart_head( $history_cart_head, $umhs ){
          global $usces;
          $history_cart_head = 
              '<tr>
              <th scope="row" class="num">No.</th>
              <th class="thumbnail"> </th>
              <th>' . __('Items', 'usces') . '</th>
              <th>在庫</th>//追加するTH
              <th class="price ">' . __('Unit price', 'usces') . '</th>
              <th class="quantity">' . __('Quantity', 'usces') . '</th>
              <th class="subtotal">' . __('Amount', 'usces') . '</th>
              </tr>';
          return $history_cart_head;
      }
      
      add_filter( 'usces_filter_history_cart_row', 'my_usces_filter_history_cart_row',10,5); 
      function my_usces_filter_history_cart_row( $history_cart_row, $umhs, $cart_row, $i, $materials ){
          global $usces;
          $post_id = $cart_row['post_id'];
          $sku = urldecode($cart_row['sku']);
          $usces->itemskus = $usces->get_skus($post_id, 'sort'); // usces_the_item()と同じ処理
          if( usces_sku_num() ) : while ( usces_have_skus() ):
              if ( esc_attr(urlencode($usces->itemsku['code'])) !== $sku ) continue; 
              if ( (int)$usces->itemsku['stock'] <= 1 && $usces->itemsku['stocknum'] ) $zaiko = '残り<b>'.$usces->itemsku['stocknum'].'</b>点'; 
              else $zaiko = usces_get_itemZaiko( 'name', $post_id, $sku ); 
          endwhile; endif;
          preg_match_all('/<td.*?>.*?<\/td>/i', $history_cart_row, $matches, PREG_SET_ORDER);
          $pettern = $matches[2][0]; // [3]単価[5]金額は同値になる可能性が高いので対象にしないこと
          $replce = $matches[2][0].'<td class="rightnum zaiko">' . $zaiko . '</td>'; // 追加するTD
          $history_cart_row = str_replace( $pettern, $replce, $history_cart_row );
          return $history_cart_row;
      }

      私の管理サイトで導入して確認してみました。

    6. はなです。

      本当に、何を言えば良いやら言葉が見つかりません。
      完璧に思い通りの表示をしてくれました。
      (あとは文章などを追記する予定ですが)
      正直、諦めていたところでしたので、本当に感謝の言葉しかありません。

      今後、お手をわずらわすような作業はご依頼させていただきますのでよろしくお願いいたします。

      本当にありがとうございました。

  5. welcartでただ今悪戦苦闘しています。

    phpとかcssについては、ほとんど知識がないに等しいので教えてください。
    上記スクリプトをfunction.phpに書き加え、商品情報編集画面・sku欄に新たなフィールドを追加することができましたが、それが商品情報画面に反映されません。
    下記作業をしてないからだろうと思われるのですが、対処の方法がどうしてもわかりません。
    「商品情報ページのループ内でuscesを呼び出し、$usces->itemsku[‘advance’] をechoすれば出力できます。」とありますが、具体的にどのテンプレートのどの辺にその文言を書き加えれば良いのでしょうか?

    1. 商品の情報ページに表示させるだけであれば、wc_templates下のwc_item_single.php内に書き加えて下さい。

      ここでは仮に【重さ】を表記したいとします。
      wc_item_singleテンプレート内には、商品につきSKUが一つしかない場合(<!–1SKU–>以下)と、複数ある場合の2カ所(<!– some SKU–>以下)が存在していますので、両方を書き換える必要があります。global $usces;としてウェルカートのSKU情報を呼び出ししています。

      <?php if(usces_sku_num() === 1) : usces_have_skus(); ?>
      <!--1SKU-->
      // 中略
      		<div class="field">
      		<?php if( usces_the_itemCprice('return') > 0 ) : ?>
      			<div class="field_name"><?php _e('List price', 'usces'); ?><?php usces_guid_tax(); ?></div>
      			<div class="field_cprice"><?php usces_the_itemCpriceCr(); ?></div>
      		<?php endif; ?>
      			<div class="field_name"><?php _e('selling price', 'usces'); ?><?php usces_guid_tax(); ?></div>
      			<div class="field_price"><?php usces_the_itemPriceCr(); ?></div>
      		</div>
      		<div class="field"><?php _e('stock status', 'usces'); ?> : <?php usces_the_itemZaikoStatus(); ?></div>
      		<div class="field">重さ : <?php global $usces; echo $usces->itemsku['advance']; ?>kg</div><!-- 追加しました -->
      		<?php if( $item_custom = usces_get_item_custom( $post->ID, 'list', 'return' ) ) : ?>
      		<div class="field"><?php echo $item_custom; ?></div>
      		<?php endif; ?>
      //中略
      <?php 
      endif; 
      elseif(usces_sku_num() > 1) : usces_have_skus(); ?>
      <!--some SKU-->
      //中略
      			<tr>
      				<th class="thborder"><?php _e('stock status', 'usces'); ?></th>
      				<th class="thborder"><?php _e('Quantity', 'usces'); ?></th>
      				<!-- <th class="thborder"><?php _e('unit', 'usces'); ?></th> ユニット欄を削除しました-->
      				<th class="thborder">重さ</th><!-- 追加しました -->
      				<th class="thborder"> </th>
      			</tr>
      //中略
      			<tr>
      				<td class="zaiko"><?php usces_the_itemZaikoStatus(); ?></td>
      				<td class="quant"><?php usces_the_itemQuant(); ?><?php usces_the_itemSkuUnit(); ?></td><!-- 単位名をテーブル内に統合。 -->
      				<style type="text/css">#itempage table.skumulti td.quant input { width:30px; }</style><!-- inputフィールドが大きすぎるので小さく。邪魔なのでusces_cart.css内に書いた方が良いです。 -->
      				<td class="advance"><?php global $usces; echo $usces->itemsku['advance']; ?>kg</td><!-- 追加しました -->
      			<?php if( !usces_have_zaiko() ) : ?>
      				<td class="button"><?php echo apply_filters('usces_filters_multi_sku_zaiko_message', esc_html(usces_get_itemZaiko( 'name' ))); ?></td>
      			<?php else : ?>
      				<td class="button"><?php usces_the_itemSkuButton(__('Add to Shopping Cart', 'usces'), 0); ?></td>
      			<?php endif; ?>
      			</tr>
      //中略
      <?php endif; ?>

      変更箇所にコメントを入れてあります。デフォルトのテーマは使ってないのでちゃんと検証してないのですが、表示はしてくれるはずです。複数SKU(<!– some SKU–>以下)の場合、【単位】を動かしてテーブルに新規SKU項目を表示するためのスペースを作っています。デフォルトのテーマでない場合、ソースが違うかもしれませんが、基本的には同じはずなのであとは手探りで頑張って下さい!

    2. ご丁寧な解説ありがとうございます。

      あれこれ悩みながら、カスタムフィールドのカスタマイズでの対応も考えておりました。
      またわからないことが出てきたら教えてください(汗)
      どうもありがとうございました!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です