管理画面の投稿一覧・投稿編集画面でカテゴリの一覧の表示を少なくするプラグインを作りました。
カテゴリを大量に使用している WordPress サイトがあるのですが、投稿編集画面や投稿一覧画面でカテゴリを選択使用とした際にどこにあるのかスクロールバーを右往左往させることが多いのが悩みでした。
サイトの用途として
という状態です。端的に言えば「追加するだけ追加するけど、一定の期間を終えたらそのカテゴリを使用することはほぼない」「検索用途として使用するため、カテゴリの削除は基本しない」という運用です。
そうなると、冒頭のように「(編集の際に)大量のカテゴリのチェックボックスからスクロールしまくって目的のカテゴリを探す」羽目になるわけです。
これをどうにかしたい。
この悩みを解決するために、以下のような機能を考えました。
できたものがこちらになります。
まずは準備。適当な WordPress サイトを Docker 等で建てて上述のようなサンプルのカテゴリを作成します。
これで試験します。
次に設定画面。
非表示にする投稿のカテゴリを選択するチェックボックスと、 JavaScript 側の制御のタイムアウト期限の2つの枠を作りました。
前者は親子関係にきちんと沿った表示をするために Walker_Category_Checklist
クラス を extends して start_el
メソッド をカスタマイズしています。
後者は JavaScript でポーリングする回数の最大値(後述)です。
これについては、投稿新規作成画面と投稿編集画面でのカテゴリ一覧の非表示で壁に当たったのがきっかけで作りました。
これらの画面は AJAX 経由でカテゴリ一覧を作成しているようなので、サーバサイド( PHP )での制御は難しいと判断しました(やるとしたら、 WP REST API の出力を絞る?)。
また、仮にサーバサイドでカテゴリ一覧を絞ってしまうと、過去記事のカテゴリを整理する際に
の2つの条件を満たすカテゴリが存在した場合、チェックされずに記事の保存が行われてしまう、つまり「カテゴリに既に付けてあったチェックが外れてしまう」可能性が考えられるため、この点でもサーバサイドのみでの制御は難しいと考えました。
そこで苦肉の策ではありますが、 JavaScript で「一定時間おきにカテゴリの一覧が描画されたか(クラス editor-post-taxonomies__hierarchical-terms-list
の要素があるか)をポーリング」し、「存在したことを確認したら該当カテゴリの項目を非表示にする」ことにしました。
このポーリングの回数が上述のタイムアウト期限の項目になります。
register_setting
のコールバックにバリデーションも登録しました。
開発者ツールを使ってタイムアウト期限の input
タグを type="number"
から type="text"
に変えて文字列を入力します。
結果、エラー表示されました。
正しい入力の場合は保存の通知が表示されます。
今度はチェックボックスで送信される値を操作します。
結果、エラー表示されました。
こちらも正しい入力の場合は保存の通知が表示されます。
「カテゴリを選択した際に子孫カテゴリがいる場合は、これも一括で非表示にする」という仕様ですが、これもやや頭を悩ませるものでした。
というのは、 Walker_Category_Checklist
クラス で探索するカテゴリは「自身から見て親と子」の情報は持っていますが、親のさらに上の祖先や、逆に孫以下の情報は直接は持っていなさそうでした。
そのため、「あるカテゴリを非表示にした」場合、子供はともかく孫以降まで非表示にする判定をして行かなければなりません。
逆に、あるカテゴリに非表示のチェックが付いていなかったとしても、親より上の祖先のカテゴリが非表示チェックが付いていないか判定しなければなりません。
どちらも再帰的に探索して潰していく形になるので、そこそこ面倒かと。
今回は実装スピードを重視したかったので、上述のような再帰的な判定ではなく、「設定画面であるカテゴリにチェックを付けたら、子孫カテゴリも全て連動してチェックを付ける」機能を JavaScript 側で実装しました。
そこで、「親以上のカテゴリでチェックが付いていたら子孫カテゴリはチェックを外せない」という機能も追加しました。
続いて、投稿編集画面(新規投稿、既存投稿の編集)。
テストのため、一度プラグインを無効化して、表示し続ける予定の「テスト子供2」の他に、非表示にする予定の「テスト孫1」「サンプル子供」もカテゴリとしてチェックを付けておきます。
投稿一覧画面で「テスト子供2」「テスト孫1」「サンプル子供」のカテゴリに所属していることを確認しておきます。
続いてプラグインを有効化し、以下のように非表示設定をします。
先ほどの投稿では、上述の通り「テスト子供2」は残りますが、「テスト孫1」「サンプル子供」の2つは非表示になります。
投稿編集画面で「テスト孫1」「サンプル子供」が非表示になっていることを確認。「テスト子供2」だけ表示上残っています。
この状態で「未分類」カテゴリにも所属するようにチェックを付けて「更新」します。
投稿一覧画面で元々チェックが付いていて表示されていた「テスト子供2」、新規で追加した「未分類」はもちろん、非表示になっている「テスト孫1」「サンプル子供」も依然として所属していることが確認できました(原案時点、 display: none;
で全くの非表示にした場合は「テスト孫1」「サンプル子供」のチェックが外れてしまったので、若干の工夫が必要でした)。
なお、投稿編集画面のカテゴリは以下の操作を行う度にメニューの中が再描画されるため、最初の編集画面表示時以外のタイミングでも非表示にするように JavaScript の調整が必要でした。
続いて投稿一覧画面。
いったん先ほどのテスト投稿のカテゴリを「テスト子供2」「テスト孫1」「サンプル子供」の3つに戻しておきます。
この状態で「クイック編集」をクリックし、カテゴリの一覧を表示させます。先ほどと同様、「テスト孫1」「サンプル子供」の2つは非表示になっています。
この状態で「更新」。
投稿一覧画面に戻り、依然「テスト子供2」「テスト孫1」「サンプル子供」の3つに所属し続けています。
Walker_Category_Checklist
クラス をカスタマイズした
display: none;
で潰してしまうと、保存時にチェックが外れてしまうので 1x1px で position: absolute;
して……など、「見た目上は非表示に見えるが要素としては存在している」状態にしたwp_terms_checklist_args
は投稿編集画面、投稿一覧画面以外でもフックが発火するので、「管理画面内」全体でアクションフックを掛けると動作に不具合が出るため、アクションフック発火前に別個でページ判定を実施し、意図した部分だけアクションフックが掛かるように制限した点
$hook_suffix
で判定して回避可能他、WordPress の head タグの中を整理するプラグイン (設定画面付き) の自作に類する点。
連続でプラグインを作ったことで、ある程度知見を貯めることはできたのではないかと個人的には思います。
今回は
というイメージから、「木の切り落とす音はするが、音のした方向を探しても倒れた木が見付からない」怪異である古杣(ふるそま)を採用しました。
なお、類似の怪異は「天狗倒し」「天狗ナメシ」「空木(からぎ)倒し」「空木(そらぎ)倒し」「天崩し」「木伐り坊」等のバリエーションがあります。
in_array
json_encode
htmlspecialchars
parse_url
mb_strpos
wp_terms_checklist_args
Walker_Category_Checklist
admin_print_styles
hook_suffix
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント