Skip to content

Instantly share code, notes, and snippets.

@GaryJones
Forked from bradyvercher/cpt-class.mustache
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GaryJones/9262186 to your computer and use it in GitHub Desktop.
Save GaryJones/9262186 to your computer and use it in GitHub Desktop.
/**
* {{singular}} Custom Post Type.
*
* @package {{plural}}
* @author Your Name <email@example.com>
* @license GPL-2.0+
* @link http://www.blazersix.com/wordpress-code-generators/
*
* @todo Remove unused code and update where needed.
*
{{#plugin_headers}}
* @wordpress-plugin
* Plugin Name: {{singular}} CPT
* Plugin URI: http://
* Description: A generated {{singular_lower}} custom post type implementation.
* Version: 1.0.0
* Author: Your Name
* Author URI: http://
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
{{/plugin_headers}}
*/
/**
* Main {{singular_name}} class.
*/
class {{class_name}} {
/**
* Register the {{singular}} custom post type and related admin interface
* elements (custom columns, update messages, meta boxes, standard menu).
*
* @since 1.0.0
*
* @link http://codex.wordpress.org/Function_Reference/register_post_type
*/
public function init() {
$this->register();
if ( is_admin() ) {
add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
{{#verbosify}}
add_filter( 'parse_query', array( $this, 'parse_admin_query' ) );
{{/verbosify}}
add_filter( 'manage_edit-{{post_type}}_columns', array( $this, 'register_columns' ) );
{{#verbosify}}
add_action( 'manage_edit-{{post_type}}_sortable_columns', array( $this, 'register_sortable_columns' ) );
{{/verbosify}}
add_action( 'manage_{{post_type}}_posts_custom_column', array( $this, 'display_columns' ), 10, 2 );
add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
}
{{#verbosify}}
add_filter( 'map_meta_cap', array( $this, 'map_meta_cap' ), 10, 4 );
{{/verbosify}}
}
/**
* Register {{singular}} custom post type.
*
* @since 1.0.0
*
* @link http://codex.wordpress.org/Function_Reference/register_post_type
*/
public function register() {
$labels = array(
'name' => {{#text_domain}}_x( {{/text_domain}}'{{plural}}',{{#text_domain}} 'post type general name', '{{text_domain}}' ),{{/text_domain}}
'singular_name' => {{#text_domain}}_x( {{/text_domain}}'{{singular}}',{{#text_domain}} 'post type singular name', '{{text_domain}}' ),{{/text_domain}}
'menu_name' => {{#text_domain}}_x( {{/text_domain}}'{{plural}}',{{#text_domain}} 'admin menu', '{{text_domain}}' ),{{/text_domain}}
'name_admin_bar' => {{#text_domain}}_x( {{/text_domain}}'{{singular}}',{{#text_domain}} 'add new on admin bar', '{{text_domain}}' ),{{/text_domain}}
'add_new' => {{#text_domain}}_x( {{/text_domain}}'Add New',{{#text_domain}} '{{post_type}}', '{{text_domain}}' ),{{/text_domain}}
'add_new_item' => {{#text_domain}}__( {{/text_domain}}'Add New {{singular}}',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'new_item' => {{#text_domain}}__( {{/text_domain}}'New {{singular}}',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'edit_item' => {{#text_domain}}__( {{/text_domain}}'Edit {{singular}}',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'view_item' => {{#text_domain}}__( {{/text_domain}}'View {{singular}}',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'all_items' => {{#text_domain}}__( {{/text_domain}}'All {{plural}}',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'search_items' => {{#text_domain}}__( {{/text_domain}}'Search {{plural}}',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'parent_item_colon' => {{#text_domain}}__( {{/text_domain}}'Parent {{plural}}:',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'not_found' => {{#text_domain}}__( {{/text_domain}}'No {{plural_lower}} found.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'not_found_in_trash' => {{#text_domain}}__( {{/text_domain}}'No {{plural_lower}} found in Trash.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
);
{{#verbosify}}
$capabilities = array(
// Meta capabilities.
'edit_post' => 'edit_{{post_type}}',
'read_post' => 'read_{{post_type}}',
'delete_post' => 'delete_{{post_type}}',
// Primitive capabilities used throughout core to check permissions.
'edit_posts' => 'edit_{{post_type}}s',
'edit_others_posts' => 'edit_others_{{post_type}}s',
'publish_posts' => 'publish_{{post_type}}s',
'read_private_posts' => 'read_private_{{post_type}}s',
// Primitive capabilites translated from meta capabilities in map_meta_cap().
'read' => 'read',
'delete_posts' => 'delete_{{post_type}}s',
'delete_private_posts' => 'delete_private_{{post_type}}s',
'delete_published_posts' => 'delete_published_{{post_type}}s',
'delete_others_posts' => 'delete_others_{{post_type}}s',
'edit_private_posts' => 'edit_private_{{post_type}}s',
'edit_published_posts' => 'edit_published_{{post_type}}s'
);
{{/verbosify}}
$rewrite = array(
'slug' => '{{post_type}}',
'with_front' => false,
{{#verbosify}}
'feeds' => null,
'pages' => true,
'ep_mask' => EP_PERMALINK,
{{/verbosify}}
);
$supports = array(
'title',
'editor',
'author',
'thumbnail',
'excerpt',
'trackbacks',
'custom-fields',
'comments',
'revisions',
'page-attributes',
'post-formats'
);
$args = array(
{{#verbosify}}
'can_export' => true,
'capability_type' => array( '{{post_type}}', '{{post_type}}s' ),
'capabilities' => $capabilities,
'delete_with_user' => null,
'description' => '',
{{/verbosify}}
'exclude_from_search' => false,
'has_archive' => false,
'hierarchical' => {{#hierarchical}}true{{/hierarchical}}{{^hierarchical}}false{{/hierarchical}},
'labels' => $labels,
{{#verbosify}}
'map_meta_cap' => false,
'menu_icon' => null,
{{/verbosify}}
'menu_position' => 50,
'public' => true,
'publicly_queryable' => true,
'register_meta_box_cb' => array( $this, 'register_meta_boxes' ),
'rewrite' => $rewrite,
{{#verbosify}}
'query_var' => '{{post_type}}',
{{/verbosify}}
'show_ui' => true,
{{#verbosify}}
'show_in_admin_bar' => true,
{{/verbosify}}
'show_in_menu' => true,
'show_in_nav_menus' => false,
'supports' => $supports,
{{#verbosify}}
'taxonomies' => array(),
{{/verbosify}}
);
register_post_type( '{{post_type}}', $args );
}
/**
* {{singular}} update messages.
*
* @since 1.0.0
*
* See /wp-admin/edit-form-advanced.php
*
* @param array $messages Existing post update messages.
*
* @return array Amended post update messages with new CPT update messages.
*/
public function updated_messages( $messages ) {
$post = get_post();
$post_type = get_post_type( $post );
$post_type_object = get_post_type_object( $post_type );
$messages['{{post_type}}'] = array(
0 => '', // Unused. Messages start at index 1.
1 => {{#text_domain}}__( {{/text_domain}}'{{singular}} updated.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
2 => {{#text_domain}}__( {{/text_domain}}'Custom field updated.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
3 => {{#text_domain}}__( {{/text_domain}}'Custom field deleted.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
4 => {{#text_domain}}__( {{/text_domain}}'{{singular}} updated.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
/* translators: %s: date and time of the revision */
5 => isset( $_GET['revision'] ) ? sprintf( {{#text_domain}}__( {{/text_domain}}'{{singular}} restored to revision from %s',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}} wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
6 => {{#text_domain}}__( {{/text_domain}}'{{singular}} published.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
7 => {{#text_domain}}__( {{/text_domain}}'{{singular}} saved.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
8 => {{#text_domain}}__( {{/text_domain}}'{{singular}} submitted.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
9 => sprintf(
{{#text_domain}}__( {{/text_domain}}'{{singular}} scheduled for: <strong>%1$s</strong>.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
/* translators: Publish box date format, see http://php.net/date */
date_i18n( {{#text_domain}}__( {{/text_domain}}'M j, Y @ G:i',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}} strtotime( $post->post_date ) )
),
10 => {{#text_domain}}__( {{/text_domain}}'{{singular}} draft updated.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
);
if ( $post_type_object->publicly_queryable ) {
$permalink = get_permalink( $post->ID );
$preview_permalink = add_query_arg( 'preview', 'true', $permalink );
$view_link = sprintf(
' <a href="%s">%s</a>',
esc_url( $permalink ),
{{#text_domain}}__( {{/text_domain}}'View {{singular_lower}}',{{#text_domain}} '{{text_domain}}' ){{/text_domain}}
);
$preview_link = sprintf(
' <a target="_blank" href="%s">%s</a>',
esc_url( $preview_permalink ),
{{#text_domain}}__( {{/text_domain}}'Preview {{singular_lower}}',{{#text_domain}} '{{text_domain}}' ){{/text_domain}}
);
$messages[ $post_type ][1] .= $view_link;
$messages[ $post_type ][6] .= $view_link;
$messages[ $post_type ][9] .= $view_link;
$messages[ $post_type ][8] .= $preview_link;
$messages[ $post_type ][10] .= $preview_link;
}
return $messages;
}
{{#verbosify}}
/**
* Custom sort the posts on the Manage {{plural}} screen.
*
* @since 1.0.0
*
* @link http://codex.wordpress.org/Class_Reference/WP_Query
*
* @todo Update the sortable key to match the query_var set in the
* register_sortable_columns() method.
* @todo Implement custom sorting rules.
*
* @param WP_Query $wp_query The main WP_Query object passed by reference.
*/
public function parse_admin_query( $wp_query ) {
// Ensure this only affects requests in the admin panel.
if ( ! is_admin() || empty( $_GET['post_type'] ) || '{{post_type}}' != $_GET['post_type'] ) {
return;
}
// An array of custom sortable column query vars.
$sortable_keys = array( '{{prefix}}query-var' );
if ( ! empty( $_GET['orderby'] ) && in_array( $_GET['orderby'], $sortable_keys ) ) {
// Set the order.
$order = ( isset( $_GET['order'] ) && 'desc' === $_GET['order'] ) ? 'desc' : 'asc';
$wp_query->set( 'order', $order );
// Implement custom sorting rules.
if ( '{{prefix}}query-var' === $_GET['orderby'] ) {
// An example to sort results by a custom meta field.
$wp_query->set( 'meta_key', '_{{prefix}}meta_key' );
$wp_query->set( 'orderby', 'meta_value_num' );
}
}
}
{{/verbosify}}
/**
* Register custom {{singular}} columns.
*
* @since 1.0.0
*
* @param array $columns Column names to display.
*
* @return array Amended column names to display.
*/
public function register_columns( $columns ) {
// $columns['{{prefix}}custom_column_id'] = {{#text_domain}}_x( {{/text_domain}}'Column Name'{{#text_domain}}, 'column name', '{{text_domain}}' ){{/text_domain}};
return $columns;
}
{{#verbosify}}
/**
* Register custom {{singular}} sortable columns.
*
* Registering a column as sortable will allow the table header to be
* clicked to sort the {{singular}} posts. The query var assigned in this
* function will be passed in the URL as the value of 'orderby', along
* with whether or not results should be ASC or DESC. A hook should be
* attached to the 'parse_query' filter in order to handle the custom
* sorting rules.
*
* Multiple sortable columns may be registered at the same time.
*
* @since 1.0.0
*
* @param array $columns Column query vars with their corresponding column id as the key.
*
* @return array Amended sortable columns.
*/
public function register_sortable_columns( $columns ) {
$columns['{{prefix}}custom_column_id'] = '{{prefix}}query-var';
return $columns;
}
{{/verbosify}}
/**
* Display custom {{singular}} columns.
*
* @since 1.0.0
*
* @param string $column_id The id of the column to display.
* @param int $post_id Post ID.
*/
public function display_columns( $column_id, $post_id ) {
switch ( $column_id ) {
case '{{prefix}}custom_column_id' :
// Output the custom column content here.
echo 'Value';
break;
}
}
/**
* Save {{singular}} CPT data.
*
* @since 1.0.0
*
* @see wp_insert_post()
*
* @param int $post_id Post ID.
* @param WP_Post $post Post object.
*
* @return null Abort if data should not be saved.
*/
public function save_post( $post_id, $post ) {
$is_autosave = defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE;
$is_revision = wp_is_post_revision( $post_id );
$is_valid_nonce = isset( $_POST['{{prefix}}{{post_type}}_nonce'] ) && wp_verify_nonce( $_POST['{{prefix}}{{post_type}}_nonce'], 'save-{{post_type}}_' . $post_id );
// Bail if the data shouldn't be saved or intention can't be verified.
if ( $is_autosave || $is_revision || ! $is_valid_nonce ) {
return;
}
// @todo Save custom data from $_POST global here.
}
/**
* Register {{singular}} meta boxes.
*
* This is the callback defined in the {{singular}} CPT registration
* function. Meta boxes or any other functionality that should be limited
* to the Add/Edit {{singular}} screen and occurs after 'do_meta_boxes'
* can be registered here.
*
* @since 1.0.0
*
* @param WP_Post $post Post object.
*/
public function register_meta_boxes( $post ) {
// Update these parameters and uncomment to add a meta box.
/*
add_meta_box(
'meta-box-id',
{{#text_domain}}__( {{/text_domain}}'{{singular}} Meta Box',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
array( $this, 'meta_box' ),
'{{post_type}}',
'normal',
'default'
);
*/
}
/**
* Display {{singular}} meta box.
*
* @since 1.0.0
*
* @param WP_Post $post Post object.
* @param array $meta_box Arguments passed when the meta box was registered.
*/
public function meta_box( $post, $meta_box ) {
wp_nonce_field( 'save-{{post_type}}_' . $post->ID, '{{prefix}}{{post_type}}_nonce' );
?>
<p>
<label for="field-id"><?php {{#text_domain}}__( {{/text_domain}}'Field Label:'{{#text_domain}}, '{{text_domain}}' ){{/text_domain}}; ?></label><br>
<input type="text" name="field_name" id="field-id" value="<?php echo esc_attr( $field_value ); ?>" class="regular-text">
</p>
<p>
<label for="field2-id"><?php {{#text_domain}}__( {{/text_domain}}'Field Label:'{{#text_domain}}, '{{text_domain}}' ){{/text_domain}}; ?></label><br>
<textarea name="field2_name" id="field2-id" rows="3" class="widefat"><?php echo esc_textarea( $field2_value ); ?></textarea>
</p>
<?php
}
{{#verbosify}}
/**
* Map {{singular}} meta capabilities to primitive capabilities.
*
* @since 1.0.0
*
* @link http://justintadlock.com/archives/2010/07/10/meta-capabilities-for-custom-post-types
* @see map_meta_cap()
*
* @param array $caps Primitive capabilities determined by core.
* @param string $cap Capability name.
* @param int $user_id User ID.
*
* @return array Actual capabilities for meta capability.
*/
public function map_meta_cap( $caps, $cap, $user_id, $args ) {
$meta_caps = array( 'edit_{{post_type}}', 'read_{{post_type}}', 'delete_{{post_type}}' );
if ( in_array( $cap, $meta_caps ) ) {
$post = get_post( $args[0] );
if ( 'revision' == $post->post_type ) {
$post = get_post( $post->post_parent );
}
$post_type = get_post_type_object( $post->post_type );
$caps = array();
if ( ! $post_type->map_meta_cap ) {
$caps[] = $post_type->cap->$cap;
}
$user_data = get_userdata( $user_id );
$post_author_data = $user_data;
if ( ! empty( $post->post_author ) ) {
$post_author_data = get_userdata( $post->post_author );
}
switch( $cap ) {
case 'edit_{{post_type}}' :
// If the user is the author...
if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) {
// If the post is published...
if ( 'publish' == $post->post_status ) {
$caps[] = $post_type->cap->edit_published_posts;
} elseif ( 'trash' == $post->post_status ) {
if ( 'publish' == get_post_meta( $post->ID, '_wp_trash_meta_status', true ) ) {
$caps[] = $post_type->cap->edit_published_posts;
}
} else {
// If the post is draft...
$caps[] = $post_type->cap->edit_posts;
}
} else {
// The user is trying to edit someone else's post.
$caps[] = $post_type->cap->edit_others_posts;
// The post is published, extra cap required.
if ( 'publish' == $post->post_status ) {
$caps[] = $post_type->cap->edit_published_posts;
} elseif ( 'private' == $post->post_status ) {
$caps[] = $post_type->cap->edit_private_posts;
}
}
break;
case 'read_{{post_type}}' :
$status_obj = get_post_status_object( $post->post_status );
if ( $status_obj->public ) {
$caps[] = $post_type->cap->read;
break;
}
if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) {
$caps[] = $post_type->cap->read;
} elseif ( $status_obj->private ) {
$caps[] = $post_type->cap->read_private_posts;
} else {
$caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
}
break;
case 'delete_{{post_type}}' :
// If the user is the author...
if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) {
// If the post is published...
if ( 'publish' == $post->post_status ) {
$caps[] = $post_type->cap->delete_published_posts;
} elseif ( 'trash' == $post->post_status ) {
if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) ) {
$caps[] = $post_type->cap->delete_published_posts;
}
} else {
// If the post is draft...
$caps[] = $post_type->cap->delete_posts;
}
} else {
// The user is trying to edit someone else's post.
$caps[] = $post_type->cap->delete_others_posts;
// The post is published, extra cap required.
if ( 'publish' == $post->post_status ) {
$caps[] = $post_type->cap->delete_published_posts;
} elseif ( 'private' == $post->post_status ) {
$caps[] = $post_type->cap->delete_private_posts;
}
}
break;
}
}
return $caps;
}
{{/verbosify}}
}
${{prefix}}{{post_type}} = new {{class_name}}();
add_action( 'init', array( ${{prefix}}{{post_type}}, 'init' ) );
/**
* {{singular}} CPT
*
* @package {{plural}}
* @author Your Name <email@example.com>
* @license http://www.gnu.org/licenses/gpl-2.0.html
* @link http://www.blazersix.com/wordpress-code-generators/
*
* @todo Remove unused code and update where needed.
*
{{#plugin_headers}}
* @wordpress-plugin
* Plugin Name: {{singular}} CPT
* Plugin URI:
* Description: A generated {{singular_lower}} custom post type implementation.
* Version: 1.0
* Author:
* Author URI:
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
{{/plugin_headers}}
*/
/**
* Register {{singular}} custom post type.
*
* Registers the {{singular}} custom post type and related admin interface
* elements (custom columns, update messages, meta boxes, standard menu).
*
* @link http://codex.wordpress.org/Function_Reference/register_post_type
*/
function {{prefix}}{{post_type}}_init() {
$labels = array(
'name' => {{#text_domain}}_x( {{/text_domain}}'{{plural}}',{{#text_domain}} 'post type general name', '{{text_domain}}' ),{{/text_domain}}
'singular_name' => {{#text_domain}}_x( {{/text_domain}}'{{singular}}',{{#text_domain}} 'post type singular name', '{{text_domain}}' ),{{/text_domain}}
'menu_name' => {{#text_domain}}_x( {{/text_domain}}'{{plural}}',{{#text_domain}} 'admin menu', '{{text_domain}}' ),{{/text_domain}}
'name_admin_bar' => {{#text_domain}}_x( {{/text_domain}}'{{singular}}',{{#text_domain}} 'add new on admin bar', '{{text_domain}}' ),{{/text_domain}}
'add_new' => {{#text_domain}}_x( {{/text_domain}}'Add New',{{#text_domain}} '{{post_type}}', '{{text_domain}}' ),{{/text_domain}}
'add_new_item' => {{#text_domain}}__( {{/text_domain}}'Add New {{singular}}',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'new_item' => {{#text_domain}}__( {{/text_domain}}'New {{singular}}',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'edit_item' => {{#text_domain}}__( {{/text_domain}}'Edit {{singular}}',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'view_item' => {{#text_domain}}__( {{/text_domain}}'View {{singular}}',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'all_items' => {{#text_domain}}__( {{/text_domain}}'All {{plural}}',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'search_items' => {{#text_domain}}__( {{/text_domain}}'Search {{plural}}',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'parent_item_colon' => {{#text_domain}}__( {{/text_domain}}'Parent {{plural}}:',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'not_found' => {{#text_domain}}__( {{/text_domain}}'No {{plural_lower}} found.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
'not_found_in_trash' => {{#text_domain}}__( {{/text_domain}}'No {{plural_lower}} found in Trash.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
);
{{#verbosify}}
$capabilities = array(
// Meta capabilities.
'edit_post' => 'edit_{{post_type}}',
'read_post' => 'read_{{post_type}}',
'delete_post' => 'delete_{{post_type}}',
// Primitive capabilities used throughout core to check permissions.
'edit_posts' => 'edit_{{post_type}}s',
'edit_others_posts' => 'edit_others_{{post_type}}s',
'publish_posts' => 'publish_{{post_type}}s',
'read_private_posts' => 'read_private_{{post_type}}s',
// Primitive capabilites translated from meta capabilities in map_meta_cap().
'read' => 'read',
'delete_posts' => 'delete_{{post_type}}s',
'delete_private_posts' => 'delete_private_{{post_type}}s',
'delete_published_posts' => 'delete_published_{{post_type}}s',
'delete_others_posts' => 'delete_others_{{post_type}}s',
'edit_private_posts' => 'edit_private_{{post_type}}s',
'edit_published_posts' => 'edit_published_{{post_type}}s'
);
{{/verbosify}}
$args = array(
{{#verbosify}}
'can_export' => true,
'capability_type' => array( '{{post_type}}', '{{post_type}}s' ),
'capabilities' => $capabilities,
'delete_with_user' => null,
'description' => '',
{{/verbosify}}
'exclude_from_search' => false,
'has_archive' => false,
'hierarchical' => {{#hierarchical}}true{{/hierarchical}}{{^hierarchical}}false{{/hierarchical}},
'labels' => $labels,
{{#verbosify}}
'map_meta_cap' => false,
'menu_icon' => null,
{{/verbosify}}
'menu_position' => 50,
'public' => true,
'publicly_queryable' => true,
'register_meta_box_cb' => '{{prefix}}register_{{post_type}}_meta_boxes',
'rewrite' => array(
'slug' => '{{post_type}}',
'with_front' => false,
{{#verbosify}}
'feeds' => null,
'pages' => true,
'ep_mask' => EP_PERMALINK,
{{/verbosify}}
),
{{#verbosify}}
'query_var' => '{{post_type}}',
{{/verbosify}}
'show_ui' => true,
{{#verbosify}}
'show_in_admin_bar' => true,
{{/verbosify}}
'show_in_menu' => true,
'show_in_nav_menus' => false,
'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'trackbacks', 'custom-fields', 'comments', 'revisions', 'page-attributes', 'post-formats' ){{#verbosify}},{{/verbosify}}
{{#verbosify}}
'taxonomies' => array(),
{{/verbosify}}
);
register_post_type( '{{post_type}}', $args );
if ( is_admin() ) {
add_filter( 'post_updated_messages', '{{prefix}}{{post_type}}_updated_messages' );
{{#verbosify}}
add_filter( 'parse_query', '{{prefix}}{{post_type}}_parse_admin_query' );
{{/verbosify}}
add_filter( 'manage_edit-{{post_type}}_columns', '{{prefix}}{{post_type}}_register_columns' );
{{#verbosify}}
add_action( 'manage_edit-{{post_type}}_sortable_columns', '{{prefix}}{{post_type}}_register_sortable_columns' );
{{/verbosify}}
add_action( 'manage_{{post_type}}_posts_custom_column', '{{prefix}}{{post_type}}_display_columns', 10, 2 );
add_action( 'save_post', '{{prefix}}{{post_type}}_save_post', 10, 2 );
}
{{#verbosify}}
add_filter( 'map_meta_cap', '{{prefix}}{{post_type}}_map_meta_cap', 10, 4 );
{{/verbosify}}
}
add_action( 'init', '{{prefix}}{{post_type}}_init' );
/**
* {{singular}} update messages.
*
* @see /wp-admin/edit-form-advanced.php
*
* @param array $messages The array of post update messages.
* @return array An array with new CPT update messages.
*/
function {{prefix}}{{post_type}}_updated_messages( $messages ) {
$post = get_post();
$post_type = get_post_type( $post );
$post_type_object = get_post_type_object( $post_type );
$messages['{{post_type}}'] = array(
0 => '', // Unused. Messages start at index 1.
1 => {{#text_domain}}__( {{/text_domain}}'{{singular}} updated.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
2 => {{#text_domain}}__( {{/text_domain}}'Custom field updated.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
3 => {{#text_domain}}__( {{/text_domain}}'Custom field deleted.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
4 => {{#text_domain}}__( {{/text_domain}}'{{singular}} updated.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
/* translators: %s: date and time of the revision */
5 => isset( $_GET['revision'] ) ? sprintf( {{#text_domain}}__( {{/text_domain}}'{{singular}} restored to revision from %s',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}} wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
6 => {{#text_domain}}__( {{/text_domain}}'{{singular}} published.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
7 => {{#text_domain}}__( {{/text_domain}}'{{singular}} saved.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
8 => {{#text_domain}}__( {{/text_domain}}'{{singular}} submitted.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
9 => sprintf( {{#text_domain}}__( {{/text_domain}}'{{singular}} scheduled for: <strong>%1$s</strong>.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
// translators: Publish box date format, see http://php.net/date
date_i18n( {{#text_domain}}__( {{/text_domain}}'M j, Y @ G:i',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}} strtotime( $post->post_date ) ) ),
10 => {{#text_domain}}__( {{/text_domain}}'{{singular}} draft updated.',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}}
);
if ( $post_type_object->publicly_queryable ) {
$permalink = get_permalink( $post->ID );
$preview_permalink = add_query_arg( 'preview', 'true', $permalink );
$view_link = sprintf( ' <a href="%s">%s</a>', esc_url( $permalink ), {{#text_domain}}__( {{/text_domain}}'View {{singular_lower}}',{{#text_domain}} '{{text_domain}}' ){{/text_domain}} );
$preview_link = sprintf( ' <a target="_blank" href="%s">%s</a>', esc_url( $preview_permalink ), {{#text_domain}}__( {{/text_domain}}'Preview {{singular_lower}}',{{#text_domain}} '{{text_domain}}' ){{/text_domain}} );
$messages[ $post_type ][1] .= $view_link;
$messages[ $post_type ][6] .= $view_link;
$messages[ $post_type ][9] .= $view_link;
$messages[ $post_type ][8] .= $preview_link;
$messages[ $post_type ][10] .= $preview_link;
}
return $messages;
}
{{#verbosify}}
/**
* Custom sort the posts on the Manage {{plural}} screen.
*
* @link http://codex.wordpress.org/Class_Reference/WP_Query
*
* @todo Update the sortable key to match the query_var set in the
* register_sortable_columns() method.
* @todo Implement the custom sorting rules.
*
* @param WP_Query $wp_query The main WP_Query object passed by reference.
*/
function {{prefix}}{{post_type}}_parse_admin_query( $wp_query ) {
// Ensure this only affects requests in the admin panel.
if ( ! is_admin() || empty( $_GET['post_type'] ) || '{{post_type}}' != $_GET['post_type'] ) {
return;
}
// An array of custom sortable column query vars.
$sortable_keys = array( '{{prefix}}query-var' );
if ( ! empty( $_GET['orderby'] ) && in_array( $_GET['orderby'], $sortable_keys ) ) {
// Set the order.
$order = ( isset( $_GET['order'] ) && 'desc' == $_GET['order'] ) ? 'desc' : 'asc';
$wp_query->set( 'order', $order );
// Implement custom sorting rules.
if ( '{{prefix}}query-var' == $_GET['orderby'] ) {
// An example to sort results by a custom meta field.
$wp_query->set( 'meta_key', '_{{prefix}}meta_key' );
$wp_query->set( 'orderby', 'meta_value_num' );
}
}
}
{{/verbosify}}
/**
* Register custom {{singular}} columns.
*
* @param array $columns Column names to display.
*/
function {{prefix}}{{post_type}}_register_columns( $columns ) {
// $columns['{{prefix}}custom_column_id'] = {{#text_domain}}_x( {{/text_domain}}'Column Name'{{#text_domain}}, 'column name', '{{text_domain}}' ){{/text_domain}};
return $columns;
}
{{#verbosify}}
/**
* Register custom {{singular}} sortable columns.
*
* Registering a column as sortable will allow the table header to be clicked
* to sort the {{singular}} posts. The query var assigned in this function
* will be passed in the URL as the value of 'orderby', along with whether or
* not results should be ASC or DESC. A hook should be attached to the
* 'parse_query' filter in order to handle the custom sorting rules.
*
* Multiple sortable columns can be registered at the same time.
*
* @todo Update the column identifier key and query var.
*
* @param array $columns Column query vars with their corresponding column id as the key.
*/
function {{prefix}}{{post_type}}_register_sortable_columns( $columns ) {
$columns['{{prefix}}custom_column_id'] = '{{prefix}}query-var';
return $columns;
}
{{/verbosify}}
/**
* Display custom {{singular}} columns.
*
* @param string $column_id The id of the column to display.
* @param int $post_id Post ID.
*/
function {{prefix}}{{post_type}}_display_columns( $column_id, $post_id ) {
switch ( $column_id ) {
case '{{prefix}}custom_column_id' :
// Output the custom column content here.
echo 'Value';
break;
}
}
/**
* Save {{singular}} CPT data.
*
* @see wp_insert_post()
*
* @param int $post_id Post ID.
* @param WP_Post $post Post object.
*/
function {{prefix}}{{post_type}}_save_post( $post_id, $post ) {
$is_autosave = defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE );
$is_revision = wp_is_post_revision( $post_id );
$is_valid_nonce = isset( $_POST['{{prefix}}{{post_type}}_nonce'] ) && wp_verify_nonce( $_POST['{{prefix}}{{post_type}}_nonce'], 'save-{{post_type}}_' . $post_id );
// Bail if the data shouldn't be saved or intention can't be verified.
if ( $is_autosave || $is_revision || ! $is_valid_nonce ) {
return;
}
// @todo Save custom data from $_POST global here.
}
/**
* Register {{singular}} meta boxes.
*
* This is the callback defined in the {{singular}} CPT registration function.
* Meta boxes or any other functionality that should be limited to the
* Add/Edit {{singular}} screen and occurs after 'do_meta_boxes' can be
* registered here.
*
* @param WP_Post $post Post object.
*/
function {{prefix}}register_{{post_type}}_meta_boxes( $post ) {
// Update these parameters and uncomment to add a meta box
// add_meta_box( 'meta-box-id', {{#text_domain}}__( {{/text_domain}}'{{singular}} Meta Box',{{#text_domain}} '{{text_domain}}' ),{{/text_domain}} '{{prefix}}{{post_type}}_meta_box', '{{post_type}}', 'normal', 'default' );
}
/**
* Display {{singular}} meta box.
*
* @param WP_Post $post Post object.
* @param array $meta_box Arguments passed when the meta box was registered.
*/
function {{prefix}}{{post_type}}_meta_box( $post, $meta_box ) {
wp_nonce_field( 'save-{{post_type}}_' . $post->ID, '{{prefix}}{{post_type}}_nonce' );
?>
<p>
<label for="field-id">Field Label:</label><br>
<input type="text" name="field_name" id="field-id" value="<?php echo esc_attr( $field_value ); ?>" class="regular-text">
</p>
<p>
<label for="field2-id">Field Label:</label><br>
<textarea name="field2_name" id="field2-id" rows="3" class="widefat"><?php echo esc_textarea( $field2_value ); ?></textarea>
</p>
<?php
}
{{#verbosify}}
/**
* Map {{singular}} meta capabilities to primitive capabilities.
*
* @link http://justintadlock.com/archives/2010/07/10/meta-capabilities-for-custom-post-types
* @see map_meta_cap()
*
* @param array $caps Primitive capabilities determined by core.
* @param string $cap Capability name.
* @param int $user_id User ID.
* @return array Actual capabilities for meta capability.
*/
function {{prefix}}{{post_type}}_map_meta_cap( $caps, $cap, $user_id, $args ) {
$meta_caps = array( 'edit_{{post_type}}', 'read_{{post_type}}', 'delete_{{post_type}}' );
if ( in_array( $cap, $meta_caps ) ) {
$post = get_post( $args[0] );
if ( 'revision' == $post->post_type ) {
$post = get_post( $post->post_parent );
}
$post_type = get_post_type_object( $post->post_type );
$caps = array();
if ( ! $post_type->map_meta_cap ) {
$caps[] = $post_type->cap->$cap;
}
$user_data = get_userdata( $user_id );
$post_author_data = $user_data;
if ( ! empty( $post->post_author ) ) {
$post_author_data = get_userdata( $post->post_author );
}
switch( $cap ) {
case 'edit_{{post_type}}' :
// If the user is the author...
if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) {
// If the post is published...
if ( 'publish' == $post->post_status ) {
$caps[] = $post_type->cap->edit_published_posts;
} elseif ( 'trash' == $post->post_status ) {
if ( 'publish' == get_post_meta( $post->ID, '_wp_trash_meta_status', true ) ) {
$caps[] = $post_type->cap->edit_published_posts;
}
} else {
// If the post is draft...
$caps[] = $post_type->cap->edit_posts;
}
} else {
// The user is trying to edit someone else's post.
$caps[] = $post_type->cap->edit_others_posts;
// The post is published, extra cap required.
if ( 'publish' == $post->post_status ) {
$caps[] = $post_type->cap->edit_published_posts;
} elseif ( 'private' == $post->post_status ) {
$caps[] = $post_type->cap->edit_private_posts;
}
}
break;
case 'read_{{post_type}}' :
$status_obj = get_post_status_object( $post->post_status );
if ( $status_obj->public ) {
$caps[] = $post_type->cap->read;
break;
}
if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) {
$caps[] = $post_type->cap->read;
} elseif ( $status_obj->private ) {
$caps[] = $post_type->cap->read_private_posts;
} else {
$caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
}
break;
case 'delete_{{post_type}}' :
// If the user is the author...
if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) {
// If the post is published...
if ( 'publish' == $post->post_status ) {
$caps[] = $post_type->cap->delete_published_posts;
} elseif ( 'trash' == $post->post_status ) {
if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) ) {
$caps[] = $post_type->cap->delete_published_posts;
}
} else {
// If the post is draft...
$caps[] = $post_type->cap->delete_posts;
}
} else {
// The user is trying to edit someone else's post.
$caps[] = $post_type->cap->delete_others_posts;
// The post is published, extra cap required.
if ( 'publish' == $post->post_status ) {
$caps[] = $post_type->cap->delete_published_posts;
} elseif ( 'private' == $post->post_status ) {
$caps[] = $post_type->cap->delete_private_posts;
}
}
break;
}
}
return $caps;
}
{{/verbosify}}
<?php
$args = array(
'prefix' => '',
'taxonomy' => '',
'post_type' => '',
'singular' => '',
'plural' => '',
'text_domain' => '',
'hierarchical' => true,
'verbosify' => true,
'classy' => true,
'plugin_headers' => false,
);
$args['prefix'] = ( empty( $args['prefix'] ) ) ? '' : rtrim( $args['prefix'], '_' ) . '_';
$args['text_domain'] = ( empty( $args['text_domain'] ) ) ? false : $args['text_domain'];
$args['singular_lower'] = strtolower( $args['singular'] );
$args['plural_lower'] = strtolower( $args['plural'] );
$args['class_name'] = ucwords( $args['prefix'] ) . preg_replace( '|\s+|', '_', ucwords( $args['singular'] ) );
require_once( 'Mustache/Autoloader.php' );
Mustache_Autoloader::register();
$template = file_get_contents( 'cpt.txt' );
$m = new Mustache_Engine;
echo $m->render( $template, $args );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment