From 194405bce0ceb5f263c9934c8a0d666ce7b629dd Mon Sep 17 00:00:00 2001 From: Jacek Pyziak Date: Thu, 5 Mar 2026 00:12:33 +0100 Subject: [PATCH] feat: update diagnostic scripts and configuration for improved product data handling --- .vscode/ftp-kr.sync.cache.json | 129 ++++++++++++++++++++++-- config/defines.inc.php | 2 +- diag_20792_tmp.php | 66 ++++++++++++ diag_fix_tmp.php | 1 + diag_upload_tmp.php | 127 +++++++++++++++++++++++ modules/omnibuseufree/omnibuseufree.php | 92 +++++++++++------ 6 files changed, 376 insertions(+), 41 deletions(-) create mode 100644 diag_20792_tmp.php create mode 100644 diag_fix_tmp.php create mode 100644 diag_upload_tmp.php diff --git a/.vscode/ftp-kr.sync.cache.json b/.vscode/ftp-kr.sync.cache.json index 49b9e57f..e3a6edaf 100644 --- a/.vscode/ftp-kr.sync.cache.json +++ b/.vscode/ftp-kr.sync.cache.json @@ -99,7 +99,7 @@ "parameters.php": { "type": "-", "size": 959, - "lmtime": 1772190614158, + "lmtime": 1772655199577, "modified": false }, "parameters.yml": { @@ -188,14 +188,109 @@ "modified": false }, "classes": {}, - ".claude": {}, + ".claude": { + "settings.local.json": { + "type": "-", + "size": 96, + "lmtime": 1772461611751, + "modified": false + } + }, "composer.lock": { "type": "-", "size": 429111, "lmtime": 0, "modified": false }, - "config": {}, + "config": { + "alias.php": { + "type": "-", + "size": 2057, + "lmtime": 0, + "modified": false + }, + "autoload.php": { + "type": "-", + "size": 1340, + "lmtime": 0, + "modified": false + }, + "bootstrap.php": { + "type": "-", + "size": 6171, + "lmtime": 0, + "modified": false + }, + "config.inc.php": { + "type": "-", + "size": 11693, + "lmtime": 0, + "modified": false + }, + "db_slave_server.inc.php": { + "type": "-", + "size": 1337, + "lmtime": 0, + "modified": false + }, + "defines.inc.php": { + "type": "-", + "size": 8109, + "lmtime": 1772655759173, + "modified": false + }, + "defines_uri.inc.php": { + "type": "-", + "size": 3237, + "lmtime": 0, + "modified": false + }, + ".htaccess": { + "type": "-", + "size": 170, + "lmtime": 0, + "modified": false + }, + "index.php": { + "type": "-", + "size": 1369, + "lmtime": 0, + "modified": false + }, + "services": {}, + "settings.inc.php": { + "type": "-", + "size": 24, + "lmtime": 0, + "modified": false + }, + "smartyadmin.config.inc.php": { + "type": "-", + "size": 5934, + "lmtime": 0, + "modified": false + }, + "smarty.config.inc.php": { + "type": "-", + "size": 6750, + "lmtime": 0, + "modified": false + }, + "smartyfront.config.inc.php": { + "type": "-", + "size": 8867, + "lmtime": 0, + "modified": false + }, + "smartyfront.config.inc.php.before_pagecache_widget_block": { + "type": "-", + "size": 8488, + "lmtime": 0, + "modified": false + }, + "themes": {}, + "xml": {} + }, "controllers": {}, "cron-estella.php": { "type": "-", @@ -209,6 +304,18 @@ "lmtime": 0, "modified": false }, + "diag_fix_tmp.php": { + "type": "-", + "size": 14, + "lmtime": 1772659558751, + "modified": false + }, + "diag_upload_tmp.php": { + "type": "-", + "size": 4362, + "lmtime": 1772663092528, + "modified": false + }, "docs": {}, "download": {}, "error500.html": { @@ -279,9 +386,9 @@ }, ".htaccess": { "type": "-", - "size": 18466, - "lmtime": 0, - "modified": true + "size": 18985, + "lmtime": 1772451998229, + "modified": false }, ".htaccess.2025-01-27-1738009656": { "type": "-", @@ -436,6 +543,12 @@ "modified": false }, "config": {}, + "config_pl.xml": { + "type": "-", + "size": 648, + "lmtime": 0, + "modified": false + }, "config.xml": { "type": "-", "size": 430, @@ -463,8 +576,8 @@ }, "omnibuseufree.php": { "type": "-", - "size": 37153, - "lmtime": 1768471196653, + "size": 40041, + "lmtime": 1772663159729, "modified": false }, "Readme.md": { diff --git a/config/defines.inc.php b/config/defines.inc.php index 0ca8c162..156df347 100644 --- a/config/defines.inc.php +++ b/config/defines.inc.php @@ -26,7 +26,7 @@ /* Debug only */ if (!defined('_PS_MODE_DEV_')) { - if ( $_SERVER['REMOTE_ADDR'] == '91.189.216.43' ) + if ( $_SERVER['REMOTE_ADDR'] == '79.191.197.145' ) define('_PS_MODE_DEV_', false); else define('_PS_MODE_DEV_', false ); diff --git a/diag_20792_tmp.php b/diag_20792_tmp.php new file mode 100644 index 00000000..2626b5a8 --- /dev/null +++ b/diag_20792_tmp.php @@ -0,0 +1,66 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +$prefix = $p['database_prefix']; +$id = 20792; + +echo "
\n";
+
+// Ile wierszy omnibus dla tego produktu
+echo "=== omnibus_eu_free dla produktu $id ===\n";
+$cnt = $pdo->query("SELECT COUNT(*) FROM {$prefix}omnibus_eu_free WHERE id_product = $id")->fetchColumn();
+echo "Laczna liczba wierszy: $cnt\n";
+
+$cnt_all = $pdo->query("SELECT COUNT(*) FROM {$prefix}omnibus_eu_free")->fetchColumn();
+echo "Cala tabela: $cnt_all wierszy\n\n";
+
+echo "=== Wierszy na kombinacje (top 10) ===\n";
+$stmt = $pdo->query("SELECT id_product_attribute, COUNT(*) AS ile FROM {$prefix}omnibus_eu_free WHERE id_product = $id GROUP BY id_product_attribute ORDER BY ile DESC LIMIT 10");
+foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) echo json_encode($row) . "\n";
+
+// Czas zapytania SELECT * dla tego produktu
+echo "\n=== Czas SELECT * omnibus dla produktu (ms) ===\n";
+$start = microtime(true);
+$rows = $pdo->query("SELECT * FROM {$prefix}omnibus_eu_free WHERE id_product = $id ORDER BY id_omnibuseufree DESC")->fetchAll();
+echo round((microtime(true) - $start) * 1000, 2) . " ms, pobranych: " . count($rows) . " wierszy\n";
+
+// Duplikaty hookow
+echo "\n=== Duplikaty hook registracji ===\n";
+$stmt = $pdo->query("SELECT m.name, COUNT(*) AS rejestracji
+    FROM {$prefix}module m
+    JOIN {$prefix}hook_module hm ON m.id_module = hm.id_module
+    JOIN {$prefix}hook h ON hm.id_hook = h.id_hook
+    WHERE h.name = 'displayAdminProductsExtra'
+    GROUP BY m.name
+    HAVING rejestracji > 1");
+$dups = $stmt->fetchAll(PDO::FETCH_ASSOC);
+if (empty($dups)) {
+    echo "Brak duplikatow\n";
+} else {
+    foreach ($dups as $row) echo json_encode($row) . "\n";
+}
+
+// PHP config
+echo "\n=== PHP limits ===\n";
+echo "max_execution_time: " . ini_get('max_execution_time') . "s\n";
+echo "memory_limit: " . ini_get('memory_limit') . "\n";
+
+// gm_omniprice_history dla tego produktu
+echo "\n=== gm_omniprice_history dla produktu $id ===\n";
+$cnt2 = $pdo->query("SELECT COUNT(*) FROM {$prefix}gm_omniprice_history WHERE id_product = $id")->fetchColumn();
+echo "Wierszy: $cnt2\n";
+
+echo "
"; +echo "

PAMIETAJ: usun ten plik po diagnostyce!

"; diff --git a/diag_fix_tmp.php b/diag_fix_tmp.php new file mode 100644 index 00000000..36bfa89d --- /dev/null +++ b/diag_fix_tmp.php @@ -0,0 +1 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +$prefix = $p['database_prefix']; +$id = 20792; + +echo "
\n";
+
+// Product rows
+$cnt = $pdo->query("SELECT COUNT(*) FROM {$prefix}omnibus_eu_free WHERE id_product = $id")->fetchColumn();
+echo "=== Produkt $id: $cnt wierszy ===\n";
+
+// Table structure
+echo "\n=== Kolumny tabeli ===\n";
+$stmt = $pdo->query("DESCRIBE {$prefix}omnibus_eu_free");
+foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
+    echo "{$row['Field']} ({$row['Type']})\n";
+}
+
+// Combinations
+$combCount = $pdo->query("SELECT COUNT(*) FROM {$prefix}product_attribute WHERE id_product = $id")->fetchColumn();
+echo "\n=== Kombinacje: $combCount ===\n";
+
+// SELECT speed
+$start = microtime(true);
+$pdo->query("SELECT * FROM {$prefix}omnibus_eu_free WHERE id_product = $id AND is_last = 1")->fetchAll();
+echo "SELECT is_last=1: " . round((microtime(true) - $start) * 1000, 1) . " ms\n";
+
+// All action hooks with modules
+echo "\n=== actionProductAttributeUpdate ===\n";
+$stmt = $pdo->query("
+    SELECT m.name, hm.position
+    FROM {$prefix}hook h
+    JOIN {$prefix}hook_module hm ON h.id_hook = hm.id_hook
+    JOIN {$prefix}module m ON hm.id_module = m.id_module AND m.active = 1
+    WHERE h.name = 'actionProductAttributeUpdate'
+    ORDER BY hm.position
+");
+foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
+    echo "  {$row['name']} (pos {$row['position']})\n";
+}
+
+echo "\n=== actionProductUpdate ===\n";
+$stmt = $pdo->query("
+    SELECT m.name, hm.position
+    FROM {$prefix}hook h
+    JOIN {$prefix}hook_module hm ON h.id_hook = hm.id_hook
+    JOIN {$prefix}module m ON hm.id_module = m.id_module AND m.active = 1
+    WHERE h.name = 'actionProductUpdate'
+    ORDER BY hm.position
+");
+foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
+    echo "  {$row['name']} (pos {$row['position']})\n";
+}
+
+echo "\n=== actionProductSave ===\n";
+$stmt = $pdo->query("
+    SELECT m.name, hm.position
+    FROM {$prefix}hook h
+    JOIN {$prefix}hook_module hm ON h.id_hook = hm.id_hook
+    JOIN {$prefix}module m ON hm.id_module = m.id_module AND m.active = 1
+    WHERE h.name = 'actionProductSave'
+    ORDER BY hm.position
+");
+foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
+    echo "  {$row['name']} (pos {$row['position']})\n";
+}
+
+echo "\n=== actionObjectProductUpdateAfter ===\n";
+$stmt = $pdo->query("
+    SELECT m.name, hm.position
+    FROM {$prefix}hook h
+    JOIN {$prefix}hook_module hm ON h.id_hook = hm.id_hook
+    JOIN {$prefix}module m ON hm.id_module = m.id_module AND m.active = 1
+    WHERE h.name = 'actionObjectProductUpdateAfter'
+    ORDER BY hm.position
+");
+foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
+    echo "  {$row['name']} (pos {$row['position']})\n";
+}
+
+// How many times does actionProductAttributeUpdate fire?
+echo "\n=== Ile razy odpala sie actionProductAttributeUpdate ===\n";
+echo "Raz na kazda kombinacje = $combCount razy!\n";
+echo "Kazdy modul na tym hooku odpala sie $combCount razy.\n";
+
+// Check gm_omniprice module
+echo "\n=== gm_omniprice hooki ===\n";
+$stmt = $pdo->query("
+    SELECT h.name, hm.position
+    FROM {$prefix}hook h
+    JOIN {$prefix}hook_module hm ON h.id_hook = hm.id_hook
+    JOIN {$prefix}module m ON hm.id_module = m.id_module
+    WHERE m.name = 'gm_omniprice'
+    ORDER BY h.name
+");
+foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
+    echo "  {$row['name']} (pos {$row['position']})\n";
+}
+
+// Check creativeelements module hooks
+echo "\n=== creativeelements hooki actionProduct* ===\n";
+$stmt = $pdo->query("
+    SELECT h.name, hm.position
+    FROM {$prefix}hook h
+    JOIN {$prefix}hook_module hm ON h.id_hook = hm.id_hook
+    JOIN {$prefix}module m ON hm.id_module = m.id_module
+    WHERE m.name = 'creativeelements' AND h.name LIKE 'action%'
+    ORDER BY h.name
+");
+foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
+    echo "  {$row['name']} (pos {$row['position']})\n";
+}
+
+echo "
\n"; diff --git a/modules/omnibuseufree/omnibuseufree.php b/modules/omnibuseufree/omnibuseufree.php index 3bb07ed3..53f03b71 100644 --- a/modules/omnibuseufree/omnibuseufree.php +++ b/modules/omnibuseufree/omnibuseufree.php @@ -48,6 +48,7 @@ class OmnibusEuFree extends Module Configuration::updateValue('OMNIBUSEUFREE_DISPLAY_PRODUCT_PRICE_BLOCK', 1); Configuration::updateValue('OMNIBUSEUFREE_CRON_STATUS', 2); Configuration::updateValue('OMNIBUSEUFREE_DAYS', 30); + Configuration::updateValue('OMNIBUSEUFREE_HISTORY_DAYS', 60); include(dirname(__FILE__) . '/sql/install.php'); @@ -68,6 +69,7 @@ class OmnibusEuFree extends Module Configuration::deleteByName('OMNIBUSEUFREE_DISPLAY_PRODUCT_PRICE_BLOCK'); Configuration::deleteByName('OMNIBUSEUFREE_CRON_STATUS'); Configuration::deleteByName('OMNIBUSEUFREE_DAYS'); + Configuration::deleteByName('OMNIBUSEUFREE_HISTORY_DAYS'); include(dirname(__FILE__) . '/sql/uninstall.php'); @@ -287,6 +289,9 @@ class OmnibusEuFree extends Module public function hookDisplayAdminProductsExtra($params) { $OmnibusData = array(); + $product = new Product((int) $params['id_product']); + $hasCombinations = $product->hasCombinations(); + $nameCache = array(); foreach ($this->getOmnibusData($params['id_product']) as $rowId => $rowValue) { $OmnibusData[$rowId]['price_locale'] = ''; @@ -301,9 +306,14 @@ class OmnibusEuFree extends Module $OmnibusData[$rowId]['currency_iso_code'] = $currency->iso_code; } elseif ($key == 'id_product_attribute') { - $product = new Product($params['id_product']); - $OmnibusData[$rowId]['name'] = $product->getProductName($params['id_product'], $value); - ($product->hasCombinations() && $value == 0) ? $OmnibusData[$rowId]['name'] .= ' ' . $this->l('(default combination)') : ''; + $attrId = (int) $value; + if (!isset($nameCache[$attrId])) { + $nameCache[$attrId] = $product->getProductName((int) $params['id_product'], $attrId); + if ($hasCombinations && $attrId === 0) { + $nameCache[$attrId] .= ' ' . $this->l('(default combination)'); + } + } + $OmnibusData[$rowId]['name'] = $nameCache[$attrId]; } elseif ($key == 'is_last' && $value == 1) { $OmnibusData[$rowId]['is_last_icon'] = 'done'; @@ -334,10 +344,18 @@ class OmnibusEuFree extends Module public function hookActionProductSave($hook_params) { if (Module::isEnabled('omnibuseufree')) { - Product::flushPriceCache(); + $id_product = (int) $hook_params['id_product']; - $this->addProductPriceWithCombinations($hook_params['id_product']); - $this->addProductPrice($hook_params['id_product']); + $combinationCount = (int) Db::getInstance()->getValue( + 'SELECT COUNT(*) FROM `' . _DB_PREFIX_ . 'product_attribute` WHERE `id_product` = ' . $id_product + ); + + Product::flushPriceCache(); + $this->addProductPrice($id_product); + + if ($combinationCount <= 30) { + $this->addProductPriceWithCombinations($id_product); + } } } @@ -345,10 +363,21 @@ class OmnibusEuFree extends Module { if (Module::isEnabled('omnibuseufree')) { $id_product = (int) Tools::getValue('id_product'); - Product::flushPriceCache(); - $this->addProductPriceWithCombinations($id_product); + $combinationCount = (int) Db::getInstance()->getValue( + 'SELECT COUNT(*) FROM `' . _DB_PREFIX_ . 'product_attribute` WHERE `id_product` = ' . $id_product + ); + + // Skip entirely for products with many combinations. + // hookActionProductSave already handles base price recording. + // This hook fires once PER combination (168x), so running here is wasteful. + if ($combinationCount > 30) { + return; + } + + Product::flushPriceCache(); $this->addProductPrice($id_product); + $this->addProductPriceWithCombinations($id_product); } } @@ -473,11 +502,21 @@ class OmnibusEuFree extends Module array( 'type' => 'text', 'label' => $this->l('Number of days'), + 'desc' => $this->l('Number of days for front-end lowest price display (Omnibus Directive).'), 'name' => 'OMNIBUSEUFREE_DAYS', 'class' => 'omnibus-input-days', 'maxlength' => '3', 'required' => true ), + array( + 'type' => 'text', + 'label' => $this->l('History retention (days)'), + 'desc' => $this->l('How many days of price history to keep and display in admin. Older entries (except current price) will be deleted by CRON.'), + 'name' => 'OMNIBUSEUFREE_HISTORY_DAYS', + 'class' => 'omnibus-input-days', + 'maxlength' => '4', + 'required' => true + ), array( 'type' => 'switch', 'label' => $this->l('Display on product page'), @@ -539,7 +578,8 @@ class OmnibusEuFree extends Module 'OMNIBUSEUFREE_INFORMATION_VERSION' => Configuration::get('OMNIBUSEUFREE_INFORMATION_VERSION', null, null, null, 2), 'OMNIBUSEUFREE_DISPLAY_PRODUCT_PRICE_BLOCK' => Configuration::get('OMNIBUSEUFREE_DISPLAY_PRODUCT_PRICE_BLOCK', null, null, null, 1), 'OMNIBUSEUFREE_CRON_STATUS' => Configuration::get('OMNIBUSEUFREE_CRON_STATUS', null, null, null, 2), - 'OMNIBUSEUFREE_DAYS' => Configuration::get('OMNIBUSEUFREE_DAYS', null, null, null, 30) + 'OMNIBUSEUFREE_DAYS' => Configuration::get('OMNIBUSEUFREE_DAYS', null, null, null, 30), + 'OMNIBUSEUFREE_HISTORY_DAYS' => Configuration::get('OMNIBUSEUFREE_HISTORY_DAYS', null, null, null, 60) ); } @@ -556,6 +596,7 @@ class OmnibusEuFree extends Module Configuration::updateValue('OMNIBUSEUFREE_DISPLAY_PRODUCT_PRICE_BLOCK', (int) Tools::getValue('OMNIBUSEUFREE_DISPLAY_PRODUCT_PRICE_BLOCK')); Configuration::updateValue('OMNIBUSEUFREE_CRON_STATUS', (int) Tools::getValue('OMNIBUSEUFREE_CRON_STATUS')); Configuration::updateValue('OMNIBUSEUFREE_DAYS', (int) Tools::getValue('OMNIBUSEUFREE_DAYS')); + Configuration::updateValue('OMNIBUSEUFREE_HISTORY_DAYS', max(1, (int) Tools::getValue('OMNIBUSEUFREE_HISTORY_DAYS'))); $confirmation = $this->l('The settings have been updated.'); @@ -886,10 +927,13 @@ class OmnibusEuFree extends Module throw new Exception('Missing parameter: $id_product'); } + $historyDays = (int) Configuration::get('OMNIBUSEUFREE_HISTORY_DAYS', null, null, null, 60); + $sql = new DbQuery(); $sql->select('*'); $sql->from('omnibus_eu_free'); $sql->where('id_product = ' . (int) $id_product); + $sql->where('(`is_last` = 1 OR `date_add` >= DATE_SUB(NOW(), INTERVAL ' . $historyDays . ' DAY))'); $sql->orderBy('is_default_currency DESC'); $sql->orderBy('id_currency ASC'); $sql->orderBy('id_product_attribute ASC'); @@ -923,30 +967,14 @@ class OmnibusEuFree extends Module public function removeOldDataFromOmnibusTable() { - $NumberOfDays = (int) Configuration::get('OMNIBUSEUFREE_DAYS', null, null, null, 30); - $NumberOfDays = 90; + $numberOfDays = (int) Configuration::get('OMNIBUSEUFREE_HISTORY_DAYS', null, null, null, 60); - $date = new DateTime(); - $date->modify('-' . $NumberOfDays . ' days'); - $CutOffDate = $date->format('U'); - $counter = 0; + Db::getInstance()->execute( + 'DELETE FROM `' . _DB_PREFIX_ . 'omnibus_eu_free` + WHERE `is_last` = 0 + AND `date_add` < DATE_SUB(NOW(), INTERVAL ' . $numberOfDays . ' DAY)' + ); - $sql = new DbQuery(); - $sql->select('id_omnibuseufree, date_add'); - $sql->from('omnibus_eu_free'); - $sql->where('is_last = 0'); - $result = Db::getInstance()->executeS($sql); - - foreach ($result as $row) { - $date = new DateTime($row['date_add']); - $DatabaseDate = $date->format('U'); - - if ($DatabaseDate < $CutOffDate) { - Db::getInstance()->delete('omnibus_eu_free', '`id_omnibuseufree` = ' . (int) $row['id_omnibuseufree']); - $counter++; - } - } - - return $counter; + return (int) Db::getInstance()->Affected_Rows(); } }