prestaFinal/ecomzone/classes/EcomZoneProductSync.php
2025-02-04 18:24:30 +01:00

267 lines
8.3 KiB
PHP

<?php
class EcomZoneProductSync
{
private $client;
public function __construct()
{
$this->client = new EcomZoneClient();
}
private function resizeImage($src, $dest, $width, $height)
{
list($srcWidth, $srcHeight, $type) = getimagesize($src);
$srcImage = $this->createImageFromType($src, $type);
$destImage = imagecreatetruecolor($width, $height);
imagecopyresampled($destImage, $srcImage, 0, 0, 0, 0, $width, $height, $srcWidth, $srcHeight);
$this->saveImageFromType($destImage, $dest, $type);
imagedestroy($srcImage);
imagedestroy($destImage);
}
private function createImageFromType($filename, $type)
{
switch ($type) {
case IMAGETYPE_JPEG:
return imagecreatefromjpeg($filename);
case IMAGETYPE_PNG:
return imagecreatefrompng($filename);
case IMAGETYPE_GIF:
return imagecreatefromgif($filename);
default:
throw new Exception("Unsupported image type: " . $type);
}
}
private function saveImageFromType($image, $filename, $type)
{
switch ($type) {
case IMAGETYPE_JPEG:
$this->createDirectoryIfNotExists(dirname($filename));
imagejpeg($image, $filename);
break;
case IMAGETYPE_PNG:
$this->createDirectoryIfNotExists(dirname($filename));
imagepng($image, $filename);
break;
case IMAGETYPE_GIF:
$this->createDirectoryIfNotExists(dirname($filename));
imagegif($image, $filename);
break;
case IMAGETYPE_GIF:
imagegif($image, $filename);
break;
default:
throw new Exception("Unsupported image type: " . $type);
}
}
public function importProducts($perPage = 100)
{
$page = 1;
$totalImported = 0;
$totalAvailable = 0;
EcomZoneLogger::log("Starting product import - perPage: $perPage");
EcomZoneLogger::log("Number of products to be imported per page: $perPage", 'INFO');
try {
do {
$catalog = $this->client->getCatalog($page, $perPage);
$importedCount = 0;
foreach ($catalog['data'] as $product) {
if ($this->importSingleProduct($product)) {
$importedCount++;
}
}
$totalImported += $importedCount;
$totalAvailable = $catalog['total'];
$page++;
EcomZoneLogger::log("Imported page $page", 'INFO', [
'total_imported' => $totalImported,
'page' => $page,
'total_available' => $totalAvailable
]);
} while ($page <= ceil($totalAvailable / $perPage) && isset($catalog['next_page_url']) && $catalog['next_page_url'] !== null);
EcomZoneLogger::log("Finished importing products", 'INFO', [
'total_imported' => $totalImported,
'total_available' => $totalAvailable
]);
// Clear cache
Tools::clearSmartyCache();
Tools::clearXMLCache();
Media::clearCache();
PrestaShopAutoload::getInstance()->generateIndex();
return [
'success' => true,
'imported' => $totalImported,
'total' => $totalAvailable
];
} catch (Exception $e) {
EcomZoneLogger::log("Error importing products: " . $e->getMessage(), 'ERROR');
throw $e;
}
}
private function importSingleProduct($productData)
{
// Extract data from nested structure
$data = isset($productData['data']) ? $productData['data'] : $productData;
if (!isset($data['sku']) || !isset($data['product_name']) || !isset($data['description']) || !isset($data['product_price'])) {
EcomZoneLogger::log("Invalid product data", 'ERROR', ['data' => $productData]);
return false;
}
try {
// Check if product already exists by reference
$productId = Db::getInstance()->getValue('
SELECT id_product
FROM ' . _DB_PREFIX_ . 'product
WHERE reference = "' . pSQL($data['sku']) . '"
');
$product = $productId ? new Product($productId) : new Product();
$defaultLangId = (int)Configuration::get('PS_LANG_DEFAULT');
$product->reference = $data['sku'];
$product->name[$defaultLangId] = $data['product_name'];
$product->description[$defaultLangId] = $data['long_description'] ?? $data['description'];
$product->description_short[$defaultLangId] = $data['description'];
$product->price = $data['product_price'];
$product->active = true;
$product->quantity = (int)$data['stock'];
$homeCategoryId = (int)Configuration::get('PS_HOME_CATEGORY');
$product->id_category_default = $homeCategoryId;
$product->addToCategories([$homeCategoryId]);
$product->visibility = 'both'; // Ensure product is visible in both catalog and search
$product->active = true;
$product->quantity = (int)$data['stock'];
$homeCategoryId = (int)Configuration::get('PS_HOME_CATEGORY');
$product->id_category_default = $homeCategoryId;
$product->addToCategories([$homeCategoryId]);
// Save product first to get ID
if (!$product->id) {
$product->add();
} else {
$product->update();
}
StockAvailable::setQuantity($product->id, 0, (int)$data['stock']);
$product->available_for_order = true; // Ensure product is available for order
$product->show_price = true; // Ensure price is shown
// Handle image import if URL is provided
if (isset($data['image']) && !empty($data['image'])) {
$this->importProductImage($product, $data['image']);
}
StockAvailable::setQuantity($product->id, 0, (int)$data['stock']);
EcomZoneLogger::log("Imported product", 'INFO', [
'sku' => $data['sku'],
'id' => $product->id,
'name' => $data['product_name']
]);
return true;
} catch (Exception $e) {
EcomZoneLogger::log("Error importing product", 'ERROR', [
'sku' => $data['sku'],
'error' => $e->getMessage()
]);
return false;
}
}
private function importProductImage($product, $imageUrl)
{
try {
// Create temporary file
$tmpFile = tempnam(_PS_TMP_IMG_DIR_, 'ecomzone_');
// Download image
if (!copy($imageUrl, $tmpFile)) {
throw new Exception("Failed to download image from: " . $imageUrl);
}
// Get image info
$imageInfo = getimagesize($tmpFile);
if (!$imageInfo) {
unlink($tmpFile);
throw new Exception("Invalid image file");
}
// Validate image dimensions and file size
if ($imageInfo[0] > 2000 || $imageInfo[1] > 2000 || filesize($tmpFile) > 5000000) {
unlink($tmpFile);
throw new Exception("Image dimensions or file size exceed limits");
}
// Generate unique name
$imageName = $product->reference . '-' . time() . '.' . pathinfo($imageUrl, PATHINFO_EXTENSION);
// Delete existing images if any
$product->deleteImages();
// Add new image
$image = new Image();
$image->id_product = $product->id;
$image->position = 1;
$image->cover = true;
// Save the image to the correct directory
$imagePath = _PS_PROD_IMG_DIR_ . $image->getImgPath() . '.' . $image->image_format;
$this->createDirectoryIfNotExists(dirname($imagePath));
if (!copy($tmpFile, $imagePath)) {
unlink($tmpFile);
throw new Exception("Failed to save image to: " . $imagePath);
}
// Associate the image with the product
if (!$image->add()) {
unlink($tmpFile);
throw new Exception("Failed to add image to product");
}
// Manually resize the image and generate thumbnails
$this->resizeImage($imagePath, _PS_PROD_IMG_DIR_ . $image->getImgPath() . '-home_default.' . $image->image_format, 250, 250);
$this->resizeImage($imagePath, _PS_PROD_IMG_DIR_ . $image->getImgPath() . '-large_default.' . $image->image_format, 800, 800);
// Cleanup
unlink($tmpFile);
EcomZoneLogger::log("Imported product image", 'INFO', [
'sku' => $product->reference,
'image' => $imageUrl
]);
} catch (Exception $e) {
EcomZoneLogger::log("Error importing product image", 'ERROR', [
'sku' => $product->reference,
'image' => $imageUrl,
'error' => $e->getMessage()
]);
}
}
private function createDirectoryIfNotExists($directory)
{
if (!is_dir($directory)) {
mkdir($directory, 0755, true);
}
}
}