975 lines
34 KiB
PHP
975 lines
34 KiB
PHP
<?php
|
|
|
|
class stTaskSchedulerImportProductUtility
|
|
{
|
|
/**
|
|
*
|
|
* @var stFileDownloader
|
|
*/
|
|
protected $downloader;
|
|
|
|
/**
|
|
*
|
|
* @var stTaskSchedulerImportBaseAbstract
|
|
*/
|
|
protected $import;
|
|
|
|
/**
|
|
*
|
|
* @var stTaskLoggerInterface
|
|
*/
|
|
protected $logger;
|
|
|
|
/**
|
|
*
|
|
* @var stTaskSchedulerImportCategoryMapping|null
|
|
*/
|
|
protected $currentMapping = null;
|
|
|
|
public function __construct(stTaskSchedulerImportBaseAbstract $import)
|
|
{
|
|
$this->downloader = new stFileDownloader();
|
|
$this->logger = $import->getLogger();
|
|
$this->import = $import;
|
|
}
|
|
|
|
/**
|
|
* Zwraca instancje klasy do pobierania plików
|
|
*
|
|
* @return stFileDownloader
|
|
*/
|
|
public function getFileDownloader(): stFileDownloader
|
|
{
|
|
return $this->downloader;
|
|
}
|
|
|
|
/**
|
|
* Zwraca utworzony produkt
|
|
*
|
|
* @param string $code Kod produktu
|
|
* @param string $culture Opcjonalna wersja językowa (domyślnie brany jest domyślny język dla panelu administracyjnego)
|
|
* @return Product |null
|
|
* @throws PropelException
|
|
*/
|
|
public function getProduct(string $code, ?string $culture = null): ?Product
|
|
{
|
|
$code = $this->addProductCodePrefix($code);
|
|
$product = ProductPeer::retrieveByCode($code);
|
|
|
|
if (null !== $product)
|
|
{
|
|
$product->setCulture(null !== $culture ? $culture : stLanguage::getOptLanguage());
|
|
}
|
|
|
|
if (null !== $product)
|
|
{
|
|
$taskSchedulerImportProduct = stTaskSchedulerImportProductPeer::retrieveByProduct($product, $this->import);
|
|
|
|
if (null === $taskSchedulerImportProduct)
|
|
{
|
|
$taskSchedulerImportProduct = stTaskSchedulerImportProductPeer::create($product, $this->import);
|
|
}
|
|
|
|
$taskSchedulerImportProduct->setAvailable(true);
|
|
|
|
if (!$taskSchedulerImportProduct->isNew() && $taskSchedulerImportProduct->isColumnModified(stTaskSchedulerImportProductPeer::AVAILABLE))
|
|
{
|
|
if ($this->import->getConfigurationParameter('withdraw_availability') == 'set_availability')
|
|
{
|
|
$product->setAvailabilityId($this->import->getConfigurationParameter('default_availability'));
|
|
}
|
|
|
|
if (!$product->getActive())
|
|
{
|
|
$product->setActive($this->import->getConfigurationParameter('default_product_status', true));
|
|
}
|
|
}
|
|
}
|
|
|
|
return $product;
|
|
}
|
|
|
|
/**
|
|
* Zwraca utworzony lub tworzy i zwraca nową instancję produktu
|
|
*
|
|
* @param string $code Kod produktu
|
|
* @param string $culture Opcjonalna wersja językowa (domyślnie brany jest domyślny język dla panelu administracyjnego)
|
|
* @return Product
|
|
* @throws PropelException
|
|
*/
|
|
public function getOrCreateProduct(string $code, ?string $culture = null): Product
|
|
{
|
|
$product = $this->getProduct($code, $culture);
|
|
|
|
if (null === $product)
|
|
{
|
|
$product = new Product();
|
|
$product->setTax(stTax::getDefault());
|
|
$product->setActive($this->import->getConfigurationParameter('default_product_status', true));
|
|
$limits = stLimits::getInstance();
|
|
|
|
try
|
|
{
|
|
$limits->checkLimits($product);
|
|
}
|
|
catch (stLimitsException $e)
|
|
{
|
|
throw new stTaskSchedulerImportLogException("Limit produktów został przekroczony (maks. **%%limit%%**). Produkt o kodzie **%%code%%** nie został dodany.", stTaskLogger::TYPE_ERROR, [
|
|
'%%limit%%' => $limits->getLimit(Product::class),
|
|
'%%code%%' => $code,
|
|
]);
|
|
}
|
|
|
|
$product->setCulture(null !== $culture ? $culture : stLanguage::getOptLanguage());
|
|
$product->setCode($this->addProductCodePrefix($code));
|
|
$product->setAvailabilityId($this->import->getConfigurationParameter('default_availability'));
|
|
stTaskSchedulerImportProductPeer::create($product, $this->import);
|
|
}
|
|
|
|
return $product;
|
|
}
|
|
|
|
/**
|
|
* Zwraca cena + marża
|
|
*
|
|
* @param string $price Cena
|
|
* @return string Cena + marża
|
|
*/
|
|
public function applyPriceMargin($price)
|
|
{
|
|
if (empty($price))
|
|
{
|
|
return $price;
|
|
}
|
|
|
|
$price = strval($price);
|
|
|
|
if ($price[0] == '-' || $price[0] == '+' || substr($price, -1) == '%')
|
|
{
|
|
return $price;
|
|
}
|
|
|
|
if ($this->import->getConfiguration()->getOption('version') > 1 && null !== $this->currentMapping && $this->currentMapping->hasPriceMargin())
|
|
{
|
|
return $this->currentMapping->applyPriceMargin($price);
|
|
}
|
|
|
|
$priceMargin = $this->import->getConfigurationParameter('price_margin', [
|
|
'value' => 0,
|
|
'type' => stPrice::PRICE_MARGIN_PERCENT,
|
|
]);
|
|
|
|
$price = stPrice::applyPriceMargin($price, $priceMargin['value'], $priceMargin['type']);
|
|
|
|
$price = $this->applyPriceArray($price);
|
|
|
|
return $price;
|
|
}
|
|
|
|
public function addProductCodePrefix($code)
|
|
{
|
|
$prefix = $this->import->getConfigurationParameter('code_prefix');
|
|
|
|
return $prefix.$code;
|
|
}
|
|
|
|
/**
|
|
* Dodaje zdjęcie do produktu
|
|
*
|
|
* @param Product $product
|
|
* @param string $url
|
|
* @param bool $default
|
|
* @param null|string $filename
|
|
* @return sfAsset|null
|
|
* @throws Exception
|
|
* @throws PropelException
|
|
*/
|
|
public function addImageFromUrl(Product $product, string $url, $default = false, ?string $filename = null): ?sfAsset
|
|
{
|
|
$asset = null;
|
|
|
|
if ($product->isNew())
|
|
{
|
|
throw new Exception("To add images product must be saved first");
|
|
}
|
|
|
|
try
|
|
{
|
|
$this->downloader->download($url, function(stFileDownloaderFile $file) use ($product, $url, $filename, $default, &$asset) {
|
|
if (null === $filename)
|
|
{
|
|
$matches = null;
|
|
|
|
if (preg_match('#([a-z0-9-_]+).(jpeg|jpg|gif|png)#', $url, $matches))
|
|
{
|
|
$filename = $matches[0];
|
|
}
|
|
else
|
|
{
|
|
$filename = basename($file) . '.' . $file->getExtension();
|
|
}
|
|
}
|
|
|
|
$pha = new ProductHasSfAsset();
|
|
$pha->setProductId($product->getId());
|
|
$pha->createAsset($filename, $file, ProductHasSfAssetPeer::IMAGE_FOLDER);
|
|
$pha->setIsDefault($default);
|
|
$pha->save();
|
|
|
|
$asset = $pha->getsfAsset();
|
|
});
|
|
}
|
|
catch (stFileDownloaderException $e)
|
|
{
|
|
$this->logger->error('Wystąpił błąd `%error%` podczas pobierania zdjęcia <%image%> dla produktu **%product%**', array(
|
|
'%error%' => $e->getMessage(),
|
|
'%image%' => $url,
|
|
'%product%' => $product->getName()
|
|
));
|
|
}
|
|
|
|
return $asset;
|
|
}
|
|
|
|
/**
|
|
* Dodaje dostępność do produktu
|
|
*
|
|
* @param Product $product Produkt
|
|
* @param string $name Nazwa dostępności
|
|
* @param bool $create
|
|
* @return Availability
|
|
* @throws PropelException
|
|
*/
|
|
public function addAvailability(Product $product, string $name, bool $create = true): Availability
|
|
{
|
|
$availability = AvailabilityPeer::retrieveByName($name);
|
|
|
|
|
|
if (null === $availability)
|
|
{
|
|
if ($create)
|
|
{
|
|
$availability = new Availability();
|
|
$availability->setCulture($product->getCulture());
|
|
$availability->setAvailabilityName($name);
|
|
}
|
|
else
|
|
{
|
|
$this->import->getLogger()->warning('Dostepność o nazwie *%name%* nie istnieje, dlatego nie została dodana dla produktu *%product%*', [
|
|
'%name%' => $name,
|
|
'%product%' => $this->getProductName($product),
|
|
]);
|
|
}
|
|
}
|
|
|
|
$product->setAvailability($availability);
|
|
|
|
return $availability;
|
|
}
|
|
|
|
/**
|
|
* Dodaje producenta do produktu
|
|
*
|
|
* @param Product $product
|
|
* @param string $name
|
|
* @param bool $create
|
|
* @return Producer
|
|
* @throws PropelException
|
|
*/
|
|
public function addProducer(Product $product, string $name, bool $create = true): Producer
|
|
{
|
|
$producer = ProducerPeer::retrieveByName($name);
|
|
|
|
if (null === $producer)
|
|
{
|
|
if ($create)
|
|
{
|
|
$producer = new Producer();
|
|
$producer->setCulture($product->getCulture());
|
|
$producer->setName($name);
|
|
}
|
|
else
|
|
{
|
|
$this->import->getLogger()->warning('Producent o nazwie *%name%* nie istnieje, dlatego nie został dodany dla produktu *%product%*', [
|
|
'%name%' => $name,
|
|
'%product%' => $this->getProductName($product),
|
|
]);
|
|
}
|
|
}
|
|
|
|
$product->setProducer($producer);
|
|
|
|
return $producer;
|
|
}
|
|
|
|
/**
|
|
* Dodaje atrybuty do produktu
|
|
*
|
|
* @param Product $product
|
|
* @param Category $category
|
|
* @param array $attributes
|
|
* @return void
|
|
* @throws PropelException
|
|
* @throws SQLException
|
|
*/
|
|
public function addAttributes(Product $product, array $attributes)
|
|
{
|
|
if ($product->isNew())
|
|
{
|
|
throw new Exception("To add attributes product must be saved first");
|
|
}
|
|
|
|
$c = new Criteria();
|
|
$c->add(appProductAttributeVariantHasProductPeer::PRODUCT_ID, $product->getId());
|
|
appProductAttributeVariantHasProductPeer::doDelete($c);
|
|
|
|
$category = $product->getDefaultCategory();
|
|
$culture = $product->getCulture();
|
|
|
|
foreach ($attributes as $name => $data)
|
|
{
|
|
$values = $data['values'];
|
|
$attribute = $this->getOrCreateAttribute($name, isset($data['type']) ? strtoupper($data['type']) : 'T', $culture);
|
|
|
|
if ($category)
|
|
{
|
|
$c = new Criteria();
|
|
$c->add(appProductAttributeHasCategoryPeer::CATEGORY_ID, $category->getId());
|
|
$c->add(appProductAttributeHasCategoryPeer::ATTRIBUTE_ID, $attribute->getId());
|
|
|
|
if (!appProductAttributeHasCategoryPeer::doCount($c))
|
|
{
|
|
$pahc = new appProductAttributeHasCategory();
|
|
$pahc->setAttributeId($attribute->getId());
|
|
$pahc->setCategoryId($category->getId());
|
|
$pahc->save();
|
|
}
|
|
|
|
}
|
|
|
|
if (empty($values))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* @var appProductAttributeVariant[]
|
|
*/
|
|
$variants = [];
|
|
|
|
$c = new Criteria();
|
|
$c->addJoin(appProductAttributeVariantPeer::ID, appProductAttributeHasVariantPeer::VARIANT_ID);
|
|
|
|
if ($attribute->getType() == 'C')
|
|
{
|
|
$c->add(appProductAttributeVariantPeer::OPT_NAME, array_keys($values), Criteria::IN);
|
|
}
|
|
else
|
|
{
|
|
$c->add(appProductAttributeVariantPeer::OPT_VALUE, array_keys($values), Criteria::IN);
|
|
}
|
|
|
|
$c->add(appProductAttributeHasVariantPeer::ATTRIBUTE_ID, $attribute->getId());
|
|
|
|
foreach (appProductAttributeVariantPeer::doSelect($c) as $variant)
|
|
{
|
|
$name = $attribute->getType() == 'C' ? $variant->getOptName() : $variant->getOptValue();
|
|
$variants[$name] = $variant;
|
|
}
|
|
|
|
foreach ($values as $name => $params)
|
|
{
|
|
if (!isset($variants[$name]))
|
|
{
|
|
$v = new appProductAttributeVariant();
|
|
$v->setCulture($culture);
|
|
|
|
$ahv = new appProductAttributeHasVariant();
|
|
$ahv->setAttributeId($attribute->getId());
|
|
$v->addappProductAttributeHasVariant($ahv);
|
|
|
|
if ($attribute->getType() == 'C')
|
|
{
|
|
$v->setType($params['color'][0] == '#' ? appProductAttributeVariantPeer::COLOR_TYPE : appProductAttributeVariantPeer::PICTURE_TYPE);
|
|
$v->setName($name);
|
|
|
|
if (isset($params['color']))
|
|
{
|
|
if ($v->getType() == appProductAttributeVariantPeer::COLOR_TYPE)
|
|
{
|
|
$v->setColor(ltrim($params['color'], '#'));
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
$url = $params['color'];
|
|
|
|
$this->downloader->download($url, function(stFileDownloaderFile $file) use ($v, $attribute, $product, $url) {
|
|
$filename = uniqid().'.'.$file->getExtension();
|
|
$v->setPicture($filename);
|
|
|
|
if (!is_dir($v->getUploadDir(true)))
|
|
{
|
|
mkdir($v->getUploadDir(true), 0755, true);
|
|
}
|
|
|
|
$target = $v->getPicturePath(true);
|
|
|
|
if (!$file->move($target))
|
|
{
|
|
throw new stTaskSchedulerImportLogException("Wystąpił błąd podczas zapisu zdjęcia <%image%> do lokalizacji **%target%** dla atrybutu **%attr%** produktu **%product%**", stTaskLogger::TYPE_ERROR, [
|
|
'%attr%' => $attribute->getName(). '.' . $v->getName(),
|
|
'%image%' => $url,
|
|
'%target%' => $target,
|
|
'%product%' => $this->getProductName($product),
|
|
]);
|
|
}
|
|
});
|
|
}
|
|
catch (stFileDownloaderException $e)
|
|
{
|
|
throw new stTaskSchedulerImportLogException('Wystąpił błąd `%error%` podczas pobierania zdjęcia <%image%> dla atrybutu **%attr%** dla produktu **%product%**', stTaskLogger::TYPE_ERROR, [
|
|
'%error%' => $e->getMessage(),
|
|
'%attr%' => $attribute->getName(). '.' . $v->getName(),
|
|
'%image%' => $params['color'],
|
|
'%product%' => $this->getProductName($product),
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
elseif ($attribute->getType() == 'B')
|
|
{
|
|
$v->setValue('');
|
|
}
|
|
else
|
|
{
|
|
$v->setValue($name);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$v = $variants[$name];
|
|
}
|
|
|
|
if ($attribute->getType() != 'B' || isset($params['checked']) && $params['checked'])
|
|
{
|
|
$vhp = new appProductAttributeVariantHasProduct();
|
|
$vhp->setProductId($product->getId());
|
|
$v->addappProductAttributeVariantHasProduct($vhp);
|
|
$v->save();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Dodaje kategorie do produktu
|
|
*
|
|
* @param Product $product Obiekt modelu produktu
|
|
* @param array $categories array('Kategoria1/Podkategoria1', 'Kategoria2/Podkategoria2/PodPodKategoria2', 'itd...')
|
|
* @param string $separator Separator ścieżki domyślnie '/'
|
|
* @param null|int $default Indeks kategorii domyślnej
|
|
* @return stTaskSchedulerImportCategoryMapping
|
|
* @throws PropelException
|
|
* @throws SQLException
|
|
* @throws stTaskSchedulerImportLogException
|
|
*/
|
|
public function addCategories(Product $product, array $categories, ?string $separator = '/', ?int $default = null): stTaskSchedulerImportCategoryMapping
|
|
{
|
|
if (!$product->isNew() && !$this->import->getConfigurationParameter('disable_categories_update'))
|
|
{
|
|
$this->removeFromCategories($product);
|
|
}
|
|
|
|
if (null === $default)
|
|
{
|
|
$default = key($categories);
|
|
}
|
|
|
|
/**
|
|
* @var stTaskSchedulerImportCategoryMapping[]
|
|
*/
|
|
$excluded = [];
|
|
|
|
$this->currentMapping = null;
|
|
|
|
foreach ($categories as $index => $category)
|
|
{
|
|
$isDefault = $default == $index;
|
|
$currentMapping = $this->import->getCategoryMapper()->addCategory($product, $category, $isDefault, $separator);
|
|
|
|
if (null !== $currentMapping && $currentMapping->getIsExcluded())
|
|
{
|
|
$excluded[] = $currentMapping;
|
|
|
|
continue;
|
|
}
|
|
|
|
if ($isDefault)
|
|
{
|
|
$this->currentMapping = $currentMapping;
|
|
}
|
|
}
|
|
|
|
if (!empty($excluded))
|
|
{
|
|
if ($product->isNew())
|
|
{
|
|
throw new stTaskSchedulerImportLogException('Kategoria **%category%** została wykluczona import produktu **%product%** został przerwany', stTaskLogger::TYPE_WARNING, [
|
|
'%category%' => implode(', ', array_map(function(stTaskSchedulerImportCategoryMapping $mapping) {
|
|
return $mapping->getCategoryPath();
|
|
}, $excluded)),
|
|
'%product%' => $this->getProductName($product),
|
|
]);
|
|
}
|
|
elseif ($this->import->getConfigurationParameter('delete_product_with_excluded_category'))
|
|
{
|
|
$product->delete();
|
|
|
|
throw new stTaskSchedulerImportLogException('Kategoria **%category%** została wykluczona produkt **%product%** zgodnie z konfiguracją został usunięty', stTaskLogger::TYPE_WARNING, [
|
|
'%category%' => implode(', ', array_map(function(stTaskSchedulerImportCategoryMapping $mapping) {
|
|
return $mapping->getCategoryPath();
|
|
}, $excluded)),
|
|
'%product%' => $this->getProductName($product),
|
|
]);
|
|
}
|
|
}
|
|
|
|
if (null === $this->currentMapping)
|
|
{
|
|
$this->currentMapping = $currentMapping;
|
|
}
|
|
|
|
return $this->currentMapping;
|
|
}
|
|
|
|
/**
|
|
* Dodaje opcje produktu
|
|
*
|
|
* @param Product $product Instancja modelu produktu
|
|
* @param array $data Opcje produktu
|
|
* @param string|null $priceType Typ ceny
|
|
* @return void
|
|
* @throws PropelException
|
|
* @throws SQLException
|
|
*/
|
|
public function setProductOptions(Product $product, array $data, string $priceType = null, ?\Closure $callback = null, bool $updateStockAvailability = true)
|
|
{
|
|
$root = ProductOptionsValuePeer::getOrCreateRoot($product);
|
|
$root->setPriceType($priceType);
|
|
$current = $this->getProductOptions($product);
|
|
$utility = $this;
|
|
|
|
$process = function(Product $product, array $data, array $current, ProductOptionsValue $root) use (&$process, $utility, $callback)
|
|
{
|
|
$count = 0;
|
|
$fieldOrder = 0;
|
|
$version = $this->import->getConfiguration()->getOption('version');
|
|
|
|
foreach ($data as $name => $values)
|
|
{
|
|
$defaultOption = null;
|
|
$name = trim($name);
|
|
$optionAttributes = isset($values['@attributes']) ? $values['@attributes'] : [];
|
|
$filter = isset($optionAttributes['filter']) ? ProductOptionsFilterPeer::retrieveByName($optionAttributes['filter']) : null;
|
|
|
|
if (!isset($current[$name]))
|
|
{
|
|
$pof = new ProductOptionsField();
|
|
$pof->disableProductUpdate();
|
|
$pof->setCulture($product->getCulture());
|
|
$pof->setFieldOrder($fieldOrder);
|
|
$pof->setName($name);
|
|
}
|
|
else
|
|
{
|
|
$pof = ProductOptionsFieldPeer::retrieveByPK($current[$name]['@id']);
|
|
}
|
|
|
|
if ($filter)
|
|
{
|
|
$pof->setProductOptionsFilterId($filter->getId());
|
|
}
|
|
|
|
$pof->save();
|
|
|
|
if (!isset($current[$name]))
|
|
{
|
|
$current[$name] = [
|
|
'@id' => $pof->getId(),
|
|
];
|
|
}
|
|
|
|
foreach ($values as $value => $params)
|
|
{
|
|
if ($value == '@attributes')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$value = trim($value);
|
|
$attributes = isset($params['@attributes']) ? $params['@attributes'] : [];
|
|
|
|
if (!isset($current[$name][$value]))
|
|
{
|
|
$pov = new ProductOptionsValue();
|
|
$pov->setCulture($product->getCulture());
|
|
$pov->setProductId($product->getId());
|
|
$pov->setProductOptionsFieldId($current[$name]['@id']);
|
|
$pov->insertAsLastChildOf($root);
|
|
$pov->setValue($value);
|
|
}
|
|
else
|
|
{
|
|
$pov = ProductOptionsValuePeer::retrieveByPK($current[$name][$value]['@id']);
|
|
}
|
|
|
|
if ($filter)
|
|
{
|
|
$pov->setOptFilterId($filter->getId());
|
|
}
|
|
|
|
if (isset($attributes['stock']))
|
|
{
|
|
$pov->setStock('' !== $attributes['stock'] ? $attributes['stock'] : null);
|
|
}
|
|
|
|
if (isset($attributes['price']) && !empty($attributes['price']))
|
|
{
|
|
$pov->setPrice($version > 1 ? $utility->applyPriceMargin($attributes['price']) : $attributes['price']);
|
|
}
|
|
|
|
if (isset($attributes['oldPrice']) && !empty($attributes['oldPrice']))
|
|
{
|
|
$pov->setOldPrice($version > 1 ? $utility->applyPriceMargin($attributes['oldPrice']) : $attributes['oldPrice']);
|
|
}
|
|
|
|
if (isset($attributes['weight']))
|
|
{
|
|
$pov->setWeight($attributes['weight']);
|
|
}
|
|
|
|
if (isset($attributes['code']))
|
|
{
|
|
$pov->setUseProduct($attributes['code']);
|
|
}
|
|
|
|
if (isset($attributes['ean']))
|
|
{
|
|
$pov->setManCode($attributes['ean']);
|
|
}
|
|
|
|
if (isset($attributes['color']) && $attributes['color'][0] == '#' && null !== $filter && $filter->getFilterType() == ProductOptionsFilterPeer::COLOR_FILTER)
|
|
{
|
|
$pov->setColor(ltrim($attributes['color'], '#'));
|
|
$pov->setUseImageAsColor(false);
|
|
}
|
|
|
|
if (isset($attributes['product_image']))
|
|
{
|
|
$pov->setSfAssetId($attributes['product_image']);
|
|
}
|
|
|
|
if (isset($attributes['default']) && $attributes['default'] && null === $defaultOption)
|
|
{
|
|
$defaultOption = $pov->getOptValue();
|
|
}
|
|
|
|
$isNew = $pov->isNew();
|
|
|
|
if (null !== $callback)
|
|
{
|
|
call_user_func($callback, $pov, $attributes);
|
|
}
|
|
|
|
$pov->disableProductUpdate();
|
|
$pov->save();
|
|
|
|
if ($isNew)
|
|
{
|
|
$current[$name][$value] = [
|
|
'@id' => $pov->getId(),
|
|
];
|
|
}
|
|
|
|
if (isset($attributes['color']) && $attributes['color'][0] != '#' && null !== $filter && $filter->getFilterType() == ProductOptionsFilterPeer::COLOR_FILTER)
|
|
{
|
|
try
|
|
{
|
|
$url = $attributes['color'];
|
|
|
|
$this->downloader->download($url, function(stFileDownloaderFile $file) use ($pov, $product, $url) {
|
|
$filename = uniqid() . '.' . $file->getExtension();
|
|
$pov->setUseImageAsColor(true);
|
|
$pov->setColorImage($filename);
|
|
$target = $pov->getColorImagePath(true);
|
|
$targetDir = $pov->getColorImageDir(true);
|
|
|
|
if (!is_dir($targetDir))
|
|
{
|
|
mkdir($targetDir, 0755, true);
|
|
}
|
|
|
|
if (!$file->move($target))
|
|
{
|
|
throw new stTaskSchedulerImportLogException('Wystąpił błąd podczas zapisu zdjęcia <%image%> do lokalizacji **%target%** dla opcji **%option%** produktu **%product%**', stTaskLogger::TYPE_ERROR, [
|
|
'%option%' => $pov->getOptValue(),
|
|
'%image%' => $url,
|
|
'%target%' => $target,
|
|
'%product%' => $this->getProductName($product),
|
|
]);
|
|
}
|
|
|
|
$pov->save();
|
|
});
|
|
}
|
|
catch (stFileDownloaderException $e)
|
|
{
|
|
throw new stTaskSchedulerImportLogException('Wystąpił błąd `%error%` podczas pobierania zdjęcia <%image%> dla opcji **%option%** produktu **%product%**', stTaskLogger::TYPE_ERROR, [
|
|
'%error%' => $e->getMessage(),
|
|
'%option%' => $pov->getOptValue(),
|
|
'%image%' => $attributes['color'],
|
|
'%product%' => $this->getProductName($product),
|
|
]);
|
|
}
|
|
}
|
|
|
|
if (isset($params['@children']))
|
|
{
|
|
$count += $process($product, $params['@children'], isset($current[$name][$value]['@children']) ? $current[$name][$value]['@children'] : array(), $isNew ? $pov->reload() : $pov);
|
|
}
|
|
|
|
$root = $root->reload();
|
|
|
|
$count++;
|
|
}
|
|
|
|
if ($defaultOption)
|
|
{
|
|
$pof->setOptDefaultValue($defaultOption);
|
|
|
|
if ($pof->isModified())
|
|
{
|
|
ProductOptionsFieldPeer::doUpdate($pof);
|
|
}
|
|
}
|
|
|
|
$fieldOrder++;
|
|
}
|
|
|
|
return $count;
|
|
};
|
|
|
|
$updateAvailableOptions = function(array $data, array $current) use (&$updateAvailableOptions)
|
|
{
|
|
foreach ($current as $name => $values)
|
|
{
|
|
if ($name == '@id')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
foreach ($values as $value => $params)
|
|
{
|
|
if ($value == '@id' || $value == '@children')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
if (isset($params['@children']))
|
|
{
|
|
$updateAvailableOptions(isset($data[$name][$value]['@children']) ? $data[$name][$value]['@children'] : [], $params['@children']);
|
|
}
|
|
elseif (!isset($data[$name][$value]))
|
|
{
|
|
$pov = ProductOptionsValuePeer::retrieveByPK($params['@id']);
|
|
$pov->disableProductUpdate();
|
|
$pov->setIsActive(false);
|
|
$pov->save();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
$count = $process($product, $data, $current, $root);
|
|
|
|
if ($updateStockAvailability)
|
|
{
|
|
$updateAvailableOptions($data, $current);
|
|
}
|
|
|
|
$product->setOptHasOptions($count + 1);
|
|
|
|
$stock = ProductOptionsValuePeer::updateStock($product, false);
|
|
|
|
$product->setStock($stock);
|
|
|
|
ProductOptionsValuePeer::updateProductColor($product);
|
|
|
|
if ($product->isModified())
|
|
{
|
|
$product->save();
|
|
}
|
|
}
|
|
|
|
private function getProductOptions(Product $product): array
|
|
{
|
|
$c = new Criteria();
|
|
$c->addSelectColumn(ProductOptionsValuePeer::ID);
|
|
$c->addSelectColumn(ProductOptionsValuePeer::PRODUCT_OPTIONS_FIELD_ID);
|
|
$c->addSelectColumn(ProductOptionsValuePeer::DEPTH);
|
|
$c->addSelectColumn(ProductOptionsValuePeer::OPT_VALUE);
|
|
$c->addSelectColumn(ProductOptionsValuePeer::LFT);
|
|
$c->addSelectColumn(ProductOptionsValuePeer::RGT);
|
|
$c->addSelectColumn(ProductOptionsFieldPeer::OPT_NAME);
|
|
|
|
$c->add(ProductOptionsValuePeer::PRODUCT_ID, $product->getId());
|
|
$c->add(ProductOptionsValuePeer::PRODUCT_OPTIONS_VALUE_ID, null, Criteria::ISNOTNULL);
|
|
$c->addJoin(ProductOptionsValuePeer::PRODUCT_OPTIONS_FIELD_ID, ProductOptionsFieldPeer::ID);
|
|
$c->addAscendingOrderByColumn(ProductOptionsFieldPeer::FIELD_ORDER);
|
|
$c->addAscendingOrderByColumn(ProductOptionsValuePeer::LFT);
|
|
|
|
$rs = ProductOptionsValuePeer::doSelectRS($c);
|
|
|
|
$hydrate = function (ResultSet $rs, int $depth = 1) use (&$hydrate): array
|
|
{
|
|
$results = [];
|
|
|
|
$rs->setFetchmode(ResultSet::FETCHMODE_ASSOC);
|
|
|
|
while ($rs->next())
|
|
{
|
|
if ($depth != $rs->getInt('DEPTH'))
|
|
{
|
|
$rs->previous();
|
|
break;
|
|
}
|
|
|
|
$fieldName = $rs->getString('OPT_NAME');
|
|
$optionValue = $rs->getString('OPT_VALUE');
|
|
$hasChildren = $rs->getInt('RGT') - $rs->getInt('LFT') > 1;
|
|
|
|
if (!isset($results[$fieldName]))
|
|
{
|
|
$results[$fieldName] = [
|
|
'@id' => $rs->getInt('PRODUCT_OPTIONS_FIELD_ID'),
|
|
];
|
|
}
|
|
|
|
$results[$fieldName][$optionValue] = [
|
|
'@id' => $rs->getInt('ID'),
|
|
];
|
|
|
|
if ($hasChildren)
|
|
{
|
|
$results[$fieldName][$optionValue]['@children'] = $hydrate($rs, $depth + 1);
|
|
}
|
|
}
|
|
|
|
return $results;
|
|
};
|
|
|
|
return $hydrate($rs);
|
|
}
|
|
|
|
private function getOrCreateAttribute($name, $type, $culture)
|
|
{
|
|
$c = new Criteria();
|
|
$c->add(appProductAttributePeer::IMPORT_NAME, $name);
|
|
$attribute = appProductAttributePeer::doSelectOne($c);
|
|
|
|
if (null === $attribute)
|
|
{
|
|
$attribute = new appProductAttribute();
|
|
$attribute->setCulture($culture);
|
|
$attribute->setName($name);
|
|
$attribute->setImportName($name);
|
|
$attribute->setType($type);
|
|
$attribute->save();
|
|
}
|
|
|
|
return $attribute;
|
|
}
|
|
|
|
/**
|
|
* Usuwa przypisanie do kategorii
|
|
*
|
|
* @param Product $product
|
|
* @return void
|
|
*/
|
|
public function removeFromCategories(Product $product)
|
|
{
|
|
$c = new Criteria();
|
|
$c->add(ProductHasCategoryPeer::IMPORT_HASH_ID, $this->import->getConfiguration()->getHashId());
|
|
$c->add(ProductHasCategoryPeer::PRODUCT_ID, $product->getId());
|
|
|
|
$sql = BasePeer::createSqlQuery($c);
|
|
|
|
list(,$from) = explode(' FROM ', $sql);
|
|
|
|
$sql = 'DELETE ' . ProductHasCategoryPeer::TABLE_NAME . ' FROM ' . $from;
|
|
|
|
Propel::getConnection()->executeQuery($sql);
|
|
}
|
|
|
|
/**
|
|
* Usuwa zdjęcia z produktu
|
|
*
|
|
* @param Product $product
|
|
* @return void
|
|
* @throws PropelException
|
|
*/
|
|
public function removeImages(Product $product)
|
|
{
|
|
foreach ($product->getImages() as $image)
|
|
{
|
|
$image->delete();
|
|
}
|
|
}
|
|
|
|
protected function getProductName(Product $product)
|
|
{
|
|
$name = $product->getName();
|
|
|
|
if ($name)
|
|
{
|
|
$name .= ' ('.$product->getCode().')';
|
|
}
|
|
else
|
|
{
|
|
$name = $product->getCode();
|
|
}
|
|
|
|
return $name;
|
|
}
|
|
|
|
/**
|
|
* Zwraca cenę zmodyfikowaną o reguły określone w tabeli narzutów
|
|
*
|
|
* @param string|float $price
|
|
* @return string|float
|
|
*/
|
|
protected function applyPriceArray($price)
|
|
{
|
|
if ($this->import->getConfiguration()->getUserOption('price_array_enabled'))
|
|
{
|
|
$prices = $this->import->getConfiguration()->getUserOption('price_array');
|
|
|
|
|
|
|
|
foreach($prices as $range)
|
|
{
|
|
if($price >= $range['from'] && $price <= $range['to'])
|
|
{
|
|
return $price * $range['multiplier'] + $range['add'];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return $price;
|
|
}
|
|
} |