Files
interblue.pl/export-csv.php

399 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* PrestaShop 1.7.x eksport produktów z atrybutami i cechami do CSV
* Każdy wiersz = produkt bez kombinacji albo konkretna kombinacja produktu.
*/
ini_set('memory_limit', '1024M');
set_time_limit(0);
// ===== KONFIGURACJA =====
$host = "localhost";
$db = "interblue_sklep";
$user = "interblue_sklep";
$pass = "2212+#++@pSVSb4";
$prefix = "ps_"; // zmień jeśli masz inny prefix
$idLang = 1; // ID języka (sprawdź w ps_lang)
$idShop = 1; // ID sklepu (sprawdź w ps_shop)
$outFile = __DIR__ . "/export_products.csv";
$delimiter = ";"; // średnik wygodny do Excela w PL
// ========================
// --- TRYB TESTOWY NOWE ---
// Ustaw JEDNO z poniższych (drugie zostaw puste), aby wyeksportować tylko wybrany produkt:
$testProductId = null; // np. 123; lub null
$testEan = ""; // np. "5901234567890"; lub "" (puste)
// Dodatkowo możesz nadpisać przez URL/CLI: ?test_id=123 lub ?test_ean=590...
if (php_sapi_name() !== 'cli')
{
if (isset($_GET['test_id']) && is_numeric($_GET['test_id']))
{
$testProductId = (int)$_GET['test_id'];
}
if (isset($_GET['test_ean']) && $_GET['test_ean'] !== '')
{
$testEan = trim($_GET['test_ean']);
}
}
else
{
// CLI: php export.php test_id=123 lub test_ean=590...
foreach ($argv as $arg)
{
if (preg_match('/^test_id=(\d+)$/', $arg, $m)) $testProductId = (int)$m[1];
if (preg_match('/^test_ean=(.+)$/', $arg, $m)) $testEan = trim($m[1]);
}
}
// ========================
// Połączenie PDO
$pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8", $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, // <— włącz buffer
]);
// Otwórz CSV
$fh = fopen($outFile, "w");
if (!$fh) die("Nie mogę utworzyć pliku CSV: {$outFile}\n");
// (Opcjonalnie) BOM dla Excela na Windows
fwrite($fh, "\xEF\xBB\xBF");
// Nagłówek
$header = [
'id_product',
'id_product_attribute',
'product_name',
'manufacturer',
'default_category',
'active',
'price_tax_excl',
'quantity',
'reference',
'ean13',
'weight',
'comb_reference',
'comb_ean13',
'comb_weight',
'comb_quantity',
'attributes', // "Grupa: Wartość | Grupa2: Wartość2"
'features' // "Cecha: Wartość | Cecha2: Wartość2"
];
fputcsv($fh, $header, $delimiter);
// ===== POMOCNICZE FUNKCJE =====
function getProductFeatures(PDO $pdo, $prefix, $idLang, $idProduct): array
{
// Fallback: weź tłumaczenie w :id_lang, a jeśli go nie ma w minimalnym (dowolnym) id_lang
$sql = "
SELECT
COALESCE(fl.name, fl_any.name, '') AS feature_name,
COALESCE(fvl.value, fvl_any.value, '') AS feature_value
FROM {$prefix}feature_product fp
/* nazwa cechy w żądanym języku */
LEFT JOIN {$prefix}feature_lang fl
ON fl.id_feature = fp.id_feature
AND fl.id_lang = :id_lang
/* wybór jakiegokolwiek dostępnego języka dla cechy */
LEFT JOIN (
SELECT id_feature, MIN(id_lang) AS any_lang
FROM {$prefix}feature_lang
GROUP BY id_feature
) fl_pick
ON fl_pick.id_feature = fp.id_feature
LEFT JOIN {$prefix}feature_lang fl_any
ON fl_any.id_feature = fp.id_feature
AND fl_any.id_lang = fl_pick.any_lang
/* wartość cechy */
JOIN {$prefix}feature_value fv
ON fv.id_feature_value = fp.id_feature_value
/* wartość w żądanym języku */
LEFT JOIN {$prefix}feature_value_lang fvl
ON fvl.id_feature_value = fv.id_feature_value
AND fvl.id_lang = :id_lang
/* fallback: jakikolwiek język dla wartości */
LEFT JOIN (
SELECT id_feature_value, MIN(id_lang) AS any_lang
FROM {$prefix}feature_value_lang
GROUP BY id_feature_value
) fvl_pick
ON fvl_pick.id_feature_value = fv.id_feature_value
LEFT JOIN {$prefix}feature_value_lang fvl_any
ON fvl_any.id_feature_value = fv.id_feature_value
AND fvl_any.id_lang = fvl_pick.any_lang
WHERE fp.id_product = :id_product
ORDER BY feature_name ASC
";
$stmt = $pdo->prepare($sql);
$stmt->execute([
':id_lang' => (int)$idLang,
':id_product' => (int)$idProduct,
]);
$out = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$fname = trim((string)($row['feature_name'] ?? ''));
$fval = trim((string)($row['feature_value'] ?? ''));
if ($fname === '' && $fval === '') continue;
if ($fname === '') $fname = 'Cecha';
$out[$fname] = $fval;
}
return $out;
}
function getProductCombinations(PDO $pdo, $prefix, $idLang, $idShop, $idProduct): array
{
$sqlComb = "
SELECT pa.id_product_attribute,
pa.reference AS comb_reference,
pa.ean13 AS comb_ean13,
pa.weight AS comb_weight,
COALESCE(sa.quantity, 0) AS comb_quantity
FROM {$prefix}product_attribute pa
LEFT JOIN {$prefix}stock_available sa
ON sa.id_product = pa.id_product
AND sa.id_product_attribute = pa.id_product_attribute
AND (sa.id_shop = :id_shop OR sa.id_shop IS NULL)
WHERE pa.id_product = :id_product
ORDER BY pa.id_product_attribute ASC
";
$st = $pdo->prepare($sqlComb);
$st->execute([':id_product' => (int)$idProduct, ':id_shop' => (int)$idShop]);
$combinations = $st->fetchAll(PDO::FETCH_ASSOC);
if (!$combinations) return [];
$ids = array_column($combinations, 'id_product_attribute');
$in = implode(',', array_map('intval', $ids));
$sqlAttrs = "
SELECT pac.id_product_attribute,
agl.name AS group_name,
al.name AS attr_name
FROM {$prefix}product_attribute_combination pac
JOIN {$prefix}attribute a
ON a.id_attribute = pac.id_attribute
JOIN {$prefix}attribute_lang al
ON al.id_attribute = a.id_attribute AND al.id_lang = :id_lang
JOIN {$prefix}attribute_group_lang agl
ON agl.id_attribute_group = a.id_attribute_group AND agl.id_lang = :id_lang
WHERE pac.id_product_attribute IN ($in)
ORDER BY agl.name, al.name
";
$st2 = $pdo->prepare($sqlAttrs);
$st2->execute([':id_lang' => (int)$idLang]);
$attrMap = [];
while ($r = $st2->fetch(PDO::FETCH_ASSOC))
{
$ipa = (int)$r['id_product_attribute'];
$pair = trim($r['group_name']) . ": " . trim($r['attr_name']);
$attrMap[$ipa][] = $pair;
}
foreach ($combinations as &$c)
{
$ipa = (int)$c['id_product_attribute'];
$pairs = $attrMap[$ipa] ?? [];
$c['attributes_str'] = implode(' | ', $pairs);
}
return $combinations;
}
// ===== FUNKCJA PISZĄCA WIERSZE DO CSV =====
function writeProductRowsToCsv($fh, $prod, $featuresStr, $combinations, $delimiter)
{
if ($combinations)
{
foreach ($combinations as $c)
{
$line = [
$prod['id_product'],
$c['id_product_attribute'],
$prod['product_name'],
$prod['manufacturer'],
$prod['default_category'],
(int)$prod['active'],
$prod['price_tax_excl'],
$prod['quantity'],
$prod['reference'],
$prod['ean13'],
$prod['weight'],
$c['comb_reference'],
$c['comb_ean13'],
$c['comb_weight'],
$c['comb_quantity'],
$c['attributes_str'],
$featuresStr,
];
fputcsv($fh, $line, $delimiter);
}
}
else
{
$line = [
$prod['id_product'],
0,
$prod['product_name'],
$prod['manufacturer'],
$prod['default_category'],
(int)$prod['active'],
$prod['price_tax_excl'],
$prod['quantity'],
$prod['reference'],
$prod['ean13'],
$prod['weight'],
'',
'',
'',
'',
'', // attributes
$featuresStr,
];
fputcsv($fh, $line, $delimiter);
}
}
// ===== ZAPYTANIE BAZOWE (wspólne) =====
$baseSelect = "
SELECT
p.id_product,
COALESCE(pl.name, CONCAT('Produkt #', p.id_product)) AS product_name,
p.reference,
p.ean13,
p.weight,
ps.price AS price_tax_excl,
ps.active,
COALESCE(sa.quantity, 0) AS quantity,
m.name AS manufacturer,
cl.name AS default_category
FROM {$prefix}product p
/* KLUCZOWA ZMIANA: LEFT JOIN + warunek po id_shop */
LEFT JOIN {$prefix}product_lang pl
ON pl.id_product = p.id_product
AND pl.id_lang = :id_lang
AND pl.id_shop = :id_shop
JOIN {$prefix}product_shop ps
ON ps.id_product = p.id_product
AND ps.id_shop = :id_shop
LEFT JOIN {$prefix}stock_available sa
ON sa.id_product = p.id_product
AND sa.id_product_attribute = 0
AND (sa.id_shop = :id_shop OR sa.id_shop IS NULL)
LEFT JOIN {$prefix}manufacturer m
ON m.id_manufacturer = p.id_manufacturer
LEFT JOIN {$prefix}category_lang cl
ON cl.id_category = p.id_category_default
AND cl.id_lang = :id_lang
";
// ===== TRYB TESTOWY: tylko jeden produkt po id_product lub EAN =====
if ($testProductId || $testEan !== "")
{
if ($testEan !== "" && !$testProductId)
{
$stmtId = $pdo->prepare("SELECT id_product FROM {$prefix}product WHERE ean13 = :ean LIMIT 1");
$stmtId->execute([':ean' => $testEan]);
$foundId = (int)$stmtId->fetchColumn();
if ($foundId) $testProductId = $foundId;
}
if (!$testProductId)
{
fclose($fh);
die("Nie znaleziono produktu dla podanego EAN.\n");
}
echo "Tryb testowy eksport tylko produktu id_product={$testProductId}" . ($testEan ? " (EAN={$testEan})" : "") . "\n";
$sqlOne = $baseSelect . " WHERE p.id_product = :pid LIMIT 1";
$stmt = $pdo->prepare($sqlOne);
$stmt->bindValue(':id_lang', (int)$idLang, PDO::PARAM_INT);
$stmt->bindValue(':id_shop', (int)$idShop, PDO::PARAM_INT);
$stmt->bindValue(':pid', (int)$testProductId, PDO::PARAM_INT);
$stmt->execute();
$prod = $stmt->fetch(PDO::FETCH_ASSOC);
$stmt->closeCursor();
if ($prod)
{
$featuresMap = getProductFeatures($pdo, $prefix, $idLang, (int)$prod['id_product']);
$featuresStr = '';
if ($featuresMap)
{
$pairs = [];
foreach ($featuresMap as $k => $v) $pairs[] = trim($k) . ': ' . trim($v);
$featuresStr = implode(' | ', $pairs);
}
$combinations = getProductCombinations($pdo, $prefix, $idLang, $idShop, (int)$prod['id_product']);
writeProductRowsToCsv($fh, $prod, $featuresStr, $combinations, $delimiter);
echo "✅ Zapisano rekord(y) produktu testowego do CSV.\n";
}
else
{
echo "Brak produktu o id_product={$testProductId}.\n";
}
fclose($fh);
echo "✅ Zapisano CSV: {$outFile}\n";
exit;
}
// ===== PEŁNY EKSPORT (paginacja) =====
$sqlCount = "SELECT COUNT(*) FROM {$prefix}product";
$total = (int)$pdo->query($sqlCount)->fetchColumn();
echo "Znaleziono produktów: {$total}\n";
$limit = 1000;
$offset = 0;
while (true)
{
$sqlProducts = $baseSelect . " ORDER BY p.id_product ASC LIMIT :limit OFFSET :offset";
$stmt = $pdo->prepare($sqlProducts);
$stmt->bindValue(':id_lang', (int)$idLang, PDO::PARAM_INT);
$stmt->bindValue(':id_shop', (int)$idShop, PDO::PARAM_INT);
$stmt->bindValue(':limit', (int)$limit, PDO::PARAM_INT);
$stmt->bindValue(':offset', (int)$offset, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stmt->closeCursor();
if (!$rows) break;
foreach ($rows as $prod)
{
$idProduct = (int)$prod['id_product'];
$featuresMap = getProductFeatures($pdo, $prefix, $idLang, $idProduct);
$featuresStr = '';
if ($featuresMap)
{
$pairs = [];
foreach ($featuresMap as $k => $v) $pairs[] = trim($k) . ': ' . trim($v);
$featuresStr = implode(' | ', $pairs);
}
$combinations = getProductCombinations($pdo, $prefix, $idLang, $idShop, $idProduct);
writeProductRowsToCsv($fh, $prod, $featuresStr, $combinations, $delimiter);
}
$offset += $limit;
echo "Przetworzono: {$offset} / {$total}\n";
}
fclose($fh);
echo "✅ Zapisano CSV: {$outFile}\n";