1
0
mirror of synced 2024-11-22 21:36:10 +03:00
bitrix-module/intaro.retailcrm/lib/icml/xmlofferdirector.php

332 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Intaro\RetailCrm\Icml;
use CIBlock;
use CIBlockSection;
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;
/**
* @var array
*/
private $barcodes;
/**
* 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()
);
$this->barcodes = $this->catalogRepository->getBarcodes();
}
/**
* Возвращает страницу (массив) с товарами или торговыми предложениями (в зависимости от $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, $this->setup->loadNonActivity);
$offers = [];
$this->xmlOfferBuilder->setServerName($this->fileRepository->getServerName($catalogIblockInfo->productIblockId));
while ($offer = $ciBlockResult->Fetch()) {
$categories = $this->catalogRepository->getProductCategories($offer['ID']);
$offer['DETAIL_PAGE_URL'] = $this->replaceUrlTemplate($offer, $categories);
$this->setXmlOfferParams($param, $offer, $catalogIblockInfo);
$this->xmlOfferBuilder
->setCategories(array_column($categories, 'IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_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 = $this->mergeParams($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->barcode = $offer->mergeValues($product->barcode, $offer->barcode);
$offer->categoryIds = $product->categoryIds;
$offer->productName = $product->productName;
$offer->url = $this->mergeUrls($product->url, $offer->url);
}
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
*/
private function setXmlOfferParams(
SelectParams $param,
array $product,
CatalogIblockInfo $catalogIblockInfo
): 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($this->barcodes[$product['ID']] ?? '');
$this->xmlOfferBuilder->setCatalogIblockInfo($catalogIblockInfo);
$this->xmlOfferBuilder->setPicturesPath(
$this
->fileRepository
->getProductPicture($product, $pictureProperty ?? '', $catalogIblockInfo->productIblockId)
);
}
/**
* @param array $offer
* @param array $categories
*
* @return string
*/
private function replaceUrlTemplate(array $offer, array $categories): string
{
if (strpos($offer['DETAIL_PAGE_URL'], '#PRODUCT_URL#')) {
return $offer['DETAIL_PAGE_URL'];
}
$replaceableUrlParts = [
'#SITE_DIR#'=> 'LANG_DIR',
'#ID#' => 'ID',
'#CODE#' => 'CODE',
'#EXTERNAL_ID#' => 'EXTERNAL_ID',
'#IBLOCK_TYPE_ID#' => 'IBLOCK_TYPE_ID',
'#IBLOCK_ID#' => 'IBLOCK_ID',
'#IBLOCK_CODE#' => 'IBLOCK_CODE',
'#IBLOCK_EXTERNAL_ID#' => 'IBLOCK_EXTERNAL_ID',
'#ELEMENT_ID#' => 'ID',
'#ELEMENT_CODE#' => 'CODE',
];
$resultUrl = $offer['DETAIL_PAGE_URL'];
foreach ($replaceableUrlParts as $key => $replaceableUrlPart) {
if (isset($offer[$replaceableUrlPart])) {
$resultUrl = str_replace($key, $offer[$replaceableUrlPart], $resultUrl);
}
}
if (
isset($categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_ID'])
&& strpos($offer['DETAIL_PAGE_URL'], '#SECTION_ID#') !== false
) {
$resultUrl = str_replace(
'#SECTION_ID#',
$categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_ID'],
$resultUrl
);
}
if (
isset($categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_CODE'])
&& strpos($offer['DETAIL_PAGE_URL'], '#SECTION_CODE#') !== false
) {
$resultUrl = str_replace(
'#SECTION_CODE#',
$categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_CODE'],
$resultUrl
);
}
if (
isset(
$categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_CODE'],
$categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_ID']
)
&& strpos($offer['DETAIL_PAGE_URL'], '#SECTION_CODE_PATH#') !== false
) {
$resultUrl = str_replace(
'#SECTION_CODE_PATH#',
CIBlockSection::getSectionCodePath($categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_ID']),
$resultUrl
);
}
return str_replace('//', '/', $resultUrl);
}
/**
* @param string $productUrl
* @param string $offerUrl
*
* @return string
*/
private function mergeUrls(string $productUrl, string $offerUrl): string
{
if (strpos($offerUrl, '#PRODUCT_URL#') !== false) {
return $productUrl;
}
return $offerUrl;
}
/**
* @param array $offerParams
* @param array $productParams
*/
private function mergeParams(array $offerParams, array $productParams): array
{
$offerCodes = [];
/** @var \Intaro\RetailCrm\Model\Bitrix\Xml\OfferParam $offerParam */
foreach ($offerParams as $offerParam) {
$offerCodes[] = $offerParam->code;
}
/** @var \Intaro\RetailCrm\Model\Bitrix\Xml\OfferParam $productParam */
foreach ($productParams as $productParam) {
if (in_array($productParam->code, $offerCodes, true)) {
continue;
}
$offerParams[] = $productParam;
}
return $offerParams;
}
}