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 onacf/initwith 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
| Class | File | Hook | Responsibility |
|---|---|---|---|
CustomPostTypes | core/WP/CustomPostTypes.php | init | Collects CPT configurations and delegates to factory |
CustomTaxonomies | core/WP/CustomTaxonomies.php | init | Collects taxonomy configurations and delegates to factory |
Acf | core/WP/Acf.php | acf/init | Collects ACF options page configurations and delegates to factory |
Factory classes
| Factory | File | Purpose |
|---|---|---|
RegisterCustomPostType | core/Factories/RegisterCustomPostType.php | Generates labels, merges defaults, calls register_post_type() |
RegisterCustomTaxonomy | core/Factories/RegisterCustomTaxonomy.php | Generates labels, merges defaults, calls register_taxonomy() |
RegisterAcfOptionsPage | core/Factories/RegisterAcfOptionsPage.php | Wraps acf_add_options_page() and acf_add_options_sub_page() |
Custom Post Types
File: core/WP/CustomPostTypes.php
Registration workflow
set_properties()runs onafter_setup_themeto set defaultsregister_post_types()runs oninit- Applies
chisel_custom_post_typesfilter to collect CPT configurations - For each CPT, creates
RegisterCustomPostTypefactory instance - 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→truefeeds→truepages→trueep_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 generationplural— Plural name for label generation
Default values:
show_in_rest→true(enables block editor and REST API)public→truehas_archive→truerewrite.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_base, rest_namespace, rest_controller_class, autosave_rest_controller_class, revisions_rest_controller_class, late_route_registration, map_meta_cap, register_meta_box_cb, taxonomies, template, template_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;
}
}PHPCustom Taxonomies
File: core/WP/CustomTaxonomies.php
Registration workflow
set_properties()runs onafter_setup_themeto set defaultsregister_taxonomies()runs oninit- Applies
chisel_custom_taxonomiesfilter to collect configurations - For each taxonomy, creates
RegisterCustomTaxonomyfactory instance - 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→truehierarchical→trueep_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 generationplural— Plural name for label generationpost_types— Array of post types to attach taxonomy to
Default values:
show_in_rest→true(enables REST API)public→truehierarchical→false(settruefor category-like taxonomy)show_admin_column→truerewrite.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_base, rest_namespace, rest_controller_class, meta_box_cb, default_term, sort, args
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;
}
}PHPACF Options Pages
File: core/WP/Acf.php
Registration workflow
options_pages()runs onacf/init- Applies
chisel_acf_options_pagesfilter for top-level pages - Applies
chisel_acf_options_sub_pagesfilter for subpages - For each page, creates
RegisterAcfOptionsPagefactory instance - Factory calls
acf_add_options_page()oracf_add_options_sub_page()
Options page arguments
File: core/Factories/RegisterAcfOptionsPage.php
Required:
page_title— Page titlemenu_slug— Unique slug
Optional with defaults:
menu_title→ Falls back topage_titlecapability→'edit_posts'position→45redirect→trueicon_url→'dashicons-screenoptions'post_id→'options'autoload→falseupdate_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;
}
}PHPRetrieving registered items
Get all registered CPTs:
$cpts = \Chisel\WP\CustomPostTypes::get_post_types();PHPGet all registered taxonomies:
$taxonomies = \Chisel\WP\CustomTaxonomies::get_taxonomies();PHPGet all registered ACF options pages:
$pages = \Chisel\WP\Acf::get_options_pages();
$subpages = \Chisel\WP\Acf::get_options_sub_pages();PHPBest practices
Permalink flush
After adding/modifying CPTs or taxonomies:
- Visit Settings → Permalinks in WordPress admin
- Click Save Changes (no modifications needed)
- This flushes rewrite rules and makes new slugs active