Here is a mod to the mod above that checks to see if the product has an image already; if not, it takes in the remote image URL in the Location field and saves it, but also updates the Product listing in the database to point to the locally served image. In V1.5.1.3, "uploaded" files are saved in image/data which is the location I chose to save my remote images. You may need to modify this location depending upon version...?
I have added support for validating the file type and extension name as well as to deal with database served images that don't have a file extension at all. It looks up the headers during the call to the remote image for Content-Type validation. This script should fail gracefully if the content is not a valid URL or image type.
Code: Select all
//-----BEGIN REMOTE IMAGE EXTRACTION-----//
//If product does not have a locally stored image...
if($product_info['image'] === '') {
//Let's get an external Image using a URL stored in the Location field
if (strpos($product_info['location'], 'http') !== false) {
//Save the contents of the file to our variable
$contents = file_get_contents($product_info['location']);
//If we got some data from the URL...
if ($contents) {
$imgExt = '';
//Set the filename for the image to be saved locally
$tmpImage = basename($product_info['location']);
//Check to make sure the filename has a valid image extension
preg_match('/[^?]*/', $tmpImage, $matches);
$string = $matches[0];
$pattern = preg_split('/\./', $string, -1, PREG_SPLIT_OFFSET_CAPTURE);
//No extension?? It's probably an image served from a DB
if(count($pattern) == 1 || count($pattern) > 2) {
//Let's fetch the image type from the page headers
$imgHeader = get_headers($product_info['location']);
$imgTypes = array('jpg' => '.jpg', 'jpeg' => '.jpg', 'png' => '.png', 'gif' => '.gif');
//Cycle through image headers array to match an image type
foreach ( $imgHeader as $header => $head ) {
foreach ( $imgTypes as $type => $ext ) {
//Store the extension we matched
if(strpos($head, $type)) { $imgExt = $ext; }
}
}
//If we didn't find an appropriate content type then it isn't a valid image. Set ext to NONE as a failsafe
if($imgExt === '') {$imgExt = 'NONE';}
//Otherwise, we probably want to change the filename to a managable length since our URL was probably a long string of characters.
//Let's process the name to unique 8 char filename using a CRC32 hash
else { $tmpImage = hash('crc32', $tmpImage); }
//If the filename did have an extension initially, let's be sure it is a valid one
} else {
if(!(strpos($tmpImage, '.jpeg' )
|| strpos($tmpImage, '.jpg' )
|| strpos($tmpImage, '.gif' )
|| strpos($tmpImage, '.png' )
|| strpos($tmpImage, '.bmp' ))) {
//No valid Extension? Let's fetch the image type from the page headers
$imgHeader = get_headers($product_info['location']);
$imgTypes = array('jpg' => '.jpg', 'jpeg' => '.jpg', 'png' => '.png', 'gif' => '.gif');
//Cycle through image headers array to match an image type
foreach ( $imgHeader as $header => $head ) {
foreach ( $imgTypes as $type => $ext ) {
//Store the extension we matched
if(strpos($head, $type)) { $imgExt = $ext; }
}
}
//If we didn't find an appropriate content type, then it isn't a valid image. Set ext to NONE as a failsafe
if($imgExt === '') {$imgExt = 'NONE';}
}
}
//Now that we have validated the filename and image type
if($imgExt !== 'NONE') {
//Add the file extension to the end of our filename, if necessary
$tmpImage .= $imgExt;
//Save the file to our image folder
file_put_contents(DIR_IMAGE . "data/" . $tmpImage, $contents);
$product_info['image'] = "data/" . $tmpImage;
//Let's update the database to reflect the location of our new file so we only call the local file from now on.
$product_id = $product_info['product_id'];
$this->db->query("UPDATE " . DB_PREFIX . "product SET image = '" . $this->db->escape($product_info['image']) . "' WHERE product_id = '" . (int)$product_id . "'");
}
}
}
} //-----END IMAGE EXTRACTION-----//
I implemented this mod in V1.5.1.3 in controller/product/product.php just after:
Remote extraction happens before any image manipulation is performed on the product page and is only done once during the life-cycle of the product (or until you clear the image from within the catalog admin.)
I believe this script could be better served somewhere during the search function to extract multiple product images at once. Haven't looked to see where I should move it to, yet. I'll let you know when I figure it out.
Any corrections / additions / modifications are welcome.