New ICML generator
This commit is contained in:
parent
c37b05c6d2
commit
a4c06ed8ee
@ -1,3 +1,10 @@
|
||||
## 2021-05-31 v.5.7.0
|
||||
* Переработан генератор ICML каталога:
|
||||
- генератор использует потоковую запись в файл через `XMLWriter`;
|
||||
- по умолчанию опция выгрузки каталога в момент установки модуля отключена;
|
||||
- код генератора каталога теперь использует автолоадер Битрикса.
|
||||
* Скидка на позицию больше не учитывается в заказе при установке произвольной цены для позиции.
|
||||
|
||||
## 2021-01-14 v.5.6.2
|
||||
* Исправлено формирование картинок в ICML при включеном CDN
|
||||
* Убрана некорректная запись внешнего идентификатора платежа для новых платежей по истории
|
||||
|
@ -14,7 +14,8 @@
|
||||
],
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*"
|
||||
"ext-mbstring": "*",
|
||||
"ext-xmlwriter": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7",
|
||||
|
8
composer.lock
generated
8
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "032aa518034a20c6776e550379084efc",
|
||||
"content-hash": "72c54dce7daa3cd6c40577578128091a",
|
||||
"packages": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
@ -1761,7 +1761,9 @@
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*"
|
||||
"ext-mbstring": "*",
|
||||
"ext-xmlwriter": "*"
|
||||
},
|
||||
"platform-dev": []
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.0.0"
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class AddressBuilder
|
||||
*/
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class BuyerProfile
|
||||
*/
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class Customer
|
||||
*/
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class CustomerAddress
|
||||
*/
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class CustomerContragent
|
||||
*/
|
||||
|
@ -225,6 +225,33 @@ class RetailcrmConfigProvider
|
||||
static::setOption(RetailcrmConstants::CRM_ONLINE_CONSULTANT, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|string|null
|
||||
*/
|
||||
public static function getCrmPurchasePrice()
|
||||
{
|
||||
return static::getOption(RetailcrmConstants::CRM_PURCHASE_PRICE_NULL);
|
||||
}
|
||||
|
||||
public static function getProtocol()
|
||||
{
|
||||
return static::getOption(RetailcrmConstants::PROTOCOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function getSiteName(): string
|
||||
{
|
||||
$sitename = COption::GetOptionString('main', 'site_name');
|
||||
|
||||
if (!$sitename) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $sitename;
|
||||
}
|
||||
|
||||
/**
|
||||
* setOnlineConsultantScript
|
||||
*
|
||||
@ -588,6 +615,21 @@ class RetailcrmConfigProvider
|
||||
return static::$catalogBasePrice;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $profileId
|
||||
*
|
||||
* @return false|string|null
|
||||
*/
|
||||
public static function getCatalogBasePriceByProfile($profileId)
|
||||
{
|
||||
return COption::GetOptionString(
|
||||
RetailcrmConstants::MODULE_ID,
|
||||
RetailcrmConstants::CRM_CATALOG_BASE_PRICE . '_' . $profileId,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* getOrderDimensions
|
||||
*
|
||||
|
@ -21,58 +21,59 @@ IncludeModuleLangFile(__FILE__);
|
||||
*/
|
||||
class RetailcrmConstants
|
||||
{
|
||||
const MODULE_ID = 'intaro.retailcrm';
|
||||
const CRM_API_HOST_OPTION = 'api_host';
|
||||
const CRM_API_KEY_OPTION = 'api_key';
|
||||
const CRM_ORDER_TYPES_ARR = 'order_types_arr';
|
||||
const CRM_DELIVERY_TYPES_ARR = 'deliv_types_arr';
|
||||
const CRM_DELIVERY_SERVICES_ARR = 'deliv_services_arr';
|
||||
const CRM_PAYMENT_TYPES = 'pay_types_arr';
|
||||
const CRM_INTEGRATION_PAYMENT = 'integration_payment';
|
||||
const CRM_PAYMENT_STATUSES = 'pay_statuses_arr';
|
||||
const CRM_PAYMENT = 'payment_arr'; //order payment Y/N
|
||||
const CRM_ORDER_LAST_ID = 'order_last_id';
|
||||
const CRM_ORDER_SITES = 'sites_ids';
|
||||
const CRM_ORDER_DISCHARGE = 'order_discharge';
|
||||
const CRM_SITES_LIST = 'sites_list';
|
||||
const CRM_ORDER_PROPS = 'order_props';
|
||||
const CRM_LEGAL_DETAILS = 'legal_details';
|
||||
const CRM_CUSTOM_FIELDS = 'custom_fields';
|
||||
const CRM_CONTRAGENT_TYPE = 'contragent_type';
|
||||
const CRM_SITES_LIST_CORPORATE = 'shops-corporate';
|
||||
const CRM_ORDER_NUMBERS = 'order_numbers';
|
||||
const CRM_CANCEL_ORDER = 'cansel_order';
|
||||
const CRM_INVENTORIES_UPLOAD = 'inventories_upload';
|
||||
const CRM_STORES = 'stores';
|
||||
const CRM_SHOPS = 'shops';
|
||||
const CRM_IBLOCKS_INVENTORIES = 'iblocks_inventories';
|
||||
const CRM_PRICES_UPLOAD = 'prices_upload';
|
||||
const CRM_PRICES = 'prices';
|
||||
const CRM_PRICE_SHOPS = 'price_shops';
|
||||
const CRM_IBLOCKS_PRICES = 'iblock_prices';
|
||||
const CRM_COLLECTOR = 'collector';
|
||||
const CRM_COLL_KEY = 'coll_key';
|
||||
const CRM_UA = 'ua';
|
||||
const CRM_UA_KEYS = 'ua_keys';
|
||||
const CRM_DISCOUNT_ROUND = 'discount_round';
|
||||
const CRM_CC = 'cc';
|
||||
const CRM_CORP_SHOPS = 'shops-corporate';
|
||||
const CRM_CORP_NAME = 'nickName-corporate';
|
||||
const CRM_CORP_ADDRESS = 'adres-corporate';
|
||||
const CRM_API_VERSION = 'api_version';
|
||||
const CRM_CURRENCY = 'currency';
|
||||
const CRM_ADDRESS_OPTIONS = 'address_options';
|
||||
const CRM_DIMENSIONS = 'order_dimensions';
|
||||
const PROTOCOL = 'protocol';
|
||||
const CRM_ORDER_FAILED_IDS = 'order_failed_ids';
|
||||
const CRM_CUSTOMERS_HISTORY_SINCE_ID = 'customer_history';
|
||||
const CRM_ORDER_HISTORY_DATE = 'order_history_date';
|
||||
const CRM_CATALOG_BASE_PRICE = 'catalog_base_price';
|
||||
const CRM_ORDER_DIMENSIONS = 'order_dimensions';
|
||||
const CANCEL_PROPERTY_CODE = 'INTAROCRM_IS_CANCELED';
|
||||
const CRM_INTEGRATION_DELIVERY = 'integration_delivery';
|
||||
const CRM_SHIPMENT_DEDUCTED = 'shipment_deducted';
|
||||
const SEND_PAYMENT_AMOUNT = 'send_payment_amount';
|
||||
const CRM_ONLINE_CONSULTANT = 'online_consultant';
|
||||
const CRM_ONLINE_CONSULTANT_SCRIPT = 'online_consultant_script';
|
||||
public const MODULE_ID = 'intaro.retailcrm';
|
||||
public const CRM_API_HOST_OPTION = 'api_host';
|
||||
public const CRM_API_KEY_OPTION = 'api_key';
|
||||
public const CRM_ORDER_TYPES_ARR = 'order_types_arr';
|
||||
public const CRM_DELIVERY_TYPES_ARR = 'deliv_types_arr';
|
||||
public const CRM_DELIVERY_SERVICES_ARR = 'deliv_services_arr';
|
||||
public const CRM_PAYMENT_TYPES = 'pay_types_arr';
|
||||
public const CRM_INTEGRATION_PAYMENT = 'integration_payment';
|
||||
public const CRM_PAYMENT_STATUSES = 'pay_statuses_arr';
|
||||
public const CRM_PAYMENT = 'payment_arr'; //order payment Y/N
|
||||
public const CRM_ORDER_LAST_ID = 'order_last_id';
|
||||
public const CRM_ORDER_SITES = 'sites_ids';
|
||||
public const CRM_ORDER_DISCHARGE = 'order_discharge';
|
||||
public const CRM_SITES_LIST = 'sites_list';
|
||||
public const CRM_ORDER_PROPS = 'order_props';
|
||||
public const CRM_LEGAL_DETAILS = 'legal_details';
|
||||
public const CRM_CUSTOM_FIELDS = 'custom_fields';
|
||||
public const CRM_CONTRAGENT_TYPE = 'contragent_type';
|
||||
public const CRM_SITES_LIST_CORPORATE = 'shops-corporate';
|
||||
public const CRM_ORDER_NUMBERS = 'order_numbers';
|
||||
public const CRM_CANCEL_ORDER = 'cansel_order';
|
||||
public const CRM_INVENTORIES_UPLOAD = 'inventories_upload';
|
||||
public const CRM_STORES = 'stores';
|
||||
public const CRM_SHOPS = 'shops';
|
||||
public const CRM_IBLOCKS_INVENTORIES = 'iblocks_inventories';
|
||||
public const CRM_PRICES_UPLOAD = 'prices_upload';
|
||||
public const CRM_PRICES = 'prices';
|
||||
public const CRM_PRICE_SHOPS = 'price_shops';
|
||||
public const CRM_IBLOCKS_PRICES = 'iblock_prices';
|
||||
public const CRM_COLLECTOR = 'collector';
|
||||
public const CRM_COLL_KEY = 'coll_key';
|
||||
public const CRM_UA = 'ua';
|
||||
public const CRM_UA_KEYS = 'ua_keys';
|
||||
public const CRM_DISCOUNT_ROUND = 'discount_round';
|
||||
public const CRM_CC = 'cc';
|
||||
public const CRM_CORP_SHOPS = 'shops-corporate';
|
||||
public const CRM_CORP_NAME = 'nickName-corporate';
|
||||
public const CRM_CORP_ADDRESS = 'adres-corporate';
|
||||
public const CRM_API_VERSION = 'api_version';
|
||||
public const CRM_CURRENCY = 'currency';
|
||||
public const CRM_ADDRESS_OPTIONS = 'address_options';
|
||||
public const CRM_DIMENSIONS = 'order_dimensions';
|
||||
public const PROTOCOL = 'protocol';
|
||||
public const CRM_ORDER_FAILED_IDS = 'order_failed_ids';
|
||||
public const CRM_CUSTOMERS_HISTORY_SINCE_ID = 'customer_history';
|
||||
public const CRM_ORDER_HISTORY_DATE = 'order_history_date';
|
||||
public const CRM_CATALOG_BASE_PRICE = 'catalog_base_price';
|
||||
public const CRM_ORDER_DIMENSIONS = 'order_dimensions';
|
||||
public const CANCEL_PROPERTY_CODE = 'INTAROCRM_IS_CANCELED';
|
||||
public const CRM_INTEGRATION_DELIVERY = 'integration_delivery';
|
||||
public const CRM_SHIPMENT_DEDUCTED = 'shipment_deducted';
|
||||
public const SEND_PAYMENT_AMOUNT = 'send_payment_amount';
|
||||
public const CRM_ONLINE_CONSULTANT = 'online_consultant';
|
||||
public const CRM_ONLINE_CONSULTANT_SCRIPT = 'online_consultant_script';
|
||||
public const CRM_PURCHASE_PRICE_NULL = 'purchasePrice_null';
|
||||
}
|
||||
|
@ -1,910 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Bitrix\Highloadblock as HL;
|
||||
use Bitrix\Main\Entity;
|
||||
|
||||
IncludeModuleLangFile(__FILE__);
|
||||
class RetailCrmICML
|
||||
{
|
||||
public $profileID;
|
||||
public $iblocks;
|
||||
public $filename;
|
||||
public $serverName;
|
||||
public $defaultServerName;
|
||||
public $propertiesSKU;
|
||||
public $propertiesUnitSKU;
|
||||
public $propertiesProduct;
|
||||
public $propertiesUnitProduct;
|
||||
public $highloadblockSkuProperties;
|
||||
public $highloadblockProductProperties;
|
||||
public $application;
|
||||
public $encoding = 'utf-8';
|
||||
public $encodingDefault = 'utf-8';
|
||||
public $loadPurchasePrice = false;
|
||||
public $productPictures;
|
||||
public $skuPictures;
|
||||
public $offerPageSize = 50;
|
||||
|
||||
protected $fp;
|
||||
protected $mainSection = 1000000;
|
||||
protected $pageSize = 500;
|
||||
protected $protocol;
|
||||
protected $purchasePriceNull;
|
||||
|
||||
protected $isLogged = false;
|
||||
protected $logFile = '/bitrix/catalog_export/i_crm_load_log.txt';
|
||||
protected $fpLog;
|
||||
protected $localizedIBlockProps;
|
||||
|
||||
protected $MODULE_ID = 'intaro.retailcrm';
|
||||
protected $CRM_CATALOG_BASE_PRICE = 'catalog_base_price';
|
||||
protected $PROTOCOL_OPTION = 'protocol';
|
||||
protected $CRM_PURCHASE_PRICE_NULL = 'purchasePrice_null';
|
||||
|
||||
protected $measurement = array (
|
||||
'mm' => 1, // 1 mm = 1 mm
|
||||
'cm' => 10, // 1 cm = 10 mm
|
||||
'm' => 1000,
|
||||
'mg' => 0.001, // 0.001 g = 1 mg
|
||||
'g' => 1,
|
||||
'kg' => 1000,
|
||||
);
|
||||
|
||||
protected $measurementLink = array (
|
||||
'mm' => 'mm',
|
||||
'cm' => 'mm',
|
||||
'm' => 'mm',
|
||||
'mg' => 'g',
|
||||
'g' => 'g',
|
||||
'kg' => 'g',
|
||||
);
|
||||
|
||||
protected $measure = array (
|
||||
'pc. 1' => 'pc',
|
||||
'm' => 'm',
|
||||
'l' => 'l',
|
||||
'kg' => 'kg',
|
||||
);
|
||||
|
||||
public function Load()
|
||||
{
|
||||
global $USER;
|
||||
if (!isset($_SESSION["SESS_AUTH"]["USER_ID"]) || !$_SESSION["SESS_AUTH"]["USER_ID"]) {
|
||||
$USER = new CUser();
|
||||
}
|
||||
|
||||
$this->isLogged = true;
|
||||
$this->localizedIBlockProps = $this->getLocalizedIBlockProps();
|
||||
|
||||
$defaultSite = CSite::GetList($by = "def", $order = "desc", array('DEF' => 'Y'))->Fetch();
|
||||
$this->encodingDefault = $defaultSite["CHARSET"];
|
||||
|
||||
$this->protocol = COption::GetOptionString($this->MODULE_ID, $this->PROTOCOL_OPTION);
|
||||
$this->purchasePriceNull = COption::GetOptionString($this->MODULE_ID, $this->CRM_PURCHASE_PRICE_NULL);
|
||||
|
||||
$this->PrepareSettings();
|
||||
|
||||
$this->fp = $this->PrepareFile($this->filename. '.tmp');
|
||||
|
||||
if ($this->isLogged) {
|
||||
$this->fpLog = $this->PrepareFile($this->logFile);
|
||||
$this->WriteLog("Start Loading");
|
||||
}
|
||||
|
||||
$this->PreWriteCatalog();
|
||||
|
||||
$categories = $this->GetCategories();
|
||||
|
||||
$this->WriteCategories($categories);
|
||||
|
||||
$this->PreWriteOffers();
|
||||
$this->BuildOffers($categories);
|
||||
$this->PostWriteOffers();
|
||||
|
||||
$this->PostWriteCatalog();
|
||||
|
||||
if ($this->isLogged) {
|
||||
$this->WriteLog("Loading was ended successfully (peek memory usage: " . memory_get_peak_usage() . ")");
|
||||
}
|
||||
|
||||
$this->CloseFile($this->fp);
|
||||
$this->CloseFile($this->fpLog);
|
||||
unlink($defaultSite['ABS_DOC_ROOT'] . $this->filename);
|
||||
rename($defaultSite['ABS_DOC_ROOT'] . $this->filename. '.tmp', $defaultSite['ABS_DOC_ROOT'] . $this->filename);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private function setSiteAddress($block_id)
|
||||
{
|
||||
$site = CAllIBlock::GetSite($block_id)->Fetch();
|
||||
|
||||
if ($site['SERVER_NAME']) {
|
||||
$this->serverName = $site['SERVER_NAME'];
|
||||
} else {
|
||||
$this->serverName = $this->defaultServerName;
|
||||
}
|
||||
}
|
||||
|
||||
protected function PrepareSettings()
|
||||
{
|
||||
foreach ($this->propertiesSKU as $iblock => $arr) {
|
||||
foreach ($arr as $id => $sku) {
|
||||
$this->propertiesSKU[$iblock][$id] = strtoupper($sku);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->propertiesProduct as $iblock => $arr) {
|
||||
foreach ($arr as $id => $prod) {
|
||||
$this->propertiesProduct[$iblock][$id] = strtoupper($prod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function PrepareValue($text)
|
||||
{
|
||||
$newText = $this->application->ConvertCharset($text, $this->encodingDefault, $this->encoding);
|
||||
$newText = strip_tags($newText);
|
||||
$newText = str_replace("&", "&", $newText);
|
||||
|
||||
return $newText;
|
||||
}
|
||||
|
||||
protected function PrepareFile($filename)
|
||||
{
|
||||
$fullFilename = $_SERVER["DOCUMENT_ROOT"] . $filename;
|
||||
CheckDirPath($fullFilename);
|
||||
|
||||
if ($fp = @fopen($fullFilename, "w")){
|
||||
return $fp;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function PreWriteCatalog()
|
||||
{
|
||||
@fwrite($this->fp, "<yml_catalog date=\"" . $this->PrepareValue(Date("Y-m-d H:i:s")) . "\">\n
|
||||
<shop>\n
|
||||
<name>" . $this->PrepareValue(COption::GetOptionString("main", "site_name", ""))."</name>\n
|
||||
<company>" . $this->PrepareValue(COption::GetOptionString("main", "site_name", ""))."</company>\n"
|
||||
);
|
||||
}
|
||||
|
||||
protected function WriteCategories($categories)
|
||||
{
|
||||
$stringCategories = "";
|
||||
@fwrite($this->fp, "<categories>\n");
|
||||
foreach ($categories as $category) {
|
||||
$stringCategories .= $this->BuildCategory($category);
|
||||
}
|
||||
@fwrite($this->fp, $stringCategories);
|
||||
@fwrite($this->fp, "</categories>\n");
|
||||
}
|
||||
protected function PreWriteOffers()
|
||||
{
|
||||
@fwrite($this->fp, "<offers>\n");
|
||||
}
|
||||
|
||||
protected function PostWriteOffers()
|
||||
{
|
||||
@fwrite($this->fp, "</offers>\n");
|
||||
}
|
||||
|
||||
protected function WriteOffers($offers)
|
||||
{
|
||||
@fwrite($this->fp, $offers);
|
||||
}
|
||||
|
||||
protected function WriteLog($text)
|
||||
{
|
||||
if ($this->isLogged) {
|
||||
@fwrite($this->fpLog, Date("Y:m:d H:i:s") . ": " . $text . "\n");
|
||||
}
|
||||
}
|
||||
|
||||
protected function PostWriteCatalog()
|
||||
{
|
||||
@fwrite($this->fp, "</shop>\n
|
||||
</yml_catalog>\n");
|
||||
}
|
||||
|
||||
protected function CloseFile($fp)
|
||||
{
|
||||
@fclose($fp);
|
||||
}
|
||||
|
||||
protected function GetCategories()
|
||||
{
|
||||
$categories = array();
|
||||
foreach ($this->iblocks as $id) {
|
||||
$this->setSiteAddress($id);
|
||||
$filter = array("IBLOCK_ID" => $id);
|
||||
|
||||
$dbRes = CIBlockSection::GetList(array("left_margin" => "asc"), $filter);
|
||||
$hasCategories = false;
|
||||
|
||||
while ($arRes = $dbRes->Fetch()) {
|
||||
$categories[$arRes['ID']] = $arRes;
|
||||
$categories[$arRes['ID']]['SITE'] = $this->protocol . $this->serverName;
|
||||
$hasCategories = true;
|
||||
}
|
||||
|
||||
if (!$hasCategories) {
|
||||
$iblock = CIBlock::GetByID($id)->Fetch();
|
||||
|
||||
$arRes = array();
|
||||
$arRes['ID'] = $this->mainSection + $id;
|
||||
$arRes['IBLOCK_SECTION_ID'] = 0;
|
||||
$arRes['NAME'] = sprintf(GetMessage('ROOT_CATEGORY_FOR_CATALOG'), $iblock['NAME']);
|
||||
$categories[$arRes['ID']] = $arRes;
|
||||
$categories[$arRes['ID']]['SITE'] = $this->protocol . $this->serverName;
|
||||
}
|
||||
}
|
||||
|
||||
return $categories;
|
||||
}
|
||||
|
||||
protected function BuildCategory($arCategory)
|
||||
{
|
||||
$category =
|
||||
"<category id=\"" . $this->PrepareValue($arCategory["ID"]) . "\""
|
||||
. (intval($arCategory["IBLOCK_SECTION_ID"]) > 0 ?
|
||||
" parentId=\"" . $this->PrepareValue($arCategory["IBLOCK_SECTION_ID"]) . "\""
|
||||
:"")
|
||||
. ">\n\t"
|
||||
. "<name>" . $this->PrepareValue($arCategory["NAME"]) . "</name>\n";
|
||||
|
||||
if (CFile::GetPath($arCategory["DETAIL_PICTURE"])) {
|
||||
$category .= "\t<picture>" . $this->getImageUrl($arCategory["DETAIL_PICTURE"]) . "</picture>\n";
|
||||
}
|
||||
|
||||
if (CFile::GetPath($arCategory["PICTURE"])) {
|
||||
$category .= "\t<picture>" . $this->getImageUrl($arCategory["PICTURE"]) . "</picture>\n";
|
||||
}
|
||||
|
||||
$category .= "</category>\n";
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
protected function BuildOffers(&$allCategories)
|
||||
{
|
||||
$basePriceId = $this->getBasePriceId();
|
||||
|
||||
foreach ($this->iblocks as $key => $id) {
|
||||
$this->setSiteAddress($id);
|
||||
$barcodes = $this->getProductBarcodesByIblock($id);
|
||||
|
||||
// Get Info by infoblocks
|
||||
$iblockData = CIBlock::GetByID($id)->Fetch();
|
||||
$iblockOffer = CCatalogSKU::GetInfoByProductIBlock($id);
|
||||
|
||||
$highloadblockSkuProps = $this->getAvailableHighloadOfferSkuProps($iblockOffer['IBLOCK_ID']);
|
||||
$highloadblockProductProps = $this->getAvailableHighloadProductProps($id);
|
||||
|
||||
$arSelect = $this->buildProductQuery($id);
|
||||
$arSelectOffer = $this->buildOfferQuery($id, $iblockOffer['SKU_PROPERTY_ID']);
|
||||
|
||||
// Set filter
|
||||
$order = array("id");
|
||||
$filter = array(
|
||||
"IBLOCK_ID" => $id,
|
||||
"ACTIVE" => 'Y',
|
||||
);
|
||||
$arNavStatParams = array(
|
||||
"iNumPage" => 1,
|
||||
"nPageSize" => $this->pageSize,
|
||||
);
|
||||
|
||||
// Cycle page to page
|
||||
do {
|
||||
// Get products on this page
|
||||
$elems = array();
|
||||
$dbResProductsIds = CIBlockElement::GetList($order, $filter, false, $arNavStatParams, array('ID'));
|
||||
|
||||
while ($obIds = $dbResProductsIds->Fetch()) {
|
||||
$elems[] = $obIds['ID'];
|
||||
}
|
||||
|
||||
foreach ($elems as $elemId) {
|
||||
$arFilter = array(
|
||||
"IBLOCK_ID" => $id,
|
||||
"ID" => array($elemId)
|
||||
);
|
||||
|
||||
$this->ProcessProductOffers(
|
||||
$arSelect,
|
||||
$arSelectOffer,
|
||||
$allCategories,
|
||||
$basePriceId,
|
||||
$id,
|
||||
$iblockData,
|
||||
$iblockOffer,
|
||||
$barcodes,
|
||||
$highloadblockProductProps,
|
||||
$highloadblockSkuProps,
|
||||
$order,
|
||||
$arFilter
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->isLogged) {
|
||||
$this->WriteLog(
|
||||
count($elems)
|
||||
. " product(s) has been loaded from " . $id . " IB (memory usage: " . memory_get_usage() . ")"
|
||||
);
|
||||
}
|
||||
|
||||
$arNavStatParams['iNumPage'] = $dbResProductsIds->NavPageNomer + 1;
|
||||
} while ($dbResProductsIds->NavPageNomer < $dbResProductsIds->NavPageCount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process offers for a single product
|
||||
*
|
||||
* @param array $arSelect Properties to select for order
|
||||
* @param array $arSelectOffer Properties to select for offer
|
||||
* @param array $allCategories Categories to pick data from
|
||||
* @param string $basePriceId Base price ID
|
||||
* @param string $iblockId iblock id
|
||||
* @param array $iblock iblock data
|
||||
* @param array $iblockOffer offer iblock
|
||||
* @param array $barcodes Catalog barcodes
|
||||
* @param array $highloadblockProductProps Product props
|
||||
* @param array $highloadblockSkuProps SKU props
|
||||
* @param array $order Order data
|
||||
* @param array $arFilter filter
|
||||
*/
|
||||
protected function ProcessProductOffers(
|
||||
$arSelect,
|
||||
$arSelectOffer,
|
||||
$allCategories,
|
||||
$basePriceId,
|
||||
$iblockId,
|
||||
$iblock,
|
||||
$iblockOffer,
|
||||
$barcodes,
|
||||
$highloadblockProductProps,
|
||||
$highloadblockSkuProps,
|
||||
$order,
|
||||
$arFilter
|
||||
) {
|
||||
$dbResProducts = CIBlockElement::GetList($order, $arFilter, false, false, $arSelect);
|
||||
|
||||
$products = [];
|
||||
|
||||
while ($product = $dbResProducts->GetNext()) {
|
||||
// Compile products to array
|
||||
$products[$product['ID']] = $product;
|
||||
$products[$product['ID']]['offers'] = [];
|
||||
}
|
||||
|
||||
unset($product);
|
||||
|
||||
if (!empty($iblockOffer['IBLOCK_ID']) && !empty($products)) {
|
||||
$arFilterOffer = array(
|
||||
'IBLOCK_ID' => $iblockOffer['IBLOCK_ID'],
|
||||
'PROPERTY_' . $iblockOffer['SKU_PROPERTY_ID'] => array_keys($products),
|
||||
);
|
||||
|
||||
// Get all offers for products on this page
|
||||
$dbResOffers = CIBlockElement::GetList(
|
||||
array(),
|
||||
$arFilterOffer,
|
||||
false,
|
||||
array('nTopCount' => $this->pageSize * $this->offerPageSize),
|
||||
$arSelectOffer
|
||||
);
|
||||
|
||||
while ($offer = $dbResOffers->GetNext()) {
|
||||
// Link offers to products
|
||||
$products[$offer['PROPERTY_' . $iblockOffer['SKU_PROPERTY_ID'] . '_VALUE']]['offers'][$offer['ID']] = $offer;
|
||||
}
|
||||
|
||||
unset($offer, $dbResOffers);
|
||||
}
|
||||
|
||||
foreach ($products as $product) {
|
||||
$product['PICTURE'] = $this->getProductPicture($iblockId, $product);
|
||||
$resPropertiesProduct = $this->getProductProperties($iblockId, $highloadblockProductProps, $product);
|
||||
$categories = $this->getProductCategories($allCategories, $iblockId, $product['ID']);
|
||||
|
||||
$existOffer = false;
|
||||
if (!empty($iblockOffer['IBLOCK_ID'])) {
|
||||
foreach ($product['offers'] as $offer) {
|
||||
$offer['BARCODE'] = isset($barcodes[$offer['ID']]) ? $barcodes[$offer['ID']] : '';
|
||||
$offer['PRODUCT_ID'] = $product["ID"];
|
||||
$offer['DETAIL_PAGE_URL'] = $product["DETAIL_PAGE_URL"];
|
||||
|
||||
if (CFile::GetPath($offer["DETAIL_PICTURE"])) {
|
||||
$offer['PICTURE'] = $this->getImageUrl($offer["DETAIL_PICTURE"]);
|
||||
} elseif (CFile::GetPath($offer["PREVIEW_PICTURE"])) {
|
||||
$offer['PICTURE'] = $this->getImageUrl($offer["PREVIEW_PICTURE"]);
|
||||
} elseif (
|
||||
$this->skuPictures
|
||||
&& isset($this->skuPictures[$iblockId])
|
||||
&& CFile::GetPath($offer["PROPERTY_" . $this->skuPictures[$iblockId]['picture'] . "_VALUE"])
|
||||
) {
|
||||
$offer['PICTURE'] = $this->getImageUrl($offer["PROPERTY_" . $this->skuPictures[$iblockId]['picture'] . "_VALUE"]);
|
||||
} else {
|
||||
$offer['PICTURE'] = $product['PICTURE'];
|
||||
}
|
||||
|
||||
$offer['PRODUCT_NAME'] = $product["NAME"];
|
||||
$offer['PRODUCT_ACTIVE'] = $product["ACTIVE"];
|
||||
$offer['PRICE'] = $offer['CATALOG_PRICE_' . $basePriceId];
|
||||
$offer['PURCHASE_PRICE'] = $offer['CATALOG_PURCHASING_PRICE'];
|
||||
$offer['QUANTITY'] = $offer["CATALOG_QUANTITY"];
|
||||
|
||||
// Get properties of product
|
||||
foreach ($this->propertiesSKU[$iblockId] as $key => $propSKU) {
|
||||
if ($propSKU != "") {
|
||||
if (isset ($offer["PROPERTY_" . $propSKU . "_NAME"])) {
|
||||
$offer['_PROP_' . $key] = $offer["PROPERTY_" . $propSKU . "_NAME"];
|
||||
} elseif (isset($offer["PROPERTY_" . $propSKU . "_VALUE"])) {
|
||||
$offer['_PROP_' . $key] = $offer["PROPERTY_" . $propSKU . "_VALUE"];
|
||||
} elseif (isset($offer[$propSKU])) {
|
||||
$offer['_PROP_' . $key] = $offer[$propSKU];
|
||||
}
|
||||
if (array_key_exists($key, $this->propertiesUnitSKU[$iblockId])) {
|
||||
$offer['_PROP_' . $key] *= $this->measurement[$this->propertiesUnitSKU[$iblockId][$key]];
|
||||
$offer['_PROP_' . $key . "_UNIT"] = $this->measurementLink[$this->propertiesUnitSKU[$iblockId][$key]];
|
||||
}
|
||||
if (isset($highloadblockSkuProps[$propSKU])) {
|
||||
$propVal = $this->getHBprop($highloadblockSkuProps[$propSKU], $offer["PROPERTY_" . $propSKU . "_VALUE"]);
|
||||
$tableName = $highloadblockSkuProps[$propSKU]['USER_TYPE_SETTINGS']['TABLE_NAME'];
|
||||
$field = $this->highloadblockSkuProperties[$tableName][$iblockId][$key];
|
||||
$offer['_PROP_' . $key] = $propVal[$field];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($resPropertiesProduct as $key => $propProduct) {
|
||||
if ($this->propertiesProduct[$iblockId][$key] != "" && !isset($offer[$key])) {
|
||||
$offer['_PROP_' . $key] = $propProduct;
|
||||
}
|
||||
}
|
||||
|
||||
$this->PutOffer($offer, $categories, $iblock, $allCategories);
|
||||
$existOffer = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$existOffer) {
|
||||
$offer['BARCODE'] = isset($barcodes[$product["ID"]]) ? $barcodes[$product["ID"]] : '';
|
||||
$product['PRODUCT_ID'] = $product["ID"];
|
||||
$product['PRODUCT_NAME'] = $product["NAME"];
|
||||
$product['PRODUCT_ACTIVE'] = $product["ACTIVE"];
|
||||
$product['PRICE'] = $product['CATALOG_PRICE_' . $basePriceId];
|
||||
$product['PURCHASE_PRICE'] = $product['CATALOG_PURCHASING_PRICE'];
|
||||
$product['QUANTITY'] = $product["CATALOG_QUANTITY"];
|
||||
|
||||
foreach ($resPropertiesProduct as $key => $propProduct) {
|
||||
if ($this->propertiesProduct[$iblockId][$key] != "" || $this->propertiesProduct[$iblockId][str_replace("_UNIT", "", $key)] != "") {
|
||||
$product['_PROP_' . $key] = $propProduct;
|
||||
}
|
||||
}
|
||||
|
||||
$this->PutOffer($product, $categories, $iblock, $allCategories);
|
||||
}
|
||||
}
|
||||
|
||||
unset($products);
|
||||
}
|
||||
|
||||
protected function getProductPicture($iblockId, array $product)
|
||||
{
|
||||
$picture = '';
|
||||
|
||||
if (CFile::GetPath($product["DETAIL_PICTURE"])) {
|
||||
$picture = $this->getImageUrl($product["DETAIL_PICTURE"]);
|
||||
} elseif (CFile::GetPath($product["PREVIEW_PICTURE"])){
|
||||
$picture = $this->getImageUrl($product["PREVIEW_PICTURE"]);
|
||||
} elseif (
|
||||
$this->productPictures
|
||||
&& isset($this->productPictures[$iblockId])
|
||||
&& CFile::GetPath($product["PROPERTY_" . $this->productPictures[$iblockId]['picture'] . "_VALUE"])
|
||||
) {
|
||||
$picture = $this->getImageUrl($product["PROPERTY_" . $this->productPictures[$iblockId]['picture'] . "_VALUE"]);
|
||||
}
|
||||
|
||||
return $picture;
|
||||
}
|
||||
|
||||
protected function PutOffer($arOffer, $categories, $iblock, &$allCategories)
|
||||
{
|
||||
$offerData = $this->BuildOffer($arOffer, $categories, $iblock, $allCategories);
|
||||
|
||||
if ($offerData !== "") {
|
||||
$this->WriteOffers($offerData);
|
||||
}
|
||||
}
|
||||
|
||||
protected function BuildOffer($arOffer, $categories, $iblock, &$allCategories)
|
||||
{
|
||||
$offer = "";
|
||||
$offer .= "<offer id=\"" .$this->PrepareValue($arOffer["ID"]) . "\" ".
|
||||
"productId=\"" . $this->PrepareValue($arOffer["PRODUCT_ID"]) . "\" ".
|
||||
"quantity=\"" . $this->PrepareValue(DoubleVal($arOffer['QUANTITY'])) . "\">\n";
|
||||
|
||||
if ($arOffer['PRODUCT_ACTIVE'] == "N") {
|
||||
$offer .= "<productActivity>" . $this->PrepareValue($arOffer['PRODUCT_ACTIVE']) . "</productActivity>\n";
|
||||
}
|
||||
|
||||
$keys = array_keys($categories);
|
||||
if (strpos($arOffer['DETAIL_PAGE_URL'], "#SECTION_PATH#") !== false) {
|
||||
if (count($categories) != 0) {
|
||||
$category = $allCategories[$keys[0]];
|
||||
$path = $category['CODE'];
|
||||
|
||||
if (intval($category["IBLOCK_SECTION_ID"] ) != 0) {
|
||||
while (true) {
|
||||
$category = $allCategories[$category['IBLOCK_SECTION_ID']];
|
||||
$path = $category['CODE'] . '/' . $path;
|
||||
if(intval($category["IBLOCK_SECTION_ID"]) == 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
$arOffer['DETAIL_PAGE_URL'] = str_replace("#SECTION_PATH#", $path, $arOffer['DETAIL_PAGE_URL']);
|
||||
}
|
||||
|
||||
if (isset($arOffer["PICTURE"]) && $arOffer["PICTURE"]) {
|
||||
$offer .= "<picture>" . $this->PrepareValue($arOffer["PICTURE"]) . "</picture>\n";
|
||||
}
|
||||
|
||||
$offer .= "<url>" . $this->protocol . $this->serverName . $this->PrepareValue($arOffer['DETAIL_PAGE_URL']) . "</url>\n";
|
||||
|
||||
$offer .= "<price>" . $this->PrepareValue($arOffer['PRICE']) . "</price>\n";
|
||||
|
||||
if ($this->loadPurchasePrice) {
|
||||
if ($arOffer['PURCHASE_PRICE']) {
|
||||
$offer .= "<purchasePrice>" . $this->PrepareValue($arOffer['PURCHASE_PRICE']) . "</purchasePrice>\n";
|
||||
} elseif ("Y" == $this->purchasePriceNull) {
|
||||
$offer .= "<purchasePrice>0</purchasePrice>\n";
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($categories as $category) {
|
||||
$offer .= "<categoryId>" . $category['ID'] . "</categoryId>\n";
|
||||
}
|
||||
|
||||
$offer .= "<name>" . $this->PrepareValue($arOffer["NAME"]) . "</name>\n";
|
||||
|
||||
$offer .= "<xmlId>" . $this->PrepareValue($arOffer["EXTERNAL_ID"]) . "</xmlId>\n";
|
||||
$offer .= "<productName>" . $this->PrepareValue($arOffer["PRODUCT_NAME"]) . "</productName>\n";
|
||||
|
||||
foreach ($this->propertiesProduct[$iblock['ID']] as $key => $propProduct) {
|
||||
if ($propProduct != "" && $arOffer['_PROP_' . $key] != null) {
|
||||
if ($key === "manufacturer") {
|
||||
$offer .= "<vendor>" . $this->PrepareValue($arOffer['_PROP_' . $key]) . "</vendor>\n";
|
||||
} else {
|
||||
$name = $key;
|
||||
|
||||
if (isset($this->localizedIBlockProps[$key])) {
|
||||
$name = $this->localizedIBlockProps[$key];
|
||||
}
|
||||
|
||||
$offer .= '<param name="' . $this->PrepareValue($name) . '" code="' . $key . '"' . (isset($arOffer['_PROP_' . $key . "_UNIT"]) ? ' unit="' . $arOffer['_PROP_' . $key . "_UNIT"] . '"' : "") . ">" . $this->PrepareValue($arOffer['_PROP_' . $key]) . "</param>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($this->propertiesSKU[$iblock['ID']] as $key => $propProduct) {
|
||||
if ($propProduct != "" && $arOffer['_PROP_' . $key] != null) {
|
||||
if ($key === "manufacturer") {
|
||||
$offer .= "<vendor>" . $this->PrepareValue($arOffer['_PROP_' . $key]) . "</vendor>\n";
|
||||
} else {
|
||||
$name = $key;
|
||||
|
||||
if (isset($this->localizedIBlockProps[$key])) {
|
||||
$name = $this->localizedIBlockProps[$key];
|
||||
}
|
||||
|
||||
$offer .= '<param name="' . $this->PrepareValue($name) . '" code="' . $key . '"' . (isset($arOffer['_PROP_' . $key . "_UNIT"]) ? ' unit="' . $arOffer['_PROP_' . $key . "_UNIT"] . '"' : "") . ">" . $this->PrepareValue($arOffer['_PROP_' . $key]) . "</param>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($arOffer["MEASURE"]['SYMBOL_INTL'])) {
|
||||
if ($this->measure[$arOffer["MEASURE"]['SYMBOL_INTL']]) {
|
||||
$offer .= '<unit code="' . $this->measure[$this->PrepareValue($arOffer["MEASURE"]['SYMBOL_INTL'])] . '" />' . "\n";
|
||||
} else {
|
||||
$offer .= '<unit code="' . $this->PrepareValue($arOffer["MEASURE"]['SYMBOL_INTL']) . '" name="' . $this->PrepareValue($arOffer["MEASURE"]['MEASURE_TITLE']) . '" sym="' . $this->PrepareValue($arOffer["MEASURE"]['SYMBOL_RUS']) . '" />' . "\n";
|
||||
}
|
||||
} else {
|
||||
$measure = \Bitrix\Catalog\ProductTable::getCurrentRatioWithMeasure($arOffer["ID"]);
|
||||
|
||||
if ($this->measure[$measure[$arOffer["ID"]]["MEASURE"]['SYMBOL_INTL']]) {
|
||||
$offer .= '<unit code="' . $this->measure[$this->PrepareValue($measure[$arOffer["ID"]]["MEASURE"]['SYMBOL_INTL'])] . '" />' . "\n";
|
||||
} else {
|
||||
$offer .= '<unit code="' . $this->PrepareValue($measure[$arOffer["ID"]]["MEASURE"]['SYMBOL_INTL']) . '" name="' . $this->PrepareValue($measure[$arOffer["ID"]]["MEASURE"]['MEASURE_TITLE']) . '" sym="' . $this->PrepareValue($measure[$arOffer["ID"]]["MEASURE"]['SYMBOL_RUS']) . '" />' . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($arOffer["BARCODE"]) {
|
||||
$offer.= "<barcode>" . $this->PrepareValue($arOffer["BARCODE"]) . "</barcode>\n";
|
||||
}
|
||||
|
||||
if ((float)$arOffer["CATALOG_VAT"]) {
|
||||
$vatRate = $arOffer["CATALOG_VAT"];
|
||||
} else {
|
||||
$vatRate = 'none';
|
||||
}
|
||||
|
||||
$offer.= "<vatRate>" . $this->PrepareValue($vatRate) . "</vatRate>\n";
|
||||
$offer.= "</offer>\n";
|
||||
|
||||
return $offer;
|
||||
}
|
||||
|
||||
private function getHBprop($hbProp, $xml_id)
|
||||
{
|
||||
if (CModule::IncludeModule('highloadblock')) {
|
||||
$hlblockArr = \Bitrix\Highloadblock\HighloadBlockTable::getList(array(
|
||||
'filter' => array('=TABLE_NAME' => $hbProp['USER_TYPE_SETTINGS']['TABLE_NAME'])
|
||||
))->fetch();
|
||||
|
||||
$hlblock = HL\HighloadBlockTable::getById($hlblockArr["ID"])->fetch();
|
||||
$entity = HL\HighloadBlockTable::compileEntity($hlblock);
|
||||
$entityClass = $entity->getDataClass();
|
||||
|
||||
$result = $entityClass::getList(array(
|
||||
'select' => array('*'),
|
||||
'filter' => array('UF_XML_ID' => $xml_id)
|
||||
));
|
||||
|
||||
return $result->fetch();
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns products IDs with barcodes by infoblock id
|
||||
*
|
||||
* @param int $iblockId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getProductBarcodesByIblock($iblockId)
|
||||
{
|
||||
$barcodes = array();
|
||||
$dbBarCode = CCatalogStoreBarCode::getList(
|
||||
array(),
|
||||
array("IBLOCK_ID" => $iblockId),
|
||||
false,
|
||||
false,
|
||||
array('PRODUCT_ID', 'BARCODE')
|
||||
);
|
||||
|
||||
while ($arBarCode = $dbBarCode->GetNext()) {
|
||||
if (!empty($arBarCode)) {
|
||||
$barcodes[$arBarCode['PRODUCT_ID']] = $arBarCode['BARCODE'];
|
||||
}
|
||||
}
|
||||
|
||||
return $barcodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns necessary product properties
|
||||
*
|
||||
* @param int $iblockId
|
||||
* @param array $highloadblockProductProps
|
||||
* @param array $product
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getProductProperties($iblockId, $highloadblockProductProps, $product)
|
||||
{
|
||||
// Get properties of product
|
||||
$resPropertiesProduct = array();
|
||||
|
||||
foreach ($this->propertiesProduct[$iblockId] as $key => $propProduct) {
|
||||
$resPropertiesProduct[$key] = "";
|
||||
|
||||
if ($propProduct != "") {
|
||||
if (isset($product["PROPERTY_" . $propProduct . "_NAME"])) {
|
||||
$resPropertiesProduct[$key] = $product["PROPERTY_" . $propProduct . "_NAME"];
|
||||
} elseif (isset($product["PROPERTY_" . $propProduct . "_VALUE"])) {
|
||||
$resPropertiesProduct[$key] = $product["PROPERTY_" . $propProduct . "_VALUE"];
|
||||
} elseif (isset($product[$propProduct])) {
|
||||
$resPropertiesProduct[$key] = $product[$propProduct];
|
||||
}
|
||||
|
||||
if (array_key_exists($key, $this->propertiesUnitProduct[$iblockId])) {
|
||||
$resPropertiesProduct[$key] *= $this->measurement[$this->propertiesUnitProduct[$iblockId][$key]];
|
||||
$resPropertiesProduct[$key . "_UNIT"] = $this->measurementLink[$this->propertiesUnitProduct[$iblockId][$key]];
|
||||
}
|
||||
|
||||
if (isset($highloadblockProductProps[$propProduct])) {
|
||||
$propVal = $this->getHBprop($highloadblockProductProps[$propProduct], $product["PROPERTY_" . $propProduct . "_VALUE"]);
|
||||
$tableName = $highloadblockProductProps[$propProduct]['USER_TYPE_SETTINGS']['TABLE_NAME'];
|
||||
$field = $this->highloadblockProductProperties[$tableName][$iblockId][$key];
|
||||
|
||||
$resPropertiesProduct[$key] = $propVal[$field];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $resPropertiesProduct;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $allCategories
|
||||
* @param int $iblockId
|
||||
* @param string $productId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getProductCategories(&$allCategories, $iblockId, $productId)
|
||||
{
|
||||
$categories = array();
|
||||
$dbResCategories = CIBlockElement::GetElementGroups($productId, true);
|
||||
|
||||
while ($arResCategory = $dbResCategories->Fetch()) {
|
||||
$categories[$arResCategory["ID"]] = array(
|
||||
'ID' => $arResCategory["ID"],
|
||||
'NAME' => $arResCategory["NAME"],
|
||||
);
|
||||
}
|
||||
|
||||
if (count($categories) == 0) {
|
||||
$catId = $this->mainSection + $iblockId;
|
||||
$categories[$catId] = $allCategories[$catId];
|
||||
}
|
||||
|
||||
return $categories;
|
||||
}
|
||||
|
||||
private function buildProductQuery($iblockId)
|
||||
{
|
||||
$arSelect = array(
|
||||
"ID",
|
||||
"LID",
|
||||
"IBLOCK_ID",
|
||||
"IBLOCK_SECTION_ID",
|
||||
"ACTIVE",
|
||||
"NAME",
|
||||
"DETAIL_PICTURE",
|
||||
"PREVIEW_PICTURE",
|
||||
"DETAIL_PAGE_URL",
|
||||
"CATALOG_GROUP_" . $this->getBasePriceId()
|
||||
);
|
||||
|
||||
// Set selected properties
|
||||
foreach ($this->propertiesProduct[$iblockId] as $key => $propProduct) {
|
||||
if ($this->propertiesProduct[$iblockId][$key] != "") {
|
||||
$arSelect[] = "PROPERTY_" . $propProduct;
|
||||
$arSelect[] = "PROPERTY_" . $propProduct . ".NAME";
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->productPictures && isset($this->productPictures[$iblockId])) {
|
||||
$arSelect[] = "PROPERTY_" . $this->productPictures[$iblockId]['picture'];
|
||||
$arSelect[] = "PROPERTY_" . $this->productPictures[$iblockId]['picture'] . ".NAME";
|
||||
}
|
||||
|
||||
return $arSelect;
|
||||
}
|
||||
|
||||
private function buildOfferQuery($iblockId, $skuPropertyId)
|
||||
{
|
||||
$arSelectOffer = array(
|
||||
'ID',
|
||||
"NAME",
|
||||
"DETAIL_PAGE_URL",
|
||||
"DETAIL_PICTURE",
|
||||
"PREVIEW_PICTURE",
|
||||
'PROPERTY_' . $skuPropertyId,
|
||||
"CATALOG_GROUP_" . $this->getBasePriceId()
|
||||
);
|
||||
|
||||
// Set selected properties
|
||||
foreach ($this->propertiesSKU[$iblockId] as $key => $propSKU) {
|
||||
if ($this->propertiesSKU[$iblockId][$key] != "") {
|
||||
$arSelectOffer[] = "PROPERTY_" . $propSKU;
|
||||
$arSelectOffer[] = "PROPERTY_" . $propSKU . ".NAME";
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->skuPictures && isset($this->skuPictures[$iblockId])) {
|
||||
$arSelectOffer[] = "PROPERTY_" . $this->skuPictures[$iblockId]['picture'];
|
||||
$arSelectOffer[] = "PROPERTY_" . $this->skuPictures[$iblockId]['picture'] . ".NAME";
|
||||
}
|
||||
|
||||
return $arSelectOffer;
|
||||
}
|
||||
|
||||
private function getAvailableHighloadProductProps($iblockId)
|
||||
{
|
||||
$highloadblockProductProps = array();
|
||||
$productProps = CIBlockproperty::GetList(array(), array("IBLOCK_ID" => $iblockId));
|
||||
|
||||
while ($arrProductProps = $productProps->Fetch()) {
|
||||
if ($arrProductProps["USER_TYPE"] == 'directory') {
|
||||
$highloadblockProductProps[$arrProductProps['CODE']] = $arrProductProps;
|
||||
}
|
||||
}
|
||||
|
||||
return $highloadblockProductProps;
|
||||
}
|
||||
|
||||
private function getAvailableHighloadOfferSkuProps($iblockId)
|
||||
{
|
||||
$highloadblockSkuProps = array();
|
||||
$skuProps = CIBlockproperty::GetList(array(), array("IBLOCK_ID" => $iblockId));
|
||||
|
||||
while ($arrSkuProps = $skuProps->Fetch()) {
|
||||
if ($arrSkuProps["USER_TYPE"] == 'directory') {
|
||||
$highloadblockSkuProps[$arrSkuProps['CODE']] = $arrSkuProps;
|
||||
}
|
||||
}
|
||||
|
||||
return $highloadblockSkuProps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns base price id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getBasePriceId()
|
||||
{
|
||||
$basePriceId = COption::GetOptionString(
|
||||
$this->MODULE_ID,
|
||||
$this->CRM_CATALOG_BASE_PRICE . '_' . $this->profileID,
|
||||
0
|
||||
);
|
||||
|
||||
if (!$basePriceId) {
|
||||
$dbPriceType = CCatalogGroup::GetList(
|
||||
array(),
|
||||
array('BASE' => 'Y'),
|
||||
false,
|
||||
false,
|
||||
array('ID')
|
||||
);
|
||||
|
||||
$result = $dbPriceType->GetNext();
|
||||
$basePriceId = $result['ID'];
|
||||
}
|
||||
|
||||
return $basePriceId;
|
||||
}
|
||||
|
||||
private function getLocalizedIBlockProps()
|
||||
{
|
||||
return array(
|
||||
"article" => GetMessage("PROPERTY_ARTICLE_HEADER_NAME"),
|
||||
"manufacturer" => GetMessage("PROPERTY_MANUFACTURER_HEADER_NAME"),
|
||||
"color" => GetMessage("PROPERTY_COLOR_HEADER_NAME"),
|
||||
"size" => GetMessage("PROPERTY_SIZE_HEADER_NAME"),
|
||||
"weight" => GetMessage("PROPERTY_WEIGHT_HEADER_NAME"),
|
||||
"length" => GetMessage("PROPERTY_LENGTH_HEADER_NAME"),
|
||||
"width" => GetMessage("PROPERTY_WIDTH_HEADER_NAME"),
|
||||
"height" => GetMessage("PROPERTY_HEIGHT_HEADER_NAME"),
|
||||
"picture" => GetMessage("PROPERTY_PICTURE_HEADER_NAME")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $fileId
|
||||
* @return string
|
||||
*/
|
||||
public function getImageUrl($fileId)
|
||||
{
|
||||
$pathImage = CFile::GetPath($fileId);
|
||||
$validation = "/^(http|https):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i";
|
||||
|
||||
if ((bool)preg_match($validation, $pathImage) === false) {
|
||||
return $this->protocol . $this->serverName . $pathImage;
|
||||
} else {
|
||||
return $pathImage;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,2 @@
|
||||
- Исправлено формирование картинок в ICML при включеном CDN
|
||||
- Убрана некорректная запись внешнего идентификатора платежа для новых платежей по истории
|
||||
- Добавлена проверка на длину email при отправке в систему
|
||||
- Переработан генератор ICML каталога;
|
||||
- Скидка на позицию больше не учитывается в заказе при установке произвольной цены для позиции.
|
@ -1,59 +1,65 @@
|
||||
<?php
|
||||
if (file_exists($_SERVER["DOCUMENT_ROOT"]."/bitrix/php_interface/retailcrm/export_run.php")){
|
||||
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/php_interface/retailcrm/export_run.php");
|
||||
|
||||
use Bitrix\Highloadblock\HighloadBlockTable;
|
||||
use Intaro\RetailCrm\Icml\IcmlDirector;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetupProps;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetupPropsCategories;
|
||||
use Intaro\RetailCrm\Repository\CatalogRepository;
|
||||
|
||||
if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/bitrix/php_interface/retailcrm/export_run.php')) {
|
||||
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/php_interface/retailcrm/export_run.php');
|
||||
} else {
|
||||
ignore_user_abort(true);
|
||||
set_time_limit(0);
|
||||
|
||||
global $APPLICATION;
|
||||
if (!CModule::IncludeModule("iblock")){
|
||||
return;
|
||||
}
|
||||
if (!CModule::IncludeModule("catalog")){
|
||||
return;
|
||||
}
|
||||
if (!CModule::IncludeModule("intaro.retailcrm")){
|
||||
return;
|
||||
}
|
||||
|
||||
$rsSites = CSite::GetList($by, $sort, array('ACTIVE' => 'Y'));
|
||||
while ($ar = $rsSites->Fetch()) {
|
||||
if ($ar['DEF'] == 'Y') {
|
||||
$SERVER_NAME = $ar['SERVER_NAME'];
|
||||
}
|
||||
if (
|
||||
!CModule::IncludeModule('iblock')
|
||||
|| !CModule::IncludeModule('catalog')
|
||||
|| !CModule::IncludeModule('intaro.retailcrm')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$hlblockModule = false;
|
||||
|
||||
if (CModule::IncludeModule('highloadblock')) {
|
||||
$hlblockModule = true;
|
||||
$hlblockList = array();
|
||||
$hlblockListDb = \Bitrix\Highloadblock\HighloadBlockTable::getList();
|
||||
$hlblockList = [];
|
||||
$hlblockListDb = HighloadBlockTable::getList();
|
||||
|
||||
while ($hlblockArr = $hlblockListDb->Fetch()) {
|
||||
$hlblockList[$hlblockArr["TABLE_NAME"]] = $hlblockArr;
|
||||
}
|
||||
}
|
||||
|
||||
$iblockProperties = array(
|
||||
"article" => "article",
|
||||
"manufacturer" => "manufacturer",
|
||||
"color" =>"color",
|
||||
"weight" => "weight",
|
||||
"size" => "size",
|
||||
"length" => "length",
|
||||
"width" => "width",
|
||||
"height" => "height",
|
||||
);
|
||||
$IBLOCK_PROPERTY_SKU = array();
|
||||
$IBLOCK_PROPERTY_SKU_HIGHLOADBLOCK = array();
|
||||
$IBLOCK_PROPERTY_UNIT_SKU = array();
|
||||
$iblockProperties = [
|
||||
'article' => 'article',
|
||||
'manufacturer' => 'manufacturer',
|
||||
'color' => 'color',
|
||||
'weight' => 'weight',
|
||||
'size' => 'size',
|
||||
'length' => 'length',
|
||||
'width' => 'width',
|
||||
'height' => 'height',
|
||||
];
|
||||
|
||||
$iblockPropertySku = [];
|
||||
$iblockPropertySkuHl = [];
|
||||
$iblockPropertyUnitSku = [];
|
||||
$iblockPropertyProduct = [];
|
||||
$iblockPropertyProductHl = [];
|
||||
$iblockPropertyUnitProduct = [];
|
||||
|
||||
foreach ($iblockProperties as $prop) {
|
||||
$skuUnitProps = ('IBLOCK_PROPERTY_UNIT_SKU' . "_" . $prop);
|
||||
$skuUnitProps = $$skuUnitProps;
|
||||
|
||||
if (is_array($skuUnitProps)) {
|
||||
foreach ($skuUnitProps as $iblock => $val) {
|
||||
$IBLOCK_PROPERTY_UNIT_SKU[$iblock][$prop] = $val;
|
||||
$iblockPropertyUnitSku[$iblock][$prop] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,7 +67,7 @@ if (file_exists($_SERVER["DOCUMENT_ROOT"]."/bitrix/php_interface/retailcrm/expor
|
||||
$skuProps = $$skuProps;
|
||||
if (is_array($skuProps)) {
|
||||
foreach ($skuProps as $iblock => $val) {
|
||||
$IBLOCK_PROPERTY_SKU[$iblock][$prop] = $val;
|
||||
$iblockPropertySku[$iblock][$prop] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,22 +78,17 @@ if (file_exists($_SERVER["DOCUMENT_ROOT"]."/bitrix/php_interface/retailcrm/expor
|
||||
|
||||
if (is_array($hbProps)) {
|
||||
foreach ($hbProps as $iblock => $val) {
|
||||
$IBLOCK_PROPERTY_SKU_HIGHLOADBLOCK[$hlblockTable][$iblock][$prop] = $val;
|
||||
}
|
||||
$iblockPropertySkuHl[$hlblockTable][$iblock][$prop] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$IBLOCK_PROPERTY_PRODUCT = array();
|
||||
$IBLOCK_PROPERTY_PRODUCT_HIGHLOADBLOCK = array();
|
||||
$IBLOCK_PROPERTY_UNIT_PRODUCT = array();
|
||||
foreach ($iblockProperties as $prop) {
|
||||
$productUnitProps = "IBLOCK_PROPERTY_UNIT_PRODUCT" . "_" . $prop;
|
||||
$productUnitProps = $$productUnitProps;
|
||||
if (is_array($productUnitProps)) {
|
||||
foreach ($productUnitProps as $iblock => $val) {
|
||||
$IBLOCK_PROPERTY_UNIT_PRODUCT[$iblock][$prop] = $val;
|
||||
$iblockPropertyUnitProduct[$iblock][$prop] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,7 +96,7 @@ if (file_exists($_SERVER["DOCUMENT_ROOT"]."/bitrix/php_interface/retailcrm/expor
|
||||
$productProps = $$productProps;
|
||||
if (is_array($productProps)) {
|
||||
foreach ($productProps as $iblock => $val) {
|
||||
$IBLOCK_PROPERTY_PRODUCT[$iblock][$prop] = $val;
|
||||
$iblockPropertyProduct[$iblock][$prop] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,51 +107,52 @@ if (file_exists($_SERVER["DOCUMENT_ROOT"]."/bitrix/php_interface/retailcrm/expor
|
||||
|
||||
if (is_array($hbProps)) {
|
||||
foreach ($hbProps as $iblock => $val) {
|
||||
$IBLOCK_PROPERTY_PRODUCT_HIGHLOADBLOCK[$hlblockTable][$iblock][$prop] = $val;
|
||||
$iblockPropertyProductHl[$hlblockTable][$iblock][$prop] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$productPictures = array();
|
||||
$productPictures = [];
|
||||
|
||||
if (is_array($IBLOCK_PROPERTY_PRODUCT_picture)) {
|
||||
foreach ($IBLOCK_PROPERTY_PRODUCT_picture as $key => $value) {
|
||||
$productPictures[$key]['picture'] = $value;
|
||||
$productPictures[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$skuPictures = array();
|
||||
$skuPictures = [];
|
||||
|
||||
if (is_array($IBLOCK_PROPERTY_SKU_picture)) {
|
||||
foreach ($IBLOCK_PROPERTY_SKU_picture as $key => $value) {
|
||||
$skuPictures[$key]['picture'] = $value;
|
||||
$skuPictures[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$loader = new RetailCrmICML();
|
||||
$loader->profileID = $profile_id;
|
||||
$loader->iblocks = $IBLOCK_EXPORT;
|
||||
$loader->propertiesSKU = $IBLOCK_PROPERTY_SKU;
|
||||
$loader->propertiesUnitSKU = $IBLOCK_PROPERTY_UNIT_SKU;
|
||||
$loader->propertiesProduct = $IBLOCK_PROPERTY_PRODUCT;
|
||||
$loader->propertiesUnitProduct = $IBLOCK_PROPERTY_UNIT_PRODUCT;
|
||||
$loader->productPictures = $productPictures;
|
||||
$loader->skuPictures = $skuPictures;
|
||||
$xmlProps = new XmlSetupPropsCategories(
|
||||
new XmlSetupProps($iblockPropertyProduct, $iblockPropertyUnitProduct, $productPictures),
|
||||
new XmlSetupProps($iblockPropertySku, $iblockPropertyUnitSku, $skuPictures)
|
||||
);
|
||||
|
||||
if ($hlblockModule === true) {
|
||||
$loader->highloadblockSkuProperties = $IBLOCK_PROPERTY_SKU_HIGHLOADBLOCK;
|
||||
$loader->highloadblockProductProperties = $IBLOCK_PROPERTY_PRODUCT_HIGHLOADBLOCK;
|
||||
$xmlProps->highloadblockSku = $iblockPropertySkuHl;
|
||||
$xmlProps->highloadblockProduct = $iblockPropertyProductHl;
|
||||
}
|
||||
|
||||
if ($MAX_OFFERS_VALUE) {
|
||||
$loader->offerPageSize = $MAX_OFFERS_VALUE;
|
||||
}
|
||||
$fileSetup = new XmlSetup($xmlProps);
|
||||
$fileSetup->profileId = $profile_id;
|
||||
$fileSetup->iblocksForExport = $IBLOCK_EXPORT;
|
||||
$fileSetup->maxOffersValue = $MAX_OFFERS_VALUE ?? null;
|
||||
$fileSetup->filePath = $SETUP_FILE_NAME;
|
||||
$fileSetup->loadPurchasePrice = $LOAD_PURCHASE_PRICE === 'Y';
|
||||
$fileSetup->basePriceId = CatalogRepository::getBasePriceId($fileSetup->profileId);
|
||||
$logger = Logger::getInstance('/bitrix/catalog_export/');
|
||||
|
||||
$loader->filename = $SETUP_FILE_NAME;
|
||||
$loader->defaultServerName = $SERVER_NAME;
|
||||
$loader->application = $APPLICATION;
|
||||
$loader->loadPurchasePrice = $LOAD_PURCHASE_PRICE == 'Y';
|
||||
$loader->Load();
|
||||
if (!is_array($fileSetup->iblocksForExport) || count($fileSetup->iblocksForExport) === 0) {
|
||||
$logger->write(GetMessage("IBLOCK_NOT_SELECTED"), 'i_crm_load_log');
|
||||
} else {
|
||||
$loader = new IcmlDirector($fileSetup, $logger);
|
||||
$loader->generateXml();
|
||||
}
|
||||
}
|
@ -1,13 +1,16 @@
|
||||
<?
|
||||
|
||||
use Bitrix\Highloadblock\HighloadBlockTable;
|
||||
|
||||
if (file_exists($_SERVER["DOCUMENT_ROOT"]."/bitrix/php_interface/retailcrm/export_setup.php")){
|
||||
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/php_interface/retailcrm/export_setup.php");
|
||||
} else {
|
||||
if (isset($_POST['ajax']) && $_POST['ajax'] == '1') {
|
||||
CModule::IncludeModule('highloadblock');
|
||||
$rsData = \Bitrix\Highloadblock\HighloadBlockTable::getList(array('filter' => array('TABLE_NAME' => $_POST['table'])));
|
||||
$rsData = HighloadBlockTable::getList(['filter' => ['TABLE_NAME' => $_POST['table']]]);
|
||||
$hlblockArr = $rsData->Fetch();
|
||||
$hlblock = \Bitrix\Highloadblock\HighloadBlockTable::getById($hlblockArr["ID"])->fetch();
|
||||
$entity = \Bitrix\Highloadblock\HighloadBlockTable::compileEntity($hlblock);
|
||||
$hlblock = HighloadBlockTable::getById($hlblockArr["ID"])->fetch();
|
||||
$entity = HighloadBlockTable::compileEntity($hlblock);
|
||||
$hbFields = $entity->getFields();
|
||||
$hlblockList['table'] = $hlblockArr["TABLE_NAME"];
|
||||
|
||||
@ -55,11 +58,11 @@ if (file_exists($_SERVER["DOCUMENT_ROOT"]."/bitrix/php_interface/retailcrm/expor
|
||||
if (CModule::IncludeModule('highloadblock')) {
|
||||
$hlblockModule = true;
|
||||
$hlblockList = array();
|
||||
$hlblockListDb = \Bitrix\Highloadblock\HighloadBlockTable::getList();
|
||||
$hlblockListDb = HighloadBlockTable::getList();
|
||||
|
||||
while ($hlblockArr = $hlblockListDb->Fetch()) {
|
||||
$hlblock = \Bitrix\Highloadblock\HighloadBlockTable::getById($hlblockArr["ID"])->fetch();
|
||||
$entity = \Bitrix\Highloadblock\HighloadBlockTable::compileEntity($hlblock);
|
||||
$hlblock = HighloadBlockTable::getById($hlblockArr["ID"])->fetch();
|
||||
$entity = HighloadBlockTable::compileEntity($hlblock);
|
||||
$hbFields = $entity->getFields();
|
||||
$hlblockList[$hlblockArr["TABLE_NAME"]]['LABEL'] = $hlblockArr["NAME"];
|
||||
|
||||
|
@ -14,7 +14,6 @@ CModule::AddAutoloadClasses(
|
||||
'RetailCrmUser' => file_exists($server . '/bitrix/php_interface/retailcrm/RetailCrmUser.php') ? '../../php_interface/retailcrm/RetailCrmUser.php' : 'classes/general/user/RetailCrmUser.php',
|
||||
'RetailCrmOrder' => file_exists($server . '/bitrix/php_interface/retailcrm/RetailCrmOrder.php') ? '../../php_interface/retailcrm/RetailCrmOrder.php' : 'classes/general/order/RetailCrmOrder_' . $version . '.php',
|
||||
'RetailCrmHistory' => file_exists($server . '/bitrix/php_interface/retailcrm/RetailCrmHistory.php') ? '../../php_interface/retailcrm/RetailCrmHistory.php' : 'classes/general/history/RetailCrmHistory_' . $version . '.php',
|
||||
'RetailCrmICML' => file_exists($server . '/bitrix/php_interface/retailcrm/RetailCrmICML.php') ? '../../php_interface/retailcrm/RetailCrmICML.php' : 'classes/general/icml/RetailCrmICML.php',
|
||||
'RetailCrmInventories' => file_exists($server . '/bitrix/php_interface/retailcrm/RetailCrmInventories.php') ? '../../php_interface/retailcrm/RetailCrmInventories.php' : 'classes/general/inventories/RetailCrmInventories.php',
|
||||
'RetailCrmPrices' => file_exists($server . '/bitrix/php_interface/retailcrm/RetailCrmPrices.php') ? '../../php_interface/retailcrm/RetailCrmPrices.php' : 'classes/general/prices/RetailCrmPrices.php',
|
||||
'RetailCrmCollector' => file_exists($server . '/bitrix/php_interface/retailcrm/RetailCrmCollector.php') ? '../../php_interface/retailcrm/RetailCrmCollector.php' : 'classes/general/collector/RetailCrmCollector.php',
|
||||
|
@ -6,73 +6,74 @@
|
||||
* Class name: intaro_retailcrm
|
||||
*/
|
||||
global $MESS;
|
||||
use Bitrix\Main\Context;
|
||||
use Intaro\RetailCrm\Icml\IcmlDirector;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetupProps;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetupPropsCategories;
|
||||
use Intaro\RetailCrm\Repository\CatalogRepository;
|
||||
use Intaro\RetailCrm\Vendor\Symfony\Component\Process\PhpExecutableFinder;
|
||||
use RetailCrm\Exception\CurlException;
|
||||
use RetailCrm\Response\ApiResponse;
|
||||
|
||||
IncludeModuleLangFile(__FILE__);
|
||||
if (class_exists('intaro_retailcrm'))
|
||||
return;
|
||||
|
||||
class intaro_retailcrm extends CModule
|
||||
{
|
||||
var $MODULE_ID = 'intaro.retailcrm';
|
||||
var $OLD_MODULE_ID = 'intaro.intarocrm';
|
||||
var $MODULE_VERSION;
|
||||
var $MODULE_VERSION_DATE;
|
||||
var $MODULE_NAME;
|
||||
var $MODULE_DESCRIPTION;
|
||||
var $MODULE_GROUP_RIGHTS = 'N';
|
||||
|
||||
var $PARTNER_NAME;
|
||||
var $PARTNER_URI;
|
||||
|
||||
var $RETAIL_CRM_API;
|
||||
var $RETAIL_CRM_EXPORT = 'retailcrm';
|
||||
var $CRM_API_HOST_OPTION = 'api_host';
|
||||
var $CRM_API_KEY_OPTION = 'api_key';
|
||||
var $CRM_SITES_LIST= 'sites_list';
|
||||
var $CRM_ORDER_TYPES_ARR = 'order_types_arr';
|
||||
var $CRM_DELIVERY_TYPES_ARR = 'deliv_types_arr';
|
||||
var $CRM_DELIVERY_SERVICES_ARR = 'deliv_services_arr';
|
||||
var $CRM_PAYMENT_TYPES = 'pay_types_arr';
|
||||
var $CRM_PAYMENT_STATUSES = 'pay_statuses_arr';
|
||||
var $CRM_PAYMENT = 'payment_arr'; //order payment Y/N
|
||||
var $CRM_ORDER_LAST_ID = 'order_last_id';
|
||||
var $CRM_ORDER_PROPS = 'order_props';
|
||||
var $CRM_LEGAL_DETAILS = 'legal_details';
|
||||
var $CRM_CUSTOM_FIELDS = 'custom_fields';
|
||||
var $CRM_CONTRAGENT_TYPE = 'contragent_type';
|
||||
var $CRM_ORDER_DISCHARGE = 'order_discharge';
|
||||
var $CRM_ORDER_FAILED_IDS = 'order_failed_ids';
|
||||
var $CRM_ORDER_HISTORY = 'order_history';
|
||||
var $CRM_CUSTOMER_HISTORY = 'customer_history';
|
||||
var $CRM_CATALOG_BASE_PRICE = 'catalog_base_price';
|
||||
public $MODULE_ID = 'intaro.retailcrm';
|
||||
public $OLD_MODULE_ID = 'intaro.intarocrm';
|
||||
public $MODULE_VERSION;
|
||||
public $MODULE_VERSION_DATE;
|
||||
public $MODULE_NAME;
|
||||
public $MODULE_DESCRIPTION;
|
||||
public $MODULE_GROUP_RIGHTS = 'N';
|
||||
public $PARTNER_NAME;
|
||||
public $PARTNER_URI;
|
||||
public $RETAIL_CRM_API;
|
||||
public $RETAIL_CRM_EXPORT = 'retailcrm';
|
||||
public $CRM_API_HOST_OPTION = 'api_host';
|
||||
public $CRM_API_KEY_OPTION = 'api_key';
|
||||
public $CRM_SITES_LIST = 'sites_list';
|
||||
public $CRM_ORDER_TYPES_ARR = 'order_types_arr';
|
||||
public $CRM_DELIVERY_TYPES_ARR = 'deliv_types_arr';
|
||||
public $CRM_DELIVERY_SERVICES_ARR = 'deliv_services_arr';
|
||||
public $CRM_PAYMENT_TYPES = 'pay_types_arr';
|
||||
public $CRM_PAYMENT_STATUSES = 'pay_statuses_arr';
|
||||
public $CRM_PAYMENT = 'payment_arr'; //order payment Y/N
|
||||
public $CRM_ORDER_LAST_ID = 'order_last_id';
|
||||
public $CRM_ORDER_PROPS = 'order_props';
|
||||
public $CRM_LEGAL_DETAILS = 'legal_details';
|
||||
public $CRM_CUSTOM_FIELDS = 'custom_fields';
|
||||
public $CRM_CONTRAGENT_TYPE = 'contragent_type';
|
||||
public $CRM_ORDER_DISCHARGE = 'order_discharge';
|
||||
public $CRM_ORDER_FAILED_IDS = 'order_failed_ids';
|
||||
public $CRM_ORDER_HISTORY = 'order_history';
|
||||
public $CRM_CUSTOMER_HISTORY = 'customer_history';
|
||||
public $CRM_CATALOG_BASE_PRICE = 'catalog_base_price';
|
||||
//var $CRM_CATALOG_IBLOCKS = 'catalog_base_iblocks';
|
||||
var $CRM_ORDER_NUMBERS = 'order_numbers';
|
||||
var $CRM_CANSEL_ORDER = 'cansel_order';
|
||||
var $CRM_CURRENCY = 'currency';
|
||||
var $CRM_ADDRESS_OPTIONS = 'address_options';
|
||||
|
||||
var $CRM_INVENTORIES_UPLOAD = 'inventories_upload';
|
||||
var $CRM_STORES = 'stores';
|
||||
var $CRM_SHOPS = 'shops';
|
||||
var $CRM_IBLOCKS_INVENTORIES = 'iblocks_inventories';
|
||||
|
||||
var $CRM_PRICES_UPLOAD = 'prices_upload';
|
||||
var $CRM_PRICES = 'prices';
|
||||
var $CRM_PRICE_SHOPS = 'price_shops';
|
||||
var $CRM_IBLOCKS_PRICES = 'iblock_prices';
|
||||
|
||||
var $CRM_COLLECTOR = 'collector';
|
||||
var $CRM_COLL_KEY = 'coll_key';
|
||||
|
||||
var $CRM_UA = 'ua';
|
||||
var $CRM_UA_KEYS = 'ua_keys';
|
||||
|
||||
var $CRM_API_VERSION = 'api_version';
|
||||
var $HISTORY_TIME = 'history_time';
|
||||
|
||||
var $CLIENT_ID = 'client_id';
|
||||
var $PROTOCOL = 'protocol';
|
||||
|
||||
var $INSTALL_PATH;
|
||||
public $CRM_ORDER_NUMBERS = 'order_numbers';
|
||||
public $CRM_CANSEL_ORDER = 'cansel_order';
|
||||
public $CRM_CURRENCY = 'currency';
|
||||
public $CRM_ADDRESS_OPTIONS = 'address_options';
|
||||
public $CRM_INVENTORIES_UPLOAD = 'inventories_upload';
|
||||
public $CRM_STORES = 'stores';
|
||||
public $CRM_SHOPS = 'shops';
|
||||
public $CRM_IBLOCKS_INVENTORIES = 'iblocks_inventories';
|
||||
public $CRM_PRICES_UPLOAD = 'prices_upload';
|
||||
public $CRM_PRICES = 'prices';
|
||||
public $CRM_PRICE_SHOPS = 'price_shops';
|
||||
public $CRM_IBLOCKS_PRICES = 'iblock_prices';
|
||||
public $CRM_COLLECTOR = 'collector';
|
||||
public $CRM_COLL_KEY = 'coll_key';
|
||||
public $CRM_UA = 'ua';
|
||||
public $CRM_UA_KEYS = 'ua_keys';
|
||||
public $CRM_API_VERSION = 'api_version';
|
||||
public $HISTORY_TIME = 'history_time';
|
||||
public $CLIENT_ID = 'client_id';
|
||||
public $PROTOCOL = 'protocol';
|
||||
public $INSTALL_PATH;
|
||||
|
||||
function intaro_retailcrm()
|
||||
{
|
||||
@ -94,6 +95,7 @@ class intaro_retailcrm extends CModule
|
||||
if (!class_exists('RetailcrmConstants')) {
|
||||
require_once dirname(__FILE__) . '/../classes/general/RetailcrmConstants.php';
|
||||
}
|
||||
|
||||
if (!class_exists('RetailcrmConfigProvider')) {
|
||||
require_once dirname(__FILE__) . '/../classes/general/RetailcrmConfigProvider.php';
|
||||
}
|
||||
@ -136,7 +138,33 @@ class intaro_retailcrm extends CModule
|
||||
include($this->INSTALL_PATH . '/../classes/general/RCrmActions.php');
|
||||
include($this->INSTALL_PATH . '/../classes/general/user/RetailCrmUser.php');
|
||||
include($this->INSTALL_PATH . '/../classes/general/events/RetailCrmEvent.php');
|
||||
include($this->INSTALL_PATH . '/../classes/general/icml/RetailCrmICML.php');
|
||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/offerparam.php');
|
||||
include($this->INSTALL_PATH . '/../lib/component/agent.php');
|
||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/selectparams.php');
|
||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/unit.php');
|
||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmlcategory.php');
|
||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmldata.php');
|
||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmloffer.php');
|
||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmlsetup.php');
|
||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmlsetupprops.php');
|
||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmlsetuppropscategories.php');
|
||||
include($this->INSTALL_PATH . '/../lib/icml/icmldirector.php');
|
||||
include($this->INSTALL_PATH . '/../lib/icml/icmlwriter.php');
|
||||
include($this->INSTALL_PATH . '/../lib/icml/queryparamsmolder.php');
|
||||
include($this->INSTALL_PATH . '/../lib/icml/xmlcategorydirector.php');
|
||||
include($this->INSTALL_PATH . '/../lib/icml/xmlcategoryfactory.php');
|
||||
include($this->INSTALL_PATH . '/../lib/icml/xmlofferdirector.php');
|
||||
include($this->INSTALL_PATH . '/../lib/icml/xmlofferbuilder.php');
|
||||
include($this->INSTALL_PATH . '/../lib/icml/utils/icmlutils.php');
|
||||
include($this->INSTALL_PATH . '/../lib/repository/catalogrepository.php');
|
||||
include($this->INSTALL_PATH . '/../lib/repository/filerepository.php');
|
||||
include($this->INSTALL_PATH . '/../lib/repository/hlrepository.php');
|
||||
include($this->INSTALL_PATH . '/../lib/repository/measurerepository.php');
|
||||
include($this->INSTALL_PATH . '/../lib/repository/siterepository.php');
|
||||
include($this->INSTALL_PATH . '/../lib/service/hl.php');
|
||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/orm/catalogiblockinfo.php');
|
||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/orm/iblockcatalog.php');
|
||||
include($this->INSTALL_PATH . '/../classes/general/RetailcrmConstants.php');
|
||||
include($this->INSTALL_PATH . '/../classes/general/Exception/InvalidJsonException.php');
|
||||
include($this->INSTALL_PATH . '/../classes/general/Exception/CurlException.php');
|
||||
include($this->INSTALL_PATH . '/../classes/general/RestNormalizer.php');
|
||||
@ -367,7 +395,7 @@ class intaro_retailcrm extends CModule
|
||||
$arResult['paymentStatusesList'] = $this->RETAIL_CRM_API->paymentStatusesList()->paymentStatuses;
|
||||
$arResult['paymentList'] = $this->RETAIL_CRM_API->statusesList()->statuses;
|
||||
$arResult['paymentGroupList'] = $this->RETAIL_CRM_API->statusGroupsList()->statusGroups;
|
||||
} catch (\RetailCrm\Exception\CurlException $e) {
|
||||
} catch (CurlException $e) {
|
||||
RCrmActions::eventLog(
|
||||
'intaro.retailcrm/install/index.php', 'RetailCrm\ApiClient::*List::CurlException',
|
||||
$e->getCode() . ': ' . $e->getMessage()
|
||||
@ -477,7 +505,7 @@ class intaro_retailcrm extends CModule
|
||||
'description' => RCrmActions::toJSON($deliveryType['DESCRIPTION']),
|
||||
'paymentTypes' => ''
|
||||
)));
|
||||
} catch (\RetailCrm\Exception\CurlException $e) {
|
||||
} catch (CurlException $e) {
|
||||
$load = false;
|
||||
RCrmActions::eventLog(
|
||||
'intaro.crm/install/index.php', 'RetailCrm\ApiClient::deliveryTypeEdit::CurlException',
|
||||
@ -496,7 +524,7 @@ class intaro_retailcrm extends CModule
|
||||
'name' => RCrmActions::toJSON($deliveryService['NAME']),
|
||||
'deliveryType' => $deliveryType['ID']
|
||||
)));
|
||||
} catch (\RetailCrm\Exception\CurlException $e) {
|
||||
} catch (CurlException $e) {
|
||||
RCrmActions::eventLog(
|
||||
'intaro.crm/install/index.php', 'RetailCrm\ApiClient::deliveryServiceEdit::CurlException',
|
||||
$e->getCode() . ': ' . $e->getMessage()
|
||||
@ -722,7 +750,7 @@ class intaro_retailcrm extends CModule
|
||||
if ($historyDate = COption::GetOptionString($this->OLD_MODULE_ID, 'order_history_date', 0)) {
|
||||
try {
|
||||
$history = $api->ordersHistory(array('startDate' => $historyDate));
|
||||
} catch (\RetailCrm\Exception\CurlException $e) {
|
||||
} catch (CurlException $e) {
|
||||
RCrmActions::eventLog(
|
||||
'intaro.retailcrm/install/index.php', 'RetailCrm\RestApi::ordersHistory::CurlException',
|
||||
$e->getCode() . ': ' . $e->getMessage()
|
||||
@ -903,9 +931,9 @@ class intaro_retailcrm extends CModule
|
||||
}
|
||||
|
||||
if (!isset($_POST['MAX_OFFERS_VALUE'])) {
|
||||
$maxOffers = "";
|
||||
$maxOffers = null;
|
||||
} else {
|
||||
$maxOffers = $_POST['MAX_OFFERS_VALUE'];
|
||||
$maxOffers = (int) $_POST['MAX_OFFERS_VALUE'];
|
||||
}
|
||||
|
||||
if (!isset($_POST['SETUP_PROFILE_NAME'])) {
|
||||
@ -970,44 +998,24 @@ class intaro_retailcrm extends CModule
|
||||
);
|
||||
|
||||
$this->CopyFiles();
|
||||
if (isset($_POST['LOAD_NOW'])) {
|
||||
$loader = new RetailCrmICML();
|
||||
$loader->iblocks = $iblocks;
|
||||
$loader->propertiesUnitProduct = $propertiesUnitProduct;
|
||||
$loader->propertiesProduct = $propertiesProduct;
|
||||
$loader->propertiesUnitSKU = $propertiesUnitSKU;
|
||||
$loader->propertiesSKU = $propertiesSKU;
|
||||
|
||||
if ($hlblockModule === true) {
|
||||
$loader->highloadblockSkuProperties = $propertiesHbSKU;
|
||||
$loader->highloadblockProductProperties = $propertiesHbProduct;
|
||||
}
|
||||
|
||||
if ($maxOffers) {
|
||||
$loader->offerPageSize = $maxOffers;
|
||||
}
|
||||
|
||||
$loader->filename = $filename;
|
||||
$loader->serverName = \Bitrix\Main\Context::getCurrent()->getServer()->getHttpHost();
|
||||
$loader->application = $APPLICATION;
|
||||
$loader->Load();
|
||||
}
|
||||
|
||||
COption::RemoveOption($this->MODULE_ID, $this->CRM_CATALOG_BASE_PRICE);
|
||||
|
||||
if ($typeLoading == 'agent' || $typeLoading == 'cron') {
|
||||
if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/bitrix/php_interface/include/catalog_export/' . $this->RETAIL_CRM_EXPORT . '_run.php')) {
|
||||
$dbProfile = CCatalogExport::GetList(array(), array("FILE_NAME" => $this->RETAIL_CRM_EXPORT));
|
||||
if (
|
||||
file_exists($_SERVER['DOCUMENT_ROOT']
|
||||
. '/bitrix/php_interface/include/catalog_export/'
|
||||
. $this->RETAIL_CRM_EXPORT
|
||||
. '_run.php')
|
||||
) {
|
||||
$dbProfile = CCatalogExport::GetList([], ['FILE_NAME' => $this->RETAIL_CRM_EXPORT]);
|
||||
|
||||
if ($dbProfile instanceof CDBResult) {
|
||||
$this->removeExportProfiles($dbProfile);
|
||||
|
||||
while ($arProfile = $dbProfile->Fetch()) {
|
||||
if ($arProfile["DEFAULT_PROFILE"] != "Y") {
|
||||
CAgent::RemoveAgent("CCatalogExport::PreGenerateExport(" . $arProfile['ID'] . ");", "catalog");
|
||||
CCatalogExport::Delete($arProfile['ID']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ar = $this->GetProfileSetupVars(
|
||||
$setupVars = $this->getProfileSetupVars(
|
||||
$iblocks,
|
||||
$propertiesProduct,
|
||||
$propertiesUnitProduct,
|
||||
@ -1018,7 +1026,7 @@ class intaro_retailcrm extends CModule
|
||||
$filename,
|
||||
$maxOffers
|
||||
);
|
||||
$PROFILE_ID = CCatalogExport::Add(array(
|
||||
$profileId = CCatalogExport::Add([
|
||||
"LAST_USE" => false,
|
||||
"FILE_NAME" => $this->RETAIL_CRM_EXPORT,
|
||||
"NAME" => $profileName,
|
||||
@ -1027,9 +1035,10 @@ class intaro_retailcrm extends CModule
|
||||
"IN_AGENT" => "N",
|
||||
"IN_CRON" => "N",
|
||||
"NEED_EDIT" => "N",
|
||||
"SETUP_VARS" => $ar
|
||||
));
|
||||
if (intval($PROFILE_ID) <= 0) {
|
||||
"SETUP_VARS" => $setupVars,
|
||||
]);
|
||||
|
||||
if ((int) $profileId <= 0) {
|
||||
$arResult['errCode'] = 'ERR_IBLOCK';
|
||||
|
||||
return;
|
||||
@ -1037,27 +1046,55 @@ class intaro_retailcrm extends CModule
|
||||
|
||||
COption::SetOptionString(
|
||||
$this->MODULE_ID,
|
||||
$this->CRM_CATALOG_BASE_PRICE . '_' . $PROFILE_ID,
|
||||
$this->CRM_CATALOG_BASE_PRICE . '_' . $profileId,
|
||||
htmlspecialchars(trim($_POST['price-types']))
|
||||
);
|
||||
|
||||
if ($typeLoading == 'agent') {
|
||||
$agentId = null;
|
||||
|
||||
if ($typeLoading === 'agent') {
|
||||
$dateAgent = new DateTime();
|
||||
$intAgent = new DateInterval('PT60S'); // PT60S - 60 sec;
|
||||
$dateAgent->add($intAgent);
|
||||
CAgent::AddAgent(
|
||||
"CCatalogExport::PreGenerateExport(" . $PROFILE_ID . ");", "catalog", "N", 86400, $dateAgent->format('d.m.Y H:i:s'), // date of first check
|
||||
"Y", // agent is active
|
||||
$dateAgent->format('d.m.Y H:i:s'), // date of first start
|
||||
$agentId = CAgent::AddAgent(
|
||||
'CCatalogExport::PreGenerateExport(' . $profileId . ');',
|
||||
'catalog',
|
||||
'N',
|
||||
86400,
|
||||
$dateAgent->format('d.m.Y H:i:s'),
|
||||
'Y',
|
||||
$dateAgent->format('d.m.Y H:i:s'),
|
||||
30
|
||||
);
|
||||
|
||||
CCatalogExport::Update($PROFILE_ID, array(
|
||||
"IN_AGENT" => "Y"
|
||||
));
|
||||
} else {
|
||||
CCatalogExport::Update($profileId, [
|
||||
"IN_AGENT" => "Y",
|
||||
]);
|
||||
}
|
||||
|
||||
if (
|
||||
isset($_POST['LOAD_NOW'])
|
||||
&& $agentId === null
|
||||
) {
|
||||
CAgent::AddAgent(
|
||||
'\Intaro\RetailCrm\Component\Agent::preGenerateExport(' . $profileId . ');',
|
||||
$this->MODULE_ID,
|
||||
'N',
|
||||
86400,
|
||||
$dateAgent->format('d.m.Y H:i:s'),
|
||||
'Y',
|
||||
$dateAgent->format('d.m.Y H:i:s')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if ('cron' === $typeLoading) {
|
||||
include($this->INSTALL_PATH . '/../lib/vendor/symfony/component/process/phpexecutablefinder.php');
|
||||
include($this->INSTALL_PATH . '/../lib/vendor/symfony/component/process/executablefinder.php');
|
||||
|
||||
$agent_period = 24;
|
||||
$agent_php_path = "/usr/local/php/bin/php";
|
||||
$finder = new PhpExecutableFinder();
|
||||
$agent_php_path = $finder->find();
|
||||
|
||||
if (!file_exists($_SERVER["DOCUMENT_ROOT"] . CATALOG_PATH2EXPORTS . "cron_frame.php")) {
|
||||
CheckDirPath($_SERVER["DOCUMENT_ROOT"] . CATALOG_PATH2EXPORTS);
|
||||
@ -1086,18 +1123,35 @@ class intaro_retailcrm extends CModule
|
||||
|
||||
if ($arProfile["IN_CRON"] == "Y") {
|
||||
// remove
|
||||
$cfg_data = preg_replace("#^.*?" . preg_quote(CATALOG_PATH2EXPORTS) . "cron_frame.php +" . $PROFILE_ID . " *>.*?$#im", "", $cfg_data);
|
||||
$cfg_data = preg_replace("#^.*?"
|
||||
. preg_quote(CATALOG_PATH2EXPORTS)
|
||||
. "cron_frame.php +"
|
||||
. $profileId
|
||||
. " *>.*?$#im", "", $cfg_data);
|
||||
} else {
|
||||
$strTime = "0 */" . $agent_period . " * * * ";
|
||||
if (strlen($cfg_data) > 0)
|
||||
if (strlen($cfg_data) > 0) {
|
||||
$cfg_data .= "\n";
|
||||
|
||||
$cfg_data .= $strTime . $agent_php_path . " -f " . $_SERVER["DOCUMENT_ROOT"] . CATALOG_PATH2EXPORTS . "cron_frame.php " . $PROFILE_ID . " >" . $_SERVER["DOCUMENT_ROOT"] . CATALOG_PATH2EXPORTS . "logs/" . $PROFILE_ID . ".txt\n";
|
||||
}
|
||||
|
||||
CCatalogExport::Update($PROFILE_ID, array(
|
||||
"IN_CRON" => "Y"
|
||||
));
|
||||
$cfg_data .= $strTime
|
||||
. $agent_php_path
|
||||
. " -f "
|
||||
. $_SERVER["DOCUMENT_ROOT"]
|
||||
. CATALOG_PATH2EXPORTS
|
||||
. "cron_frame.php "
|
||||
. $profileId
|
||||
. " >"
|
||||
. $_SERVER["DOCUMENT_ROOT"]
|
||||
. CATALOG_PATH2EXPORTS
|
||||
. "logs/"
|
||||
. $profileId
|
||||
. ".txt\n";
|
||||
}
|
||||
|
||||
CCatalogExport::Update($profileId, [
|
||||
"IN_CRON" => "Y",
|
||||
]);
|
||||
|
||||
CheckDirPath($_SERVER["DOCUMENT_ROOT"] . "/bitrix/crontab/");
|
||||
$cfg_data = preg_replace("#[\r\n]{2,}#im", "\n", $cfg_data);
|
||||
@ -1105,10 +1159,9 @@ class intaro_retailcrm extends CModule
|
||||
fwrite($fp, $cfg_data);
|
||||
fclose($fp);
|
||||
|
||||
$arRetval = array();
|
||||
$arRetval = [];
|
||||
@exec("crontab " . $_SERVER["DOCUMENT_ROOT"] . "/bitrix/crontab/crontab.cfg", $arRetval, $return_var);
|
||||
}
|
||||
}
|
||||
|
||||
$api_host = COption::GetOptionString($this->MODULE_ID, $this->CRM_API_HOST_OPTION, 0);
|
||||
$api_key = COption::GetOptionString($this->MODULE_ID, $this->CRM_API_KEY_OPTION, 0);
|
||||
@ -1218,16 +1271,18 @@ class intaro_retailcrm extends CModule
|
||||
UnRegisterModuleDependences("sale", "OnSalePaymentEntitySaved", $this->MODULE_ID, "RetailCrmEvent", "paymentSave");
|
||||
UnRegisterModuleDependences("sale", "OnSalePaymentEntityDeleted", $this->MODULE_ID, "RetailCrmEvent", "paymentDelete");
|
||||
|
||||
if (CModule::IncludeModule("catalog")) {
|
||||
if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/bitrix/php_interface/include/catalog_export/' . $this->RETAIL_CRM_EXPORT . '_run.php')) {
|
||||
$dbProfile = CCatalogExport::GetList(array(), array("FILE_NAME" => $this->RETAIL_CRM_EXPORT));
|
||||
if (
|
||||
CModule::IncludeModule('catalog')
|
||||
&& file_exists($_SERVER['DOCUMENT_ROOT']
|
||||
. '/bitrix/php_interface/include/catalog_export/'
|
||||
. $this->RETAIL_CRM_EXPORT
|
||||
. '_run.php')
|
||||
) {
|
||||
$dbProfile = CCatalogExport::GetList([], ['FILE_NAME' => $this->RETAIL_CRM_EXPORT]);
|
||||
|
||||
if ($dbProfile instanceof CDBResult) {
|
||||
$this->removeExportProfiles($dbProfile);
|
||||
|
||||
while ($arProfile = $dbProfile->Fetch()) {
|
||||
if ($arProfile["DEFAULT_PROFILE"] != "Y") {
|
||||
CAgent::RemoveAgent("CCatalogExport::PreGenerateExport(" . $arProfile['ID'] . ");", "catalog");
|
||||
CCatalogExport::Delete($arProfile['ID']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1245,7 +1300,14 @@ class intaro_retailcrm extends CModule
|
||||
function CopyFiles()
|
||||
{
|
||||
CopyDirFiles(
|
||||
$_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/' . $this->MODULE_ID . '/install/export/', $_SERVER['DOCUMENT_ROOT'] . '/bitrix/php_interface/include/catalog_export/', true, true
|
||||
$_SERVER['DOCUMENT_ROOT']
|
||||
. '/bitrix/modules/'
|
||||
. $this->MODULE_ID
|
||||
. '/install/export/',
|
||||
$_SERVER['DOCUMENT_ROOT']
|
||||
. '/bitrix/php_interface/include/catalog_export/',
|
||||
true,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
@ -1264,7 +1326,7 @@ class intaro_retailcrm extends CModule
|
||||
rmdir($defaultSite['ABS_DOC_ROOT'] . '/retailcrm/');
|
||||
}
|
||||
|
||||
function GetProfileSetupVars(
|
||||
function getProfileSetupVars(
|
||||
$iblocks,
|
||||
$propertiesProduct,
|
||||
$propertiesUnitProduct,
|
||||
@ -1316,7 +1378,7 @@ class intaro_retailcrm extends CModule
|
||||
|
||||
try {
|
||||
$history = $api->$method(array(), $page);
|
||||
} catch (\RetailCrm\Exception\CurlException $e) {
|
||||
} catch (CurlException $e) {
|
||||
RCrmActions::eventLog(
|
||||
'RetailCrmHistory::' . $method, 'RetailCrm\RestApi::' . $method . '::CurlException',
|
||||
$e->getCode() . ': ' . $e->getMessage()
|
||||
@ -1336,7 +1398,7 @@ class intaro_retailcrm extends CModule
|
||||
while (true) {
|
||||
try {
|
||||
$history = $api->$method(array(), $page);
|
||||
} catch (\RetailCrm\Exception\CurlException $e) {
|
||||
} catch (CurlException $e) {
|
||||
RCrmActions::eventLog(
|
||||
'RetailCrmHistory::' . $method, 'RetailCrm\RestApi::' . $method . '::CurlException',
|
||||
$e->getCode() . ': ' . $e->getMessage()
|
||||
@ -1380,7 +1442,7 @@ class intaro_retailcrm extends CModule
|
||||
$client = new RetailCrm\Http\Client($api_host . '/api/' . $version, array('apiKey' => $api_key));
|
||||
try {
|
||||
$result = $client->makeRequest('/reference/sites', 'GET');
|
||||
} catch (\RetailCrm\Exception\CurlException $e) {
|
||||
} catch (CurlException $e) {
|
||||
RCrmActions::eventLog(
|
||||
'intaro.retailcrm/install/index.php', 'RetailCrm\ApiClient::sitesList',
|
||||
$e->getCode() . ': ' . $e->getMessage()
|
||||
@ -1389,7 +1451,7 @@ class intaro_retailcrm extends CModule
|
||||
$res['errCode'] = 'ERR_' . $e->getCode();
|
||||
}
|
||||
|
||||
if ($result->getStatusCode() == 200) {
|
||||
if ($result instanceof ApiResponse && $result->getStatusCode() == 200) {
|
||||
COption::SetOptionString($this->MODULE_ID, $this->CRM_API_VERSION, $version);
|
||||
$res['sitesList'] = $APPLICATION->ConvertCharsetArray($result->sites, 'utf-8', SITE_CHARSET);
|
||||
|
||||
@ -1401,4 +1463,19 @@ class intaro_retailcrm extends CModule
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет профили экспорта icml каталага и агент, запускавший этот экспорт
|
||||
*
|
||||
* @param \CDBResult $dbProfile
|
||||
*/
|
||||
private function removeExportProfiles(CDBResult $dbProfile): void
|
||||
{
|
||||
while ($arProfile = $dbProfile->Fetch()) {
|
||||
if ($arProfile['DEFAULT_PROFILE'] !== 'Y') {
|
||||
CAgent::RemoveAgent('CCatalogExport::PreGenerateExport(' . $arProfile['ID'] . ');', 'catalog');
|
||||
CCatalogExport::Delete($arProfile['ID']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -495,8 +495,9 @@ if (!empty($oldValues)) {
|
||||
<br>
|
||||
<br>
|
||||
<font class="text"><?=GetMessage("LOAD_NOW");?> </font>
|
||||
<input id="load-now" type="checkbox" name="LOAD_NOW" value="now" checked >
|
||||
<input id="load-now" onchange="checkLoadStatus(this)" type="checkbox" name="LOAD_NOW" value="now">
|
||||
<br>
|
||||
<div id="loadMessage" hidden><?=GetMessage("LOAD_NOW_MSG");?></div>
|
||||
<br>
|
||||
<font class="text"><?=GetMessage("BASE_PRICE");?> </font>
|
||||
<select name="price-types" class="typeselect">
|
||||
@ -615,6 +616,16 @@ if (!empty($oldValues)) {
|
||||
getHbFromAjax($(obj).find('option')[obj.selectedIndex], 'product');
|
||||
}
|
||||
};
|
||||
|
||||
function checkLoadStatus(object)
|
||||
{
|
||||
if (object.checked) {
|
||||
$('#loadMessage').show();
|
||||
} else {
|
||||
$('#loadMessage').hide();
|
||||
}
|
||||
}
|
||||
|
||||
function checkProfile(obj)
|
||||
{
|
||||
if (obj.value !== 'none')
|
||||
@ -677,12 +688,11 @@ if (!empty($oldValues)) {
|
||||
<input type="hidden" name="continue" value="5">
|
||||
<div style="padding: 1px 13px 2px; height:28px;">
|
||||
<div align="right" style="float:right; width:50%; position:relative;">
|
||||
<input type="submit" name="inst" value="<?php echo GetMessage("MOD_NEXT_STEP"); ?>" class="adm-btn-save">
|
||||
<input type="submit" name="inst" onclick="BX.showWait()" value="<?= GetMessage("MOD_NEXT_STEP"); ?>"
|
||||
class="adm-btn-save">
|
||||
</div>
|
||||
<div align="left" style="float:right; width:50%; position:relative;">
|
||||
<input type="submit" name="back" value="<?php echo GetMessage("MOD_PREV_STEP"); ?>" class="adm-btn-save">
|
||||
<input type="submit" name="back" value="<?= GetMessage("MOD_PREV_STEP"); ?>" class="adm-btn-save">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?
|
||||
$arModuleVersion = array(
|
||||
"VERSION" => "5.6.2",
|
||||
"VERSION_DATE" => "2021-01-14 16:00:00"
|
||||
);
|
||||
<?php
|
||||
|
||||
$arModuleVersion = [
|
||||
'VERSION' => '5.7.0',
|
||||
'VERSION_DATE' => '2021-05-31 13:00:00',
|
||||
];
|
||||
|
3
intaro.retailcrm/lang/en/export/export_run.php
Normal file
3
intaro.retailcrm/lang/en/export/export_run.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
$MESS['IBLOCK_NOT_SELECTED'] = 'No infoblock selected for export';
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
$MESS['IBLOCK_NOT_SELECTED'] = 'No infoblock selected for export';
|
||||
$MESS ['RETAIL_MODULE_NAME'] = 'RetailCRM';
|
||||
$MESS ['MODULE_DESCRIPTION'] = 'Integration module with RetailCRM - specialized CRM for e-commerce';
|
||||
$MESS ['MODULE_PARTNER_NAME'] = 'Intaro Software';
|
||||
|
@ -17,6 +17,8 @@ $MESS ['NOT_LOADING'] = 'No';
|
||||
$MESS ['CRON_LOADING'] = 'By CRON every 24 hours';
|
||||
$MESS ['AGENT_LOADING'] = 'By Agent every 24 hours (by default)';
|
||||
$MESS ['LOAD_NOW'] = 'Export now';
|
||||
$MESS ['LOAD_NOW_MSG'] = 'The generation will start after you click "Finish installation".
|
||||
This may take some time';
|
||||
$MESS ['PROFILE_NAME'] = 'Profile name:';
|
||||
$MESS ['PROFILE_NAME_EXAMPLE'] = 'RetailCRM catalog export';
|
||||
$MESS ['ERR_FIELDS_PROFILE'] = 'Invalid profile name field';
|
||||
|
3
intaro.retailcrm/lang/ru/export/export_run.php
Normal file
3
intaro.retailcrm/lang/ru/export/export_run.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
$MESS['IBLOCK_NOT_SELECTED'] = 'Не выбрано ни одного инфоблока для экспорта';
|
@ -14,6 +14,8 @@ $MESS ['RETAILCRM_CURL_ERR'] = 'Для работы модуля интегра
|
||||
$MESS ['ERR_ARTICLE_IBLOCK'] = 'Не установлены артикулы';
|
||||
$MESS ['DATE_TIMEZONE_ERR'] = 'Не указана временная зона в настройках php.';
|
||||
$MESS ['SALE_VERSION_ERR'] = 'Версия модуля \'Интернет-магазин\' должна быть выше 16.';
|
||||
$MESS['IBLOCK_NOT_SELECTED'] = 'Не выбрано ни одного инфоблока для экспорта';
|
||||
|
||||
/*
|
||||
$MESS ['ORDER_PROPS'] = 'Настройки соответствия полей заказа RetailCRM свойствам заказа 1С-Битрикс';
|
||||
$MESS ['FIO'] = 'Ф.И.О.';
|
||||
|
@ -17,6 +17,7 @@ $MESS ['NOT_LOADING'] = 'Нет';
|
||||
$MESS ['CRON_LOADING'] = 'С помощью CRON каждые 24 часа';
|
||||
$MESS ['AGENT_LOADING'] = 'Агентом каждые 24 часа (по умолчанию)';
|
||||
$MESS ['LOAD_NOW'] = 'Выгрузить сейчас';
|
||||
$MESS ['LOAD_NOW_MSG'] = 'Генерация начнется после нажатия "Завершить установку". Это может занять некоторое время';
|
||||
$MESS ['PROFILE_NAME'] = 'Имя профиля:';
|
||||
$MESS ['PROFILE_NAME_EXAMPLE'] = 'Выгрузка каталога RetailCRM';
|
||||
$MESS ['ERR_FIELDS_PROFILE'] = 'Неверно заполнено поле имени профиля';
|
||||
|
28
intaro.retailcrm/lib/component/agent.php
Normal file
28
intaro.retailcrm/lib/component/agent.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Component;
|
||||
|
||||
use CCatalogExport;
|
||||
use CModule;
|
||||
use Dotenv\Loader;
|
||||
|
||||
/**
|
||||
* Class Agent
|
||||
*
|
||||
* @package Intaro\RetailCrm\Component
|
||||
*/
|
||||
class Agent
|
||||
{
|
||||
/**
|
||||
* @param int $profileId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function preGenerateExport(int $profileId): string
|
||||
{
|
||||
CModule::IncludeModule('catalog');
|
||||
CCatalogExport::PreGenerateExport($profileId);
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
334
intaro.retailcrm/lib/icml/icmldirector.php
Normal file
334
intaro.retailcrm/lib/icml/icmldirector.php
Normal file
@ -0,0 +1,334 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Icml;
|
||||
|
||||
use COption;
|
||||
use Intaro\RetailCrm\Icml\Utils\IcmlUtils;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlData;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup;
|
||||
use Intaro\RetailCrm\Repository\CatalogRepository;
|
||||
use Logger;
|
||||
use RetailcrmConfigProvider;
|
||||
|
||||
/**
|
||||
* Class IcmlDirector
|
||||
* @package Intaro\RetailCrm\Icml
|
||||
*/
|
||||
class IcmlDirector
|
||||
{
|
||||
public const INFO = 'INFO';
|
||||
public const OFFERS_PART = 500;
|
||||
public const FILE_LOG_NAME = 'i_crm_load_log';
|
||||
public const DEFAULT_PRODUCT_PAGE_SIZE = 1;
|
||||
|
||||
/**
|
||||
* @var IcmlWriter
|
||||
*/
|
||||
private $icmlWriter;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Icml\XmlOfferDirector
|
||||
*/
|
||||
private $xmlOfferDirector;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup
|
||||
*/
|
||||
private $setup;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Repository\CatalogRepository
|
||||
*/
|
||||
private $catalogRepository;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $shopName;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Icml\XmlCategoryDirector
|
||||
*/
|
||||
private $xmlCategoryDirector;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Icml\QueryParamsMolder
|
||||
*/
|
||||
private $queryBuilder;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\XmlData
|
||||
*/
|
||||
private $xmlData;
|
||||
|
||||
/**
|
||||
* @var \Logger
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* RetailCrmlXml constructor.
|
||||
*
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup $setup
|
||||
* @param \Logger $logger
|
||||
*/
|
||||
public function __construct(XmlSetup $setup, Logger $logger)
|
||||
{
|
||||
$this->setup = $setup;
|
||||
$this->shopName = RetailcrmConfigProvider::getSiteName();
|
||||
$this->catalogRepository = new CatalogRepository();
|
||||
$this->icmlWriter = new IcmlWriter($this->setup->filePath);
|
||||
$this->xmlOfferDirector = new XmlOfferDirector($this->setup);
|
||||
$this->xmlCategoryDirector = new XmlCategoryDirector($this->setup->iblocksForExport);
|
||||
$this->queryBuilder = new QueryParamsMolder();
|
||||
$this->xmlData = new XmlData();
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Основной метод. Генерирует icml файл католога товаров Битрикс
|
||||
*/
|
||||
public function generateXml(): void
|
||||
{
|
||||
$this->setXmlData();
|
||||
$this->icmlWriter->writeToXmlTop($this->xmlData);
|
||||
$this->logger->write(
|
||||
self::INFO . ': Start writing categories and header',
|
||||
self::FILE_LOG_NAME
|
||||
);
|
||||
$this->icmlWriter->writeToXmlHeaderAndCategories($this->xmlData);
|
||||
$this->logger->write(
|
||||
self::INFO . ': End writing categories in XML and Start writing offers',
|
||||
self::FILE_LOG_NAME
|
||||
);
|
||||
$this->writeOffers();
|
||||
$this->logger->write(
|
||||
self::INFO . ': End writing offers in XML',
|
||||
self::FILE_LOG_NAME
|
||||
);
|
||||
$this->icmlWriter->writeToXmlBottom();
|
||||
$this->logger->write(
|
||||
self::INFO . ': Loading complete (peak memory usage: ' . memory_get_peak_usage() . ')',
|
||||
self::FILE_LOG_NAME
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function setXmlData(): void
|
||||
{
|
||||
$this->xmlData->shopName = $this->shopName;
|
||||
$this->xmlData->company = $this->shopName;
|
||||
$this->xmlData->filePath = $this->setup->filePath;
|
||||
$this->xmlData->categories = $this->xmlCategoryDirector->getXmlCategories();
|
||||
}
|
||||
|
||||
/**
|
||||
* записывает оферы всех торговых каталогов в xml файл
|
||||
*/
|
||||
private function writeOffers(): void
|
||||
{
|
||||
$this->icmlWriter->startOffersBlock();
|
||||
|
||||
foreach ($this->setup->iblocksForExport as $iblockId) {
|
||||
$this->writeIblockOffers($iblockId);
|
||||
}
|
||||
|
||||
$this->icmlWriter->endBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* записывает оферы конкретного торгового каталога товаров в xml файл
|
||||
*
|
||||
* @param int $productIblockId //ID инфоблока товаров в торговом каталоге
|
||||
*/
|
||||
private function writeIblockOffers(int $productIblockId): void
|
||||
{
|
||||
$catalogIblockInfo = $this->catalogRepository->getCatalogIblockInfo($productIblockId);
|
||||
|
||||
//если нет торговых предложений
|
||||
if ($catalogIblockInfo->skuIblockId === null) {
|
||||
$selectParams
|
||||
= $this->queryBuilder->getSelectParams(
|
||||
$this->setup->properties->products->names[$productIblockId],
|
||||
$this->setup->basePriceId
|
||||
);
|
||||
|
||||
$selectParams->pageNumber = 1;
|
||||
$selectParams->nPageSize = self::OFFERS_PART;
|
||||
$selectParams->parentId = null;
|
||||
|
||||
while ($xmlOffers = $this->xmlOfferDirector->getXmlOffersPart($selectParams, $catalogIblockInfo)) {
|
||||
$this->icmlWriter->writeOffers($xmlOffers);
|
||||
|
||||
$selectParams->pageNumber++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//если есть торговые предложения
|
||||
$paramsForProduct
|
||||
= $this->queryBuilder->getSelectParams(
|
||||
$this->setup->properties->products->names[$productIblockId],
|
||||
$this->setup->basePriceId
|
||||
);
|
||||
$paramsForOffer
|
||||
= $this->queryBuilder->getSelectParams(
|
||||
$this->setup->properties->sku->names[$productIblockId],
|
||||
$this->setup->basePriceId
|
||||
);
|
||||
$this->writeOffersAsOffersInXml($paramsForProduct, $paramsForOffer, $catalogIblockInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Эта стратегия записи используется,
|
||||
* когда в каталоге есть торговые предложения
|
||||
*
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams $paramsForProduct
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams $paramsForOffer
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo $catalogIblockInfo
|
||||
*/
|
||||
private function writeOffersAsOffersInXml(
|
||||
SelectParams $paramsForProduct,
|
||||
SelectParams $paramsForOffer,
|
||||
CatalogIblockInfo $catalogIblockInfo
|
||||
): void {
|
||||
$paramsForProduct->pageNumber = 1;
|
||||
$paramsForProduct->nPageSize = $this->calculateProductPageSize();
|
||||
|
||||
do {
|
||||
$productsPart = $this->xmlOfferDirector->getXmlOffersPart($paramsForProduct, $catalogIblockInfo);
|
||||
$paramsForProduct->pageNumber++;
|
||||
|
||||
$this->writeProductsOffers($productsPart, $paramsForOffer, $catalogIblockInfo);
|
||||
} while (!empty($productsPart));
|
||||
}
|
||||
|
||||
/**
|
||||
* Записывает в файл оферы всех товаров из $products
|
||||
*
|
||||
* @param XmlOffer[] $products
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams $paramsForOffer
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo $catalogIblockInfo
|
||||
*/
|
||||
private function writeProductsOffers(
|
||||
array $products,
|
||||
SelectParams $paramsForOffer,
|
||||
CatalogIblockInfo $catalogIblockInfo
|
||||
): void {
|
||||
$paramsForOffer->nPageSize = $this->calculateOffersPageSize();
|
||||
|
||||
foreach ($products as $product) {
|
||||
$this->writeProductOffers($paramsForOffer, $catalogIblockInfo, $product);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Записывает оферы отдельного продукта в xml файл
|
||||
*
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams $paramsForOffer
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo $catalogIblockInfo
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer $product
|
||||
*/
|
||||
private function writeProductOffers(
|
||||
SelectParams $paramsForOffer,
|
||||
CatalogIblockInfo $catalogIblockInfo,
|
||||
XmlOffer $product
|
||||
): void {
|
||||
$paramsForOffer->pageNumber = 1;
|
||||
$writingOffersCount = 0;
|
||||
$paramsForOffer->parentId = $product->id;
|
||||
|
||||
do {
|
||||
$xmlOffersPart
|
||||
= $this->xmlOfferDirector->getXmlOffersBySingleProduct($paramsForOffer, $catalogIblockInfo, $product);
|
||||
|
||||
// если это "простой товар", у которого нет ТП, то просто записываем его
|
||||
if ($paramsForOffer->pageNumber === 1 && count($xmlOffersPart) === 0) {
|
||||
$this->icmlWriter->writeOffers([$product]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!empty($xmlOffersPart)) {
|
||||
$xmlOffersPart
|
||||
= $this->trimOffersList($writingOffersCount, $xmlOffersPart);
|
||||
|
||||
$this->icmlWriter->writeOffers($xmlOffersPart);
|
||||
|
||||
$writingOffersCount += count($xmlOffersPart);
|
||||
$paramsForOffer->pageNumber++;
|
||||
}
|
||||
} while ($this->shouldContinueWriting($writingOffersCount, $xmlOffersPart));
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет,не достигнул ли лимит по записываемым оферам maxOffersValue
|
||||
* и обрезает массив до лимита, если он достигнут
|
||||
*
|
||||
* @param int $writingOffers
|
||||
* @param XmlOffer[] $xmlOffers
|
||||
*
|
||||
* @return XmlOffer[]
|
||||
*/
|
||||
private function trimOffersList(int $writingOffers, array $xmlOffers): array
|
||||
{
|
||||
if (!empty($this->setup->maxOffersValue) && ($writingOffers + count($xmlOffers)) > $this->setup->maxOffersValue) {
|
||||
$sliceIndex
|
||||
= count($xmlOffers) - ($writingOffers + count($xmlOffers) - $this->setup->maxOffersValue);
|
||||
return array_slice($xmlOffers, 0, $sliceIndex);
|
||||
}
|
||||
|
||||
return $xmlOffers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает размер страницы для запроса товаров
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function calculateProductPageSize(): int
|
||||
{
|
||||
if (empty($this->setup->maxOffersValue)) {
|
||||
return self::DEFAULT_PRODUCT_PAGE_SIZE;
|
||||
}
|
||||
|
||||
return (int) ceil(self::OFFERS_PART / $this->setup->maxOffersValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает размер страницы для офферов
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function calculateOffersPageSize(): int
|
||||
{
|
||||
if (empty($this->setup->maxOffersValue)) {
|
||||
return self::OFFERS_PART;
|
||||
}
|
||||
|
||||
return $this->setup->maxOffersValue < self::OFFERS_PART ?
|
||||
$this->setup->maxOffersValue : self::OFFERS_PART;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет, нужно ли дальше записывать офферы
|
||||
*
|
||||
* @param int $writingOffers
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer[] $xmlOffers
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function shouldContinueWriting(int $writingOffers, array $xmlOffers): bool
|
||||
{
|
||||
if (empty($this->setup->maxOffersValue)) {
|
||||
return !empty($xmlOffers);
|
||||
}
|
||||
|
||||
return !empty($xmlOffers) && $writingOffers < $this->setup->maxOffersValue;
|
||||
}
|
||||
}
|
227
intaro.retailcrm/lib/icml/icmlwriter.php
Normal file
227
intaro.retailcrm/lib/icml/icmlwriter.php
Normal file
@ -0,0 +1,227 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Icml;
|
||||
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\OfferParam;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlCategory;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlData;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer;
|
||||
use XMLWriter;
|
||||
|
||||
/**
|
||||
* Отвечает за запись данных каталога в файл
|
||||
*
|
||||
* Class IcmlWriter
|
||||
* @package Intaro\RetailCrm\Icml
|
||||
*/
|
||||
class IcmlWriter
|
||||
{
|
||||
public const INFO = 'INFO';
|
||||
public const CATEGORY_PART = 1000;
|
||||
|
||||
/**
|
||||
* @var \XMLWriter
|
||||
*/
|
||||
private $writer;
|
||||
|
||||
/**
|
||||
* IcmlWriter constructor.
|
||||
* @param $filePath
|
||||
*/
|
||||
public function __construct($filePath)
|
||||
{
|
||||
$this->writer = new XMLWriter();
|
||||
$this->writer->openURI($_SERVER['DOCUMENT_ROOT'] . $filePath);
|
||||
$this->writer->setIndent(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlData $data
|
||||
*/
|
||||
public function writeToXmlTop(XmlData $data): void
|
||||
{
|
||||
$this->writer->startElement('yml_catalog');
|
||||
$this->writeSimpleAttribute('date', Date('Y-m-d H:i:s'));
|
||||
|
||||
$this->writer->startElement('shop');
|
||||
$this->writeSimpleElement('name', $data->shopName);
|
||||
$this->writeSimpleElement('company', $data->company);
|
||||
}
|
||||
|
||||
public function writeToXmlBottom(): void
|
||||
{
|
||||
$this->writer->endElement();
|
||||
$this->writer->endElement();
|
||||
$this->writer->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlData $data
|
||||
*/
|
||||
public function writeToXmlHeaderAndCategories(XmlData $data): void
|
||||
{
|
||||
$this->writer->startElement('categories');
|
||||
|
||||
foreach ($data->categories as $key => $category) {
|
||||
$this->writeCategory($category);
|
||||
|
||||
if (
|
||||
count($data->categories) === $key + 1
|
||||
|| is_int(count($data->categories) / self::CATEGORY_PART)
|
||||
) {
|
||||
$this->writer->flush();
|
||||
}
|
||||
}
|
||||
|
||||
$this->writer->endElement();
|
||||
$this->writer->flush();
|
||||
}
|
||||
|
||||
public function startOffersBlock(): void
|
||||
{
|
||||
$this->writer->startElement('offers');
|
||||
}
|
||||
|
||||
public function endBlock(): void
|
||||
{
|
||||
$this->writer->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param XmlOffer[] $offers
|
||||
*/
|
||||
public function writeOffers(array $offers): void
|
||||
{
|
||||
foreach ($offers as $offer) {
|
||||
$this->writeOffer($offer);
|
||||
}
|
||||
|
||||
$this->writer->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer $offer
|
||||
*/
|
||||
private function writeOffer(XmlOffer $offer): void
|
||||
{
|
||||
$this->writer->startElement('offer');
|
||||
$this->writeSimpleAttribute('id', $offer->id);
|
||||
$this->writeSimpleAttribute('productId', $offer->productId);
|
||||
$this->writeSimpleAttribute('quantity', $offer->quantity);
|
||||
|
||||
foreach ($offer->categoryIds as $categoryId) {
|
||||
$this->writeSimpleElement('categoryId', $categoryId);
|
||||
}
|
||||
|
||||
if (!empty($offer->picture)) {
|
||||
$this->writeSimpleElement('picture', $offer->picture);
|
||||
}
|
||||
|
||||
if (!empty($offer->unitCode->code)) {
|
||||
$this->writer->startElement('unit');
|
||||
$this->writeSimpleAttribute('code', $offer->unitCode->code);
|
||||
$this->writeSimpleAttribute('name', $offer->unitCode->name);
|
||||
$this->writeSimpleAttribute('sym', $offer->unitCode->sym);
|
||||
$this->writer->endElement();
|
||||
}
|
||||
|
||||
foreach ($offer->params as $param) {
|
||||
$this->writeParam($param);
|
||||
}
|
||||
|
||||
$this->writeSimpleElement('url', $offer->url);
|
||||
$this->writeSimpleElement('price', $offer->price);
|
||||
$this->writeSimpleElement('name', $offer->name);
|
||||
$this->writeSimpleElement('productName', $offer->productName);
|
||||
$this->writeSimpleElement('xmlId', $offer->xmlId);
|
||||
$this->writeOptionalSimpleElement('vendor', $offer->vendor);
|
||||
$this->writeOptionalSimpleElement('barcode', $offer->barcode);
|
||||
$this->writeOptionalSimpleElement('vatRate', $offer->vatRate);
|
||||
$this->writeOptionalSimpleElement('weight', $offer->weight);
|
||||
$this->writeOptionalSimpleElement('dimensions', $offer->dimensions);
|
||||
$this->writeOptionalSimpleElement('purchasePrice', $offer->purchasePrice);
|
||||
$this->writer->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает ноду, если значение не пустое
|
||||
*
|
||||
* @param string $name
|
||||
* @param $value
|
||||
*/
|
||||
private function writeOptionalSimpleElement(string $name, $value): void
|
||||
{
|
||||
if (!empty($value)) {
|
||||
$this->writeSimpleElement($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param $value
|
||||
*/
|
||||
private function writeSimpleElement(string $name, $value): void
|
||||
{
|
||||
$this->writer->startElement($name);
|
||||
$this->writer->text($this->prepareValue($value));
|
||||
$this->writer->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param $value
|
||||
*/
|
||||
private function writeSimpleAttribute(string $name, $value): void
|
||||
{
|
||||
$this->writer->startAttribute($name);
|
||||
$this->writer->text($this->prepareValue($value));
|
||||
$this->writer->endAttribute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $text
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function prepareValue($text): string
|
||||
{
|
||||
global $APPLICATION;
|
||||
|
||||
return strip_tags($APPLICATION->ConvertCharset($text, 'utf-8', 'utf-8'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlCategory $category
|
||||
*/
|
||||
private function writeCategory(XmlCategory $category): void
|
||||
{
|
||||
$this->writer->startElement('category');
|
||||
$this->writeSimpleAttribute('id', $category->id);
|
||||
$this->writeParentId($category->parentId);
|
||||
$this->writeSimpleElement('name', $category->name);
|
||||
$this->writeSimpleElement('picture', $category->picture);
|
||||
$this->writer->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\OfferParam $param
|
||||
*/
|
||||
private function writeParam(OfferParam $param): void
|
||||
{
|
||||
$this->writer->startElement('param');
|
||||
$this->writeSimpleAttribute('name', $param->name);
|
||||
$this->writeSimpleAttribute('code', $param->code);
|
||||
$this->writer->text($this->prepareValue($param->value));
|
||||
$this->writer->endElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $parentId
|
||||
*/
|
||||
private function writeParentId(string $parentId)
|
||||
{
|
||||
if ($parentId > 0) {
|
||||
$this->writeSimpleAttribute('parentId', $parentId);
|
||||
}
|
||||
}
|
||||
}
|
80
intaro.retailcrm/lib/icml/queryparamsmolder.php
Normal file
80
intaro.retailcrm/lib/icml/queryparamsmolder.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Icml;
|
||||
|
||||
use Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams;
|
||||
|
||||
/**
|
||||
* Class QueryParamsMolder
|
||||
* @package Intaro\RetailCrm\Icml
|
||||
*/
|
||||
class QueryParamsMolder
|
||||
{
|
||||
/**
|
||||
* Формирует параметры товаров или офферов для запросов к БД на основе настроек экспорта
|
||||
*
|
||||
* @param array|null $userProps
|
||||
* @param int $basePriceId
|
||||
* @return \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams
|
||||
*/
|
||||
public function getSelectParams(?array $userProps, int $basePriceId): SelectParams
|
||||
{
|
||||
$catalogFields = ['catalog_length', 'catalog_width', 'catalog_height', 'catalog_weight'];
|
||||
|
||||
$params = new SelectParams();
|
||||
|
||||
foreach ($userProps as $key => $name) {
|
||||
if ($name === '') {
|
||||
unset($userProps[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($name, $catalogFields, true)) {
|
||||
$userProps[$key] = strtoupper($userProps[$key]);
|
||||
} else {
|
||||
$userProps[$key] = 'PROPERTY_' . $userProps[$key];
|
||||
}
|
||||
}
|
||||
|
||||
$params->configurable = $userProps ?? [];
|
||||
$params->main = [
|
||||
'IBLOCK_ID',
|
||||
'IBLOCK_SECTION_ID',
|
||||
'NAME',
|
||||
'DETAIL_PICTURE',
|
||||
'PREVIEW_PICTURE',
|
||||
'DETAIL_PAGE_URL',
|
||||
'CATALOG_QUANTITY',
|
||||
'CATALOG_PRICE_' . $basePriceId,
|
||||
'CATALOG_PURCHASING_PRICE',
|
||||
'EXTERNAL_ID',
|
||||
'CATALOG_GROUP_' . $basePriceId,
|
||||
'ID',
|
||||
'LID',
|
||||
];
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $parentId
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo $info
|
||||
* @return array
|
||||
*/
|
||||
public function getWhereForOfferPart(?int $parentId, CatalogIblockInfo $info): array
|
||||
{
|
||||
if ($parentId === null) {
|
||||
return [
|
||||
'IBLOCK_ID' => $info->productIblockId,
|
||||
'ACTIVE' => 'Y',
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'IBLOCK_ID' => $info->skuIblockId,
|
||||
'ACTIVE' => 'Y',
|
||||
'PROPERTY_' . $info->skuPropertyId => $parentId,
|
||||
];
|
||||
}
|
||||
}
|
140
intaro.retailcrm/lib/icml/xmlcategorydirector.php
Normal file
140
intaro.retailcrm/lib/icml/xmlcategorydirector.php
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Intaro\RetailCrm\Icml;
|
||||
|
||||
use Bitrix\Main\ArgumentException;
|
||||
use Bitrix\Main\ORM\Objectify\Collection;
|
||||
use Bitrix\Main\ORM\Objectify\EntityObject;
|
||||
use Bitrix\Main\SystemException;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlCategory;
|
||||
use Intaro\RetailCrm\Repository\CatalogRepository;
|
||||
use Intaro\RetailCrm\Repository\FileRepository;
|
||||
use Intaro\RetailCrm\Repository\SiteRepository;
|
||||
|
||||
/**
|
||||
* Class XmlCategoryDirector
|
||||
* @package Intaro\RetailCrm\Icml
|
||||
*/
|
||||
class XmlCategoryDirector
|
||||
{
|
||||
private const MILLION = 1000000;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Repository\CatalogRepository
|
||||
*/
|
||||
private $catalogRepository;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $iblocksForExport;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Icml\XmlCategoryFactory
|
||||
*/
|
||||
private $xmlCategoryFactory;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Repository\FileRepository
|
||||
*/
|
||||
private $fileRepository;
|
||||
|
||||
public function __construct(array $iblocksForExport)
|
||||
{
|
||||
$this->iblocksForExport = $iblocksForExport;
|
||||
$this->catalogRepository = new CatalogRepository();
|
||||
$this->xmlCategoryFactory = new XmlCategoryFactory();
|
||||
$this->fileRepository = new FileRepository(SiteRepository::getDefaultServerName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return XmlCategory[]
|
||||
*/
|
||||
public function getXmlCategories(): array
|
||||
{
|
||||
$xmlCategories = [];
|
||||
|
||||
foreach ($this->iblocksForExport as $iblockId) {
|
||||
$categories = $this->catalogRepository->getCategoriesByIblockId($iblockId);
|
||||
|
||||
if ($categories === null) {
|
||||
$categoryId = self::MILLION + $iblockId;
|
||||
$xmlCategory = $this->makeXmlCategoryFromIblock($iblockId, $categoryId);
|
||||
|
||||
if (!$xmlCategory) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$xmlCategories[$categoryId] = $xmlCategory;
|
||||
}
|
||||
|
||||
$xmlCategories = array_merge($xmlCategories, $this->getXmlSubCategories($categories));
|
||||
}
|
||||
|
||||
return $xmlCategories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает коллекцию подкатегорий категории
|
||||
*
|
||||
* @param \Bitrix\Main\ORM\Objectify\Collection $categories
|
||||
* @return XmlCategory[]
|
||||
*/
|
||||
public function getXmlSubCategories(Collection $categories): array
|
||||
{
|
||||
$xmlCategories = [];
|
||||
|
||||
foreach ($categories as $categoryKey => $category) {
|
||||
if (!$category instanceof EntityObject) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$xmlCategory = $this->xmlCategoryFactory->create(
|
||||
$category,
|
||||
$this->fileRepository->getImageUrl($category->get('PICTURE'))
|
||||
);
|
||||
|
||||
if (!$xmlCategory) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$xmlCategories[$categoryKey] = $this->xmlCategoryFactory->create(
|
||||
$category,
|
||||
$this->fileRepository->getImageUrl($category->get('PICTURE'))
|
||||
);
|
||||
} catch (ArgumentException | SystemException $exception) {
|
||||
AddMessage2Log($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $xmlCategories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает XmlCategory из инфоблока
|
||||
*
|
||||
* @param int $iblockId
|
||||
* @param int $categoryId
|
||||
* @return \Intaro\RetailCrm\Model\Bitrix\Xml\XmlCategory|null
|
||||
*/
|
||||
public function makeXmlCategoryFromIblock(int $iblockId, int $categoryId): ?XmlCategory
|
||||
{
|
||||
$iblock = $this->catalogRepository->getIblockById($iblockId);
|
||||
|
||||
if ($iblock === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return $this->xmlCategoryFactory->create(
|
||||
$iblock,
|
||||
$this->fileRepository->getImageUrl($iblock->get('PICTURE')),
|
||||
$categoryId
|
||||
);
|
||||
} catch (ArgumentException | SystemException $exception) {
|
||||
AddMessage2Log($exception->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
43
intaro.retailcrm/lib/icml/xmlcategoryfactory.php
Normal file
43
intaro.retailcrm/lib/icml/xmlcategoryfactory.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Icml;
|
||||
|
||||
use Bitrix\Main\ArgumentException;
|
||||
use Bitrix\Main\ORM\Objectify\Collection;
|
||||
use Bitrix\Main\ORM\Objectify\EntityObject;
|
||||
use Bitrix\Main\SystemException;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlCategory;
|
||||
use Intaro\RetailCrm\Repository\CatalogRepository;
|
||||
use Intaro\RetailCrm\Repository\FileRepository;
|
||||
use Intaro\RetailCrm\Repository\SiteRepository;
|
||||
|
||||
/**
|
||||
* Отвечает за создание XmlCategory
|
||||
*
|
||||
* Class XmlCategoryFactory
|
||||
* @package Intaro\RetailCrm\Icml
|
||||
*/
|
||||
class XmlCategoryFactory
|
||||
{
|
||||
/**
|
||||
* @param \Bitrix\Main\ORM\Objectify\EntityObject $category
|
||||
* @param string $picture
|
||||
* @param int|null $categoryId
|
||||
*
|
||||
* @return \Intaro\RetailCrm\Model\Bitrix\Xml\XmlCategory|null
|
||||
*/
|
||||
public function create(EntityObject $category, string $picture, int $categoryId = null): ?XmlCategory
|
||||
{
|
||||
try {
|
||||
$xmlCategory = new XmlCategory();
|
||||
$xmlCategory->id = $categoryId ?? $category->get('ID');
|
||||
$xmlCategory->name = $category->get('NAME');
|
||||
$xmlCategory->parentId = $categoryId ? 0 : $category->get('IBLOCK_SECTION_ID');
|
||||
$xmlCategory->picture = $picture;
|
||||
} catch (ArgumentException | SystemException $exception) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $xmlCategory;
|
||||
}
|
||||
}
|
520
intaro.retailcrm/lib/icml/xmlofferbuilder.php
Normal file
520
intaro.retailcrm/lib/icml/xmlofferbuilder.php
Normal file
@ -0,0 +1,520 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Icml;
|
||||
|
||||
use Bitrix\Catalog\ProductTable;
|
||||
use Bitrix\Main\ArgumentException;
|
||||
use Intaro\RetailCrm\Icml\Utils\IcmlUtils;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\OfferParam;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\Unit;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetupPropsCategories;
|
||||
use Logger;
|
||||
use RetailcrmConfigProvider;
|
||||
|
||||
/**
|
||||
* Отвечает за создание XMLOffer
|
||||
*
|
||||
* Class XmlOfferBuilder
|
||||
* @package Intaro\RetailCrm\Icml
|
||||
*/
|
||||
class XmlOfferBuilder
|
||||
{
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup
|
||||
*/
|
||||
private $setup;
|
||||
|
||||
/**
|
||||
* @var bool|string|null
|
||||
*/
|
||||
private $purchasePriceNull;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $measures;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $defaultServerName;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $skuHlParams;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $productHlParams;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $productPicture;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo
|
||||
*/
|
||||
private $catalogIblockInfo;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $productProps;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $barcode;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams
|
||||
*/
|
||||
private $selectParams;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer
|
||||
*/
|
||||
private $xmlOffer;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $categories;
|
||||
|
||||
/**
|
||||
* IcmlDataManager constructor.
|
||||
*
|
||||
* XmlOfferBuilder constructor.
|
||||
*
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup $setup
|
||||
* @param array $measure
|
||||
* @param string|null $defaultServerName
|
||||
*/
|
||||
public function __construct(XmlSetup $setup, array $measure, ?string $defaultServerName)
|
||||
{
|
||||
$this->setup = $setup;
|
||||
$this->purchasePriceNull = RetailcrmConfigProvider::getCrmPurchasePrice();
|
||||
$this->measures = $this->prepareMeasures($measure);
|
||||
$this->defaultServerName = $defaultServerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer
|
||||
*/
|
||||
public function build(): XmlOffer
|
||||
{
|
||||
$this->xmlOffer = new XmlOffer();
|
||||
$this->xmlOffer->barcode = $this->barcode;
|
||||
$this->xmlOffer->picture = $this->productPicture;
|
||||
|
||||
$this->addDataFromParams();
|
||||
$this->addDataFromItem($this->productProps, $this->categories);
|
||||
|
||||
return $this->xmlOffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $categories
|
||||
*/
|
||||
public function setCategories(array $categories)
|
||||
{
|
||||
$this->categories = $categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $skuHlParams
|
||||
*/
|
||||
public function setSkuHlParams($skuHlParams): void
|
||||
{
|
||||
$this->skuHlParams = $skuHlParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $productHlParams
|
||||
*/
|
||||
public function setProductHlParams($productHlParams): void
|
||||
{
|
||||
$this->productHlParams = $productHlParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams $selectParams
|
||||
*/
|
||||
public function setSelectParams(SelectParams $selectParams): void
|
||||
{
|
||||
$this->selectParams = $selectParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $productProps
|
||||
*/
|
||||
public function setOfferProps(array $productProps): void
|
||||
{
|
||||
$this->productProps = $productProps;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $barcode
|
||||
*/
|
||||
public function setBarcode(string $barcode): void
|
||||
{
|
||||
$this->barcode = $barcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo $catalogIblockInfo
|
||||
*/
|
||||
public function setCatalogIblockInfo(CatalogIblockInfo $catalogIblockInfo): void
|
||||
{
|
||||
$this->catalogIblockInfo = $catalogIblockInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $getProductPicture
|
||||
*/
|
||||
public function setPicturesPath(string $getProductPicture): void
|
||||
{
|
||||
$this->productPicture = $getProductPicture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет в XmlOffer значения настраиваемых параметров, производителя, вес и габариты
|
||||
*/
|
||||
private function addDataFromParams(): void
|
||||
{
|
||||
$resultParams = array_merge($this->productHlParams, $this->skuHlParams);
|
||||
|
||||
//достаем значения из обычных свойств
|
||||
$resultParams = array_merge($resultParams, $this->getSimpleParams(
|
||||
$resultParams,
|
||||
$this->selectParams->configurable,
|
||||
$this->productProps
|
||||
));
|
||||
|
||||
[$resultParams, $this->xmlOffer->dimensions]
|
||||
= $this->extractDimensionsFromParams(
|
||||
$this->setup->properties,
|
||||
$resultParams,
|
||||
$this->catalogIblockInfo->productIblockId
|
||||
);
|
||||
[$resultParams, $this->xmlOffer->weight]
|
||||
= $this->extractWeightFromParams(
|
||||
$this->setup->properties,
|
||||
$resultParams,
|
||||
$this->catalogIblockInfo->productIblockId
|
||||
);
|
||||
[$resultParams, $this->xmlOffer->vendor] = $this->extractVendorFromParams($resultParams);
|
||||
$resultParams = $this->dropEmptyParams($resultParams);
|
||||
$this->xmlOffer->params = $this->createParamObject($resultParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет в объект XmlOffer информацию из GetList
|
||||
*
|
||||
* @param array $item
|
||||
* @param array $categoryIds
|
||||
*/
|
||||
private function addDataFromItem(array $item, array $categoryIds): void
|
||||
{
|
||||
$this->xmlOffer->id = $item['ID'];
|
||||
$this->xmlOffer->productId = $item['ID'];
|
||||
$this->xmlOffer->quantity = $item['CATALOG_QUANTITY'] ?? '';
|
||||
$this->xmlOffer->url = $item['DETAIL_PAGE_URL']
|
||||
? $this->defaultServerName . $item['DETAIL_PAGE_URL']
|
||||
: '';
|
||||
$this->xmlOffer->price = $item['CATALOG_PRICE_' . $this->setup->basePriceId];
|
||||
$this->xmlOffer->purchasePrice = $this->getPurchasePrice(
|
||||
$item,
|
||||
$this->setup->loadPurchasePrice,
|
||||
$this->purchasePriceNull
|
||||
);
|
||||
$this->xmlOffer->categoryIds = $categoryIds;
|
||||
$this->xmlOffer->name = $item['NAME'];
|
||||
$this->xmlOffer->xmlId = $item['EXTERNAL_ID'] ?? '';
|
||||
$this->xmlOffer->productName = $item['NAME'];
|
||||
$this->xmlOffer->vatRate = $item['CATALOG_VAT'] ?? 'none';
|
||||
$this->xmlOffer->unitCode = $this->getUnitCode($item['CATALOG_MEASURE'], $item['ID']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает закупочную цену, если она требуется настройками
|
||||
*
|
||||
* @param array $product
|
||||
* @param bool|null $isLoadPrice
|
||||
* @param string $purchasePriceNull
|
||||
* @return int|null
|
||||
*/
|
||||
private function getPurchasePrice(array $product, ?bool $isLoadPrice, string $purchasePriceNull): ?int
|
||||
{
|
||||
if ($isLoadPrice) {
|
||||
if ($product['CATALOG_PURCHASING_PRICE']) {
|
||||
return $product['CATALOG_PURCHASING_PRICE'];
|
||||
}
|
||||
|
||||
if ($purchasePriceNull === 'Y') {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает массив обычных свойств
|
||||
*
|
||||
* @param array $resultParams
|
||||
* @param array $configurableParams
|
||||
* @param array $productProps
|
||||
* @return array
|
||||
*/
|
||||
private function getSimpleParams(array $resultParams, array $configurableParams, array $productProps): array
|
||||
{
|
||||
foreach ($configurableParams as $key => $params) {
|
||||
if (isset($resultParams[$key])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$codeWithValue = $params . '_VALUE';
|
||||
|
||||
if (isset($productProps[$codeWithValue])) {
|
||||
$resultParams[$key] = $productProps[$codeWithValue];
|
||||
} elseif (isset($productProps[$params])) {
|
||||
$resultParams[$key] = $productProps[$params];
|
||||
}
|
||||
}
|
||||
|
||||
return $resultParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет параметры с пустыми и нулевыми значениями
|
||||
*
|
||||
* @param array $params
|
||||
* @return array
|
||||
*/
|
||||
private function dropEmptyParams(array $params): array
|
||||
{
|
||||
return array_diff($params, ['', 0, '0']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Разделяем вендора и остальные параметры
|
||||
*
|
||||
* @param array $resultParams
|
||||
* @return array
|
||||
*/
|
||||
private function extractVendorFromParams(array $resultParams): array
|
||||
{
|
||||
$vendor = null;
|
||||
|
||||
if (isset($resultParams['manufacturer'])) {
|
||||
$vendor = $resultParams['manufacturer'];
|
||||
|
||||
unset($resultParams['manufacturer']);
|
||||
}
|
||||
|
||||
return [$resultParams, $vendor];
|
||||
}
|
||||
|
||||
/**
|
||||
* Преобразует вес товара в килограммы для ноды weight
|
||||
*
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetupPropsCategories $xmlSetupPropsCategories
|
||||
* @param array $resultParams
|
||||
* @param int $iblockId
|
||||
* @return array
|
||||
*/
|
||||
private function extractWeightFromParams(
|
||||
XmlSetupPropsCategories $xmlSetupPropsCategories,
|
||||
array $resultParams,
|
||||
int $iblockId
|
||||
): array {
|
||||
$factors = [
|
||||
'mg' => 0.000001,
|
||||
'g' => 0.001,
|
||||
'kg' => 1,
|
||||
];
|
||||
$unit = '';
|
||||
|
||||
if (!empty($xmlSetupPropsCategories->products->names[$iblockId]['weight'])) {
|
||||
$unit = $xmlSetupPropsCategories->products->units[$iblockId]['weight'];
|
||||
} elseif (!empty($xmlSetupPropsCategories->sku->names[$iblockId]['weight'])) {
|
||||
$unit = $xmlSetupPropsCategories->sku->units[$iblockId]['weight'];
|
||||
}
|
||||
|
||||
if (isset($resultParams['weight'], $factors[$unit])) {
|
||||
$weight = $resultParams['weight'] * $factors[$unit];
|
||||
} else {
|
||||
$weight = '';
|
||||
}
|
||||
|
||||
if (isset($resultParams['weight'])) {
|
||||
unset($resultParams['weight']);
|
||||
}
|
||||
|
||||
return [$resultParams, $weight];
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение данных для ноды dimensions
|
||||
*
|
||||
* Данные должны быть переведены в сантиметры
|
||||
* и представлены в формате Длина/Ширина/Высота
|
||||
*
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetupPropsCategories $xmlSetupPropsCategories
|
||||
* @param array $resultParams
|
||||
* @param int $iblockId
|
||||
* @return array
|
||||
*/
|
||||
private function extractDimensionsFromParams(
|
||||
XmlSetupPropsCategories $xmlSetupPropsCategories,
|
||||
array $resultParams,
|
||||
int $iblockId
|
||||
): array {
|
||||
$dimensionsParams = ['length', 'width', 'height'];
|
||||
$dimensions = '';
|
||||
$factors = [
|
||||
'mm' => 0.1,
|
||||
'cm' => 1,
|
||||
'm' => 100,
|
||||
];
|
||||
|
||||
foreach ($dimensionsParams as $key => $param) {
|
||||
$unit = '';
|
||||
|
||||
if (!empty($xmlSetupPropsCategories->products->names[$iblockId][$param])) {
|
||||
$unit = $xmlSetupPropsCategories->products->units[$iblockId][$param];
|
||||
} elseif (!empty($xmlSetupPropsCategories->sku->names[$iblockId][$param])) {
|
||||
$unit = $xmlSetupPropsCategories->sku->units[$iblockId][$param];
|
||||
}
|
||||
|
||||
if (isset($factors[$unit], $resultParams[$param])) {
|
||||
$dimensions .= $resultParams[$param] * $factors[$unit];
|
||||
} else {
|
||||
$dimensions .= '0';
|
||||
}
|
||||
|
||||
if (count($dimensionsParams) > $key + 1) {
|
||||
$dimensions .= '/';
|
||||
}
|
||||
|
||||
if (isset($resultParams[$param])) {
|
||||
unset($resultParams[$param]);
|
||||
}
|
||||
}
|
||||
|
||||
return [$resultParams, $dimensions === '0/0/0' ? '' : $dimensions];
|
||||
}
|
||||
|
||||
/**
|
||||
* Собираем объект параметре заказа
|
||||
*
|
||||
* @param array $params
|
||||
* @return OfferParam[]
|
||||
*/
|
||||
private function createParamObject(array $params): array
|
||||
{
|
||||
$offerParams = [];
|
||||
|
||||
foreach ($params as $code => $value) {
|
||||
$paramName = GetMessage('PARAM_NAME_' . $code);
|
||||
|
||||
if (empty($paramName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$offerParam = new OfferParam();
|
||||
$offerParam->name = $paramName;
|
||||
$offerParam->code = $code;
|
||||
$offerParam->value = $value;
|
||||
$offerParams[] = $offerParam;
|
||||
}
|
||||
|
||||
return $offerParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Собираем объект единицы измерения для товара
|
||||
*
|
||||
* @param int $measureIndex
|
||||
* @return \Intaro\RetailCrm\Model\Bitrix\Xml\Unit
|
||||
*/
|
||||
private function createUnitFromCode(int $measureIndex): Unit
|
||||
{
|
||||
$unit = new Unit();
|
||||
$unit->name = $this->measures[$measureIndex]['MEASURE_TITLE'] ?? '';
|
||||
$unit->code = $this->measures[$measureIndex]['SYMBOL_INTL'] ?? '';
|
||||
$unit->sym = $this->measures[$measureIndex]['SYMBOL_RUS'] ?? '';
|
||||
|
||||
return $unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет запрещенные в unit сode символы
|
||||
*
|
||||
* @link https://docs.retailcrm.ru/Developers/modules/ICML
|
||||
*
|
||||
* @param array $measures
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function prepareMeasures(array $measures): array
|
||||
{
|
||||
foreach ($measures as &$measure) {
|
||||
if (isset($measure['SYMBOL_INTL'])) {
|
||||
$measure['SYMBOL_INTL'] = preg_replace("/[^a-zA-Z_\-]/",'', $measure['SYMBOL_INTL']);
|
||||
}
|
||||
}
|
||||
|
||||
return $measures;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $currentMeasure
|
||||
*
|
||||
* @return \Intaro\RetailCrm\Model\Bitrix\Xml\Unit
|
||||
*/
|
||||
private function createUnitFromProductTable(array $currentMeasure): Unit
|
||||
{
|
||||
$clearCurrentMeasure = $this->prepareMeasures(array_shift($currentMeasure));
|
||||
|
||||
$unit = new Unit();
|
||||
$unit->name = $clearCurrentMeasure['MEASURE']['MEASURE_TITLE'] ?? '';
|
||||
$unit->code = $clearCurrentMeasure['MEASURE']['SYMBOL_INTL'] ?? '';
|
||||
$unit->sym = $clearCurrentMeasure['MEASURE']['SYMBOL_RUS'] ?? '';
|
||||
|
||||
return $unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $measureId
|
||||
* @param int $itemId
|
||||
*
|
||||
* @return \Intaro\RetailCrm\Model\Bitrix\Xml\Unit|null
|
||||
*/
|
||||
private function getUnitCode(?int $measureId, int $itemId): ?Unit
|
||||
{
|
||||
if (isset($measureId) && !empty($measureId)) {
|
||||
return $this->createUnitFromCode($measureId);
|
||||
} else {
|
||||
try {
|
||||
$currentMeasure = ProductTable::getCurrentRatioWithMeasure($itemId);
|
||||
|
||||
if (is_array($currentMeasure)) {
|
||||
return $this->createUnitFromProductTable($currentMeasure);
|
||||
}
|
||||
} catch (ArgumentException $exception) {
|
||||
Logger::getInstance()->write(GetMessage('UNIT_ERROR'), 'i_crm_load_log');
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
206
intaro.retailcrm/lib/icml/xmlofferdirector.php
Normal file
206
intaro.retailcrm/lib/icml/xmlofferdirector.php
Normal file
@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Icml;
|
||||
|
||||
use Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup;
|
||||
use Intaro\RetailCrm\Repository\CatalogRepository;
|
||||
use Intaro\RetailCrm\Repository\FileRepository;
|
||||
use Intaro\RetailCrm\Repository\HlRepository;
|
||||
use Intaro\RetailCrm\Repository\MeasureRepository;
|
||||
use Intaro\RetailCrm\Repository\SiteRepository;
|
||||
|
||||
/**
|
||||
* Class XmlOfferDirector
|
||||
* @package Intaro\RetailCrm\Icml
|
||||
*/
|
||||
class XmlOfferDirector
|
||||
{
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup
|
||||
*/
|
||||
private $setup;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Repository\FileRepository
|
||||
*/
|
||||
private $fileRepository;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Repository\CatalogRepository
|
||||
*/
|
||||
private $catalogRepository;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Icml\XmlOfferBuilder
|
||||
*/
|
||||
private $xmlOfferBuilder;
|
||||
|
||||
/**
|
||||
* XmlOfferFactory constructor.
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup $setup
|
||||
*/
|
||||
public function __construct(XmlSetup $setup)
|
||||
{
|
||||
$this->setup = $setup;
|
||||
$this->fileRepository = new FileRepository(SiteRepository::getDefaultServerName());
|
||||
$this->catalogRepository = new CatalogRepository();
|
||||
$this->xmlOfferBuilder = new XmlOfferBuilder(
|
||||
$setup,
|
||||
MeasureRepository::getMeasures(),
|
||||
SiteRepository::getDefaultServerName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает страницу (массив) с товарами или торговыми предложениями (в зависимости от $param)
|
||||
*
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams $param
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo $catalogIblockInfo
|
||||
* @return XmlOffer[]
|
||||
*/
|
||||
public function getXmlOffersPart(SelectParams $param, CatalogIblockInfo $catalogIblockInfo): array
|
||||
{
|
||||
$ciBlockResult = $this->catalogRepository->getProductPage($param, $catalogIblockInfo);
|
||||
$barcodes = $this->catalogRepository->getProductBarcodesByIblockId($catalogIblockInfo->productIblockId);
|
||||
$offers = [];
|
||||
|
||||
while ($offer = $ciBlockResult->GetNext()) {
|
||||
$this->setXmlOfferParams($param, $offer, $catalogIblockInfo, $barcodes);
|
||||
$this->xmlOfferBuilder->setCategories($this->catalogRepository->getProductCategoriesIds($offer['ID']));
|
||||
|
||||
$offers[] = $this->xmlOfferBuilder->build();
|
||||
}
|
||||
|
||||
return $offers;
|
||||
}
|
||||
|
||||
/**
|
||||
* возвращает массив XmlOffers для конкретного продукта
|
||||
*
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams $paramsForOffer
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo $catalogIblockInfo
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer $product
|
||||
* @return XmlOffer[]
|
||||
*/
|
||||
public function getXmlOffersBySingleProduct(
|
||||
SelectParams $paramsForOffer,
|
||||
CatalogIblockInfo $catalogIblockInfo,
|
||||
XmlOffer $product
|
||||
): array {
|
||||
$xmlOffers = $this->getXmlOffersPart($paramsForOffer, $catalogIblockInfo);
|
||||
|
||||
return $this->addProductInfo($xmlOffers, $product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Декорирует оферы информацией из товаров
|
||||
*
|
||||
* @param XmlOffer[] $xmlOffers
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer $product
|
||||
* @return \Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer[]
|
||||
*/
|
||||
private function addProductInfo(array $xmlOffers, XmlOffer $product): array
|
||||
{
|
||||
foreach ($xmlOffers as $offer) {
|
||||
$offer->productId = $product->id;
|
||||
$offer->params = array_merge($offer->params, $product->params);
|
||||
$offer->unitCode = $offer->unitCode === null ? null : $offer->unitCode->merge($product->unitCode);
|
||||
$offer->vatRate = $offer->vatRate === 'none' ? $product->vatRate : $offer->vatRate;
|
||||
$offer->vendor = $offer->mergeValues($product->vendor, $offer->vendor);
|
||||
$offer->picture = $offer->mergeValues($product->picture, $offer->picture);
|
||||
$offer->weight = $offer->mergeValues($product->weight, $offer->weight);
|
||||
$offer->dimensions = $offer->mergeValues($product->dimensions, $offer->dimensions);
|
||||
$offer->categoryIds = $product->categoryIds;
|
||||
$offer->productName = $product->productName;
|
||||
}
|
||||
|
||||
return $xmlOffers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение настраиваемых параметров, если они лежат в HL-блоке
|
||||
*
|
||||
* @param int $iblockId //ID инфоблока товаров, даже если данные нужны по SKU
|
||||
* @param array $productProps
|
||||
* @param array $configurableParams
|
||||
* @param array $hls
|
||||
* @return array
|
||||
*/
|
||||
private function getHlParams(int $iblockId, array $productProps, array $configurableParams, array $hls): array
|
||||
{
|
||||
$params = [];
|
||||
|
||||
foreach ($hls as $hlName => $hlBlockProduct) {
|
||||
if (isset($hlBlockProduct[$iblockId])) {
|
||||
reset($hlBlockProduct[$iblockId]);
|
||||
$firstKey = key($hlBlockProduct[$iblockId]);
|
||||
$hlRepository = new HlRepository($hlName);
|
||||
|
||||
if ($hlRepository->getHl() === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = $hlRepository->getDataByXmlId($productProps[$configurableParams[$firstKey] . '_VALUE']);
|
||||
|
||||
if ($result === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($hlBlockProduct[$iblockId] as $hlPropCodeKey => $hlPropCode) {
|
||||
if (isset($result[$hlPropCode])) {
|
||||
$params[$hlPropCodeKey] = $result[$hlPropCode];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams $param
|
||||
* @param array $product
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo $catalogIblockInfo
|
||||
* @param array $barcodes
|
||||
*/
|
||||
private function setXmlOfferParams(
|
||||
SelectParams $param,
|
||||
array $product,
|
||||
CatalogIblockInfo $catalogIblockInfo,
|
||||
array $barcodes
|
||||
): void {
|
||||
if ($param->parentId === null) {
|
||||
$pictureProperty = $this->setup->properties->products->pictures[$catalogIblockInfo->productIblockId];
|
||||
} else {
|
||||
$pictureProperty = $this->setup->properties->sku->pictures[$catalogIblockInfo->productIblockId];
|
||||
}
|
||||
|
||||
//достаем значения из HL блоков товаров
|
||||
$this->xmlOfferBuilder->setProductHlParams($this->getHlParams(
|
||||
$catalogIblockInfo->productIblockId,
|
||||
$product,
|
||||
$param->configurable,
|
||||
$this->setup->properties->highloadblockProduct
|
||||
));
|
||||
|
||||
//достаем значения из HL блоков торговых предложений
|
||||
$this->xmlOfferBuilder->setSkuHlParams($this->getHlParams(
|
||||
$catalogIblockInfo->productIblockId,
|
||||
$product,
|
||||
$param->configurable,
|
||||
$this->setup->properties->highloadblockSku
|
||||
));
|
||||
$this->xmlOfferBuilder->setSelectParams($param);
|
||||
$this->xmlOfferBuilder->setOfferProps($product);
|
||||
$this->xmlOfferBuilder->setBarcode($barcodes[$product['ID']] ?? '');
|
||||
$this->xmlOfferBuilder->setCatalogIblockInfo($catalogIblockInfo);
|
||||
$this->xmlOfferBuilder->setPicturesPath(
|
||||
$this
|
||||
->fileRepository
|
||||
->getProductPicture($product, $pictureProperty ?? '')
|
||||
);
|
||||
}
|
||||
}
|
13
intaro.retailcrm/lib/lang/ru/icml/xmlofferbuilder.php
Normal file
13
intaro.retailcrm/lib/lang/ru/icml/xmlofferbuilder.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
$MESS['ROOT_CATEGORY_FOR_CATALOG'] = "Корневой раздел для каталога \"%s\"";
|
||||
$MESS['PARAM_NAME_article'] = 'Артикул';
|
||||
$MESS['PARAM_NAME_manufacturer'] = 'Производитель';
|
||||
$MESS['PARAM_NAME_color'] = 'Цвет';
|
||||
$MESS['PARAM_NAME_weight'] = 'Вес (габариты)';
|
||||
$MESS['PARAM_NAME_length'] = 'Длина (габариты)';
|
||||
$MESS['PARAM_NAME_width'] = 'Ширина (габариты)';
|
||||
$MESS['PARAM_NAME_height'] = 'Высота (габариты)';
|
||||
$MESS['PARAM_NAME_picture'] = 'Фото';
|
||||
$MESS['PARAM_NAME_size'] = 'Размер';
|
||||
$MESS['UNIT_ERROR'] = 'Ошибка получения unit кода';
|
32
intaro.retailcrm/lib/model/bitrix/orm/catalogiblockinfo.php
Normal file
32
intaro.retailcrm/lib/model/bitrix/orm/catalogiblockinfo.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Intaro\RetailCrm\Model\Bitrix\Orm;
|
||||
|
||||
/**
|
||||
* Class CatalogIblockInfo
|
||||
* @package Intaro\RetailCrm\Model\Bitrix\Orm
|
||||
*/
|
||||
class CatalogIblockInfo
|
||||
{
|
||||
/**
|
||||
* ID инфоблока торговых предложений
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $skuIblockId;
|
||||
|
||||
/**
|
||||
* ID инфоблока товаров
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $productIblockId;
|
||||
|
||||
/**
|
||||
* ID свойства привязки торговых предложений к товарам
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $skuPropertyId;
|
||||
}
|
94
intaro.retailcrm/lib/model/bitrix/orm/iblockcatalog.php
Normal file
94
intaro.retailcrm/lib/model/bitrix/orm/iblockcatalog.php
Normal file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Model\Bitrix\Orm;
|
||||
|
||||
use Bitrix\Main,
|
||||
Bitrix\Main\Localization\Loc;
|
||||
use Bitrix\Main\Entity\BooleanField;
|
||||
use Bitrix\Main\Entity\IntegerField;
|
||||
use Bitrix\Main\Entity\ReferenceField;
|
||||
|
||||
Loc::loadMessages(__FILE__);
|
||||
|
||||
/**
|
||||
* Class IblockCatalogTable
|
||||
*
|
||||
* Fields:
|
||||
* <ul>
|
||||
* <li> IBLOCK_ID int mandatory
|
||||
* <li> YANDEX_EXPORT bool optional default 'N'
|
||||
* <li> SUBSCRIPTION bool optional default 'N'
|
||||
* <li> VAT_ID int optional
|
||||
* <li> PRODUCT_IBLOCK_ID int mandatory
|
||||
* <li> SKU_PROPERTY_ID int mandatory
|
||||
* <li> VAT reference to {@link \Bitrix\Catalog\CatalogVatTable}
|
||||
* <li> IBLOCK reference to {@link \Bitrix\Iblock\IblockTable}
|
||||
* <li> PRODUCT_IBLOCK reference to {@link \Bitrix\Iblock\IblockTable}
|
||||
* <li> SKU_PROPERTY reference to {@link \Bitrix\Iblock\IblockPropertyTable}
|
||||
* </ul>
|
||||
*
|
||||
* @package Bitrix\Catalog
|
||||
**/
|
||||
class IblockCatalogTable extends Main\Entity\DataManager
|
||||
{
|
||||
/**
|
||||
* Returns DB table name for entity.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getTableName()
|
||||
{
|
||||
return 'b_catalog_iblock';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns entity map definition.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public static function getMap(): ?array
|
||||
{
|
||||
try {
|
||||
return [
|
||||
new IntegerField('IBLOCK_ID'),
|
||||
new BooleanField('YANDEX_EXPORT'),
|
||||
new BooleanField('SUBSCRIPTION'),
|
||||
new IntegerField('VAT_ID'),
|
||||
new IntegerField('PRODUCT_IBLOCK_ID'),
|
||||
new IntegerField('SKU_PROPERTY_ID'),
|
||||
new ReferenceField(
|
||||
'VAT',
|
||||
'Bitrix\Catalog\CatalogVat',
|
||||
['=this.VAT_ID' => 'ref.ID']
|
||||
),
|
||||
new ReferenceField(
|
||||
'IBLOCK',
|
||||
'Bitrix\Iblock\Iblock',
|
||||
['=this.IBLOCK_ID' => 'ref.ID']
|
||||
),
|
||||
new ReferenceField(
|
||||
'PRODUCT_IBLOCK',
|
||||
'Bitrix\Iblock\Iblock',
|
||||
['=this.PRODUCT_IBLOCK_ID' => 'ref.ID']
|
||||
),
|
||||
new ReferenceField(
|
||||
'SKU_PROPERTY',
|
||||
'Bitrix\Iblock\IblockProperty',
|
||||
['=this.SKU_PROPERTY_ID' => 'ref.ID']
|
||||
),
|
||||
new ReferenceField(
|
||||
'SECTION',
|
||||
'Bitrix\Iblock\IblockSection',
|
||||
['=this.IBLOCK_ID' => 'ref.IBLOCK_ID']
|
||||
),
|
||||
new ReferenceField(
|
||||
'OFFERS_IBLOCK',
|
||||
'Bitrix\Iblock\IblockSection',
|
||||
['=this.IBLOCK_ID' => 'this.ID']
|
||||
),
|
||||
];
|
||||
} catch (Main\ArgumentException | Main\SystemException $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
34
intaro.retailcrm/lib/model/bitrix/xml/offerparam.php
Normal file
34
intaro.retailcrm/lib/model/bitrix/xml/offerparam.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category Integration
|
||||
* @package Intaro\RetailCrm\Model\Bitrix
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @license MIT
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://retailcrm.ru/docs
|
||||
*/
|
||||
namespace Intaro\RetailCrm\Model\Bitrix\Xml;
|
||||
|
||||
/**
|
||||
* Class OfferParam
|
||||
* @package Intaro\RetailCrm\Model\Bitrix\Xml
|
||||
*/
|
||||
class OfferParam
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $code;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $value;
|
||||
}
|
54
intaro.retailcrm/lib/model/bitrix/xml/selectparams.php
Normal file
54
intaro.retailcrm/lib/model/bitrix/xml/selectparams.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category Integration
|
||||
* @package Intaro\RetailCrm\Model\Bitrix
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @license MIT
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://retailcrm.ru/docs
|
||||
*/
|
||||
namespace Intaro\RetailCrm\Model\Bitrix\Xml;
|
||||
|
||||
/**
|
||||
* Class SelectParams
|
||||
* @package Intaro\RetailCrm\Model\Bitrix\Xml
|
||||
*/
|
||||
class SelectParams
|
||||
{
|
||||
/**
|
||||
* конфигурируемые свойства
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $configurable;
|
||||
|
||||
/**
|
||||
* обязательные свойства
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $main;
|
||||
|
||||
/**
|
||||
* номер запрашиваемой страницы
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $pageNumber;
|
||||
|
||||
/**
|
||||
* количество товаров на странице
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $nPageSize;
|
||||
|
||||
/**
|
||||
* id товара у торогового предложения, если запрашивается SKU
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $parentId;
|
||||
}
|
51
intaro.retailcrm/lib/model/bitrix/xml/unit.php
Normal file
51
intaro.retailcrm/lib/model/bitrix/xml/unit.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category Integration
|
||||
* @package Intaro\RetailCrm\Model\Bitrix
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @license MIT
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://retailcrm.ru/docs
|
||||
*/
|
||||
namespace Intaro\RetailCrm\Model\Bitrix\Xml;
|
||||
|
||||
/**
|
||||
* единица измерения для товара, элемент не является обязательным в icml
|
||||
*
|
||||
* Class Unit
|
||||
* @package Intaro\RetailCrm\Model\Bitrix\Xml
|
||||
*/
|
||||
class Unit
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $code;
|
||||
|
||||
/**
|
||||
* единица измерения товара
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $sym;
|
||||
|
||||
/**
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\Unit|null $unitCode
|
||||
* @return \Intaro\RetailCrm\Model\Bitrix\Xml\Unit
|
||||
*/
|
||||
public function merge(?Unit $unitCode): Unit
|
||||
{
|
||||
if ($this->code === null && $unitCode !== null) {
|
||||
return $unitCode;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
39
intaro.retailcrm/lib/model/bitrix/xml/xmlcategory.php
Normal file
39
intaro.retailcrm/lib/model/bitrix/xml/xmlcategory.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category Integration
|
||||
* @package Intaro\RetailCrm\Model\Bitrix
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @license MIT
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://retailcrm.ru/docs
|
||||
*/
|
||||
namespace Intaro\RetailCrm\Model\Bitrix\Xml;
|
||||
|
||||
/**
|
||||
* Class XmlCategory
|
||||
*/
|
||||
class XmlCategory
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $parentId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $picture;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
}
|
39
intaro.retailcrm/lib/model/bitrix/xml/xmldata.php
Normal file
39
intaro.retailcrm/lib/model/bitrix/xml/xmldata.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category Integration
|
||||
* @package Intaro\RetailCrm\Model\Bitrix
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @license MIT
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://retailcrm.ru/docs
|
||||
*/
|
||||
namespace Intaro\RetailCrm\Model\Bitrix\Xml;
|
||||
|
||||
/**
|
||||
* Class XmlData
|
||||
* @package Intaro\RetailCrm\Model\Bitrix
|
||||
*/
|
||||
class XmlData
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $shopName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $company;
|
||||
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\XmlCategory[]
|
||||
*/
|
||||
public $categories;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $filePath;
|
||||
}
|
131
intaro.retailcrm/lib/model/bitrix/xml/xmloffer.php
Normal file
131
intaro.retailcrm/lib/model/bitrix/xml/xmloffer.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category Integration
|
||||
* @package Intaro\RetailCrm\Model\Bitrix
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @license MIT
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://retailcrm.ru/docs
|
||||
*/
|
||||
namespace Intaro\RetailCrm\Model\Bitrix\Xml;
|
||||
|
||||
/**
|
||||
* Class XmlOffer
|
||||
* @package Intaro\RetailCrm\Model\Bitrix\Xml
|
||||
*/
|
||||
class XmlOffer
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $productId;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $quantity;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $picture;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $url;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
public $price;
|
||||
|
||||
/**
|
||||
* Категории, к которым относится товар
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $categoryIds;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $xmlId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $productName;
|
||||
|
||||
/**
|
||||
* @var OfferParam[]
|
||||
*/
|
||||
public $params;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $vendor;
|
||||
|
||||
/**
|
||||
* @var Unit
|
||||
*/
|
||||
public $unitCode;
|
||||
|
||||
/**
|
||||
* ставка налога (НДС)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $vatRate;
|
||||
|
||||
/**
|
||||
* штрих-код
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $barcode;
|
||||
|
||||
/**
|
||||
* Закупочная цена
|
||||
*
|
||||
* @var mixed|null
|
||||
*/
|
||||
public $purchasePrice;
|
||||
|
||||
/**
|
||||
* Вес товара
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $weight;
|
||||
|
||||
/**
|
||||
* Габариты товара
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $dimensions;
|
||||
|
||||
/**
|
||||
* @param $productValue
|
||||
* @param $offerValue
|
||||
* @return mixed
|
||||
*/
|
||||
public function mergeValues($productValue, $offerValue)
|
||||
{
|
||||
return empty($offerValue) ? $productValue : $offerValue;
|
||||
}
|
||||
}
|
74
intaro.retailcrm/lib/model/bitrix/xml/xmlsetup.php
Normal file
74
intaro.retailcrm/lib/model/bitrix/xml/xmlsetup.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category Integration
|
||||
* @package Intaro\RetailCrm\Model\Bitrix
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @license MIT
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://retailcrm.ru/docs
|
||||
*/
|
||||
namespace Intaro\RetailCrm\Model\Bitrix\Xml;
|
||||
|
||||
/**
|
||||
* Class XmlSetup
|
||||
* @package Intaro\RetailCrm\Model\Bitrix\Xml
|
||||
*/
|
||||
class XmlSetup
|
||||
{
|
||||
/**
|
||||
* XmlSetup constructor.
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetupPropsCategories $xmlProps
|
||||
*/
|
||||
public function __construct(XmlSetupPropsCategories $xmlProps)
|
||||
{
|
||||
$this->properties = $xmlProps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $profileId;
|
||||
|
||||
/**
|
||||
* id инфоблоков, которые подлежат экспорту - IBLOCK_EXPORT
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $iblocksForExport;
|
||||
|
||||
/**
|
||||
* Путь, по которому сохраняется xml - SETUP_FILE_NAME
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $filePath;
|
||||
|
||||
/**
|
||||
* синхронизируемые свойства
|
||||
*
|
||||
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetupPropsCategories
|
||||
*/
|
||||
public $properties;
|
||||
|
||||
/**
|
||||
* максимальное количество торговых предложений у товара - MAX_OFFERS_VALUE
|
||||
*
|
||||
* @var null|int
|
||||
*/
|
||||
public $maxOffersValue;
|
||||
|
||||
/**
|
||||
* выгружать ли закупочную цену
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $loadPurchasePrice;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
public $basePriceId;
|
||||
}
|
55
intaro.retailcrm/lib/model/bitrix/xml/xmlsetupprops.php
Normal file
55
intaro.retailcrm/lib/model/bitrix/xml/xmlsetupprops.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category Integration
|
||||
* @package Intaro\RetailCrm\Model\Bitrix
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @license MIT
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://retailcrm.ru/docs
|
||||
*/
|
||||
namespace Intaro\RetailCrm\Model\Bitrix\Xml;
|
||||
|
||||
/**
|
||||
* Class XmlSetupProps
|
||||
*
|
||||
* @package Intaro\RetailCrm\Model\Bitrix\Xml
|
||||
*/
|
||||
class XmlSetupProps
|
||||
{
|
||||
/**
|
||||
* XmlSetupProps constructor.
|
||||
* @param array $names
|
||||
* @param array $units
|
||||
* @param array|null $pictures
|
||||
*/
|
||||
public function __construct(array $names, array $units, ?array $pictures)
|
||||
{
|
||||
$this->names = $names;
|
||||
$this->units = $units;
|
||||
$this->pictures = $pictures;
|
||||
}
|
||||
|
||||
/**
|
||||
* названия свойств
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $names;
|
||||
|
||||
/**
|
||||
* меры измерения
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $units;
|
||||
|
||||
/**
|
||||
* свойства, из которых нужно брать картинки
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $pictures;
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category Integration
|
||||
* @package Intaro\RetailCrm\Model\Bitrix
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @license MIT
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://retailcrm.ru/docs
|
||||
*/
|
||||
namespace Intaro\RetailCrm\Model\Bitrix\Xml;
|
||||
|
||||
/**
|
||||
* Class XmlSetupProps
|
||||
* @package Intaro\RetailCrm\Model\Bitrix\Xml
|
||||
*/
|
||||
class XmlSetupPropsCategories
|
||||
{
|
||||
/**
|
||||
* XmlSetupPropsCategories constructor.
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetupProps $products
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetupProps $sku
|
||||
*/
|
||||
public function __construct(XmlSetupProps $products, XmlSetupProps $sku)
|
||||
{
|
||||
$this->products = $products;
|
||||
$this->sku = $sku;
|
||||
}
|
||||
|
||||
/**
|
||||
* Синхронизируемые свойства товаров
|
||||
*
|
||||
* @var XmlSetupProps
|
||||
*/
|
||||
public $products;
|
||||
|
||||
/**
|
||||
* Синхронизируемые свойства торговых предложений
|
||||
*
|
||||
* @var XmlSetupProps
|
||||
*/
|
||||
public $sku;
|
||||
|
||||
/**
|
||||
* Синхронизируемые свойства торговых предложений, находящиеся в HL блоках
|
||||
*
|
||||
* массив с названиями HL блоков, элементы которого содержат,
|
||||
* синхронизируемые св-ва
|
||||
*
|
||||
* @var array[][]
|
||||
*/
|
||||
public $highloadblockSku;
|
||||
|
||||
/**
|
||||
* Синхрозируемые свойства товаров, находящиеся в HL блоках
|
||||
*
|
||||
* массив с названиями HL блоков, элементы которого содержат,
|
||||
* синхронизируемые св-ва
|
||||
*
|
||||
* @var array[][]
|
||||
*/
|
||||
public $highloadblockProduct;
|
||||
}
|
179
intaro.retailcrm/lib/repository/catalogrepository.php
Normal file
179
intaro.retailcrm/lib/repository/catalogrepository.php
Normal file
@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Repository;
|
||||
|
||||
use Bitrix\Iblock\IblockTable;
|
||||
use Bitrix\Iblock\SectionTable;
|
||||
use Bitrix\Main\ArgumentException;
|
||||
use Bitrix\Main\ObjectPropertyException;
|
||||
use Bitrix\Main\ORM\Objectify\Collection;
|
||||
use Bitrix\Main\ORM\Objectify\EntityObject;
|
||||
use Bitrix\Main\SystemException;
|
||||
use CCatalogGroup;
|
||||
use CCatalogSku;
|
||||
use CCatalogStoreBarCode;
|
||||
use CIBlockElement;
|
||||
use Intaro\RetailCrm\Icml\QueryParamsMolder;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo;
|
||||
use Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams;
|
||||
use RetailcrmConfigProvider;
|
||||
|
||||
/**
|
||||
* Class CatalogRepository
|
||||
* @package Intaro\RetailCrm\Repository
|
||||
*/
|
||||
class CatalogRepository
|
||||
{
|
||||
/**
|
||||
* @var \Intaro\RetailCrm\Icml\QueryParamsMolder
|
||||
*/
|
||||
private $builder;
|
||||
|
||||
/**
|
||||
* CatalogRepository constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->builder = new QueryParamsMolder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение категорий, к которым относится товар
|
||||
*
|
||||
* @param int $offerId
|
||||
* @return array
|
||||
*/
|
||||
public function getProductCategoriesIds(int $offerId): array
|
||||
{
|
||||
$query = CIBlockElement::GetElementGroups($offerId, false, ['ID']);
|
||||
$ids = [];
|
||||
|
||||
while ($category = $query->GetNext()) {
|
||||
$ids[] = $category['ID'];
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns products IDs with barcodes by infoblock id
|
||||
*
|
||||
* @param int $iblockId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getProductBarcodesByIblockId(int $iblockId): array
|
||||
{
|
||||
$barcodes = [];
|
||||
$dbBarCode = CCatalogStoreBarCode::getList(
|
||||
[],
|
||||
['IBLOCK_ID' => $iblockId],
|
||||
false,
|
||||
false,
|
||||
['PRODUCT_ID', 'BARCODE']
|
||||
);
|
||||
|
||||
while ($arBarCode = $dbBarCode->GetNext()) {
|
||||
if (!empty($arBarCode)) {
|
||||
$barcodes[$arBarCode['PRODUCT_ID']] = $arBarCode['BARCODE'];
|
||||
}
|
||||
}
|
||||
|
||||
return $barcodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams $param
|
||||
* @param \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo $catalogIblockInfo
|
||||
* @return \CIBlockResult|int
|
||||
*/
|
||||
public function getProductPage(SelectParams $param, CatalogIblockInfo $catalogIblockInfo)
|
||||
{
|
||||
return CIBlockElement::GetList(
|
||||
[],
|
||||
$this->builder->getWhereForOfferPart($param->parentId, $catalogIblockInfo),
|
||||
false,
|
||||
['nPageSize' => $param->nPageSize, 'iNumPage' => $param->pageNumber, 'checkOutOfRange' => true],
|
||||
array_merge($param->configurable, $param->main)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iblockId
|
||||
* @return \Bitrix\Main\ORM\Objectify\Collection|null
|
||||
*/
|
||||
public function getCategoriesByIblockId(int $iblockId): ?Collection
|
||||
{
|
||||
try {
|
||||
return SectionTable::query()
|
||||
->addSelect('*')
|
||||
->where('IBLOCK_ID', $iblockId)
|
||||
->fetchCollection();
|
||||
} catch (ObjectPropertyException | ArgumentException | SystemException $exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $iblockId
|
||||
* @return EntityObject|null
|
||||
*/
|
||||
public function getIblockById($iblockId): ?EntityObject
|
||||
{
|
||||
try {
|
||||
return IblockTable::query()
|
||||
->where('ID', $iblockId)
|
||||
->fetchObject();
|
||||
} catch (ObjectPropertyException | ArgumentException | SystemException $exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает информацию об инфоблоке торговых предложений по ID инфоблока товаров
|
||||
*
|
||||
* @param int $productIblockId
|
||||
* @return \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo
|
||||
*/
|
||||
public function getCatalogIblockInfo(int $productIblockId): CatalogIblockInfo
|
||||
{
|
||||
$catalogIblockInfo = new CatalogIblockInfo();
|
||||
$info = CCatalogSKU::GetInfoByProductIBlock($productIblockId);
|
||||
|
||||
if ($info === false) {
|
||||
$catalogIblockInfo->productIblockId = $productIblockId;
|
||||
|
||||
return $catalogIblockInfo;
|
||||
}
|
||||
|
||||
$catalogIblockInfo->skuIblockId = $info['IBLOCK_ID'];
|
||||
$catalogIblockInfo->productIblockId = $info['PRODUCT_IBLOCK_ID'];
|
||||
$catalogIblockInfo->skuPropertyId = $info['SKU_PROPERTY_ID'];
|
||||
|
||||
return $catalogIblockInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $profileId
|
||||
* @return int
|
||||
*/
|
||||
public static function getBasePriceId(?int $profileId): int
|
||||
{
|
||||
$basePriceId = RetailcrmConfigProvider::getCatalogBasePriceByProfile($profileId);
|
||||
|
||||
if (!$basePriceId) {
|
||||
$dbPriceType = CCatalogGroup::GetList(
|
||||
[],
|
||||
['BASE' => 'Y'],
|
||||
false,
|
||||
false,
|
||||
['ID']
|
||||
);
|
||||
|
||||
$result = $dbPriceType->GetNext();
|
||||
return $result['ID'];
|
||||
}
|
||||
|
||||
return $basePriceId;
|
||||
}
|
||||
}
|
67
intaro.retailcrm/lib/repository/filerepository.php
Normal file
67
intaro.retailcrm/lib/repository/filerepository.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Repository;
|
||||
|
||||
use CFile;
|
||||
|
||||
/**
|
||||
* Class FileRepository
|
||||
* @package Intaro\RetailCrm\Repository
|
||||
*/
|
||||
class FileRepository
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $defaultServerName;
|
||||
|
||||
/**
|
||||
* FileRepository constructor.
|
||||
* @param string $defaultServerName
|
||||
*/
|
||||
public function __construct(string $defaultServerName)
|
||||
{
|
||||
$this->defaultServerName = $defaultServerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $fileId
|
||||
* @return string
|
||||
*/
|
||||
public function getImageUrl(?int $fileId): string
|
||||
{
|
||||
if (!$fileId) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$pathImage = CFile::GetPath($fileId);
|
||||
$validation = '/^(http|https):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i';
|
||||
|
||||
if ((bool) preg_match($validation, $pathImage) === false) {
|
||||
return $this->defaultServerName . $pathImage;
|
||||
}
|
||||
|
||||
return $pathImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $product
|
||||
* @param string $pictureProp
|
||||
* @return string
|
||||
*/
|
||||
public function getProductPicture(array $product, string $pictureProp = ''): string
|
||||
{
|
||||
$picture = '';
|
||||
$pictureId = $product['PROPERTY_' . $pictureProp . '_VALUE'] ?? null;
|
||||
|
||||
if (isset($product['DETAIL_PICTURE'])) {
|
||||
$picture = $this->getImageUrl($product['DETAIL_PICTURE']);
|
||||
} elseif (isset($product['PREVIEW_PICTURE'])) {
|
||||
$picture = $this->getImageUrl($product['PREVIEW_PICTURE']);
|
||||
} elseif ($pictureId !== null) {
|
||||
$picture = $this->getImageUrl($pictureId);
|
||||
}
|
||||
|
||||
return $picture ?? '';
|
||||
}
|
||||
}
|
56
intaro.retailcrm/lib/repository/hlrepository.php
Normal file
56
intaro.retailcrm/lib/repository/hlrepository.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Repository;
|
||||
|
||||
use Bitrix\Main\ArgumentException;
|
||||
use Bitrix\Main\ObjectPropertyException;
|
||||
use Bitrix\Main\SystemException;
|
||||
use Intaro\RetailCrm\Service\Hl;
|
||||
|
||||
/**
|
||||
* Class HlRepository
|
||||
* @package Intaro\RetailCrm\Repository
|
||||
*/
|
||||
class HlRepository
|
||||
{
|
||||
/**
|
||||
* @var \Bitrix\Main\Entity\DataManager|string|null
|
||||
*/
|
||||
private $hl;
|
||||
|
||||
public function __construct($hlName)
|
||||
{
|
||||
$this->hl = Hl::getHlClassByTableName($hlName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $propertyValue
|
||||
* @return array|null
|
||||
*/
|
||||
public function getDataByXmlId(?string $propertyValue): ?array
|
||||
{
|
||||
try {
|
||||
$result = $this->hl::query()
|
||||
->setSelect(['*'])
|
||||
->where('UF_XML_ID', '=', $propertyValue)
|
||||
->fetch();
|
||||
|
||||
if ($result === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $result;
|
||||
} catch (ObjectPropertyException | ArgumentException | SystemException $exception) {
|
||||
AddMessage2Log($exception->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Bitrix\Main\Entity\DataManager|string|null
|
||||
*/
|
||||
public function getHl()
|
||||
{
|
||||
return $this->hl;
|
||||
}
|
||||
}
|
29
intaro.retailcrm/lib/repository/measurerepository.php
Normal file
29
intaro.retailcrm/lib/repository/measurerepository.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Repository;
|
||||
|
||||
use CCatalogMeasure;
|
||||
|
||||
/**
|
||||
* Class MeasureRepository
|
||||
* @package Intaro\RetailCrm\Repository
|
||||
*/
|
||||
class MeasureRepository
|
||||
{
|
||||
/**
|
||||
* Получает доступные в Битриксе единицы измерения для товаров
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getMeasures(): array
|
||||
{
|
||||
$measures = [];
|
||||
$resMeasure = CCatalogMeasure::getList();
|
||||
|
||||
while ($measure = $resMeasure->Fetch()) {
|
||||
$measures[$measure['ID']] = $measure;
|
||||
}
|
||||
|
||||
return $measures;
|
||||
}
|
||||
}
|
29
intaro.retailcrm/lib/repository/siterepository.php
Normal file
29
intaro.retailcrm/lib/repository/siterepository.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Repository;
|
||||
|
||||
use CSite;
|
||||
use RetailcrmConfigProvider;
|
||||
|
||||
/**
|
||||
* Class SiteRepository
|
||||
* @package Intaro\RetailCrm\Repository
|
||||
*/
|
||||
class SiteRepository
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function getDefaultServerName(): ?string
|
||||
{
|
||||
$rsSites = CSite::GetList($by, $sort, ['ACTIVE' => 'Y']);
|
||||
|
||||
while ($ar = $rsSites->Fetch()) {
|
||||
if ($ar['DEF'] === 'Y') {
|
||||
return RetailcrmConfigProvider::getProtocol() . $ar['SERVER_NAME'];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
76
intaro.retailcrm/lib/service/hl.php
Normal file
76
intaro.retailcrm/lib/service/hl.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Intaro\RetailCrm\Service;
|
||||
|
||||
use Bitrix\Main\ArgumentException;
|
||||
use Bitrix\Main\Entity\DataManager;
|
||||
use Bitrix\Main\Loader;
|
||||
use Bitrix\Highloadblock as Highloadblock;
|
||||
use Bitrix\Main\LoaderException;
|
||||
use Bitrix\Main\ObjectPropertyException;
|
||||
use Bitrix\Main\SystemException;
|
||||
|
||||
/**
|
||||
* Class Hl
|
||||
*
|
||||
* Позволяет получить DataManager для HL-блоков
|
||||
*
|
||||
* @package Intaro\RetailCrm\Service
|
||||
*/
|
||||
class Hl
|
||||
{
|
||||
/**
|
||||
* Получение DataManager класса управления HLBlock
|
||||
*
|
||||
* @param int $HlBlockId
|
||||
* @return \Bitrix\Main\Entity\DataManager|null
|
||||
* @throws \Bitrix\Main\ArgumentException
|
||||
* @throws \Bitrix\Main\LoaderException
|
||||
* @throws \Bitrix\Main\ObjectPropertyException
|
||||
* @throws \Bitrix\Main\SystemException
|
||||
*/
|
||||
public static function getHlClassById(int $HlBlockId): ?DataManager
|
||||
{
|
||||
Loader::includeModule('highloadblock');
|
||||
|
||||
$hlblock = Highloadblock\HighloadBlockTable::getById($HlBlockId)->fetch();
|
||||
|
||||
if (!$hlblock) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$entity = Highloadblock\HighloadBlockTable::compileEntity($hlblock);
|
||||
|
||||
return $entity->getDataClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение DataManager класса управления HLBlock по названию таблицы
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Bitrix\Main\Entity\DataManager|string|null
|
||||
*/
|
||||
public static function getHlClassByTableName(string $name)
|
||||
{
|
||||
try {
|
||||
Loader::includeModule('highloadblock');
|
||||
|
||||
$hlblock = Highloadblock\HighloadBlockTable::query()
|
||||
->addSelect('*')
|
||||
->where('TABLE_NAME', '=', $name)
|
||||
->exec()
|
||||
->fetch();
|
||||
|
||||
if (!$hlblock) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$entity = Highloadblock\HighloadBlockTable::compileEntity($hlblock);
|
||||
|
||||
return $entity->getDataClass();
|
||||
} catch (ObjectPropertyException | ArgumentException | SystemException | LoaderException $exception) {
|
||||
AddMessage2Log($exception->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
19
intaro.retailcrm/lib/vendor/symfony/component/process/LICENSE
vendored
Normal file
19
intaro.retailcrm/lib/vendor/symfony/component/process/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2004-2021 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
86
intaro.retailcrm/lib/vendor/symfony/component/process/executablefinder.php
vendored
Normal file
86
intaro.retailcrm/lib/vendor/symfony/component/process/executablefinder.php
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Intaro\RetailCrm\Vendor\Symfony\Component\Process;
|
||||
|
||||
/**
|
||||
* Generic executable finder.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class ExecutableFinder
|
||||
{
|
||||
private $suffixes = ['.exe', '.bat', '.cmd', '.com'];
|
||||
|
||||
/**
|
||||
* Replaces default suffixes of executable.
|
||||
*/
|
||||
public function setSuffixes(array $suffixes)
|
||||
{
|
||||
$this->suffixes = $suffixes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new possible suffix to check for executable.
|
||||
*/
|
||||
public function addSuffix(string $suffix)
|
||||
{
|
||||
$this->suffixes[] = $suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an executable by name.
|
||||
*
|
||||
* @param string $name The executable name (without the extension)
|
||||
* @param string|null $default The default to return if no executable is found
|
||||
* @param array $extraDirs Additional dirs to check into
|
||||
*
|
||||
* @return string|null The executable path or default value
|
||||
*/
|
||||
public function find(string $name, string $default = null, array $extraDirs = []): ?string
|
||||
{
|
||||
if (ini_get('open_basedir')) {
|
||||
$searchPath = array_merge(explode(\PATH_SEPARATOR, ini_get('open_basedir')), $extraDirs);
|
||||
$dirs = [];
|
||||
foreach ($searchPath as $path) {
|
||||
// Silencing against https://bugs.php.net/69240
|
||||
if (@is_dir($path)) {
|
||||
$dirs[] = $path;
|
||||
} else {
|
||||
if (basename($path) == $name && @is_executable($path)) {
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$dirs = array_merge(
|
||||
explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
|
||||
$extraDirs
|
||||
);
|
||||
}
|
||||
|
||||
$suffixes = [''];
|
||||
if ('\\' === \DIRECTORY_SEPARATOR) {
|
||||
$pathExt = getenv('PATHEXT');
|
||||
$suffixes = array_merge($pathExt ? explode(\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
|
||||
}
|
||||
foreach ($suffixes as $suffix) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
}
|
99
intaro.retailcrm/lib/vendor/symfony/component/process/phpexecutablefinder.php
vendored
Normal file
99
intaro.retailcrm/lib/vendor/symfony/component/process/phpexecutablefinder.php
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Intaro\RetailCrm\Vendor\Symfony\Component\Process;
|
||||
|
||||
/**
|
||||
* An executable finder specifically designed for the PHP executable.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class PhpExecutableFinder
|
||||
{
|
||||
private $executableFinder;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->executableFinder = new ExecutableFinder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds The PHP executable.
|
||||
*
|
||||
* @return string|false The PHP executable path or false if it cannot be found
|
||||
*/
|
||||
public function find(bool $includeArgs = true)
|
||||
{
|
||||
if ($php = getenv('PHP_BINARY')) {
|
||||
if (!is_executable($php)) {
|
||||
$command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v';
|
||||
if ($php = strtok(exec($command.' '.escapeshellarg($php)), \PHP_EOL)) {
|
||||
if (!is_executable($php)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $php;
|
||||
}
|
||||
|
||||
$args = $this->findArguments();
|
||||
$args = $includeArgs && $args ? ' '.implode(' ', $args) : '';
|
||||
|
||||
// PHP_BINARY return the current sapi executable
|
||||
if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cgi-fcgi', 'cli', 'cli-server', 'phpdbg'], true)) {
|
||||
return \PHP_BINARY.$args;
|
||||
}
|
||||
|
||||
if ($php = getenv('PHP_PATH')) {
|
||||
if (!@is_executable($php)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $php;
|
||||
}
|
||||
|
||||
if ($php = getenv('PHP_PEAR_PHP_BIN')) {
|
||||
if (@is_executable($php)) {
|
||||
return $php;
|
||||
}
|
||||
}
|
||||
|
||||
if (@is_executable($php = \PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) {
|
||||
return $php;
|
||||
}
|
||||
|
||||
$dirs = [\PHP_BINDIR];
|
||||
if ('\\' === \DIRECTORY_SEPARATOR) {
|
||||
$dirs[] = 'C:\xampp\php\\';
|
||||
}
|
||||
|
||||
return $this->executableFinder->find('php', false, $dirs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the PHP executable arguments.
|
||||
*
|
||||
* @return array The PHP executable arguments
|
||||
*/
|
||||
public function findArguments(): array
|
||||
{
|
||||
$arguments = [];
|
||||
if ('phpdbg' === \PHP_SAPI) {
|
||||
$arguments[] = '-qrr';
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class RetailCrmOrderTest
|
||||
*/
|
||||
use \Bitrix\Main\Loader;
|
||||
|
||||
class RetailCrmICMLTest extends BitrixTestCase
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
COption::SetOptionString('intaro.retailcrm', 'api_version', 'v5');
|
||||
CModule::IncludeModule('intaro.retailcrm');
|
||||
}
|
||||
|
||||
public function testModuleInstalled()
|
||||
{
|
||||
$this->assertTrue(Loader::includeModule("intaro.retailcrm"));
|
||||
}
|
||||
|
||||
public function testGetImageUrl()
|
||||
{
|
||||
$test = new RetailCrmICML();
|
||||
$result = $test->getImageUrl(1);
|
||||
|
||||
if (!empty($result)) {
|
||||
$this->assertIsString($result);
|
||||
$this->assertEquals("/upload/iblock/c44/test.jpg", $result);
|
||||
} else {
|
||||
$this->assertEmpty($result);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user