out_blog_card.php

<?php
// 参考サイト
// https://dis-play.net/wordpress/tips/blogcard-external/

// キャッシュテーブル作成
function add_yagi_out_blog_card_cache_table() {
  global $wpdb;
  global $table_that_yagi_out_blog_card;
  $charset_collate = $wpdb->get_charset_collate();

  // https://www.dbonline.jp/mysql/type/
  $sql = "CREATE TABLE $table_that_yagi_out_blog_card (
    id mediumint(9) NOT NULL AUTO_INCREMENT,
    url varchar(1000) DEFAULT '' NOT NULL,
    time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
    title text DEFAULT NULL,
    content text DEFAULT NULL,
    pict MEDIUMBLOB DEFAULT NULL,
    favicon MEDIUMBLOB DEFAULT NULL,
    UNIQUE KEY id (id)
  ) $charset_collate;";

  require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
  dbDelta( $sql );
}
// キャッシュテーブル削除
function dll_yagi_out_blog_card_cache_table() {
  global $wpdb;
  global $table_that_yagi_out_blog_card;
  $sql = "DROP TABLE " . $table_that_yagi_out_blog_card;
  $wpdb->query($sql);
}

/**
 * 画像のリサイズ+トリミング
 *
 * @return string $fileUrl urlもしくは画像ファイル
 */
function yagi_resize_img($fileUrl) {

  //トリミングサイズ
  $thumbW = 130;
  $thumbH = 130;

  //元の画像のサイズを取得する
  // list($w, $h) = getimagesize($fileUrl);
  $imginfo = getimagesize($fileUrl);
  $w = $imginfo[0];
  $h = $imginfo[1];
  $img_type = $imginfo['mime'];

  //元画像の縦横の大きさを比べてどちらかにあわせる
  // なおかつ縦横の差をコピー開始位置として使えるようセット
  if($w > $h){
      $diff  = ($w - $h) * 0.5;
      $diffW = $h;
      $diffH = $h;
      $diffY = 0;
      $diffX = $diff;
  }elseif($w < $h){
      $diff  = ($h - $w) * 0.5;
      $diffW = $w;
      $diffH = $w;
      $diffY = $diff;
      $diffX = 0;
  }elseif($w === $h){
      $diffW = $w;
      $diffH = $h;
      $diffY = 0;
      $diffX = 0;
  }

  //サムネイルになる土台の画像を作る
  $thumbnail = imagecreatetruecolor($thumbW, $thumbH);

  //元の画像を読み込む
  if ($img_type === 'image/jpeg') {
    $baseImage = imagecreatefromjpeg($fileUrl);
  } elseif ($img_type === 'image/png') {
    $baseImage = imagecreatefrompng($fileUrl);
  } else {
    // 該当しないNULLなどの場合は適当なベース画像を作る
    $baseImage = imagecreatetruecolor($thumbW, $thumbH);
  }


  //サムネイルになる土台の画像に合わせて元の画像を縮小しコピーペーストする
  imagecopyresampled($thumbnail, $baseImage, 0, 0, $diffX, $diffY, $thumbW, $thumbH, $diffW, $diffH);

  ob_start(); // start a new output buffer
    imagejpeg( $thumbnail );
    $ImageData = ob_get_contents();
  ob_end_clean(); // stop this output buffer
  return $ImageData;
}

// キャッシュスプリント
// yagi_out_blog_card_cache
// https://qiita.com/okdyy75/items/669dd51b432ee2c1dfbc#db%E3%81%AB%E4%BF%9D%E5%AD%98%E3%81%97%E3%81%A6%E8%A1%A8%E7%A4%BA
function yagi_out_blog_card_cache($url, $title, $content, $pict, $favi) {
  global $wpdb;
  global $table_that_yagi_out_blog_card;
  // wp api はエラーが出るためこれで対応
  $pict = yagi_out_blog_card_file_get_contents($pict);
  $favi = file_get_contents($favi);

  $wpdb->insert(
    $table_that_yagi_out_blog_card,
    array(
      'time' => current_time( 'mysql' ),
      'url' => $url,
      'title' => $title,
      'content' => $content,
      'pict' => $pict,
      'favicon' => $favi,
    )
  );
}
// ワードプレスAPIから取得を行う場合
function yagi_out_blog_card_file_get_contents($pict_url) {
  // https://teratail.com/questions/31417
  $ctx = stream_context_create(array(
    'http' => array(
      'method' => 'GET',
      'header' => 'User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko')
    )
  );
  // wp api はエラーが出るためこれで対応
  $pic_file = file_get_contents($pict_url, false, $ctx);
  // 通常ファイルを一旦data化する
  $pic_file = change_yagi_out_blog_card_db_pic($pic_file);
  // data化した後にリサイズし、リターン
  return yagi_resize_img($pic_file[0]);
}

function get_yagi_out_blog_card_cache($url) {
  global $wpdb;
  global $table_that_yagi_out_blog_card;

  $query = $wpdb->prepare("
    SELECT *
    FROM $table_that_yagi_out_blog_card
    WHERE url = %s
    LIMIT 1
  ", strval($url));
  $results = $wpdb->get_results($query);
  if (empty($results)) {
    return false;
  }
  $results = $results[0];
  // var_dump($results);
  // echo $results->pict;

  $results->pict = change_yagi_out_blog_card_db_pic($results->pict);
  $results->favicon = change_yagi_out_blog_card_db_pic($results->favicon);
  // var_dump($results->pict);
  // echo $results->pict;
  // echo $results->favicon;

  return $results;
}
// ※DBを変更するスクリプトではない。写真形式base64をつくるスクリプト
function change_yagi_out_blog_card_db_pic($pic) {
  $enc_img = base64_encode($pic);
  $imginfo = getimagesize('data:application/octet-stream;base64,' . $enc_img);
  // データの型を配列で返す
  return ['data:' . $imginfo['mime'] . ';base64,' . $enc_img, $imginfo['mime']];
}

/**
 * 内部リンクのカードリンクの HTML を作成
 *
 * @param int $id 投稿 ID
 * @param array $atts ユーザーがショートコードタグに指定した属性
 * @return string カードリンクの HTML
 */
function yagi_get_internal_blog_card( $id, $atts ) {

  // ID から投稿情報を取得
  $post = get_post( $id );

  // 投稿日を取得
  $date = mysql2date( 'Y.m.d', $post->post_date );

  // タイトルを取得
  $title = $atts['title'] ? $atts['title'] : get_the_title( $id );
  $title = is_mobile() ? wp_trim_words( $title, 42, '...' ) : $title;

  // 抜粋を取得
  $excerpt = $atts['excerpt'];

  if ( ! $excerpt ) {
    if ( $post->post_excerpt ) {
      $excerpt = get_the_custom_excerpt( $post->post_excerpt, 70 );
    } else {
      $excerpt = get_the_custom_excerpt( $post->post_content, 70 );
    }
  }

  $excerpt = is_mobile() ? wp_trim_words( $excerpt, 50, '...' ) : $excerpt;

  // アイキャッチ画像を取得
  if ( has_post_thumbnail( $id ) ) {
    $img = wp_get_attachment_image_src( get_post_thumbnail_id( $id ), 'size-card' );
    $img = $img[0];
  } else {
    $img = get_template_directory_uri() . '/img/common/no_image1.gif';
  }

  // 内部リンク用ブログカードHTML出力(返却)
  $clink  = '<div class="cardlink">
    <a href="' . esc_url( $atts['url'] ) . '">
      <div class="cardlink_thumbnail">
        <img src="' . esc_attr( $img ) . '">
      </div>
    </a>
    <div class="cardlink_content">
      <span class="cardlink_timestamp">' . esc_html( $date ) . '</span>
      <div class="cardlink_title">
        <a href="' . esc_url( $atts['url'] ) . '">' . esc_html( $title ) . '</a>
      </div>
      <div class="cardlink_excerpt"><span>' . esc_html( $excerpt ) . '</span></div>
    </div>
    <div class="cardlink_footer"></div>
  </div>' . "\n";

  return $clink;
}

/* 外部リンク対応ブログカードのショートコードを作成 */
function show_Linkcard($atts) {
  global $wpdb;
  global $table_that_yagi_out_blog_card;

  extract(shortcode_atts(array(
    'id'=>"",
    'url'=>"",
    'title'=>"",
    'excerpt'=>""
  ),$atts));

  // ID、URLの両方とも指定がない場合はリターン
  if ( empty($id) && empty($url) ) { return; }

  // 内部リンクの場合はリターン
  // $idが空、[0]["0"]でない場合
  if (!empty($id)) {
    // 記事IDからURLを作成し連想配列に代入=>ID,URLを合わせる
    $atts['url'] = get_permalink( $id );
    return yagi_get_internal_blog_card( $id, $atts );
  }
  // URL から投稿 ID を取得
  $id = url_to_postid( $url );
  if (!empty($id)) {
    return yagi_get_internal_blog_card( $id, $atts );
  }


  // ======== ↓↓↓外部リンク作成↓↓↓ ========
  //画像サイズの横幅を指定
  $img_width ="130";
  //画像サイズの高さを指定
  $img_height = "130";

  $blog_card_info = get_yagi_out_blog_card_cache($url);
  if ($blog_card_info) {
    $url = $blog_card_info->url;
    $Link_title = $blog_card_info->title;
    $Link_description = $blog_card_info->content;
    $xLink_img = $blog_card_info->pict[0];
    $favicon = $blog_card_info->favicon[0];
  } else {

    // プラグインの衝突を防ぐ
    // OpenGraphクラスが定義されていない場合にのみ1回だけ読み込む
    if (!class_exists('OpenGraph')) { require_once 'OpenGraph.php'; }
    // OGP情報を取得
    $graph = OpenGraph::fetch($url);

    // OGPタグからタイトルを取得
    $Link_title = $graph->title;
    if(!empty($title)){
      $Link_title = $title;// title=""の入力がある場合はそちらを優先
    }

    // OGPタグからdescriptionを取得(抜粋文として利用)
    $Link_description = wp_trim_words($graph->description, 160, '…' );//文字数は任意で変更
    if(!empty($excerpt)){
      $Link_description = $excerpt;//値を取得できない時は手動でexcerpt=""を入力
    }

    // 三項演算子
    // $graph->imageがある場合はアイキャッチ画像を表示
    // wordpress.comのAPIを利用してスクリーンショットを取得
    $screenShot = $graph->image ? $graph->image : 'https://s.wordpress.com/mshots/v1/'. urlencode(esc_url(rtrim( $url, '/' ))) .'?w='. $img_width .'&h='.$img_height.'';
    //スクリーンショットを表示
    $xLink_img = $screenShot;
    // var_dump($screenShot);

    //ファビコンを取得(GoogleのAPIでスクレイピング)
    $host = parse_url($url)['host'];
    $searchFavcon = 'https://www.google.com/s2/favicons?domain='.$host;
    if($searchFavcon){
      $favicon = $searchFavcon;
    } else { // ファビコンが無い場合
      $favicon = "";
    }

    // echo $screenShot;
    // echo $searchFavcon;
    yagi_out_blog_card_cache($url, $Link_title, $Link_description, $screenShot, $searchFavcon);
  }

  // ワードプレスapiからのデータがデフォルト(image/gif)の場合データベースを更新
  if ($blog_card_info && $blog_card_info->pict[1] == 'image/gif') {
    // echo $blog_card_info->pict[1].'<br />';
    // var_dump($blog_card_info);
    //wordpress.comのAPIを利用してスクリーンショットを取得
    $screenShot = 'https://s.wordpress.com/mshots/v1/'. urlencode(esc_url(rtrim( $url, '/' ))) .'?w='. $img_width .'&h='.$img_height.'';

    $add_img = yagi_out_blog_card_file_get_contents($screenShot);
    $wpdb->update(
      $table_that_yagi_out_blog_card,
      array(
        'pict' => $add_img
      ),
      array( 'ID' => $blog_card_info->id )
    );

    // $xLink_imgもついでに反映させたい
    $xLink_img = change_yagi_out_blog_card_db_pic($add_img)[0];
  }

  // 外部リンク用ブログカードHTML出力
  $sc_Linkcard ='<div class="cardlink">
    <a href="' . esc_url( $url ) . '">
      <div class="cardlink_thumbnail">
        <img src="' . esc_attr( $xLink_img ) . '">
      </div>
    </a>
    <div class="cardlink_content">
      <div class="cardlink_title">
        <a href="' . esc_url( $url ) . '">' . esc_html( $Link_title ) . '</a>
      </div>
      <div class="cardlink_excerpt"><span>' . esc_html( $Link_description ) . '</span></div>
    </div>
    <div class="cardlink_footer"><img src="' .esc_attr( $favicon ). '"> ' . $url .'</div>
  </div>' . "\n";

  return $sc_Linkcard;
}
// ショートコードに追加
add_shortcode("bc", "show_Linkcard");

関連記事

コメント

この記事へのコメントはありません。

TOP