Files
grzanieplus.pl/plugins/stSoteshopXmlPlugin/lib/stSoteshopXml.class.php
2025-03-12 17:06:23 +01:00

458 lines
16 KiB
PHP

<?php
/**
* SOTESHOP/stNokautPlugin
*
* Ten plik należy do aplikacji stNokautPlugin opartej na licencji (Professional License SOTE).
* Nie zmieniaj tego pliku, jeśli chcesz korzystać z automatycznych aktualizacji oprogramowania.
* Jeśli chcesz wprowadzać swoje modyfikacje do programu, zapoznaj się z dokumentacją, jak zmieniać
* oprogramowanie bez zmiany kodu bazowego http://www.sote.pl/modifications
*
* @package stNokautPlugin
* @subpackage libs
* @copyright SOTE (www.sote.pl)
* @license http://www.sote.pl/license/sote (Professional License SOTE)
* @version $Id: stNokaut.class.php 6125 2010-07-07 11:35:39Z pawel $
* @author Michal Prochowski <michal.prochowski@sote.pl>
*/
/**
* Klasa stNokaut
*
* @package stNokautPlugin
* @subpackage libs
*/
class stSoteshopXml extends stPriceCompareGenerateFile implements stPriceCompareGenerateFileInterface
{
/**
* Konstruktor
*/
public function __construct()
{
parent::__construct(__CLASS__);
$this->config = stConfig::getInstance('stPriceCompare');
}
/**
* Generowanie nagłówka pliku
*
* @return string
*/
protected function getFileHead()
{
$content = xml_open_tag('?xml version="1.0" encoding="UTF-8"?');
$content .= xml_open_tag('products');
return $content;
}
/**
* Generowanie zawartości pliku
*
* @param $step integer numer kroku
* @return string
*/
protected function getFileBody($step)
{
$priceCompareProducts = $this->getProducts($step);
$url_product_params = "";
$content = "";
foreach ($priceCompareProducts as $priceCompareProduct)
{
$productContent = "";
$parsedProduct = new stPriceCompareProductParser($priceCompareProduct->getProduct());
if ($parsedProduct->checkProduct())
{
$product = $priceCompareProduct->getProduct();
$productContent .= xml_tag('url', $parsedProduct->getUrl() . $url_product_params);
$productContent .= xml_cdata_tag('producer', $parsedProduct->getProducer());
$productContent .= xml_cdata_tag('name', $parsedProduct->getName());
$productContent .= xml_cdata_tag('description', $parsedProduct->getDescription());
$productContent .= xml_cdata_tag('shortDescription', $parsedProduct->getShortDescription());
$productContent .= xml_tag('weight', number_format($parsedProduct->getWeight(), 2, '.', ''));
$productContent .= xml_tag('stock', $parsedProduct->getStock(), [
'unit' => $product->getUom(),
]);
$productContent .= xml_tag('tax', number_format($parsedProduct->getOptVat()), 2, '.', '');
$productContent .= xml_tag('price', number_format($parsedProduct->getPriceNetto(), 2, '.', ''), [
'type' => 'netto',
]);
$productContent .= xml_tag('oldPrice', number_format($parsedProduct->getOldPriceNetto(), 2, '.', ''), [
'type' => 'netto',
]);
$productContent .= $this->getProductWholesaleXml($product);
$productContent .= $this->getProductCategoriesXml($product);
$productContent .= $this->getProductAttributesXml($product);
$productContent .= $this->getProductOptionsXml($product);
$productContent .= $this->getProductPhotosXml($product);
$content .= price_compare_xml_tag('product', $productContent, [
'code' => $product->getCode(),
'active' => $product->getActive() ? 'true' : 'false',
'ean' => $product->getManCode(),
]);
}
unset($parsedProduct);
if ($this->isCLI())
{
usleep(250000);
}
}
return $content;
}
/**
* Generowanie stopki pliku
*
* @return string
*/
protected function getFileFoot()
{
$content = xml_close_tag('products');
return $content;
}
/**
* Pobieranie infromacji o porównywarce podczas eksportu
*
* @param object $object
* @return integer
*/
static public function getProduct($object = null)
{
return stPriceCompareGenerateFile::getProductForExport(__CLASS__, $object);
}
/**
* Ustawianie infromacji o porównywarce podczas importu
*
* @param object $object
* @param integer $value
* @return boolean
*/
static public function setProduct($object = null, $active = 0)
{
return stPriceCompareGenerateFile::setProductForImport(__CLASS__, $object, $active);
}
public function getCategoryPath($category, $separator = '/', $htmlspecialchars = false)
{
$c = array();
foreach ($category->getPath() as $categoryPath)
$c[] = $categoryPath->getName();
$c[] = $category->getName();
if ($htmlspecialchars)
foreach ($c as $k => $v)
$c[$k] = htmlspecialchars($v);
if ($this->config->get('category_root'))
unset($c[0]);
return implode($separator, $c);
}
protected function getProductWholesaleXml(Product $product): string
{
if ($this->getConfig('none_whoolesale') != true)
{
return "";
}
$wholesaleXml = "";
foreach (array('a', 'b', 'c') as $group)
{
$method = 'getWholesale' . ucfirst($group) . 'Netto';
$wholesaleXml .= xml_tag('price', number_format($product->$method(), 2, '.', ''), [
'type' => $this->getPriceType(),
'group' => $group,
]);
}
return xml_tag('wholesale', $wholesaleXml);
}
protected function getProductCategoriesXml(Product $product): string
{
$categoriesXml = "";
foreach ($product->getProductHasCategorys() as $category)
{
$categoryPath = $this->getCategoryPath($category->getCategory());
if ($category->getIsDefault() == 1)
{
$categoriesXml .= xml_cdata_tag('category', $categoryPath, array('main' => 'true'));
}
else
{
$categoriesXml .= xml_cdata_tag('category', $categoryPath);
}
}
return !empty($categoriesXml) ? xml_tag('categories', $categoriesXml) : '';
}
protected function getProductPhotosXml(Product $product): string
{
$photosXml = "";
foreach ($product->getImages() as $image)
{
if ($image->getId() == $product->getDefaultAssetImage()->getId())
{
$photosXml .= xml_tag('photo', htmlspecialchars(st_product_image_path($image, 'full', true, false, true)), array('id' => $image->getId(), 'main' => 'true'));
}
else
{
$photosXml .= xml_tag('photo', htmlspecialchars(st_product_image_path($image, 'full', true, false, true)), array('id' => $image->getId()));
}
}
return !empty($photosXml) ? xml_tag('photos', $photosXml) : '';
}
protected function getProductAttributesXml(Product $product): string
{
$productVariants = appProductAttributeVariantPeer::doSelectArrayWithAttribyteByProduct($product, stLanguage::getOptLanguage());
if (!empty($productVariants))
{
$attributesXml = "";
$productAttributes = appProductAttributePeer::doSelectArrayByProduct($product, stLanguage::getOptLanguage(), false);
if (!empty($productAttributes))
{
foreach ($productVariants as $attributeId => $productVariant)
{
if (!isset($productAttributes[$attributeId]))
{
continue;
}
$valuesXml = "";
$attribute = $productAttributes[$attributeId];
foreach ($productVariant as $value)
{
switch ($attribute['type'])
{
case "T":
$valuesXml .= xml_cdata_tag('value', $value['value']);
break;
case "B":
$valuesXml .= xml_cdata_tag('value', '', array('checked' => 'true'));
break;
case "C":
$colorValue = $value['type'] == "C" ? "#" . $value['value'] : htmlspecialchars(image_path('/' . $value['value'], true));
$valuesXml .= xml_cdata_tag('value', $value['name'], array('color' => $colorValue));
break;
}
}
$attributesXml .= xml_tag('attribute', $valuesXml, array('name' => $attribute['name'], 'type' => $attribute['type']));
}
}
if (!empty($attributesXml))
{
return !empty($product->getAttributesLabel()) ? xml_tag('attributes', $attributesXml, array('title' => $product->getAttributesLabel())) : xml_tag('attributes', $attributesXml);
}
}
return '';
}
protected function getProductOptionsXml(Product $product): string
{
$root = ProductOptionsValuePeer::getOrCreateRoot($product);
$options = $this->getProductOptions($product);
$helper = function (array $options) use (&$helper): string
{
$content = '';
foreach ($options as $fieldName => $values)
{
$valuesContent = '';
foreach ($values as $value => $params)
{
if ('@attributes' == $value)
{
continue;
}
$attributes = array_merge(['name' => $value], $params['@attributes']);
if (isset($params['@children']))
{
$valuesContent .= xml_tag('value', $helper($params['@children']), $attributes);
}
else
{
$valuesContent .= xml_cdata_tag('value', '', $attributes);
}
}
$optionAttributes = array_merge(['name' => $fieldName], isset($values['@attributes']) ? $values['@attributes'] : []);
$content .= xml_tag('option', $valuesContent, $optionAttributes);
}
return $content;
};
return !empty($options) ? xml_tag('options', $helper($options), array('priceType' => $root->getPriceType())) : '';
}
protected function getPriceType(): string
{
return 'netto';
}
private function getProductOptions(Product $product): array
{
sfLoader::loadHelpers(['Helper', 'Asset']);
$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->addSelectColumn(ProductOptionsValuePeer::STOCK);
$c->addSelectColumn(ProductOptionsValuePeer::WEIGHT);
$c->addSelectColumn(ProductOptionsValuePeer::USE_PRODUCT);
$c->addSelectColumn(ProductOptionsValuePeer::MAN_CODE);
$c->addSelectColumn(ProductOptionsValuePeer::PRICE);
$c->addSelectColumn(ProductOptionsValuePeer::OLD_PRICE);
$c->addSelectColumn(ProductOptionsValuePeer::COLOR);
$c->addSelectColumn(ProductOptionsValuePeer::USE_IMAGE_AS_COLOR);
$c->addSelectColumn(ProductOptionsValuePeer::SF_ASSET_ID);
$c->addSelectColumn(ProductOptionsFieldPeer::PRODUCT_OPTIONS_FILTER_ID);
$c->addSelectColumn(ProductOptionsFieldPeer::OPT_DEFAULT_VALUE);
$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, Product $product, 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]))
{
$fieldAttributes = [];
$filterId = $rs->getInt('PRODUCT_OPTIONS_FILTER_ID');
if ($filterId)
{
$filter = ProductOptionsFilterPeer::retrieveById($filterId);
$fieldAttributes['filter'] = $filter->getOptName();
}
$results[$fieldName] = ['@attributes' => $fieldAttributes];
}
$attributes = [
'price' => $rs->getString('PRICE'),
'old_price' => $rs->getString('OLD_PRICE'),
'weight' => $rs->getString('WEIGHT'),
'color' => $rs->getString('USE_IMAGE_AS_COLOR') ? image_path(ProductOptionsValuePeer::getColorImagePath($product->getId(), $rs->getInt('ID'), $rs->getString('COLOR')), true) : '#' . $rs->getString('COLOR'),
'product_image' => $rs->getInt('SF_ASSET_ID'),
];
if (!$hasChildren)
{
$attributes['stock'] = $rs->getString('STOCK');
$attributes['code'] = $rs->getString('USE_PRODUCT');
$attributes['ean'] = $rs->getString('MAN_CODE');
}
if ($rs->getInt('OPT_DEFAULT_VALUE') == $rs->getInt('OPT_VALUE'))
{
$attributes['default'] = 'true';
}
$results[$fieldName][$optionValue] = [
'@attributes' => $attributes
];
if ($hasChildren)
{
$results[$fieldName][$optionValue]['@children'] = $hydrate($rs, $product, $depth + 1);
}
}
return $results;
};
return $hydrate($rs, $product);
}
protected function getProducts($step)
{
$peerClass = $this->getConfiguration($this->priceCompareName, 'peer_name');
$c = new Criteria();
$c->add(constant($peerClass.'::ACTIVE'), 1);
if ($this->getConfig('none_active')){
$c->add(ProductPeer::ACTIVE, 1);
}
if ($this->getConfig('none_stock'))
{
$c4 = $c->getNewCriterion(ProductPeer::STOCK, null, Criteria::ISNULL);
$c5 = $c->getNewCriterion(ProductPeer::STOCK, 0, Criteria::GREATER_THAN);
$c4->addOr($c5);
$c->add($c4);
}
$c->setOffset($this->productsByStep*$step);
$c->setLimit($this->productsByStep);
$c->addAscendingOrderByColumn(constant($peerClass.'::PRODUCT_ID'));
return call_user_func($peerClass.'::doSelectJoinAll', $c);
}
}