You're working on a new project with WordPress. You enjoy yourself. You're confident in your abilities but then all of a sudden you realize you need a bunch of custom post types and the user is not allowed to edit the title to one of them but you need to find a way to auto-increment the title because that was a client request.

So, you pull up the functions file, scratch your head and copy / paste the bellow snippet and hope for the best.

// Use a filter to make the change
add_filter( 'wp_insert_post_data' , 'modify_post_title' , '99', 2 );  
function modify_post_title( $data , $postarr ) {

    // Check for the custom post type and it's status
    // We only need to modify it when it's going to be published
    $posts_status = ['publish', 'future', 'pending', 'private', 'trash'];
    if( $data['post_type'] == 'penguins' && !in_array($data['post_status'], $posts_status)) {

        // Count the number of posts to check if the current post is the first one
        $count_posts = wp_count_posts('penguins');
        $published_posts = $count_posts->publish;

        // Check if it's the first one
        if ($published_posts == 0) {

            // Save the title and the slug
            $data['post_title'] = date('Y-m') . '-1';
            $data['post_name'] = sanitize_title($data['post_title']);

        } else {

            // Get the most recent post
            $args = array(
                'numberposts' => 1,
                'orderby' => 'post_date',
                'order' => 'DESC',
                'post_type' => 'penguins',
                'post_status' => 'publish'
            $last_post = wp_get_recent_posts($args);
            // Get the title
            $last_post_title = $last_post['0']['post_title'];
            // Get the title and get the number from it.
            // We increment from that number
            $number = explode('-', $last_post_title);
            $number = intval($number[2]) + 1;

            // Save the title and the slug
            $data['post_title'] = date('Y-m') . '-' . $number;
            $data['post_name'] = sanitize_title($data['post_title']);

    return $data;

But what does this code do? Let us begin from the top, shall we?

We start from the premise that the user is not allowed to edit the custom post type title entitled penguins.

To be able to identify the post we'll need to add a title manually, after the post is published. We can do that using the, very useful, filter wp_insert_post_data. This will enable us to grab the data that is send to the database and alter it.

After we grab the post data we need to check the state that the post is in. Because we don't want to modify the title if the state is altered in any way. We just create a simple array of all the post statuses and check the current post status with that array. We also want to make sure we're modifying the correct post type, so we check for that as well.

If the test passed then we need to count the number of posts and see if the current one is the first one for this custom post type. We do this using the wp_count_posts function and then grabbing only the published ones.

If there are no published posts then we save the post_title with the current date (Y-m) and the number 1.

Now this next step is where the magic happens. If we do have posts then we need to get the most recent one using the wp_get_recent_posts functions. After that, we get the title for that post and since the title is partitioned using the - character (you can use any character you want) we just need to explode it (the title that is) and increment the number it results to form the new title and save that as the new post title. We also apply the same thing to the post slug, represented here by post_name.


And that folks is how you auto increment a custom post type title, until next time, code long and prosper!