How to Arrange Posts by Size in the WordPress Dashboard?

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 );

Leave a Comment