1

I would like to move attached file from one directory within WP uploads folder to another directory. The code below achieves the task. As you can see, I move the original file and also all widthxheight files automatically generated by WP (such as 150x150, 30x300). I call update_attached_file($id, $new_filepath ) and I can see the files moved, they are visible in Media library - no problem.

The issue happens when I try to rename the original file. From "name.jpg" to "username_name.jpg". Now the files are still moved to the new directory and they are renamed "username_name.jpg", "username_name-150x150.jpg", "username_name-300x300.jpg". However, WP Media library does not show the thumbnail now. It still expects "name-150x150.jpg" istead of "username_name-150x150.jpg".

The question is how can I update wordpress on the new file names for the widthxheight files? I searched and could not find any function that would give me IDs for the attachment size files. It must be possible. So many plugins do the renaming all the time...Any help?

  // Get all uploaded file attachment IDs
  $media_ids = $_POST['item_meta'][205]; // file upload field ID

 // Loop through each attachment
  foreach ( (array)$media_ids as $id ) {
    if ( ! $id ) {
      continue; // exit when there are no more attachments to loop through
    }

    // extract attachment file name without extension
    $path_parts = pathinfo( get_attached_file( $id ));
    $filenamenoextention = $path_parts['filename'];

    // Extract username
    $username = sanitize_title($_POST['item_meta'][195]);

    // Set new base path
    $new_filepath_base = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/uploads/profiles/pro/';

    // create user directory, if it does not exist already
    $userdir = $new_filepath_base . $username;
    if (!file_exists($userdir)) {
      mkdir($userdir, 0775, true);
    }


    // Wordpress saves extra file sizes. Extract paths to all of them using wildcard *.
    $original_filepaths = glob($_SERVER['DOCUMENT_ROOT'] . '/wp-content/uploads/form/20/' . $filenamenoextention . '*'); 


    // Loop through WP-generated files and move them to a new location.
    foreach ($original_filepaths as $original_filepath) {

        // Add alt to the image. Good for SEO.
       update_post_meta( $id, '_wp_attachment_image_alt', 'main profile photo - ' . $username);

        // enrich filename with username and a tag
       // $new_filename = $username .'_'  . basename($original_filepath);
        $new_filename = basename($original_filepath);

        $new_filepath = $userdir . '/' . $new_filename;
        $rename_result = rename($original_filepath, $new_filepath);

        // If move was successful, update file path so that WP Media interface can find it.
        if($rename_result)
        {
           update_attached_file($id, $new_filepath );

        }
      }

    }

2 Answers 2

2

Here is the code that works. Files are moved to 'username' folder and names for all files (including width x height) are updated.

 // Get all uploaded file attachment IDs
  $media_ids = $_POST['item_meta'][205]; // file upload field ID


 // Loop through each attachment
  foreach ( (array) $media_ids as $id ) {
        if ( ! $id ) {
          continue; // exit when there are no more attachments to loop through
        }

        // Extract username
        $username = sanitize_title($_POST['item_meta'][195]);

        // Set filenames and paths
        $old_filename_mainmedia =  basename( get_attached_file( $id ) );
        $new_filename_mainmedia = $username . '_' . $old_filename_mainmedia;
        $old_filepath_mainmedia = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/uploads/' . $old_filename_mainmedia; 
        $new_filepath_mainmedia = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/uploads/profiles/' . $username .'/' . $new_filename_mainmedia;

        // create user directory, if it does not exist already
        if (!file_exists($_SERVER['DOCUMENT_ROOT'] . '/wp-content/uploads/profiles/pro/' . $username)) {
          mkdir($_SERVER['DOCUMENT_ROOT'] . '/wp-content/uploads/profiles/pro/' . $username, 0775, true);
        }


        // Construct attachment metadata: https://codex.wordpress.org/Function_Reference/wp_get_attachment_metadata
        $meta = wp_get_attachment_metadata($id);
        $meta['file'] = str_replace( $old_filename_mainmedia, $new_filename_mainmedia, $meta['file'] );

        // Rename the original file
        rename($old_filepath_mainmedia, $new_filepath_mainmedia);

        // Rename the sizes
        $old_filename_sizemedia = pathinfo( basename( $old_filepath_mainmedia ), PATHINFO_FILENAME );
        $new_filename_sizemedia = pathinfo( basename( $new_filepath_mainmedia ), PATHINFO_FILENAME );
        foreach ( (array)$meta['sizes'] AS $size => $meta_size ) {
            $old_filepath_sizemedia = dirname( $old_filepath_mainmedia ).DIRECTORY_SEPARATOR.$meta['sizes'][$size]['file'];
            $meta['sizes'][$size]['file'] = str_replace( $old_filename_sizemedia, $new_filename_sizemedia, $meta['sizes'][$size]['file'] );
            $new_filepath_sizemedia = dirname( $new_filepath_mainmedia ).DIRECTORY_SEPARATOR.$meta['sizes'][$size]['file'];
            rename( $old_filepath_sizemedia, $new_filepath_sizemedia );
        }

        // Add alt to the image. Good for SEO.
        update_post_meta( $id, '_wp_attachment_image_alt', 'Gritmatch Pro - main profile photo - ' . $username);

        // Update media library post title
        $post = get_post($id); 
        $post->post_title = $new_filename_mainmedia;
        $post->post_excerpt = "this is caption";
        $post->post_content = "this is content";
        $post->post_name = "this is post name";
        wp_update_post( $post );

        // Update Wordpress 
        wp_update_attachment_metadata( $id, $meta );
        update_attached_file($id, $new_filepath_mainmedia );

      } // end looping through each media attachment
0

If you upload an image in the wordpress backend, wordpress creates copies of that file in different sizes ("widthxheight" files). The metadata of that attachment will be saved in the table "wp_postmeta".

But if you look in this table, you would realize there are only two entries for that attachment (post_id). The first entry is "_wp_attached_file" and the second is "_wp_attachment_metadata".

_wp_attached_file => contains the path to the orginal image

_wp_attachment_metadata => contains the metadata which includes the names and sizes of "widthxheight" files.

To get the data from _wp_attachment_metadata you can use the function wp_get_attachment_metadata an to change the data you can use the function wp_update_attachment_metadata.

The function update_attached_file edit only the _wp_attached_file entry.

Usefull links:

How to change _wp_attachment_metadata specific value in SQL? - wordpress.stackexchange.com

Change attachment filename - wordpress.stackexchange.com

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.