One of the best custom post type plugins has to be Easy Content Types by Pippin Williamson (@pippinspages). This previously mentioned plugin, Easy Content Types provides an extremely easy-to-use, familiar (very WordPress-like) and intuitive interface for creating custom post types, taxonomies, and meta boxes. It makes creating custom categories, custom tags, and custom input fields so easy and simple. The stepwise process of creating the custom post type is extremely logical.
- Create the Custom Post Type (register custom post type)
- Create the Custom Taxonomies (register taxonomy)
- Create the Metabox
- Create the Metabox fields
Just like Custom Post Types UI exported CPT registration information, just recently announced, Pippin's newest edition now exports metabox php! Thus, this becomes the best custom post type plugin available! Now child theme designers can easily create custom post types in their sandbox, copy and paste the code in their functions.php file or an associate cpt.php file (or whatever) and have an excellently created custom post type to continue working to design!
So to demonstrate the exported php code, I went into the plugin, created a post type called wps_books, a custom taxonomy called wps_genre, and added a meta box with a few fields. Then I copied and pasted the code in my functions.php file, deactivated the plugin and the code works!
The Easy Content Types plugin is a premium plugin, available on CodeCanyon for $20. I know that most of us WordPress junkies are not keen on paying for premium plugins, but using this plugin can make coding easy and make it easy to learn how to do custom post types on your own.
However, for those who are just cheap and want a free plugin (like I do most of the time!): check out the giveaway of the plugin we’re running at the bottom of the post!
Here's the exported registration code:
[php]
// registration code for wps_books post type
function register_wps_books_posttype() {
$labels = array(
'name' => _x( 'Books', 'post type general name' ),
'singular_name' => _x( 'Book', 'post type singular name' ),
'add_new' => _x( 'Add New', 'Book'),
'add_new_item' => __( 'Add New Book '),
'edit_item' => __( 'Edit Book '),
'new_item' => __( 'New Book '),
'view_item' => __( 'View Book '),
'search_items' => __( 'Search Books '),
'not_found' => __( 'No Book found' ),
'not_found_in_trash'=> __( 'No Books found in Trash' ),
'parent_item_colon' => ''
);
$supports = array('title','editor','author','thumbnail','excerpt','custom-fields','comments');
$post_type_args = array(
'labels' => $labels,
'singular_label' => __('Book'),
'public' => true,
'show_ui' => true,
'publicly_queryable'=> true,
'query_var' => true,
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'rewrite' => array('slug' => 'books'),
'supports' => $supports,
'menu_position' => 5,
'menu_icon' => 'http://localhost:8888/www/sandbox/wp-content/uploads/2011/09/Book-icon16.png'
);
register_post_type('wps_books',$post_type_args);
}
add_action('init', 'register_wps_books_posttype');
[/php]
Then I created a custom taxonomy called wps_genre, and here is the exported registration code:
[php]
// registration code for wps_genre taxonomy
function register_wps_genre_tax() {
$labels = array(
'name' => _x( 'Genre', 'taxonomy general name' ),
'singular_name' => _x( 'Genre', 'taxonomy singular name' ),
'add_new' => _x( 'Add New Genre', 'Genre'),
'add_new_item' => __( 'Add New Genre' ),
'edit_item' => __( 'Edit Genre' ),
'new_item' => __( 'New Genre' ),
'view_item' => __( 'View Genre' ),
'search_items' => __( 'Search Genre' ),
'not_found' => __( 'No Genre found' ),
'not_found_in_trash' => __( 'No Genre found in Trash' ),
);
$pages = array('wps_books');
$args = array(
'labels' => $labels,
'singular_label' => __('Genre'),
'public' => true,
'show_ui' => true,
'hierarchical' => false,
'show_tagcloud' => false,
'show_in_nav_menus' => true,
'rewrite' => array('slug' => 'genre'),
);
register_taxonomy('wps_genre', $pages, $args);
}
add_action('init', 'register_wps_genre_tax');
[/php]
Then I created a meta box area called "Book Information" with 3 fields: Pages, ISBN, and Publish Date, and here is the exported metabox code:
[php]
$bookinformation_metabox = array(
'id' => 'bookinformation',
'title' => 'Book Information',
'page' => 'wps_books',
'context' => 'normal',
'priority' => 'high',
'fields' => $bookinformation_fields = array(
array(
'name' => 'Pages',
'desc' => 'Enter the number of pages',
'id' => 'ecpt_pages',
'class' => 'ecpt_pages',
'type' => 'text',
'rich_editor' => 0,
'max' => 0
),
array(
'name' => 'ISBN',
'desc' => 'ISBN',
'id' => 'ecpt_isbn',
'class' => 'ecpt_isbn',
'type' => 'text',
'rich_editor' => 0,
'max' => 0
),
array(
'name' => 'Publish Date',
'desc' => '',
'id' => 'ecpt_publishdate',
'class' => 'ecpt_publishdate',
'type' => 'date',
'rich_editor' => 0,
'max' => 0
),
)
);
add_action('admin_menu', 'ecpt_add_bookinformation_meta_box');
function ecpt_add_bookinformation_meta_box() {
global $bookinformation_metabox;
add_meta_box($bookinformation_metabox['id'], $bookinformation_metabox['title'], 'ecpt_show_bookinformation_box', 'wps_books', 'normal', 'high', $bookinformation_metabox);
}
// function to show meta boxes
function ecpt_show_bookinformation_box() {
global $post;
global $bookinformation_metabox;
global $ecpt_prefix;
// Use nonce for verification
echo '<input type="hidden" name="ecpt_bookinformation_meta_box_nonce" value="', wp_create_nonce(basename(__FILE__)), '" />';
echo '<table class="form-table">';
foreach ($bookinformation_metabox['fields'] as $field) {
// get current post meta data
$meta = get_post_meta($post->ID, $field['id'], true);
echo '<tr>',
'<th style="width:20%"><label for="', $field['id'], '">', $field['name'], '</label></th>',
'<td>';
switch ($field['type']) {
case 'text':
echo '<input type="text" name="', $field['id'], '" id="', $field['id'], '" value="', $meta ? $meta : $field['std'], '" size="30" style="width:97%" /><br/>', '', $field['desc'];
break;
case 'date':
echo '<input type="text" class="ecpt_datepicker" name="', $field['id'], '" id="', $field['id'], '" value="', $meta ? $meta : $field['std'], '" size="30" style="width:97%" />', '', $field['desc'];
break;
case 'upload':
echo '<input type="text" class="ecpt_upload_field" name="', $field['id'], '" id="', $field['id'], '" value="', $meta ? $meta : $field['std'], '" size="30" style="width:80%" /><input class="upload_image_button" type="button" value="Upload Image" /><br/>', '', $field['desc'];
break;
case 'textarea':
if($field['rich_editor'] == 1) {
// this is the old method of enabling the RTE. Now it only needs the class name.
//wp_tiny_mce(true, array('editor_selector' => $field['class'], 'remove_linebreaks' => false) );
echo '<div style="width: 97%; border: 1px solid #DFDFDF;"><textarea name="', $field['id'], '" class="theEditor ', $field['class'], '" id="', $field['id'], '" cols="60" rows="8" style="width:97%">', $meta ? $meta : $field['std'], '</textarea></div>', '', $field['desc'];
} else {
echo '<div style="width: 100%;"><textarea name="', $field['id'], '" class="', $field['class'], '" id="', $field['id'], '" cols="60" rows="8" style="width:97%">', $meta ? $meta : $field['std'], '</textarea></div>', '', $field['desc'];
}
break;
case 'select':
echo '<select name="', $field['id'], '" id="', $field['id'], '">';
foreach ($field['options'] as $option) {
echo '<option value="' . $option . '"', $meta == $option ? ' selected="selected"' : '', '>', $option, '</option>';
}
echo '</select>', '', $field['desc'];
break;
case 'radio':
foreach ($field['options'] as $option) {
echo '<input type="radio" name="', $field['id'], '" value="', $option, '"', $meta == $option ? ' checked="checked"' : '', ' /> ', $option;
}
echo '<br/>' . $field['desc'];
break;
case 'checkbox':
echo '<input type="checkbox" name="', $field['id'], '" id="', $field['id'], '"', $meta ? ' checked="checked"' : '', ' /> ';
echo $field['desc'];
break;
case 'slider':
echo '<input type="text" rel="' . $field['max'] . '" name="' . $field['id'] . '" id="' . $field['id'] . '" value="' . $meta . '" size="1" style="float: left; margin-right: 5px" />';
echo '<div class="ecpt-slider" rel="' . $field['id'] . '" style="float: left; width: 60%; margin: 5px 0 0 0;"></div>';
echo '<div style="width: 100%; clear: both;">' . $field['desc'] . '</div>';
break;
}
echo '<td>',
'</tr>';
}
echo '</table>';
}
add_action('save_post', 'ecpt_bookinformation_save');
// Save data from meta box
function ecpt_bookinformation_save($post_id) {
global $post;
global $bookinformation_metabox;
// verify nonce
if (!wp_verify_nonce($_POST['ecpt_bookinformation_meta_box_nonce'], basename(__FILE__))) {
return $post_id;
}
// check autosave
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return $post_id;
}
// check permissions
if ('page' == $_POST['post_type']) {
if (!current_user_can('edit_page', $post_id)) {
return $post_id;
}
} elseif (!current_user_can('edit_post', $post_id)) {
return $post_id;
}
foreach ($bookinformation_metabox['fields'] as $field) {
$old = get_post_meta($post_id, $field['id'], true);
$new = $_POST[$field['id']];
if ($new && $new != $old) {
update_post_meta($post_id, $field['id'], $new);
} elseif ('' == $new && $old) {
delete_post_meta($post_id, $field['id'], $old);
}
}
}
function ecpt_export_ui_scripts() {
global $ecpt_options;
?>
<script type="text/javascript">
jQuery(document).ready(function()
{
if(jQuery('.form-table .ecpt_upload_field').length > 0 ) {
// Media Uploader
window.formfield = '';
jQuery('.upload_image_button').live('click', function() {
window.formfield = jQuery('.ecpt_upload_field',jQuery(this).parent());
tb_show('', 'media-upload.php?type=file&TB_iframe=true');
return false;
});
window.original_send_to_editor = window.send_to_editor;
window.send_to_editor = function(html) {
if (window.formfield) {
imgurl = jQuery('a','<div>'+html+'</div>').attr('href');
window.formfield.val(imgurl);
tb_remove();
}
else {
window.original_send_to_editor(html);
}
window.formfield = '';
window.imagefield = false;
}
}
if(jQuery('.form-table .ecpt-slider').length > 0 ) {
jQuery('.ecpt-slider').each(function(){
var $this = jQuery(this);
var id = $this.attr('rel');
var val = jQuery('#' + id).val();
var max = jQuery('#' + id).attr('rel');
max = parseInt(max);
//var step = $('#' + id).closest('input').attr('rel');
$this.slider({
value: val,
max: max,
step: 1,
slide: function(event, ui) {
jQuery('#' + id).val(ui.value);
}
});
});
}
if(jQuery('.form-table .ecpt_datepicker').length > 0 ) {
var dateFormat = 'mm-dd-yy';
jQuery('.ecpt_datepicker').datepicker({dateFormat: dateFormat});
}
});
</script>
<?php
}
function ecpt_export_datepicker_ui_scripts() {
global $ecpt_base_dir;
wp_enqueue_script('jquery-ui.min', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js', false, '1.8', 'all');
}
function ecpt_export_datepicker_ui_styles() {
global $ecpt_base_dir;
wp_enqueue_style('jquery-ui-css', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css', false, '1.8', 'all');
}
// these are for newest versions of WP
add_action('admin_print_scripts-post.php', 'ecpt_export_datepicker_ui_scripts');
add_action('admin_print_scripts-edit.php', 'ecpt_export_datepicker_ui_scripts');
add_action('admin_print_scripts-post-new.php', 'ecpt_export_datepicker_ui_scripts');
add_action('admin_print_styles-post.php', 'ecpt_export_datepicker_ui_styles');
add_action('admin_print_styles-edit.php', 'ecpt_export_datepicker_ui_styles');
add_action('admin_print_styles-post-new.php', 'ecpt_export_datepicker_ui_styles');
if ((isset($_GET['post']) && (isset($_GET['action']) && $_GET['action'] == 'edit') ) || (strstr($_SERVER['REQUEST_URI'], 'wp-admin/post-new.php')))
{
add_action('admin_head', 'ecpt_export_ui_scripts');
}
[/php]
Awesome! Simply awesome! Pippin told me he was trying to do this and I am very, very excited that he has accomplished this!
If you haven't seen the introduction video, please check it out here:
If you haven't seen the basic how to video, please check it out here:
Development Perspective Mini-Review
From a development perspective, Easy Content Types is a solid plugin, with a strong and active developer! However, overuse of the exported php code will lead to some redundant code for someone who doesn't know much coding. Also, with frameworks, like Genesis, there are some difficulties that the plugin must overcome to be fully integrated with the particular framework. However, after talking with Pippin, he made some updates to the export code (reducing some of the potential redundancy) and single/archives post type templating in light of frameworks, which can be expected in the next release in the next few days.
In light of the upcoming meta box class that is being targeted for WordPress 3.3, it will drastically reduce the export code. However, there will be a quick and seemless update when the metabox_class is announced in beta RCs.
Plugin Giveaway
CLOSED.
I have one copy to give away. To enter, do the following:
- Tweet on Twitter: "Free Giveaway by @wp_smith: Easy Content Types Plugin for WordPress by @pippinspages http://wp.me/pSgPV-1f0"
- Share the link on Google Plus
- If you don't have a Twitter account or a Google+ account, share the link on Facebook
- Then enter a comment below with the appropriate links answering the question, "Why should you get a copy of Easy Content Types by Pippin Williamson?"
One commenter will be chosen randomly on Friday to win. Only one comment per person will be counted.