Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/goodde.yandexturboapi/lib/ |
Upload File : |
<? namespace Goodde\YandexTurbo; use Bitrix\Main, Bitrix\Main\Loader, Bitrix\Currency, Bitrix\Iblock, Bitrix\Catalog, Bitrix\Sale, Bitrix\Main\Type, Bitrix\Main\IO\Path, Bitrix\Main\Config\Option, Bitrix\Main\SystemException, Bitrix\Main\Localization\Loc, Goodde\YandexTurbo\FeedTable, Goodde\YandexTurbo\Condition; Loc::loadMessages(__FILE__); class TurboFeed { public $arResult = array(); protected $feedId = 0; protected $parameters; public $feed; protected $lastId = 0; protected $limitItem = 300; protected $limitDebugItem = 10; protected $amountItem = 10000; public $modeDebug = false; public $arrFilter = array(); public $isGzip = true; public $gzipLevel = 9; protected $isCatalog = false; protected $isCurrency = false; protected $baseCurrency = 'RUB'; protected $obCond; protected $isSubdomainHostId = false; private $_sections_cache = array(); protected $isXmlProfile = false; /** * DateField constructor. * * @param $element * @param array $parameters * * @throws SystemException */ public function __construct($element = 0, $parameters = array()) { $this->feedId = intval($element); $this->parameters = $parameters; $this->isCatalog = Loader::includeModule('catalog'); $this->isCurrency = Loader::includeModule('currency'); if($this->isCurrency) { $this->baseCurrency = Currency\CurrencyManager::getBaseCurrency(); } if($this->isCatalog) { $this->obCond = new \CCatalogCondTree(); } } public function execute($parameters = array()) { global $APPLICATION; $this->loadFeed(); if($parameters['LAST_ID']) $this->lastId = $parameters['LAST_ID']; if($this->feed['FIELDS']['AMOUNT_ITEM']) $this->amountItem = min(intval($this->feed['FIELDS']['AMOUNT_ITEM']), 10000); // is subdomain if($this->feed['FIELDS']['IS_SUBDOMAIN'] == 'Y' && $this->feed['FIELDS']['HOST_ID_SUBDOMAIN']) { $this->isSubdomainHostId = true; $this->feed['SERVER_ADDRESS'] = \Goodde\YandexTurbo\Model\Request::getHostNamebyYandexHostId($this->feed['FIELDS']['HOST_ID_SUBDOMAIN']); } $this->arResult['CHANNEL'] = $this->getChannelDescription(); $this->arResult['ITEMS'] = $this->getItems(); $this->arResult['LAST_ID'] = $this->lastId; return $this->arResult; } public function loadFeed() { if ($this->feedId <= 0) { ShowError(Loc::getMessage("GOODDE_TYRBO_API_ERROR_FEED_ID")); return; } if (!Loader::includeModule('iblock')) { ShowError(Loc::getMessage("GOODDE_TYRBO_API_ERROR_IBLOCK")); return; } if (!$this->feed = FeedTable::getById($this->feedId)->fetch()) { ShowError(Loc::getMessage("GOODDE_TYRBO_API_ERROR_NOT_FEED")); return; } if ($this->feed['ACTIVE'] != 'Y') { ShowError(Loc::getMessage("GOODDE_TYRBO_API_ERROR_NOT_FEED")); return; } } public function SelectedRowsCount() { $this->loadFeed(); $arFilter = $this->getItemsFilter(); return \CIBlockElement::GetList(array(), $arFilter, array(), false, array('ID')); } public function getChannelDescription() { $description = array( 'FEED_ID' => $this->feedId, 'TITLE' => $this->feed['NAME'], 'DESCRIPTION' => $this->feed['DESCRIPTION'], 'LINK' => $this->feed['SERVER_ADDRESS'], ); return $description; } protected function getItems() { $arResult = array(); $arItems = array(); $arCatalog = array(); $selectedPriceType = 0; $selectedOldPriceType = 0; $saleIncluded = false; $needProperties = false; $arProperties = array(); $arOffersProperties = array(); $arStoreSelect = array(); $arStoreFilter = array(); if($this->feed['PROPERTY'] || $this->feed['FIELDS']['CONTENT']) { $needProperties = true; if(!$this->isXmlProfile) { foreach($this->feed['PROPERTY'] as $id) $yandexNeedPropertyIds[$id] = true; unset($id); } $arProperties = $this->getProperty($this->feed['IBLOCK_ID']); $propertyIdList = array_keys($arProperties); } if($saleIncluded = Loader::includeModule('catalog')) { $arCatalog = \CCatalogSKU::GetInfoByIBlock($this->feed['IBLOCK_ID']); if($priceCode = $this->feed['PRICE_CODE']) { //This function returns array with prices description and access rights //in case catalog module n/a prices get values from element properties $arItems['PRICES'] = \CIBlockPriceTools::GetCatalogPrices($this->feed['IBLOCK_ID'], array($priceCode)); $selectedPriceType = (int)$arItems['PRICES'][$priceCode]['ID']; } if($oldPriceCode = $this->feed['OLD_PRICE_CODE']) { //This function returns array with prices description and access rights //in case catalog module n/a prices get values from element properties $arItems['OLD_PRICES'] = \CIBlockPriceTools::GetCatalogPrices($this->feed['IBLOCK_ID'], array($oldPriceCode)); $selectedOldPriceType = (int)$arItems['OLD_PRICES'][$oldPriceCode]['ID']; } //store $arStoreFilter = array('>AMOUNT' => 0, 'STORE.ACTIVE' => 'Y'); $arStoreSelect = array( 'STORE_ID', 'PRODUCT_ID', 'AMOUNT', 'STORE_TITLE' => 'STORE.TITLE', 'STORE_ACTIVE' => 'STORE.ACTIVE', 'STORE_ADDRESS' => 'STORE.ADDRESS', 'STORE_DESCRIPTION' => 'STORE.DESCRIPTION', 'STORE_GPS_N' => 'STORE.GPS_N', 'STORE_GPS_S' => 'STORE.GPS_S', 'STORE_IMAGE_ID' => 'STORE.IMAGE_ID', 'STORE_PHONE' => 'STORE.PHONE', 'STORE_EMAIL' => 'STORE.EMAIL', 'STORE_SCHEDULE' => 'STORE.SCHEDULE', 'STORE_ISSUING_CENTER' => 'STORE.ISSUING_CENTER', 'STORE_SHIPPING_CENTER' => 'STORE.SHIPPING_CENTER' ); $res = \CUserTypeEntity::GetList(array('SORT' => 'ASC'), array('ENTITY_ID' => 'CAT_STORE')); while($arProp = $res->Fetch()) { $arStoreSelect['STORE_'.$arProp['FIELD_NAME']] = 'STORE.'.$arProp['FIELD_NAME']; } } if($selectedPriceType > 0) { $saleDiscountOnly = false; $calculationConfig = array( 'CURRENCY' => $this->baseCurrency, 'USE_DISCOUNTS' => true, 'RESULT_WITH_VAT' => true, 'RESULT_MODE' => Catalog\Product\Price\Calculation::RESULT_MODE_COMPONENT ); if ($saleIncluded) { $saleDiscountOnly = (string)Main\Config\Option::get('sale', 'use_sale_discount_only') == 'Y'; if ($saleDiscountOnly) $calculationConfig['PRECISION'] = (int)Main\Config\Option::get('sale', 'value_precision'); } Catalog\Product\Price\Calculation::setConfig($calculationConfig); unset($calculationConfig); $arCatalogGroupIds = array($selectedPriceType); if($selectedOldPriceType > 0) { $arCatalogGroupIds[] = $selectedOldPriceType; } } $arItems['CATALOG'] = $arCatalog; $sort = $this->getItemsSort(); $filter = $this->getItemsFilter(); $navParams = $this->getItemsNavParams(); $itemFields = $this->getItemsSelect(); $arItems['ITEMS'] = array(); $itemIdsList = array(); $skuIdsList = array(); $simpleIdsList = array(); $iterator = \CIBlockElement::GetList($sort, $filter, false, $navParams, $itemFields); $iterator->SetUrlTemplates($this->feed['DETAIL_URL'], '', ''); while($row = $iterator->GetNext()) { $id = (int)$row['ID']; if($needProperties) $row['PROPERTIES'] = array(); if($arCatalog) { $elementType = (int)($row['CATALOG_TYPE'] ? $row['CATALOG_TYPE'] : $row['TYPE']); $row['PRICES'] = array(); $row['OLD_PRICES'] = array(); if ($elementType == Catalog\ProductTable::TYPE_SKU) $skuIdsList[$id] = $id; else $simpleIdsList[$id] = $id; } if($row['ACTIVE_FROM']) { $data = new Type\DateTime($row['ACTIVE_FROM']); $year = $data->format('Y'); $row['DETAIL_PAGE_URL'] = str_replace('#YEAR#', $year, $row['DETAIL_PAGE_URL']); unset($data, $year); } $arItems['ITEMS'][$id] = $row; $itemIdsList[$id] = $id; $this->lastId = $id; } unset($row, $iterator); if(!empty($arItems['ITEMS'])) { if($needProperties) { $propertyFields = array('ID', 'CODE', 'PROPERTY_TYPE', 'MULTIPLE', 'USER_TYPE', 'NAME', 'USER_TYPE_SETTINGS'); if (!empty($propertyIdList)) { \CIBlockElement::GetPropertyValuesArray( $arItems['ITEMS'], $this->feed['IBLOCK_ID'], array( 'ID' => $itemIdsList, 'IBLOCK_ID' => $this->feed['IBLOCK_ID'] ), array('ID' => $propertyIdList), array('USE_PROPERTY_ID' => 'Y', 'PROPERTY_FIELDS' => $propertyFields) ); } if (!$needProperties) { foreach ($itemIdsList as $id) $arItems['ITEMS'][$id]['PROPERTIES'] = array(); unset($id); } else { foreach($itemIdsList as $id) { if (empty($arItems['ITEMS'][$id]['PROPERTIES'])) continue; foreach (array_keys($arItems['ITEMS'][$id]['PROPERTIES']) as $index) { $propertyId = $arItems['ITEMS'][$id]['PROPERTIES'][$index]['ID']; $propertyCode = $arItems['ITEMS'][$id]['PROPERTIES'][$index]['CODE']; if(isset($yandexNeedPropertyIds[$propertyId]) || $this->isXmlProfile) { if(in_array($arItems['ITEMS'][$id]['PROPERTIES'][$index]['PROPERTY_TYPE'], array('E', 'G', 'S')) || mb_strlen($arItems['ITEMS'][$id]['PROPERTIES'][$index]['USER_TYPE']) > 0) { $arItems['ITEMS'][$id]['PROPERTIES'][$index] = \CIBlockFormatProperties::GetDisplayValue(array(), $arItems['ITEMS'][$id]['PROPERTIES'][$index], $event1 = ''); } if(!$this->isXmlProfile) { $arItems['ITEMS'][$id]['DISPLAY_PROPERTIES'][$propertyCode] = $arItems['ITEMS'][$id]['PROPERTIES'][$index]; } } $arItems['ITEMS'][$id]['PROPERTIES'][$propertyCode] = $arItems['ITEMS'][$id]['PROPERTIES'][$index]; unset($arItems['ITEMS'][$id]['PROPERTIES'][$index]); } unset($propertyId, $propertyCode, $index); } unset($id); } } if(!empty($skuIdsList)) { if(!empty($this->feed['OFFERS_PROPERTY'])) { $offersPropertyFields = array('ID', 'CODE', 'NAME', 'PROPERTY_TYPE', 'USER_TYPE', 'USER_TYPE_SETTINGS'); $offersNeedProperties = true; if(!$this->isXmlProfile) { foreach($this->feed['OFFERS_PROPERTY'] as $id) $yandexNeedoffersPropertyIds[$id] = true; unset($id); } $arOffersProperties = $this->getProperty($arCatalog['IBLOCK_ID']); $offersPropertyIdList = array_keys($arOffersProperties); } $offerPropertyFilter = array(); if ($offersNeedProperties) { if (!empty($offersPropertyIdList)) $offerPropertyFilter = array('ID' => $offersPropertyIdList); } $offers = \CCatalogSku::getOffersList( $skuIdsList, $this->feed['IBLOCK_ID'], $this->getoffersFilter(), $this->getOffersSelect(), $offerPropertyFilter, array('USE_PROPERTY_ID' => 'Y', 'PROPERTY_FIELDS' => $offersPropertyFields) ); unset($offerPropertyFilter); if(!empty($offers)) { $offerLinks = array(); $offerIdsList = array(); $parentsUrl = array(); foreach (array_keys($offers) as $productId) { $arItems['ITEMS'][$productId]['OFFERS'] = array(); foreach(array_keys($offers[$productId]) as $offerId) { $productOffer = $offers[$productId][$offerId]; $productOffer['PRICES'] = array(); $productOffer['OLD_PRICES'] = array(); $productOffer['MIN_PRICE'] = array(); if(!$offersNeedProperties) { $productOffer['PROPERTIES'] = array(); } else { if (!empty($productOffer['PROPERTIES'])) { foreach (array_keys($productOffer['PROPERTIES']) as $index) { $propertyId = $productOffer['PROPERTIES'][$index]['ID']; $propertyCode = $productOffer['PROPERTIES'][$index]['CODE']; if(isset($yandexNeedoffersPropertyIds[$propertyId]) || $this->isXmlProfile) { if(in_array($productOffer['PROPERTIES'][$index]['PROPERTY_TYPE'], array('E', 'G', 'S')) || mb_strlen($productOffer['PROPERTIES'][$index]['USER_TYPE']) > 0) { $productOffer['PROPERTIES'][$index] = \CIBlockFormatProperties::GetDisplayValue(array(), $productOffer['PROPERTIES'][$index], $event1 = ''); } if(!$this->isXmlProfile) { $productOffer['DISPLAY_PROPERTIES'][$propertyCode] = $productOffer['PROPERTIES'][$index]; } } $productOffer['PROPERTIES'][$propertyCode] = $productOffer['PROPERTIES'][$index]; unset($productOffer['PROPERTIES'][$index]); } unset($propertyId, $propertyCode, $index); } } $arItems['ITEMS'][$productId]['OFFERS'][$offerId] = $productOffer; unset($productOffer); $offerLinks[$offerId] = &$arItems['ITEMS'][$productId]['OFFERS'][$offerId]; $offerIdsList[$offerId] = $offerId; } unset($offerId); } if(!empty($offerIdsList)) { if($selectedPriceType > 0) { foreach (array_chunk($offerIdsList, 500) as $pageIds) { // load vat cache $vatList = \CCatalogProduct::GetVATDataByIDList($pageIds); unset($vatList); $priceFilter = array( '@PRODUCT_ID' => $pageIds, '@CATALOG_GROUP_ID' => $arCatalogGroupIds, array( 'LOGIC' => 'OR', '<=QUANTITY_FROM' => 1, '=QUANTITY_FROM' => null ), array( 'LOGIC' => 'OR', '>=QUANTITY_TO' => 1, '=QUANTITY_TO' => null ) ); $iterator = Catalog\PriceTable::getList([ 'select' => ['ID', 'PRODUCT_ID', 'CATALOG_GROUP_ID', 'PRICE', 'CURRENCY'], 'filter' => $priceFilter ]); while ($price = $iterator->fetch()) { $id = (int)$price['PRODUCT_ID']; $priceTypeId = (int)$price['CATALOG_GROUP_ID']; if($priceTypeId == $selectedOldPriceType) { $offerLinks[$id]['OLD_PRICES'][$priceTypeId] = $price; } else { $offerLinks[$id]['PRICES'][$priceTypeId] = $price; } unset($priceTypeId, $id); } unset($price, $iterator); if ($saleDiscountOnly) { Catalog\Discount\DiscountManager::preloadPriceData( $pageIds, ($selectedPriceType > 0 ? [$selectedPriceType] : $priceTypeList) ); } /*bind events*/ foreach(GetModuleEvents("goodde.yandexturboapi", "OnStoreElementFilterBefore", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($this->feed, &$arStoreFilter)); } if(!is_array($arStoreFilter)) $arStoreFilter = array(); $arStoreFilter['@PRODUCT_ID'] = $pageIds; $resStore = \Bitrix\Catalog\StoreProductTable::getlist(array( 'filter' => $arStoreFilter, 'select' => $arStoreSelect )); while($arStore = $resStore->fetch()) { $id = (int)$arStore['PRODUCT_ID']; $storeId = (int)$arStore['STORE_ID']; foreach($arStoreSelect as $select) { $select = str_replace('STORE.', 'STORE_', $select); $offerLinks[$id]['STORE'][$select][$storeId] = $arStore[$select]; } } unset($storeId, $id, $arStore, $select); } unset($pageIds); foreach($offerIdsList as $id) { $row = $offerLinks[$id]; if(!empty($row['PRICES'])) { $calculatePrice = \CCatalogProduct::GetOptimalPrice( $row['ID'], 1, array(2), // anonymous 'N', $row['PRICES'], $this->feed['LID'], array() ); if(!empty($calculatePrice)) { $offerLinks[$id]['MIN_PRICE'] = array( 'DISCOUNT_VALUE' => $calculatePrice['RESULT_PRICE']['DISCOUNT_PRICE'], 'PRINT_DISCOUNT_VALUE' => \CCurrencyLang::CurrencyFormat($calculatePrice['RESULT_PRICE']['DISCOUNT_PRICE'], $calculatePrice['RESULT_PRICE']['CURRENCY'], true), 'DISCOUNT' => $calculatePrice['RESULT_PRICE']['DISCOUNT'], 'PRINT_DISCOUNT' => \CCurrencyLang::CurrencyFormat($calculatePrice['RESULT_PRICE']['DISCOUNT'], $calculatePrice['RESULT_PRICE']['CURRENCY'], true), 'PERCENT' => ceil($calculatePrice['RESULT_PRICE']['PERCENT']), 'VALUE' => $calculatePrice['RESULT_PRICE']['BASE_PRICE'], 'PRINT_VALUE' => \CCurrencyLang::CurrencyFormat($calculatePrice['RESULT_PRICE']['BASE_PRICE'], $calculatePrice['RESULT_PRICE']['CURRENCY'], true), 'CURRENCY' => $calculatePrice['RESULT_PRICE']['CURRENCY'], 'PRICE_TYPE_ID' => $calculatePrice['RESULT_PRICE']['PRICE_TYPE_ID'], ); } unset($calculatePrice); } if(!empty($row['OLD_PRICES'])) { $calculatePrice = \CCatalogProduct::GetOptimalPrice( $row['ID'], 1, array(2), // anonymous 'N', $row['OLD_PRICES'], $this->feed['LID'], array() ); if(!empty($calculatePrice)) { $offerLinks[$id]['OLD_MIN_PRICE'] = array( 'DISCOUNT_VALUE' => $calculatePrice['RESULT_PRICE']['DISCOUNT_PRICE'], 'PRINT_DISCOUNT_VALUE' => \CCurrencyLang::CurrencyFormat($calculatePrice['RESULT_PRICE']['DISCOUNT_PRICE'], $calculatePrice['RESULT_PRICE']['CURRENCY'], true), 'DISCOUNT' => $calculatePrice['RESULT_PRICE']['DISCOUNT'], 'PRINT_DISCOUNT' => \CCurrencyLang::CurrencyFormat($calculatePrice['RESULT_PRICE']['DISCOUNT'], $calculatePrice['RESULT_PRICE']['CURRENCY'], true), 'PERCENT' => ceil($calculatePrice['RESULT_PRICE']['PERCENT']), 'VALUE' => $calculatePrice['RESULT_PRICE']['BASE_PRICE'], 'PRINT_VALUE' => \CCurrencyLang::CurrencyFormat($calculatePrice['RESULT_PRICE']['BASE_PRICE'], $calculatePrice['RESULT_PRICE']['CURRENCY'], true), 'CURRENCY' => $calculatePrice['RESULT_PRICE']['CURRENCY'], 'PRICE_TYPE_ID' => $calculatePrice['RESULT_PRICE']['PRICE_TYPE_ID'], ); } unset($calculatePrice); } } } } unset($offerIdsList, $offerLinks); } unset($arOffers); } if(!empty($simpleIdsList)) { if($selectedPriceType > 0) { foreach (array_chunk($simpleIdsList, 500) as $pageIds) { // load vat cache $vatList = \CCatalogProduct::GetVATDataByIDList($pageIds); unset($vatList); $priceFilter = array( '@PRODUCT_ID' => $pageIds, '@CATALOG_GROUP_ID' => $arCatalogGroupIds, array( 'LOGIC' => 'OR', '<=QUANTITY_FROM' => 1, '=QUANTITY_FROM' => null ), array( 'LOGIC' => 'OR', '>=QUANTITY_TO' => 1, '=QUANTITY_TO' => null ) ); $iterator = Catalog\PriceTable::getList([ 'select' => ['ID', 'PRODUCT_ID', 'CATALOG_GROUP_ID', 'PRICE', 'CURRENCY'], 'filter' => $priceFilter ]); while ($price = $iterator->fetch()) { $id = (int)$price['PRODUCT_ID']; $priceTypeId = (int)$price['CATALOG_GROUP_ID']; if($priceTypeId == $selectedOldPriceType) { $arItems['ITEMS'][$id]['OLD_PRICES'][$priceTypeId] = $price; } else { $arItems['ITEMS'][$id]['PRICES'][$priceTypeId] = $price; } unset($priceTypeId, $id); } unset($price, $iterator); if ($saleDiscountOnly) { Catalog\Discount\DiscountManager::preloadPriceData( $pageIds, ($selectedPriceType > 0 ? [$selectedPriceType] : $priceTypeList) ); } /*bind events*/ foreach(GetModuleEvents("goodde.yandexturboapi", "OnStoreElementFilterBefore", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($this->feed, &$arStoreFilter)); } if(!is_array($arStoreFilter)) $arStoreFilter = array(); $arStoreFilter['@PRODUCT_ID'] = $pageIds; $resStore = \Bitrix\Catalog\StoreProductTable::getlist(array( 'filter' => $arStoreFilter, 'select' => $arStoreSelect )); while($arStore = $resStore->fetch()) { $id = (int)$arStore['PRODUCT_ID']; $storeId = (int)$arStore['STORE_ID']; foreach($arStoreSelect as $select) { $select = str_replace('STORE.', 'STORE_', $select); $arItems['ITEMS'][$id]['STORE'][$select][$storeId] = $arStore[$select]; } } unset($storeId, $id, $arStore, $select); } unset($pageIds); foreach($itemIdsList as $id) { $row = $arItems['ITEMS'][$id]; if (isset($simpleIdsList[$id]) && !empty($row['PRICES'])) { $calculatePrice = \CCatalogProduct::GetOptimalPrice( $row['ID'], 1, array(2), // anonymous 'N', $row['PRICES'], $this->feed['LID'], array() ); if(!empty($calculatePrice)) { $arItems['ITEMS'][$id]['MIN_PRICE'] = array( 'DISCOUNT_VALUE' => $calculatePrice['RESULT_PRICE']['DISCOUNT_PRICE'], 'PRINT_DISCOUNT_VALUE' => \CCurrencyLang::CurrencyFormat($calculatePrice['RESULT_PRICE']['DISCOUNT_PRICE'], $calculatePrice['RESULT_PRICE']['CURRENCY'], true), 'DISCOUNT' => $calculatePrice['RESULT_PRICE']['DISCOUNT'], 'PRINT_DISCOUNT' => \CCurrencyLang::CurrencyFormat($calculatePrice['RESULT_PRICE']['DISCOUNT'], $calculatePrice['RESULT_PRICE']['CURRENCY'], true), 'PERCENT' => ceil($calculatePrice['RESULT_PRICE']['PERCENT']), 'VALUE' => $calculatePrice['RESULT_PRICE']['BASE_PRICE'], 'PRINT_VALUE' => \CCurrencyLang::CurrencyFormat($calculatePrice['RESULT_PRICE']['BASE_PRICE'], $calculatePrice['RESULT_PRICE']['CURRENCY'], true), 'CURRENCY' => $calculatePrice['RESULT_PRICE']['CURRENCY'], 'PRICE_TYPE_ID' => $calculatePrice['RESULT_PRICE']['PRICE_TYPE_ID'], ); } unset($calculatePrice); } if (isset($simpleIdsList[$id]) && !empty($row['OLD_PRICES'])) { $calculatePrice = \CCatalogProduct::GetOptimalPrice( $row['ID'], 1, array(2), // anonymous 'N', $row['OLD_PRICES'], $this->feed['LID'], array() ); if(!empty($calculatePrice)) { $arItems['ITEMS'][$id]['OLD_MIN_PRICE'] = array( 'DISCOUNT_VALUE' => $calculatePrice['RESULT_PRICE']['DISCOUNT_PRICE'], 'PRINT_DISCOUNT_VALUE' => \CCurrencyLang::CurrencyFormat($calculatePrice['RESULT_PRICE']['DISCOUNT_PRICE'], $calculatePrice['RESULT_PRICE']['CURRENCY'], true), 'DISCOUNT' => $calculatePrice['RESULT_PRICE']['DISCOUNT'], 'PRINT_DISCOUNT' => \CCurrencyLang::CurrencyFormat($calculatePrice['RESULT_PRICE']['DISCOUNT'], $calculatePrice['RESULT_PRICE']['CURRENCY'], true), 'PERCENT' => ceil($calculatePrice['RESULT_PRICE']['PERCENT']), 'VALUE' => $calculatePrice['RESULT_PRICE']['BASE_PRICE'], 'PRINT_VALUE' => \CCurrencyLang::CurrencyFormat($calculatePrice['RESULT_PRICE']['BASE_PRICE'], $calculatePrice['RESULT_PRICE']['CURRENCY'], true), 'CURRENCY' => $calculatePrice['RESULT_PRICE']['CURRENCY'], 'PRICE_TYPE_ID' => $calculatePrice['RESULT_PRICE']['PRICE_TYPE_ID'], ); } unset($calculatePrice); } } } } foreach($arItems['ITEMS'] as $arItem) { $arResult[] = $this->prepareItem($arItem); } if($this->feed['RELATED_SOURCE'] === 'QUEUE') { $count = count($arResult); if($count >= 10) { foreach($arResult as $key => $arItem) { if($arRelated = $this->getRelatedItems($count, $key, $arRelated, $this->feed['RELATED_LIMIT'])) { foreach($arRelated as $k => $v) { $arResult[$key]['RELATED'][$k] = array( 'LINK' => $arResult[$v]['LINK'], 'PICTURE' => $arResult[$v]['PICTURE'], 'TITLE' => $arResult[$v]['PAGE_TITLE'], ); } } } unset($count, $arRelated); } } } unset($arItems); return array_values($arResult); } public function getItemsFilter() { $arFilter = array(); $elementsFilter = (array)$this->feed['ELEMENTS_FILTER']; foreach($elementsFilter as $k => $val) { if($val === 'N') unset($elementsFilter[$k]); } $arFilter = array_merge($arFilter, $elementsFilter); if(is_array($this->feed['ELEMENTS_CONDITION']) && $this->feed['ELEMENTS_CONDITION']) { $condition = new Condition(); $conditionFilter = $condition->getConditionFilter($this->feed['ELEMENTS_CONDITION'], $arFilter); if($conditionFilter) { $arFilter[] = $conditionFilter; } unset($conditionFilter, $condition); } if(!is_array($this->arrFilter)) $this->arrFilter = array(); /*bind events*/ foreach(GetModuleEvents("goodde.yandexturboapi", "OnFeedOneStepElementFilterBefore", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($this->feed, &$this->arrFilter)); } if(!is_array($this->arrFilter)) $this->arrFilter = array(); $arFilter = array_merge($arFilter, $this->arrFilter); $arFilter['IBLOCK_ID'] = $this->feed['IBLOCK_ID']; if($this->feed['DATE_ADD_FEED'] && !($this->feed['ALL_FEED'] == 'Y' || $this->modeDebug)) { $arFilter['>TIMESTAMP_X'] = $this->feed['DATE_ADD_FEED']; } if($this->feed['ACTIVE_DATE'] == 'Y') { $arFilter['ACTIVE_DATE'] = 'Y'; } if(intval($this->lastId) > 0) { $arFilter['>ID'] = $this->lastId; } return $arFilter; } protected function getBaseSelect() { return array( 'ID', 'XML_ID', 'CODE', 'NAME', 'ACTIVE', 'IBLOCK_ID', 'IBLOCK_CODE', 'DATE_CREATE', 'ACTIVE_FROM', 'ACTIVE_TO', 'SORT', 'IBLOCK_SECTION_ID', 'DETAIL_PAGE_URL', 'PREVIEW_PICTURE', 'DETAIL_PICTURE', 'PREVIEW_TEXT', 'DETAIL_TEXT', 'SEARCHABLE_CONTENT', 'TIMESTAMP_X', 'MODIFIED_BY', 'IBLOCK_SECTION_NAME', 'LIST_PAGE_URL', 'SHOW_COUNTER', 'TAGS', ); } protected function getBaseCatalogSelect() { return array( 'TYPE', 'MEASURE', 'AVAILABLE', 'VAT_ID', 'VAT_INCLUDED', 'QUANTITY', 'QUANTITY_TRACE', 'CAN_BUY_ZERO', 'SUBSCRIBE', 'WEIGHT', 'LENGTH', 'HEIGHT', 'GROUP_ID', ); } protected function getItemsSelect() { $select = $this->getBaseSelect(); $select[] = $this->feed['CONTENT']; if($this->feed['PRICE_CODE']) { $select[] = 'CATALOG_TYPE'; } return array_unique($select); } protected function getItemsSort() { $sort = array( 'ID' => 'asc', ); return $sort; } protected function getItemsNavParams($parameters = array()) { if($this->modeDebug) { $this->feed['LIMIT'] = $this->limitDebugItem; } elseif (intval($this->feed['LIMIT']) > 0) { $this->feed['LIMIT'] = min($this->feed['LIMIT'], $this->limitItem); } else { $this->feed['LIMIT'] = $this->limitItem; } $nav = array( 'nTopCount' => intval($this->feed['LIMIT']), ); return $nav; } protected function getoffersFilter() { $arFilter = array(); $offersFilter = (array)$this->feed['OFFERS_FILTER']; foreach($offersFilter as $k => $val) { if($val === 'N') unset($offersFilter[$k]); } $arFilter = array_merge($arFilter, $offersFilter); if(is_array($this->feed['OFFERS_CONDITION']) && $this->feed['OFFERS_CONDITION']) { $condition = new Condition(); $conditionFilter = $condition->getConditionFilter($this->feed['OFFERS_CONDITION'], $arFilter); if($conditionFilter) { $arFilter[] = $conditionFilter; } unset($conditionFilter, $condition); } $arFilter['IBLOCK_ID'] = $this->feed['IBLOCK_ID']; return $arFilter; } protected function getOffersSort() { $sort = array( 'ID' => 'asc', 'NAME' => 'asc', ); return $sort; } protected function getOffersSelect() { $select = array( 'ID', 'XML_ID', 'CODE', 'NAME', 'ACTIVE', 'IBLOCK_ID', 'IBLOCK_CODE', 'SORT', 'DETAIL_PAGE_URL', 'PREVIEW_PICTURE', 'DETAIL_PICTURE', 'PREVIEW_TEXT', 'DETAIL_TEXT', 'CATALOG_QUANTITY', ); return $select; } protected function getOffersPropertyCode() { $propertyCode = array(); if($this->feed['OFFERS_PROPERTY']) { $propertyCode = $this->feed['OFFERS_PROPERTY']; } return array_unique($propertyCode); } protected function getProperty($iblockId = 0) { $arProperties = array(); $rsProps = \CIBlockProperty::GetList( array('SORT' => 'ASC', 'NAME' => 'ASC'), array('IBLOCK_ID' => $iblockId, 'ACTIVE' => 'Y', 'CHECK_PERMISSIONS' => 'N') ); while ($arProp = $rsProps->Fetch()) { $arProp['ID'] = (int)$arProp['ID']; $arProp['USER_TYPE'] = (string)$arProp['USER_TYPE']; $arProp['CODE'] = (string)$arProp['CODE']; if ($arProp['CODE'] == '') $arProp['CODE'] = $arProp['ID']; $arProp['LINK_IBLOCK_ID'] = (int)$arProp['LINK_IBLOCK_ID']; $arProperties[$arProp['ID']] = $arProp; } return $arProperties; } protected function prepareItem($arItem = array()) { $arItems = array( 'ID' => $arItem['ID'], 'ACTIVE' => $arItem['ACTIVE'], 'SERVER_ADDRESS' => $this->feed['SERVER_ADDRESS'], 'IS_EXTENDED_HTML' => $this->feed['FIELDS']['IS_EXTENDED_HTML'], 'LINK' => $this->feed['SERVER_ADDRESS'].$arItem['DETAIL_PAGE_URL'], 'DESCRIPTION' => $this->fullTextFormatting($arItem['PREVIEW_TEXT']), 'MENU' => '', 'CATEGORY' => false, 'MIN_PRICE' => $arItem['MIN_PRICE'], 'TURBO_CONTENT' => '', 'PROPERTIES' => $arItem['PROPERTIES'], 'DISPLAY_PROPERTIES' => $arItem['DISPLAY_PROPERTIES'], 'PUB_DATE' => '', ); if(!is_array($arItem['OFFERS'])) $arItem['OFFERS'] = array(); if($arItem['IBLOCK_SECTION_ID'] > 0) { if(!array_key_exists($arItem['IBLOCK_SECTION_ID'], $this->_sections_cache)) { $this->_sections_cache[$arItem['IBLOCK_SECTION_ID']] = ''; $rsNavChain = \CIBlockSection::GetNavChain($arItem['IBLOCK_ID'], $arItem['IBLOCK_SECTION_ID']); while($arNavChain = $rsNavChain->Fetch()) { $this->_sections_cache[$arItem['IBLOCK_SECTION_ID']] .= $this->fullTextFormatting($arNavChain["NAME"]).'/'; } } if($navChain = $this->_sections_cache[$arItem['IBLOCK_SECTION_ID']]) { $arItems['CATEGORY'] = trim($navChain, '/'); } } if($arItem['DETAIL_PICTURE']) { $arItems['PICTURE'] = $this->getImagePath($arItem['DETAIL_PICTURE']); } elseif($arItem['PREVIEW_PICTURE']) { $arItems['PICTURE'] = $this->getImagePath($arItem['PREVIEW_PICTURE']); } else { $arItems['PICTURE'] = false; } if($arItem['OFFERS'] && mb_strlen($arItems['PICTURE']) == 0) { foreach($arItem['OFFERS'] as $arOffer) { if($arOffer['DETAIL_PICTURE']) { $arItems['PICTURE'] = $this->getImagePath($arOffer['DETAIL_PICTURE']); break; } elseif($arOffer['PREVIEW_PICTURE']) { $arItems['PICTURE'] = $this->getImagePath($arOffer['PREVIEW_PICTURE']); break; } } } $arItem['IPROPERTY_VALUES'] = $ipropertyValues = array(); $ipropValues = new \Bitrix\Iblock\InheritedProperty\ElementValues($this->feed['IBLOCK_ID'], $arItem['ID']); $arItem['IPROPERTY_VALUES'] = $ipropertyValues = $ipropValues->getValues(); if(mb_strlen($ipropertyValues['G_ELEMENT_META_TITLE_'.$this->feed['ID']]) > 0) { $arItems['TITLE'] = $this->fullTextFormatting($ipropertyValues['G_ELEMENT_META_TITLE_'.$this->feed['ID']]); } elseif(mb_strlen($ipropertyValues['ELEMENT_META_TITLE']) > 0) { $arItems['TITLE'] = $this->fullTextFormatting($ipropertyValues['ELEMENT_META_TITLE']); } else { $arItems['TITLE'] = $this->fullTextFormatting($arItem['NAME']); } if(mb_strlen($ipropertyValues['G_ELEMENT_PAGE_TITLE_'.$this->feed['ID']]) > 0) { $arItems['PAGE_TITLE'] = $this->fullTextFormatting($ipropertyValues['G_ELEMENT_PAGE_TITLE_'.$this->feed['ID']]); } elseif(mb_strlen($ipropertyValues['ELEMENT_PAGE_TITLE']) > 0) { $arItems['PAGE_TITLE'] = $this->fullTextFormatting($ipropertyValues['ELEMENT_PAGE_TITLE']); } else { $arItems['PAGE_TITLE'] = $this->fullTextFormatting($arItem['NAME']); } unset($ipropertyValues); if($pubDate = $arItem[$this->feed['PUB_DATE']]) { $arItems['PUB_DATE'] = date("r", MkDateTime($GLOBALS['DB']->FormatDate($pubDate, \Clang::GetDateFormat("FULL"), "DD.MM.YYYY H:I:S"), "d.m.Y H:i:s")); } $contentField = $this->feed['CONTENT']; if(mb_substr($contentField, 0, 9) == 'PROPERTY_') { if(isset($arItem[$contentField . '_VALUE']['TEXT'])) { $arItems['TURBO_CONTENT'] = $this->prepareTurboContent($arItem['~'.$contentField . '_VALUE']['TEXT']); } else { $arItems['TURBO_CONTENT'] = $this->prepareTurboContent($arItem[$contentField . '_VALUE']); } } else { $arItems['TURBO_CONTENT'] = $this->prepareTurboContent($arItem[$contentField]); $arItems['~TURBO_CONTENT'] = $this->prepareTurboContent($arItem['~'.$contentField]); } unset($contentField); $arItems['TURBO_CONTENT_FIELDS'] = $this->prepareItemContentFields($arItem); unset($arItem['PROPERTIES'], $arItem['DISPLAY_PROPERTIES'], $arItem['MIN_PRICE']); if($this->feed['MENU']) { foreach($this->feed['MENU'] as $arMenu) { if(mb_strlen($arMenu[1])>0) $arItems['MENU'] .= '<a href="'.$this->feed['SERVER_ADDRESS'].$arMenu[1].'">'.$arMenu[0].'</a>'; } } if($this->feed['FEEDBACK'] && isset($this->feed['FEEDBACK']['SHOW'])) { if(mb_strlen($this->feed['FEEDBACK']['TITLE']) > 0) $arItems['FEEDBACK']['TITLE'] = $this->feed['FEEDBACK']['TITLE']; if(mb_strlen($this->feed['FORM']['AGREEMENT']['COMPANY']) > 0 && mb_strlen($this->feed['FORM']['AGREEMENT']['LINK']) > 0) { $arItems['FORM'] = array( 'AGREEMENT_COMPANY' => $this->feed['FORM']['AGREEMENT']['COMPANY'], 'AGREEMENT_LINK' => $this->feed['FORM']['AGREEMENT']['LINK'], ); } if($this->feed['FEEDBACK']['TYPE']) { foreach($this->feed['FEEDBACK']['TYPE'] as $key => $arFeedback) { $arItems['FEEDBACK']['ITEMS'][$arFeedback['STICK']]['TYPE'][$key] = array( 'TYPE' => $arFeedback['PROVIDER_KEY'], ); switch($arFeedback['PROVIDER_KEY']) { case 'mail': $arItems['FEEDBACK']['ITEMS'][$arFeedback['STICK']]['TYPE'][$key]['VALUE'] = 'mailto:'.$arFeedback['PROVIDER_VALUE'][$arFeedback['PROVIDER_KEY']]; break; case 'call': $arItems['FEEDBACK']['ITEMS'][$arFeedback['STICK']]['TYPE'][$key]['VALUE'] = 'tel:'.$arFeedback['PROVIDER_VALUE'][$arFeedback['PROVIDER_KEY']]; break; case 'chat': break; default; $arItems['FEEDBACK']['ITEMS'][$arFeedback['STICK']]['TYPE'][$key]['VALUE'] = $arFeedback['PROVIDER_VALUE'][$arFeedback['PROVIDER_KEY']]; break; } } } } else { $arItems['FEEDBACK'] = array(); $arItems['FORM'] = array(); } if($galleryField = $this->feed['GALLERY']) { $galleryFiles = array(); $res = \CIBlockElement::GetProperty($this->feed['IBLOCK_ID'], $arItem['ID'], array(), array('CODE' => $galleryField, 'ACTIVE' => 'Y')); while($value = $res->Fetch()) { if ($value['VALUE']) { if($filePath = $this->getImagePath($value['VALUE'])) { $galleryFiles[] = $filePath; } } } if(!empty($galleryFiles)) { $arItems['GALLERY'] = array( 'TITLE' => $this->feed['GALLERY_TITLE'], 'ITEMS' => $galleryFiles, ); } unset($galleryFiles); } $arItems['SHARE'] = $this->feed['SHARE_NETWORKS'] ? $this->feed['SHARE_NETWORKS'] : array(); $arItems['RELATED_INFINITY'] = $this->feed['RELATED_SOURCE']; $arItems['OFFERS'] = $arItem['OFFERS']; unset($arItem['OFFERS']); $arItems['ELEMENT'] = $arItem; return $arItems; } protected function prepareItemContentFields($arItem = array()) { $arResult = $previewPic = $detailPic = array(); if($arItem['PREVIEW_PICTURE']) { $previewPic = array( 'ID' => ($arItem['~PREVIEW_PICTURE'] ? $arItem['~PREVIEW_PICTURE'] : $arItem['PREVIEW_PICTURE']['ID']), 'SRC' => $this->getImagePath(($arItem['~PREVIEW_PICTURE'] ? $arItem['~PREVIEW_PICTURE'] : $arItem['PREVIEW_PICTURE']['ID'])), ); if($this->isXmlProfile) { $arItem['PREVIEW_PICTURE'] = $previewPic['SRC']; } else { $arItem['PREVIEW_PICTURE'] = '<figure><img src="'.$previewPic['SRC'].'"/></figure>'; } } if($arItem['DETAIL_PICTURE']) { $detailPic = array( 'ID' => ($arItem['~DETAIL_PICTURE'] ? $arItem['~DETAIL_PICTURE'] : $arItem['DETAIL_PICTURE']['ID']), 'SRC' => $this->getImagePath(($arItem['~DETAIL_PICTURE'] ? $arItem['~DETAIL_PICTURE'] : $arItem['DETAIL_PICTURE']['ID'])), ); if($this->isXmlProfile) { $arItem['DETAIL_PICTURE'] = $detailPic['SRC']; } else { $arItem['DETAIL_PICTURE'] = '<figure><img src="'.$detailPic['SRC'].'"/></figure>'; } } if($this->isXmlProfile) { if(mb_strlen($arItem['DETAIL_PAGE_URL']) > 0) { $arItem['DETAIL_PAGE_URL'] = $this->formatUri( $this->feed['SERVER_ADDRESS'] . $arItem['DETAIL_PAGE_URL'], $this->feed['UTM_TAGS'], $arItem['ID'] ); } if($arItem['WEIGHT'] && $this->feed['WEIGHT_KOEF']) { $arItem['WEIGHT'] = roundEx(doubleval($arItem['WEIGHT'] / $this->feed['WEIGHT_KOEF']), SALE_WEIGHT_PRECISION); } if($this->feed['STORES'] && $arItem['STORE']) { $quantity = 0; foreach ($this->feed['STORES'] as $storeId) { if(isset($arItem['STORE']['AMOUNT'][$storeId])) { $quantity += (float)$arItem['STORE']['AMOUNT'][$storeId]; } } $arItem['PRODUCT']['QUANTITY'] = $quantity; } } /* @CONSTRUCTOR FIELD */ if($this->feed['FIELDS']['CONTENT']) { foreach($this->feed['FIELDS']['CONTENT'] as $i => $arField) { // function handler $userFunc = ''; if($arField['USE_FUNCTION'] == 'Y' && $arField['FUNCTION']) { $userFunc = trim($arField['FUNCTION']); // Format: TurboYa::getDetailText || Turbo\Export\Ya\Feed::getDetailText preg_match('/([a-z_\\\]+)::([a-z_]+)/is', $userFunc, $matches); if($matches[1] && $matches[2] && class_exists($matches[1], true) && method_exists($matches[1], $matches[2])) { $userFunc = $userFunc; } elseif(method_exists(__CLASS__, $userFunc)) { $userFunc = __CLASS__ . '::' . $userFunc; } elseif(!function_exists($arField['FUNCTION'])) { $userFunc = ''; } } $isCustom = $arField['IS_CUSTOM']; $isRequired = $arField['REQUIRED'] == 'Y'; $isSingle = false; $isMultiple = false; $isMultipleType = (count($arField['TYPE']) > 1 ? true : false); if($arField['USE_CONCAT'] == 'Y') { if($arField['CONCAT_VALUE'] == 'MULTIPLE') $isMultiple = true; if($arField['CONCAT_VALUE'] == 'SINGLE') $isSingle = true; } if($isMultiple) $isMultipleType = false; $textLength = ($arField['USE_TEXT_LENGTH'] == 'Y' ? intval($arField['TEXT_LENGTH']) : 0); $propName = ''; $propUnit = trim($arField['UNIT_VALUE']); $propAttr = array(); $key = $arField['CODE']; $tmpValue = null; $value = null; /* @TYPE FIELD */ foreach($arField['TYPE'] as $typeKey => $typeId) { $typeValue = $arField['VALUE'][$typeKey]; /** Field */ if($typeId == 'FIELD' || $typeId == 'OFFER_FIELD') { $tmpValue = $arItem[$typeValue]; /** Date format */ if($arField['USE_DATE_FORMAT'] == 'Y' && is_string($tmpValue) && mb_strlen($tmpValue) > 0) { if($dateFormat = trim($arField['DATE_FORMAT_VALUE'])) { $date = new Type\DateTime($tmpValue); $newDate = $date->format($dateFormat); $tmpValue = $newDate; unset($date, $newDate); } } if($isMultiple) { if($typeValue == 'PREVIEW_PICTURE') { $value[$previewPic['ID']] = $tmpValue; } elseif($typeValue == 'DETAIL_PICTURE') { $value[$detailPic['ID']] = $tmpValue; } else { $value[] = $tmpValue; } } elseif($isSingle) { $value .= ' ' . $tmpValue; } elseif($isMultipleType) { if($typeValue == 'PREVIEW_PICTURE') { $value[$previewPic['ID']] = $tmpValue; } elseif($typeValue == 'DETAIL_PICTURE') { $value[$detailPic['ID']] = $tmpValue; } else { $value[] = $tmpValue; } } else { $value = $tmpValue; } } /** Property */ if($typeId == 'PROPERTY' || $typeId == 'OFFER_PROPERTY') { if($arProp = $arItem['PROPERTIES'][$typeValue]) { $propName = $arProp['NAME']; $propValue = ''; if($arProp['USER_TYPE'] == 'HTML') { if($arProp['~VALUE']) { $propValue = ($arProp['MULTIPLE'] == 'Y' ? array_column($arProp['~VALUE'], 'TEXT') : $arProp['~VALUE']['TEXT']); } } else { $propValue = ($arProp['USER_TYPE'] && $arProp['DISPLAY_VALUE'] ? $arProp['DISPLAY_VALUE'] : $arProp['~VALUE']); //DISPLAY_VALUE } if($arProp['PROPERTY_TYPE'] == 'F') { if($propValue) { $isContent = (!$this->isXmlProfile && $key === 'content' ? true : false); if(is_array($propValue)) { foreach($propValue as $kFile => $vFile) { $propValue[$vFile] = $this->getImagePath($vFile, $isContent); unset($propValue[ $kFile ]); } unset($kFile, $vFile); } else { $propValue = $this->getImagePath($propValue, $isContent); } unset($isContent); } } elseif($arProp['PROPERTY_TYPE'] == 'L') { if(!is_array($propValue)) $arItem['PROPERTY_'. $arProp['ID'] .'_VALUE'] = array($arProp['VALUE_ENUM_ID']); } elseif($arProp['USER_TYPE'] == 'DateTime') { if($propValue) { if(is_array($propValue)) { foreach($propValue as $kProp => $vProp) { if($arField['USE_DATE_FORMAT'] == 'Y' && is_string($vProp) && mb_strlen($vProp) > 0) { if($dateFormat = trim($arField['DATE_FORMAT_VALUE'])) { $vProp = (new Type\DateTime($vProp))->format($dateFormat); $propValue[$vProp] = $vProp; unset($propValue[$kPro]); } } } unset($kProp, $vProp); } else { if($arField['USE_DATE_FORMAT'] == 'Y' && is_string($propValue) && mb_strlen($propValue) > 0) { if($dateFormat = trim($arField['DATE_FORMAT_VALUE'])) { $propValue = (new Type\DateTime($propValue))->format($dateFormat); } } } } } if($isCustom && mb_strlen($propUnit) == 0 && $this->isXmlProfile) { $propUnit = trim(is_array($arProp['DESCRIPTION']) ? $arProp['DESCRIPTION'][0] : $arProp['DESCRIPTION']); } if($isMultiple) { if(is_array($propValue)) { foreach($propValue as $pKey => $pVal) { $value[$pKey] = $pVal; } unset($pKey, $pVal); } else $value[] = $propValue; } elseif($isSingle) { $value .= ' ' . (is_array($propValue) ? implode(' / ', $propValue) : $propValue); } elseif($isMultipleType) { if(is_array($propValue)) { foreach($propValue as $pKey => $pVal) { $value[$pKey] = $pVal; } unset($pKey, $pVal); } else { $value[] = $propValue; } } else { $value = (is_array($propValue) && $arProp['PROPERTY_TYPE'] != 'F' ? implode(' / ', $propValue) : $propValue); } } } /** Catalog fields */ if($typeId == 'PRODUCT') { if($this->isXmlProfile) { $tmpValue = $arItem['PRODUCT'][$typeValue]; } else { $tmpValue = $arItem['CATALOG_'.$typeValue]; } if(in_array($typeValue, array('CATALOG_AVAILABLE', 'CATALOG_VAT_INCLUDED', 'CATALOG_QUANTITY_TRACE', 'CATALOG_CAN_BUY_ZERO', 'AVAILABLE', 'VAT_INCLUDED', 'QUANTITY_TRACE', 'CAN_BUY_ZERO'))) { $tmpValue = ($tmpValue == 'Y' ? 'true' : 'false'); } if($isMultiple) $value[] = $tmpValue; elseif($isSingle) $value .= ' ' . $tmpValue; elseif($isMultipleType) $value[] = $tmpValue; else $value = $tmpValue; } if($typeId == 'STORE') { $tmpValue = $arItem['STORE'][$typeValue]; if(in_array($typeValue, array('STORE_ISSUING_CENTER', 'STORE_SHIPPING_CENTER'))) { $tmpValue = ($tmpValue == 'Y' ? 'true' : 'false'); } if($isMultiple) $value[] = $tmpValue; elseif($isSinngle) $value .= ' ' . $tmpValue; elseif($isMultipleType) $value[] = $tmpValue; else $value = $tmpValue; } /** Currency */ if($typeId == 'CURRENCY') { $tmpValue = ($typeValue ? $typeValue : $this->baseCurrency); if($isMultiple) $value[] = $tmpValue; elseif($isSingle) $value .= ' ' . $tmpValue; elseif($isMultipleType) $value[] = $tmpValue; else $value = $tmpValue; } /** Price */ if($typeId == 'PRICE') { $price = $arItem['MIN_PRICE']; if($typeValue == 'OLD_PRICE') { if($price['DISCOUNT_VALUE'] < $price['VALUE']) $typeValue = 'VALUE'; else $typeValue = ''; } $tmpValue = mb_strlen($typeValue) > 0 ? $price[$typeValue] : ''; if($isMultiple) $value[] = $tmpValue; elseif($isSingle) $value .= ' ' . $tmpValue; elseif($isMultipleType) $value[] = $tmpValue; else $value = $tmpValue; } /** Old price */ if($typeId == 'OLD_PRICE') { $price = $arItem['OLD_MIN_PRICE']; if($typeValue == 'OLD_PRICE') { if($price['DISCOUNT_VALUE'] < $price['VALUE']) $typeValue = 'VALUE'; else $typeValue = ''; } $tmpValue = mb_strlen($typeValue) > 0 ? $price[$typeValue] : ''; if($isMultiple) $value[] = $tmpValue; elseif($isSingle) $value .= ' ' . $tmpValue; elseif($isMultipleType) $value[] = $tmpValue; else $value = $tmpValue; } /** Meta-tag*/ if($typeId == 'IPROPERTY') { if($this->isXmlProfile) { $arField['USE_IPROPERTY_VALUE'][$typeKey] = trim($arField['USE_IPROPERTY_VALUE'][$typeKey]); if(mb_strlen($arField['USE_IPROPERTY_VALUE'][$typeKey]) > 0) { $typeValue = $arField['USE_IPROPERTY_VALUE'][$typeKey]; } } $tmpValue = $arItem['IPROPERTY_VALUES'] ? $arItem['IPROPERTY_VALUES'][$typeValue] : ''; if($isMultiple) $value[] = $tmpValue; elseif($isSingle) $value .= ' ' . $tmpValue; elseif($isMultipleType) $value[] = $tmpValue; else $value = $tmpValue; } } if($this->isXmlProfile) { if($this->feed['TYPE'] === 'ya_zen') { if($isCustom) { $propName = 'enclosure'; $propAttr = \Goodde\Export\ProfileTools::getDetailMedia($arItem['DETAIL_TEXT'], $arField, $arItem, $this->feed); } } elseif(in_array($this->feed['TYPE'], array('ym_simple', 'ym_vendor_model', 'avito_doma_dachi')) && in_array($key, ['picture', 'avitoImage'])) { /* @market.yandex */ /** You can specify up to 10 links to product images for each offer. */ if(is_array($value)) { $j = 1; foreach($value as $k => $val) { if($j > 10) unset($value[$k]); $j++; } } else { $expValues = explode(' ', trim($value)); $j = 1; foreach($expValues as $k => $val) { if($j > 10) unset($expValues[$k]); $j++; } $value = implode(' ', $expValues); } unset($j, $k, $val, $expValues); } } else { if($isCustom && mb_strlen($propUnit) == 0) { $propUnit = Loc::getMessage('GOODDE_TYRBO_API_FIELDS_NOT_UNIT_VALUE'); } } if($arField['USE_TEXT'] == 'Y') { $tmpValue = trim($arField['TEXT_VALUE']); if($isMultiple) $value[] = $tmpValue; elseif($isSingle) $value .= ' ' . $tmpValue; else $value = $tmpValue; } if($arField['USE_BOOLEAN'] == 'Y') { if(!is_array($value)) { if(mb_strlen($arField['BOOLEAN_VALUE']) > 0) { $expValues = explode('/', trim($arField['BOOLEAN_VALUE'])); } else { $expValues = array('true', 'false'); } $valueTrue = $expValues[0]; $valueFalse = $expValues[1]; $value = ($value == 'Y' || $value == 1 || $value > 0 || $value == 'true' || ToLower($value) == Loc::getMessage('GOODDE_TYRBO_API_TEMP_YES_VALUE') ? $valueTrue : $valueFalse); unset($expValues, $valueTrue, $valueFalse); } } if($arField['USE_CONDITIONS'] == 'Y' && $arField['CONDITIONS']) { $obCond = $this->obCond; if($obCond->Init(BT_COND_MODE_GENERATE, BT_COND_BUILD_CATALOG)) { $strEval = $obCond->Generate( $arField['CONDITIONS'], array('FIELD' => '$arItem') ); $value = ($strEval && $strEval != '((1 == 1))' && eval('return ' . $strEval . ';') == 1 ? 'true' : 'false'); } } if(is_array($value)) { $arResult[$i] = array( 'KEY' => $key, 'VALUE' => ($isMultipleType ? '' : array()), 'IS_CUSTOM' => $isCustom, 'IS_REQUIRED' => $isRequired, 'PARAM_NAME' => $this->fullTextFormatting($propName), 'PARAM_UNIT' => $propUnit, 'PARAM_ATTR' => $propAttr, ); foreach($value as $k => $val) { if($userFunc) $val = call_user_func_array($userFunc, array($val, $arField, $arItem, $this->feed)); if($textLength) $val = mb_substr($val, 0, $textLength); $value[$k] = $val; } foreach($value as $val) { if($isMultipleType) { if($val) { $arResult[$i]['VALUE'] = $val; break; } } else { $arResult[$i]['VALUE'][] = $val; } } } else { if($userFunc) $value = call_user_func_array($userFunc, array($value, $arField, $arItem, $this->feed)); if($textLength) $value = mb_substr($value, 0, $textLength); $arResult[$i] = array( 'KEY' => $key, 'VALUE' => $value, 'IS_CUSTOM' => $isCustom, 'IS_REQUIRED' => $isRequired, 'PARAM_NAME' => $this->fullTextFormatting($propName), 'PARAM_UNIT' => $propUnit, 'PARAM_ATTR' => $propAttr, ); } } unset($userFunc, $isCustom, $isRequired, $textLength, $arProp, $propName, $propUnit, $propAttr, $propValue, $key, $value, $i, $arField, $arItem, $previewPic, $detailPic); } return $arResult; } protected function getImagePath($picId = 0, $isContent = false) { $url = ''; $picId = (int)$picId; if($picId > 0) { $url = \CFile::GetPath($picId); if(!preg_match('!://!is', $url, $matches)) { $url = $this->feed['SERVER_ADDRESS'] . $url; } } if($isContent && $url <> '') { $url = '<figure><img src="'.$url.'"/></figure>'; } return $url; } protected function formatUri($url, $tags = array(), $id = null) { if($tags && $tags['NAME']) { $params = array(); foreach($tags['NAME'] as $pKey => $pName) { $pValue = $tags['VALUE'][ $pKey ]; $pValue = str_replace('#ID#', $id, $pValue); $params[] = $pName . '=' . $pValue; } $url .= (mb_strpos($url, '?') === false ? '?' : '&') . implode('&', $params); } return $this->validCharacters($url); } /** formatting */ public function fullTextFormatting($text) { $text = htmlspecialchars_decode($text); $text = $this->stripAllTags($text); $text = preg_replace('/\s\s+/', ' ', $text); $text = preg_replace('/(\r|\n|\r\n){3,}/', '', $text); return $this->validCharacters($text); } public function prepareTurboContent($turboContent) { $turboContent = htmlspecialchars_decode($turboContent); if($this->feed['IS_EXTENDED_HTMLTAGS'] != 'Y') { $turboContent = $this->stripAllTags($turboContent, $this->yandexTurboAllOwedTags(), false); } $turboContent = preg_replace('/<p[^>]*?>/', '<p>', $turboContent); $turboContent = preg_replace('/<ul[^>]*?>/', '<ul>', $turboContent); $turboContent = preg_replace('/<ol[^>]*?>/', '<ol>', $turboContent); $turboContent = preg_replace('/<li[^>]*?>/', '<li>', $turboContent); $turboContent = preg_replace('/style\s*=\s*".*?"/', '', $turboContent); $turboContent = preg_replace('/style\s*=\s*\'.*?\'/', '', $turboContent); $turboContent = preg_replace('/\s+>/', '>', $turboContent); if($this->feed['FIELDS']['IS_EXTENDED_HTML'] != 'Y') { $turboContent = preg_replace('/class\s*=\s*".*?"/', '', $turboContent); $turboContent = preg_replace('/class\s*=\s*\'.*?\'/', '', $turboContent); $turboContent = preg_replace('/\s+>/', '>', $turboContent); } $turboContent = $this->wrapTurboImages($turboContent); $turboContent = $this->wrapTurboVideo($turboContent); return $turboContent; } protected function validCharacters($text) { $text = htmlspecialchars_decode($text); $text = strtr($text, $this->getCharsTable()); $text = htmlspecialchars($text, ENT_HTML5 | ENT_QUOTES, SITE_CHARSET, false); return $text; } public static function gooddeText2xml($text = '') { $text = htmlspecialchars_decode($text); $text = strip_tags($text); $text = htmlspecialchars($text, ENT_HTML5 | ENT_QUOTES, SITE_CHARSET, false); $text = preg_replace("/[\x1-\x8\xB-\xC\xE-\x1F]/", "", $text); $text = preg_replace('/\s*\r+/' . BX_UTF_PCRE_MODIFIER, "", $text); return $text; } public function wrapTurboImages($turboContent) { preg_match_all('!(<img.*>)!Ui', $turboContent, $matches); if(isset($matches[1]) && !empty($matches)) { foreach($matches[1] as $k => $v) { if(!preg_match('!<figure>.*?'. preg_quote($v).'.*?</figure>!is', $turboContent)) { $turboContent = str_replace($v, "<figure>{$v}</figure>", $turboContent); } } } return $turboContent; } public function wrapTurboVideo($turboContent) { $turboContent = preg_replace('/<video[^>]*?>/', '<video>', $turboContent); preg_match_all('!<video>(.*)<\/video>!Ui', $turboContent, $matches); if(isset($matches[1]) && !empty($matches)) { foreach($matches[1] as $k => $v) { if(!preg_match('!<figure><video>.*?'.preg_quote($v).'.*?</video><img src="(.*?)" /><figcaption>(.*?)</figcaption></figure>!is', $turboContent)) { $turboContent = preg_replace('@(<figure><video>|<video>)'.$v.'(</video>|</video></figure>)@', '<figure><video>'.$v.'</video><img src="'.$this->feed['SERVER_ADDRESS'].'/yandex-turbo/img-by-video.png" /><figcaption>'.$this->figcaptionByVideo().'</figcaption></figure>', $turboContent); } } } return $turboContent; } protected function stripAllTags($string, $allowedTags = false, $removeBreaks = false) { $string = preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $string); if($allowedTags) $string = strip_tags($string, $allowedTags); else $string = strip_tags($string); if ($removeBreaks) $string = preg_replace('/[\r\n\t ]+/', ' ', $string); return trim($string); } protected function yandexTurboAllOwedTags() { return '<p><a><br><h1><h2><h3><h4><h5><h6><figure><img><figcaption><header><ul><ol><li><table><th><tr><td><video><source><b><strong><i><em><sup><sub><ins><del><small><big><pre><iframe><blockquote><hr><abr><u><abbr><span><div><code><header><footer><dl><dt><dd><main><aside><section><button><form>'; } protected function figcaptionByVideo() { return $this->feed['FIGCAPTION_VIDEO']; } protected function getCharsTable() { return array( ' ' => ' ', # no-break space = non-breaking space, U+00A0 ISOnum '¡' => '¡', # inverted exclamation mark, U+00A1 ISOnum '¢' => '¢', # cent sign, U+00A2 ISOnum '£' => '£', # pound sign, U+00A3 ISOnum '¤' => '¤', # currency sign, U+00A4 ISOnum '¥' => '¥', # yen sign = yuan sign, U+00A5 ISOnum '¦' => '¦', # broken bar = broken vertical bar, U+00A6 ISOnum '§' => '§', # section sign, U+00A7 ISOnum '¨' => '¨', # diaeresis = spacing diaeresis, U+00A8 ISOdia '©' => '©', # copyright sign, U+00A9 ISOnum 'ª' => 'ª', # feminine ordinal indicator, U+00AA ISOnum '«' => '«', # left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum '¬' => '¬', # not sign, U+00AC ISOnum '­' => '­', # soft hyphen = discretionary hyphen, U+00AD ISOnum '®' => '®', # registered sign = registered trade mark sign, U+00AE ISOnum '¯' => '¯', # macron = spacing macron = overline = APL overbar, U+00AF ISOdia '°' => '°', # degree sign, U+00B0 ISOnum '±' => '±', # plus-minus sign = plus-or-minus sign, U+00B1 ISOnum '²' => '²', # superscript two = superscript digit two = squared, U+00B2 ISOnum '³' => '³', # superscript three = superscript digit three = cubed, U+00B3 ISOnum '´' => '´', # acute accent = spacing acute, U+00B4 ISOdia 'µ' => 'µ', # micro sign, U+00B5 ISOnum '¶' => '¶', # pilcrow sign = paragraph sign, U+00B6 ISOnum '·' => '·', # middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum '¸' => '¸', # cedilla = spacing cedilla, U+00B8 ISOdia '¹' => '¹', # superscript one = superscript digit one, U+00B9 ISOnum 'º' => 'º', # masculine ordinal indicator, U+00BA ISOnum '»' => '»', # right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum '¼' => '¼', # vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum '½' => '½', # vulgar fraction one half = fraction one half, U+00BD ISOnum '¾' => '¾', # vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum '¿' => '¿', # inverted question mark = turned question mark, U+00BF ISOnum 'À' => 'À', # latin capital letter A with grave = latin capital letter A grave, U+00C0 ISOlat1 'Á' => 'Á', # latin capital letter A with acute, U+00C1 ISOlat1 'Â' => 'Â', # latin capital letter A with circumflex, U+00C2 ISOlat1 'Ã' => 'Ã', # latin capital letter A with tilde, U+00C3 ISOlat1 'Ä' => 'Ä', # latin capital letter A with diaeresis, U+00C4 ISOlat1 'Å' => 'Å', # latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1 'Æ' => 'Æ', # latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1 'Ç' => 'Ç', # latin capital letter C with cedilla, U+00C7 ISOlat1 'È' => 'È', # latin capital letter E with grave, U+00C8 ISOlat1 'É' => 'É', # latin capital letter E with acute, U+00C9 ISOlat1 'Ê' => 'Ê', # latin capital letter E with circumflex, U+00CA ISOlat1 'Ë' => 'Ë', # latin capital letter E with diaeresis, U+00CB ISOlat1 'Ì' => 'Ì', # latin capital letter I with grave, U+00CC ISOlat1 'Í' => 'Í', # latin capital letter I with acute, U+00CD ISOlat1 'Î' => 'Î', # latin capital letter I with circumflex, U+00CE ISOlat1 'Ï' => 'Ï', # latin capital letter I with diaeresis, U+00CF ISOlat1 'Ð' => 'Ð', # latin capital letter ETH, U+00D0 ISOlat1 'Ñ' => 'Ñ', # latin capital letter N with tilde, U+00D1 ISOlat1 'Ò' => 'Ò', # latin capital letter O with grave, U+00D2 ISOlat1 'Ó' => 'Ó', # latin capital letter O with acute, U+00D3 ISOlat1 'Ô' => 'Ô', # latin capital letter O with circumflex, U+00D4 ISOlat1 'Õ' => 'Õ', # latin capital letter O with tilde, U+00D5 ISOlat1 'Ö' => 'Ö', # latin capital letter O with diaeresis, U+00D6 ISOlat1 '×' => '×', # multiplication sign, U+00D7 ISOnum 'Ø' => 'Ø', # latin capital letter O with stroke = latin capital letter O slash, U+00D8 ISOlat1 'Ù' => 'Ù', # latin capital letter U with grave, U+00D9 ISOlat1 'Ú' => 'Ú', # latin capital letter U with acute, U+00DA ISOlat1 'Û' => 'Û', # latin capital letter U with circumflex, U+00DB ISOlat1 'Ü' => 'Ü', # latin capital letter U with diaeresis, U+00DC ISOlat1 'Ý' => 'Ý', # latin capital letter Y with acute, U+00DD ISOlat1 'Þ' => 'Þ', # latin capital letter THORN, U+00DE ISOlat1 'ß' => 'ß', # latin small letter sharp s = ess-zed, U+00DF ISOlat1 'à' => 'à', # latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1 'á' => 'á', # latin small letter a with acute, U+00E1 ISOlat1 'â' => 'â', # latin small letter a with circumflex, U+00E2 ISOlat1 'ã' => 'ã', # latin small letter a with tilde, U+00E3 ISOlat1 'ä' => 'ä', # latin small letter a with diaeresis, U+00E4 ISOlat1 'å' => 'å', # latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1 'æ' => 'æ', # latin small letter ae = latin small ligature ae, U+00E6 ISOlat1 'ç' => 'ç', # latin small letter c with cedilla, U+00E7 ISOlat1 'è' => 'è', # latin small letter e with grave, U+00E8 ISOlat1 'é' => 'é', # latin small letter e with acute, U+00E9 ISOlat1 'ê' => 'ê', # latin small letter e with circumflex, U+00EA ISOlat1 'ë' => 'ë', # latin small letter e with diaeresis, U+00EB ISOlat1 'ì' => 'ì', # latin small letter i with grave, U+00EC ISOlat1 'í' => 'í', # latin small letter i with acute, U+00ED ISOlat1 'î' => 'î', # latin small letter i with circumflex, U+00EE ISOlat1 'ï' => 'ï', # latin small letter i with diaeresis, U+00EF ISOlat1 'ð' => 'ð', # latin small letter eth, U+00F0 ISOlat1 'ñ' => 'ñ', # latin small letter n with tilde, U+00F1 ISOlat1 'ò' => 'ò', # latin small letter o with grave, U+00F2 ISOlat1 'ó' => 'ó', # latin small letter o with acute, U+00F3 ISOlat1 'ô' => 'ô', # latin small letter o with circumflex, U+00F4 ISOlat1 'õ' => 'õ', # latin small letter o with tilde, U+00F5 ISOlat1 'ö' => 'ö', # latin small letter o with diaeresis, U+00F6 ISOlat1 '÷' => '÷', # division sign, U+00F7 ISOnum 'ø' => 'ø', # latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1 'ù' => 'ù', # latin small letter u with grave, U+00F9 ISOlat1 'ú' => 'ú', # latin small letter u with acute, U+00FA ISOlat1 'û' => 'û', # latin small letter u with circumflex, U+00FB ISOlat1 'ü' => 'ü', # latin small letter u with diaeresis, U+00FC ISOlat1 'ý' => 'ý', # latin small letter y with acute, U+00FD ISOlat1 'þ' => 'þ', # latin small letter thorn, U+00FE ISOlat1 'ÿ' => 'ÿ', # latin small letter y with diaeresis, U+00FF ISOlat1 'ƒ' => 'ƒ', # latin small f with hook = function = florin, U+0192 ISOtech 'Α' => 'Α', # greek capital letter alpha, U+0391 'Β' => 'Β', # greek capital letter beta, U+0392 'Γ' => 'Γ', # greek capital letter gamma, U+0393 ISOgrk3 'Δ' => 'Δ', # greek capital letter delta, U+0394 ISOgrk3 'Ε' => 'Ε', # greek capital letter epsilon, U+0395 'Ζ' => 'Ζ', # greek capital letter zeta, U+0396 'Η' => 'Η', # greek capital letter eta, U+0397 'Θ' => 'Θ', # greek capital letter theta, U+0398 ISOgrk3 'Ι' => 'Ι', # greek capital letter iota, U+0399 'Κ' => 'Κ', # greek capital letter kappa, U+039A 'Λ' => 'Λ', # greek capital letter lambda, U+039B ISOgrk3 'Μ' => 'Μ', # greek capital letter mu, U+039C 'Ν' => 'Ν', # greek capital letter nu, U+039D 'Ξ' => 'Ξ', # greek capital letter xi, U+039E ISOgrk3 'Ο' => 'Ο', # greek capital letter omicron, U+039F 'Π' => 'Π', # greek capital letter pi, U+03A0 ISOgrk3 'Ρ' => 'Ρ', # greek capital letter rho, U+03A1 'Σ' => 'Σ', # greek capital letter sigma, U+03A3 ISOgrk3 'Τ' => 'Τ', # greek capital letter tau, U+03A4 'Υ' => 'Υ', # greek capital letter upsilon, U+03A5 ISOgrk3 'Φ' => 'Φ', # greek capital letter phi, U+03A6 ISOgrk3 'Χ' => 'Χ', # greek capital letter chi, U+03A7 'Ψ' => 'Ψ', # greek capital letter psi, U+03A8 ISOgrk3 'Ω' => 'Ω', # greek capital letter omega, U+03A9 ISOgrk3 'α' => 'α', # greek small letter alpha, U+03B1 ISOgrk3 'β' => 'β', # greek small letter beta, U+03B2 ISOgrk3 'γ' => 'γ', # greek small letter gamma, U+03B3 ISOgrk3 'δ' => 'δ', # greek small letter delta, U+03B4 ISOgrk3 'ε' => 'ε', # greek small letter epsilon, U+03B5 ISOgrk3 'ζ' => 'ζ', # greek small letter zeta, U+03B6 ISOgrk3 'η' => 'η', # greek small letter eta, U+03B7 ISOgrk3 'θ' => 'θ', # greek small letter theta, U+03B8 ISOgrk3 'ι' => 'ι', # greek small letter iota, U+03B9 ISOgrk3 'κ' => 'κ', # greek small letter kappa, U+03BA ISOgrk3 'λ' => 'λ', # greek small letter lambda, U+03BB ISOgrk3 'μ' => 'μ', # greek small letter mu, U+03BC ISOgrk3 'ν' => 'ν', # greek small letter nu, U+03BD ISOgrk3 'ξ' => 'ξ', # greek small letter xi, U+03BE ISOgrk3 'ο' => 'ο', # greek small letter omicron, U+03BF NEW 'π' => 'π', # greek small letter pi, U+03C0 ISOgrk3 'ρ' => 'ρ', # greek small letter rho, U+03C1 ISOgrk3 'ς' => 'ς', # greek small letter final sigma, U+03C2 ISOgrk3 'σ' => 'σ', # greek small letter sigma, U+03C3 ISOgrk3 'τ' => 'τ', # greek small letter tau, U+03C4 ISOgrk3 'υ' => 'υ', # greek small letter upsilon, U+03C5 ISOgrk3 'φ' => 'φ', # greek small letter phi, U+03C6 ISOgrk3 'χ' => 'χ', # greek small letter chi, U+03C7 ISOgrk3 'ψ' => 'ψ', # greek small letter psi, U+03C8 ISOgrk3 'ω' => 'ω', # greek small letter omega, U+03C9 ISOgrk3 'ϑ' => 'ϑ', # greek small letter theta symbol, U+03D1 NEW 'ϒ' => 'ϒ', # greek upsilon with hook symbol, U+03D2 NEW 'ϖ' => 'ϖ', # greek pi symbol, U+03D6 ISOgrk3 '•' => '•', # bullet = black small circle, U+2022 ISOpub '…' => '…', # horizontal ellipsis = three dot leader, U+2026 ISOpub '′' => '′', # prime = minutes = feet, U+2032 ISOtech '″' => '″', # double prime = seconds = inches, U+2033 ISOtech '‾' => '‾', # overline = spacing overscore, U+203E NEW '⁄' => '⁄', # fraction slash, U+2044 NEW '℘' => '℘', # script capital P = power set = Weierstrass p, U+2118 ISOamso 'ℑ' => 'ℑ', # blackletter capital I = imaginary part, U+2111 ISOamso 'ℜ' => 'ℜ', # blackletter capital R = real part symbol, U+211C ISOamso '™' => '™', # trade mark sign, U+2122 ISOnum 'ℵ' => 'ℵ', # alef symbol = first transfinite cardinal, U+2135 NEW '←' => '←', # leftwards arrow, U+2190 ISOnum '↑' => '↑', # upwards arrow, U+2191 ISOnum '→' => '→', # rightwards arrow, U+2192 ISOnum '↓' => '↓', # downwards arrow, U+2193 ISOnum '↔' => '↔', # left right arrow, U+2194 ISOamsa '↵' => '↵', # downwards arrow with corner leftwards = carriage return, U+21B5 NEW '⇐' => '⇐', # leftwards double arrow, U+21D0 ISOtech '⇑' => '⇑', # upwards double arrow, U+21D1 ISOamsa '⇒' => '⇒', # rightwards double arrow, U+21D2 ISOtech '⇓' => '⇓', # downwards double arrow, U+21D3 ISOamsa '⇔' => '⇔', # left right double arrow, U+21D4 ISOamsa '∀' => '∀', # for all, U+2200 ISOtech '∂' => '∂', # partial differential, U+2202 ISOtech '∃' => '∃', # there exists, U+2203 ISOtech '∅' => '∅', # empty set = null set = diameter, U+2205 ISOamso '∇' => '∇', # nabla = backward difference, U+2207 ISOtech '∈' => '∈', # element of, U+2208 ISOtech '∉' => '∉', # not an element of, U+2209 ISOtech '∋' => '∋', # contains as member, U+220B ISOtech '∏' => '∏', # n-ary product = product sign, U+220F ISOamsb '∑' => '∑', # n-ary sumation, U+2211 ISOamsb '−' => '−', # minus sign, U+2212 ISOtech '∗' => '∗', # asterisk operator, U+2217 ISOtech '√' => '√', # square root = radical sign, U+221A ISOtech '∝' => '∝', # proportional to, U+221D ISOtech '∞' => '∞', # infinity, U+221E ISOtech '∠' => '∠', # angle, U+2220 ISOamso '∧' => '∧', # logical and = wedge, U+2227 ISOtech '∨' => '∨', # logical or = vee, U+2228 ISOtech '∩' => '∩', # intersection = cap, U+2229 ISOtech '∪' => '∪', # union = cup, U+222A ISOtech '∫' => '∫', # integral, U+222B ISOtech '∴' => '∴', # therefore, U+2234 ISOtech '∼' => '∼', # tilde operator = varies with = similar to, U+223C ISOtech '≅' => '≅', # approximately equal to, U+2245 ISOtech '≈' => '≈', # almost equal to = asymptotic to, U+2248 ISOamsr '≠' => '≠', # not equal to, U+2260 ISOtech '≡' => '≡', # identical to, U+2261 ISOtech '≤' => '≤', # less-than or equal to, U+2264 ISOtech '≥' => '≥', # greater-than or equal to, U+2265 ISOtech '⊂' => '⊂', # subset of, U+2282 ISOtech '⊃' => '⊃', # superset of, U+2283 ISOtech '⊄' => '⊄', # not a subset of, U+2284 ISOamsn '⊆' => '⊆', # subset of or equal to, U+2286 ISOtech '⊇' => '⊇', # superset of or equal to, U+2287 ISOtech '⊕' => '⊕', # circled plus = direct sum, U+2295 ISOamsb '⊗' => '⊗', # circled times = vector product, U+2297 ISOamsb '⊥' => '⊥', # up tack = orthogonal to = perpendicular, U+22A5 ISOtech '⋅' => '⋅', # dot operator, U+22C5 ISOamsb '⌈' => '⌈', # left ceiling = apl upstile, U+2308 ISOamsc '⌉' => '⌉', # right ceiling, U+2309 ISOamsc '⌊' => '⌊', # left floor = apl downstile, U+230A ISOamsc '⌋' => '⌋', # right floor, U+230B ISOamsc '⟨' => '〈', # left-pointing angle bracket = bra, U+2329 ISOtech '⟩' => '〉', # right-pointing angle bracket = ket, U+232A ISOtech '◊' => '◊', # lozenge, U+25CA ISOpub '♠' => '♠', # black spade suit, U+2660 ISOpub '♣' => '♣', # black club suit = shamrock, U+2663 ISOpub '♥' => '♥', # black heart suit = valentine, U+2665 ISOpub '♦' => '♦', # black diamond suit, U+2666 ISOpub //'"' => '"', # quotation mark = APL quote, U+0022 ISOnum //'&' => '&', # ampersand, U+0026 ISOnum //'<' => '<', # less-than sign, U+003C ISOnum //'>' => '>', # greater-than sign, U+003E ISOnum 'Œ' => 'Œ', # latin capital ligature OE, U+0152 ISOlat2 'œ' => 'œ', # latin small ligature oe, U+0153 ISOlat2 'Š' => 'Š', # latin capital letter S with caron, U+0160 ISOlat2 'š' => 'š', # latin small letter s with caron, U+0161 ISOlat2 'Ÿ' => 'Ÿ', # latin capital letter Y with diaeresis, U+0178 ISOlat2 'ˆ' => 'ˆ', # modifier letter circumflex accent, U+02C6 ISOpub '˜' => '˜', # small tilde, U+02DC ISOdia ' ' => ' ', # en space, U+2002 ISOpub ' ' => ' ', # em space, U+2003 ISOpub ' ' => ' ', # thin space, U+2009 ISOpub '‌' => '‌', # zero width non-joiner, U+200C NEW RFC 2070 '‍' => '‍', # zero width joiner, U+200D NEW RFC 2070 '‎' => '‎', # left-to-right mark, U+200E NEW RFC 2070 '‏' => '‏', # right-to-left mark, U+200F NEW RFC 2070 '–' => '–', # en dash, U+2013 ISOpub '—' => '—', # em dash, U+2014 ISOpub '‘' => '‘', # left single quotation mark, U+2018 ISOnum '’' => '’', # right single quotation mark, U+2019 ISOnum '‚' => '‚', # single low-9 quotation mark, U+201A NEW '“' => '“', # left double quotation mark, U+201C ISOnum '”' => '”', # right double quotation mark, U+201D ISOnum '„' => '„', # double low-9 quotation mark, U+201E NEW '†' => '†', # dagger, U+2020 ISOpub '‡' => '‡', # double dagger, U+2021 ISOpub '‰' => '‰', # per mille sign, U+2030 ISOtech '‹' => '‹', # single left-pointing angle quotation mark, U+2039 ISO proposed '›' => '›', # single right-pointing angle quotation mark, U+203A ISO proposed '€' => '€', # euro sign, U+20AC NEW //''' => ''', # apostrophe = APL quote, U+0027 ISOnum ); } //previous and next related protected function getRelatedItems($count, $key = null, $arRelated = array(), $cntRelated = 2) { if($count > 0 && isset($key)) { $keyL = $count - 1; $keyR = 1; $arResult = array(); for($i = 1; $i <= $cntRelated; $i++) { if($key == 0) { if(($i % 2) == 0) { $curKey = $count - $keyL; $keyL--; } else { $curKey = $count - $keyR; $keyR++; } } else { if($arRelated[$i] >= $count - 1) { $curKey = 0; } else { $curKey = $arRelated[$i] + 1; } } $arResult[$i] = $curKey; } return $arResult; } } public function rssBody($fp = '', $path = '', $arFields = array(), $arParams = array(), &$bytesWritten = 0, &$numberRss = 0, &$numberItem = 0) { if(mb_strlen($path) > 0) { $fp = fopen($path, 'ab'); } $arParams['ID'] = $arParams['ID'] ? intval($arParams['ID']) : 0; $arParams['ITEM_STATUS'] = $arParams['ITEM_STATUS'] ? $arParams['ITEM_STATUS'] : ''; $arParams['TEMPLATE'] = $arParams['TEMPLATE'] ? $arParams['TEMPLATE'] : '.default'; $pathToAction = $this->getDirTemplates($arParams['TEMPLATE']); if(file_exists($pathToAction)) { $this->includeResultModifier($arFields, $pathToAction); } foreach($arFields['ITEMS'] as $arField) { if(mb_strlen($arParams['ITEM_STATUS']) <= 0) { if($arField['ACTIVE'] == 'Y') { $arField['ITEM'] = 'true'; } elseif($arField['ACTIVE'] == 'N') { $arField['ITEM'] = 'false'; } } else { $arField['ITEM'] = $arParams['ITEM_STATUS']; } $str = "\n"; if(file_exists($pathToAction)) { ob_start(); $this->includeTemplates($arField, $pathToAction); $str .= ob_get_contents(); ob_end_clean(); } $rv = fwrite($fp, $str); $numberItem ++; $bytesWritten += $rv; if($numberItem == $this->amountItem ) { $this->rssFooter($fp); $bytesWritten = 0; $numberItem = 1; $numberRss ++; $fp = $this->rssHeader($this->getPath().'/'.$arParams['ID'].'/turbo_'.$numberRss.'.xml', $bytesWritten, $arFields['CHANNEL']); } } return $fp; } public function rssHeader($fileName = '', &$bytesWritten = 0, $arFields = array()) { global $runError; $str = '<?xml version="1.0" encoding="'.SITE_CHARSET.'"?>'; $str .= '<rss xmlns:yandex="http://news.yandex.ru" xmlns:media="http://search.yahoo.com/mrss/" xmlns:turbo="http://turbo.yandex.ru" version="2.0">'; $str .= '<channel>'; $str .= '<title>'.$arFields['TITLE'].'</title>'; $str .= '<link>'.$arFields['LINK'].'/</link>'; $str .= '<turbo:cms_plugin>62668D13197952BEA072E87B176AA7BE</turbo:cms_plugin>'; $str .= '<description>'.$arFields['DESCRIPTION'].'</description>'; if(!$fp = @fopen($fileName, "wb")) { if(intval($arFields['ID']) > 0) { $directory = \Bitrix\Main\IO\Directory::createDirectory(\Goodde\YandexTurbo\Turbo::getPath().'/'.$arFields['ID'].'/'); if($directory->isExists()) { $fp = @fopen($fileName, "wb"); } else { $runError = str_replace('#FILE#', $fileName, Loc::getMessage('GOODDE_TYRBO_API_FILE_OPEN_WRITING')); } } } if($fp) { $rv = fwrite($fp, $str); $bytesWritten += $rv; } return $fp; } public function rssFooter($fp) { $str = '</channel>'; $str .= '</rss>'; fwrite($fp, $str); fclose($fp); } public function getPath() { return Turbo::getPath(); } protected function getDirTemplates($templates = '.default') { $type = $this->feed['IS_SECTION'] == 'Y' ? 'section' : 'element'; $arTemplateList = \Goodde\YandexTurbo\Turbo::getTemplateList($type); if(file_exists($pathToAction = $_SERVER['DOCUMENT_ROOT'].'/bitrix/php_interface/include/yandex_turbo/templates/'.$type.'/'.$templates)) { $pathToAction = str_replace('\\', '/', $pathToAction); while(mb_substr($pathToAction, mb_strlen($pathToAction) - 1, 1) == '/') $pathToAction = mb_substr($pathToAction, 0, mb_strlen($pathToAction) - 1); } elseif($arTemplateList[$templates]) { $pathToAction = $_SERVER['DOCUMENT_ROOT'].'/bitrix/modules/goodde.yandexturboapi/load/templates/'.$type.'/'.$templates; } return $pathToAction; } protected function includeResultModifier(&$arFields, $pathToAction = '') { if(file_exists($pathToAction)) { if(is_dir($pathToAction) && file_exists($pathToAction.'/result_modifier.php')) include($pathToAction .= '/result_modifier.php'); } } protected function includeTemplates($arField, $pathToAction = '') { if(file_exists($pathToAction)) { if(is_dir($pathToAction) && file_exists($pathToAction.'/template.php')) include($pathToAction .= '/template.php'); } } public function uploadFeed($path = '', $arFields = array()) { global $arErrors; $arErrors = array(); $directory = new \Bitrix\Main\IO\Directory($path, null); if($directory->isExists()) { $i = 0; $j = 0; $n = 0; $arChildren = $directory->getChildren(); $count = count($arChildren); $newName = ''; foreach($arChildren as $k => $file) { if($file->isExists()) { if(in_array($file->getName(), array('debug_turbo.xml', 'debug_turbo.gz'))) { $file->delete(); continue; } $data = $file->getContents(); /*bind events*/ foreach(GetModuleEvents("goodde.yandexturboapi", "OnBeforeContentAdd", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($arFields, &$data)); } if($this->isGzip) { $data = gzencode($data, $this->gzipLevel); } $result = \Goodde\YandexTurbo\Model\Request::addFeed($arFields['LID'], 'production', $data, $this->isGzip, $this->feed['FIELDS']['HOST_ID_SUBDOMAIN']); if(is_array($result) && isset($result['task_id'])) { $resultTask = \Goodde\YandexTurbo\TaskTable::add(array('FEED_ID' => $arFields['ID'], 'LID' => $arFields['LID'], 'TASK_ID' => $result['task_id'], 'MODE' => 'PRODUCTION')); if($resultTask->isSuccess()) { $taskId = $resultTask->getId(); $newName = str_replace('.xml', '_'.$taskId.'.xml', $file->getName()); if(rename(Path::convertLogicalToPhysical($file->getPath()), $this->getPath().'/reports/'.$newName)) { if($this->isGzip) { $fileName = $this->addArchive($this->getPath().'/reports/'.$newName, $data); if(mb_strlen($fileName) > 0) { $newName = $fileName; } unset($fileName); } \Goodde\YandexTurbo\TaskTable::update($taskId, array('NAME' => $newName)); } unset($newName); } $j++; } else { $newName = str_replace('.xml', '_'.$arFields['ID'].'_'.strftime('%Y-%m-%d_%H-%M-%S').'.xml', $file->getName()); if(rename(Path::convertLogicalToPhysical($file->getPath()), $this->getPath().'/reports/'.$newName)) { if($this->isGzip) { $this->addArchive($this->getPath().'/reports/'.$newName, $data); } } unset($newName); $arErrors[$file->getName()] = array( 'ERROR_CODE' => $result['error_code'], 'ERROR_MESSAGE' => $result['error_message'], ); $n++; } if($i++ == 9) { break; } } } \Goodde\YandexTurbo\FeedTable::update($arFields['ID'], array('IS_NOT_UPLOAD_FEED' => ($count - $j > 0 ? 'Y' : 'N'))); } return array( 'TOTAL_FILE' => $count, 'PROCESSED' => $i, 'ADD' => $j, 'ERROR' => $n, ); } public function addArchive($path = '', $data = '') { $fileName = ''; $file = new \Bitrix\Main\IO\File($path, null); if($file->isExists()) { $directoryName = $file->getDirectoryName(); $fileName = str_replace('.xml', '', $file->getName()); $fileNameZip = $directoryName.'/'.$fileName.'.gz'; if(mb_strlen($data) > 0) { $put = file_put_contents($fileNameZip, $data); } else { $data = file_get_contents($file->getPath()); /*bind events*/ foreach(GetModuleEvents("goodde.yandexturboapi", "OnBeforeContentAdd", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($arFields, &$data)); } $put = file_put_contents($fileNameZip, gzencode($data, $this->gzipLevel)); } if(intval($put) > 0) { $file->delete(); $file = new \Bitrix\Main\IO\File($fileNameZip, null); $fileName = $file->getName(); } } return $fileName; } public function addFalseByCsv($fileName = '', $lid = '', $arFields = array()) { global $runError; $str = '<?xml version="1.0" encoding="'.SITE_CHARSET.'"?>'; $str .= '<rss xmlns:yandex="http://news.yandex.ru" xmlns:media="http://search.yahoo.com/mrss/" xmlns:turbo="http://turbo.yandex.ru" version="2.0">'; $str .= "<channel>\n"; $path = \Goodde\YandexTurbo\Turbo::getPath().'/'.$fileName; if(!$fp = @fopen($path, "wb")) { $directory = \Bitrix\Main\IO\Directory::createDirectory(\Goodde\YandexTurbo\Turbo::getPath().'/'); if($directory->isExists()) { $fp = @fopen($path, "wb"); } else { $runError = str_replace('#FILE#', $path, Loc::getMessage('GOODDE_TYRBO_API_FILE_OPEN_WRITING')); } } if($fp) { $numberItem = 0; if($arFields) { foreach($arFields as $arField) { if($arField['URL']) { $str .= '<item turbo="false"><link>'.$arField['URL'].'</link><turbo:content><![CDATA[<header><h1>false</h1></header><p> </p>]]></turbo:content>'."</item>\n"; } $numberItem ++; if($numberItem == $this->amountItem) { break; } } fwrite($fp, $str); } $this->rssFooter($fp); $file = new \Bitrix\Main\IO\File($path); if($file->isExists()) { $data = $file->getContents(); if($this->isGzip) { $data = gzencode($data, $this->gzipLevel); } $result = \Goodde\YandexTurbo\Model\Request::addFeed($lid, 'production', $data, $this->isGzip); if(is_array($result) && isset($result['task_id'])) { $resultTask = \Goodde\YandexTurbo\TaskTable::add(array('FEED_ID' => 0, 'LID' => $lid, 'TASK_ID' => $result['task_id'], 'MODE' => 'PRODUCTION')); if($resultTask->isSuccess()) { $taskId = $resultTask->getId(); $newName = str_replace('.xml', '_'.$taskId.'.xml', $file->getName()); if(rename(Path::convertLogicalToPhysical($file->getPath()), $this->getPath().'/reports/'.$newName)) { if($this->isGzip) { $fileName = $this->addArchive($this->getPath().'/reports/'.$newName, $data); if(mb_strlen($fileName) > 0) { $newName = $fileName; } unset($fileName); } \Goodde\YandexTurbo\TaskTable::update($taskId, array('NAME' => $newName)); unset($newName); } } } else { $runError = $result['error_code']. ' - '.$result['error_message']; } } else { $runError = str_replace('#FILE#', $path, Loc::getMessage('GOODDE_TYRBO_API_FILE_OPEN_WRITING')); } return true; } return false; } } ?>