330 lines
12 KiB
PHP
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);
|
|
}
|
|
}
|