Extended Page Creation Patterns to Posts and Custom Post Types

Dev note as of 8/21/23:
With the addition of “synced patterns” in WordPress 6.3, this method is no longer needed.

This is an extension of this post where I go into detail about how to add page creation patterns to my custom block patterns admin UI. With the release of WordPress 6.1, we now have the ability to assign custom page creation patterns to any post type (not just pages), which is what I will explain in this post.

Step 1: Create an array of post types

First, we’ll create an array of available post types. I include the basic “page” and “post” in this tutorial, but you can easily extent this to include as many post types as you’d like.

<?php
// array of available post types to assign creation patterns to
$available_post_types = [
	'page' => 'Page',
	'post' => 'Post',
];

Step 2: Add a checkbox field to assign post types to each block pattern

Next, we’ll add an ACF checkbox field that will show when block creation patterns are enabled. This will automatically populate with the array of post types we defined in the previous step. This will allow the end user to choose exactly what post type(s) they want their creation patterns to show on.

Note: the conditional_logic field value should match the field value from your own enable creation pattern ACF field.

<?php
[
	'key'               => 'field_638116e760be6',
	'label'             => 'Creation Patterns Locations',
	'name'              => 'wd_creation_patterns_locations',
	'aria-label'        => '',
	'type'              => 'checkbox',
	'instructions'      => 'Choose what post type(s) you would like to assign this creation pattern.',
	'required'          => 1,
	'choices'           => $available_post_types,
	'default_value'     => [],
	'return_format'     => 'value',
	'allow_custom'      => 0,
	'layout'            => 'vertical',
	'toggle'            => 0,
	'save_custom'       => 0,
	'conditional_logic' => [
		[
			[
				'field'    => 'field_631b432effe37',
				'operator' => '==',
				'value'    => '1',
			],
		],
	],
	'wrapper' => [
		'width' => '',
		'class' => '',
		'id'    => '',
	],
],

Step 3: Create $postTypes array for use in pattern registration

Next, within the block_patterns query, we create an array of post types from the checkboxes selected by the user. This will be used to define where to show the creation patterns when we register the block pattern.

<?php
$wd_creation_patterns_locations = get_field( 'wd_creation_patterns_locations' );
$postTypes = [];
if ( ! empty( $wd_creation_patterns_locations ) && $enable_starter_pattern == 1 ) {
     foreach ( $wd_creation_patterns_locations as $location ) {
          $postTypes[] = $location;
     }
}

Step 4: Add postTypes array to pattern registration

Finally, we’ll add the list of approved post types using the new postTypes option added in WordPress 6.1.

<?php
'postTypes'  => $postTypes,

Wrapping up

And there you have it. You can now create block patterns and assign them on a per-post-type basis to any custom post type as a creation pattern. Pretty snazzy. The full updated code is below:

<?php
/**
 * Setup front end UI for Block Patterns
 *
 * @author       WhiteleyDesigns
 * @since        1.0.0
 * @license      GPL-2.0+
 **/

/*
 * Register Block Patterns Custom Post Type
 */
add_action( 'init', 'wd_register_cpt_block_pattern' );
function wd_register_cpt_block_pattern() {

     $labels = [
          'name'               => _x( 'Block Pattern', 'post type general name', WD_PLUGIN_THEME_SLUG ),
          'singular_name'      => _x( 'Block Pattern', 'post type singular name', WD_PLUGIN_THEME_SLUG ),
          'menu_name'          => _x( 'Block Patterns', 'admin menu', WD_PLUGIN_THEME_SLUG ),
          'name_admin_bar'     => _x( 'Block Pattern', 'add new on admin bar', WD_PLUGIN_THEME_SLUG ),
          'add_new'            => _x( 'Add New', 'Block Pattern', WD_PLUGIN_THEME_SLUG ),
          'add_new_item'       => __( 'Add New Block Pattern', WD_PLUGIN_THEME_SLUG ),
          'new_item'           => __( 'New Block Pattern', WD_PLUGIN_THEME_SLUG ),
          'edit_item'          => __( 'Edit Block Pattern', WD_PLUGIN_THEME_SLUG ),
          'view_item'          => __( 'View Block Pattern', WD_PLUGIN_THEME_SLUG ),
          'all_items'          => __( 'All Block Patterns', WD_PLUGIN_THEME_SLUG ),
          'search_items'       => __( 'Search Block Patterns', WD_PLUGIN_THEME_SLUG ),
          'parent_item_colon'  => __( 'Parent Block Patterns:', WD_PLUGIN_THEME_SLUG ),
          'not_found'          => __( 'No Block Patterns found.', WD_PLUGIN_THEME_SLUG ),
          'not_found_in_trash' => __( 'No Block Patterns found in Trash.', WD_PLUGIN_THEME_SLUG )
     ];

     $args = [
          'labels'              => $labels,
          'description'         => __( 'Block Patterns.', WD_PLUGIN_THEME_SLUG ),
          'public'              => false,
          'exclude_from_search' => true,
          'publicly_queryable'  => true,
          'show_ui'             => true,
          'show_in_menu'        => true,
          'query_var'           => true,
          'capability_type'     => 'post',
          'has_archive'         => false,
          'hierarchical'        => false,
          'menu_position'       => 290,
          'menu_icon'           => 'dashicons-screenoptions',
          'show_in_rest'        => true,
          'supports'            => [
               'title',
               'editor',
               'revisions',
          ],
          'rewrite' => [
               'slug'       => 'block-pattern',
               'with_front' => false,
          ],
     ];

     register_post_type(
          'block_pattern',
          $args
     );
}


/**
 * Add custom block pattern categories
 */
function wd_register_block_pattern_categories() {

     if ( class_exists( 'WP_Block_Patterns_Registry' ) ) {

          register_block_pattern_category(
               'global-pattern',
               [
                    'label' => _x( 'Global Pattern', 'Block pattern category', WD_PLUGIN_THEME_SLUG ),
               ]
          );

     }
}
add_action( 'init', 'wd_register_block_pattern_categories' );


/**
 * Remove core block patterns
 */
remove_theme_support( 'core-block-patterns' );


/**
 * Create categories metabox
 *
 * @link https://www.advancedcustomfields.com/resources/register-fields-via-php/
 */
add_action( 'acf/init', 'wd_add_block_patterns_acf_metabox' );
function wd_add_block_patterns_acf_metabox() {

     // set array of categories to offer
     $block_pattern_categories = [
          'buttons'          => 'Buttons', // core
          'columns'          => 'Columns', // core
          'gallery'          => 'Gallery', // core
          'header'           => 'Headers', // core
          'text'             => 'Text', // core
          // 'query'            => 'Query', // core
          'global-pattern'   => 'Global Pattern', // custom
     ];

     // array of available post types to assign creation patterns to
     $available_post_types = [
          'page' => 'Page',
          'post' => 'Post',
     ];

     // register the ACF field group
     acf_add_local_field_group(
          [
               'key'    => 'group_61a8f5eb8dc40',
               'title'  => 'Block Pattern Options',
               'fields' => [
                    [
                         'key'               => 'field_61a8f608a61fa',
                         'label'             => 'Block Pattern Categories',
                         'name'              => 'wd_block_pattern_categories',
                         'type'              => 'checkbox',
                         'instructions'      => '',
                         'required'          => 0,
                         'conditional_logic' => 0,
                         'choices'           => $block_pattern_categories,
                         'allow_custom'      => 0,
                         'default_value'     => [],
                         'layout'            => 'vertical',
                         'toggle'            => 0,
                         'return_format'     => 'value',
                         'save_custom'       => 0,
                         'wrapper' => [
                              'width' => '',
                              'class' => '',
                              'id'    => '',
                         ],
                    ],
                    [
                         'key'               => 'field_631b432effe37',
                         'label'             => 'Enable Creation Pattern',
                         'name'              => 'wd_block_patterns_enable_starter_pattern',
                         'type'              => 'true_false',
                         'instructions'      => 'Set this pattern as a creation pattern for pages.',
                         'required'          => 0,
                         'conditional_logic' => 0,
                         'message'           => '',
                         'default_value'     => 0,
                         'ui_on_text'        => '',
                         'ui_off_text'       => '',
                         'ui'                => 1,
                         'wrapper' => [
                              'width' => '',
                              'class' => '',
                              'id'    => '',
                         ],
                    ],
                    [
          			'key'               => 'field_638116e760be6',
          			'label'             => 'Creation Patterns Locations',
          			'name'              => 'wd_creation_patterns_locations',
          			'aria-label'        => '',
          			'type'              => 'checkbox',
          			'instructions'      => 'Choose what post type(s) you would like to assign this creation pattern.',
          			'required'          => 1,
          			'choices'           => $available_post_types,
          			'default_value'     => [],
          			'return_format'     => 'value',
          			'allow_custom'      => 0,
          			'layout'            => 'vertical',
          			'toggle'            => 0,
          			'save_custom'       => 0,
                         'conditional_logic' => [
                              [
                                   [
                                        'field'    => 'field_631b432effe37',
                                        'operator' => '==',
                                        'value'    => '1',
                                   ],
                              ],
                         ],
                         'wrapper' => [
                              'width' => '',
                              'class' => '',
                              'id'    => '',
                         ],
          		],
               ],
               'location' => [
                    [
                         [
                              'param'    => 'post_type',
                              'operator' => '==',
                              'value'    => 'block_pattern',
                         ]
                    ]
               ],
               'menu_order'            => 0,
               'position'              => 'side',
               'style'                 => 'default',
               'label_placement'       => 'top',
               'instruction_placement' => 'label',
               'hide_on_screen'        => '',
               'active'                => true,
               'description'           => '',
               'show_in_rest'          => 0,
          ]
     );
}


/*
 * Redirect single posts to home page
 */
add_action( 'template_redirect', 'wd_block_patterns_cpt_redirect_single' );
function wd_block_patterns_cpt_redirect_single() {

     if ( is_singular( 'block_pattern' ) ) {
          wp_redirect( get_home_url() );
          exit;
     }
}


/*
 * Register Block Patterns
 */
add_action( 'admin_init', 'wd_register_block_patterns' );
function wd_register_block_patterns() {

     if ( class_exists( 'WP_Block_Patterns_Registry' ) ) {

          $loop = new WP_Query(
               [
                    'post_type'      => 'block_pattern',
                    'post_status'    => 'publish',
                    'posts_per_page' => -1,
               ]
          );

          if ( $loop->have_posts() ) : while ( $loop->have_posts() ) : $loop->the_post();

               $post_title = get_the_title();
               $post_slug = str_replace( ' ', '-', strtolower( $post_title ) );
               $post_content = get_the_content();
               $enable_starter_pattern = get_field( 'wd_block_patterns_enable_starter_pattern', get_the_ID() );
               $blockTypes = $enable_starter_pattern == 1 ? 'core/post-content' : '';
               $block_pattern_categories = get_field( 'wd_block_pattern_categories', get_the_ID() );
               $wd_creation_patterns_locations = get_field( 'wd_creation_patterns_locations' );
               $postTypes = [];
               if ( ! empty( $wd_creation_patterns_locations ) && $enable_starter_pattern == 1 ) {
                    foreach ( $wd_creation_patterns_locations as $location ) {
                         $postTypes[] = $location;
                    }
               }

               register_block_pattern(
                    'wd/' . $post_slug,
                    [
                         'title'      => $post_title,
                         'blockTypes' => [ $blockTypes ],
                         'postTypes'  => $postTypes,
                         'content'    => trim( $post_content ),
                         'categories' => $block_pattern_categories,
                         'keywords'   => [
                              $post_title,
                              'pattern',
                              'block pattern',
                         ]
                    ]
               );

          endwhile; endif; wp_reset_postdata();
     }
}

Leave a Reply

Your email address will not be published. Required fields are marked *