Converting Posts to Pages

A while ago I added a function to one of my sites to change a set of posts from one type to another. I can’t remember exactly why, but I’ve dug it out and updated it a little, and it is tested and working.


The function

Place this in functions.php so that it can be called from anywhere within your blog.

/**
 * Change the type of a WP_Post object
 *
 * @param required array $posts         An array of post objects to update
 * @param required string $change_to    The post type to change the selected objects to
 * @param string $change_from           The post type to change the selected objects from (ignored if 'false')
 */
function my_change_post_type($posts, $change_to, $change_from = false){

    /** Ensure that an array of objects has been passed */
    if(!is_array($posts))
        return new WP_Error('change_post_type', __('<h4>Function \'my_change_post_type()\'</h4>The $posts array is empty, unable to proceed.'));

    /** Ensure that $change_to is a valid post type */
    if(!post_type_exists($change_to))
        return new WP_Error('change_post_type', __(sprintf('<h4>Function \'my_change_post_type()\'</h4>The value of the <b>$change_to</b> parameter (<b>%1$s</b>) is not a valid post type, unable to proceed.', $change_to)));

    /** Loop through each object in the $posts array... */
    foreach($posts as $key => $post) :

        /** Ensure that this $post is actually a 'WP_Post' object... */
        if(!is_a($post, 'WP_Post')) : // It is not, so unset this $post and continue to the next (no need to update what hasn't changed)
            unset($posts[$key]);
            continue;
        endif;

        /** Check whether or not $change_from has been set... */
        if($change_from) :  // It has

            /** Ensure that $change_from is formatted as an array... */
            if(!array())    // It is not, so make it an array
                $change_from = (array)$change_from;

            /** Check if the post type needs to be changed... */
            if(in_array($post->post_type, $change_from)) :  // It does, so change it
                $post->post_type = $change_to;
            else :
                unset($posts[$key]);    // It does not, so unset this $post (no need to update what hasn't changed)
            endif;

        else :  // It has not, so change the post type
            $post->post_type = $change_to;
        endif;

    endforeach;

    /** Finally, update $posts (if there are any) */
    if(!empty($posts)) :
        wp_update_post($posts);
        return true;
    else:
        return false;
    endif;

}

How to use

To use this function you simply pass it an array of WP_Post objects and the the post type to set them to.

As mentioned in my comment to your question, I’d recommend using the ID of the objects you want to change to first grab only those Posts, like so –

$args = array(
    'post__in'  => array(12,58,79,105)
);
$posts = get_posts($args);
$result = my_change_post_type($posts, 'page');

However, if you don’t care about singling out certain objects and simply want to change all Posts to Pages you can just grab all posts –

$args = array(
    'post_type' => 'post'
);
$posts = get_posts($args);
$result = my_change_post_type($posts, 'page');

You also have to option, if the need ever arrises, to change from multiple post types to a single type (if you decide to deprecate a couple of custom post types and wish to set all objects from them as Posts, for example) –

$posts = get_posts(array());
$result = my_change_post_type($posts, 'page', array('cpt_1', 'cpt_2'));

Error handling

Additionally, if you require, you can check for errors returned by the my_change_post_type() function and stop execution.

if(is_wp_error($result)) :
    wp_die($result);
endif;