458 lines
16 KiB
PHP
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);
|
|
}
|
|
}
|