I saw this post came to life again and wanted to give it another try. Here is my status on this problem. Found two solutions, not heavy tested, and not pretty, but seems to be working.
In wp-includes/post.php line 2450 change:
if ( ('' == $post_content) && ('' == $post_title) && ('' == $post_excerpt) && ('attachment' != $post_type) ) {
to somting like
if ( ('' == $post_content) && ('' == $post_title) && ('' == $post_excerpt) && ('post' == $post_type or 'page' == $post_type) ) {
seems to solve the problem for custom post types. The wrong message is still being produced for normal posts or pages without title/content/excerpt, so its not a complete fix.
This code can fix it for your custom post type without editing wordpress itself. The idea is that if wordpress don't want to do things without a post title, then lets do it ourself, or give wordpress a temporary title to work with. The temporary title will make the 'if test' over validate to false, and continue the script. We can then remove the title again later. Please suggest improvements if you see any.
add_filter('title_save_pre', 'check_title'); //if no post title set it to notitle
function check_title($post_title) {
if ($_POST['post_type'] == 'my_post_type' and !$post_title){
$post_title = 'notitle'; //set this to what you want the post name/url to be ?
}
return $post_title;
}
add_action( 'save_post', 'no_custom_post_type_title' ); //if post title = 'notitle' set it to ''
function no_custom_post_type_title ( $post_id ) {
$post_type = get_post_type( $post_id );
if ( $post_type == 'my_post_type') {
$post_title = get_the_title($post_id);
if ( $post_title == 'notitle') {
global $wpdb;
global $post;
$post_name = $post->post_name;
if (strlen(stristr($post_name,$post_title))>0) { //generate a post_name
$post_name = sanitize_title($post_type.'-'.$post_id);
}
$post_title = '';
$where = array( 'ID' => $post_id );
$wpdb->update( $wpdb->posts, array( 'post_title' => $post_title, 'post_name' => $post_name), $where ); //can set post name/url here based on other meta data?
}
}
}
add_action ( 'trash_post', 'do_trash_post' ); // Set status to trash when post is trashed
function do_trash_post($post_id) {
if ( get_post_type( $post_id ) == 'my_post_type' and !get_the_title($post_id)) {
global $wpdb;
$post_status = 'trash';
$where = array( 'ID' => $post_id );
$wpdb->update( $wpdb->posts, array( 'post_status' => $post_status), $where );
}
}
add_action ( 'untrash_post', 'do_untrash_post' ); // Set status to whatever it was before it was in the trash
function do_untrash_post($post_id) {
if ( get_post_type( $post_id ) == 'my_post_type' and !get_the_title($post_id)) {
global $wpdb;
$post_status = get_post_meta($post_id, '_wp_trash_meta_status', true);
$where = array( 'ID' => $post_id );
$wpdb->update( $wpdb->posts, array( 'post_status' => $post_status), $where );
}
}
This code can be improved for sure but works for me so far.
I think its a good idea to to have a post_title even if you don't need a title field. This can be done with an inut with the name set to post_title:
<input type="text" name="post_title" value="<?php echo get_the_title(); ?>"/>
You can label it however you want, and wordpress takes care of saving it even with no support for title on that post type. Can even use a hidden post_title input and generated a post_title based on other form values with jquery, or generate it in a hook ofc.