Add automatic image downloading from URLs during menu import
This commit is contained in:
parent
f882e84704
commit
4471ddc92b
1 changed files with 127 additions and 2 deletions
|
|
@ -23,6 +23,118 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
response = { "OK": false, "steps": [], "errors": [] };
|
response = { "OK": false, "steps": [], "errors": [] };
|
||||||
|
itemsDir = expandPath("/uploads/items");
|
||||||
|
|
||||||
|
// Helper function: Resize image maintaining aspect ratio, fitting within maxSize box
|
||||||
|
function resizeToFit(img, maxSize) {
|
||||||
|
w = imageGetWidth(img);
|
||||||
|
h = imageGetHeight(img);
|
||||||
|
if (w <= maxSize && h <= maxSize) return img;
|
||||||
|
|
||||||
|
if (w > h) {
|
||||||
|
newW = maxSize;
|
||||||
|
newH = int(h * (maxSize / w));
|
||||||
|
} else {
|
||||||
|
newH = maxSize;
|
||||||
|
newW = int(w * (maxSize / h));
|
||||||
|
}
|
||||||
|
imageResize(img, newW, newH, "highQuality");
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function: Create square thumbnail (center crop)
|
||||||
|
function createSquareThumb(img, size) {
|
||||||
|
thumb = imageCopy(img, 0, 0, imageGetWidth(img), imageGetHeight(img));
|
||||||
|
w = imageGetWidth(thumb);
|
||||||
|
h = imageGetHeight(thumb);
|
||||||
|
|
||||||
|
// Resize so smallest dimension equals size
|
||||||
|
if (w > h) {
|
||||||
|
imageResize(thumb, "", size, "highQuality");
|
||||||
|
} else {
|
||||||
|
imageResize(thumb, size, "", "highQuality");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Center crop to square
|
||||||
|
w = imageGetWidth(thumb);
|
||||||
|
h = imageGetHeight(thumb);
|
||||||
|
if (w > h) {
|
||||||
|
x = int((w - h) / 2);
|
||||||
|
imageCrop(thumb, x, 0, h, h);
|
||||||
|
} else if (h > w) {
|
||||||
|
y = int((h - w) / 2);
|
||||||
|
imageCrop(thumb, 0, y, w, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final resize to exact size
|
||||||
|
imageResize(thumb, size, size, "highQuality");
|
||||||
|
return thumb;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function: Download and save item image from URL
|
||||||
|
function downloadItemImage(itemID, imageUrl) {
|
||||||
|
try {
|
||||||
|
// Skip empty or invalid URLs
|
||||||
|
if (!len(trim(imageUrl))) return false;
|
||||||
|
|
||||||
|
// Make URL absolute if relative
|
||||||
|
if (left(imageUrl, 2) == "//") {
|
||||||
|
imageUrl = "https:" & imageUrl;
|
||||||
|
} else if (left(imageUrl, 1) == "/") {
|
||||||
|
// Can't resolve relative URL without base - skip
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download the image
|
||||||
|
http url="#imageUrl#" method="GET" timeout="30" result="httpResult" {
|
||||||
|
httpparam type="header" name="User-Agent" value="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (httpResult.statusCode != "200 OK" && !httpResult.statusCode.startsWith("200")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's actually an image
|
||||||
|
contentType = structKeyExists(httpResult.responseHeader, "Content-Type") ? httpResult.responseHeader["Content-Type"] : "";
|
||||||
|
if (!findNoCase("image", contentType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to temp file
|
||||||
|
tempFile = itemsDir & "/temp_" & itemID & "_" & createUUID() & ".tmp";
|
||||||
|
fileWrite(tempFile, httpResult.fileContent);
|
||||||
|
|
||||||
|
// Read as image
|
||||||
|
img = imageNew(tempFile);
|
||||||
|
|
||||||
|
// Create thumbnail (128x128 square for retina)
|
||||||
|
thumb = createSquareThumb(img, 128);
|
||||||
|
thumbPath = itemsDir & "/" & itemID & "_thumb.jpg";
|
||||||
|
imageWrite(thumb, thumbPath, 0.85);
|
||||||
|
|
||||||
|
// Create medium size (400px max)
|
||||||
|
medium = imageCopy(img, 0, 0, imageGetWidth(img), imageGetHeight(img));
|
||||||
|
medium = resizeToFit(medium, 400);
|
||||||
|
mediumPath = itemsDir & "/" & itemID & "_medium.jpg";
|
||||||
|
imageWrite(medium, mediumPath, 0.85);
|
||||||
|
|
||||||
|
// Save full size (max 1200px)
|
||||||
|
img = resizeToFit(img, 1200);
|
||||||
|
fullPath = itemsDir & "/" & itemID & ".jpg";
|
||||||
|
imageWrite(img, fullPath, 0.90);
|
||||||
|
|
||||||
|
// Clean up temp file
|
||||||
|
try { fileDelete(tempFile); } catch (any e) {}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (any e) {
|
||||||
|
// Clean up temp file if it exists
|
||||||
|
if (isDefined("tempFile") && fileExists(tempFile)) {
|
||||||
|
try { fileDelete(tempFile); } catch (any e2) {}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
requestBody = toString(getHttpRequestData().content);
|
requestBody = toString(getHttpRequestData().content);
|
||||||
|
|
@ -465,6 +577,7 @@ try {
|
||||||
|
|
||||||
totalItems = 0;
|
totalItems = 0;
|
||||||
totalLinks = 0;
|
totalLinks = 0;
|
||||||
|
totalImages = 0;
|
||||||
|
|
||||||
// Track item order within each category
|
// Track item order within each category
|
||||||
categoryItemOrder = {};
|
categoryItemOrder = {};
|
||||||
|
|
@ -595,9 +708,20 @@ try {
|
||||||
modOrder++;
|
modOrder++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Download item image if URL provided
|
||||||
|
itemImageUrl = "";
|
||||||
|
if (structKeyExists(item, "imageUrl") && isSimpleValue(item.imageUrl)) {
|
||||||
|
itemImageUrl = trim(item.imageUrl);
|
||||||
|
}
|
||||||
|
if (len(itemImageUrl)) {
|
||||||
|
if (downloadItemImage(menuItemID, itemImageUrl)) {
|
||||||
|
totalImages++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response.steps.append("Created/updated " & totalItems & " items with " & totalLinks & " modifier links");
|
response.steps.append("Created/updated " & totalItems & " items with " & totalLinks & " modifier links" & (totalImages > 0 ? " and " & totalImages & " images downloaded" : ""));
|
||||||
|
|
||||||
response.OK = true;
|
response.OK = true;
|
||||||
response.summary = {
|
response.summary = {
|
||||||
|
|
@ -605,7 +729,8 @@ try {
|
||||||
"categoriesProcessed": arrayLen(categories),
|
"categoriesProcessed": arrayLen(categories),
|
||||||
"templatesProcessed": arrayLen(modTemplates),
|
"templatesProcessed": arrayLen(modTemplates),
|
||||||
"itemsProcessed": totalItems,
|
"itemsProcessed": totalItems,
|
||||||
"linksCreated": totalLinks
|
"linksCreated": totalLinks,
|
||||||
|
"imagesDownloaded": totalImages
|
||||||
};
|
};
|
||||||
|
|
||||||
} catch (any e) {
|
} catch (any e) {
|
||||||
|
|
|
||||||
Reference in a new issue