%PDF- %PDF-
Direktori : /home/bitrix/www/bitrix/modules/sale/lib/tradingplatform/vk/feed/data/converters/ |
Current File : //home/bitrix/www/bitrix/modules/sale/lib/tradingplatform/vk/feed/data/converters/product.php |
<?php namespace Bitrix\Sale\TradingPlatform\Vk\Feed\Data\Converters; use Bitrix\Main\ArgumentNullException; use Bitrix\Main\Localization\Loc; use Bitrix\Sale\TradingPlatform\Vk; use Bitrix\Highloadblock\HighloadBlockTable; Loc::loadMessages(__FILE__); class Product extends DataConverter { protected $selectOfferProps; protected $sectionsList; private $result; const DESCRIPTION_LENGHT_MIN = 10; const DESCRIPTION_LENGHT_MAX = 3300; // it is not entirely accurate value, but in doc i can't find true info const NAME_LENGHT_MIN = 4; const NAME_LENGHT_MAX = 100; /** * Product constructor. * @param $exportId - int ID of export */ public function __construct($exportId) { if (!isset($exportId) || strlen($exportId) <= 0) throw new ArgumentNullException("EXPORT_ID"); $this->exportId = $exportId; $this->sectionsList = new Vk\SectionsList($this->exportId); } /** * Main method for convert * * @param $data - Array of albums data from source. * @return array */ public function convert($data) { $logger = new Vk\Logger($this->exportId); $this->result = array(); // get common SKU and notSKU data $this->result = $this->getNotSkuItemData($data); // product WITH SKU $offersDescription = ''; if (isset($data["OFFERS"]) && is_array($data["OFFERS"]) && !empty($data["OFFERS"])) { //adding desc and additional photos from SKU $this->selectOfferProps = $data["SELECT_OFFER_PROPS"]; $this->result["PHOTOS_OFFERS"] = array(); $this->result["PHOTOS_OFFERS_FOR_VK"] = array(); $offersConverted = array(); foreach ($data["OFFERS"] as $offer) { $resultOffer = $this->getItemDataOffersOffer($offer); if (!empty($resultOffer["PHOTOS"])) $this->result["PHOTOS_OFFERS"] += $resultOffer["PHOTOS"]; if (!empty($resultOffer["PHOTOS_FOR_VK"])) $this->result["PHOTOS_OFFERS_FOR_VK"] += $resultOffer["PHOTOS_FOR_VK"]; $offersConverted[] = $resultOffer; } $offersDescription = $this->createOffersDescriptionByPrices($offersConverted); } // check price. After offers convertions price may be changed if (!$this->result["PRICE"]) { $logger->addError('PRODUCT_EMPTY_PRICE', $data["ID"]); return NULL; } // if exist offers descriptions - add title for them if (strlen($offersDescription) > 0) $this->result["description"] .= "\n\n" . Loc::getMessage("SALE_VK_PRODUCT_VARIANTS") . "\n" . $offersDescription; // sorted photos array in right order // todo: move this operation in Photoresizer $photosSorted = $this->sortPhotosArray(); // CHECK photo sizes and count $photosChecked = Vk\PhotoResizer::checkPhotos($photosSorted, 'PRODUCT'); if (empty($photosChecked)) { $logger->addError("PRODUCT_WRONG_PHOTOS", $data["ID"]); return NULL; } $this->result["PHOTO_MAIN_BX_ID"] = $photosChecked["PHOTO_MAIN_BX_ID"]; $this->result["PHOTO_MAIN_URL"] = $photosChecked["PHOTO_MAIN_URL"]; $this->result["PHOTOS"] = $photosChecked["PHOTOS"]; // add item to log, if image was be resized if ($photosChecked['RESIZE_UP']) $logger->addError('PRODUCT_PHOTOS_RESIZE_UP', $data["ID"]); if ($photosChecked['RESIZE_DOWN']) $logger->addError('PRODUCT_PHOTOS_RESIZE_DOWN', $data["ID"]); // cleaing DESCRIPTION $this->result["description"] = html_entity_decode($this->result["description"]); $this->result["description"] = preg_replace('/\t*/', '', $this->result["description"]); $this->result["description"] = strip_tags($this->result["description"]); // VK don't understand specialchars-quotes. Change them to the yolochki $this->result["description"] = self::convertQuotes($this->result["description"]); // validate LENGTH $this->result['description'] = $this->validateDescription($this->result['description'], $logger); $this->result['NAME'] = self::convertQuotes($this->result['NAME']); $this->result['NAME'] = $this->validateName($this->result['NAME'], $logger); // VK don't understand specialchars-quotes. Change them to the yolochki return array($data["ID"] => $this->result); } /** * Valid length of name * * @param $name * @param Vk\Logger|NULL $logger * @return string */ private function validateName($name, Vk\Logger $logger = NULL) { $newName = $name; if (strlen($name) < self::NAME_LENGHT_MIN) { $newName = str_pad($name, self::NAME_LENGHT_MIN, "_"); if ($logger) { $logger->addError('PRODUCT_SHORT_NAME', $this->result["BX_ID"]); } } if (strlen($name) > self::NAME_LENGHT_MAX) { $newName = substr($name, 0, self::NAME_LENGHT_MAX - 1 - 4) . ' ...'; if ($logger) { $logger->addError('PRODUCT_LONG_NAME', $this->result["BX_ID"]); } } return $newName; } /** * Valid length of description * * @param $name * @param Vk\Logger|NULL $logger * @return string */ private function validateDescription($desc, Vk\Logger $logger = NULL) { $newDesc = $desc; if (strlen($desc) < self::DESCRIPTION_LENGHT_MIN) { $newDesc = $this->result['NAME'] . ': ' . $desc; if (strlen($newDesc) < self::DESCRIPTION_LENGHT_MIN) { $newDesc = str_pad($newDesc, self::DESCRIPTION_LENGHT_MIN, "_"); if ($logger) $logger->addError('PRODUCT_SHORT_DESCRIPTION', $this->result["BX_ID"]); } } if (strlen($newDesc) > self::DESCRIPTION_LENGHT_MAX) { $newDesc = substr($newDesc, 0 ,self::DESCRIPTION_LENGHT_MAX) . '...'; } return $newDesc; } /** * Create description of SKU depending of prices. * If all SKU prices equal main price - hide them. * If prices a different - add them to description * * @param $offers * @return string - string of SKUs description */ private function createOffersDescriptionByPrices($offers) { $mainPrice = isset($this->result['PRICE']) && $this->result['PRICE'] ? $this->result['PRICE'] : 0; $needSkuPriceDescription = false; // compare main price and SKU prices. Find minimum, check difference foreach ($offers as $offer) { if ($offer['PRICE']) { // if not set main price - get them from SKU prices if ($mainPrice == 0) $mainPrice = $offer['PRICE']; // add price to SKU descriptions only of prices is different if ($offer['PRICE'] != $mainPrice) $needSkuPriceDescription = true; $mainPrice = ($mainPrice != 0) ? min($offer['PRICE'], $mainPrice) : $offer['PRICE']; } } // update SKU DESRIPTIONS if needed $offersDescription = ''; if ($needSkuPriceDescription) { foreach ($offers as $offer) { $offersDescription .= $offer["DESCRIPTION_PROPERTIES"] . " - " . Loc::getMessage("SALE_VK_PRODUCT_PRICE") . " " . $offer['PRICE'] . " " . Loc::getMessage("SALE_VK_PRODUCT_CURRENCY") . "\n"; } } else { foreach ($offers as $offer) { $offersDescription .= $offer["DESCRIPTION_PROPERTIES"] . "\n"; } } $this->result['PRICE'] = $mainPrice; return $offersDescription; } /** * Sorted different photos types by priority * * @return array - Array of sorted photos */ private function sortPhotosArray() { $newPhotos = array(); if (isset($this->result['PHOTOS_FOR_VK']) && !empty($this->result['PHOTOS_FOR_VK'])) $newPhotos += $this->result['PHOTOS_FOR_VK']; if (isset($this->result['PHOTOS_OFFERS_FOR_VK']) && !empty($this->result['PHOTOS_OFFERS_FOR_VK'])) $newPhotos += $this->result['PHOTOS_OFFERS_FOR_VK']; if (isset($this->result['PHOTO_MAIN']) && !empty($this->result['PHOTO_MAIN'])) $newPhotos += $this->result['PHOTO_MAIN']; if (isset($this->result['PHOTOS']) && !empty($this->result['PHOTOS'])) $newPhotos += $this->result['PHOTOS']; if (isset($this->result['PHOTOS_OFFERS']) && !empty($this->result['PHOTOS_OFFERS'])) $newPhotos += $this->result['PHOTOS_OFFERS']; // delete wasted photos unset( $this->result['PHOTOS_FOR_VK'], $this->result['PHOTOS_OFFERS_FOR_VK'], $this->result['PHOTOS'], $this->result['PHOTO_MAIN'], $this->result['PHOTOS_OFFERS'] ); return $newPhotos; } /** * Get description, prices and photos by SKUs * * @param $data * @return array * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\SystemException */ private function getItemDataOffersOffer($data) { $result = array("DESCRIPTION" => ""); // create description for SKU PROPERTIES $propertyDescriptions = array(); foreach ($this->selectOfferProps as $prop) { if ($propValue = $data["PROPERTIES"][$prop]["VALUE"]) { // check if HIGLOADBLOCKS if ($data["PROPERTIES"][$prop]["USER_TYPE"] == 'directory') { if (\CModule::IncludeModule('highloadblock')) { // get ID for hl-block $resHlBlocks = HighloadBlockTable::getList(array( 'filter' => array('=TABLE_NAME' => $data["PROPERTIES"][$prop]["USER_TYPE_SETTINGS"]["TABLE_NAME"]), )); $hlBlockItemId = $resHlBlocks->fetch(); $hlBlockItemId = $hlBlockItemId['ID']; // HL directory may not exist in some strange situations if(!$hlBlockItemId) continue; // get entity class for current hl $hlBlock = HighloadBlockTable::getById($hlBlockItemId)->fetch(); $hlEntity = HighloadBlockTable::compileEntity($hlBlock); $strEntityDataClass = $hlEntity->getDataClass(); // get value for current hl $resData = $strEntityDataClass::getList(array( 'select' => array('ID', 'UF_NAME'), 'filter' => array('=UF_XML_ID' => $propValue), )); $propValue = $resData->fetch(); $propValue = $propValue['UF_NAME']; } } if(is_array($propValue)) $propValue = implode(', ', $propValue); $propertyDescriptions[] = $data["PROPERTIES"][$prop]["NAME"] . ": " . $propValue; } } if (!empty($propertyDescriptions)) $result["DESCRIPTION_PROPERTIES"] = implode("; ", $propertyDescriptions); // adding MAIN DESCRIPTION $description = strip_tags(strlen($data["~DETAIL_TEXT"]) > 0 ? $data["~DETAIL_TEXT"] : $data["~PREVIEW_TEXT"]); if ($description) $result["DESCRIPTION"] .= $description; // adding PRICE. Ib desc we adding prices later $result['PRICE'] = $data["PRICES"]["MIN_RUB"]; // adding PHOTOS $photoId = (strlen($data["DETAIL_PICTURE"]) > 0) ? $data["DETAIL_PICTURE"] : $data["PREVIEW_PICTURE"]; if ($photoId) $result["PHOTOS"] = array($photoId => array("PHOTO_BX_ID" => $photoId)); // adding special VK photos $vkPhotosKey = 'PHOTOS_FOR_VK_' . $data["IBLOCK_ID"]; $resOfferProps = new \_CIBElement(); $resOfferProps->fields = array("IBLOCK_ID" => $data["IBLOCK_ID"], "ID" => $data["ID"]); $resOfferProps = $resOfferProps->GetProperties(array(), array("CODE" => $vkPhotosKey)); if (!empty($resOfferProps[$vkPhotosKey]["VALUE"])) { foreach ($resOfferProps[$vkPhotosKey]["VALUE"] as $ph) { $result["PHOTOS_FOR_VK"][$ph] = array( "PHOTO_BX_ID" => $ph, ); } } return $result; } /** * Get main (not SKU) data. * * @param $data * @return array */ private function getNotSkuItemData($data) { $result = array(); $result["BX_ID"] = $data["ID"]; $result["IBLOCK_ID"] = $data["IBLOCK_ID"];; $result["NAME"] = $data["NAME"]; $result["SECTION_ID"] = $data["IBLOCK_SECTION_ID"]; $result["CATEGORY_VK"] = $this->sectionsList->getVkCategory($data["IBLOCK_SECTION_ID"]); // todo: DELETED should depended by AVAILABLE $result["deleted"] = 0; $result["PRICE"] = $data["PRICES"]["MIN_RUB"]; // price converted in roubles $result["description"] = strlen($data["~DETAIL_TEXT"]) > 0 ? $data["~DETAIL_TEXT"] : $data["~PREVIEW_TEXT"]; $result["description"] = trim(preg_replace('/\s{2,}/', "\n", $result["description"])); // get main photo from preview or detail $photoMainBxId = strlen($data["DETAIL_PICTURE"]) > 0 ? $data["DETAIL_PICTURE"] : $data["PREVIEW_PICTURE"]; $photoMainUrl = strlen($data["DETAIL_PICTURE_URL"]) > 0 ? $data["DETAIL_PICTURE_URL"] : $data["PREVIEW_PICTURE_URL"]; if ($photoMainBxId && $photoMainUrl) $result["PHOTO_MAIN"] = array( $photoMainBxId => array( "PHOTO_BX_ID" => $photoMainBxId, "PHOTO_URL" => $photoMainUrl, ), ); // adding MORE PHOTOS to the all_photos array/ Later we will checked sizes if (isset($data["PROPERTIES"]["MORE_PHOTO"]["VALUE"]) && is_array($data["PROPERTIES"]["MORE_PHOTO"]["VALUE"]) && !empty($data["PROPERTIES"]["MORE_PHOTO"]["VALUE"]) ) { foreach ($data["PROPERTIES"]["MORE_PHOTO"]["VALUE"] as $ph) { $result["PHOTOS"][$ph] = array("PHOTO_BX_ID" => $ph); } } // take special VK photos $vkPhotosKey = 'PHOTOS_FOR_VK_' . $data["IBLOCK_ID"]; if (isset($data["PROPERTIES"][$vkPhotosKey]["VALUE"]) && is_array($data["PROPERTIES"][$vkPhotosKey]["VALUE"]) && !empty($data["PROPERTIES"][$vkPhotosKey]["VALUE"]) ) { foreach ($data["PROPERTIES"][$vkPhotosKey]["VALUE"] as $ph) { $result["PHOTOS_FOR_VK"][$ph] = array( "PHOTO_BX_ID" => $ph, ); } } return $result; } }