What to create new post using wp_insert_post, but it repeat the post infinitely

For testing I just set the external DB to the current DB. As you can see on your own setup they should all fail the check to be created because they all exist (B -> B).

Obviously on your ( A -> B ) setup you will get many that will pass as long as the slug doesn’t already exist.

I chose post_name over post_title because post_name has to be unique. You could also check against guid.

function wpse_20160318_do_db_sync() {

    // set the DB creds
    $another_db_user   = DB_USER;
    $another_db_pass   = DB_PASSWORD;
    $another_db_name   = DB_NAME;
    $another_db_host   = DB_HOST;
    $another_tb_prefix = 'wp_';
    $post_type="post";

    // setup the DB connection
    $mydb = new wpdb( $another_db_user, $another_db_pass, $another_db_name, $another_db_host );

    $mydb->set_prefix( $another_tb_prefix );

    // query the DB
    $result = $mydb->get_results(
        "
    SELECT ID, post_title, post_name, guid
    FROM $mydb->posts
    WHERE post_status="publish"
        AND post_type="$post_type"
    "
    );

    // for all the results, let's check against the slug.
    foreach ( $result as $r ) {

        // see if we can find it...
        $post = get_page_by_path( $r->post_name, OBJECT, $post_type );

        if ( ! $post ) {
            // We're cool, let's create this one.
            echo PHP_EOL . 'Let\'s make a new post for ' . $r->post_title . PHP_EOL;
        }
        else {
            // No need to duplicate this one
            echo PHP_EOL . 'Post already exists for ' . $post->post_title . PHP_EOL;
        }
    }
}

// using on init to make sure the DB is ready to go
add_action( 'init', 'wpse_20160318_do_db_sync' );

The Flow of data will look like:

Query

$result = $mydb->get_results(
    "
    SELECT {PROPERTY}
    FROM $mydb->posts
    "
);

Loop

foreach ( $result as $r ) {

Create

$data = Array(
    '{PROPERTY}' => $r->{PROPERTY},
    'post_name'  => $r->post_name,
);

wp_insert_post($data);

Working Version

You can use this on your own db if you comment out the testing block. Set $another_post_type to and CPT in your WP and it will generate a page for each $post_type. The meta key will also keep track of the ID used from the DB. Since the search doesn’t specify a publish type, a new page will not be created if a duplicate page is in the trash until the trash is emptied.

function wpse_20160318_do_db_sync() {

    $another_db_user="user";
    $another_db_pass="pass";
    $another_db_name="name";
    $another_db_host="localhost";

// FOR TESTING SAME DB
//
//  $another_db_user = DB_USER;
//  $another_db_pass = DB_PASSWORD;
//  $another_db_name = DB_NAME;
//  $another_db_host = DB_HOST;

    $another_tb_prefix   = 'wp_';
    $another_post_type="bio";
    $another_post_status="publish";

    $mydb = new wpdb( $another_db_user, $another_db_pass, $another_db_name, $another_db_host );
    $mydb->set_prefix( $another_tb_prefix );
    $result = $mydb->get_results(
        "
    SELECT ID, post_title, post_name, guid, post_content, post_excerpt, post_date, post_date_gmt, post_modified, post_modified_gmt
    FROM $mydb->posts
    WHERE post_status="$another_post_status"
        AND post_type="$another_post_type"
    "
    );

    $another_db_post_id_meta_key = 'another_db_post_id';

    $post_type="page";
    $mods      = array (
        'post_status'    => 'publish',
        'post_author'    => '1',
        'comment_status' => 'closed',
        'ping_status'    => 'closed',
        'page_template'  => 'template-profile-info.php',
        'post_parent'    => '115822',
        'post_type'      => $post_type,
    );

    foreach ( $result as $r ) {

        $post_title = wp_strip_all_tags( $r->post_title );

        // see if we can find it by title...
        $post = get_page_by_title( $post_title, OBJECT, $post_type );

        if ( ! $post ) {

            // title wasn't found... but let's check the meta
            $meta_args  = array (
                'post_type'  => array ( $post_type ),
                'meta_query' => array (
                    array (
                        'key'     => $another_db_post_id_meta_key,
                        'compare' => '=',
                        'type'    => 'NUMERIC',
                        'value'   => $r->ID,
                    ),
                ),
            );
            $meta_posts = get_posts( $meta_args );

            // set the post to the first item in the list, if it isn't empty
            if ( ! empty( $meta_posts ) ) {
                list( $post ) = $meta_posts;
            }
        }

        if ( ! $post ) {

            // Can't find the post, let's create this one.

            // Data from another DB
            $clone = array (
                'post_title'        => $post_title,
                'post_content'      => $r->post_content,
                'post_excerpt'      => $r->post_excerpt,
                'post_date'         => $r->post_date,
                'post_date_gmt'     => $r->post_date_gmt,
                'post_modified'     => $r->post_modified,
                'post_modified_gmt' => $r->post_modified_gmt,
            );

            // Merge with our defaults
            $args = array_merge( $clone, $mods );

            // create new post
            $post_id = wp_insert_post( $args );

            if ( $post_id instanceof WP_Error ) {
                // failed to create new post
                // wp_die( 'Failed to create ' . $post_id );
            }
            else {
                // new post created
                $post = get_post( $post_id );

                // add clone tag that we can check later
                add_post_meta( $post->ID, $another_db_post_id_meta_key, $r->ID, false );
            }
        }
        else {
            // no need to dup
        }
    }
}