Justin Tadlock

Post format support for custom post types

When building the Custom Content Portfolio plugin, I needed to add post format support to my portfolio project post type. Generally speaking, this is a pretty easy thing to do. However, I wanted to limit the possible formats to only those that made sense for portfolios.

This tutorial will walk you through the process of what I done to handle that scenario.

Adding post format support

Adding support is as simple as adding one line of code to your supports array when calling register_post_type().

'post-formats'

Here’s what that’d look like in the code:

register_post_type(
        'portfolio_project',
        array(
           'supports' => array(
              'title',
              'editor',
              'post-formats'
           )
        )
);

That’s all you need if you want to support all post formats for a custom post type.

Limiting post formats

If, like me, you have a post type in which you want to limit support to only some of the formats, you’ll need to work a little magic. Core WP doesn’t have filter hooks for disabling formats.

The first thing we’ll do is create a function that returns an array of the post formats that our post type supports. I’ve chosen the audio, gallery, image, and video formats.

function jt_get_allowed_project_formats() {

    return array( 'audio', 'gallery', 'image', 'video' );
}

Because there are no hooks for changing the available formats, we’ll instead work with the “theme support” system by changing the theme-supported formats. We’ll just need to limit it to our post type’s admin screens so that it won’t mess with other post types.

add_action( 'load-post.php',     'jt_post_format_support_filter' );
add_action( 'load-post-new.php', 'jt_post_format_support_filter' );
add_action( 'load-edit.php',     'jt_post_format_support_filter' );

function jt_post_format_support_filter() {

    $screen = get_current_screen();

    // Bail if not on the projects screen.
    if ( empty( $screen->post_type ) ||  $screen->post_type !== 'portfolio_project' )
        return;

    // Check if the current theme supports formats.
    if ( current_theme_supports( 'post-formats' ) ) {

        $formats = get_theme_support( 'post-formats' );

        // If we have formats, add theme support for only the allowed formats.
        if ( isset( $formats[0] ) ) {
            $new_formats = array_intersect( $formats[0], jt_get_allowed_project_formats() );

            // Remove post formats support.
            remove_theme_support( 'post-formats' );

            // If the theme supports the allowed formats, add support for them.
            if ( $new_formats )
                add_theme_support( 'post-formats', $new_formats );
        }
    }

    // Filter the default post format.
    add_filter( 'option_default_post_format', 'jt_default_post_format_filter', 95 );
}

You might notice a filter on the default post format there at the end of that function. The reason for this is because core WP allows the user to select a default format. We’ll need to overwrite that if it’s not one of the approved formats for our post type.

function jt_default_post_format_filter( $format ) {

    return in_array( $format, jt_get_allowed_project_formats() ) ? $format : 'standard';
}

That’s all there is to it. Now a post type like portfolio projects doesn’t have to support formats like “chat” and “aside” when it doesn’t make sense.