Jump to Navigation Jump to Main Content Jump to Footer
Home » Docs » Features » Automated Custom Post Type and ACF Options Pages registration

Automated Custom Post Type and ACF Options Pages registration

Chisel automatically registers Custom Post Types, Taxonomies, and ACF Options Pages based on simple array configurations. Define your content structure via PHP filters, and Chisel handles label generation, default arguments, REST API exposure, and admin integration— no boilerplate or repetitive registration calls.

CPTs and taxonomies default to block editor support, REST API access, and sensible rewrite rules. Labels are auto-generated from singular/plural names, with full override support for edge cases. ACF options pages and subpages register on acf/init with parent-child relationships handled automatically.

The architecture separates concerns: core classes (CustomPostTypes, CustomTaxonomies, Acf) collect configurations via filters, while factory classes (RegisterCustomPostType, RegisterCustomTaxonomy, RegisterAcfOptionsPage) handle WordPress API calls and argument merging. Extend via filters in custom/ to avoid modifying core files.

Overview

Core classes

ClassFileHookResponsibility
CustomPostTypescore/WP/CustomPostTypes.phpinitCollects CPT configurations and delegates to factory
CustomTaxonomiescore/WP/CustomTaxonomies.phpinitCollects taxonomy configurations and delegates to factory
Acfcore/WP/Acf.phpacf/initCollects ACF options page configurations and delegates to factory

Factory classes

FactoryFilePurpose
RegisterCustomPostTypecore/Factories/RegisterCustomPostType.phpGenerates labels, merges defaults, calls register_post_type()
RegisterCustomTaxonomycore/Factories/RegisterCustomTaxonomy.phpGenerates labels, merges defaults, calls register_taxonomy()
RegisterAcfOptionsPagecore/Factories/RegisterAcfOptionsPage.phpWraps acf_add_options_page() and acf_add_options_sub_page()

Custom Post Types

File: core/WP/CustomPostTypes.php

Registration workflow

  1. set_properties() runs on after_setup_theme to set defaults
  2. register_post_types() runs on init
  3. Applies chisel_custom_post_types filter to collect CPT configurations
  4. For each CPT, creates RegisterCustomPostType factory instance
  5. Factory generates labels, merges arguments, and calls register_post_type()

Default arguments

Set in: CustomPostTypes::set_properties()

Supports:

  • Filter: chisel_default_post_type_supports
  • Default: array('title', 'page-attributes', 'revisions', 'author')

Rewrite args:

  • Filter: chisel_default_post_type_rewrite_args
  • Default:
    • slug → '' (defaults to post type name)
    • with_front → true
    • feeds → true
    • pages → true
    • ep_mask → EP_PERMALINK

Per-CPT default overrides:

  • chisel_default_post_type_supports_{post_type}
  • chisel_default_post_type_rewrite_args_{post_type}

CPT registration details

File: core/Factories/RegisterCustomPostType.php

Required fields:

  • singular — Singular name for label generation
  • plural — Plural name for label generation

Default values:

  • show_in_rest → true (enables block editor and REST API)
  • public → true
  • has_archive → true
  • rewrite.slug → Post type name (if not provided)
  • menu_icon → 'dashicons-admin-post'
  • capability_type → 'post'
  • can_export → true

Label generation:

Auto-generates complete label set from singular and plural :

  • add_new_item → “Add New {Singular}”
  • edit_item → “Edit {Singular}”
  • all_items → “All {Plural}”
  • search_items → “Search {Plural}”
  • Plus 20+ more labels

Override any label via labels array in configuration .

Supported optional arguments:

rest_baserest_namespacerest_controller_classautosave_rest_controller_classrevisions_rest_controller_classlate_route_registrationmap_meta_capregister_meta_box_cbtaxonomiestemplatetemplate_lock

Thumbnail support:

If supports array contains 'thumbnail', CPT is automatically added to chisel_post_thumbnails_post_types filter .

Adding a Custom Post Type

Via custom class (recommened)

File: custom/app/WP/CustomPostTypes.php

<?php
namespace Chisel\WP\Custom;

use Chisel\Traits\HooksSingleton;

class CustomPostTypes {
    use HooksSingleton;

    public function action_hooks(): void {}

    public function filter_hooks(): void {
        add_filter( 'chisel_custom_post_types', array( $this, 'register_custom_post_types' ) );
        add_filter( 'chisel_custom_taxonomies', array( $this, 'register_custom_taxonomies' ) );
    }

    public function register_custom_post_types( array $post_types ): array {
        $post_types['book'] = array(
            'singular'  => __('Book', 'chisel'),
            'plural'    => __('Books', 'chisel'),
            'supports'  => array('editor', 'thumbnail', 'excerpt'),
            'menu_icon' => 'dashicons-book',
            'rewrite'   => array('slug' => 'library'),
        );
        
        return $post_types;
    }

    public function register_custom_taxonomies( array $taxonomies ): array {
        // Add taxonomies here
        return $taxonomies;
    }
}
PHP

Custom Taxonomies

File: core/WP/CustomTaxonomies.php

Registration workflow

  1. set_properties() runs on after_setup_theme to set defaults
  2. register_taxonomies() runs on init
  3. Applies chisel_custom_taxonomies filter to collect configurations
  4. For each taxonomy, creates RegisterCustomTaxonomy factory instance
  5. Factory generates labels, merges arguments, and calls register_taxonomy()

Default arguments

Set in: CustomTaxonomies::set_properties()

Capabilities:

  • Filter: chisel_default_taxonomy_capabilities
  • Default:
    • manage_terms → 'manage_categories'
    • edit_terms → 'manage_categories'
    • delete_terms → 'manage_categories'
    • assign_terms → 'edit_posts'

Rewrite args:

  • Filter: chisel_default_taxonomy_rewrite_args
  • Default:
    • slug → '' (defaults to taxonomy name)
    • with_front → true
    • hierarchical → true
    • ep_mask → EP_NONE

Per-taxonomy default overrides:

  • chisel_default_taxonomy_capabilities_{taxonomy}
  • chisel_default_taxonomy_rewrite_args_{taxonomy}

Taxonomy registration details

File: core/Factories/RegisterCustomTaxonomy.php

Required fields:

  • singular — Singular name for label generation
  • plural — Plural name for label generation
  • post_types — Array of post types to attach taxonomy to

Default values:

  • show_in_rest → true (enables REST API)
  • public → true
  • hierarchical → false (set true for category-like taxonomy)
  • show_admin_column → true
  • rewrite.slug → Taxonomy name (if not provided)
  • rest_base → Taxonomy name

Label generation:

Auto-generates complete label set from singular and plural :

  • search_items → “Search {Plural}”
  • add_new_item → “Add New {Singular}”
  • parent_item → “Parent {Singular}”
  • Plus 15+ more labels

Override any label via labels array in configuration .

Supported optional arguments:

rest_baserest_namespacerest_controller_classmeta_box_cbdefault_termsortargs

Adding a Custom Taxonomy

Via custom class (recommened)

File: custom/app/WP/CustomPostTypes.php

<?php
namespace Chisel\WP\Custom;

use Chisel\Traits\HooksSingleton;

class CustomPostTypes {
    use HooksSingleton;

    public function action_hooks(): void {}

    public function filter_hooks(): void {
        add_filter( 'chisel_custom_post_types', array( $this, 'register_custom_post_types' ) );
        add_filter( 'chisel_custom_taxonomies', array( $this, 'register_custom_taxonomies' ) );
    }

    public function register_custom_post_types( array $post_types ): array {
        // Add custom post types here
        
        return $post_types;
    }

    public function register_custom_taxonomies( array $taxonomies ): array {
        $taxonomies['genre'] = array(
          'singular'    => __('Genre', 'chisel'),
          'plural'      => __('Genres', 'chisel'),
          'post_types'  => array('book'),
          'public'      => true,
          'hierarchical' => true,
          'rewrite'     => array('slug' => 'genres'),
          'show_in_rest' => true,
        );
        
        return $taxonomies;
    }
}
PHP

ACF Options Pages

File: core/WP/Acf.php

Registration workflow

  1. options_pages() runs on acf/init
  2. Applies chisel_acf_options_pages filter for top-level pages
  3. Applies chisel_acf_options_sub_pages filter for subpages
  4. For each page, creates RegisterAcfOptionsPage factory instance
  5. Factory calls acf_add_options_page() or acf_add_options_sub_page()

Options page arguments

File: core/Factories/RegisterAcfOptionsPage.php

Required:

  • page_title — Page title
  • menu_slug — Unique slug

Optional with defaults:

  • menu_title → Falls back to page_title
  • capability → 'edit_posts'
  • position → 45
  • redirect → true
  • icon_url → 'dashicons-screenoptions'
  • post_id → 'options'
  • autoload → false
  • update_button → __('Update', 'chisel')
  • updated_message → __('Options Updated', 'chisel')
  • parent_slug → Required for subpages

Adding ACF Options Pages

Via custom class (recommened)

File: custom/app/WP/Acf.php

<?php
namespace Chisel\WP\Custom;

use Chisel\Traits\HooksSingleton;

class Acf {
    use HooksSingleton;

    public function action_hooks(): void {}

    public function filter_hooks(): void {
        add_filter( 'chisel_acf_options_pages', array( $this, 'register_acf_options_pages' ) );
        add_filter( 'chisel_acf_options_sub_pages', array( $this, 'register_acf_options_sub_pages' ) );
    }

    public function register_acf_options_pages( array $options_pages ): array {
        $options_pages[] = array(
            'menu_slug'  => 'theme-settings',
            'page_title' => __('Theme Settings', 'chisel'),
            'icon_url'   => 'dashicons-admin-generic',
            'position'   => 45,
        );
        
        return $options_pages;
    }

    public function register_acf_options_sub_pages( array $options_sub_pages ): array {
        $options_sub_pages[] = array(
            'menu_slug'   => 'theme-header',
            'page_title'  => __('Header', 'chisel'),
            'menu_title'  => __('Header', 'chisel'),
            'parent_slug' => 'theme-settings',
        );
        
        return $options_sub_pages;
    }
}
PHP

Retrieving registered items

Get all registered CPTs:

$cpts = \Chisel\WP\CustomPostTypes::get_post_types();
PHP

Get all registered taxonomies:

$taxonomies = \Chisel\WP\CustomTaxonomies::get_taxonomies();
PHP

Get all registered ACF options pages:

$pages = \Chisel\WP\Acf::get_options_pages();
$subpages = \Chisel\WP\Acf::get_options_sub_pages();
PHP

Best practices

Permalink flush

After adding/modifying CPTs or taxonomies:

  1. Visit Settings → Permalinks in WordPress admin
  2. Click Save Changes (no modifications needed)
  3. This flushes rewrite rules and makes new slugs active

Do you like Chisel?

Give it a star on GitHub!