診断タブ — Test renderer / アクセスログ / Export Import / 互換性 / Bootstrap
プラグインの運用診断・デバッグ・移行・トラブルシューティングを担う最大ボリュームのタブです。5 つの独立した機能 (Test renderer / アクセスログ / 設定 export-import / 互換性チェック / md ホスト Bootstrap installer) が 1 タブに集約されています。
概要
「診断」タブは WordPress 管理画面 → LLMO Markdown → 診断 でアクセスできるタブです (URL: /wp-admin/admin.php?page=kashiwazaki-llmo-md&tab=diagnostics)。
本タブは他のタブと違い、設定値の保存だけでなく実行系のアクションを多く含みます。それぞれが独立したフォーム / nonce action を持ちます。
5 つの機能ブロック
| # | 機能 | 主な用途 | 関連ファイル |
|---|---|---|---|
| 1 | Test renderer (プレビュー) | 任意 URL の md 化結果を管理画面で確認 (キャッシュ bypass) | admin/settings-page-logic.php / includes/security.php |
| 2 | アクセスログ | md ホストへのアクセス記録 (UA / status / latency) | includes/security.php / {prefix}ksmd_access_logs table |
| 3 | 設定の export / import | JSON で設定をダウンロード / 復元 | admin/settings-page-logic.php |
| 4 | 互換性チェック | PHP / WP / DOMDocument / mbstring / Object Cache / WPML / Polylang の動作要件確認 | admin/sections/diagnostics.php |
| 5 | md ホスト Bootstrap installer | md.example.com の DocumentRoot に index.php を生成 / 検証 / 削除 / 復元 |
includes/md-bootstrap-installer.php |
画面構成
機能 1: Test renderer (プレビュー)
任意の URL を入力すると、その URL を md サブドメイン側で配信したらどう見えるかをこの管理画面内でプレビューします。キャッシュは bypass されるので、設定変更 / filter 修正の効果を即時確認できます。
使い方
「Test renderer (プレビュー)」セクションのテキスト入力に、確認したい URL を入力 (例: https://www.example.com/2026/04/30/hello-world/ 等)。空欄なら home_url('/') がデフォルト。
「プレビュー」ボタンをクリック。
新しいタブで md 化結果が表示される。Markdown インライン Schema.org ヘッダ、本文 Markdown、フッタが見える。
内部挙動
このフォームは admin-post.php の action=ksmd_test_render へ POST 送信されます (target="_blank")。サーバ側では:
- nonce
ksmd_test_renderを verify (CSRF 防御) - 入力 URL を
esc_url_raw()でサニタイズ - HMAC ベースのキャッシュ bypass token を生成 (cookieless)
- md ホスト側へ内部リクエスト実行 (実際にはサーバ内 WP_Query が走る)
- キャッシュキーを使わずに都度 regenerate
- 結果を Markdown のまま
text/plainで出力
キャッシュ bypass token (HMAC)
本機能は cookieless で「これは管理画面からのテストリクエストですよ」という signed token を URL に乗せて識別します:
// includes/security.php (概念抜粋)
$token = ksmd_make_test_token( $url, $ts ); // HMAC-SHA256 ベース
$preview_url = add_query_arg(
array( 'ksmd_preview' => 1, 'ksmd_t' => $token, 'ksmd_ts' => $ts ),
$url
);
md-renderer 側で token が valid と判定された場合のみ cache_get / cache_set をスキップして強制 regenerate。
使うべき場面
- 設定変更直後: post_type マッピングや filter を変更した直後の効果確認
- filter 開発中:
ksmd_route_schema_header_lines等を実装したときの結果確認 - トラブル時: 特定 URL だけ挙動異常な場合の切り分け
- エディタ作業確認: 投稿を更新したあと、md 側でどう見えるかをすぐ確認
機能 2: アクセスログ
md サブドメインへのすべてのリクエストを記録する機能です。AI クローラ (ChatGPT / Claude / Perplexity / Gemini) からのアクセスパターンを把握するのに有用です。
3 つの設定項目
| 項目 | UI | option key | 用途 |
|---|---|---|---|
| アクセスログを有効化 | checkbox | access_log_enabled (bool) |
記録の ON/OFF |
| 保持期間 | select (1/7/30 日) | access_log_retention_days (int) |
古いログの自動切り捨て |
| IP 匿名化 | checkbox | access_log_anonymize_ip (bool) |
GDPR 対応の末尾オクテットマスク |
記録される項目
1 リクエストにつき以下のフィールドが記録されます:
| カラム | 内容 |
|---|---|
logged_at |
DATETIME (UTC) |
ip |
クライアント IP (IP 匿名化 ON 時はマスク済) |
user_agent |
User-Agent ヘッダ (255 文字) |
uri |
REQUEST_URI (500 文字) |
status |
レスポンスステータス (200 / 404 / 503 等) |
duration_ms |
サーバ処理時間 (ms) |
専用テーブル {prefix}ksmd_access_logs
アクセスログは wp_options ではなく独立した 専用 MySQL テーブル に INSERT-only で書き込まれます。これにより wp_options のデシリアライズ競合が起きず、書き込みが O(1) で完結します。
CREATE TABLE {prefix}ksmd_access_logs (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
logged_at DATETIME NOT NULL,
ip VARCHAR(64) NOT NULL DEFAULT '',
user_agent VARCHAR(255) NOT NULL DEFAULT '',
uri VARCHAR(500) NOT NULL DEFAULT '',
status SMALLINT UNSIGNED NOT NULL DEFAULT 0,
duration_ms INT UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY logged_at (logged_at)
);
テーブル作成は初回利用時または activation 時に dbDelta 経由で 1 回限り実行 (ksmd_access_log_table_ready option flag で重複防止)。
retention (保持期間) の働き
retention は読み込み時 (表示時) の WHERE 句で適用されます:
// includes/security.php
$cutoff = gmdate( 'Y-m-d H:i:s', time() - $retention * DAY_IN_SECONDS );
$wpdb->get_results( $wpdb->prepare(
"SELECT ... FROM {$table} WHERE logged_at >= %s ORDER BY id DESC LIMIT %d",
$cutoff, $limit
) );
つまり物理削除はされていない (TRUNCATE 時のみ削除)。retention を 1 日に短くしても古いログ行は DB に残るため、テーブルサイズ管理は手動 TRUNCATE で行ってください。
IP 匿名化 (GDPR 対応)
IP 匿名化を ON にすると、IPv4 / IPv6 別に末尾を 0 マスクします:
| 原 IP | 匿名化後 |
|---|---|
192.168.1.42 |
192.168.1.0 (末尾オクテット 0) |
2001:db8::1 |
2001:db8:: (下位 64 bit を 0 マスク) |
IPv6 は inet_pton で 16 バイトに正規化したあと下位 8 バイトを 0 マスクし inet_ntop で文字列化します (RFC 7239 / GDPR 推奨の /64 anonymization)。
直近 50 件の表示
アクセスログ有効化中は、設定保存ボタンの下に直近 50 件のテーブルが表示されます (日時 / IP / UA / URI / Status / ms)。retention 範囲内のレコードのみ。
「アクセスログを全削除」ボタン
表の下部の赤いボタンを押すと、専用テーブルが TRUNCATE されます。 加えて旧バージョン互換のため delete_option('ksmd_access_logs') も実行されます。
機能 3: 設定の export / import
本プラグインのすべての設定を JSON ファイルとしてダウンロード / アップロード復元できます。
export の用途
- 別サイトへの設定移行: 開発 → ステージング → 本番への移行
- バックアップ: 定期的に保存して設定変更前にバックアップ
- サポート問い合わせの添付: 設定状態を 1 ファイルで第三者と共有
- マルチサイトでの設定統一: 1 拠点で設定したものを N 拠点に展開
JSON 構造の例
{
"enabled": true,
"kill_switch": false,
"md_host": "md.example.com",
"enabled_post_types": ["post", "page"],
"enabled_routes": ["home", "archive", "category", "tag", "author", "search"],
"enable_schema_header": true,
"enable_schema_footer": true,
"home_intro_markdown": "## About\n\n...",
"schema_type_map": {
"post": "Article",
"page": "WebPage",
"archive": "CollectionPage",
"category": "CollectionPage",
"tag": "CollectionPage",
"author": "ProfilePage",
"home": "WebSite",
"search": "SearchResultsPage"
},
"cache_backend": "transient",
"cache_duration": 3600,
"default_in_language": "",
"access_log_enabled": false,
"access_log_retention_days": 7,
"access_log_anonymize_ip": true
}
export の手順
「設定を JSON でダウンロード」ボタンをクリック
ブラウザにより ksmd-settings-{date}.json がダウンロードされる
import の手順
「JSON ファイルから復元」横の input でファイルを選択
ボタンをクリック → JSON が読み込まれて ksmd_settings option が更新
各タブを再読み込みすると新しい設定が反映されている
⚠️ Warning
import は現在の設定を完全に上書きします。先に export でバックアップを取ることを推奨します。
注意点
- nonce action は
ksmd_export_settings/ksmd_import_settingsでそれぞれ独立。 - import 後の値はサーバ側で再 sanitize されます (悪意ある JSON 値の混入は防御)。
bootstrap_path等のサーバ依存パスは移行先で再設定が必要です。- access_log のテーブルや transient 等のデータ本体 は export に含まれません (設定のみ)。
機能 4: 互換性チェック
本プラグインの動作要件を満たしているかを 7 項目で一目で確認できる表です。
チェック項目
| 項目 | 要件 | 判定ロジック |
|---|---|---|
| PHP version | 7.4+ | version_compare( PHP_VERSION, '7.4', '>=' ) |
| WordPress version | 6.0+ | version_compare( get_bloginfo( 'version' ), '6.0', '>=' ) |
| DOMDocument 拡張 | 必須 | class_exists( 'DOMDocument' ) |
| mbstring 拡張 | 必須 | function_exists( 'mb_convert_encoding' ) |
| External Object Cache | 任意 | wp_using_ext_object_cache() |
| WPML | 任意 | function_exists( 'icl_object_id' ) || class_exists( 'SitePress' ) |
| Polylang | 任意 | function_exists( 'pll_get_post_translations' ) |
項目別の意味
PHP version (7.4+)
本プラグインは PHP 7.4 以上が必須です。?\? (null coalescing assignment) や arrow functions を使用しているためです。 PHP 8.0 / 8.1 / 8.2 / 8.3 でテスト済。
WordPress version (6.0+)
readme.txt 上は 6.1+ ですが、診断タブの実検査は 6.0+ に緩和されています。wp_cache_supports() 関数の利用が 6.1+ で安全のため、6.1 以上を推奨。
DOMDocument 拡張 (必須)
HTML→Markdown 変換のコア。多くの PHP ディストリビューションで標準搭載されていますが、minimal な構成では php-xml パッケージのインストールが必要な場合があります。
mbstring 拡張 (必須)
マルチバイト文字 (日本語・中国語等) の正確な処理に使用。mb_convert_encoding() が必須です。
External Object Cache (任意)
有効なら「キャッシュタブ」で object_cache backend を選択可能。Redis Object Cache plugin / W3 Total Cache / Object Cache Pro 等で実現。
WPML / Polylang (任意)
v1.0.0 では検出のみで自動連携なし。次バージョンで自動連携予定。
機能 5: md ホスト Bootstrap installer
md サブドメイン (例 md.example.com) のDocumentRoot に WordPress 入口となる index.php を自動生成・削除・状態確認 する機能です。SSH での手動配置が不要になります。
なぜ必要か
md サブドメインを使う構成では、md.example.com 用の DocumentRoot にも WordPress を起動するための入口 (3 行 PHP) が必要です。手動で書くなら以下のような内容:
<?php
// md.example.com/index.php (手動例)
define( 'WP_USE_THEMES', false );
require __DIR__ . '/../public_html/wp-blog-header.php';
本機能はこれを GUI から自動生成 / 検証 / 削除します。
サポート構成
| 構成タイプ | レイアウト | 典型例 |
|---|---|---|
| sibling (兄弟) | WP 本体と同じ親ディレクトリ配下、別フォルダ | /home/user/public_html/wp/ + /home/user/public_html/md.example.com/ |
| subdir (サブディレクトリ) | ABSPATH 直下のサブディレクトリ (XServer 標準) | /home/user/public_html/ + /home/user/public_html/md.example.com/ (= ABSPATH 内側) |
非対応構成
- Bedrock (
wp/+vendor/構造) — 非対応 - WP コア dir (
wp-admin,wp-includes,wp-content) を md パスに指定 — 拒否 - ABSPATH の孫以下のディレクトリ — 拒否
UI 部品の対応表
| セクション | UI | nonce action |
|---|---|---|
| WP 本体パス | read-only 表示 (ABSPATH) |
— |
| md 側 DocumentRoot | text input (パス保存) | ksmd_bootstrap_save_path |
| 状態を再確認 | button | ksmd_bootstrap_check |
| index.php を生成 / 再生成 | button (primary) | ksmd_bootstrap_install |
| index.php を削除 | button (link-delete) + confirm | ksmd_bootstrap_uninstall |
| 直前の削除を元に戻す | button (24h 以内のみ表示) | ksmd_bootstrap_restore |
md 側 DocumentRoot の入力
md ホストのドキュメントルートを絶対パスで入力します。例:
/home/user/public_html/md.example.com/var/www/sites/md.example.com
入力後「パスを保存」ボタンで ksmd_settings.bootstrap_path に保存。サニタイズは ksmd_sanitize_bootstrap_path() で:
sanitize_text_field()で制御文字除去- 絶対パス (
/始まり) でなければ空文字へ - 末尾スラッシュ除去
realpathはここでは呼ばない (生成時の gate でのみ)
パス検証 (validation)
パス保存後、再び画面を開いたときに ksmd_bootstrap_check_status() が validation を実行します:
- パスが実在するか
- WP コア dir (wp-admin/wp-includes/wp-content) でないか
- サポートレイアウト (sibling / subdir) のいずれかか
open_basedir制約に抵触しないか- 書き込み権限 + probe ファイル作成テスト
NG の場合は警告が表示され、後段の操作ボタン群が表示されません。
状態カード — 4 行の表示
| 表示行 | 内容 |
|---|---|
| index.php の存在 | ✓ 存在する / ✗ 存在しない (= md ホスト 403) |
| 生成日時 | 本プラグインが生成した時刻 (installed_at) |
| 構成タイプ | sibling または subdir |
| md ホスト動作確認 (verify) | SUCCESS / PENDING / FAILED + HTTP コード + メッセージ |
3 重チェック (marker + sha256 + version)
index.php の同一性検証は以下 3 つを照合します:
- marker: コメント内の固定文字列
KSMD-BOOTSTRAP-MARKER - sha256: 期待される全ファイル hash (sha256)
- version: コメント内のテンプレートバージョン (
v1)
1 つでも一致しない場合は「手動編集の可能性あり」と表示され、上書き再生成は確認を促す挙動になります。
install アクション
「index.php を生成」ボタンを押すと:
- nonce
ksmd_bootstrap_installverify - パス validation 再実行
- テンプレートを sibling/subdir 別にレンダリング (ABSPATH を相対パス化)
- tempnam → atomic rename でファイル書き込み (TOCTOU 防止)
chmod 0644- meta (
installed_at,layout_type等) をksmd_bootstrap_metaoption に保存 - verify として md ホストへ HTTP リクエスト + HMAC ヘッダ確認
uninstall アクション (confirm 必須)
「index.php を削除」ボタンは JS confirm dialog 付き:
md ホストの index.php を削除します。md.host が一時的に 403 になります。続行しますか?
確認後:
- 削除前にファイル全体を
ksmd_bootstrap_last_removed_backupoption にバックアップ (24 時間有効) unlink()で削除- meta を更新 (削除フラグ +
removed_at)
restore アクション (24h 以内のみ)
削除から 24 時間以内 (KSMD_BOOTSTRAP_BACKUP_TTL = DAY_IN_SECONDS) は「直前の削除を元に戻す」ボタンが表示されます。クリックすると:
- backup から元ファイルを atomic write で復元
- backup を削除 (1 回限りの巻き戻し)
- meta も復元前の状態へ
24 時間を過ぎた backup は ksmd_bootstrap_expire_backup_if_old() によって自動削除され、ボタンは消えます。
verify (md ホスト動作確認)
install 後の verify は WP HTTP API で md ホストに GET リクエストを発行し、HMAC ヘッダを付けて応答内容と組み合わせて成否判定します:
- SUCCESS (200 + 期待するレスポンス) — 緑表示
- PENDING (リクエスト未実行) — オレンジ表示
- FAILED (タイムアウト / 4xx / 5xx) — 赤表示
SSL 検証は ksmd_bootstrap_sslverify filter で上書き可能 (ローカル開発で self-signed cert を使う等)。
内部挙動 — 設定値が読まれる場所
access_log_* 系
access_log_enabled:md-renderer.phpの出力直後にksmd_access_log_record()を呼ぶか分岐access_log_retention_days:ksmd_get_recent_access_logs()で WHERE cutoff に使用access_log_anonymize_ip: 記録時にksmd_anonymize_ip()を通すか分岐
bootstrap_path 系
bootstrap_path: 検証 / install / uninstall / restore のターゲットパスksmd_bootstrap_meta: 別 option key で installed_at / layout_type / file sha256 を管理ksmd_bootstrap_last_removed_backup: 別 option key で 24h backup を保持
関連 filter
ksmd_bootstrap_sslverify— verify 時の SSL 検証を上書き- (その他のアクセスログ系・test renderer 系は filter なし。コードから直接弄ってください)
typical configurations
パターン A — 開発環境 (アクセスログ ON、保持 30 日)
access_log_enabled: trueaccess_log_retention_days: 30access_log_anonymize_ip: false (開発中は IP も見たい)
パターン B — 本番 GDPR 対応
access_log_enabled: trueaccess_log_retention_days: 7access_log_anonymize_ip: true (必須)
パターン C — 軽量本番 (ログ無効)
access_log_enabled: false (ログのオーバーヘッドゼロ)
用途: アクセス解析を別ツール (Cloudflare Analytics 等) で取っていて DB 圧迫を避けたい。
パターン D — XServer サブドメイン構成
- 共有レンタルサーバ (XServer) でサブドメインを
md.example.comとして作成 bootstrap_path:/home/user/example.com/public_html/md.example.com(subdir レイアウト)- install ボタンで自動生成
よくある質問
Q. Test renderer で実 URL を叩いても md 化されない
A. プレビュー機能はサーバ内で WP_Query を内部実行する設計です。外部 HTTP リクエストを発行するわけではないので、URL がメインサイト (www) でアクセス可能であれば内部解決できます。404 が返る場合は対象範囲タブで該当 post_type / route が ON になっているか確認してください。
Q. アクセスログを ON にしたのに表示されない
A. ログは md サブドメイン側のリクエストのみ記録されます。管理画面 (wp-admin) のリクエストや www 側は対象外。md.example.com に実際にアクセスしてから設定タブをリロードしてください。
Q. アクセスログテーブルのサイズはどのくらいになる?
A. 1 行あたり概算 1-2 KB。月間 1 万 PV なら月 10〜20 MB、100 万 PV で 1〜2 GB 程度。retention 7 日でも実テーブルからは消えないため、定期的に「アクセスログを全削除」ボタンで TRUNCATE するか、cron で ksmd_access_log_clear() を呼ぶ運用を推奨。
Q. import で「不正な JSON」エラー
A. ファイルが UTF-8 BOM 付きで保存されているか、改行コードが破損している可能性があります。テキストエディタで UTF-8 (BOM なし) で保存し直してください。
Q. 互換性チェックで External Object Cache が「無効」
A. これは「未検出」と同義で、必須ではありません。Redis 等を導入する場合のみ ON になります。判定は ✓ OK のままです (任意項目のため)。
Q. Bootstrap installer のパスを保存したら「open_basedir 制約」エラー
A. PHP の open_basedir 設定が指定パスを許容していません。Web サーバの設定 (Apache の php_admin_value open_basedir、または php.ini) で md ホストの DocumentRoot を open_basedir に追加してください。
Q. install ボタンで「権限がない」エラー
A. PHP プロセスが md ホストの DocumentRoot に書き込み権限を持っていません。次のいずれかの対処:
- DocumentRoot のオーナー / 権限を確認 (PHP の uid と一致 or 書き込み可能)
- SSH で手動配置 (本機能を使わずに
index.phpを直接配置)
Q. verify が PENDING のままで進まない
A. md.example.com への DNS が伝播していないか、SSL 証明書が未発行の可能性があります。「動作確認」セクション (一般タブ末尾) で md ホストにブラウザから直接アクセスして確認してください。
Q. uninstall した直後に再 install したら backup は?
A. 再 install で新しい index.php が生成されるため、既存の backup は意味を失います。restore ボタンは表示されますが、復元すると新生成版が backup の旧版で上書きされます。意図しない場合は注意。
Q. test renderer の出力に Schema.org ヘッダが入っていない
A. 「出力タブ」で「Schema.org ヘッダブロック」がチェック済みか確認してください。test renderer は通常の md 化パイプラインを通るため、この設定が反映されます。
Q. アクセスログの IP 匿名化 ON/OFF を切り替えたら、過去ログも変わる?
A. いいえ。匿名化は記録時に適用されるため、過去のログは設定変更前のフォーマットのままです。過去ログも匿名化したい場合は手動で全削除して再度 ON にしてください。
Q. config の export で password / secret は含まれる?
A. このプラグインは password / secret を保管しないため、export JSON に機密値はありません。bootstrap_path 等のサーバパスのみ。それでもサポートに送る前に確認推奨。
Q. Bedrock 構成で動かない
A. Bedrock (wp/ + vendor/) は非対応とドキュメントに明記されています。Bootstrap installer は使用せず、index.php を Bedrock 流に手動で書く必要があります。
Q. md ホスト Bootstrap installer を使わずに index.php を手書きしたい
A. 可能です。最小例 (sibling 構成):
<?php
// md.example.com/index.php
define( 'WP_USE_THEMES', false );
require dirname( __DIR__ ) . '/path/to/wp/wp-blog-header.php';
marker / sha256 が一致しないため診断タブでは「手動編集の可能性あり」と表示されますが、本プラグインの動作には影響ありません。
関連
- 一般タブ — md_host 設定 (Bootstrap installer の対象ホスト)
- DNS と Bootstrap — DNS 設定と Bootstrap installer の事前条件
- キャッシュタブ — cache backend 別の挙動 (互換性チェックの External Object Cache)
- 言語タブ — WPML / Polylang 検出 (互換性チェックでも表示)
- アーキテクチャ — md-resolver / md-renderer / cache のフロー全体
- 拡張ポイント — filter リファレンス
- トラブルシューティング — 各エラーシナリオの切り分け手順