Files
interblue.pl/modules/pshowimporter/classes/PShow_Combination_Generator.php
2024-10-25 14:16:28 +02:00

330 lines
12 KiB
PHP

<?php
/**
* File from http://PrestaShow.pl
*
* DISCLAIMER
* Do not edit or add to this file if you wish to upgrade this module to newer
* versions in the future.
*
* @authors PrestaShow.pl <kontakt@prestashow.pl>
* @copyright 2015 PrestaShow.pl
* @license http://PrestaShow.pl/license
*/
class PShow_Combination_Generator
{
private static $instance = null;
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new PShow_Combination_Generator();
}
return self::$instance;
}
/**
* Create product combinations
*
* @param array $list
* @return array
*/
protected function createCombinations($list)
{
if (count($list) <= 1) {
return count($list) ? array_map(create_function('$v', 'return (array($v));'), reset($list)) : $list;
}
$res = array();
$first = array_pop($list);
foreach ($first as $attribute) {
$tab = $this->createCombinations($list);
foreach ($tab as $to_add) {
$res[] = is_array($to_add) ? array_merge($to_add, array($attribute)) : array($to_add, $attribute);
}
}
return $res;
}
/**
* Set product combinations impact
*
* @param integer $id_product
* @param array $tab
* @return boolean
*/
protected function setAttributesImpacts($id_product, $tab)
{
$attributes = array();
foreach ($tab as $group) {
foreach ($group as $attribute) {
$price = preg_replace('/[^0-9.]/', '', str_replace(',', '.', 0)); //Tools::getValue('price_impact_' . (int) $attribute)));
$weight = preg_replace('/[^0-9.]/', '', str_replace(',', '.', 0)); //Tools::getValue('weight_impact_' . (int) $attribute)));
$attributes[] = '(' . (int) $id_product . ', ' . (int) $attribute . ', ' . (float) $price . ', ' . (float) $weight . ')';
}
}
return Db::getInstance()->execute('
INSERT INTO `' . _DB_PREFIX_ . 'attribute_impact` (`id_product`, `id_attribute`, `price`, `weight`)
VALUES ' . implode(',', $attributes) . '
ON DUPLICATE KEY UPDATE `price` = VALUES(price), `weight` = VALUES(weight)');
}
public function generateMultipleCombinations($combinations, $attributes, $product)
{
$res = true;
$default_on = 1;
foreach ($combinations as $key => $combination) {
$id_combination = (int) $product->productAttributeExists($attributes[$key], false, null, true, true);
$obj = new Combination($id_combination, null, PShow_Import::getInstance()->id_shop);
if ($id_combination) {
$obj->minimal_quantity = 1;
$obj->available_date = '0000-00-00';
}
foreach ($combination as $field => $value) {
if ($field == 'images') {
continue;
}
$obj->$field = $value;
}
$obj->default_on = $default_on;
$default_on = 0;
$product->setAvailableDate();
try {
$obj->save();
} catch (PrestaShopDatabaseException $e) {
$obj->default_on = false;
$obj->save();
}
$obj->setImages($combination['images']);
if (!$id_combination) {
$attribute_list = array();
foreach ($attributes[$key] as $id_attribute) {
$attribute_list[] = array(
'id_product_attribute' => (int) $obj->id,
'id_attribute' => (int) $id_attribute
);
}
$res &= Db::getInstance()->insert('product_attribute_combination', $attribute_list);
}
}
return $res;
}
public function setFirstCombinationAsDefault($id_product)
{
$id_product = (int) $id_product;
$q = 'UPDATE IGNORE `ps_product_attribute_shop` SET `default_on` = NULL WHERE `id_product` = ' . $id_product . ';
UPDATE IGNORE `ps_product_attribute` SET `default_on` = NULL WHERE `id_product` = ' . $id_product . ';
UPDATE IGNORE `ps_product_attribute_shop`
SET `default_on` = 1
WHERE `id_product` = ' . $id_product . '
AND `id_product_attribute` IN (
SELECT pa.`id_product_attribute`
FROM `ps_product_attribute` pa
JOIN `ps_product_attribute_combination` pac
ON (pac.`id_product_attribute` = pa.`id_product_attribute`)
ORDER BY pa.`id_product_attribute` ASC
);
UPDATE IGNORE `ps_product_attribute`
SET `default_on` = 1
WHERE `id_product` = ' . $id_product . '
AND `id_product_attribute` IN (
SELECT `id_product_attribute`
FROM `ps_product_attribute_shop`
WHERE `default_on` = 1
);';
Db::getInstance()->query($q);
}
/**
* Generate all possible combinations for product
*
* @param integer $id_product
*/
public function generateCombinationsForProduct($id_product)
{
if (PShow_Import::getInstance() && Module::getInstanceByName("pagecache")) {
PShow_Log::addImportLog(
"Disabling module: pagecache..." . (Module::disableByName("pagecache") ? 'success' : 'failed')
);
}
if (PShow_Import::getInstance()) {
PShow_Log::addImportLog(
"Generating all possible combinations for product id: " . $id_product
);
}
if (PShow_Import::getInstance()) {
PShow_Log::addImportLog(
"Getting all attributes from product..."
);
}
// get all product attributes
$q = "SELECT DISTINCT pac.`id_attribute`, a.`id_attribute_group` "
. "FROM `" . _DB_PREFIX_ . "product_attribute_combination` pac "
. "JOIN `" . _DB_PREFIX_ . "product_attribute` pa ON (pa.`id_product_attribute` = pac.`id_product_attribute`) "
. "JOIN `" . _DB_PREFIX_ . "attribute` a ON (a.`id_attribute` = pac.`id_attribute`) "
. "WHERE pa.`id_product` = " . (int) $id_product;
$attributes = Db::getInstance()->executeS($q);
// product don't have any combinations
if (!count($attributes)) {
if (PShow_Import::getInstance()) {
PShow_Log::addImportLog(
"Product don't have any attributes assigned... "
);
}
return;
}
if (PShow_Import::getInstance()) {
PShow_Log::addImportLog(
"Preparing attributes array..."
);
}
$tab = array();
foreach ($attributes as $k => $attribute) {
if (!isset($tab[$attribute['id_attribute_group']])) {
$tab[$attribute['id_attribute_group']] = array();
}
array_push($tab[$attribute['id_attribute_group']], $attribute['id_attribute']);
}
// product have only one group of attributes - module won't generate any new
if (count($tab) <= 1) {
if (PShow_Import::getInstance()) {
PShow_Log::addImportLog(
"Generating have only one group of attributes, skipping..."
);
}
$this->setFirstCombinationAsDefault($id_product);
return;
}
$product = new Product((int) $id_product, false, null, PShow_Import::getInstance()->id_shop);
if (PShow_Import::getInstance()) {
PShow_Log::addImportLog(
"Getting attributes impact..."
);
}
$this->setAttributesImpacts($id_product, $tab);
if (PShow_Import::getInstance()) {
PShow_Log::addImportLog(
"Preparing combinations..."
);
}
$combinations = array_values($this->createCombinations($tab));
$imagesToRemove = array();
$values = array();
foreach ($combinations as $attributes) {
if (PShow_Import::getInstance()) {
PShow_Log::addImportLog(
"Preparing combination values for attributes: " . implode(',', $attributes)
);
}
$images = array();
$q = "SELECT pai.`id_image`, pai.`id_product_attribute`
FROM `" . _DB_PREFIX_ . "product_attribute_image` pai
JOIN `" . _DB_PREFIX_ . "product_attribute` pa ON (pa.`id_product` = " . $id_product . " AND pa.`id_product_attribute` = pai.`id_product_attribute`)
WHERE pai.`id_product_attribute` IN (
SELECT pac.`id_product_attribute`
FROM `" . _DB_PREFIX_ . "product_attribute_combination` pac
WHERE (pac.`id_attribute` = " . implode(' OR pac.`id_attribute` = ', $attributes) . ") AND pac.`id_product_attribute` > 0
)";
$rows = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($q);
if (count($rows)) {
foreach ($rows as $row) {
$imagesToRemove[] = $row;
if (in_array((int) $row['id_image'], $images))
continue;
array_push($images, (int) $row['id_image']);
}
unset($rows);
}
$reference = uniqid($product->id . '-' . $product->reference . '-', false);
$values[] = array(
'id_product' => (int) $product->id,
'price' => (float) 0,
'weight' => (float) 0,
'ecotax' => 0,
'images' => $images,
'quantity' => (int) 0,
'reference' => $reference,
'default_on' => 0,
'available_date' => '0000-00-00'
);
}
if (PShow_Import::getInstance() && Module::getInstanceByName("pagecache")) {
PShow_Log::addImportLog(
"Enabling module: pagecache..." . (Module::enableByName("pagecache") ? 'success' : 'failed')
);
}
if (PShow_Import::getInstance()) {
PShow_Log::addImportLog(
"Removing current product combinations..."
);
}
// remove all existing product combinations
$product->deleteProductAttributes();
$q = "DELETE FROM `" . _DB_PREFIX_ . "product_attribute_image` "
. "WHERE `id_product_attribute` = 0; ";
$q .= "DELETE FROM `" . _DB_PREFIX_ . "product_attribute_image` "
. "WHERE `id_image` NOT IN (SELECT `id_image` FROM `" . _DB_PREFIX_ . "image`); ";
$q .= "DELETE FROM `" . _DB_PREFIX_ . "product_attribute_image` "
. "WHERE `id_product_attribute` NOT IN ("
. "SELECT `id_product_attribute` FROM `" . _DB_PREFIX_ . "product_attribute` WHERE `id_product` > 0"
. "); ";
foreach ($imagesToRemove as $img) {
$q .= "DELETE IGNORE FROM `" . _DB_PREFIX_ . "product_attribute_image` "
. "WHERE `id_product_attribute` = " . $img['id_product_attribute'] . " "
. "AND `id_image` = " . $img['id_image'] . "; ";
}
Db::getInstance()->query($q);
if (PShow_Import::getInstance()) {
PShow_Log::addImportLog(
"Generating new combinations..."
);
}
// generate combinations
$this->generateMultipleCombinations($values, $combinations, $product);
if (PShow_Import::getInstance()) {
PShow_Log::addImportLog(
"Setting first combination as default..."
);
}
$this->setFirstCombinationAsDefault($id_product);
}
}