Sorting by size
Adding custom column and sorting by post_content length is possible. It won't be very efficient though, I'm afraid.
First you'll have to add your custom column and display the length of content in there. I've assumed that you're interested in trimmed content (so ' ' is still empty).
Then you'll have to make this column sortable and write your custom code to sort posts.
/* Add custom column to post list */
function add_content_size_column( $columns ) {
return array_merge( $columns, array( 'content_size' => __( 'Size', 'your_text_domain' ) ) );
}
add_filter( 'manage_posts_columns' , 'add_content_size_column' );
/* Display custom column */
function display_posts_content_size( $column, $post_id ) {
if ( 'content_size' == $column ) {
echo mb_strlen( trim( get_post_field( 'post_content', $post_id ) ) );
}
}
add_action( 'manage_posts_custom_column' , 'display_posts_content_size', 10, 2 );
/* Set custom column as sortable */
function set_content_size_column_as_sortable( $columns ) {
$columns['content_size'] = 'content_size';
return $columns;
}
add_filter( 'manage_edit-post_sortable_columns', 'set_content_size_column_as_sortable' );
function my_content_size_orderby( $orderby ) {
global $wpdb;
// Run this filter only once, when needed (it will be added by pre_get_posts)
remove_filter( 'posts_orderby', 'my_content_size_orderby' );
$orderby = str_replace( "{$wpdb->posts}.post_date ", "CHAR_LENGTH( TRIM({$wpdb->posts}.post_content) ) ", $orderby );
return $orderby;
}
function my_content_size_modify_orderby( $query ) {
if ( ! is_admin() ) return;
if ( 'content_size' == $query->get( 'orderby' ) ) {
add_filter( 'posts_orderby', 'my_content_size_orderby' );
}
}
add_action( 'pre_get_posts', 'my_content_size_modify_orderby' );
Preventing from beeing published
There is an pretty easy way to prevent the post from getting published. All you have to do is write your own save_post
action. You can check if the post is empty and if so, you can change it status to draft
(or pending
, or whatever you'd like).
The only thing you'll need to remember is that WP will display some message saying that the post was published. You can change that message with redirect_post_location
filter.
function my_save_post( $post_id ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
// Now perform checks to validate your data.
$prevent_publish = ('' == trim( $_POST['content'] )); // Set to true if data was invalid.
if ( $prevent_publish ) {
// Unhook this function to prevent indefinite loop
remove_action( 'save_post', 'my_save_post' );
// Update the post to change post status
wp_update_post( array(
'ID' => $post_id,
'post_status' => 'draft'
) );
// Re-hook this function again
add_action( 'save_post', 'my_save_post' );
}
}
add_action( 'save_post', 'my_save_post' );
function my_redirect_location( $location, $post_id ) {
if ( isset($_POST['publish']) ) {
// Obtain current post status
$status = get_post_status( $post_id );
// The post was 'published', but if it is still a draft, display draft message (10).
if ( 'draft' === $status ) {
$location = add_query_arg( 'message', 10, $location );
}
}
return $location;
}
add_filter( 'redirect_post_location', 'my_redirect_location', 10, 2 );
wp_insert_post_empty_content
filter