0

First of all, I should say that this is a WordPress based question, which I originally asked on the WordPress StackExchange, here. But I think it's turned into a more PHP-based question so that's why I'm asking here.

So basically, I've written this preg_replace_callback function, which, on saving/publishing the post, will replace all of the image URLs with URLs from the WP Uploads directory. I've had fleeting success with this; sometimes it works, but only on one of the URLs (in my test examples on my site I have 3 img tags, each split up with paragraphs.

Here is my code:

add_filter('content_save_pre', 'getpostimgs'); // content_save_pre filter may be depreceated? => http://adambrown.info/p/wp_hooks/hook/content_save_pre

function getpostimgs() {
    global $post;

    $postContent = $post->post_content;

    $content = preg_replace_callback(
        '/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', // pattern to match to (i.e the contents of an <img src="..." /> tag)
        function ($match) {
            $imgURL = $match[1]; // the second array (#1) (0-based) is the array with the URLs in. First array (#0) has the whole img tag in.

            $image_data = file_get_contents($imgURL); // Get image data
            $filename   = basename($imgURL) . "-" . $post->ID . ".jpg"; // Create image file name

            if( wp_mkdir_p( $upload_dir['path'] ) ) { // check upload file exists and the permissions on it are correct
                $file = $upload_dir['path'] . '/' . $filename;
            } else {
                $file = $upload_dir['basedir'] . '/' . $filename;
            } // save file to server

            file_put_contents( $file, $image_data ); // save the file to the server

            return $file;
        },
        $postContent
    );

    return $content;
}

I've added some comments along the way to hopefully explain what I'm doing at each stage. I'm not a PHP wizard (I mainly do WordPress PHP) so be nice! Also, as I put in the comments, the WordPress filter I'm using, content_save_pre, which is supposed to edit the content before being saved to the database, has been depreciated. But that's a WordPress issue, so I'll consult the guys on the WordPress Stackexchange about that one.

Anyway, my main problem is that when I hit save, the content is completely wiped. As I said above, I've had fleeting success - sometimes it will replace maybe one of the URLs, other times it won't, and most of the time it simply wipes all the content. I'm assuming there's something wrong with the preg_replace_callback.

Lastly: as you may have seen from the link I posted to the Wordpress StackExchange (right at the top), I originally coded this up by using a preg_match_all to find all the image URLs, then used a foreach loop to go through the array of URLs and had a prey_replace to replace the URLs. That code is here if you want to take a look at that. I changed it based on the advice on this thread (correct answer). But both methods act pretty much the same.

Thanks for any help :)

EDIT: I've updated my code a little, made a few silly mistakes regarding global variables/variable scope and a few syntax/WP errors. Here's my updated code:

function getpostimgs() {
    global $post;
    $postContent = $post->post_content;

    $content = preg_replace_callback(
        '/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', // pattern to match to (i.e the contents of an <img src="..." /> tag)
        function ($match) {
            global $post, $postContent;

            $upload_dir = wp_upload_dir(); // Set upload folder
            $imgURL = $match[1];

                $image_data = file_get_contents($imgURL); // Get image data
            $filename   = basename($imgURL) . "-" . $post->ID . ".jpg"; // Create image file name

            if( wp_mkdir_p( $upload_dir['path'] ) ) { // check upload file exists and the permissions on it are correct
                $file = $upload_dir['path'] . '/' . $filename;
            } else {
                $file = $upload_dir['basedir'] . '/' . $filename;
            } // save file to server

            file_put_contents( $file, $image_data ); // save the file to the server


            return $file;
        },
        $postContent
    );

    return $content;
}

add_filter('content_save_pre', 'getpostimgs'); // content_save_pre filter may be depreceated? => http://adambrown.info/p/wp_hooks/hook/content_save_pre

If I call this function on a single.php page or something, it will work, i.e. the Original Image URLs in the post content which is returned have been replaced by Upload Directory URLs, so the regex and stuff is correct. However, it doesn't work when I try to publish/update a post (the content is usually wiped). Any ideas?

Community
  • 1
  • 1
Tom Oakley
  • 6,065
  • 11
  • 44
  • 73
  • getpostimgs is a filter and hence takes an argument $post_content. I am not sure if $post->post_content is valid at this time. –  Apr 01 '14 at 22:17
  • should be valid, `$post` is a global variable in both functions, and the Images from the post are picked up and saved with correct Post ID so `$post->post_content` should be valid. What do you mean 'getpostimgs is a filter and hence takes an argument $post_content'? Do you mean this already exists in another part of WP and I should rename my function? – Tom Oakley Apr 01 '14 at 22:29
  • filters are not actions and they are called with at least 1 argument - the data to be manipulated. I am not sure but all the members of $post in particular post_content may not yet be valid since they are in the process of being saved/updated - I will read the code and see if I can give you a more definite answer. Anyway you don't need that and should use the argument instead. –  Apr 01 '14 at 22:36
  • ah ok that makes sense. So I should have an argument, such as the original post content that will be manipulated, for my argument? Thanks for the help :) – Tom Oakley Apr 01 '14 at 22:40
  • The filter content_save_pre is called from sanitize_post_field() which is called from sanitize_post() (and some other places). sanitize_post() can be called with either a $post object or a $post array. My guess is the $post array is a $post object precursor so the $post object is not yet valid. This is a guess. Sorry don't have any more time to spend now. –  Apr 01 '14 at 23:00

0 Answers0