Custom Post Types

Here’s an example of a custom post type for an “Example” CPT:

<?php

class CPT_Example
{
    /**
     * CPT_NAME is the custom post type name. Also used to generate the CPT Label using `ucfirst()`.
     * 
     * @var string
     */
    const CPT_NAME = 'example';

    const TAX_NAME_TYPE = 'example-type';

    const NONCE_NAME = 'example_meta_box';

    public $fields = [
        'example_name',
        'example_company',
    ];

    /**
     * Set all the required hooks to register the Staff custom post type and all other required components/features
     * 
     * @return void
     */
    public function init()
    {
        // All the init operations we need to do in one call
        add_action('init', [$this, 'register']);

        // Remove the "Archive: " prefix (eg: "Archive: Staff Directory")
        add_filter('get_the_archive_title_prefix', [$this, 'remove_archive_prefix'], 10, 1);

        // Add a custom metabox for the example post type
        add_action('add_meta_boxes', [$this, 'add_meta_boxes']);
    }

    /**
     * Method to choreograph the registration of the custom post type and all of its required components
     * 
     * @return void
     */
    public function register()
    {
        $this->register_taxonomies();
        $this->register_post_type();

        add_action('save_post_' . self::CPT_NAME, [$this, 'save_example_meta']);
    }

    /**
     * Registers the Staff custom post type
     * 
     * @return void
     */
    public function register_post_type()
    {
        $uc_label = ucwords(str_replace('-', ' ', self::CPT_NAME));
        $uc_plural = $uc_label . 's';

        register_post_type(
            self::CPT_NAME,
            [
                'labels' => [
                    'name'                => $uc_plural,
                    'singular_name'       => $uc_label,
                    'menu_name'           => $uc_label,
                    'parent_item_colon'   => 'Parent ' . $uc_label,
                    'all_items'           => 'All ' . $uc_plural,
                    'view_item'           => 'View ' . $uc_label,
                    'add_new_item'        => 'Add New ' . $uc_label,
                    'add_new'             => 'Add New',
                    'edit_item'           => 'Edit ' . $uc_label,
                    'update_item'         => 'Update ' . $uc_label,
                    'search_items'        => 'Search ' . $uc_plural,
                    'not_found'           => 'Not Found',
                    'not_found_in_trash'  => 'Not found in Trash',
                ],
                'taxonomies'    => [ self::TAX_NAME_TYPE, /* Add more taxonomies here */ ],
                'show_ui'       => true,
                'public'        => true,
                'has_archive'   => true,
                'rewrite'       => [
                    'slug'          => self::CPT_NAME . 's',
                    'with_front'    => false, // removes the /blog/ prefix in the url
                    'feeds'         => false,
                    'pages'         => true,
                    'ep_mask'       => EP_PAGES
                ],
                'menu_icon'     => 'dashicons-businessman',
                'supports'      => ['title', 'editor', 'thumbnail'],
                'show_in_rest'  => true,
                'rest_base'     => self::CPT_NAME
            ]
        );
    }

    public function register_taxonomies()
    {
        register_taxonomy(
            self::TAX_NAME_TYPE,
            self::CPT_NAME,
            [
                'labels' => [
                    'name'              => 'Example Types',
                    'singular_name'     => 'Example Type',
                    'search_items'      => 'Search Example Types',
                    'all_items'         => 'All Example Types',
                    'parent_item'       => 'Parent Example Type',
                    'parent_item_colon' => 'Parent Example Type:',
                    'edit_item'         => 'Edit Example Type',
                    'update_item'       => 'Update Example Type',
                    'add_new_item'      => 'Add New Example Type',
                    'new_item_name'     => 'New Example Type Name',
                    'menu_name'         => 'Example Types',
                ],
                'show_ui'           => true,
                'show_admin_column' => true,
                'hierarchical'      => true,
                'show_in_rest'      => true,
                'rest_base'         => self::TAX_NAME_TYPE . 's'
            ]
        );
    }

    /**
     * Remove the "Archives:" prefix from the archive title for the post type
     * 
     * @param string $prefix    The current prefix as given by the filter
     * @return string           The modified prefix
     */ 
    public function remove_archive_prefix($prefix)
    {
        return is_post_type_archive(self::CPT_NAME)
            || is_tax(self::TAX_NAME_TYPE)
                ? ''
                : $prefix;
    }

    public function add_meta_boxes()
    {
        add_meta_box(
            'example_posting_meta_box',
            'Example Details',
            [$this, 'render_example_meta_box'],
            self::CPT_NAME,
            'normal',
            'high'
        );
    }

    public function render_example_meta_box($post)
    {
        // Get existing meta values ('post' here means the object type comes from the posts table)
        $meta = get_metadata( 'post', $post->ID, '', true );
        foreach ( $this->fields as $field ) {
            $$field = $meta[$field][0] ?? '';
        }

        // Add the hidden nonce field
        wp_nonce_field( self::NONCE_NAME, self::NONCE_NAME . '_nonce');

        include_once EXAMPLE_TEMPLATEDIR . 'metabox.php';
    }

    public function save_example_meta($post_id) 
    {
        // Add nonce check, autosave check, and capability check here
        $nonce = $_POST[self::NONCE_NAME . '_nonce'] ?? false;
        if ( !$nonce || !wp_verify_nonce($nonce, self::NONCE_NAME) ) {
            return $post_id;
        }

        foreach ( $this->fields as $field ) {
            if (isset($_POST[$field])) {
                update_post_meta($post_id, $field, $_POST[$field]);
            }
        }
    }
}

Comments

Leave a Reply

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