Developer

日本語校正マネージャー — 開発者向け情報

フック・ショートコード・カスタム投稿タイプなど、本プラグインを拡張・連携するための技術情報です。

ショートコード / ブロック / フロント出力

本プラグインはショートコードもブロックも登録しません。サイトの表示側(読者が見るページ)には一切出力しません。動作するのは管理画面・ブロックエディタ・サーバー側の公開処理だけです。

  • ショートコード登録(add_shortcode)・ブロック登録(register_block_type)・本文フィルタ(the_content)・フロント側の資産読み込み(wp_enqueue_scripts)・wp_head / wp_footer への出力は、いずれも実装にありません。
  • JavaScript / CSS を読み込むフックは enqueue_block_editor_assets(校正サイドバー)と admin_enqueue_scripts(管理画面 CSS/JS・オンボーディングツアー・バグ報告ウィジェット)だけです。
  • 校正サイドバーの資産は、ブロックエディタであること$screen->is_block_editor())と、設定 post_types に含まれる投稿タイプであることの両方を満たすときにのみ読み込まれます。クラシックエディタには校正 UI が出ず、メタボックス等の代替 UI もありません。
  • ビルド成果物 block/build/editor.js(エディタ)と admin/build/tour.js(管理画面ツアー)は配布 zip に同梱済みです。ソース(block/src / admin/src)は配布物から除外されます。
  • @wordpress/hooksaddFilter / applyFilters / doAction は使用していません。JavaScript 側の拡張ポイントはありません。

したがって、テーマ側で表示崩れ・追加 CSS・出力バッファへの干渉を考慮する必要はありません。連携する場合の入口は、次章の REST API と第 7 章のフィルタです。

REST API

名前空間は jpl/v1、認証は WordPress コア標準の cookie 認証 + noncewp_rest / X-WP-Nonce)です。独自の認証機構やトークン発行はありません。各ルートの permission_callback で capability を検証します。全 21 パス(メソッド×パスの組で 37 通り)。フロント公開用ではなく、管理画面・ブロックエディタ・外部の入稿ツール向けです。

校正・エディタ系

エンドポイントメソッド / 権限内容
/jpl/v1/checkPOST / context.post_id 指定時はその投稿の edit_post、未指定は edit_posts本文を渡して校正。引数は title slug excerpt content seo(object) context(object) triggerauto / manual のみ受理。他の値は rest_invalid_param の 400)。戻りは findings[] / summary / profile / publish / truncated
/jpl/v1/posts/{id}/checkPOST / 対象投稿の edit_postDB の保存値を使って校正。trigger=manual として jpl_logs に記録される
/jpl/v1/posts/{id}/publish-statusGET / 対象投稿の edit_post{ blocked, error_count, checked_at }checked_atY-m-d H:i:s の GMT)。ログは記録しない
/jpl/v1/ignoresGET / 対象投稿の edit_postpost_id 必須)
POST / jpl_ignore_findings +スコープ検査
無視設定の一覧・作成(201)。scopefinding / post / user / category / ruleuser / category / rulejpl_manage_rules が必要
/jpl/v1/ignores/{id}DELETE / jpl_ignore_findings または jpl_manage_rules削除。最終判定は「作成者本人 または jpl_manage_rules 保持者」
/jpl/v1/ai-reviewPOST / 対象投稿の edit_postjpl_use_ai + 可用性判定AI 最終チェック。引数は post_id(必須) content fields{title,excerpt}、戻りは { findings[], truncated, dropped }。AI が利用不可なら 400
/jpl/v1/tour-statePOST / capability 不要(ログイン済みであること)オンボーディングツアーの進行状態。course / status / dismiss_notice / reset

/check/ai-review の finding オブジェクトは同じ形です: hash / rule_id / rule_key / rule_name / severity / message / text / suggestions[] / note / field / block_index / offset[開始, 終了] の 2 要素配列)/ auto_fixable / ignorable / source_layer。AI 由来の指摘は rule_id = 0ignorable = falsesource_layer = 'ai' になります。

管理(CRUD)系

エンドポイントメソッド / 権限内容
/jpl/v1/rulesGET, POST / jpl_manage_rulesルールの一覧・作成(201)。一覧は type 絞り込みに対応
/jpl/v1/rules/{id}GET, PUT, DELETE / jpl_manage_rules単一ルールの取得・更新・削除
/jpl/v1/dictionariesGET, POST / jpl_manage_dictionaries辞書の一覧・作成(201)。一覧は type 絞り込みに対応
/jpl/v1/dictionaries/{id}GET, PUT, DELETE / jpl_manage_dictionaries取得・更新・削除。参照しているルールがあり force=false なら 409
/jpl/v1/dictionaries/{id}/entriesGET, POST, PATCH / jpl_manage_dictionariesエントリの一覧・作成(201)・一括有効化/無効化。PATCH は enabled 必須、ids[] 省略時は辞書内全件で { updated: 件数 } を返す
/jpl/v1/dictionaries/{id}/importPOST / jpl_manage_dictionaries辞書エントリの取り込み。multipart の fileformatcsv / json・必須)、dry_run既定 true)。dry run は 200、確定は 201
/jpl/v1/dictionaries/{id}/exportGET / jpl_manage_dictionaries書き出し。format 既定 csv。HTTP 経由では JSON エンベロープをバイパスして生の CSV / JSON 本文を返す(Content-Disposition: attachment 付き)
/jpl/v1/entries/{id}PUT, DELETE / jpl_manage_dictionaries単一エントリの更新・削除
/jpl/v1/profilesGET, POST / jpl_manage_profilesプロファイルの一覧・作成(201)。rules[] をネストで受け取る。rules の検証に失敗すると本体もロールバック
/jpl/v1/profiles/{id}GET, PUT, DELETE / jpl_manage_profiles取得・更新・削除。PUT に rules を渡すと全置換。参照する割り当てがあり force=false なら 409
/jpl/v1/assignmentsGET, POST / jpl_manage_profiles割り当ての一覧・作成(201)。target_type / profile_id で絞り込み可
/jpl/v1/assignments/previewGET / jpl_manage_profiles実効プロファイルのプレビュー。post_id / post_type(既定 post)/ category_ids[] / tag_ids[] / user_id。戻りは disabled / auto_fix / block_publish / applied[] / rules[]
/jpl/v1/assignments/{id}GET, PUT, DELETE / jpl_manage_profiles単一割り当ての取得・更新・削除
/jpl/v1/reports/dashboardGET / jpl_view_reportsダッシュボード集計。periodmonth / last_month / 90days(既定 month

作成・更新時の主なボディパラメータは次のとおりです。

リソースパラメータ
ルールrule_key name type description pattern match_type case_sensitive suggestion severity auto_fixable is_forced params(object) is_enabled
辞書name type description is_enabled
辞書エントリpattern suggestion alternatives[] match_type case_sensitive note is_enabled
プロファイルname description auto_fix_enabled block_publish is_enabled rules[](ネスト。各要素は rule_idis_enabled / severity_override / params_override の上書き 3 項目)
割り当てtarget_type target_id profile_id priority is_enabled
無視設定scope(必須) rule_id finding_hash matched_text post_id user_id term_id

設定(オプション jpl_settings)を読み書きする REST ルートはありません。書き込み経路は管理画面「AI 校正」の保存ハンドラ(admin-post.phpSettings::update())だけで、しかも渡されるのは ai_enabled / ai_consent / ai_log_requests / ai_model_preference の 4 キーに限られます。残る post_types / realtime_default / log_findings_detail / log_retention_days / exclude_quotes に v0.1.0 の管理画面 UI はなく、変更するには update_option( 'jpl_settings', … ) 相当の直接操作が要ります。なお Settings API(options.php / 設定グループ jpl_settings_group)で保存しているのは jpl_delete_data_on_uninstall の 1 項目だけです。

一覧系の共通クエリ引数

引数型 / 既定制約
pageinteger / 1最小 1
per_pageinteger / 20最小 1・最大 200(リポジトリ層でも 1〜200 にクランプ)
searchstring / ''ルールは name / rule_key、辞書とプロファイルは name、エントリは pattern / suggestion が対象。/assignments では受理されるが無視されます
enabledstring / '''' / '0' / '1'
typestring/rules/dictionaries のみ/profiles /assignments にはありません

一覧の総件数は X-WP-Total ヘッダで返します(X-WP-TotalPages は返しません)。enum の実値は次のとおりです。

enum
ルールの type8 種(第 9 章の表を参照)
match_type(ルール / 辞書エントリ)exact / partial / regex
severityerror / warning / info / suggestion
辞書の typenotation / forbidden / caution / proper_noun / allowed / term / client / genre
割り当ての target_typeglobal / post_type / category / tag / role / user / post
無視設定の scopefinding / post / user / category / rule

エラー規約

リポジトリ層が返す WP_Error のコードから HTTP ステータスを決定します。マップに無いコードは 400 にフォールバックします。

エラーコードHTTP意味
jpl_forbidden401 / 403capability 不足(未ログインは 401、ログイン済みは 403)。/ai-review の権限不足のみ 403 固定
jpl_not_found404対象が存在しない
jpl_rule_key_exists409rule_key の一意制約違反
jpl_assignment_exists409割り当ての UNIQUE(target_type, target_id) 違反
jpl_dictionary_in_use409参照しているルールがある辞書の削除
jpl_profile_in_use409参照している割り当てがあるプロファイルの削除
jpl_db_error500DB 書き込み失敗
jpl_invalid_entry / jpl_invalid_pattern / jpl_invalid_override / jpl_invalid_format400エントリ検証・正規表現コンパイル失敗・プロファイルのルール上書き不正・format 不正
jpl_no_file / jpl_upload_error / jpl_file_too_large400インポートのファイル未添付・アップロードエラー・5MB 超
jpl_ai_unavailable400AI が利用不可(環境・設定・同意のいずれかが未達)
jpl_ai_encode_failed500送信データの生成失敗
jpl_ai_request_failed / jpl_ai_invalid_response502AI API 呼び出し失敗 / 応答を解釈できない
jpl_publish_blocked403公開前ゲート(第 6 章)
rest_invalid_param400args スキーマ(enum・型)違反。WordPress コアが返す

作成系(POST /rules /dictionaries /entries /profiles /assignments /ignores)の成功ステータスは 201、インポートは dry run が 200・確定が 201、それ以外は 200 です。

エクスポートを PHP 内部から rest_do_request() で呼んだ場合は rest_pre_serve_request が走らないため、戻り値は {filename, mime, content} の配列のままになります。生の CSV / JSON になるのは HTTP 経由のときだけです。

同梱モジュール由来の /plugin-bug-report/v1/report(POST)は別名前空間で、ライセンスが有効かつ所定の capability を持つときだけ受け付けます(本プラグインの校正 API ではありません)。WP-CLI コマンドは提供していません。

データベース(カスタムテーブル 8 本)

物理テーブル名は $wpdb->prefix + 論理名です(サイトの DB プレフィックスに従うため、wp_jpl_rules と決め打ちはできません)。作成は有効化時の dbDelta()日時カラムはすべて UTC 保存です。

論理テーブル名役割
jpl_rules校正ルール本体(種別・パターン・重要度・ワンクリック修正可否・params
jpl_dictionaries辞書セット(表記ゆれ/禁止語/許可語などの束)
jpl_dictionary_entries辞書の語句エントリ(検出表記・推奨表記・一致方式)
jpl_profilesルールプロファイル(ルールの束 + 自動修正可否・公開ブロック可否)
jpl_profile_rulesプロファイル×ルールの上書き(有効/無効・重要度・パラメータ)。UNIQUE(profile_id, rule_id)
jpl_assignmentsプロファイルの割り当て(対象種別 7 種と優先度)。UNIQUE(target_type, target_id)
jpl_ignored_items無視設定(指摘/投稿/ライター/カテゴリ/ルール)
jpl_logs指摘ログ(ダッシュボード集計元。重要度別件数・blocked フラグ・明細 JSON)
  • jpl_dictionary_entries(dictionary_id, pattern) の UNIQUE 制約はありません(キーは PRIMARY・dictionary_idis_enabled)。同じ語を二重登録できます。
  • jpl_logs.findings は明細 JSON です。設定 log_findings_detail で記録を止められます(管理画面 UI は無く、jpl_settings をコードで書き換える必要があります)。保持日数は既定 90 日・設定値は保存時に 1〜3650 日へクランプされます(これも UI 無し)。日次 cron jpl_purge_logs がパージします。
  • スキーマバージョンは 1.0.0、保存先はオプション jpl_db_version毎リクエストの plugins_loaded で保存値と比較し、差分があれば「テーブル作成(dbDelta 差分適用)→ capability の付与判定 → 既定設定の投入 → バージョン保存」を行います。
  • 同梱データ(辞書 5 冊・73 エントリ、ルール 9 本、既定プロファイル、サイト全体割り当て)の投入は 有効化フック経由の 1 回だけで、プラグイン更新の経路では走りません(マイグレータは seed を呼びません)。

オプション・post meta・user meta

オプション(すべて jpl_ 接頭辞)

キー内容
jpl_settings全体設定。既定値は post_types = ['post','page'] / realtime_default = 1 / log_findings_detail = 1 / log_retention_days = 90 / exclude_quotes = 1 / ai_enabled = 0 / ai_consent = 0 / ai_log_requests = 0 / ai_model_preference = ''
jpl_delete_data_on_uninstallアンインストール時のデータ削除オプトイン('1' / ''。既定は空=削除しない)
jpl_db_versionスキーマバージョン
jpl_caps_grantedcapability 付与済みフラグ
jpl_builtin_version同梱データ投入済みバージョン
jpl_installed_version初回インストール時のバージョン
jpl_ai_review_logAI 実行履歴(ai_log_requests が ON のときだけ書き込み・最大 50 件・本文は保存しない。閲覧する管理画面は無く、参照するには get_option() で直接読む必要があります
jpl_license_key / jpl_license_status / jpl_license_expires_at / jpl_license_last_check / jpl_license_max_activations / jpl_license_current_activationsライセンス情報(キーは暗号化して保存)。jpl_license_statusactive / expired / suspended / revoked
jpl_pbr_disabledバグ報告ウィジェットの無効化フラグ

transient も同じ接頭辞です: jpl_update_data_<md5> / jpl_releases_data(更新情報・12 時間)、jpl_license_notice(60 秒)、jpl_ai_text_generation_supported(300 秒)、jpl_ai_model_choices(3600 秒)、jpl_matcher_<md5>(辞書の事前コンパイル結果・12 時間)、jpl_notice_<token>(管理画面のフラッシュ通知)、jpl_import_<token>(辞書インポートのプレビュー・15 分)、jpl_publish_blocked_{user_id}(公開ゲートの差し戻し通知・5 分)。

post meta(すべて _jpl_ 接頭辞)

メタキー型 / 既定内容
_jpl_profile_idinteger / 0この投稿に使うプロファイルの差し替え。0 は「差し替えなし」。差し替え先が無効・削除済みなら無視されます
_jpl_disabledboolean / falseこの投稿の校正を丸ごと止める。指摘 0 件・公開ブロックもしない

どちらも show_in_rest で登録されていますが、auth_callbackedit_post かつ jpl_manage_profiles を要求します(寄稿者がコア REST 経由でメタを直接書き、公開ゲートを回避する経路を塞ぐためです)。エディタ側の「この投稿の設定」パネルも jpl_manage_profiles 保持者にしか表示されません。

_jpl_profile_id による差し替えは、post レイヤーの中で priority / id ともに PHP_INT_MAX の合成割り当てとして扱われます。つまり全レイヤー中で最強ですが、合成そのものは続きます(下位レイヤーの結果を全部捨てて置き換えるわけではありません)。

user meta

メタキー内容
_jpl_tourオンボーディングツアーの進行状況(/tour-state が読み書きする)。アンインストール時にも削除されません(第 10 章)

独自 capability(8 種)とロール既定

capability用途administratoreditorauthorcontributor
jpl_manage_settings最上位メニューの設定画面・「AI 校正」画面の表示と保存
jpl_manage_rules「ルール」画面と /rules、無視設定の広域スコープ・他人の無視解除
jpl_manage_profiles「プロファイル」「割り当て」画面と REST、投稿単位メタの書き込み
jpl_manage_dictionaries「辞書」画面と REST、エディタからの「辞書に登録」
jpl_view_reports「ダッシュボード」画面と /reports/dashboard
jpl_ignore_findings指摘の「無視」(/ignores)。エディタの無視ボタン表示可否
jpl_force_publish公開前ゲートのバイパス
jpl_use_aiAI 最終チェックの実行(/ai-review
  • 購読者(subscriber)には何も付きません。jpl_use_ai が管理者のみなのは意図した既定で、編集者・投稿者へは運用側で付与する想定です。
  • 付与は初回インストール時の 1 回だけです。フラグオプション jpl_caps_granted が立っていれば、有効化時も DB バージョン差分検出時も何もしません。運用側でロールから外した capability(例: 編集者から jpl_force_publish を剥奪してゲートを厳格化する)を、プラグイン更新や再有効化で黙って復元しない設計です。
  • 付与は role への add_cap のみで、個別ユーザーへ付与する UI はありません。権限管理プラグイン等の標準機構で行います。
  • ライセンス画面だけは独自 capability ではなく manage_options を要求します。jpl_manage_settings を編集者に付けてもこの画面は出ません。
  • アンインストール時の revoke() は、既定付与の対象外だったロールも含めて全ロールを走査し 8 種を remove_cap します。

公開前ゲートの挙動(開発者向け)

ブロックされるのは 「その記事の実効プロファイルで block_publish が有効」かつ「Error 指摘が 1 件以上」の 2 条件が同時に成立したときだけです。件数のしきい値は 1 件以上に固定で、設定項目はありません。Warning / Info / Suggestion は何件あっても止まりません。

配線しているフックは 3 本です: 対象投稿タイプごとの rest_pre_insert_{$post_type}wp_insert_post_dataadmin_noticestransition_post_statussave_post は使っていません。

経路 A: REST 主経路経路 B: 非 REST フォールバック
フックrest_pre_insert_{$post_type}wp_insert_post_data
対象ブロックエディタの公開、/wp/v2/posts などコア REST コントローラ経由の書き込みClassic Editor、クイック編集、wp_insert_post() を使うプログラム・インポータ
ブロック時の動作保存そのものを中断して WP_Error を返すステータスを draft に書き換えて保存を続行(下書きに差し戻し)
エラーコード / HTTPjpl_publish_blocked / 403なし(通常の保存として完了する)
付帯情報data.summary(重要度別件数)と data.findingsError 指摘だけrule_key / message / text で抜粋)なし。admin_notices次に 1 回だけ通知(投稿編集画面のみ・有効期間 5 分)

REST 主経路が処理した保存は、続く wp_insert_post_data では再評価しません(内部フラグ)。ただし REST であってもコア posts コントローラを通らない書き込み(独自ルート・インポータ等)は経路 B が評価します。403 レスポンスに truncated は含まれません。

対象になる状態遷移

定数は PUBLIC_STATUSES = ['publish', 'future']LIVE_STATUSES = ['publish']

新ステータス旧ステータスゲート対象
publish(新規)/ draft / pending対象
future(新規)/ future対象(予約公開の設定時も、予約投稿を編集して保存したときも検査する)
publishpublish対象外(公開済み記事の更新はブロックしない)
draft / pending / private任意対象外
  • WP-Cron による futurepublish の自動公開は wp_insert_post_data を通らないためゲートが走りません。だからこそ future への遷移・編集の側を対象にしています。
  • REST の部分更新で post_status が送られない場合は、既存投稿の現在のステータスを新ステータスとみなします。本文・タイトル・スラッグ・抜粋も送られなければ DB の現在値で評価します。「ステータスだけ publish に変える」保存でも、タイトルに残った Error でブロックされます。
  • ゲートが張られるのは設定 post_types の投稿タイプだけです。既定は postpage の 2 つで、v0.1.0 にこれを変更する管理画面 UI はありません。カスタム投稿タイプを対象にするにはオプション jpl_settings をコードで書き換える必要があります。
  • 公開前チェックの時間予算は 5.0 秒です。超過すると残りのルールをスキップした部分結果で判定します。
  • ゲートが呼ぶのはルールエンジン(trigger = 'prepublish')だけで、AI 最終チェックの指摘は公開ブロックに一切関与しません

バイパス

評価順は capability が先、フィルタが後です。capability を持っていればフィルタは呼ばれません。2 経路とも同じ判定を通ります。

  1. capability jpl_force_publish — 判定対象は現在ログイン中のユーザーであって、記事の著者ではありません。
  2. フィルタ jpl_skip_publish_gate — cron・インポータ向けの逃し弁として実装されています(設定 UI ではありません)。

バイパスしても評価とログ記録は必ず走ります。ログには blocked = 1 が残ります(blocked は「ブロック条件を満たしたか」であって「実際に公開が止まったか」ではありません)。誰がバイパスしたかを記録する列は jpl_logs にありません(記録される author_id は記事の著者です)。

フック(フィルタ)

提供している拡張ポイントは フィルタ 4 本のみです。do_action() によるカスタムアクションは 0 件で、プラグインが独自に発火するアクションフックはありません。JavaScript 側(@wordpress/hooks)のフックもありません。

フック名引数用途
jpl_seo_adaptersSeo_Adapter[] $adaptersSEO 連携アダプタ(Yoast SEO / Rank Math / All in One SEO)の一覧を差し替える
jpl_seo_fieldsarray<string,string> $fields, int $post_id抽出済みの seo_title / seo_description を上書きする
jpl_skip_publish_gatebool $skip(既定 false), WP_Post|null $post(新規は null), array $contextpost_type / content公開前ゲートの逃し弁(cron・インポータ等)
jpl_tour_sample_contentarray $sampletitle / slug / excerpt / contentオンボーディングツアーのデモ原稿を差し替える。content は Gutenberg のシリアライズ済みブロックであること
apply_filters(
    'jpl_skip_publish_gate',
    false,                                                 // bool     バイパスするか
    $post,                                                 // WP_Post|null
    [ 'post_type' => $post_type, 'content' => $content ]   // array
);

SEO 欄の取得は、Yoast SEO / Rank Math / All in One SEO のアダプタを順に試し、最初に有効だったもの 1 つだけを使います。どれも有効でなければ空になります。取得したキーは正規化され、キー名に title を含むものは seo_titledesc を含むものは seo_description に寄せられます。

同梱モジュール由来の plugin_bug_report_is_license_active / plugin_bug_report_should_display / plugin_bug_report_allow_with_heavy_plugin はバグ報告ウィジェットのフックで、校正機能とは無関係です。

辞書のインポート / エクスポート形式

インポート/エクスポートがあるのは辞書エントリだけです。ルール・プロファイル・割り当て・無視設定・プラグイン設定に入出力機能はありません。取り込み先の辞書は URL の {id} で決まるため、先に辞書を作っておく必要があります

CSV(7 列・順序固定)

1 行目のヘッダは必須です。小文字化・トリム後にこの並びと完全一致しなければ、1 行目エラーとして全件不採用になります。

#列名必須既定(空欄時)値の規則
1pattern検出表記。空はエラー。最大 500 バイト
2suggestionnull推奨表記。空文字は DB では null
3alternativesnull許容表記を |(パイプ)区切り。前後空白は除去、空要素は捨てる
4match_typeexactexact / partial / regex(小文字化される)。regex は保存前にコンパイル検証
5case_sensitive00 / 1 / true / false(大小無視)。それ以外はその行がエラー
6notenullメモ
7is_enabled10 / 1 / true / false。それ以外はその行がエラー
  • UTF-8 BOM は除去して受け付けます。全セルが空の行はスキップ、列数が 7 でない行はエラーとしてスキップします。
  • エラー行の行番号は CSV レコード番号(ヘッダ = 1)です。引用符内改行を含むセルがあると物理行とはずれます。
  • fgetcsv / fputcsv$escape = ''(RFC 4180 準拠)で呼びます。\ で終わるセルが後続行を飲み込む問題を回避するためです。
  • 往復で保たれるのは 7 列の値だけです。id / dictionary_id / created_at / updated_at は列に無く、取り込み先で新しい ID が振られます。無効(is_enabled=0)のエントリも書き出されます。
  • alternatives の値そのものに | が含まれる場合、往復で分割されます(区切り文字と衝突するため)。

JSON

「辞書メタ + entries 配列」の単一オブジェクトです。出力は JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT(日本語がそのまま読める整形済み JSON)。

{
  "name": "辞書名",
  "type": "notation",
  "description": "説明",
  "entries": [
    {
      "pattern": "Wordpress",
      "suggestion": "WordPress",
      "alternatives": null,
      "match_type": "exact",
      "case_sensitive": 0,
      "note": null,
      "is_enabled": 1
    }
  ]
}
  • case_sensitive / is_enabled整数 0/1で出力します。取り込み時は true / false / "true" / "false" / 0 / 1 / bool を受け付け、"false" は 0 になります(単純な truthy 判定ではありません)。
  • 辞書メタ(name / type / description)は取り込みに使われません。参考情報です。
  • エラー行の行番号は entries 配列の位置(1 始まり)です。entries が無い・JSON が壊れている場合は line: 0 の 1 件エラーで全件不採用になります。

取り込みの挙動

論点実装
既存データとの関係追記型(append)。既存エントリの上書きも重複スキップもしません。同じファイルを 2 回入れれば同じ語が 2 行できます
2 段階フロー既定 dry_run=true で件数とエラー行だけを返し、DB は触りません。dry_run=false で確定します
dry run のレスポンスtotal(解析できた行 + フォーマット層エラー行)/ valid(取り込み可能行)/ errors[]{line, reason}・行番号昇順)
エラー行スキップして報告。1 行でも壊れていれば全体が止まる、という挙動ではありません
確定時の再検証dry run 済みでも validate_entry を通し直します
書き込み単位200 行ずつのチャンクで複数行 INSERT し、全チャンクを 1 トランザクションで括ります。途中失敗時は全体 ROLLBACK して jpl_db_error
ファイルサイズ上限5,242,880 バイト(5MB)。超過は 400 jpl_file_too_large行数の上限は実装にありません
存在しない辞書への取り込み404 jpl_not_found
管理画面経路REST とは別に admin-post.php 経路(jpl_import_entries → プレビュー、jpl_import_commit → 確定)があります。ファイル内容は 15 分の transient に生のまま保持し、表示・確定時に再パースします。プレビューのエラー表示は先頭 100 件まで

CSV インジェクション対策: 書き出し時、' を 0 個以上挟んで = + - @ に到達するセルの先頭に ' を前置します。取り込み時は同じ規則で 1 つだけ剥がすため、エクスポート → 編集 → 再インポートで語が変質しません。あわせて suggestion / notesanitize_textarea_fieldalternatives の各要素は sanitize_text_field を通し、一括 INSERT を含む全値を $wpdb->prepare に通します。ダウンロードファイル名は sanitize_file_name() を通し、空なら dictionary-{id}.csv にフォールバックします。

管理画面のエクスポートリンクは REST URL に _wpnoncewp_rest nonce)を付けたものです。公開ダウンロード URL ではありません。管理画面経路のアップロードは is_uploaded_file() を必須とし、nonce(check_admin_referer)と capability を検証します。

校正エンジンの拡張ポイントと制約

ルールの挙動は jpl_rules.params(longtext / JSON)で調整します。専用の入力欄はなく、管理画面「ルール」の「その他パラメータ(JSON)」テキストエリアに書く方式です(参照辞書だけはチェックボックス UI)。未設定のキーは既定値でマージされます。プロファイル側の params_override丸ごと置換で、キー単位の部分マージはしません。

種別キー画面表示名params キー既定値意味
notation表記ゆれdictionariesなし参照する辞書 ID の配列
choon未設定'short' のときだけ「語末の長音符を省く」ヒューリスティクスを追加。語末の を除いて 3 文字以上残るカタカナ語が対象
forbidden禁止語・注意語dictionariesなし参照する辞書 ID の配列
redundancy冗長表現dictionariesなし参照する辞書 ID の配列
style文体tonenull'desumasu' / 'dearu' を指定すると期待文体を固定。null なら多数決(同数なら指摘しない)
max_ending_repeat3同じ語尾がこの回数連続したら指摘(2 未満を指定しても 2 に丸められる)
phrase_frequency[]{"表現": 閾値} のマップ。閾値は最低 1 に丸められる
long_sentence長文max_chars801 文の文字数上限(超えたら指摘)
max_commas41 文中の の個数上限
max_conjunction_repeat2同じ文頭接続詞で始まる文の連続回数(対象は固定 15 語)
max_bracket_depth1括弧の入れ子の深さ上限
list_suggestion_commas6読点がこの数以上なら箇条書きを提案する一文を追記
char_width全角半角alnum'half'全角英数字を半角に寄せる
space'half'全角スペースを半角に寄せる
half_kana'full'半角カタカナを全角に寄せる
symbols'half'全角記号を半角に寄せる。対象は %/:-+=&#@~| の 11 文字のみ
punctuation句読点style'ten_maru''ten_maru'(、。)/ 'comma_period'(,.)
require_period1段落末の句点欠落を指摘するか
seo_fieldSEO 項目fields['title','excerpt','slug','seo_title','seo_description']チェック対象のフィールド
checks['notation','forbidden','redundancy','char_width','punctuation']委譲するルール種別

char_width の params は既定以外の値(例 'ignore')にすればその検出が無効になります。seo_field は自前で検出せず、同じ実効プロファイル内の他ルールを本文以外のフィールドへ再実行させる委譲型です(seo_field どうしの委譲は起きません)。既定の checksstylelong_sentence は含まれないため、タイトル・抜粋・SEO 欄では文体・長文チェックは既定では走りません。

正規表現ルールの制約

  • パターンはデリミタなしで保存し、使用時に ~ デリミタ + u(Unicode)フラグでコンパイルします。大小を区別しない設定なら i フラグを追加します。ユーザーが書いた未エスケープの ~ だけを自動エスケープします(既存の \~ を二重エスケープしません)。
  • 長さ上限は 500 バイトstrlen 判定)。空・空白のみは拒否します。保存時に ~u でコンパイルし preg_match を試行して、失敗すれば jpl_invalid_pattern で保存を拒否します。
  • バックトラック爆発(ReDoS)そのものは検出しません。500 バイト上限が予防を兼ねている、という位置づけです。実行時にパターンが失敗しても例外は出さず「0 件ヒット」として進みます。
  • 検証は「ルールの patternmatch_type=regex)」「辞書エントリの pattern(保存時・インポートの dry run と確定の両方)」で走り、照合実行時も保存時と同じコンパイル処理を使います。

エンジン側の制約

  • 形態素解析器(MeCab / Sudachi 等)は使いません。正規表現 + 辞書 + 文分割ヒューリスティクスで動き、外部 API への送信もありません(AI 最終チェックは別機能・既定 OFF・手動実行)。
  • 照合は NFKC 正規化したテキストに対して行い、ヒット位置を原文の文字位置へ写像します。intl 拡張(\Normalizer)が無い環境では mb_convert_kana($text, 'asKV') にフォールバックするため、intl は必須ではありません
  • 日本語に語境界(word boundary)を付けられません。CJK を含むパターンの「完全一致」は実質「出現一致」と同じ挙動になります。語境界が付くのは ASCII 英数字・アンダースコアのみで構成された exact パターンだけです。
  • 辞書は 500 語単位の交替正規表現に事前コンパイルし、辞書の更新スタンプとエントリのフィンガープリントをキーに 12 時間 transient にキャッシュします。同一パターンの重複登録は先勝ちで 1 件に、包含される短いヒットは落として長い語を優先します。
  • 時間予算はルール 1 本ごとに判定します(自動・手動 3.0 秒 / 保存・公開前 5.0 秒)。超過すると truncated = true にしてループを抜け、それまでの指摘は部分結果としてそのまま返します。1 本のルールの実行中に予算を超えてもそのルールは最後まで走ります(チェック内部に予算判定はありません)。
  • 校正対象にならないブロック: core/code / core/html / core/preformatted / core/embed / core/shortcode / core/freeform-embed と、core-embed/ で始まる旧形式の埋め込み。設定 exclude_quotes(既定 1)が有効なら core/quote / core/pullquote も除外します。除外ブロックの innerBlocks も連鎖して除外されます。
  • 本文中の URL・メールアドレス・ショートコードは、オフセットを保つため同じ文字数のマスク文字 U+FFFC に置換されてから照合されます(=指摘の対象外)。<script> / <style> は中身ごと削除、残りの HTML タグは wp_strip_all_tags() で除去します。
  • 実効プロファイルは DB に保存せず都度計算します(キャッシュはありません)。レイヤーは弱→強の順に globalrolepost_typetagcategoryuserpost の 7 段で、priority同一レイヤー内のタイブレーク専用です(数値でレイヤーの上下は覆せません)。role / user がマッチするのは投稿の著者であって、編集中のログインユーザーではありません。
  • ワンクリック修正が実際に適用されるのは、ルールの auto_fixable が真・指摘に suggestion がある・field === 'content' かつ block_index !== null・実効プロファイルの auto_fix が真、をすべて満たすときだけです。書き換え対象はブロック属性(RichText 値)で、post_content の生 HTML ではありません。RichText の生の値に <& が含まれるブロックは誤置換を避けるため修正せず「指摘のみ」に倒します。

アンインストール時の挙動

プラグインをアンインストール(削除)しても、既定ではデータは削除されません。設定画面のチェックボックス(オプション jpl_delete_data_on_uninstall・既定は空文字=オフ)を '1' にしたうえで削除した場合のみ、次のデータが削除されます。停止(無効化)では何も削除されません

対象処理
カスタムテーブル 8 本prefix 付きで DROP TABLE IF EXISTS
独自 capability 8 種全ロールから remove_cap
オプションoption_name LIKE 'jpl_%' を一括 DELETE(ライセンス情報を含む
transient_transient_jpl_%_transient_timeout_jpl_% を一括 DELETE
post metameta_key LIKE '_jpl_%' を一括 DELETE(_jpl_profile_id / _jpl_disabled
オブジェクトキャッシュ直 SQL 削除の後始末として wp_cache_flush()

削除されないものは次のとおりです。

  • user meta _jpl_tour(オンボーディングツアーの進行状況)— uninstall.php に user meta を削除する処理はなく、オプトインを有効にしていても wp_usermeta に残ります。
  • 投稿本文・記事データ — 触る処理はありません。
  • cron イベント(jpl_purge_logs / jpl_daily_license_check)— uninstall.php では解除しませんが、削除前に必ず通る無効化フックで解除済みです。

無効化(deactivate)時に行うのは、日次 cron jpl_purge_logs の解除、ライセンス cron jpl_daily_license_check の解除(自プロダクトのインスタンスのときだけ)、flush_rewrite_rules() の 3 つです。データ・capability・ライセンス情報はいずれも残ります。

※ 本ページの内容は v0.1.0 時点の実装に基づきます。マルチサイトのネットワーク対応コードは実装されておらず、テーブルは有効化したサイトの $wpdb->prefix でのみ作成されます。翻訳ファイル(.po / .mo)は同梱していないため、UI にはソース内の日本語がそのまま表示されます。