Support

Account

Home Forums General Issues Copy Image / Media Uploads to Another Page

Solving

Copy Image / Media Uploads to Another Page

  • Hello,

    I’ve done some research on this and I’m not sure I’m finding a solution or working answer.

    In my case, I’m trying to copy pages from a main site, blogID 1 to a child site, another blogID, however, this question can be related to copying the image / media uploads to another page on the same site (a non-multisite WordPress install).

    I’ve had luck with every other field (except the media uploads) copying just fine with this – including repeaters.

    $meta = get_post_meta($post->ID);
    
    $post->ID = ''; // empty id field, to tell WordPress that this will be a new post
    
    $inserted_post_id = wp_insert_post($post);
    
    foreach($meta as $key => $value) {
        update_post_meta($inserted_post_id, $key, $value[0]);
    }

    I’m using Flexible Content fields, I’m not sure if that matters, to have “widgets” with their own ACF settings onto a page. Some of the ACF definitions have an image upload at the top level and some have them nested within a repeater. I cannot figure out how to:

    1) Copy the media item (in all of my cases so far they are images, but they could be any media) to the new post
    2) Use that media item / new upload related to the new post in the ACF values

    In my case, I don’t care if the media item is uploaded to the new site in my multisite installation, I could just use the main site media asset, but I don’t know if you HAVE to duplicate the media item or not to get it to work correctly.

    Any help with this would be great! Thanks in advance!

  • The problem with image fields is that they store the Post ID of the image in the media library and the image does not exist in the other site and if the ID value does exist it is already used for another post. The first thing you need to do is to insert the image into the media library, get the new ID and then swap the ID from the site you’re copying from with the new ID for the site that you’re copying to.

    You’ll have the same problem with any field type that stores ID values for other WP objects including relationship fields, post object fields, taxonomy fields, etc.

    flex fields and repeaters will make a difference because you’ll need to know how ACF stores values in the DB in order to find the fields that need to be replaced with new ID values. Flex fields and repeaters are stored in a similar fashion.

    A repeater or flex field will have meta keys like
    "{$repeater_name}_{$index}_{$sub_field_name}"
    a nested repeater field will look like
    "{$repeater_name}_{$index}_{$sub_field_name}_{$index}_{$sub_field_name}"

  • Thanks. I think I know what you mean. I played around for a few hours yesterday and I think I’m close, but not quite.

    This is what I have so far – I pass in the post to be copied to the new site and the target blog ID. It should work the same to copy the post on the same site if you were to remove the switch_to_blog() lines.

    public function copy_post_to_blog($post, $target_blog_id) {
                var_dump('copy_post_to_blog');
                $source_blog_id = 1;
    
                switch_to_blog($source_blog_id); // Enforce that we're still on blog ID 1
                $meta = get_post_meta($post->ID);
                $post_custom = get_post_custom($post->ID);
    
                $save_post = $post;
    
                $post->ID = ''; // empty id field, to tell wordpress that this will be a new post
                switch_to_blog($target_blog_id); // switch to target blog
                $inserted_post_id = wp_insert_post($post); // insert the post
    
                $attached_images = array();
    
                foreach($meta as $key => $value) {
    
                    $attach_id = NULL;
    
                    if( strpos($key, 'sections_') === 0 ) {
    
                        switch_to_blog($source_blog_id);
    
                        $new_file_url = $main_site_url . '/wp-content/uploads/' . $post_media_attachment['file'];
    
                        $post_media_attachment = wp_get_attachment_metadata($value[0]);
           
                        switch_to_blog($target_blog_id);
    
                        $main_site_url = get_site_url( get_current_blog_id() );
                        $current_site_url = get_site_url( get_current_blog_id() );
    
                        $img_url = $main_site_url . '/wp-content/uploads/' . $post_media_attachment['file'];
    
                        $info       = pathinfo($img_url);
                        $file_name  = basename($img_url,'.' . $info['extension']);
    
                         // Get the upload directory for the current site
                        $upload_dir = wp_upload_dir();
                        // Make the path to the desired path to the new file we are about to create
                        if( wp_mkdir_p( $upload_dir['path'] ) ) {
    
                            $file = $upload_dir['path'] . '/' . $file_name .'.'. $info['extension'];
    
                        } else {
    
                            $file = $upload_dir['basedir'] . '/' . $file_name .'.'. $info['extension'];
    
                        }
                        
    
                         $image_data = file_get_contents( $main_site_url . '/wp-content/uploads/' . $post_media_attachment['file'] );
    
                        // Add the file contents to the new path with the new filename
                        file_put_contents( $file, $image_data );
    
                        $attachment = array(
                            'post_mime_type' => 'image/jpeg',
                            'post_title'     => sanitize_file_name( $file_name ),
                            'post_content'   => '',
                            'post_status'    => 'inherit',
                            'post_excerpt'   => '',
                            'post_name'      => sanitize_file_name( $file_name ),
                            'guid'           => $file
                        );
    
                        // Attach the new file and its information to the database
                        $attach_id = wp_insert_attachment( $attachment, $file, $inserted_post_id );
    
                        // Include code to process functions below:
                        require_once(ABSPATH . 'wp-admin/includes/image.php');
    
                        // Define attachment metadata
                        $attach_data = wp_generate_attachment_metadata( $attach_id, $file );
    
                        wp_update_attachment_metadata( $attach_id, $attach_data );
    
                    }
    
                    $new_value = ( isset($attach_id) ) ? $attach_id : $value[0];
    
                    update_post_meta($inserted_post_id, $key, $new_value);
                }

    I feel like I’m switching blogs too much, maybe that’s an issue…and the $new_value field, what I’m trying to do is if it’s one of my “sections_” ACF fields, save the image value where applicable or just the value itself to the new post.

    What I don’t like about it, besides it not working, is it’s not dynamic – what if there are other ACF fields later…if they aren’t starting with the name “sections_” it won’t get picked up. I don’t really know enough of what’s going on to make this better.

    Do you happen to have any working code or can you help with what I’ve got started?

  • To be honest, I don’t know why your code is not working. Copying images from one blog to another is not something I have any experience with.

    And the difficulty with updating acf values to point to new images, when you’re dealing with unknowns like repeaters and flex fields, well, I don’t thing that there’s any real way to do this dynamically, especially by using get_post_meta() to get the values.

    The best way that I can thing of would be to work through ACF using the ACF function to get values and use get_field_object() https://www.advancedcustomfields.com/resources/get_field_object/, then do whatever you need to do with the images to transfer them. After getting all the values this way and moving the images you can then use update_field to update the values of the post where you’re copying to. https://www.advancedcustomfields.com/resources/update_field/.

Viewing 4 posts - 1 through 4 (of 4 total)

The topic ‘Copy Image / Media Uploads to Another Page’ is closed to new replies.