why when I try to insert an image attachment along with a post does wp_get_attachment_url give me a very wrong file path?

I am using a new blog on WPMS (3.0.1, updating is not an option) to aggregate posts (and their featured image) from a few blogs on the same install, and I have to do it programmatically rather than through a pre-made plugin due to firewall restrictions. I’ve tried several ways of doing it, and feel like this method is most promising. Here’s what I’ve cooked up:

switch_to_blog(oldblognumber);
$zargs  = array( 'numberposts' => 1, 'category_name' => 'featured');
$zlastpost = get_posts( $zargs );
foreach($zlastpost as $post) : setup_postdata($post);
    $extrapost = array();
    $extrapost['post_title'] = get_the_title();
    $extrapost['post_content'] = get_the_content();
    $extrapost['comment_status'] = 'closed';
    $extrapost['post_status'] = 'publish';
    $extrapost['post_date'] = get_the_date( $d = 'Y-m-d H:i:s');
    $extrapost['post_category'] = array(80);
    $upload_dir = wp_upload_dir();
    $oldid = get_the_ID();
    $image_url = wp_get_attachment_url(get_post_thumbnail_id($oldid));
    $image_data = file_get_contents($image_url);
    $filename = basename($image_url);
    switch_to_blog(newblognumber);          
        $file = $upload_dir['path'] . "https://wordpress.stackexchange.com/" . $filename; //removed the conditional cuz it was giving me trouble
        file_put_contents($file, $image_data);
        $post_id = wp_insert_post($extrapost);
        $wp_filetype = wp_check_filetype($filename, null );
        $attachment = array(
            'post_mime_type' => $wp_filetype['type'],
            'post_title' => sanitize_file_name($filename),
            'post_content' => '',
            'post_status' => 'inherit',
        );                  
        $attach_id = wp_insert_attachment( $attachment, $file, $post_id );
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        $attach_data = wp_generate_attachment_metadata( $attach_id, $file );
        wp_update_attachment_metadata( $attach_id, $attach_data );
        set_post_thumbnail( $post_id, $attach_id );                       
    restore_current_blog();
    wp_reset_postdata();
endforeach;
restore_current_blog();

The post insertion works just fine, and it pulls the image alright, but somewhere in there things are getting muddled and it spits out an absurd attachment url:
http://myblogs.com/newblog/wp-content/blogs.dir/newblognumber/files//internet/http/wp-content/blogs.dir/oldblognumber/files/year/month/filename.jpg.

Likewise, in the loop where I ask for the_post_thumbnail, I get a broken image whose src is http://myblogs.com/newblog/files//internet/http/wp-content/blogs.dir/oldblognumber/files/year/month/filename-200×100.jpg

For what it’s worth, since I’m using a pre set_post_thumbnail version of WP, I just manually define the function in my newblog’s functions.php:

function set_post_thumbnail( $post, $thumbnail_id ) {
$post = get_post( $post );
$thumbnail_id = absint( $thumbnail_id );
if ( $post && $thumbnail_id && get_post( $thumbnail_id ) ) {
   $thumbnail_html = wp_get_attachment_image( $thumbnail_id, 'thumbnail' );
   if ( ! empty( $thumbnail_html ) ) {
       update_post_meta( $post->ID, '_thumbnail_id', $thumbnail_id );
       return true;
   }
}
return false;
}

I’ve tried fudging GUIDs and using regular expressions to force urls into submission among other things, but all to no avail. Please let me know if you have any guidance for me!


I have also tried an alternate method of setting the post thumbnail of an inserted post, but this simply calls the original file in the oldblog’s upload directory, which will not suffice, as I’d like to generate new image sizes for the newblog’s Media Library, and I’d prefer to not go through and add them to each of the original oldblogs. Here’s that attempt:

switch_to_blog(oldblognumber);
$zargs  = array( 'numberposts' => 1, 'category_name' => 'featured');
$zlastpost = get_posts( $zargs );
foreach($zlastpost as $post) : setup_postdata($post);
    $extrapost = array();
    $extrapost['post_title'] = get_the_title();
    $extrapost['post_content'] = get_the_content();
    $extrapost['comment_status'] = 'closed';
    $extrapost['post_status'] = 'publish';
    $extrapost['post_date'] = get_the_date( $d = 'Y-m-d H:i:s');
    $extrapost['post_category'] = array(80);
    $oldid = get_the_ID();
    $thumbo = get_the_post_thumbnail($oldid);
    $filename = wp_get_attachment_url( get_post_thumbnail_id($post->ID) );
    switch_to_blog(68);
        $post_id = wp_insert_post($extrapost);
        $wp_filetype = wp_check_filetype(basename($filename), null );
            $wp_upload_dir = wp_upload_dir();
            $attachment = array(
                'guid' => _wp_relative_upload_path( $filename ), 
                'post_mime_type' => $wp_filetype['type'],
                'post_title' => preg_replace('/\.[^.]+$/', '', basename($filename)),
                'post_content' => '',
                'post_status' => 'inherit'
            );
            $attach_id = wp_insert_attachment( $attachment, false, $post_id );
            require_once(ABSPATH . 'wp-admin/includes/image.php');
            $attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
            update_post_meta( $post->ID, '_thumbnail_id', $attachment_id );
            wp_update_attachment_metadata( $attach_id, $attach_data );
            set_post_thumbnail( $post_id, $attach_id);        
        restore_current_blog();
        wp_reset_postdata();
    endforeach;
restore_current_blog();     

I’ve tried feeding a number of things to wp_insert_attachment’s $filename parameter, but that doesn’t seem to be my answer.

1 Answer
1

It turns out I was barking up the wrong (or at least a slightly different) tree by using wp_insert_attachment. media_sideload_image managed to pull attachments from other blogs on the same multisite install, copy them to the aggregating blog’s uploads directory, and generate thumbnails, while wp_insert_attachment was doing what it was supposed to, which just happened to not be what I wanted. I realize that this is just a slight variation on other fairly well explained uses of similar functionality, but I figured I’d post my solution here in case anyone happens to have more success applying this particular combination of solutions.

I still get the sense that I’m not doing this in the most efficient way, but it’s working for now:

function switch_and_insert($srcblog, $targetcat, $fromcat) {
  switch_to_blog($srcblog);
  $args  = array( 'numberposts' => 1, 'category_name' => $fromcat);
  $flastpost = get_posts( $args );
  foreach($flastpost as $post) : setup_postdata($post);
    $extrapost = array();
    $extrapost['post_title'] = get_the_title($post);
    $extrapost['post_content'] = get_the_post_thumbnail();
    $extrapost['comment_status'] = 'closed';
    $extrapost['post_status'] = 'publish';
    $extrapost['post_date'] = get_the_date( $d = 'Y-m-d H:i:s');
    $extrapost['post_category'] = array($targetcat);
    $oldid = get_the_ID();
    if ( has_post_thumbnail($oldid)) {
        $filename = wp_get_attachment_url( get_post_thumbnail_id($post->ID) );
    }
    else $filename = $forchomper; // URL of backup image
    switch_to_blog($aggregator_blog_id);
        $post_id = wp_insert_post($extrapost);
        $wp_filetype = wp_check_filetype(basename($filename), null );
        $wp_upload_dir = wp_upload_dir();
        $attachment = array(
            'guid' => _wp_relative_upload_path( $filename ), 
            'post_mime_type' => $wp_filetype['type'],
            'post_title' => preg_replace('/\.[^.]+$/', '', basename($filename)),
            'post_content' => '',
            'post_status' => 'inherit'
        );
        require_once(ABSPATH . "wp-admin" . '/includes/media.php');
        require_once(ABSPATH . "wp-admin" . '/includes/image.php');
        require_once(ABSPATH . "wp-admin" . '/includes/file.php');
        $sideloaded = media_sideload_image($filename, $post_id);
        $attachments = get_children($post_id);
        foreach ( $attachments as $attachment_id => $attachment );
        set_post_thumbnail($post_id, $attachment_id);
    restore_current_blog();
    wp_reset_postdata();
  endforeach;
  restore_current_blog();
}

It might not be noteworthy, but nevertheless I will mention that using this method provided a very convenient opportunity to apply a placeholder image as a post thumbnail/featured image in the event that the originating post didn’t have one, which is a different solution than the more widely suggested one that relies on a conditional within a theme used to display a placeholder, which doesn’t actually assign it as a post’s thumbnail. I realize that most of the time that is the better solution, but in my case these posts must have their own attached featured images, even if they are duplicates.

Here are a couple of the things that helped:
https://wordpress.stackexchange.com/a/19847/14351
http://old.nabble.com/Uploading-image-attachments-from-the-front-end-td26307647.html

Leave a Comment