ACFを使ったカスタムブロックの作り方

# ACFで作成したカスタムブロックの使い方

## 前置き

WordPress 5.0から追加されているブロックエディタ（Gutenberg）のACFを使ったカスタムブロックの使い方を記載していきます。

## 対応時のバージョン

WordPress 5.7.2

## カスタムブロックの作り方

詳しい作り方は[公式のチュートリアル](https://developer.wordpress.org/block-editor/handbook/tutorials/create-block/)を参照。

チュートリアルを見るとわかるがカスタムブロックは基本的にPHPではなくReactの知識が求められる。

なので、今までJSを全くやってこなかったっていう人にはちょっとハードルが高い感じになっている。

そこで[ACF Pro](https://www.advancedcustomfields.com/pro/)が提供する[ACF Blocks](https://www.advancedcustomfields.com/resources/blocks/)を利用することでJS部分は書かずにカスタムのブロックを作ることができる。

## ACFを使ったカスタムブロックの作り方

公式ドキュメントからの引用になるが、基本的に以下のコードを`functions.php`に埋め込んであげれば`testimonial`というブロックが有効化できる。

```php:functions.php
<?php
add_action('acf/init', 'my_acf_init_block_types');
function my_acf_init_block_types() {

    // Check function exists.
    if( function_exists('acf_register_block_type') ) {

        // register a testimonial block.
        acf_register_block_type(array(
            'name'              => 'testimonial',
            'title'             => __('Testimonial'),
            'description'       => __('A custom testimonial block.'),
            'render_template'   => 'template-parts/blocks/testimonial/testimonial.php',
            'category'          => 'formatting',
            'icon'              => 'admin-comments',
            'keywords'          => array( 'testimonial', 'quote' ),
        ));
    }
}
```

実際にエディタと投稿ページに表示するには`render_template`で指定しているテンプレートを作成と登録したブロックにカスタムフィールドを紐づける必要がある。

公式ドキュメントからの引用になるがテンプレートの中身は以下の通り。

```php:template-parts/blocks/testimonial/testimonial.php
<?php

/**
 * Testimonial Block Template.
 *
 * @param   array $block The block settings and attributes.
 * @param   string $content The block inner HTML (empty).
 * @param   bool $is_preview True during AJAX preview.
 * @param   (int|string) $post_id The post ID this block is saved to.
 */

// Create id attribute allowing for custom "anchor" value.
$id = 'testimonial-' . $block['id'];
if( !empty($block['anchor']) ) {
    $id = $block['anchor'];
}

// Create class attribute allowing for custom "className" and "align" values.
$className = 'testimonial';
if( !empty($block['className']) ) {
    $className .= ' ' . $block['className'];
}
if( !empty($block['align']) ) {
    $className .= ' align' . $block['align'];
}

// Load values and assign defaults.
$text = get_field('testimonial') ?: 'Your testimonial here...';
$author = get_field('author') ?: 'Author name';
$role = get_field('role') ?: 'Author role';
$image = get_field('image') ?: 295;
$background_color = get_field('background_color');
$text_color = get_field('text_color');

?>
<div id="<?php echo esc_attr($id); ?>" class="<?php echo esc_attr($className); ?>">
    <blockquote class="testimonial-blockquote">
        <span class="testimonial-text"><?php echo $text; ?></span>
        <span class="testimonial-author"><?php echo $author; ?></span>
        <span class="testimonial-role"><?php echo $role; ?></span>
    </blockquote>
    <div class="testimonial-image">
        <?php echo wp_get_attachment_image( $image, 'full' ); ?>
    </div>
    <style type="text/css">
        #<?php echo $id; ?> {
            background: <?php echo $background_color; ?>;
            color: <?php echo $text_color; ?>;
        }
    </style>
</div>
```

## ホワイトリスト形式での利用するブロックのフィルタリング

ブロックのフィルタリングは`allowed_block_types`を使うことで可能。

指定できるブロックとして[こちら](https://www.nxworld.net/wp-gutenberg-remove-default-block.html)を参考にした。

下記は一例。

```php:functions.php
add_filter('allowed_block_types', function ($allow) {
    return [
        // テキスト
        'core/paragraph',           // 段落
        'core/heading',             // 見出し
        'core/list',                // リスト
        'core/quote',               // 引用
        'core/table',               // テーブル

        // メディア
        'core/image',               // 画像
        'core/gallery',               // 画像

        // デザイン
        'core/columns',             // カラム
        'core/separator',           // 区切り
        'core/spacer',              // スペーサー

        // ウィジェット
        'core/html',                // カスタムHTML

        // 埋め込み
        'core/embed',               // 埋め込み
        'core-embed/twitter',       // Twitter
        'core-embed/youtube',       // YouTube
        'core-embed/wordpress',     // WordPress
    ];
}, 10, 2);
```

ACFで作ったブロックを有効化する場合には、namespaceがacfになるのでACFの公式ドキュメント例のブロックだと`acf/testimonial`を追加する必要がある。

注意点としては実際に絞り込みを行おうとしたときには`core/embed`を許可すると許可していない他の埋め込み系のブロックも出てしまうため、個別でJSでフィルタリングをする必要があった。

JSでフィルタリングする場合は下記例。

```js:example.js
wp.domReady(() => {
  wp.blocks.unregisterBlockVariation( 'core/embed', 'soundcloud' );    // SoundCloud
  wp.blocks.unregisterBlockVariation( 'core/embed', 'spotify' );       // Spotify
  wp.blocks.unregisterBlockVariation( 'core/embed', 'flickr' );        // Flickr
  wp.blocks.unregisterBlockVariation( 'core/embed', 'vimeo' );         // Vimeo
  wp.blocks.unregisterBlockVariation( 'core/embed', 'animoto' );       // Animoto
  wp.blocks.unregisterBlockVariation( 'core/embed', 'cloudup' );       // Cloudup
  wp.blocks.unregisterBlockVariation( 'core/embed', 'crowdsignal' );   // Crowdsignal
  wp.blocks.unregisterBlockVariation( 'core/embed', 'dailymotion' );   // Dailymotion
  wp.blocks.unregisterBlockVariation( 'core/embed', 'imgur' );         // Imgur
  wp.blocks.unregisterBlockVariation( 'core/embed', 'issuu' );         // Issuu
  wp.blocks.unregisterBlockVariation( 'core/embed', 'kickstarter' );   // Kickstarter
  wp.blocks.unregisterBlockVariation( 'core/embed', 'meetup-com' );    // Meetup.com
  wp.blocks.unregisterBlockVariation( 'core/embed', 'mixcloud' );      // Mixcloud
  wp.blocks.unregisterBlockVariation( 'core/embed', 'reddit' );        // Reddit
  wp.blocks.unregisterBlockVariation( 'core/embed', 'reverbnation' );  // ReverbNation
  wp.blocks.unregisterBlockVariation( 'core/embed', 'screencast' );    // Screencast
  wp.blocks.unregisterBlockVariation( 'core/embed', 'scribd' );        // Scribd
  wp.blocks.unregisterBlockVariation( 'core/embed', 'slideshare' );    // Slideshare
  wp.blocks.unregisterBlockVariation( 'core/embed', 'smugmug' );       // SmugMug
  wp.blocks.unregisterBlockVariation( 'core/embed', 'speaker-deck' );  // Speaker Deck
  wp.blocks.unregisterBlockVariation( 'core/embed', 'tiktok' );        // TikTok
  wp.blocks.unregisterBlockVariation( 'core/embed', 'ted' );           // TED
  wp.blocks.unregisterBlockVariation( 'core/embed', 'tumblr' );        // Tumblr
  wp.blocks.unregisterBlockVariation( 'core/embed', 'videopress' );    // VideoPress
  wp.blocks.unregisterBlockVariation( 'core/embed', 'wordpress-tv' );  // WordPress.tv
  wp.blocks.unregisterBlockVariation( 'core/embed', 'amazon-kindle' ); // Amazon Kindle
});
```

また、Gutenbergにはブロックを組み合わせたテンプレートをパターンという形で登録できますが、既存で登録されているパターンで利用しているブロックを削除した場合には利用できなくなるので注意が必要です。

## 終わりに

実装をやってる途中で5.8が出たのですがリリースが近かったりでアプデ対応はしていません。

5.8ではtheme.jsonという機能が追加されてブロックエディターのカスタマイズがやりやすくなったようです。

theme.jsonのドキュメントは[こちら](https://ja.wordpress.org/team/handbook/block-editor/how-to-guides/themes/theme-json/)。