/** * ピラーページ別クラスター提案の表示(完全版) */ function tcl_display_proposals_by_pillar() { // ページング設定 $per_page = 10; $current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1; $show_linked = isset($_GET['show_linked']) ? true : false; $show_all_clusters = isset($_GET['show_all_clusters']) ? sanitize_text_field($_GET['show_all_clusters']) : ''; echo '
'; echo '

📋 ピラーページ別クラスター管理

'; // すべての投稿タイプを取得 $all_post_types = get_post_types(array('public' => true), 'names'); // ピラーページを取得(ページング対応) $pillar_query = new WP_Query(array( 'post_type' => $all_post_types, 'posts_per_page' => $per_page, 'paged' => $current_page, 'post_status' => 'publish', 'meta_query' => array( array( 'key' => 'pillar_keywords', 'value' => '', 'compare' => '!=' ) ) )); $total_pillars = $pillar_query->found_posts; $total_pages = ceil($total_pillars / $per_page); // 統計情報 echo '
'; echo '

📊 統計: '; echo 'ピラーページ総数: ' . $total_pillars . '件 | '; echo '現在のページ: ' . $current_page . '/' . $total_pages . '

'; echo '
'; // 表示オプション echo '
'; echo '
🔧 表示オプション
'; echo '

'; if (!$show_linked) { $show_linked_url = add_query_arg('show_linked', '1'); echo '🔗 リンク済みも含めて表示 '; } else { $hide_linked_url = remove_query_arg('show_linked'); echo '📋 未リンクのみ表示 '; } echo '現在: ' . ($show_linked ? 'リンク済み含む' : '未リンクのみ') . ''; echo '

'; if ($pillar_query->have_posts()) { $proposals = get_option('tcl_cluster_proposals', []); while ($pillar_query->have_posts()) { $pillar_query->the_post(); $pillar_id = get_the_ID(); $pillar_title = get_the_title(); $keywords = get_field('pillar_keywords', $pillar_id); // 投稿タイプ情報 $post_type_obj = get_post_type_object(get_post_type()); $type_text = $post_type_obj ? $post_type_obj->label : get_post_type(); $type_colors = array( 'post' => '#2196f3', 'page' => '#4caf50', 'product' => '#ff9800', 'service' => '#9c27b0' ); $type_color = isset($type_colors[get_post_type()]) ? $type_colors[get_post_type()] : '#757575'; echo '
'; // ピラーページヘッダー echo '
'; echo '

📍 ' . esc_html($pillar_title) . '

'; echo '

投稿タイプ: ' . $type_text . ' | ID: ' . $pillar_id . '

'; echo '
'; echo '
'; echo '

🎯 キーワード: ' . esc_html($keywords) . '

'; // クラスター提案の確認 $clusters = isset($proposals[$pillar_id]) ? $proposals[$pillar_id] : array(); $linked_clusters = tcl_get_linked_clusters($pillar_id); $unlinked_clusters = tcl_filter_unlinked_clusters($clusters, $linked_clusters); // 統計表示 echo '
'; echo '

📊 クラスター統計:

'; echo '
    '; echo '
  • 🔗 リンク済み: ' . count($linked_clusters) . '件
  • '; echo '
  • 📝 未リンク: ' . count($unlinked_clusters) . '件
  • '; echo '
  • 📈 提案総数: ' . count($clusters) . '件
  • '; echo '
'; echo '
'; // アクションボタン echo '
'; echo '編集する '; echo '表示する'; echo '
'; // クラスター一覧(入れ子表示) $display_clusters = $show_linked ? $clusters : $unlinked_clusters; if (!empty($display_clusters)) { $show_all_key = 'pillar_' . $pillar_id; $is_expanded = ($show_all_clusters === $show_all_key); $display_limit = $is_expanded ? count($display_clusters) : 3; $visible_clusters = array_slice($display_clusters, 0, $display_limit); echo '
'; echo '
🎯 関連クラスターページ (' . count($display_clusters) . '件)
'; foreach ($visible_clusters as $index => $cluster) { $cluster_post = get_post($cluster['cluster_id']); if (!$cluster_post) continue; $is_linked = in_array($cluster['cluster_id'], $linked_clusters); $status_color = $is_linked ? '#28a745' : '#6c757d'; $status_text = $is_linked ? 'リンク済み' : '未リンク'; $status_icon = $is_linked ? '🔗' : '📄'; echo '
'; echo '
'; echo '
'; echo '
' . $status_icon . ' '; echo ''; echo esc_html($cluster_post->post_title) . '
'; if (!empty($cluster['matched_keywords'])) { echo '🎯 マッチ: ' . implode(', ', $cluster['matched_keywords']) . '
'; } echo '' . $status_text . ''; echo '
'; echo '
'; echo '' . ($index + 1) . '/' . count($display_clusters) . ''; echo '
'; echo '
'; echo '
'; } // 展開/折りたたみボタン if (count($display_clusters) > 3) { echo '
'; if (!$is_expanded) { $expand_url = add_query_arg('show_all_clusters', $show_all_key); echo ''; echo '📋 全て表示 (' . count($display_clusters) . '件)'; } else { $collapse_url = remove_query_arg('show_all_clusters'); echo ''; echo '📁 3件表示に戻る'; } echo '
'; } echo '
'; } else { echo '
'; echo $show_linked ? '関連クラスターページがありません。' : '未リンクのクラスターページがありません。'; echo '
'; } echo '
'; // padding div echo '
'; // pillar container } wp_reset_postdata(); // ページネーション if ($total_pages > 1) { echo '
'; echo '
📄 ページナビゲーション
'; for ($i = 1; $i <= $total_pages; $i++) { $page_url = add_query_arg('paged', $i); $is_current = ($i === $current_page); $button_class = $is_current ? 'button button-primary' : 'button button-secondary'; echo '' . $i . ''; } echo '

ページ ' . $current_page . ' / ' . $total_pages . ' (全 ' . $total_pillars . '件)

'; echo '
'; } } else { echo '

❌ ピラーキーワードが設定されたコンテンツが見つかりません。

'; } echo '
'; // 提案実行セクション echo '
'; echo '

🔄 クラスター再提案

'; echo '

クラスター提案を実行するには「🔄 クラスターページ再提案」ボタンをクリックしてください。

'; echo '

※ リンク済みのクラスターは新しい提案から除外されます。

'; echo '
'; } /** * ピラーページに既にリンクされているクラスターIDを取得 */ function tcl_get_linked_clusters($pillar_id) { $pillar_post = get_post($pillar_id); if (!$pillar_post) return array(); $linked_ids = array(); // 投稿内容から内部リンクを抽出 preg_match_all('/]+href=["\']([^"\']+)["\'][^>]*>/i', $pillar_post->post_content, $matches); if (!empty($matches[1])) { foreach ($matches[1] as $url) { // 相対URLまたは同じドメインの場合 if (strpos($url, home_url()) === 0 || strpos($url, '/') === 0) { $post_id = url_to_postid($url); if ($post_id && $post_id !== $pillar_id) { $linked_ids[] = $post_id; } } } } return array_unique($linked_ids); } /** * 未リンククラスターのみをフィルタリング */ function tcl_filter_unlinked_clusters($clusters, $linked_ids) { return array_filter($clusters, function($cluster) use ($linked_ids) { return !in_array($cluster['cluster_id'], $linked_ids); }); }