• I’m looking to, programmatically on upload, change the URL of a media file to its URL on a CDN. I.e. modify site.com/wp-content/uploads/file.jpg to be cdn.site.com/wp-content/uploads/file.jpg.

    Essentially what I’m asking is: which hook should I tie into? If anybody has more code help, that’s great, but I think hook is the big question.

    People before seem to have been wondering this, so I think it’ll be helpful to resolve. Note also: I’m aware that W3 Total Cache and other plugins do this; I’d actually like it changed in the database (not just filtered on post render/output), and need to use some of my own logic, so I need to code snippet in my code.

    Many thanks.

Viewing 6 replies - 1 through 6 (of 6 total)
  • Moderator bcworkz

    (@bcworkz)

    URLs and other uploaded file data are stored in post attachments, which are just another post type much like posts themselves. So you could use any hook that you would use for posts in general. Attachments do happen to have some special features beyond the typical post. One of those is the filter ‘wp_insert_attachment_data’ with which you can alter the ‘guid’ field.

    Any metadata that needs to be altered can be filtered with ‘update_postmeta’

    Thread Starter B

    (@bh8489)

    Thank you… I’ve been playing with that but to no avail. I have the following:

    function filter_handler( $data , $post_arr ){
         update_post_meta($post_arr['ID'], 'guid', 'https://newurl.com/test.jpg');
         return $data;
    }
    add_filter( 'wp_insert_attachment_data', 'filter_handler', '99', 2 );

    Which ends up doing nothing. Thoughts?

    Thanks!

    Moderator bcworkz

    (@bcworkz)

    You are adding the test URL to postmeta under the key ‘guid’, which is fine if that is what your installation needs, but that is atypical. Also, the priority number for add_filter() should be an integer, not a string, so do not use the single quotes for 99. PHP should resolve the string into an integer for you, but it’s best to start with the correct type to begin with.

    Also note that $post_arr['ID'] only exists for attachment updates, not for new attachments. This filter is thus inappropriate for saving post meta, ‘add_attachment’ or ‘edit_attachment’ are better for post meta.

    What ‘wp_insert_attachment_data’ is good for is altering anything saved in the post table row, such as the ‘guid’ field. Do this by altering the $data array returned from the filter. You need a line like this:
    $data['guid'] = wp_slash('https://newurl.com/test.jpg');

    Note that all data added with this filter should be slashed. That particular string has nothing that would be slashed anyway, but better safe than sorry.

    For altering typical URL data, you will need to also set the URL in postmeta (using one of the above mentioned filters) under the key ‘_wp_attached_file’. For what you are doing, this next step shouldn’t be necessary, but it’s worth noting that there is a lot of meta data for attachments under ‘_wp_attachment_metadata’ that may need to be altered in some cases.

    Thread Starter B

    (@bh8489)

    Update: editing $data['guid'] does seem to update the guid field in the database, but that does not update the File URL field shown on the media uploads page, or the actual URL used when inserting an image into a post. _wp_attached_file works, but only modifies the file path, not the domain; how do we modify the complete URL for the attachment?

    Continue reading if you wish, but that’s the main question.

    —————-

    Thanks so much– very helpful.

    function filter_handler( $data , $post_arr ){
         $data['post_excerpt'] = 'Test excerpt'; //This successfully sets the excerpt
         $data['guid'] = wp_slash('https://test.com/a.jpg'); //This modifies the guid in the database but that appears to be the wrong field
         update_post_meta( $post_arr['ID'], '_wp_attached_file', wp_slash('https://test.com/a.jpg')); //This sets the path within the uploads folder to https://test.com/a.jpg
         return $data;
    }
    add_filter( 'wp_insert_attachment_data', 'filter_handler', 99, 2 );

    See comments on each line in the above. _wp_attached_file only modifies the file path after /wp-content/uploads/ (i.e. https://site.com/wp-content/uploads/sites/2/https://test.com/a.jpg) … the part of the URL I ultimately need to change is the domain.

    The whole point of all of this is to route media to my CDN subdomain. I can change the domain in the database like this or on read, but I need it to reflect the accurate domain everywhere (i.e. in the backend); I can’t just do a rewrite on frontend post render.

    Any feedback on how to get this working would be VERY much appreciated!

    Moderator bcworkz

    (@bcworkz)

    You are of course correct that metadata does not contain the entire URL, the URL is built on the fly when the media uploader loads images. I lost sight of your goal in my quest for modifying attachment data, my apologies.

    Not that it helps you, but for the record, the image path in ‘_wp_attached_file’ is also stored in the array under ‘_wp_attachment_metadata’.

    So what we really need is to intercept how the media uploader gets the image URL. Portions of WP that involve javascript, such as the uploader, are very confusing to me, so I’m not entirely sure where the image URL is being built. In poking around trying to find out something, I saw a call to wp_get_attachment_url(). I’m not sure if this is used by the uploader, but it looks very probable.

    That function has a filter of the same name, ‘wp_get_attachment_url’. Your filter callback is passed the URL as built and the post/attachment ID. You can substitute in the subdomain reference to the passed URL and return that modified URL.

    I’m not sure this will do the job for you, but it looks promising. At the very least it is likely a partial solution and a step in the right direction.

    max

    (@seoactivist)

Viewing 6 replies - 1 through 6 (of 6 total)
  • The topic ‘Change media URLs on upload’ is closed to new replies.