Custom Post Types, Taxonomies & Metaboxes
Xe Plugin comes with structured classes for registering Custom Post Types (CPTs), Custom Taxonomies, and Custom Metaboxes with built-in rewrite flushing and security verification.
1. Custom Post Types (src/PostTypes.php)
CPTs are registered via src/PostTypes.php:
namespace Xe_Plugin;
class PostTypes {
public function register(): void {
add_action( 'init', [ $this, 'register_post_types' ] );
register_activation_hook( _xe_plugin()->file(), [ $this, 'rewrite_flush' ] );
}
public function register_post_types() {
$this->sample();
}
protected function sample() {
$labels = [
'name' => esc_html__( 'Samples', 'xe-plugin' ),
'singular_name' => esc_html__( 'Sample', 'xe-plugin' ),
'add_new' => esc_html__( 'Add New', 'xe-plugin' ),
'edit_item' => esc_html__( 'Edit Sample', 'xe-plugin' ),
'all_items' => esc_html__( 'All Samples', 'xe-plugin' ),
];
$args = [
'labels' => $labels,
'public' => true,
'show_ui' => true,
'show_in_menu' => false, // Can be embedded under Plugin Menu
'menu_icon' => 'dashicons-portfolio',
'query_var' => true,
'rewrite' => [ 'slug' => 'xe-plugin-cpt' ],
'capability_type' => 'post',
'has_archive' => true,
'supports' => [ 'title', 'editor', 'thumbnail', 'comments', 'revisions' ],
];
return register_post_type( 'xe-plugin-cpt', $args );
}
public function rewrite_flush() {
$this->register_post_types();
flush_rewrite_rules();
}
}
2. Custom Taxonomies (src/Taxonomies.php)
Taxonomies are registered on init (priority 0) in src/Taxonomies.php:
namespace Xe_Plugin;
class Taxonomies {
public function register(): void {
add_action( 'init', [ $this, 'register_taxonomies' ], 0 );
}
public function register_taxonomies(): void {
// Hierarchical category
register_taxonomy( 'xe-plugin-cat', [ 'xe-plugin-cpt' ], $this->sample_categories() );
// Flat tag
register_taxonomy( 'xe-plugin-tag', [ 'xe-plugin-cpt' ], $this->sample_tags() );
}
}
3. Custom Metaboxes (src/Admin/Metaboxes/)
Metaboxes are organized as individual classes. See src/Admin/Metaboxes/Sample.php:
namespace Xe_Plugin\Admin\MetaBoxes;
use Xe_Plugin\Utils;
class Sample {
public function register(): void {
add_action( 'add_meta_boxes', [ $this, 'add' ] );
add_action( 'save_post_' . $this->post_type(), [ $this, 'save' ] );
}
protected function post_type(): string {
return 'xe-plugin-cpt';
}
public function add(): void {
add_meta_box(
'sample_meta_box',
esc_html__( 'Sample Details', 'xe-plugin' ),
[ $this, 'render' ],
$this->post_type()
);
}
public function render( $post ): void {
wp_nonce_field( 'xep_cpt_meta_box', 'xep_cpt_meta_box_nonce' );
$sample = get_post_meta( $post->ID, '_sample', true );
?>
<div class="xe-plugin-field">
<label for="sample"><?php echo esc_html__( 'Serial No:', 'xe-plugin' ); ?></label>
<input type="text" name="sample" id="sample" value="<?php echo esc_attr( $sample ); ?>" required>
</div>
<?php
}
public function save( int $post_id ) {
// 1. Verify nonce, capability, and autosave
$is_valid = Utils::verify_save(
'xep_cpt_meta_box',
'xep_cpt_meta_box_nonce',
$this->post_type(),
$post_id
);
if ( ! $is_valid ) {
return $post_id;
}
// 2. Sanitize and save post meta
Utils::update_field( $post_id, 'sample', false, 'text', '_sample' );
}
}