1. ホーム
  2. WordPress

【WordPress】allowed_block_types_all の使い方|投稿タイプごとに使えるブロックを制限する方法

Share

ブロックエディターのインサーター(ブロック追加パネル)を開くと、コアブロックだけでも相当な数が並びます。プラグインを入れればさらに増えます。制作者にとっては便利ですが、記事を書くだけの担当者にとっては選択肢が多すぎて迷いのもとです。

テーマでスタイルを当てていないブロックを使われて、表示が崩れることもあります。そこで役に立つのが allowed_block_types_all フィルターです。投稿タイプごとに「使えるブロック」を指定して、それ以外を非表示にできます。

この記事では、許可するブロックを列挙する方法と、一部だけを除外する方法、投稿タイプや編集画面による条件分岐、そして意図どおりに効かないときの確認ポイントを解説します。

allowed_block_types_all フィルターの形

このフィルターは WordPress 5.8 で追加されました。それ以前の allowed_block_types は非推奨なので、これから書くなら _all が付くほうを使います。

渡ってくる引数は2つです。

引数内容
$allowed_block_typestrue(すべて許可)またはブロック名の配列
$block_editor_contextWP_Block_Editor_Context オブジェクト。編集中の投稿や、どの編集画面かが入っている

戻り値としてブロック名の配列を返すと、そこに書いたブロックだけが使えるようになります。true を返せば制限なし、空の配列を返せばすべてのブロックが使えなくなります。

functions.php
<?php
/**
 * 使えるブロックを限定する
 *
 * @param bool|string[]           $allowed_block_types 許可するブロック名の配列、または true
 * @param WP_Block_Editor_Context $context             編集画面のコンテキスト
 * @return bool|string[]
 */
function mytheme_allowed_block_types( $allowed_block_types, $context ) {
    return array(
        'core/paragraph',
        'core/heading',
        'core/list',
        'core/list-item',
        'core/image',
        'core/quote',
        'core/table',
        'core/buttons',
        'core/button',
    );
}
add_filter( 'allowed_block_types_all', 'mytheme_allowed_block_types', 10, 2 );

add_filter() の第4引数に 2 を指定するのを忘れないでください。これがないと第2引数のコンテキストを受け取れず、条件分岐が書けません。

また、親子関係のあるブロックは両方を書く必要があります。core/list だけを許可して core/list-item を書き忘れると、リストを追加しても項目を入力できません。同じく core/buttons と core/button、core/columns と core/column もセットで指定します。

投稿タイプごとに変える

第2引数の $context には、編集中の投稿が post プロパティとして入っています。ここから投稿タイプを見て、条件を分けられます。

functions.php
<?php
function mytheme_allowed_block_types( $allowed_block_types, $context ) {
    // 投稿編集画面以外(サイトエディターなど)はそのまま返す
    if ( empty( $context->post ) ) {
        return $allowed_block_types;
    }

    // お知らせ投稿タイプだけ、最小限のブロックに絞る
    if ( 'news' === $context->post->post_type ) {
        return array(
            'core/paragraph',
            'core/heading',
            'core/image',
            'core/list',
            'core/list-item',
        );
    }

    return $allowed_block_types;
}
add_filter( 'allowed_block_types_all', 'mytheme_allowed_block_types', 10, 2 );

条件に当てはまらないときは、受け取った $allowed_block_types をそのまま返すのが作法です。ここで true を決め打ちで返してしまうと、他のプラグインが設定した制限を打ち消してしまいます。

$context->post は、投稿編集画面以外では null になることがあります。サイトエディターやウィジェット画面でも同じフィルターが呼ばれるためです。プロパティにアクセスする前に、必ず存在を確認してください。

どの編集画面かで分ける

$context->name には、呼び出し元の編集画面を表す文字列が入ります。投稿編集画面は core/edit-post、サイトエディターは core/edit-site です。

functions.php
<?php
function mytheme_allowed_block_types( $allowed_block_types, $context ) {
    // 投稿・固定ページの編集画面だけを対象にする
    if ( 'core/edit-post' !== $context->name ) {
        return $allowed_block_types;
    }

    // ここに制限の処理を書く
    return $allowed_block_types;
}
add_filter( 'allowed_block_types_all', 'mytheme_allowed_block_types', 10, 2 );

サイトエディターでブロックを制限すると、テンプレートの編集に必要なブロック(クエリーループやサイトタイトルなど)まで消えてしまいます。制限は投稿編集画面だけにとどめておくのが無難です。

一部のブロックだけを除外する

「特定のブロックだけ使わせたくない」という場合、許可リストを書くのは現実的ではありません。数が多いうえ、プラグインを追加するたびに書き足す必要が出てきます。

この場合は、登録済みのブロックをすべて取得してから、不要なものを取り除きます。一覧は WP_Block_Type_Registry から取得できます。

functions.php
<?php
function mytheme_disallow_block_types( $allowed_block_types, $context ) {
    if ( 'core/edit-post' !== $context->name ) {
        return $allowed_block_types;
    }

    // 登録済みのブロック名を配列で取得する
    $registry   = WP_Block_Type_Registry::get_instance();
    $all_blocks = array_keys( $registry->get_all_registered() );

    // 使わせたくないブロック
    $denied = array(
        'core/verse',
        'core/preformatted',
        'core/freeform',   // クラシックブロック
        'core/html',       // カスタムHTML
    );

    // 差集合を取り、キーを振り直して返す
    return array_values( array_diff( $all_blocks, $denied ) );
}
add_filter( 'allowed_block_types_all', 'mytheme_disallow_block_types', 10, 2 );

array_diff() はキーを保持したまま返すため、そのまま渡すと連番でない配列になります。JSON に変換されたときにオブジェクト扱いされて正しく動かないことがあるので、array_values() でキーを振り直しておくのが確実です。

ブロック名が分からないときは、対象のブロックを一度エディターに挿入し、投稿を保存してから本文を「コードエディター」で表示してみてください。<!-- wp:core/xxx --> の形でブロック名が確認できます。

ユーザーの権限で分ける

「管理者は全部使えるが、投稿者は限定する」という運用もよくあります。フィルターの中で権限を判定すれば実現できます。

functions.php
<?php
function mytheme_allowed_block_types_by_role( $allowed_block_types, $context ) {
    // テーマやプラグインを編集できる権限があるなら制限しない
    if ( current_user_can( 'edit_theme_options' ) ) {
        return $allowed_block_types;
    }

    return array(
        'core/paragraph',
        'core/heading',
        'core/image',
        'core/list',
        'core/list-item',
    );
}
add_filter( 'allowed_block_types_all', 'mytheme_allowed_block_types_by_role', 10, 2 );

権限の判定には current_user_can() を使います。役割名を直接比較するより、必要な権限(capability)で判定するほうが、独自の役割を追加したときにも破綻しません。

入れ子の制限とは別物

混同しやすいのですが、allowed_block_types_all が制御するのは「エディター全体で使えるブロック」です。「このブロックの中には、このブロックしか入れられない」という入れ子の制限は、block.json の parent・ancestor・allowedBlocks や、InnerBlocks の allowedBlocks で指定します。

やりたいこと使うもの
エディター全体で使えるブロックを絞るallowed_block_types_all(PHP)
自作ブロックの中に入れられるブロックを絞るallowedBlocks(block.json / InnerBlocks)
自作ブロックを特定の親の中だけで使えるようにするparent / ancestor(block.json)

思ったとおりに効かないとき

制限したのにブロックが消えない

まず add_filter() の第4引数を確認してください。10, 2 を書いていないと第2引数が渡らず、$context が未定義エラーになってフィルター自体が動きません。

次に、他のプラグインが同じフィルターで true を返していないか調べます。フィルターは順番に適用されるため、あとから実行された処理が上書きします。優先度を 20 や 99 に上げると、自分の指定を後勝ちにできます。

すでに使われているブロックはどうなるか

このフィルターが制御するのは「新しく挿入できるかどうか」です。過去の投稿にすでに入っているブロックが消えることはありませんし、フロント側の表示にも影響しません。

ただし、許可リストから外したブロックを含む投稿を編集画面で開くと、そのブロックが「このブロックはサポートされていません」という表示になることがあります。既存コンテンツがある状態で制限をかけるときは、実際に古い投稿を開いて確認しておくと安心です。

パターンや再利用ブロックが使えなくなった

パターンは複数のブロックの組み合わせなので、その中に許可していないブロックが含まれていると正しく挿入できません。パターンを使う運用なら、パターンに含まれるブロックも許可リストに入れておく必要があります。

同期パターン(旧・再利用ブロック)を使う場合は core/block も許可リストに加えてください。これを忘れると、パターン自体を挿入できなくなります。

まとめ

allowed_block_types_all は、ブロックエディターで使えるブロックを制限するためのフィルターです。ブロック名の配列を返せばそれだけが使え、true を返せば制限なしになります。add_filter() の第4引数に 2 を指定して、コンテキストを受け取るのを忘れないでください。

使うブロックが少数に決まっているなら許可リストを列挙し、一部だけ外したいなら WP_Block_Type_Registry から全ブロックを取得して array_diff() で差し引く。この2パターンを押さえておけば、たいていの要件は書けます。

制限をかけるときは、親子関係のあるブロックを両方指定すること、サイトエディターを巻き込まないこと、この2点に注意してください。編集画面がすっきりすると、コンテンツ担当者の迷いも、デザイン崩れの問い合わせも減らせます。

参考ページ