<?php //内部ブログカード関数
/**
 * Cocoon WordPress Theme
 * @author: yhira
 * @link: https://wp-cocoon.com/
 * @license: http://www.gnu.org/licenses/gpl-2.0.html GPL v2 or later
 */
if ( !defined( 'ABSPATH' ) ) exit;

//ブログカードのサムネイルタグの取得
if ( !function_exists( 'get_blogcard_thumbnail_image_tag' ) ):
function get_blogcard_thumbnail_image_tag($url, $in = true){
  if ($in) {
    $class = ' internal-blogcard-thumb-image';
  } else {
    $class = ' external-blogcard-thumb-image';
  }
  return get_original_image_tag($url, THUMB160WIDTH_DEF, THUMB160HEIGHT_DEF, $class);
}
endif;

//内部ブログカードを作成できるURLかどうか
if ( !function_exists( 'is_internal_blogcard_url' ) ):
function is_internal_blogcard_url($url){
  if (!includes_home_url($url)) {
    return false;
  }
  $id = cocoon_url_to_postid( $url );//IDを取得（URLから投稿IDへ変換・キャッシュ対応）
  $cat = url_to_category_object($url);
  $tag = url_to_tag_object($url);

  if (($id && get_post_status($id)) || is_home_url($url) || $cat || $tag) {
    return true;
  }
}
endif;

//内部ブログカードのサムネイルサイズ
if ( !function_exists( 'get_internal_blogcard_thumbnail_size' ) ):
function get_internal_blogcard_thumbnail_size(){
  $thumbnail_size = apply_filters('get_blogcard_thumbnail_size', THUMB160);
  return apply_filters('get_internal_blogcard_thumbnail_size', $thumbnail_size);
}
endif;

//内部URLからブログをカードタグの取得
if ( !function_exists( 'url_to_internal_blogcard_tag' ) ):
function url_to_internal_blogcard_tag($url){
  if ( !$url ) return;

  $url = strip_tags($url);//URL
  $id = cocoon_url_to_postid( $url );//IDを取得（URLから投稿IDへ変換・キャッシュ対応）
  //内部ブログカード作成可能なURLかどうか
  if ( !is_internal_blogcard_url($url) ) return;
  //_v($url);

  $no_image = get_no_image_160x90_url();
  if (!$no_image) {
    $no_image = get_site_screenshot_url($url);
  }

  $thumbnail = null;
  $date_tag = null;
  //投稿・固定ページの場合
  if ($id) {
    //global $post;
    $post_data = get_post($id);
    setup_postdata($post_data);
    wp_reset_query();

    $title = $post_data->post_title;//タイトルの取得

    //メタディスクリプションの取得
    $snippet = get_the_page_meta_description($id);

    //投稿管理画面の抜粋を取得
    if (!$snippet) {
      $snippet = $post_data->post_excerpt;
    }
    //All in One SEO Packのメタディスクリプションを取得
    if (!$snippet) {
      $snippet = get_the_all_in_one_seo_pack_meta_description($id);
    }
    //記事本文の抜粋文を取得
    if (!$snippet) {
      $snippet = get_content_excerpt($post_data->post_content, get_entry_card_excerpt_max_length());
    }
    $snippet = preg_replace('/\n/', '', $snippet);

    // 日付表示
    $date = null;
    $post_date = mysql2date(get_site_date_format(), $post_data->post_date);

    switch (get_internal_blogcard_date_type()) {
      case 'post_date':
        $date = $post_date;
        break;

      case 'up_date':
        $modified_date = mysql2date(get_site_date_format(), $post_data->post_modified);

        // 年が -0001 になる場合は無効な日付と判断して投稿日に差し替え
        if (
          !$modified_date ||
          strpos($modified_date, '-0001') !== false ||
          strpos($modified_date, '0000') !== false
        ) {
          $date = $post_date;
        } else {
          $date = $modified_date;
        }
        break;
    }

    if (is_internal_blogcard_date_visible()) {
      $date = '<div class="blogcard-post-date internal-blogcard-post-date">' . $date . '</div>'; // 日付の取得
      $date_tag = '<div class="blogcard-date internal-blogcard-date">' . $date . '</div>';
    }


    //サムネイルの取得（要160×90のサムネイル設定）
    $thumbnail = get_the_post_thumbnail($id, get_internal_blogcard_thumbnail_size(), array('class' => 'blogcard-thumb-image internal-blogcard-thumb-image', 'alt' => ''));

  } elseif (is_home_url($url)){
    //トップページの場合
    $title = get_front_page_title_caption();
    $snippet = get_front_page_meta_description();
    $image = get_ogp_home_image_url();
    if (!empty($image)) {
      $thumbnail = get_blogcard_thumbnail_image_tag($image);
    }
  } elseif ($cat = url_to_category_object($url)){
    //カテゴリーページの場合
    $cat_id = $cat->term_id;

    $title = get_the_category_title($cat_id);
    $snippet = get_the_category_snippet($cat_id);
    $image = get_the_category_eye_catch_url($cat_id);

    if ($image) {
      $thumbnail = get_blogcard_thumbnail_image_tag($image);
    }
  } elseif ($tag = url_to_tag_object($url)) {
    $tag_id = $tag->term_id;
    $title = get_the_tag_title($tag_id);
    $snippet = get_the_tag_snippet($tag_id);
    $image = get_the_tag_eye_catch_url($tag_id);

    if ($image) {
      $thumbnail = get_blogcard_thumbnail_image_tag($image);
    }
  }
  //タイトルのフック
  // 第2引数に内部URL($url)を渡すことで、フック側でどのブログカードかを判別可能に（外部カードとフックの引数を統一）
  $title = apply_filters('cocoon_blogcard_title',$title, $url);
  $title = apply_filters('cocoon_internal_blogcard_title',$title, $url);
  //スニペットのフック
  // 第2引数に内部URL($url)を渡すことで、フック側でどのブログカードかを判別可能に（外部カードとフックの引数を統一）
  $snippet = apply_filters( 'cocoon_blogcard_snippet', $snippet, $url );
  $snippet = apply_filters( 'cocoon_internal_blogcard_snippet', $snippet, $url );

  //サムネイルが存在しない場合
  if ( !$thumbnail ) {
    $thumbnail = get_blogcard_thumbnail_image_tag($no_image);
  }

  //ブログカードのサムネイルを右側に
  $additional_class = get_additional_internal_blogcard_classes();

  //新しいタブで開く場合
  $target = is_internal_blogcard_target_blank() ? ' target="_blank" rel="noopener"' : '';

  //ファビコン
  $favicon_tag =
  '<div class="blogcard-favicon internal-blogcard-favicon">'.
    get_original_image_tag('https://www.google.com/s2/favicons?domain='.get_home_url(), 16, 16, 'blogcard-favicon-image internal-blogcard-favicon-image').
  '</div>';

  // ドメイン名を抽出してからPunycodeデコードを適用する
  // punycode_decode() はフルURL用ラッパーのため、ホスト名だけにはPunycodeクラスを直接使用する
  $domain = get_domain_name($url);
  if (class_exists('Punycode') && $domain) {
    $punycode = new Punycode();
    $domain = $punycode->decode($domain);
  }

  if (get_internal_blogcard_domain_style() === 'name') {
    $domain = get_bloginfo('name');
  }

  $site_logo_tag = '<div class="blogcard-domain internal-blogcard-domain">'.$domain.'</div>';
  $site_logo_tag = '<div class="blogcard-site internal-blogcard-site">'.$favicon_tag.$site_logo_tag.'</div>';

  //取得した情報からブログカードのHTMLタグを作成
  //_v($url);
  $tag =
  '<a href="'.$url.'" title="'.esc_attr(wp_strip_all_tags($title)).'" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"'.$target.'>'. //HTMLタグを除去してツールチップにコードが表示されないようにする
    '<div class="blogcard internal-blogcard'.$additional_class.' cf">'.
      '<div class="blogcard-label internal-blogcard-label">'.
        '<span class="fa"></span>'.
      '</div>'.
      '<figure class="blogcard-thumbnail internal-blogcard-thumbnail">'.$thumbnail.'</figure>'.
      '<div class="blogcard-content internal-blogcard-content">'.
        '<div class="blogcard-title internal-blogcard-title">'.$title.'</div>'.
        '<div class="blogcard-snippet internal-blogcard-snippet">'.$snippet.'</div>'.

      '</div>'.
      '<div class="blogcard-footer internal-blogcard-footer cf">'.
        $site_logo_tag.$date_tag.
      '</div>'.
    '</div>'.
  '</a>';

  return $tag;
}
endif;

//本文中のURLをブログカードタグに変更する
if ( !function_exists( 'url_to_internal_blogcard' ) ):
function url_to_internal_blogcard($the_content) {
  $res = preg_match_all('/^(<p[^>]*?>)?(<a[^>]+?>)?https?:\/\/'.preg_quote(get_the_site_domain()).'(\/)?([-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)?(<\/a>)?(<\/p>)?/im', $the_content, $m);
  //_v($m);
  foreach ($m[0] as $match) {

    //マッチしたpタグが適正でないときはブログカード化しない
    if ( !is_p_tag_appropriate($match) ) {
      continue;
    }

    $url = strip_tags($match);//URL

    //wpForoのブログカードは外部ブログカードに任せる
    if (includes_wpforo_url($url)) {
      continue;
    }

    //カレントページのURLと$urlが同じ場合は、ブログカード化しない
    //ただしウィジェットなどの the_content 以外からの呼び出し時は無限ループの恐れがないため許可する
    if (doing_filter('the_content') && is_current_url_same($url)) {
      continue;
    }


    $tag = url_to_internal_blogcard_tag($url);


    if ( !$tag ) continue;//IDを取得できない場合はループを飛ばす
    //本文中のURLをブログカードタグで置換
    $the_content = preg_replace('{^'.preg_quote($match, '{}').'}im', "\n".$tag , $the_content, 1);
    wp_reset_postdata();

  }

  return $the_content;//置換後のコンテンツを返す
}
endif;
if ( is_internal_blogcard_enable() ) {
  add_filter('the_content', 'url_to_internal_blogcard', 11);
  add_filter('widget_text', 'url_to_internal_blogcard', 11);
  add_filter('widget_text_pc_text', 'url_to_internal_blogcard', 11);
  //add_filter('widget_classic_text', 'url_to_internal_blogcard', 11);
  add_filter('widget_text_mobile_text', 'url_to_internal_blogcard', 11);
  add_filter('the_category_tag_content', 'url_to_internal_blogcard', 11);
  add_filter('appeal_area_message', 'url_to_internal_blogcard', 11);
  add_filter('the_author_box_description', 'url_to_internal_blogcard', 11);
  //コメント内ブログカード
  if (is_comment_internal_blogcard_enable()) {
    add_filter('comment_text', 'url_to_internal_blogcard' ,11);
  }
}

//本文中のURLショートコードをブログカードタグに変更する
if ( !function_exists( 'url_shortcode_to_blogcard' ) ):
function url_shortcode_to_blogcard($the_content) {
  //1行にURLのみが期待されている行（URL）を全て$mに取得
  $reg = '/\[https?:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+\]/i';
  //_v(preg_match('/'.$reg.'/i', $the_content));
  //$the_content = preg_replace('/<p>('.$reg.')<\/p>/i', '$1', $the_content);
  $res = preg_match_all($reg, $the_content, $m);
  if ($res) {
    //_v($the_content);
    // $the_content = str_replace('<p>', '<div class="paragraph">', $the_content);
    // $the_content = str_replace('</p>', '</div>', $the_content);
    $pres = preg_match_all('/<p>.*?<\/p>/is', $the_content, $n);
    //_v($n);
    //URLショートコードが含まれているパラグラフだけdivにする
    if ($pres) {
      foreach ($n[0] as $paragraph) {
        if (preg_match($reg, $paragraph)) {
          $div = str_replace('<p>', '<div class="blogcard-shortcode-wrap paragraph">', $paragraph);
          $div = str_replace('</p>', '</div>', $div);
          $the_content = str_replace($paragraph, $div, $the_content);
        }
      }
    }
    //$the_content = preg_replace('/<p>((?!<\/p>)*?)('.$reg.')((?!<p>)*?)<\/p>/is', '<div class="blogcard-shortcode-wrap">$1$2$3</div>' , $the_content);
    //$the_content = preg_replace('/<p>('.$reg.')<\/p>/i', '$1', $the_content);
    //_v($the_content);
  }
  //_v($res);
  //_v($the_content);
  //_v($m);
  foreach ($m[0] as $match) {
  //マッチしたURL一つ一つをループしてカードを作成
    $url = strip_tags($match);//URL
    $url = preg_replace('{[\[\]]}', '', $url);//[と]の除去
    //$url = str_replace('?', '%3F', $url);//?をエンコード

    //wpForoのブログカードは外部ブログカードに任せる
    if (includes_wpforo_url($url)) {
      continue;
    }

    //カレントページのURLと$urlが同じ場合は、ブログカード化しない
    //ただしウィジェットなどの the_content 以外からの呼び出し時は無限ループの恐れがないため許可する
    if (doing_filter('the_content') && is_current_url_same($url)) {
      continue;
    }

    //取得した内部URLからブログカードのHTMLタグを作成
    $tag = url_to_internal_blogcard_tag($url);//外部ブログカードタグに変換
    //URLをブログカードに変換
    if ( !$tag ) {//取得したURLが外部URLだった場合
      $tag = url_to_external_blog_card($url);//外部ブログカードタグに変換
    }

    if ( $tag ) {//内部・外部ブログカードどちらかでタグを作成できた場合
      //本文中のURLをブログカードタグで置換
      $the_content = preg_replace('{'.preg_quote($match).'}', $tag , $the_content, 1);
      //$the_content = str_replace('<p>'.$tag.'</p>', $tag , $the_content);
    }
    //_v($the_content);((?!.*<\/p>).*?)
    //pタグで囲んでいるとブラウザで勝手にタグが変換されてしまうのでdivに付け替える
    //$the_content = preg_replace('{<p>((?!.*</p>).+?) class="blogcard-wrap (.+?)</p>}is', '<div class="blogcard-shortcode-wrap">$1 class="blogcard-wrap $2</div>' , $the_content);
    //_v($the_content);
  }
  //_v($the_content);
  return $the_content;//置換後のコンテンツを返す
}
endif;
add_filter('the_content', 'url_shortcode_to_blogcard' ,11);
add_filter('widget_text', 'url_shortcode_to_blogcard' ,11);
add_filter('widget_text_pc_text', 'url_shortcode_to_blogcard', 11);
//add_filter('widget_classic_text', 'url_shortcode_to_blogcard', 11);
add_filter('widget_text_mobile_text', 'url_shortcode_to_blogcard', 11);
add_filter('comment_text', 'url_shortcode_to_blogcard', 11);
add_filter('the_category_tag_content', 'url_shortcode_to_blogcard', 11);
add_filter('appeal_area_message', 'url_shortcode_to_blogcard', 11);
add_filter('the_author_box_description', 'url_shortcode_to_blogcard', 11);

//ブログカード置換用テキストにpタグが含まれているかどうか
if ( !function_exists( 'is_p_tag_appropriate' ) ):
function is_p_tag_appropriate($match){
  if (strpos($match,'p>') !== false){
    //pタグが含まれていた場合は開始タグと終了タグが揃っているかどうか
    if ( preg_match('/<p[^>]*?>/', $match) && (strpos($match,'</p>') !== false) ) {
      return true;
    }
    return false;
  }
  return true;
}
endif;

//figure.wp-block-embedとdiv.wp-block-embed__wrapperの除外
add_filter('the_content', 'remove_wp_block_embeds');
if ( !function_exists( 'remove_wp_block_embeds' ) ):
function remove_wp_block_embeds($the_content){
  $the_content = preg_replace('/<figure class="wp-block-embed"><div class="wp-block-embed__wrapper">(.*?'.URL_REG_STR.'.*?)<\/div><\/figure>/is', '$1', $the_content);
  return $the_content;
}
endif;

// ブロックエディターでoEmbed非対応URLをブログカードとして表示するブロックを登録
// ブロック登録は常に行う（設定オフ時に既存ブロックが「非サポート」になるのを防止）
// JSエンキューやrender_callback側で設定の有効/無効を制御する
add_action( 'init', 'cocoon_register_embed_blogcard_block' );

// ブログカード埋め込みブロックのレンダリングコールバック
// URLを受け取り、内部/外部ブログカードのHTMLを生成して返す
if ( ! function_exists( 'cocoon_embed_blogcard_render' ) ) :
function cocoon_embed_blogcard_render( $attributes ) {
  $url = isset( $attributes['url'] ) ? $attributes['url'] : '';
  if ( ! $url ) {
    return '';
  }

  // URLをサニタイズし、http/httpsスキームのみ許可する
  $url = esc_url_raw( $url, array( 'http', 'https' ) );
  if ( ! $url ) {
    return '';
  }

  // ブログカード機能が完全にオフの場合はURLのみプレーンテキスト表示（フォールバック）
  if ( ! is_internal_blogcard_enable() && ! is_external_blogcard_enable() ) {
    return '<p>' . esc_html( $url ) . '</p>';
  }

  // 無限ループ防止: 自ページのURLと同一の場合はブログカード化しない
  if ( function_exists( 'is_current_url_same' ) && is_current_url_same( $url ) ) {
    return '<p>' . esc_html( $url ) . '</p>';
  }

  // 内部URLの場合（自サイトのURL）
  if ( function_exists( 'is_internal_blogcard_url' ) && is_internal_blogcard_url( $url ) ) {
    if ( is_internal_blogcard_enable() ) {
      $tag = url_to_internal_blogcard_tag( $url );
      if ( $tag ) {
        return $tag;
      }
    }
  } else {
    // 外部URLの場合（他サイトのURL）
    // ※ url_to_external_ogp_blogcard_tag() 内でキャッシュ優先・ネガティブキャッシュ（1時間）が
    //    既に実装されているため、REST API経由でも安全にフェッチできる
    if ( is_external_blogcard_enable() ) {
      if ( function_exists( 'url_to_external_blog_card_tag' ) ) {
        $tag = url_to_external_blog_card_tag( $url );
        if ( $tag ) {
          return $tag;
        }
      }
    }
  }

  // どちらでも生成できなかった場合のフォールバック
  return '<p>' . esc_html( $url ) . '</p>';
}
endif;

// ブログカード埋め込みブロックの登録
if ( ! function_exists( 'cocoon_register_embed_blogcard_block' ) ) :
function cocoon_register_embed_blogcard_block() {
  // エディター用JSのファイルパス
  $js_path = get_cocoon_template_directory() . '/js/blogcard-editor.js';

  // エディター用JSを登録（ファイルが存在しない場合のWarning防止）
  wp_register_script(
    'cocoon-blogcard-editor',
    get_cocoon_template_directory_uri() . '/js/blogcard-editor.js',
    array( 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-server-side-render', 'wp-dom-ready', 'wp-data', 'wp-core-data' ),
    file_exists( $js_path ) ? filemtime( $js_path ) : false
  );

  // ブログカード設定（内部・外部）が有効かどうかをそれぞれJS側に渡す
  $blogcard_settings = array(
    'isInternalActive' => is_internal_blogcard_enable(),
    'isExternalActive' => is_external_blogcard_enable(),
  );
  wp_add_inline_script(
    'cocoon-blogcard-editor',
    'var cocoonBlogcardSettings = ' . wp_json_encode( $blogcard_settings ) . ';',
    'before'
  );

  // ダイナミックブロックとして登録（PHPのrender_callbackでHTMLを生成）
  $block_args = array(
    'api_version'     => 3,
    'attributes'      => array(
      'url' => array( 'type' => 'string', 'default' => '' ),
    ),
    'render_callback' => 'cocoon_embed_blogcard_render',
    'script_handles'  => array(),
  );
  // エディタースクリプトに翻訳を適用する
  wp_set_script_translations( 'cocoon-blogcard-editor', 'cocoon', get_cocoon_template_directory() . '/languages' );
  // ブロック登録自体は常に行い、設定オフ時に既存ブロックが「非サポート」になるのを防止する
  // WP 6.1+ は editor_script_handles（推奨形式）、WP 6.0以下は editor_script（旧形式）を使用
  if ( function_exists( 'is_wp_6_1_or_over' ) && is_wp_6_1_or_over() ) {
    $block_args['editor_script_handles'] = array( 'cocoon-blogcard-editor' );
  } else {
    $block_args['editor_script'] = 'cocoon-blogcard-editor';
  }
  register_block_type( 'cocoon-blocks/embed-blogcard', $block_args );
}
endif;
