Podatki > Reguły podatkowe $configTaxRulesGroupId = 1; // ID Kategorii domyślnej, do której mają trafić produkty (np. "Kinkiety" lub ogólna) $configDefaultCategoryId = 12; // Czy włączyć produkt po imporcie? $configActive = 1; // ============================================ // Sprawdzenie trybu działania $modeAdd = (Tools::getValue('add') === 'true'); $modeUpdate = (Tools::getValue('update') === 'true'); $modeSynch = (Tools::getValue('synch') === 'true'); if (!$modeAdd && !$modeUpdate && !$modeSynch) { die('Brak akcji. Dodaj do adresu ?add=true lub ?update=true lub ?synch=true'); } // Plik logu $logFile = __DIR__ . '/sollux_import_log.csv'; // Wczytanie XML $xmlUrl = 'https://sollux-lighting.com/product_feed/sollux/XML_polski_PLN_wszystkie_vip.xml'; $xml = simplexml_load_file($xmlUrl) or die("Error: Cannot create object from XML"); // === FUNKCJE POMOCNICZE === // Tworzenie pola multilang (wymagane przez Prestę) function createMultiLangField($field) { $languages = Language::getLanguages(false); $res = []; foreach ($languages as $lang) { $res[(int)$lang['id_lang']] = $field; } return $res; } // Tworzenie przyjaznego linku function createLinkRewrite($field) { $languages = Language::getLanguages(false); $res = []; $linkRewrite = Tools::link_rewrite($field); foreach ($languages as $lang) { $res[(int)$lang['id_lang']] = $linkRewrite; } return $res; } // Pobieranie zdjęcia function addProductImage($productId, $imageUrl) { if (empty($imageUrl)) return false; $image = new Image(); $image->id_product = (int)$productId; $image->position = Image::getHighestPosition($productId) + 1; $image->cover = ($image->position == 1); // Pierwsze zdjęcie jako okładka if (!$image->add()) return false; $imagePath = $image->getPathForCreation(); $url = str_replace(' ', '%20', trim($imageUrl)); // Próba pobrania if (!@copy($url, $imagePath . '.jpg')) { $image->delete(); return false; } // Generowanie miniatur $imageTypes = ImageType::getImagesTypes('products'); foreach ($imageTypes as $imageType) { if (!ImageManager::resize( $imagePath . '.jpg', $imagePath . '-' . stripslashes($imageType['name']) . '.jpg', (int)$imageType['width'], (int)$imageType['height'] )) { // W razie błędu resize można obsłużyć wyjątek, tutaj cicho pomijamy } } return true; } // Znajdź produkt po SKU (reference) function findProductByReference($reference) { if (empty($reference)) return false; $sql = 'SELECT `id_product` FROM `'._DB_PREFIX_.'product` WHERE `reference` = \''.pSQL($reference).'\''; $result = Db::getInstance()->getRow($sql); return $result ? new Product((int)$result['id_product']) : false; } // Parsowanie ceny (zamiana przecinków na kropki, usuwanie spacji) function parsePrice($rawPrice) { $clean = str_replace([' ', ','], ['', '.'], (string)$rawPrice); return (float)$clean; } // Budowanie tabeli HTML z atrybutów XML function buildAttributesHtml($xmlAttributesNode) { if (!$xmlAttributesNode || !isset($xmlAttributesNode->attribute)) { return ''; } $html = '
| ' . htmlspecialchars($name) . ' | '; $html .= '' . htmlspecialchars($value) . ' | '; $html .= '
Wyłączono produkty niedostępne w feedzie.
"; // Włącz produkty, które są w XML $sqlEnable = 'UPDATE `'._DB_PREFIX_.'product` p JOIN `'._DB_PREFIX_.'sollux_temp` t ON p.reference = t.sku SET p.active = 1 WHERE p.active = 0'; $db->execute($sqlEnable); echo "Włączono produkty dostępne w feedzie.
"; // Posprzątaj $db->execute('DROP TABLE `'._DB_PREFIX_.'sollux_temp`'); echo 'Zakończono synchronizację.
'; exit; } // 2. TRYB AKTUALIZACJI (Ceny, Stany) if ($modeUpdate) { cleanLogFile($logFile); $today = date('Y-m-d'); $updatedCount = 0; // Wczytaj log, aby nie aktualizować tego samego produktu wielokrotnie tego samego dnia $processedSkus = []; if (file_exists($logFile)) { $lines = file($logFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); foreach ($lines as $line) { $data = explode(';', $line); // Date;SKU if (isset($data[0]) && $data[0] == $today && isset($data[1])) { $processedSkus[trim($data[1])] = true; } } } echo "Zaktualizowano: $sku (Cena netto: $priceNet)
"; $updatedCount++; // Aktualizujemy 1 produkt na wywołanie, żeby nie przekroczyć czasu wykonywania? // W poprzednim skrypcie był break. Jeśli masz crona co minutę, odkomentuj break. // Jeśli odpalasz ręcznie w przeglądarce, break spowoduje konieczność ciągłego odświeżania. // Zostawiam break dla bezpieczeństwa, odświeżaj stronę (meta reload na dole). break; } if ($updatedCount > 0) { echo ''; echo 'Trwa przeładowanie strony...
'; } else { echo 'Wszystkie produkty z XML zostały już dzisiaj zaktualizowane.
'; } exit; } // 3. TRYB DODAWANIA (ADD) if ($modeAdd) { $addedCount = 0; foreach ($xml->product as $productNode) { $sku = trim((string)$productNode->sku); if (empty($sku)) continue; // Sprawdź czy produkt już istnieje if (findProductByReference($sku)) { // Produkt istnieje, w trybie ADD nic nie robimy (ewentualnie można zrobić update) continue; } // === TWORZENIE NOWEGO PRODUKTU === $product = new Product(); $product->reference = $sku; $product->ean13 = trim((string)$productNode->ean); $product->name = createMultiLangField(trim((string)$productNode->nazwa_produktu)); // Kategoria i Producent $product->id_category_default = (int)$configDefaultCategoryId; $product->id_manufacturer = (int)$configManufacturerId; $product->id_tax_rules_group = (int)$configTaxRulesGroupId; // VAT // Cena $priceGross = parsePrice($productNode->cena_detaliczna_brutto_pln); $product->price = Tools::ps_round($priceGross / 1.23, 6); // Wymiary i Waga $product->width = (float)$productNode->szerokosc; $product->height = (float)$productNode->wysokosc; $product->depth = (float)$productNode->dlugosc; $product->weight = (float)$productNode->waga_produktu; // Opisy $shortDesc = trim((string)$productNode->opis_krotki_html); $longDescRaw = trim((string)$productNode->opis_dlugi_korzysci_html); // Generowanie tabeli specyfikacji z atrybutów $attributesHtml = buildAttributesHtml($productNode->attributes); // Sklejenie opisu: Opis marketingowy + Tabela atrybutów $finalLongDesc = $longDescRaw . 'Dodano produkt: " . $product->name[Context::getContext()->language->id] . " ($sku)
"; $addedCount++; // Break po dodaniu jednego, aby odciążyć serwer (skrypt musi być wywoływany cyklicznie) break; } else { echo "Błąd podczas dodawania produktu: $sku
"; } } if ($addedCount > 0) { echo ''; echo 'Dodano produkt. Odświeżanie...
'; } else { echo 'Brak nowych produktów do dodania (lub wszystkie już istnieją).
'; } } ?>