Drupal 7 EMW: Adding Images to a Image List

I was tasked with migrating content from one D7 site to another. There are a number of great modules out there to help with this — but for various reasons I decided to write my own module / library. By en large — no problems, except when it came to migrating images.
I was using Entity Metadata Wrapper’s all over the show (as one should). Sadly when it comes to images, the documentation and examples are sparse at best. I am sharing my code, just in case you ever need to do the same: migrating an image from site to another and adding it to a node.
As it turns out, the code is very simple:
Assume I am getting the full URL of the image I want to import (for example http://old.site.com/sites/default/files/my_image.jpg.
Assume also you have a destination (local) file name. For that argument, you could deduce the file name from the URL, or even generate a random file name. Makes no difference, as long as you have some file name that you want to use on your new site. Let’s call it my_new_image.jpg for now.
Lastly, the field where I want to store this is a stock standard D7 image field, which allows unlimited values (so we could have more than one image for a specific node — typical for blogs and galleries).
There is this awesome function in D7 called file_save_data. The function takes 3 parameter: $data, $destination (optional) and $replace (optional).
Sadly the documentation does not make it obvious that $data could be a PHP stream. Now that you know, using the function to get a remote resource onto your local D7 site is as easy as:
$file_path = file_save_data(file_get_contents($image_url),
'public://$my_new_image.jpg');
The contents of $file_path now has all the fields required by a field of type image — and so saving it to the node using EMW is as simple as:
$wrapper->field_image->set($file_path);
This, will only work if field_image has a cardinality of one (can only take one value). As soon as the field can have two or more, it becomes an array of values and so the syntax changes to:
$wrapper->field_image[] = (array) $file_path;
So for each image we want to add, we would:
$file_name = ‘some_random_name’;
foreach ($new_images_url as $index => $image_url) {$file_path = file_save_data(file_get_contents($image_url),
'public://’ . $file_name . $index . ‘.jpg’);
$wrapper->field_image[] = (array) $file_path;
}
Remember to save the wrapper ($wrapper->save()) when you done.
As it turns out, I have a really small module that allows me to retrieve content from one site and create new nodes on a different site. The module(s) use JSON to exchange data, with only a couple dozen lines of code.
Sure I could have used an existing module — but now I have 100% control over what I send, receive and how I use that information: sometimes simple is better :)
I’m happy to answer any question you might have!