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/esol.importexportexcel/classes/import/ |
Upload File : |
<?php use Bitrix\Main\Loader; use Bitrix\Main\Localization\Loc; Loc::loadMessages(__FILE__); class CKDAImportExcel extends CKDAImportExcelBase { function __construct($filename, $params, $fparams, $stepparams, $pid = false) { parent::__construct($filename, $params); $this->params = $params; $this->fparams = $fparams; $this->maxReadRows = 500; $this->skipRows = 0; $this->sections = array(); $this->propVals = array(); $this->hlbl = array(); $this->breakWorksheet = false; $this->fl = new CKDAFieldList(); $this->stepparams = $stepparams; $this->stepparams['total_read_line'] = intval($this->stepparams['total_read_line']); $this->stepparams['total_line'] = intval($this->stepparams['total_line']); $this->stepparams['correct_line'] = intval($this->stepparams['correct_line']); $this->stepparams['error_line'] = intval($this->stepparams['error_line']); $this->stepparams['killed_line'] = intval($this->stepparams['killed_line']); $this->stepparams['offer_killed_line'] = intval($this->stepparams['offer_killed_line']); $this->stepparams['element_added_line'] = intval($this->stepparams['element_added_line']); $this->stepparams['element_updated_line'] = intval($this->stepparams['element_updated_line']); $this->stepparams['element_changed_line'] = intval($this->stepparams['element_changed_line']); $this->stepparams['element_removed_line'] = intval($this->stepparams['element_removed_line']); $this->stepparams['sku_added_line'] = intval($this->stepparams['sku_added_line']); $this->stepparams['sku_updated_line'] = intval($this->stepparams['sku_updated_line']); $this->stepparams['sku_changed_line'] = intval($this->stepparams['sku_changed_line']); $this->stepparams['section_added_line'] = intval($this->stepparams['section_added_line']); $this->stepparams['section_updated_line'] = intval($this->stepparams['section_updated_line']); $this->stepparams['section_deactivate_line'] = intval($this->stepparams['section_deactivate_line']); $this->stepparams['section_remove_line'] = intval($this->stepparams['section_remove_line']); $this->stepparams['zero_stock_line'] = intval($this->stepparams['zero_stock_line']); $this->stepparams['offer_zero_stock_line'] = intval($this->stepparams['offer_zero_stock_line']); $this->stepparams['old_removed_line'] = intval($this->stepparams['old_removed_line']); $this->stepparams['offer_old_removed_line'] = intval($this->stepparams['offer_old_removed_line']); $this->stepparams['worksheetCurrentRow'] = intval($this->stepparams['worksheetCurrentRow']); if(!isset($this->stepparams['total_line_by_list'])) $this->stepparams['total_line_by_list'] = array(); if(!isset($this->stepparams['total_file_lists_line'])) $this->stepparams['total_file_lists_line'] = array(); if(!isset($this->stepparams['total_file_line'])) { $this->stepparams['total_file_line'] = 0; if(is_array($this->params['LIST_LINES'])) { foreach($this->params['LIST_ACTIVE'] as $k=>$v) { if($v=='Y') { $this->stepparams['total_file_line'] += $this->params['LIST_LINES'][$k]; } } } } if(!$this->params['SECTION_UID']) $this->params['SECTION_UID'] = 'NAME'; $this->params['ELEMENT_MULTIPLE_SEPARATOR'] = $this->GetSeparator($this->params['ELEMENT_MULTIPLE_SEPARATOR']); if(!isset($this->params['ELEMENT_NOT_LOAD_FORMATTING'])) $this->params['ELEMENT_NOT_LOAD_FORMATTING'] = 'N'; if(!isset($this->params['ELEMENT_LOAD_IMAGES'])) $this->params['ELEMENT_LOAD_IMAGES'] = 'N'; if($this->params['ELEMENT_IMAGES_FORCE_UPDATE']!='Y' && $this->params['CHECK_CHANGES']=='N') { $this->params['ELEMENT_IMAGES_FORCE_UPDATE'] = 'Y'; } $this->logger = new CKDAImportLogger($params, $pid); if(!isset($stepparams['NOT_CHANGE_PROFILE']) || $stepparams['NOT_CHANGE_PROFILE']!='Y') { if(!isset($this->stepparams['loggerExecId'])) $this->stepparams['loggerExecId'] = 0; $this->logger->SetExecId($this->stepparams['loggerExecId']); } $this->conv = new \Bitrix\KdaImportexcel\Conversion($this); $this->cloud = new \Bitrix\KdaImportexcel\Cloud(); $this->sftp = new \Bitrix\KdaImportexcel\Sftp(); $this->el = new \Bitrix\KdaImportexcel\DataManager\IblockElementTable($params); $this->needCheckReqProps = (bool)(\Bitrix\Main\Config\Option::get(static::$moduleId, 'CHECK_REQUIRED_PROPS', 'N')=='Y'); $this->imgExts = array_map('trim', explode(',', ToLower(\CFile::GetImageExtensions()))); if(empty($this->rcurrencies)) { $this->rcurrencies = array('#USD#', '#EUR#'); if(Loader::includeModule('currency') && is_callable(array('\Bitrix\Currency\CurrencyTable', 'getList'))) { $dbRes = \Bitrix\Currency\CurrencyTable::getList(array('select'=>array('CURRENCY'))); while($arr = $dbRes->Fetch()) { if(!in_array('#'.$arr['CURRENCY'].'#', $this->rcurrencies)) $this->rcurrencies[] = '#'.$arr['CURRENCY'].'#'; } } } $this->SetZipClass(); $this->saveProductWithOffers = (bool)(Loader::includeModule('catalog') && (string)(\Bitrix\Main\Config\Option::get('catalog', 'show_catalog_tab_with_offers')) == 'Y'); AddEventHandler('iblock', 'OnBeforeIBlockElementUpdate', array($this, 'OnBeforeIBlockElementUpdateHandler'), 999999); AddEventHandler('main', 'OnFileSave', array($this, 'OnFileSaveHandler'), 1); $cm = new \Bitrix\KdaImportexcel\ClassManager($this); $this->pricer = $cm->GetPricer(); $this->productor = $cm->GetProductor(); /*Temp folders*/ $this->filecnt = 0; $dir = $_SERVER["DOCUMENT_ROOT"].'/upload/tmp/'.static::$moduleId.'/'.static::$moduleSubDir; CheckDirPath($dir); if(!$this->stepparams['tmpdir']) { $i = 0; while(($tmpdir = $dir.$i.'/') && file_exists($tmpdir)){$i++;} $this->stepparams['tmpdir'] = $tmpdir; CheckDirPath($tmpdir); } $this->tmpdir = $this->stepparams['tmpdir']; $this->imagedir = $this->stepparams['tmpdir'].'images/'; CheckDirPath($this->imagedir); $this->archivedir = $this->stepparams['tmpdir'].'archives/'; CheckDirPath($this->archivedir); $this->tmpfile = $this->tmpdir.'params.txt'; $oProfile = CKDAImportProfile::getInstance(); $oProfile->SetImportParams($pid, $this->tmpdir, $stepparams, $this->params); /*/Temp folders*/ if(file_exists($this->tmpfile) && filesize($this->tmpfile) > 0) { $this->stepparams = array_merge($this->stepparams, unserialize(file_get_contents($this->tmpfile))); } if(isset($this->stepparams['skipSepProp'])) $this->skipSepProp = $this->stepparams['skipSepProp']; if(isset($this->stepparams['skipSepSection'])) $this->skipSepSection = $this->stepparams['skipSepSection']; if(isset($this->stepparams['skipSepSectionLevels'])) $this->skipSepSectionLevels = $this->stepparams['skipSepSectionLevels']; if(isset($this->stepparams['arSectionNames'])) $this->arSectionNames = $this->stepparams['arSectionNames']; if(!isset($this->stepparams['curstep'])) $this->stepparams['curstep'] = 'import'; if(!isset($this->params['MAX_EXECUTION_TIME']) || $this->params['MAX_EXECUTION_TIME']!==0) { if(\Bitrix\Main\Config\Option::get(static::$moduleId, 'SET_MAX_EXECUTION_TIME')=='Y' && is_numeric(\Bitrix\Main\Config\Option::get(static::$moduleId, 'MAX_EXECUTION_TIME'))) { $this->params['MAX_EXECUTION_TIME'] = intval(\Bitrix\Main\Config\Option::get(static::$moduleId, 'MAX_EXECUTION_TIME')); if(ini_get('max_execution_time') && $this->params['MAX_EXECUTION_TIME'] > ini_get('max_execution_time') - 5) $this->params['MAX_EXECUTION_TIME'] = ini_get('max_execution_time') - 5; if($this->params['MAX_EXECUTION_TIME'] < 5) $this->params['MAX_EXECUTION_TIME'] = 5; if($this->params['MAX_EXECUTION_TIME'] > 300) $this->params['MAX_EXECUTION_TIME'] = 300; } else { $this->params['MAX_EXECUTION_TIME'] = intval(ini_get('max_execution_time')) - 10; if($this->params['MAX_EXECUTION_TIME'] < 10) $this->params['MAX_EXECUTION_TIME'] = 15; if($this->params['MAX_EXECUTION_TIME'] > 50) $this->params['MAX_EXECUTION_TIME'] = 50; } } if($this->params['ONLY_UPDATE_MODE']=='Y') { $this->params['ONLY_UPDATE_MODE_ELEMENT'] = $this->params['ONLY_UPDATE_MODE_SECTION'] = 'Y'; } if($this->params['ONLY_UPDATE_MODE_SEP']!='Y') { $this->params['ONLY_UPDATE_MODE_PRODUCT'] = $this->params['ONLY_UPDATE_MODE_OFFER'] = $this->params['ONLY_UPDATE_MODE_ELEMENT']; } if($this->params['ONLY_CREATE_MODE']=='Y') { $this->params['ONLY_CREATE_MODE_ELEMENT'] = $this->params['ONLY_CREATE_MODE_SECTION'] = 'Y'; } if($this->params['ONLY_CREATE_MODE_SEP']!='Y') { $this->params['ONLY_CREATE_MODE_PRODUCT'] = $this->params['ONLY_CREATE_MODE_OFFER'] = $this->params['ONLY_CREATE_MODE_ELEMENT']; } if($pid!==false) { $this->procfile = $dir.$pid.'.txt'; $this->errorfile = $dir.$pid.'_error.txt'; if((int)$this->stepparams['import_started'] < 1) { $oProfile = CKDAImportProfile::getInstance(); if(!isset($stepparams['NOT_CHANGE_PROFILE']) || $stepparams['NOT_CHANGE_PROFILE']!='Y') { if(!class_exists('\Bitrix\Main\SystemException')) { if($oProfile->OnStartImport()===false) $this->breakByEvent = true; } else { try { if($oProfile->OnStartImport()===false) $this->breakByEvent = true; } catch(\Bitrix\Main\SystemException $exception) { $this->errors[] = $exception->getMessage(); $this->breakByEvent = true; } } if($this->breakByEvent) $this->stepparams['import_started'] = 1; } if(file_exists($this->procfile)) unlink($this->procfile); if(file_exists($this->errorfile)) unlink($this->errorfile); } $this->pid = $pid; } } public function SetZipClass() { if(/*$this->params['OPTIMIZE_RAM']!='Y' &&*/ !isset($this->stepparams['optimizeRam'])) { $this->stepparams['optimizeRam'] = 'N'; $origFileSize = filesize($this->filename); if((true /*class_exists('XMLReader')*/ /*&& $origFileSize > 2*1024*1024*/) && ToLower(CKDAImportUtils::GetFileExtension($this->filename))=='xlsx') { $timeBegin = microtime(true); $needSize = $origFileSize*10; $tempPath = \CFile::GetTempName('', 'test_size.txt'); CheckDirPath($tempPath); $fileSize = 0; $handle = fopen($tempPath, 'a'); while($fileSize < $needSize && microtime(true) - $timeBegin < 3) { $partSize = min(5*1024*1024, $needSize - $fileSize); fwrite($handle, str_repeat('0', $partSize)); $fileSize += $partSize; } fclose($handle); if($fileSize <= filesize($tempPath)) { $this->stepparams['optimizeRam'] = 'Y'; } unlink($tempPath); $dir = dirname($tempPath); if(count(array_diff(scandir($dir), array('.', '..')))==0) { rmdir($dir); } } } if(/*$this->params['OPTIMIZE_RAM']=='Y' ||*/ $this->stepparams['optimizeRam']=='Y') { KDAPHPExcel_Settings::setZipClass(KDAPHPExcel_Settings::KDAIEZIPARCHIVE); } } public function OnBeforeIBlockElementUpdateHandler(&$arFields) { if(isset($arFields['PROPERTY_VALUES'])) unset($arFields['PROPERTY_VALUES']); } public function OnFileSaveHandler(&$arFile, $strFileName, $strSavePath, $bForceMD5, $bSkipExt, $dirAdd) { if($arFile['SAVE_ORIGINAL_PATH']=='Y') { $uploadDir = trim(\Bitrix\Main\Config\Option::get("main", "upload_dir", "upload"), '/'); $strFileName = $arFile["tmp_name"]; $subdir = dirname(substr($strFileName, strlen(rtrim($_SERVER['DOCUMENT_ROOT'], '/')))); if(strpos($subdir.'/', '/'.$uploadDir.'/')===0) $subdir = substr($subdir, strlen('/'.$uploadDir.'/')); else $subdir = str_repeat('../', count(explode('/', trim($uploadDir, '/')))).ltrim($subdir, '/'); $arFile["SUBDIR"] = $subdir; $arFile["FILE_NAME"] = $arFile["ORIGINAL_NAME"]; $imgArray = \CFile::GetImageSize($strFileName, true); if(is_array($imgArray)) { $arFile["WIDTH"] = $imgArray[0]; $arFile["HEIGHT"] = $imgArray[1]; } $arFile['size'] = filesize($strFileName); return true; } return false; } public function CheckTimeEnding($time = 0) { /*if(!$this->params['MAX_EXECUTION_TIME']) { if(!isset($this->timeStepBegin)) $this->timeStepBegin = $time; if(time()-$this->timeStepBegin > 10) { usleep(10000000); $this->timeStepBegin = time(); } }*/ if($time==0) $time = $this->timeBeginImport; $this->ClearIblocksTagCache(true); return ($this->params['MAX_EXECUTION_TIME'] && (time()-$time >= $this->params['MAX_EXECUTION_TIME'] || $this->memoryLimit - memory_get_peak_usage() < 2097152)); } public function GetRemainingTime() { if(!$this->params['MAX_EXECUTION_TIME']) return 600; else return ($this->params['MAX_EXECUTION_TIME'] - (time() - $this->timeBeginImport)); } public function HaveTimeSetWorksheet($time) { $this->notHaveTimeSetWorksheet = ($this->params['MAX_EXECUTION_TIME'] && $this->params['TIME_READ_FILE'] && (time()-$time+$this->params['TIME_READ_FILE'] >= $this->params['MAX_EXECUTION_TIME'] || $this->memoryLimit - memory_get_peak_usage() < 16777224)); return !$this->notHaveTimeSetWorksheet; } public function Import() { register_shutdown_function(array($this, 'OnShutdown')); set_error_handler(array($this, "HandleError")); set_exception_handler(array($this, "HandleException")); if(isset($this->stepparams['finishstatus']) && $this->stepparams['finishstatus']=='Y') { if($this->breakByEvent) return $this->GetBreakParams('afterfinish'); else return $this->AfterFinish(); } elseif($this->breakByEvent) return $this->GetBreakParams('finish'); $this->stepparams['import_started'] = 1; $this->SaveStatusImport(); if(is_callable(array('\CIBlock', 'disableClearTagCache'))) \CIBlock::disableClearTagCache(); $time = $this->timeBeginImport = $this->timeBeginTagCache = $this->timeSaveResult = time(); if($this->stepparams['curstep'] == 'import') { $this->InitImport(); while($arItem = $this->GetNextRecord($time)) { if(is_array($arItem)) $this->SaveRecord($arItem); if($this->CheckTimeEnding($time)/* || ($this->stepparams['IMPORT_MODE']!='CRON' && $this->logger->GetFileErrors())*/) { return $this->GetBreakParams(); } } if($this->CheckTimeEnding($time) || $this->notHaveTimeSetWorksheet) return $this->GetBreakParams(); $this->stepparams['curstep'] = 'import_end'; } return $this->EndOfLoading($time); } public function EndOfLoading($time) { $this->conv->Disable(); if($this->stepparams['section_added_line'] > 0 && (!isset($this->stepparams['deactivate_element_first']) || (int)$this->stepparams['deactivate_element_first']==0)) { $arIblocks = array(); foreach($this->params['IBLOCK_ID'] as $k=>$v) { if($this->params['LIST_ACTIVE'][$k]!='Y' || in_array($v, $arIblocks)) continue; \CIBlockSection::ReSort($v); $arIblocks[] = $v; } } $bSetDefaultProps = $bSetOfferDefaultProps = false; if(is_array($this->params['ADDITIONAL_SETTINGS'])) { foreach($this->params['ADDITIONAL_SETTINGS'] as $key=>$val) { if(is_array($val)) { if(!empty($val['OFFER_PROPERTIES_DEFAULT'])) $bSetOfferDefaultProps = true; if(!empty($val['ELEMENT_PROPERTIES_DEFAULT']) || $bSetOfferDefaultProps) $bSetDefaultProps = true; } } } $bSetDefaultProps2 = $bSetOfferDefaultProps2 = false; if($this->params['CELEMENT_MISSING_DEFAULTS']) { $arDefaults2 = $this->GetMissingDefaultVals($this->params['CELEMENT_MISSING_DEFAULTS']); if(!empty($arDefaults2)) $bSetDefaultProps2 = true; } if($this->params['OFFER_MISSING_DEFAULTS']) { $arDefaults2 = $this->GetMissingDefaultVals($this->params['OFFER_MISSING_DEFAULTS']); if(!empty($arDefaults2)) $bSetDefaultProps2 = $bSetOfferDefaultProps2 = true; } $bOffersDeactivate = (bool)($this->params['ELEMENT_MISSING_DEACTIVATE']=='Y' || $this->params['ELEMENT_MISSING_TO_ZERO']=='Y' || $this->params['ELEMENT_MISSING_REMOVE_PRICE']=='Y' || $this->params['OFFER_MISSING_DEACTIVATE']=='Y' || $this->params['OFFER_MISSING_TO_ZERO']=='Y' || $this->params['OFFER_MISSING_REMOVE_PRICE']=='Y' || $this->params['OFFER_MISSING_REMOVE_ELEMENT']=='Y'); $bElemDeactivate = (bool)($bOffersDeactivate || $this->params['CELEMENT_MISSING_DEACTIVATE']=='Y' || $this->params['CELEMENT_MISSING_TO_ZERO']=='Y' || $this->params['CELEMENT_MISSING_REMOVE_PRICE']=='Y' || $this->params['CELEMENT_MISSING_REMOVE_ELEMENT']=='Y'); $bOffersActions = (bool)($bOffersDeactivate || $bSetOfferDefaultProps || $bSetOfferDefaultProps2); if($bElemDeactivate || $bSetDefaultProps || $bSetDefaultProps2) { $bOnlySetDefaultProps = (bool)(($bSetDefaultProps || $bSetDefaultProps2) && !$bElemDeactivate); if($this->stepparams['curstep'] == 'import' || $this->stepparams['curstep'] == 'import_end') { $this->SaveStatusImport(); if($this->CheckTimeEnding($time)) return $this->GetBreakParams(); $this->stepparams['curstep'] = 'deactivate_elements'; $oProfile = CKDAImportProfile::getInstance(); $this->stepparams['deactivate_element_last'] = $oProfile->GetLastImportId('E'); $this->stepparams['deactivate_offer_last'] = $oProfile->GetLastImportId('O'); $this->stepparams['deactivate_element_first'] = 0; $this->stepparams['deactivate_element_first2'] = array(); $this->stepparams['deactivate_offer_first'] = 0; if(!$this->stepparams['deactivate_element_last'] && $this->params['MISSING_ACTIONS_FOR_EMPTY_FILE']=='Y') { $this->SaveElementId(0); $this->stepparams['deactivate_element_first'] = -1; $this->stepparams['deactivate_element_last'] = 0; } $this->worksheetCurrentRow = 0; $this->SaveStatusImport(); if($this->CheckTimeEnding($time + 1000)) return $this->GetBreakParams(); } $arFieldsList = array(); $arOfferFilters = array(); $arOffersExists = array(); foreach($this->params['IBLOCK_ID'] as $k=>$v) { if($this->params['LIST_ACTIVE'][$k]!='Y' || ($this->stepparams['total_line_by_list'][$k] < 1 && $this->params['MISSING_ACTIONS_FOR_EMPTY_FILE']!='Y')) continue; if($bOnlySetDefaultProps && !$bSetDefaultProps2 && empty($this->params['ADDITIONAL_SETTINGS'][$k]['ELEMENT_PROPERTIES_DEFAULT']) && empty($this->params['ADDITIONAL_SETTINGS'][$k]['OFFER_PROPERTIES_DEFAULT'])) continue; if(count(preg_grep('/^OFFER_/', $this->params['FIELDS_LIST'][$k])) > 0) { $arOffersExists[$k] = true; $arOfferFilters[$k] = array(); } $arFieldsList[$k] = array( 'IBLOCK_ID' => $v, 'CHECK_PERMISSIONS' => 'N' ); if($this->params['SECTION_ID'][$k] && $this->params['MISSING_ACTIONS_IN_SECTION']!='N') { $arFieldsList[$k]['SECTION_ID'] = $this->params['SECTION_ID'][$k]; $arFieldsList[$k]['INCLUDE_SUBSECTIONS'] = 'Y'; } if(is_array($this->fparams[$k])) { $propsDef = $this->GetIblockProperties($v); foreach($this->fparams[$k] as $k2=>$ffilter) { if(!is_array($ffilter)) $ffilter = array(); if(isset($this->stepparams['fparams'][$k][$k2]) && $ffilter['USE_FILTER_FOR_DEACTIVATE']=='Y') { $ffilter2 = $this->stepparams['fparams'][$k][$k2]; if(is_array($ffilter2['UPLOAD_VALUES'])) { if(!is_array($ffilter['UPLOAD_VALUES'])) $ffilter['UPLOAD_VALUES'] = array(); $ffilter['UPLOAD_VALUES'] = array_unique(array_merge($ffilter['UPLOAD_VALUES'], $ffilter2['UPLOAD_VALUES'])); } if(is_array($ffilter2['NOT_UPLOAD_VALUES'])) { if(!is_array($ffilter['NOT_UPLOAD_VALUES'])) $ffilter['NOT_UPLOAD_VALUES'] = array(); $ffilter['NOT_UPLOAD_VALUES'] = array_unique(array_merge($ffilter['NOT_UPLOAD_VALUES'], $ffilter2['NOT_UPLOAD_VALUES'])); } } if($ffilter['USE_FILTER_FOR_DEACTIVATE']=='Y' && (!empty($ffilter['UPLOAD_VALUES']) || !empty($ffilter['NOT_UPLOAD_VALUES']))) { $field = false; if(isset($this->params['FIELDS_LIST'][$k][$k2])) $field = $this->params['FIELDS_LIST'][$k][$k2]; elseif(is_array($this->params['LIST_SETTINGS'][$k]) && preg_match('/^__P(\d+)$/', $k2, $m) && array_key_exists('SET_PROPERTY_'.$m[1], $this->params['LIST_SETTINGS'][$k])) $field = 'IP_PROP'.$m[1]; if($field) { if(strpos($field, 'OFFER_')===0) { if(isset($arOfferFilters[$k])) { $arOfferIblock = $this->GetCachedOfferIblock($v); $this->GetMissingFilterByField($arOfferFilters[$k], substr($field, 6), $arOfferIblock['OFFERS_IBLOCK_ID'], $ffilter); } } else { $this->GetMissingFilterByField($arFieldsList[$k], $field, $v, $ffilter); } } } } } CKDAImportUtils::AddFilter($arFieldsList[$k], $this->params['CELEMENT_MISSING_FILTER']); } while($this->stepparams['deactivate_element_first'] < $this->stepparams['deactivate_element_last']) { $oProfile = CKDAImportProfile::getInstance(); $arUpdatedIds = $oProfile->GetUpdatedIds('E', $this->stepparams['deactivate_element_first']); if(empty($arUpdatedIds)) { $this->stepparams['deactivate_element_first'] = $this->stepparams['deactivate_element_last']; continue; } $lastElement = end($arUpdatedIds); foreach($arFieldsList as $key=>$arFields) { $this->deactivateListKey = $key; if($this->stepparams['begin_time']) { $arFields['<TIMESTAMP_X'] = $this->stepparams['begin_time']; } $arSubFields = $this->GetMissingFilter(false, $arFields['IBLOCK_ID'], $arUpdatedIds); if($arOffersExists && ($arOfferIblock = $this->GetCachedOfferIblock($arFields['IBLOCK_ID']))) { $OFFERS_IBLOCK_ID = $arOfferIblock['OFFERS_IBLOCK_ID']; $OFFERS_PROPERTY_ID = $arOfferIblock['OFFERS_PROPERTY_ID']; $arOfferFields = array("IBLOCK_ID" => $OFFERS_IBLOCK_ID); if(isset($arOfferFilters[$key]) && is_array($arOfferFilters[$key])) $arOfferFields = $arOfferFields + $arOfferFilters[$key]; $arSubOfferFields = $this->GetMissingFilter(true, $OFFERS_IBLOCK_ID); if(!empty($arSubOfferFields) || count($arOfferFields) > 1) { if(count($arSubOfferFields) > 1) $arOfferFields[] = array_merge(array('LOGIC' => 'OR'), $arSubOfferFields); else $arOfferFields = array_merge($arOfferFields, $arSubOfferFields); $offerSubQuery = CIBlockElement::SubQuery('PROPERTY_'.$OFFERS_PROPERTY_ID, $arOfferFields); if(array_key_exists('ID', $arSubFields)) { $arSubFields[] = array('LOGIC' => 'OR', array('ID'=>$arSubFields['ID']), array('ID'=>$offerSubQuery)); unset($arSubFields['ID']); } else { $arSubFields['ID'] = $offerSubQuery; } } } if(count($arSubFields) > 1) $arFields[] = array_merge(array('LOGIC' => 'OR'), $arSubFields); else $arFields = array_merge($arFields, $arSubFields); $arFields['!ID'] = $arUpdatedIds; if($this->stepparams['deactivate_element_first'] > 0) $arFields['>ID'] = $this->stepparams['deactivate_element_first']; if($this->stepparams['deactivate_element_first2'][$key] > $this->stepparams['deactivate_element_first'] && $this->stepparams['deactivate_element_first2'][$key] > 0) $arFields['>ID'] = $this->stepparams['deactivate_element_first2'][$key]; if($lastElement < $this->stepparams['deactivate_element_last']) $arFields['<=ID'] = $lastElement; $dbRes = CIblockElement::GetList(array('ID'=>'ASC'), $arFields, false, false, array('ID')); while($arr = $dbRes->Fetch()) { if($this->params['CELEMENT_MISSING_REMOVE_ELEMENT']=='Y') { if($arOffersExists && $bOffersActions) { $this->DeactivateAllOffersByProductId($arr['ID'], $arFields['IBLOCK_ID'], $arOfferFilters[$key], $time, true); } $this->DeleteElement($arr['ID'], $arFields['IBLOCK_ID']); $this->stepparams['old_removed_line']++; } else { $this->MissingElementsUpdate($arr['ID'], $arFields['IBLOCK_ID'], false); if($arOffersExists && $bOffersActions) { $this->DeactivateAllOffersByProductId($arr['ID'], $arFields['IBLOCK_ID'], $arOfferFilters[$key], $time); } } $this->stepparams['deactivate_element_first2'][$key] = $arr['ID']; $this->SaveStatusImport(); if($this->CheckTimeEnding($time)) { return $this->GetBreakParams(); } } if($arOffersExists && $bOffersActions) { $ret = $this->DeactivateOffersByProductIds($arUpdatedIds, $arFields['IBLOCK_ID'], $arOfferFilters[$key], $time); if(is_array($ret)) return $ret; } } $this->stepparams['deactivate_element_first'] = $lastElement; } $this->SaveStatusImport(); if($this->CheckTimeEnding($time)) return $this->GetBreakParams(); } if($this->CheckTimeEnding($time)) return $this->GetBreakParams(); if($this->params['SECTION_EMPTY_REMOVE']=='Y' && class_exists('\Bitrix\Iblock\SectionElementTable')) { $this->stepparams['curstep'] = 'deactivate_sections'; foreach($this->params['IBLOCK_ID'] as $k=>$v) { if($this->params['LIST_ACTIVE'][$k]!='Y') continue; $sectionId = (int)$this->params['SECTION_ID'][$k]; $arSectionsRes = $this->GetFESections($v, $sectionId); if(!empty($arSectionsRes['INACTIVE'])) { $dbRes = CIBlockSection::GetList(array(), array('ID'=>$arSectionsRes['INACTIVE'], '!ID'=>$sectionId, 'CHECK_PERMISSIONS'=>'N'), false, array('ID', 'IBLOCK_ID')); while($arr = $dbRes->Fetch()) { $this->BeforeSectionSave($sectId, "update"); $this->DeleteSection($arr['ID'], $arr['IBLOCK_ID']); $this->stepparams['section_remove_line']++; $this->SaveStatusImport(); if($this->CheckTimeEnding($time)) return $this->GetBreakParams(); } } } } if(($this->params['SECTION_EMPTY_DEACTIVATE']=='Y' || $this->params['SECTION_NOTEMPTY_ACTIVATE']=='Y') && class_exists('\Bitrix\Iblock\SectionElementTable')) { $this->stepparams['curstep'] = 'deactivate_sections'; foreach($this->params['IBLOCK_ID'] as $k=>$v) { if($this->params['LIST_ACTIVE'][$k]!='Y') continue; $sectionId = (int)$this->params['SECTION_ID'][$k]; $arSectionsRes = $this->GetFESections($v, $sectionId, array('ACTIVE' => 'Y')); $sect = new CIBlockSection(); if($this->params['SECTION_NOTEMPTY_ACTIVATE']=='Y' && !empty($arSectionsRes['ACTIVE'])) { $dbRes = CIBlockSection::GetList(array(), array('ID'=>$arSectionsRes['ACTIVE'], 'ACTIVE'=>'N', 'CHECK_PERMISSIONS'=>'N'), false, array('ID', 'IBLOCK_ID', 'ACTIVE')); while($arr = $dbRes->Fetch()) { $this->UpdateSection($arr['ID'], $arr['IBLOCK_ID'], array('ACTIVE'=>'Y'), $arr); $this->SaveStatusImport(); if($this->CheckTimeEnding($time)) return $this->GetBreakParams(); } } if($this->params['SECTION_EMPTY_DEACTIVATE']=='Y' && !empty($arSectionsRes['INACTIVE'])) { $dbRes = CIBlockSection::GetList(array(), array('ID'=>$arSectionsRes['INACTIVE'], 'ACTIVE'=>'Y', 'CHECK_PERMISSIONS'=>'N'), false, array('ID', 'IBLOCK_ID', 'ACTIVE')); while($arr = $dbRes->Fetch()) { $this->UpdateSection($arr['ID'], $arr['IBLOCK_ID'], array('ACTIVE'=>'N'), $arr); $this->stepparams['section_deactivate_line']++; $this->SaveStatusImport(); if($this->CheckTimeEnding($time)) return $this->GetBreakParams(); } } } } if($this->params['BIND_PROPERTIES_TO_SECTIONS']=='Y') { if(!array_key_exists('bound_properties', $this->stepparams)) { $arExclude = $this->params['BIND_PROPERTIES_TO_SECTIONS_EXCLUDE']; if(!is_array($arExclude)) $arExclude = array(); $this->stepparams['bound_properties'] = array(); foreach($this->params['IBLOCK_ID'] as $k=>$v) { if($this->params['LIST_ACTIVE'][$k]!='Y') continue; if(!array_key_exists($v, $this->stepparams['bound_properties'])) $this->stepparams['bound_properties'][$v] = array(); foreach($this->params['FIELDS_LIST'][$k] as $k2=>$v2) { if(preg_match('/^IP_PROP(\d+)$/', $v2, $m) && !in_array($m[1], $this->stepparams['bound_properties'][$v]) && !in_array($v2, $arExclude)) { $this->stepparams['bound_properties'][$v][] = $m[1]; } } } } foreach($this->stepparams['bound_properties'] as $k=>$v) { foreach($v as $k2=>$v2) { $this->UpdateSectionPropertyLinks($k, $v2); unset($this->stepparams['bound_properties'][$k][$k2]); if($this->CheckTimeEnding($time)) return $this->GetBreakParams(); } } } if($this->params['REMOVE_EXPIRED_DISCOUNT']=='Y') { $this->RemoveExpiredDiscount(); } if(is_callable(array('CIBlock', 'clearIblockTagCache'))) { if(is_callable(array('\CIBlock', 'enableClearTagCache'))) \CIBlock::enableClearTagCache(); foreach($this->params['IBLOCK_ID'] as $k=>$v) { if($this->params['LIST_ACTIVE'][$k]!='Y') continue; $bEventRes = true; foreach(GetModuleEvents(static::$moduleId, "OnBeforeClearCache", true) as $arEvent) { if(ExecuteModuleEventEx($arEvent, array($v))===false) { $bEventRes = false; } } if($bEventRes) { \CIBlock::clearIblockTagCache($v); } } if(is_callable(array('\CIBlock', 'disableClearTagCache'))) \CIBlock::disableClearTagCache(); } if($this->params['REMOVE_COMPOSITE_CACHE']=='Y' && class_exists('\Bitrix\Main\Composite\Helper')) { require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/classes/general/cache_files_cleaner.php"); $obCacheCleaner = new CFileCacheCleaner('html'); if($obCacheCleaner->InitPath('')) { $obCacheCleaner->Start(); $space_freed = 0; while($file = $obCacheCleaner->GetNextFile()) { if( is_string($file) && !preg_match("/(\\.enabled|\\.size|.config\\.php)\$/", $file) ) { $file_size = filesize($file); if(@unlink($file)) { $space_freed+=$file_size; } } if($this->CheckTimeEnding($time)) { \Bitrix\Main\Composite\Helper::updateCacheFileSize(-$space_freed); return $this->GetBreakParams(); } } \Bitrix\Main\Composite\Helper::updateCacheFileSize(-$space_freed); } $page = \Bitrix\Main\Composite\Page::getInstance(); $page->deleteAll(); } $this->SaveStatusImport(true); $this->logger->FinishExec($this->stepparams); $oProfile = CKDAImportProfile::getInstance(); $arEventData = $oProfile->OnEndImport($this->filename, $this->stepparams, $this->errors); $arEventData['FILE_SHEET_NAMES'] = $this->stepparams['listWorksheetNames']; $this->stepparams['onendeventdata'] = $arEventData; \Bitrix\KdaImportexcel\ZipArchive::RemoveFileDir($this->filename); if($this->stepparams['IMPORT_MODE']=='CRON') return $this->AfterFinish(); return $this->GetBreakParams('finish'); } public function AfterFinish() { $arEventData = (isset($this->stepparams['onendeventdata']) && is_array($this->stepparams['onendeventdata']) ? $this->stepparams['onendeventdata'] : array()); foreach(GetModuleEvents(static::$moduleId, "OnEndImport", true) as $arEvent) { $bEventRes = ExecuteModuleEventEx($arEvent, array($this->pid, $arEventData)); if($bEventRes['ACTION']=='REDIRECT') { $this->stepparams['redirect_url'] = $bEventRes['LOCATION']; } } return $this->GetBreakParams('afterfinish'); } public function GetMissingDefaultVals($vals) { $arVals = unserialize(base64_decode($vals)); if(!is_array($arVals)) $arVals = array(); $pattern = '/(#DATETIME#)/'; foreach($arVals as $k=>$v) { if(!is_array($v) && !is_bool($v)) { $arVals[$k] = preg_replace_callback($pattern, array($this, 'ConversionReplaceValues'), $v); } } return $arVals; } public function GetFESections($IBLOCK_ID, $SECTION_ID=0, $arElemFilter=array()) { $arFilterSections = array('IBLOCK_ID' => $IBLOCK_ID, 'CHECK_PERMISSIONS' => 'N'); $arFilterSE = array('IBLOCK_SECTION.IBLOCK_ID' => $IBLOCK_ID, 'IBLOCK_ELEMENT.IBLOCK_ID' => $IBLOCK_ID); foreach($arElemFilter as $k=>$v) { $arFilterSE['IBLOCK_ELEMENT.'.$k] = $v; } if($SECTION_ID) { $dbRes = CIBlockSection::GetList(array(), array('ID'=>$SECTION_ID, 'CHECK_PERMISSIONS'=>'N'), false, array('LEFT_MARGIN', 'RIGHT_MARGIN')); if($arr = $dbRes->Fetch()) { $arFilterSections['>=LEFT_MARGIN'] = $arr['LEFT_MARGIN']; $arFilterSections['<=RIGHT_MARGIN'] = $arr['RIGHT_MARGIN']; $arFilterSE['>=IBLOCK_SECTION.LEFT_MARGIN'] = $arr['LEFT_MARGIN']; $arFilterSE['<=IBLOCK_SECTION.RIGHT_MARGIN'] = $arr['RIGHT_MARGIN']; } else { return array(); } } $arListSections = array(); $dbRes = CIBlockSection::GetList(array('DEPTH_LEVEL'=>'DESC'), $arFilterSections, false, array('ID', 'IBLOCK_SECTION_ID')); while($arr = $dbRes->Fetch()) { $arListSections[$arr['ID']] = ($SECTION_ID==$arr['ID'] ? false : $arr['IBLOCK_SECTION_ID']); } $arActiveSections = array(); $dbRes = \Bitrix\Iblock\SectionElementTable::GetList(array('filter'=>$arFilterSE, 'group'=>array('IBLOCK_SECTION_ID'), 'select'=>array('IBLOCK_SECTION_ID'))); while($arr = $dbRes->Fetch()) { $sid = $arr['IBLOCK_SECTION_ID']; $arActiveSections[] = $sid; while($sid = $arListSections[$sid]) { $arActiveSections[] = $sid; } } $arInactiveSections = array_diff(array_keys($arListSections), $arActiveSections); return array( 'ACTIVE' => $arActiveSections, 'INACTIVE' => $arInactiveSections ); } public function DeactivateAllOffersByProductId($ID, $IBLOCK_ID, $arFilter, $time, $deleteMode = false) { if(!($arOfferIblock = $this->GetCachedOfferIblock($IBLOCK_ID))) return false; $OFFERS_IBLOCK_ID = $arOfferIblock['OFFERS_IBLOCK_ID']; $OFFERS_PROPERTY_ID = $arOfferIblock['OFFERS_PROPERTY_ID']; $arFields = array( 'IBLOCK_ID' => $OFFERS_IBLOCK_ID, 'PROPERTY_'.$OFFERS_PROPERTY_ID => $ID, 'CHECK_PERMISSIONS' => 'N' ); if(is_array($arFilter)) $arFields = $arFields + $arFilter; $arSubFields = $this->GetMissingFilter(true, $OFFERS_IBLOCK_ID); if(!empty($arSubFields)) { if(count($arSubFields) > 1) $arFields[] = array_merge(array('LOGIC' => 'OR'), $arSubFields); else $arFields = array_merge($arFields, $arSubFields); $dbRes = CIblockElement::GetList(array('ID'=>'ASC'), $arFields, false, false, array('ID')); while($arr = $dbRes->Fetch()) { if($deleteMode) { $this->DeleteElement($arr['ID'], $arFields['IBLOCK_ID']); $this->stepparams['offer_old_removed_line']++; } else { $this->MissingElementsUpdate($arr['ID'], $OFFERS_IBLOCK_ID, true); } if($this->CheckTimeEnding($time)) { return $this->GetBreakParams(); } } } } public function DeactivateOffersByProductIds(&$arElementIds, $IBLOCK_ID, $arFilter, $time) { if(!($arOfferIblock = $this->GetCachedOfferIblock($IBLOCK_ID))) return false; $OFFERS_IBLOCK_ID = $arOfferIblock['OFFERS_IBLOCK_ID']; $OFFERS_PROPERTY_ID = $arOfferIblock['OFFERS_PROPERTY_ID']; while($this->stepparams['deactivate_offer_first'] < $this->stepparams['deactivate_offer_last']) { $oProfile = CKDAImportProfile::getInstance(); $arUpdatedIds = $oProfile->GetUpdatedIds('O', $this->stepparams['deactivate_offer_first']); if(empty($arUpdatedIds)) { $this->stepparams['deactivate_offer_first'] = $this->stepparams['deactivate_offer_last']; continue; } $lastElement = end($arUpdatedIds); $arFields = array( 'IBLOCK_ID' => $OFFERS_IBLOCK_ID, 'PROPERTY_'.$OFFERS_PROPERTY_ID => $arElementIds, '!ID' => $arUpdatedIds, 'CHECK_PERMISSIONS' => 'N' ); if(is_array($arFilter) && !empty($arFilter)) { unset($arFields['PROPERTY_'.$OFFERS_PROPERTY_ID]); $arFields = $arFields + $arFilter; } $arSubFields = $this->GetMissingFilter(true, $OFFERS_IBLOCK_ID); if(!empty($arSubFields)) { if(count($arSubFields) > 1) $arFields[] = array_merge(array('LOGIC' => 'OR'), $arSubFields); else $arFields = array_merge($arFields, $arSubFields); } if($this->stepparams['begin_time']) { $arFields['<TIMESTAMP_X'] = $this->stepparams['begin_time']; } if($this->stepparams['deactivate_offer_first'] > 0) $arFields['>ID'] = $this->stepparams['deactivate_offer_first']; if($lastElement < $this->stepparams['deactivate_offer_last']) $arFields['<=ID'] = $lastElement; $dbRes = CIblockElement::GetList(array('ID'=>'ASC'), $arFields, false, false, array('ID')); while($arr = $dbRes->Fetch()) { if($this->params['OFFER_MISSING_REMOVE_ELEMENT']=='Y') { $this->DeleteElement($arr['ID'], $arFields['IBLOCK_ID']); $this->stepparams['offer_old_removed_line']++; } else { $this->MissingElementsUpdate($arr['ID'], $OFFERS_IBLOCK_ID, true); } $this->SaveStatusImport(); if($this->CheckTimeEnding($time)) { return $this->GetBreakParams(); } } if($this->CheckTimeEnding($time)) return $this->GetBreakParams(); $this->stepparams['deactivate_offer_first'] = $lastElement; } $this->stepparams['deactivate_offer_first'] = 0; } public function MissingElementsUpdate($ID, $IBLOCK_ID, $isOffer = false) { if(!$ID) return; if($isOffer) $this->SetSkuMode(true, $ID, $IBLOCK_ID); $prefix = ($isOffer ? 'OFFER' : 'CELEMENT'); $this->BeforeElementSave($ID, 'update'); $arElementFields = array(); $arProps = array(); $arProduct = array(); $arStores = array(); $arPrices = array(); if($this->params['ELEMENT_MISSING_DEACTIVATE']=='Y' || $this->params[$prefix.'_MISSING_DEACTIVATE']=='Y') { $arElementFields['ACTIVE'] = 'N'; if($isOffer) $this->stepparams['offer_killed_line']++; else $this->stepparams['killed_line']++; } if($this->params['ELEMENT_MISSING_TO_ZERO']=='Y' || $this->params[$prefix.'_MISSING_TO_ZERO']=='Y') { $arProduct['QUANTITY'] = $arProduct['QUANTITY_RESERVED'] = 0; $dbRes2 = CCatalogStoreProduct::GetList(array(), array('PRODUCT_ID'=>$ID/*, '>AMOUNT'=>'0'*/), false, false, array('ID', 'STORE_ID')); while($arStore = $dbRes2->Fetch()) { $arStores[$arStore["STORE_ID"]] = array('AMOUNT' => ''); } if($isOffer) $this->stepparams['offer_zero_stock_line']++; else $this->stepparams['zero_stock_line']++; } if($this->params['ELEMENT_MISSING_REMOVE_PRICE']=='Y' || $this->params[$prefix.'_MISSING_REMOVE_PRICE']=='Y') { $dbRes = CCatalogGroup::GetList(array("SORT" => "ASC")); while($arPriceType = $dbRes->Fetch()) { $arPrices[$arPriceType["ID"]] = array('PRICE' => '-'); } } $key = $this->deactivateListKey; $arDefaults = array(); if(is_array($this->params['ADDITIONAL_SETTINGS'][$key][($isOffer ? 'OFFER' : 'ELEMENT').'_PROPERTIES_DEFAULT'])) { $arDefaults = $this->params['ADDITIONAL_SETTINGS'][$key][($isOffer ? 'OFFER' : 'ELEMENT').'_PROPERTIES_DEFAULT']; } if($this->params[$prefix.'_MISSING_DEFAULTS']) { $arDefaults2 = $this->GetMissingDefaultVals($this->params[$prefix.'_MISSING_DEFAULTS']); if(!empty($arDefaults2)) $arDefaults = $arDefaults + $arDefaults2; } if(!empty($arDefaults)) { foreach($arDefaults as $propKey=>$propVal) { if(strpos($propKey, 'IE_')===0) { $arElementFields[substr($propKey, 3)] = $propVal; } elseif(preg_match('/ICAT_STORE(\d+)_AMOUNT/', $propKey, $m)) { $arStores[$m[1]] = array('AMOUNT' => $propVal); } elseif(preg_match('/ICAT_PRICE(\d+)_PRICE/', $propKey, $m)) { $arPrices[$m[1]] = array('PRICE' => $propVal); } elseif(strpos($propKey, 'ICAT_')===0) { $arProduct[substr($propKey, 5)] = $propVal; } else { $arProps[$propKey] = $propVal; } } } if(!empty($arProduct) || !empty($arPrices) || !empty($arStores)) { $this->SaveProduct($ID, $IBLOCK_ID, $arProduct, $arPrices, $arStores); } if(!empty($arProps)) { $this->SaveProperties($ID, $IBLOCK_ID, $arProps); } $this->AfterSaveProduct($arElementFields, $ID, $IBLOCK_ID, true, $isOffer); $arKeys = array_merge(array_keys($arElementFields), array('ID', 'MODIFIED_BY')); $arFilter = array('ID'=>$ID, 'IBLOCK_ID'=>$IBLOCK_ID, 'CHECK_PERMISSIONS' => 'N'); //$dbRes = CIblockElement::GetList(array(), $arFilter, false, false, $arKeys); $dbRes = \Bitrix\KdaImportexcel\DataManager\IblockElementTable::GetListComp($arFilter, $arKeys); if($arElement = $dbRes->Fetch()) { if($this->UpdateElement($ID, $IBLOCK_ID, $arElementFields, $arElement)) { //$this->logger->SaveElementChanges($ID); } $this->logger->SaveElementChanges($ID); } $this->OnAfterSaveElement($ID); if($isOffer) $this->SetSkuMode(false); } public function GetMissingFilterByField(&$arFilter, $field, $iblockId, $ffilter) { $fieldName = ''; if(strpos($field, 'IE_')===0) { $fieldName = substr($field, 3); if(strpos($fieldName, '|')!==false) $fieldName = current(explode('|', $fieldName)); } elseif(strpos($field, 'IP_PROP')===0) { $propsDef = $this->GetIblockProperties($iblockId); $propId = substr($field, 7); $fieldName = 'PROPERTY_'.$propId; if($propsDef[$propId]['PROPERTY_TYPE']=='L') { $fieldName .= '_VALUE'; } elseif($propsDef[$propId]['PROPERTY_TYPE']=='S' && $propsDef[$propId]['USER_TYPE']=='directory') { if(is_array($ffilter['UPLOAD_VALUES'])) { foreach($ffilter['UPLOAD_VALUES'] as $k3=>$v3) { $ffilter['UPLOAD_VALUES'][$k3] = $this->GetHighloadBlockValue($propsDef[$propId], $v3); } } if(is_array($ffilter['NOT_UPLOAD_VALUES'])) { foreach($ffilter['NOT_UPLOAD_VALUES'] as $k3=>$v3) { $ffilter['NOT_UPLOAD_VALUES'][$k3] = $this->GetHighloadBlockValue($propsDef[$propId], $v3); } } } elseif($propsDef[$propId]['PROPERTY_TYPE']=='E') { if(is_array($ffilter['UPLOAD_VALUES'])) { foreach($ffilter['UPLOAD_VALUES'] as $k3=>$v3) { $ffilter['UPLOAD_VALUES'][$k3] = $this->GetIblockElementValue($propsDef[$propId], $v3, $ffilter); } } if(is_array($ffilter['NOT_UPLOAD_VALUES'])) { foreach($ffilter['NOT_UPLOAD_VALUES'] as $k3=>$v3) { $ffilter['NOT_UPLOAD_VALUES'][$k3] = $this->GetIblockElementValue($propsDef[$propId], $v3, $ffilter); } } } } if(strlen($fieldName) > 0) { if(!empty($ffilter['UPLOAD_VALUES'])) { $arFilter[$fieldName] = $ffilter['UPLOAD_VALUES']; if(is_array($ffilter['UPLOAD_VALUES']) && count($ffilter['UPLOAD_VALUES'])==1) { if(in_array('{empty}', $ffilter['UPLOAD_VALUES'])) $arFilter[$fieldName] = false; elseif(in_array('{not_empty}', $ffilter['UPLOAD_VALUES'])) { unset($arFilter[$fieldName]); $arFilter['!'.$fieldName] = false; } } } elseif(!empty($ffilter['NOT_UPLOAD_VALUES'])) { $arFilter['!'.$fieldName] = $ffilter['NOT_UPLOAD_VALUES']; if(is_array($ffilter['NOT_UPLOAD_VALUES']) && count($ffilter['NOT_UPLOAD_VALUES'])==1) { if(in_array('{empty}', $ffilter['NOT_UPLOAD_VALUES'])) $arFilter['!'.$fieldName] = false; elseif(in_array('{not_empty}', $ffilter['UPLOAD_VALUES'])) { unset($arFilter['!'.$fieldName]); $arFilter[$fieldName] = false; } } } } } public function GetMissingFilter($isOffer = false, $IBLOCK_ID = 0, $arUpdatedIds=array()) { $arSubFields = array(); $prefix = ($isOffer ? 'OFFER' : 'CELEMENT'); if($this->params[$prefix.'_MISSING_REMOVE_ELEMENT']=='Y') return ($isOffer ? $arSubFields : array('!ID'=>false)); if($this->params['ELEMENT_MISSING_DEACTIVATE']=='Y' || $this->params[$prefix.'_MISSING_DEACTIVATE']=='Y') $arSubFields['ACTIVE'] = 'Y'; if($this->params['ELEMENT_MISSING_TO_ZERO']=='Y' || $this->params[$prefix.'_MISSING_TO_ZERO']=='Y') $arSubFields[] = array('LOGIC'=>'OR', array('>CATALOG_QUANTITY'=>'0'), array('>QUANTITY_RESERVED'=>'0')); if($this->params['ELEMENT_MISSING_REMOVE_PRICE']=='Y' || $this->params[$prefix.'_MISSING_REMOVE_PRICE']=='Y') $arSubFields['!CATALOG_PRICE_'.$this->pricer->GetBasePriceId()] = false; $key = $this->deactivateListKey; $arDefaults = array(); if(is_array($this->params['ADDITIONAL_SETTINGS'][$key][($isOffer ? 'OFFER' : 'ELEMENT').'_PROPERTIES_DEFAULT'])) { $arDefaults = $this->params['ADDITIONAL_SETTINGS'][$key][($isOffer ? 'OFFER' : 'ELEMENT').'_PROPERTIES_DEFAULT']; } if($this->params[$prefix.'_MISSING_DEFAULTS']) { $arDefaults2 = $this->GetMissingDefaultVals($this->params[$prefix.'_MISSING_DEFAULTS']); if(!empty($arDefaults2)) $arDefaults = $arDefaults + $arDefaults2; } if($IBLOCK_ID > 0 && !empty($arDefaults)) { $arProductFields = array(); $propsDef = $this->GetIblockProperties($IBLOCK_ID); foreach($arDefaults as $origUid=>$arValUid) { if(isset($propsDef[$origUid]) && $propsDef[$origUid]['MULTIPLE']=='Y') { $this->GetMultiplePropertyChange($arValUid); } if(!is_array($arValUid)) $arValUid = array($arValUid); foreach($arValUid as $keyUid=>$valUid) { $uid = $origUid; if(strpos($uid, 'IE_')===0) { $uid = substr($uid, 3); } elseif(preg_match('/ICAT_STORE(\d+)_AMOUNT/', $uid, $m)) { $uid = 'CATALOG_STORE_AMOUNT_'.$m[1]; if(strlen($valUid)==0 || $valUid=='-') $valUid = false; } elseif(preg_match('/ICAT_PRICE(\d+)_PRICE/', $uid, $m)) { $uid = 'CATALOG_PRICE_'.$m[1]; if($valUid=='-') $valUid = false; } elseif($uid=='ICAT_QUANTITY') { $uid = 'CATALOG_QUANTITY'; } elseif(strpos($uid, 'ICAT_')===0) { $field = substr($uid, 5); if(class_exists('\Bitrix\Catalog\ProductTable')) { if(in_array($field, array('QUANTITY_TRACE', 'CAN_BUY_ZERO', 'NEGATIVE_AMOUNT_TRACE', 'SUBSCRIBE'))) { if($field=='NEGATIVE_AMOUNT_TRACE') $configName = 'allow_negative_amount'; else $configName = 'default_'.ToLower($field); if($field=='SUBSCRIBE') $defaultVal = ((string)\Bitrix\Main\Config\Option::get('catalog', $configName) == 'N' ? 'N' : 'Y'); else $defaultVal = ((string)\Bitrix\Main\Config\Option::get('catalog', $configName) == 'Y' ? 'Y' : 'N'); $valUid = trim(ToUpper($valUid)); if($valUid!='D') $valUid = $this->GetBoolValue($valUid); if($valUid==$defaultVal) $arProductFields['!'.$field] = array($valUid, 'D'); else $arProductFields['!'.$field] = $valUid; } else { if(strlen($valUid)==0 || $valUid=='-') $valUid = false; $arProductFields['!'.$field] = $valUid; } } continue; } elseif($propsDef[$uid]['PROPERTY_TYPE']=='L') { if(strlen($valUid)==0) $valUid = false; $uid = 'PROPERTY_'.$uid.'_VALUE'; } else { if($propsDef[$uid]['PROPERTY_TYPE']=='S' && $propsDef[$uid]['USER_TYPE']=='directory') { $valUid = $this->GetHighloadBlockValue($propsDef[$uid], $valUid); } elseif($propsDef[$uid]['PROPERTY_TYPE']=='E') { $valUid = $this->GetIblockElementValue($propsDef[$uid], $valUid, array()); } if(strlen($valUid)==0) $valUid = false; $uid = 'PROPERTY_'.$uid; } if(strpos($keyUid, 'REMOVE_')===0) $fkey = '='.$uid; else $fkey = '!'.$uid; if(!isset($arSubFields[$fkey])) $arSubFields[$fkey] = $valUid; else { if(!is_array($arSubFields[$fkey])) $arSubFields[$fkey] = array($arSubFields[$fkey]); $arSubFields[$fkey][] = $valUid; } } } if(!empty($arProductFields) && !empty($arUpdatedIds) && $IBLOCK_ID > 0) { if(count($arProductFields) > 1) { $arProductFields = array(array_merge(array('LOGIC'=>'OR'), array_map(array('CKDAImportUtils', 'ArrayCombine'), array_keys($arProductFields), $arProductFields))); } $arProductFields['IBLOCK_ELEMENT.IBLOCK_ID'] = $IBLOCK_ID; $arProductFields['!ID'] = $arUpdatedIds; $lastElement = end($arUpdatedIds); if($this->stepparams['deactivate_element_first'] > 0) $arProductFields['>ID'] = $this->stepparams['deactivate_element_first']; if($lastElement < $this->stepparams['deactivate_element_last']) $arProductFields['<=ID'] = $lastElement; $dbRes = \Bitrix\Catalog\ProductTable::getList(array( 'order' => array('ID'=>'ASC'), 'select' => array('ID'), 'filter' => $arProductFields )); $arIds = array(); while($arr = $dbRes->Fetch()) { $arIds[] = $arr['ID']; } if(!empty($arIds)) { $arSubFields['ID'] = $arIds; }elseif(empty($arSubFields)) $arSubFields['ID'] = 0; } } if(!$isOffer && !$this->saveProductWithOffers && defined('\Bitrix\Catalog\ProductTable::TYPE_SKU')) { foreach($arSubFields as $k=>$v) { if(preg_match('/^.?CATALOG_/', $k)) { $arSubFields[] = array('LOGIC' => 'AND', array($k => $v), array('!CATALOG_TYPE'=>\Bitrix\Catalog\ProductTable::TYPE_SKU)); unset($arSubFields[$k]); } } } return $arSubFields; } public function InitImport() { $this->objReader = KDAPHPExcel_IOFactory::createReaderForFile($this->filename); $this->worksheetNames = array(); if(is_callable(array($this->objReader, 'listWorksheetNames'))) { $this->worksheetNames = $this->objReader->listWorksheetNames($this->filename); $this->stepparams['listWorksheetNames'] = $this->worksheetNames; } $worksheetNum = $this->worksheetNum; $pattern = '/(#FILENAME#|#IMPORT_PROCESS_ID#|#SHEETNAME#)/'; $cellPattern = '/#CELL_[A-Z]+(\d+)#/'; $extraLines = array(); foreach($this->fparams as $k=>$listParams) { $this->worksheetNum = $k; foreach($listParams as $k2=>$fs) { if(isset($fs['UPLOAD_VALUES']) && is_array($fs['UPLOAD_VALUES'])) { foreach($fs['UPLOAD_VALUES'] as $k3=>$val) { $this->fparams[$k][$k2]['UPLOAD_VALUES'][$k3] = preg_replace_callback($pattern, array($this, 'ConversionReplaceValues'), $val); } } if(isset($fs['NOT_UPLOAD_VALUES']) && is_array($fs['NOT_UPLOAD_VALUES'])) { foreach($fs['NOT_UPLOAD_VALUES'] as $k3=>$val) { $this->fparams[$k][$k2]['NOT_UPLOAD_VALUES'][$k3] = preg_replace_callback($pattern, array($this, 'ConversionReplaceValues'), $val); } } if(isset($fs['CONVERSION']) && is_array($fs['CONVERSION'])) { foreach($fs['CONVERSION'] as $k2=>$v2) { if(preg_match_all($cellPattern, $v2['TO'].$v2['FROM'], $m)) $extraLines += array_unique($m[1]); } } if(isset($fs['EXTRA_CONVERSION']) && is_array($fs['EXTRA_CONVERSION'])) { foreach($fs['EXTRA_CONVERSION'] as $k2=>$v2) { if(preg_match_all($cellPattern, $v2['TO'].$v2['FROM'], $m)) $extraLines += array_unique($m[1]); } } } } $this->worksheetNum = $worksheetNum; if($this->params['ELEMENT_NOT_LOAD_STYLES']=='Y' && $this->params['ELEMENT_NOT_LOAD_FORMATTING']=='Y') { $this->objReader->setReadDataOnly(true); } if(isset($this->params['CSV_PARAMS'])) { $this->objReader->setCsvParams($this->params['CSV_PARAMS']); } $this->chunkFilter = new KDAChunkReadFilter(); $this->chunkFilter->setParams($this->params); $this->chunkFilter->setLoadLines($extraLines); $this->objReader->setReadFilter($this->chunkFilter); $this->worksheetNum = (isset($this->stepparams['worksheetNum']) ? intval($this->stepparams['worksheetNum']) : 0); $this->worksheetCurrentRow = intval($this->stepparams['worksheetCurrentRow']); $this->GetNextWorksheetNum(); } public function GetBreakParams($action = 'continue') { $this->ClearIblocksTagCache(); $arStepParams = array( 'params' => $this->GetStepParams(), 'action' => $action, 'errors' => $this->errors, 'sessid' => bitrix_sessid(), //'file_errors' => $this->logger->GetFileErrors() ); if($action == 'continue') { file_put_contents($this->tmpfile, serialize($arStepParams['params'])); if(file_exists($this->imagedir)) { DeleteDirFilesEx(substr($this->imagedir, strlen($_SERVER['DOCUMENT_ROOT']))); } } else { if(file_exists($this->procfile)) unlink($this->procfile); if(file_exists($this->tmpdir)) DeleteDirFilesEx(substr($this->tmpdir, strlen($_SERVER['DOCUMENT_ROOT']))); } unset($arStepParams['params']['currentelement']); unset($arStepParams['params']['currentelementitem']); return $arStepParams; } public function GetStepParams() { return array_merge($this->stepparams, array( 'worksheetNum' => intval($this->worksheetNum), 'worksheetCurrentRow' => $this->worksheetCurrentRow, 'skipSepProp' => $this->skipSepProp, 'skipSepSection' => $this->skipSepSection, 'skipSepSectionLevels' => $this->skipSepSectionLevels, 'arSectionNames' => $this->arSectionNames )); } public function SetWorksheet($worksheetNum, $worksheetCurrentRow) { $this->skipRows = 0; if(!file_exists($this->filename)) { $oProfile = \CKDAImportProfile::getInstance(); $oProfile->Apply(($sd=false), ($s=false), $ID); $fid = $oProfile->GetParam('DATA_FILE'); if($fid) { $arFile = \CFile::GetFileArray($fid); $this->filename = $_SERVER['DOCUMENT_ROOT'].$arFile['SRC']; } } $timeBegin = microtime(true); $this->chunkFilter->setRows($worksheetCurrentRow, $this->maxReadRows); if($this->efile) { \CTempFile::Cleanup(); $this->efile->__destruct(); } if($this->worksheetNames[$worksheetNum]) $this->objReader->setLoadSheetsOnly($this->worksheetNames[$worksheetNum]); if($this->stepparams['csv_position'] && is_callable(array($this->objReader, 'setStartFilePosRow'))) { $this->objReader->setStartFilePosRow($this->stepparams['csv_position']); } $getCount = false; if(is_callable(array($this->objReader, 'setCountMode'))) { $getCount = !isset($this->stepparams['total_file_lists_line'][$this->worksheetNum]); $this->objReader->setCountMode($getCount); } $this->efile = $this->objReader->load($this->filename); $this->worksheetIterator = $this->efile->getWorksheetIterator(); $this->worksheet = $this->worksheetIterator->current(); if($getCount) { $preloadCount = $this->params['LIST_LINES'][$this->worksheetNum]; $this->stepparams['total_file_lists_line'][$this->worksheetNum] = $preloadCount; if(is_callable(array($this->worksheet, 'getRealHighestRow'))) { $heghestRow = intval($this->worksheet->getRealHighestRow()); $this->stepparams['total_file_lists_line'][$this->worksheetNum] = $heghestRow; $this->stepparams['total_file_line'] += $heghestRow - $preloadCount; } } $timeEnd = microtime(true); $this->params['TIME_READ_FILE'] = ceil($timeEnd - $timeBegin); $this->params['CURRENT_ELEMENT_UID'] = $this->params['ELEMENT_UID']; $this->params['CURRENT_ELEMENT_UID_SKU'] = $this->params['ELEMENT_UID_SKU']; if($this->params['CHANGE_ELEMENT_UID'][$this->worksheetNum]=='Y') { $this->params['CURRENT_ELEMENT_UID'] = $this->params['LIST_ELEMENT_UID'][$this->worksheetNum]; $this->params['CURRENT_ELEMENT_UID_SKU'] = $this->params['LIST_ELEMENT_UID_SKU'][$this->worksheetNum]; } $this->searchSections = false; if($this->params['SET_SEARCH_SECTIONS'][$this->worksheetNum]=='Y') { $this->searchSections = $this->params['SEARCH_SECTIONS'][$this->worksheetNum]; if(!is_array($this->searchSections) || count($this->searchSections)==0) $this->searchSections =false; } $listSettings = $this->params['LIST_SETTINGS'][$this->worksheetNum]; if(!is_array($listSettings)) $listSettings = array(); $addedFields = array(); foreach($listSettings as $k2=>$v2) { if(strpos($k2, 'SET_PROPERTY_')===0) $addedFields[] = 'IP_PROP'.intval(substr($k2, 13)); } $filedList = $this->params['FIELDS_LIST'][$this->worksheetNum]; $iblockId = $this->params['IBLOCK_ID'][$this->worksheetNum]; if(count(array_diff((is_array($this->params['CURRENT_ELEMENT_UID']) ? $this->params['CURRENT_ELEMENT_UID'] : array($this->params['CURRENT_ELEMENT_UID'])), array_merge($filedList, $addedFields))) > 0 && (!$this->params['SECTION_UID'] || count(preg_grep('/^(ISECT\d*_'.$this->params['SECTION_UID'].'|ISECT_PATH_NAMES|IE_SECTION_PATH)$/', $filedList))==0)) { if($this->worksheet->getHighestDataRow() > 0) { $nofields = array_diff((is_array($this->params['CURRENT_ELEMENT_UID']) ? $this->params['CURRENT_ELEMENT_UID'] : array($this->params['CURRENT_ELEMENT_UID'])), array_merge($filedList, $addedFields)); $fieldNames = $this->fl->GetFieldNames($iblockId); foreach($nofields as $k=>$field) { $nofields[$k] = '"'.$fieldNames[$field].'"'; } $nofields = implode(', ', $nofields); $this->errors[] = sprintf(Loc::getMessage("KDA_IE_NOT_SET_UID"), $this->worksheetNum+1, $nofields); } if(!$this->GetNextWorksheetNum(true)) { $this->worksheet = false; return false; } $pos = $this->GetNextLoadRow(1, $this->worksheetNum); $this->SetWorksheet($this->worksheetNum, $pos); return; } $this->iblockId = $iblockId; $this->fieldSettings = array(); $this->fieldSettingsExtra = array(); $this->fieldOnlyNew = array(); $this->fieldOnlyNewOffer = array(); $this->fieldsForSkuGen = array(); $this->fieldsBindToGenSku = array(); foreach($filedList as $k=>$field) { $fs = $this->fparams[$this->worksheetNum][$k]; if(!is_array($fs)) $fs = array(); if(preg_match('/^(ICAT_PRICE\d+_PRICE|ICAT_PURCHASING_PRICE)$/', $field) && $fs['PRICE_USE_EXT']=='Y') { $this->fieldSettings[$field.'|QUANTITY_FROM='.$fs['PRICE_QUANTITY_FROM'].'|QUANTITY_TO='.$fs['PRICE_QUANTITY_TO']] = $fs; } else { $this->fieldSettings[$field] = $fs; if(strpos($field, '|')!==false) $this->fieldSettings[substr($field, 0, strpos($field, '|'))] = $fs; if($fs['HLBL_FIELD']) $this->fieldSettings[$field.'/'.$fs['HLBL_FIELD']] = $fs; } $this->fieldSettingsExtra[$k] = $fs; if(isset($this->fparams[$this->worksheetNum]['SECTION_'.$k])) { $this->fieldSettingsExtra['SECTION_'.$k] = $this->fparams[$this->worksheetNum]['SECTION_'.$k]; } if($this->fieldSettings[$field]['SET_NEW_ONLY']=='Y') { if(strpos($field, 'OFFER_')===0) $this->fieldOnlyNewOffer[] = substr($field, 6); else $this->fieldOnlyNew[] = $field; } if(strpos($field, 'OFFER_')===0 && $this->fieldSettings[$field]['USE_FOR_SKU_GENERATE']=='Y') { $this->fieldsForSkuGen[] = (string)$k; } if(strpos($field, 'OFFER_')===0 && $this->fieldSettings[$field]['BIND_TO_GENERATED_SKU']=='Y') { $this->fieldsBindToGenSku[] = (string)$k; } } if(isset($this->worksheetNumForSave) && $this->worksheetNumForSave != $this->worksheetNum && isset($this->stepparams['cursections'.$iblockId])) { unset($this->stepparams['cursections'.$iblockId]); unset($this->stepparams['last_section']); } $sectExtraSettingsKeys = preg_grep('/^__P*\d+$/', array_keys($this->fparams[$this->worksheetNum])); foreach($sectExtraSettingsKeys as $k) { $this->fieldSettingsExtra[$k] = $this->fparams[$this->worksheetNum][$k]; } if(!isset($this->stepparams['ELEMENT_NOT_LOAD_STYLES_ORIG'])) { $this->stepparams['ELEMENT_NOT_LOAD_STYLES_ORIG'] = ($this->params['ELEMENT_NOT_LOAD_STYLES']=='Y' ? 'Y' : 'N'); } else { $this->params['ELEMENT_NOT_LOAD_STYLES'] = $this->stepparams['ELEMENT_NOT_LOAD_STYLES_ORIG']; } $this->sectionstyles = array(); $this->propertystyles = array(); if($this->params['ELEMENT_NOT_LOAD_STYLES']!='Y') { foreach($listSettings as $k2=>$v2) { if(strpos($k2, 'SET_SECTION_')===0) $this->sectionstyles[md5($v2)] = intval(substr($k2, 12)); elseif(strpos($k2, 'SET_PROPERTY_')===0) $this->propertystyles[md5($v2)] = intval(substr($k2, 13)); } if(empty($this->sectionstyles) && empty($this->propertystyles)) $this->params['ELEMENT_NOT_LOAD_STYLES'] = 'Y'; elseif(!empty($this->sectionstyles)) $this->sectionstylesFl = min($this->sectionstyles); } $this->sectioncolumn = false; if(isset($listSettings['SECTION_NAME_CELL'])) { $this->sectioncolumn = (int)$listSettings['SECTION_NAME_CELL'] - 1; } $this->titlesRow = (isset($listSettings['SET_TITLES']) ? $listSettings['SET_TITLES'] : false); $this->hintsRow = (isset($listSettings['SET_HINTS']) ? $listSettings['SET_HINTS'] : false); $maxDrawCol = 0; $this->draws = array(); if($this->params['ELEMENT_LOAD_IMAGES']=='Y') { $this->draws = self::GetWorksheetDraws($this->worksheet); } $this->useHyperlinks = false; $this->useNotes = false; foreach($this->fieldSettingsExtra as $k=>$v) { if(is_array($v['CONVERSION'])) { foreach($v['CONVERSION'] as $k2=>$v2) { if(strpos($v2['TO'], '#CLINK#')!==false) { $this->useHyperlinks = true; } if(strpos($v2['TO'], '#CNOTE#')!==false) { $this->useNotes = true; } } } } $this->conv = new \Bitrix\KdaImportexcel\Conversion($this, $iblockId, $this->fieldSettings); $this->worksheetColumns = max(KDAPHPExcel_Cell::columnIndexFromString($this->worksheet->getHighestDataColumn()), $maxDrawCol); $this->worksheetRows = min($this->maxReadRows, $this->worksheet->getHighestDataRow()+1); $this->worksheetCurrentRow = $worksheetCurrentRow; if($this->worksheet) { $this->worksheetRows = min($worksheetCurrentRow+$this->maxReadRows, $this->worksheet->getHighestDataRow()+1); } } public static function GetWorksheetDraws($worksheet) { $draws = array(); $drawCollection = $worksheet->getDrawingCollection(); if($drawCollection) { $arMergedCells = array(); $arMergedCellsPE = $worksheet->getMergeCells(); if(is_array($arMergedCellsPE)) { foreach($arMergedCellsPE as $coord) { list($coord1, $coord2) = explode(':', $coord, 2); $arCoords1 = KDAPHPExcel_Cell::coordinateFromString($coord1); $arCoords2 = KDAPHPExcel_Cell::coordinateFromString($coord2); $arMergedCells[$arCoords1[0]][$coord] = array($arCoords1[1], $arCoords2[1]); $arMergedCells[$arCoords2[0]][$coord] = array($arCoords1[1], $arCoords2[1]); } } foreach($drawCollection as $drawItem) { $coord = $drawItem->getCoordinates(); $arPartsCoord = KDAPHPExcel_Cell::coordinateFromString($coord); $maxDrawCol = max($maxDrawCol, KDAPHPExcel_Cell::columnIndexFromString($arPartsCoord[0])); $arPartsCoordTo = array(); if(is_callable(array($drawItem, 'getCoordinatesTo')) && ($coordTo = $drawItem->getCoordinatesTo())) { $arPartsCoordTo = KDAPHPExcel_Cell::coordinateFromString($coordTo); } $arCoords = array(); if(!empty($arPartsCoordTo)) { for($i=$arPartsCoord[1]; $i<=$arPartsCoordTo[1]; $i++) { $arCoords[] = $arPartsCoord[0].$i; } } if(isset($arMergedCells[$arPartsCoord[0]]) && is_array($arMergedCells[$arPartsCoord[0]])) { foreach($arMergedCells[$arPartsCoord[0]] as $range) { if($arPartsCoord[1] >= $range[0] && $arPartsCoord[1] <= $range[1]) { for($i=$range[0]; $i<=$range[1]; $i++) { $arCoords[] = $arPartsCoord[0].$i; } } } } if(empty($arCoords)) $arCoords[] = $coord; $arCoords = array_unique($arCoords); foreach($arCoords as $coord) { //if(array_key_exists($coord, $draws)) continue; if(is_callable(array($drawItem, 'getPath'))) { $draws[$coord][] = $drawItem->getPath(); } elseif(is_callable(array($drawItem, 'getImageResource'))) { $draws[$coord][] = array( 'IMAGE_RESOURCE' => $drawItem->getImageResource(), 'RENDERING_FUNCTION' => $drawItem->getRenderingFunction(), 'MIME_TYPE' => $drawItem->getMimeType(), 'FILENAME' => $drawItem->getIndexedFilename() ); } } } } return $draws; } public function SetFilePosition($pos, $time) { if($this->breakWorksheet) { $this->breakWorksheet = false; if(!$this->GetNextWorksheetNum(true)) return; if(!$this->HaveTimeSetWorksheet($time)) return false; $pos = $this->GetNextLoadRow(1, $this->worksheetNum); $this->SetWorksheet($this->worksheetNum, $pos); } else { $pos = $this->GetNextLoadRow($pos, $this->worksheetNum); if(($pos >= $this->worksheetRows) || !$this->worksheet) { if(!$this->HaveTimeSetWorksheet($time)) return false; if(!$this->GetNextWorksheetNum()) return; $this->SetWorksheet($this->worksheetNum, $pos); if($this->worksheetCurrentRow > $this->worksheetRows) { if(!$this->GetNextWorksheetNum(true)) return; if(!$this->HaveTimeSetWorksheet($time)) return false; $pos = $this->GetNextLoadRow(1, $this->worksheetNum); $this->SetWorksheet($this->worksheetNum, $pos); } $this->SaveStatusImport(); } else { $this->worksheetCurrentRow = $pos; } } $this->stepparams['csv_position'] = $this->chunkFilter->getFilePosRow($this->worksheetCurrentRow); } public function GetNextWorksheetNum($inc = false) { if($inc) $this->worksheetNum++; $arLists = $this->params['LIST_ACTIVE']; while(isset($arLists[$this->worksheetNum]) && $arLists[$this->worksheetNum]!='Y') { $this->worksheetNum++; } if(!isset($arLists[$this->worksheetNum])) { $this->worksheet = false; return false; } return true; } public function UniCheckSkipLine($val, $p) { $load = true; if($load && is_array($p['UPLOAD_VALUES']) && !empty($p['UPLOAD_VALUES'])) { $subload = false; $val = ToLower(trim(is_array($val) ? implode($this->params['ELEMENT_MULTIPLE_SEPARATOR'], $val) : $val)); $keys = $p['UPLOAD_KEYS']; foreach($p['UPLOAD_VALUES'] as $kv=>$needval) { $key = (isset($keys[$kv]) ? $keys[$kv] : ''); $needval = ToLower(trim($needval)); if($this->CompareUploadValue($key, $val, $needval)) { $subload = true; } } $load = ($load && $subload); } if($load && is_array($p['NOT_UPLOAD_VALUES']) && !empty($p['NOT_UPLOAD_VALUES'])) { $subload = true; $val = ToLower(trim(is_array($val) ? implode($this->params['ELEMENT_MULTIPLE_SEPARATOR'], $val) : $val)); $keys = $p['NOT_UPLOAD_KEYS']; foreach($p['NOT_UPLOAD_VALUES'] as $kv=>$needval) { $key = (isset($keys[$kv]) ? $keys[$kv] : ''); $needval = ToLower(trim($needval)); if($this->CompareUploadValue($key, $val, $needval)) { $subload = false; } } $load = ($load && $subload); } return !$load; } public function CompareUploadValue($key, $val, $needval) { if((!$key && $needval==$val) || ($needval=='{empty}' && strlen($val)==0) || ($needval=='{not_empty}' && strlen($val) > 0) || ($key=='contain' && strpos($val, $needval)!==false) || ($key=='begin' && mb_substr($val, 0, mb_strlen($needval))==$needval) || ($key=='end' && mb_substr($val, -mb_strlen($needval))==$needval) || ($key=='gt' && $this->GetFloatVal($val) > $this->GetFloatVal($needval)) || ($key=='lt' && $this->GetFloatVal($val) < $this->GetFloatVal($needval))) { return true; }else return false; } public function CheckSkipLine($currentRow, $worksheetNum, $checkValue = true) { $load = true; if($this->breakWorksheet || (!$this->params['CHECK_ALL'][$worksheetNum] && !isset($this->params['IMPORT_LINE'][$worksheetNum][$currentRow - 1])) || (isset($this->params['IMPORT_LINE'][$worksheetNum][$currentRow - 1]) && !$this->params['IMPORT_LINE'][$worksheetNum][$currentRow - 1]) || ($this->titlesRow!==false && $this->titlesRow==($currentRow - 1))) { $load = false; } if($load && !empty($this->params['ADDITIONAL_SETTINGS'][$worksheetNum]['LOADING_RANGE'])) { $load = false; $arRanges = $this->params['ADDITIONAL_SETTINGS'][$worksheetNum]['LOADING_RANGE']; foreach($arRanges as $k=>$v) { $row = $currentRow; if(($v['FROM'] || $v['TO']) && ($row >= $v['FROM'] || !$v['FROM']) && ($row <= $v['TO'] || !$v['TO'])) { $load = true; } } } if($load && $checkValue && is_array($this->fparams[$worksheetNum]) && $this->params['ELEMENT_NOT_LOAD_STYLES']!='Y' && (!empty($this->sectionstyles) || !empty($this->propertystyles))) { $valText = ''; $column = 0; while(strlen($valText)==0 && $column < $this->worksheetColumns) { $val = $this->worksheet->getCellByColumnAndRow($column, $currentRow); $valText = trim($this->GetCalculatedValue($val)); $column++; } if(strlen($valText) > 0) { $arStyle = md5(CUtil::PhpToJSObject($this->GetCellStyle($val))); if(isset($this->sectionstyles[$arStyle]) || isset($this->propertystyles[$arStyle])) { $checkValue = false; } } } if($load && $checkValue && is_array($this->fparams[$worksheetNum])) { foreach($this->fparams[$worksheetNum] as $k=>$v) { if(!is_array($v) || strpos($k, '__')===0) continue; if(is_array($v['UPLOAD_VALUES']) || is_array($v['NOT_UPLOAD_VALUES']) || $v['FILTER_EXPRESSION']) { $val = $this->worksheet->getCellByColumnAndRow($k, $currentRow); $valOrig = $this->GetCalculatedValue($val); $val = $this->ApplyConversions($valOrig, $v['CONVERSION'], array()); if(is_array($val)) $val = array_map(array('CKDAImportUtils', 'TrimToLower'), $val); else $val = ToLower(trim($val)); } else { $val = ''; } if(is_array($v['UPLOAD_VALUES'])) { $subload = false; foreach($v['UPLOAD_VALUES'] as $needval) { $needval = ToLower($this->Trim($needval)); if($needval==$val || (is_array($val) && in_array($needval, $val)) || ($needval=='{empty}' && ((!is_array($val) && strlen($val)==0) || (is_array($val) && count(array_diff(array_map(array($this, 'Trim'), $val), array('')))==0))) || ($needval=='{not_empty}' && ((!is_array($val) && strlen($val) > 0) || (is_array($val) && count(array_diff(array_map(array($this, 'Trim'), $val), array(''))) > 0)))) { $subload = true; } } $load = ($load && $subload); } if(is_array($v['NOT_UPLOAD_VALUES'])) { $subload = true; foreach($v['NOT_UPLOAD_VALUES'] as $needval) { $needval = ToLower($this->Trim($needval)); if($needval==$val || (is_array($val) && in_array($needval, $val)) || ($needval=='{empty}' && ((!is_array($val) && strlen($val)==0) || (is_array($val) && count(array_diff(array_map(array($this, 'Trim'), $val), array('')))==0))) || ($needval=='{not_empty}' && ((!is_array($val) && strlen($val) > 0) || (is_array($val) && count(array_diff(array_map(array($this, 'Trim'), $val), array(''))) > 0)))) { $subload = false; } } $load = ($load && $subload); } if($v['FILTER_EXPRESSION']) { $load = ($load && $this->ExecuteFilterExpression($valOrig, $v['FILTER_EXPRESSION'])); } } } if(!$load && isset($this->stepparams['currentelement'])) { unset($this->stepparams['currentelement']); } return !$load; } public function ExecuteFilterExpression($val, $expression, $altReturn = true, $arParams = array()) { foreach($arParams as $k=>$v) { ${$k} = $v; } $this->phpExpression = $expression = trim($expression); $ret = ''; try{ if(preg_match('/(^|\n)[\r\t\s]*return/is', $expression)) { $ret = eval($expression.';'); } elseif(preg_match('/\$val\s*=[^=]/', $expression)) { eval($expression.';'); $ret = $val; } else { $ret = eval('return '.$expression.';'); } }catch(Exception $ex){ $ret = $altReturn; } $this->phpExpression = null; return $ret; } public function ExecuteOnAfterSaveHandler($handler, $ID) { try{ eval($handler.';'); }catch(Exception $ex){} } public function GetNextLoadRow($row, $worksheetNum) { $nextRow = $row; if(isset($this->params['LIST_ACTIVE'][$worksheetNum])) { while($this->CheckSkipLine($nextRow, $worksheetNum, false)) { $nextRow++; if($nextRow - $row > 30000) { return $nextRow; } } } return $nextRow; } public function GetNextRecord($time) { if($this->SetFilePosition($this->worksheetCurrentRow + 1, $time)===false) return false; while($this->worksheet && $this->CheckSkipLine($this->worksheetCurrentRow, $this->worksheetNum)) { if($this->CheckTimeEnding($time)) return false; if($this->SetFilePosition($this->worksheetCurrentRow + 1, $time)===false) return false; } if(!$this->worksheet) { return false; } $arItem = array(); $this->hyperlinks = array(); $this->notes = array(); for($column = 0; $column < $this->worksheetColumns; $column++) { $val = $this->worksheet->getCellByColumnAndRow($column, $this->worksheetCurrentRow); $valText = $this->GetCalculatedValue($val); $arItem[$column] = $this->Trim($valText); $arItem['~'.$column] = $valText; if(($htmlVal = $val->getHtmlValue())!==false) $arItem['html_'.$column] = $htmlVal; if($this->params['ELEMENT_NOT_LOAD_STYLES']!='Y' && (!isset($arItem['STYLE']) || ($this->sectioncolumn!==false && $this->sectioncolumn==$column)) && strlen(trim($valText))>0) { $arItem['STYLE'] = md5(CUtil::PhpToJSObject($this->GetCellStyle($val))); } if($this->params['ELEMENT_LOAD_IMAGES']=='Y') { if($this->draws[$val->getCoordinate()]) { $bAddItemVal = (bool)(strlen(trim($arItem[$column]))==0); foreach($this->draws[$val->getCoordinate()] as $draw) { if(is_array($draw) && isset($draw['RENDERING_FUNCTION'])) { $tmpsubdir = $this->imagedir.($this->filecnt++).'/'; CheckDirPath($tmpsubdir); if(call_user_func($draw['RENDERING_FUNCTION'], $draw['IMAGE_RESOURCE'], $tmpsubdir.$draw['FILENAME'])) { $draw = substr($tmpsubdir, strlen($_SERVER["DOCUMENT_ROOT"])).$draw['FILENAME']; } else $draw = ''; } elseif(strpos($draw, '/')===0 && ($ex='exif'.'_read_data'/*bitrix.xscan*/) && function_exists($ex) && ($arExifData = $ex($draw)) && in_array($arExifData['Orientation'], array(3, 6, 8)) && in_array($arExifData['MimeType'], array('image/jpeg', 'image/png'))) { if($arExifData['MimeType']=='image/jpeg') $image = imagecreatefromjpeg($draw); elseif($arExifData['MimeType']=='image/png') $image = imagecreatefrompng($draw); if($arExifData['Orientation']==8) imagerotate($image,90,0); elseif($arExifData['Orientation']==3) imagerotate($image,180,0); elseif($arExifData['Orientation']==6) imagerotate($image,-90,0); if($arExifData['MimeType']=='image/jpeg') imagejpeg($image, $draw, 100); elseif($arExifData['MimeType']=='image/png') imagepng($image, $draw, 9); imagedestroy($image); } if(!isset($arItem['i~'.$column])) $arItem['i~'.$column] = $draw; if($bAddItemVal) { $arItem[$column] .= $draw.$this->params['ELEMENT_MULTIPLE_SEPARATOR']; $arItem['~'.$column] .= $draw.$this->params['ELEMENT_MULTIPLE_SEPARATOR']; } } } } if($this->useHyperlinks) { $this->hyperlinks[$column] = self::CorrectCalculatedValue($val->getHyperlink()->getUrl()); if(!$this->hyperlinks[$column] && ($sourceVal = $val->getValue()) && preg_match('/^=HYPERLINK\("([^"]+)"/', $sourceVal, $m)) $this->hyperlinks[$column] = $m[1]; } if($this->useNotes) { $comment = $this->worksheet->getCommentByColumnAndRow($column, $this->worksheetCurrentRow); if($comment->getImage()) $note = $comment->getImage(); elseif(is_object($comment->getText())) $note = $comment->getText()->getPlainText(); $this->notes[$column] = $note; } } $this->worksheetNumForSave = $this->worksheetNum; return $arItem; } public function SaveRecord($arItem) { if($this->hintsRow!==false && $this->hintsRow==$this->worksheetCurrentRow - 1) { return $this->SavePropertiesHints($arItem); } $saveReadRecord = (bool)(!isset($this->stepparams['lastoffergenkey'])); if($saveReadRecord) $this->stepparams['total_read_line']++; if(count(array_diff(array_map('trim', $arItem), array('')))==0) { $this->skipRows++; if($this->params['ADDITIONAL_SETTINGS'][$this->worksheetNum]['BREAK_LOADING']=='Y' || ($this->skipRows>=$this->maxReadRows - 1)) { $this->breakWorksheet = true; } return false; } if($saveReadRecord) { $this->stepparams['total_line']++; $this->stepparams['total_line_by_list'][$this->worksheetNum]++; } $filedList = $this->params['FIELDS_LIST'][$this->worksheetNumForSave]; $IBLOCK_ID = $this->params['IBLOCK_ID'][$this->worksheetNumForSave]; $SECTION_ID = $this->params['SECTION_ID'][$this->worksheetNumForSave]; $propsDef = $this->GetIblockProperties($IBLOCK_ID); if($arItem['STYLE']) { if(isset($this->sectionstyles[$arItem['STYLE']])) { if($this->SetSectionSeparate($arItem, $IBLOCK_ID, $SECTION_ID, $this->sectionstyles[$arItem['STYLE']])) $this->stepparams['correct_line']++; else { $this->Err(sprintf(Loc::getMessage("KDA_IE_NOT_SAVE_SECTION_SEPARATE"), $this->worksheetNumForSave+1, $this->worksheetCurrentRow)); } return false; } elseif(isset($this->propertystyles[$arItem['STYLE']])) { $propId = $this->propertystyles[$arItem['STYLE']]; $propVal = $this->GetStyleCellValue($arItem, 'P'.$propId); if(!isset($this->stepparams['sepproperties'])) $this->stepparams['sepproperties'] = array(); if(!isset($this->stepparams['seppropertiesOrig'])) $this->stepparams['seppropertiesOrig'] = array(); //$this->stepparams['sepproperties'][$propId] = $propVal; if(isset($this->stepparams['sepproperties'][$propId])) unset($this->stepparams['sepproperties'][$propId]); $propSettings = (isset($this->fieldSettingsExtra['__P'.$propId]) ? $this->fieldSettingsExtra['__P'.$propId] : array()); $this->GetPropField($this->stepparams['sepproperties'], $this->stepparams['seppropertiesOrig'], $propSettings, $propsDef[$propId], $propId, $propVal, $propVal, $this->params['CURRENT_ELEMENT_UID']); $this->skipSepProp = $this->UniCheckSkipLine($propVal, $propSettings); $this->stepparams['correct_line']++; return false; } } if((!empty($this->sectionstyles) && $this->skipSepSection===true) || (!empty($this->propertystyles) && $this->skipSepProp===true)) return false; $arFieldsDef = $this->fl->GetFields($IBLOCK_ID); $iblockFields = $this->GetIblockFields($IBLOCK_ID); $this->currentItemValues = $arItem; $arFieldsElement = array(); $arFieldsElementOrig = array(); $arFieldsPrices = array(); $arFieldsProduct = array(); $arFieldsProductStores = array(); $arFieldsProductDiscount = array(); $arFieldsProps = array(); $arFieldsPropsOrig = array(); $arFieldsSections = array(); $arFieldsIpropTemp = array(); if(isset($this->stepparams['sepproperties']) && is_array($this->stepparams['sepproperties'])) $arFieldsProps = $arFieldsPropsOrig = $this->stepparams['sepproperties']; foreach($filedList as $key=>$field) { $k = $key; if(strpos($k, '_')!==false) $k = substr($k, 0, strpos($k, '_')); $value = $arItem[$k]; if($this->fieldSettings[$field]['NOT_TRIM']=='Y') $value = $arItem['~'.$k]; if($this->fieldSettings[$field]['EXCEL_STYLES_TO_HTML']=='Y') $value = $arItem['html_'.$k]; $origValue = $arItem['~'.$k]; $conversions = (isset($this->fieldSettingsExtra[$key]) ? $this->fieldSettingsExtra[$key]['CONVERSION'] : $this->fieldSettings[$field]['CONVERSION']); if(!empty($conversions)) { $eqValues = (bool)($value===$origValue); $value = $this->ApplyConversions($value, $conversions, $arItem, array('KEY'=>$k, 'NAME'=>$field), $iblockFields); if($eqValues) $origValue = $value; else $origValue = $this->ApplyConversions($origValue, $conversions, $arItem, array('KEY'=>$k, 'NAME'=>$field), $iblockFields); if($value===false) continue; } if(strpos($field, 'IE_')===0) { $fieldKey = substr($field, 3); if($fieldKey=='SECTION_PATH') { $tmpSep = $this->GetSeparator($this->fieldSettingsExtra[$key]['SECTION_PATH_SEPARATOR'] ? $this->fieldSettingsExtra[$key]['SECTION_PATH_SEPARATOR'] : '/'); if($this->fieldSettingsExtra[$key]['SECTION_PATH_SEPARATED']=='Y') $arVals = explode($this->params['ELEMENT_MULTIPLE_SEPARATOR'], $value); else $arVals = array($value); foreach($arVals as $subvalue) { $tmpVal = array_map('trim', explode($tmpSep, $subvalue)); $arFieldsElement[$fieldKey][] = $tmpVal; $arFieldsElementOrig[$fieldKey][] = $tmpVal; } } elseif($this->params['ELEMENT_LOAD_IMAGES']=='Y' && in_array($fieldKey, array('DETAIL_PICTURE', 'PREVIEW_PICTURE')) && isset($arItem['i~'.$k])) { $arFieldsElement[$fieldKey] = $arItem['i~'.$k]; $arFieldsElementOrig[$fieldKey] = $arItem['i~'.$k]; } else { if(strpos($fieldKey, '|')!==false) { list($fieldKey, $adata) = explode('|', $fieldKey); $adata = explode('=', $adata); if(count($adata) > 1) { $arFieldsElement[$adata[0]] = $adata[1]; } } if(isset($arFieldsElement[$fieldKey]) && in_array($field, $this->params['CURRENT_ELEMENT_UID'])) { if(!is_array($arFieldsElement[$fieldKey])) { $arFieldsElement[$fieldKey] = array($arFieldsElement[$fieldKey]); $arFieldsElementOrig[$fieldKey] = array($arFieldsElementOrig[$fieldKey]); } $arFieldsElement[$fieldKey][] = $value; $arFieldsElementOrig[$fieldKey][] = $origValue; } else { $arFieldsElement[$fieldKey] = $value; $arFieldsElementOrig[$fieldKey] = $origValue; } } } elseif(strpos($field, 'ISECT')===0) { $adata = false; if(strpos($field, '|')!==false) { list($field, $adata) = explode('|', $field); $adata = explode('=', $adata); } $arSect = explode('_', substr($field, 5), 2); if(strlen($arSect[0])==0) $arSect[0] = 0; $arFieldsSections[$arSect[0]][$arSect[1]] = $value; if(is_array($adata) && count($adata) > 1) { $arFieldsSections[$arSect[0]][$adata[0]] = $adata[1]; } } elseif(strpos($field, 'ICAT_PRICE')===0) { $val = $value; if(substr($field, -6)=='_PRICE') { if(!in_array($val, array('', '-'))) { //$val = $this->GetFloatVal($val); $val = $this->ApplyMargins($val, $this->fieldSettingsExtra[$key]); } } elseif(substr($field, -6)=='_EXTRA') { $val = $this->GetFloatVal($val, 0, true); } $arPrice = explode('_', substr($field, 10), 2); $pkey = $arPrice[1]; if($pkey=='PRICE' && $this->fieldSettingsExtra[$key]['PRICE_USE_EXT']=='Y') { $pkey = $pkey.'|QUANTITY_FROM='.$this->CalcFloatValue($this->fieldSettingsExtra[$key]['PRICE_QUANTITY_FROM']).'|QUANTITY_TO='.$this->CalcFloatValue($this->fieldSettingsExtra[$key]['PRICE_QUANTITY_TO']); } $arFieldsPrices[$arPrice[0]][$pkey] = $val; } elseif(strpos($field, 'ICAT_LIST_STORES')===0) { $this->GetStoreAmountList($arFieldsProductStores, $this->fieldSettingsExtra[$key], $value); } elseif(strpos($field, 'ICAT_STORE')===0) { $arStore = explode('_', substr($field, 10), 2); $arFieldsProductStores[$arStore[0]][$arStore[1]] = $value; } elseif(strpos($field, 'ICAT_DISCOUNT_')===0) { if(strpos($field, 'ICAT_DISCOUNT_VALUE')===0 && in_array(trim($value), array('', '0')) && isset($arFieldsProductDiscount['VALUE'])) continue; if(strpos($field, '|')!==false) { list($field, $adata) = explode('|', $field); $adata = explode('=', $adata); if(count($adata) > 1) { $arFieldsProductDiscount[$adata[0]] = $adata[1]; } } $field = substr($field, 14); if($field=='VALUE' && isset($this->fieldSettingsExtra[$key])) { $fse = $this->fieldSettingsExtra[$key]; if(!empty($fse['CATALOG_GROUP_IDS'])) { $arFieldsProductDiscount['CATALOG_GROUP_IDS'] = $fse['CATALOG_GROUP_IDS']; } if(is_array($fse['SITE_IDS']) && !empty($fse['SITE_IDS'])) { foreach($fse['SITE_IDS'] as $siteId) { $arFieldsProductDiscount['LID_VALUES'][$siteId] = array('VALUE'=>$value); if(isset($arFieldsProductDiscount['VALUE_TYPE'])) $arFieldsProductDiscount['LID_VALUES'][$siteId]['VALUE_TYPE'] = $arFieldsProductDiscount['VALUE_TYPE']; } } } $arFieldsProductDiscount[$field] = $value; } elseif(strpos($field, 'ICAT_')===0) { $val = $value; if($field=='ICAT_PURCHASING_PRICE') { if($val=='') continue; $val = $this->GetFloatVal($val); } $arFieldsProduct[substr($field, 5)] = $val; } elseif(strpos($field, 'IP_PROP')===0) { $fieldName = substr($field, 7); if(substr($fieldName, -12)=='_DESCRIPTION') $currentPropDef = $propsDef[substr($fieldName, 0, -12)]; else $currentPropDef = $propsDef[$fieldName]; $this->GetPropField($arFieldsProps, $arFieldsPropsOrig, $this->fieldSettingsExtra[$key], $currentPropDef, $fieldName, $value, $origValue, $this->params['CURRENT_ELEMENT_UID']); } elseif(strpos($field, 'IP_LIST_PROPS')===0) { $this->GetPropList($arFieldsProps, $arFieldsPropsOrig, $this->fieldSettingsExtra[$key], $IBLOCK_ID, $value); } elseif(strpos($field, 'IPROP_TEMP_')===0) { $fieldName = substr($field, 11); $arFieldsIpropTemp[$fieldName] = $value; } } $arUid = $this->GetFilterUids($arFieldsElement, $arFieldsElementOrig, $arFieldsProps, $arFieldsPropsOrig, $IBLOCK_ID); $emptyFields = array(); foreach($arUid as $k=>$v) { if((is_array($v['valUid']) && count(array_diff(array_map(array($this, 'Trim'), $v['valUid']), array('')))==0) || (!is_array($v['valUid']) && strlen($this->Trim($v['valUid']))==0)) $emptyFields[] = $v['nameUid']; } if(!empty($emptyFields) || empty($arUid)) { $bEmptyElemFields = (bool)(count(array_diff($arFieldsElement, array('')))==0 && count(array_diff($arFieldsProps, array('')))==0); $res = false; if((empty($arUid) || count($emptyFields)==count($arUid)) && ($this->params['ONLY_DELETE_MODE']!='Y')) { /*If empty element try save SKU*/ if($this->params['CURRENT_ELEMENT_UID_SKU'] && !empty($this->stepparams['currentelement'])) { $arFieldsElementSKU = $this->stepparams['currentelement']; $res = $this->SaveSKUWithGenerate($arFieldsElementSKU['ID'], $arFieldsElementSKU['NAME'], $IBLOCK_ID, $arItem); if($res==='timesup') return false; } /*/If empty element try save SKU*/ /*Maybe additional sections*/ $arElementNEFields = array_diff($arFieldsElement, array('')); $arElementNEFieldsKeys = array_diff(array_keys($arElementNEFields), array('SECTION_PATH', 'DETAIL_TEXT_TYPE', 'PREVIEW_TEXT_TYPE')); if(!$res && !empty($arFieldsSections) && count($arElementNEFieldsKeys)==0) { $isElement = !empty($this->stepparams['currentelement']); if($this->params['ELEMENT_NOT_CHANGE_SECTIONS']!='Y' || !$isElement) { $this->GetSections($arFieldsElement, $IBLOCK_ID, $SECTION_ID, $arFieldsSections); if($isElement && is_array($arFieldsElement['IBLOCK_SECTION']) && !empty($arFieldsElement['IBLOCK_SECTION'])) { $arTmpElem = $this->stepparams['currentelement']; if(!is_array($arTmpElem['IBLOCK_SECTION'])) $arTmpElem['IBLOCK_SECTION'] = array(); $arNewSect = array_diff($arFieldsElement['IBLOCK_SECTION'], $arTmpElem['IBLOCK_SECTION']); if(count($arNewSect) > 0) { $arTmpElem['IBLOCK_SECTION'] = array_merge($arTmpElem['IBLOCK_SECTION'], $arNewSect); if($this->params['ONLY_CREATE_MODE_PRODUCT']!='Y') { $el = new CIblockElement(); $el->Update($arTmpElem['ID'], array( 'IBLOCK_SECTION' => $arTmpElem['IBLOCK_SECTION'], 'IBLOCK_SECTION_ID' => current($arTmpElem['IBLOCK_SECTION']) ), false, true, true); $this->AddTagIblock($IBLOCK_ID); } } $this->stepparams['currentelement'] = $arTmpElem; } } $res = true; } /*/Maybe additional sections*/ } //$res = (bool)($res && $bEmptyElemFields); $res = (bool)($res); if(!$res) { $this->Err(sprintf(Loc::getMessage("KDA_IE_NOT_SET_FIELD"), implode(', ', $emptyFields), $this->worksheetNumForSave+1, $this->worksheetCurrentRow)); } else { $this->stepparams['correct_line']++; } $this->SaveStatusImport(); return false; } $arDates = array('ACTIVE_FROM', 'ACTIVE_TO', 'DATE_CREATE'); foreach($arDates as $keyDate) { if(isset($arFieldsElement[$keyDate]) && strlen($arFieldsElement[$keyDate]) > 0) { $arFieldsElement[$keyDate] = $this->GetDateVal($arFieldsElement[$keyDate]); } } if(isset($arFieldsElement['ACTIVE'])) { $arFieldsElement['ACTIVE'] = $this->GetBoolValue($arFieldsElement['ACTIVE']); } elseif($this->params['ELEMENT_LOADING_ACTIVATE']=='Y') { $arFieldsElement['ACTIVE'] = 'Y'; } $arKeys = array_merge(array('ID', 'NAME', 'IBLOCK_SECTION_ID', 'MODIFIED_BY', 'PREVIEW_PICTURE', 'DETAIL_PICTURE'), array_keys($arFieldsElement)); $arFilter = array('IBLOCK_ID'=>$IBLOCK_ID, 'CHECK_PERMISSIONS' => 'N'); foreach($arUid as $v) { if(!$v['substring']) { if(is_array($v['valUid'])) { $arSubfilter = $v['valUid']; if(is_array($v['valUid2'])) $arSubfilter = array_unique(array_merge($arSubfilter, $v['valUid2'])); elseif(strlen($v['valUid2']) > 0) $arSubfilter[] = $v['valUid2']; } else { $arSubfilter = array($this->Trim($v['valUid'])); if($this->Trim($v['valUid']) != $v['valUid2']) { $arSubfilter[] = $this->Trim($v['valUid2']); if(strlen($v['valUid2']) != strlen($this->Trim($v['valUid2']))) { $arSubfilter[] = $v['valUid2']; } } if(strlen($v['valUid'])!=strlen($this->Trim($v['valUid']))) $arSubfilter[] = $v['valUid']; if((!defined('BX_UTF') || !BX_UTF) && strpos($v['valUid'], "\xA0")!==false) $arSubfilter[] = str_replace("\xA0", ' ', $v['valUid']); } if(count($arSubfilter) == 1) { $arSubfilter = $arSubfilter[0]; } $arFilter['='.$v['uid']] = $arSubfilter; } else { if(is_array($v['valUid'])) $v['valUid'] = array_map(array($this, 'Trim'), $v['valUid']); else $v['valUid'] = $this->Trim($v['valUid']); if($v['substring']=='B') $arFilter[$v['uid']] = (is_array($v['valUid']) ? array_map(array('CKDAImportUtils', 'GetFilterBeginWith'), $v['valUid']) : $v['valUid'].'%'); elseif($v['substring']=='E') $arFilter[$v['uid']] = (is_array($v['valUid']) ? array_map(array('CKDAImportUtils', 'GetFilterEndOn'), $v['valUid']) : '%'.$v['valUid']); else $arFilter['%'.$v['uid']] = $v['valUid']; } } if(!empty($arFieldsIpropTemp)) { $arFieldsElement['IPROPERTY_TEMPLATES'] = $arFieldsIpropTemp; } if($this->searchSections!==false) { $arFilter['SECTION_ID'] = $this->searchSections; $arFilter['INCLUDE_SUBSECTIONS'] = 'Y'; } $allowCreate = (bool)($this->params['ONLY_DELETE_MODE']!='Y'); if($allowCreate && $this->params['SEARCH_OFFERS_WO_PRODUCTS']=='Y') { $res = $this->SaveSKUWithGenerate(0, '', $IBLOCK_ID, $arItem); if($res==='timesup') return false; if($res===true) $allowCreate = false; } $duplicate = false; //$dbRes = CIblockElement::GetList(array(), $arFilter, false, false, $arKeys); $dbRes = \Bitrix\KdaImportexcel\DataManager\IblockElementTable::GetListComp($arFilter, $arKeys); while($arElement = $dbRes->Fetch()) { $elemName = $arElement['NAME']; if($this->params['ONLY_DELETE_MODE']=='Y') { $ID = $arElement['ID']; $this->DeleteElement($ID, $IBLOCK_ID); $this->stepparams['element_removed_line']++; unset($ID); continue; } $updated = false; $ID = $arElement['ID']; $arFieldsProps2 = $arFieldsProps; $arFieldsElement2 = $arFieldsElement; $arFieldsSections2 = $arFieldsSections; $arFieldsProduct2 = $arFieldsProduct; $arFieldsPrices2 = $arFieldsPrices; $arFieldsProductStores2 = $arFieldsProductStores; $arFieldsProductDiscount2 = $arFieldsProductDiscount; if($this->conv->SetElementId($ID, $duplicate) && $this->conv->UpdateProperties($arFieldsProps2, $ID)!==false && $this->conv->UpdateElementFields($arFieldsElement2, $ID)!==false && $this->conv->UpdateSectionFields($arFieldsSections2, $ID)!==false && $this->conv->UpdateProduct($arFieldsProduct2, $arFieldsPrices2, $arFieldsProductStores2, $ID)!==false && $this->conv->UpdateDiscountFields($arFieldsProductDiscount2, $ID)!==false && $this->conv->SetElementId(0)) { $this->BeforeElementSave($ID, 'update'); if($this->params['ONLY_CREATE_MODE_PRODUCT']!='Y') { $this->UnsetUidFields($arFieldsElement2, $arFieldsProps2, $this->params['CURRENT_ELEMENT_UID']); if(!empty($this->fieldOnlyNew)) { $this->UnsetExcessSectionFields($this->fieldOnlyNew, $arFieldsSections2, $arFieldsElement2); } $arElementSections = false; if($this->params['ELEMENT_ADD_NEW_SECTIONS']=='Y' && !isset($arFieldsElement2['IBLOCK_SECTION'])) { $arElementSections = $this->GetElementSections($ID, $arElement['IBLOCK_SECTION_ID']); $arFieldsElement2['IBLOCK_SECTION'] = $arElementSections; } $this->GetSections($arFieldsElement2, $IBLOCK_ID, $SECTION_ID, $arFieldsSections2); if($this->params['NOT_LOAD_ELEMENTS_WO_SECTION']=='Y' && (!isset($arFieldsElement2['IBLOCK_SECTION']) || empty($arFieldsElement2['IBLOCK_SECTION']))) continue; foreach($arElement as $k=>$v) { $action = $this->fieldSettings['IE_'.$k]['LOADING_MODE']; if($action) { if($action=='ADD_BEFORE') $arFieldsElement2[$k] = $arFieldsElement2[$k].$v; elseif($action=='ADD_AFTER') $arFieldsElement2[$k] = $v.$arFieldsElement2[$k]; } } if(!empty($this->fieldOnlyNew)) { $this->UnsetExcessFields($this->fieldOnlyNew, $arFieldsElement2, $arFieldsProps2, $arFieldsProduct2, $arFieldsPrices2, $arFieldsProductStores2, $arFieldsProductDiscount2); } $this->RemoveProperties($ID, $IBLOCK_ID); $this->SaveProperties($ID, $IBLOCK_ID, $arFieldsProps2); $this->SaveProduct($ID, $IBLOCK_ID, $arFieldsProduct2, $arFieldsPrices2, $arFieldsProductStores2); $this->AfterSaveProduct($arFieldsElement2, $ID, $IBLOCK_ID, true); if($this->CheckRequiredProps($arFieldsProps2, $IBLOCK_ID, $ID) && $this->UpdateElement($ID, $IBLOCK_ID, $arFieldsElement2, $arElement, $arElementSections)) { //$this->SetTimeBegin($ID); } else { $this->Err(sprintf(Loc::getMessage("KDA_IE_UPDATE_ELEMENT_ERROR"), $this->GetLastError(), $this->worksheetNumForSave+1, $this->worksheetCurrentRow, $ID)); } $this->SaveDiscount($ID, $IBLOCK_ID, $arFieldsProductDiscount2, $elemName); $updated = true; } } $isChanges = $this->IsChangedElement(); if($this->SaveElementId($ID) && $updated) { $this->stepparams['element_updated_line']++; if($isChanges) $this->stepparams['element_changed_line']++; } if($elemName && !$arFieldsElement2['NAME']) $arFieldsElement2['NAME'] = $elemName; if($this->SaveRecordAfter($ID, $IBLOCK_ID, $arItem, $arFieldsElement2, $allowCreate, $isChanges)===false) return false; $duplicate = true; } $allowCreate = (bool)($allowCreate && \Bitrix\KdaImportexcel\DataManager\IblockElementTable::SelectedRowsCountComp($dbRes)==0); if($allowCreate) { if($this->params['ONLY_UPDATE_MODE_PRODUCT']!='Y') { $this->UnsetUidFields($arFieldsElement, $arFieldsProps, $this->params['CURRENT_ELEMENT_UID'], true); if(!$this->CheckIdForNewElement($arFieldsElement)) return false; if($this->params['ELEMENT_NEW_DEACTIVATE']=='Y') { $arFieldsElement['ACTIVE'] = 'N'; } elseif(!$arFieldsElement['ACTIVE']) { $arFieldsElement['ACTIVE'] = 'Y'; } $arFieldsElement['IBLOCK_ID'] = $IBLOCK_ID; $this->GetSections($arFieldsElement, $IBLOCK_ID, $SECTION_ID, $arFieldsSections); if($this->params['NOT_LOAD_ELEMENTS_WO_SECTION']=='Y' && (!isset($arFieldsElement['IBLOCK_SECTION']) || empty($arFieldsElement['IBLOCK_SECTION']))) return false; $this->GetDefaultElementFields($arFieldsElement, $iblockFields); if($this->CheckRequiredProps($arFieldsProps, $IBLOCK_ID) && ($ID = $this->AddElement($arFieldsElement))) { $this->AddTagIblock($IBLOCK_ID); $this->BeforeElementSave($ID, 'add'); $this->logger->AddElementChanges('IE_', $arFieldsElement); //$this->SetTimeBegin($ID); $this->SaveProperties($ID, $IBLOCK_ID, $arFieldsProps, true, $arFieldsElement); $this->PrepareProductAdd($arFieldsProduct, $ID, $IBLOCK_ID); $this->SaveProduct($ID, $IBLOCK_ID, $arFieldsProduct, $arFieldsPrices, $arFieldsProductStores); $this->AfterSaveProduct($arFieldsElement, $ID, $IBLOCK_ID); $this->SaveDiscount($ID, $IBLOCK_ID, $arFieldsProductDiscount, $arFieldsElement['NAME']); $this->AfterElementAdd($IBLOCK_ID, $ID); if($this->SaveElementId($ID)) $this->stepparams['element_added_line']++; if($this->SaveRecordAfter($ID, $IBLOCK_ID, $arItem, $arFieldsElement)===false) return false; } else { $this->Err(sprintf(Loc::getMessage("KDA_IE_ADD_ELEMENT_ERROR"), $this->GetLastError(), $this->worksheetNumForSave+1, $this->worksheetCurrentRow)); return false; } } else { $this->logger->AddElementMassChanges($arFieldsElement, $arFieldsProps, $arFieldsProduct, $arFieldsProductStores, $arFieldsPrices); $this->logger->SaveElementNotFound($arFilter, $this->worksheetCurrentRow); } } $this->stepparams['correct_line']++; $this->SaveStatusImport(); $this->RemoveTmpImageDirs(); } public function SaveRecordAfter($ID, $IBLOCK_ID, $arItem, $arFieldsElement, $saveOffers=true, $isChanges=true) { if(!$ID) return true; /*Maybe additional sections*/ if($this->params['ELEMENT_NOT_CHANGE_SECTIONS']!='Y') { $arTmpElem = $this->stepparams['currentelement']; if(!empty($arTmpElem) && $arTmpElem['ID']==$ID && is_array($arTmpElem['IBLOCK_SECTION']) && !empty($arTmpElem['IBLOCK_SECTION']) && is_array($arFieldsElement['IBLOCK_SECTION']) && count(array_diff($arTmpElem['IBLOCK_SECTION'], $arFieldsElement['IBLOCK_SECTION'])) > 0) { $arFieldsElement['IBLOCK_SECTION'] = array_merge($arTmpElem['IBLOCK_SECTION'], $arFieldsElement['IBLOCK_SECTION']); if($this->params['ONLY_CREATE_MODE_PRODUCT']!='Y') { $el = new CIblockElement(); $el->Update($ID, array('IBLOCK_SECTION'=>$arFieldsElement['IBLOCK_SECTION']), false, true, true); $this->AddTagIblock($IBLOCK_ID); } } } /*/Maybe additional sections*/ $arFieldsElement['ID'] = $ID; $this->stepparams['currentelement'] = $arFieldsElement; $this->stepparams['currentelementitem'] = $arItem; if($saveOffers && $this->params['CURRENT_ELEMENT_UID_SKU']) { $res = $this->SaveSKUWithGenerate($ID, $arFieldsElement['NAME'], $IBLOCK_ID, $arItem); if($res==='timesup') return false; } $this->OnAfterSaveElement($ID, $isChanges); return true; } public function OnAfterSaveElement($ID, $isChanges=true) { if($this->params['ONAFTERSAVE_HANDLER']) { $this->ExecuteOnAfterSaveHandler($this->params['ONAFTERSAVE_HANDLER'], $ID); } if($this->params['REMOVE_COMPOSITE_CACHE_PART']=='Y' && $isChanges) { if($arElement = \CIblockElement::GetList(array(), array('ID'=>$ID, 'CHECK_PERMISSIONS' => 'N'), false, false, array('DETAIL_PAGE_URL'))->GetNext()) { $this->ClearCompositeCache($arElement['DETAIL_PAGE_URL']); } } } public function CheckIdForNewElement(&$arFieldsElement, $isOffer=false) { if(isset($arFieldsElement['ID'])) { $ID = trim($arFieldsElement['ID']); $maxVal = 2147483647; $error = false; if(!class_exists('\Bitrix\Iblock\ElementTable')) $error = ''; if($error===false && !preg_match('/^[1-9]\d*$/', $ID)) $error = Loc::getMessage("KDA_IE_ERROR_FORMAT_ID"); if($error===false && $ID > $maxVal) $error = sprintf(Loc::getMessage("KDA_IE_ERROR_OUTOFRANGE_ID"), $maxVal); if($error===false && \Bitrix\Iblock\ElementTable::getList(array('filter'=>array('ID'=>$ID), 'select'=>array('ID')))->Fetch()) $error = Loc::getMessage("KDA_IE_ERROR_EXISTING_ID"); if($error!==false) { $this->Err(sprintf(($isOffer ? Loc::getMessage("KDA_IE_NEW_OFFER_WITH_ID") : Loc::getMessage("KDA_IE_NEW_ELEMENT_WITH_ID")), $arFieldsElement['ID'], $error, $this->worksheetNumForSave+1, $this->worksheetCurrentRow)); return false; } $arFieldsElement['TMP_ID'] = md5($ID); while(\Bitrix\Iblock\ElementTable::getList(array('filter'=>array('TMP_ID'=>$arFieldsElement['TMP_ID']), 'select'=>array('ID')))->Fetch()) { $arFieldsElement['TMP_ID'] = md5($ID.'_'.mt_rand()); } } return true; } public function AddElement($arFieldsElement, $isOffer=false) { $this->PrepareElementPictures($arFieldsElement, $arFieldsElement['IBLOCK_ID'], array(), $isOffer); $arProps = $this->GetIblockDefaultProperties($arFieldsElement['IBLOCK_ID']); $arProps = (array_key_exists('PROPERTY_VALUES', $arFieldsElement) ? $arFieldsElement['PROPERTY_VALUES'] : array()) + $arProps; if(!empty($arProps)) $arFieldsElement['PROPERTY_VALUES'] = $arProps; //$el = new CIblockElement(); //$ID = $el->Add($arFieldsElement, false, true, false); $ID = $this->el->AddComp($arFieldsElement, false, true, false); if($ID) { if(isset($arFieldsElement['ID']) && isset($arFieldsElement['TMP_ID'])) { $el = new CIblockElement(); $isProps = (bool)(isset($arFieldsElement['PROPERTY_VALUES']) && !empty($arFieldsElement['PROPERTY_VALUES'])); $isSections = (bool)(isset($arFieldsElement['IBLOCK_SECTION']) && !empty($arFieldsElement['IBLOCK_SECTION'])); if($isProps) { $emptyProps = array(); foreach($arFieldsElement['PROPERTY_VALUES'] as $pk=>$pv) { $emptyProps[$pk] = false; } \CIBlockElement::SetPropertyValuesEx($ID, $arFieldsElement['IBLOCK_ID'], $emptyProps); } if($isSections) $el->Update($ID, array('IBLOCK_SECTION'=>false), false, true, true); $arElemFields = array('ID'=>$arFieldsElement['ID']); if(!isset($arFieldsElement['XML_ID'])) $arElemFields['XML_ID'] = $arFieldsElement['ID']; if(\Bitrix\KdaImportexcel\DataManager\IblockElementIdTable::update($arFieldsElement['TMP_ID'], $arElemFields)) { \Bitrix\KdaImportexcel\DataManager\IblockElementIdTable::RemoveV2Props($ID, $arFieldsElement['IBLOCK_ID']); \CIBlockElement::UpdateSearch($ID, true); $ID = $arFieldsElement['ID']; } if($isProps) \CIBlockElement::SetPropertyValuesEx($ID, $arFieldsElement['IBLOCK_ID'], $arFieldsElement['PROPERTY_VALUES']); $arUFields = array(); if($isSections) $arUFields['IBLOCK_SECTION'] = $arFieldsElement['IBLOCK_SECTION']; if($arFieldsElement['IPROPERTY_TEMPLATES']) $arUFields['IPROPERTY_TEMPLATES'] = $arFieldsElement['IPROPERTY_TEMPLATES']; if(!empty($arUFields)) $el->Update($ID, $arUFields, false, true, true); } } else { $this->SetLastError($this->el->LAST_ERROR); return false; } return $ID; } public function UpdateElement($ID, $IBLOCK_ID, $arFieldsElement, $arElement=array(), $arElementSections=array(), $isOffer=false) { if(!empty($arFieldsElement)) { $this->PrepareElementPictures($arFieldsElement, $IBLOCK_ID, $arElement, $isOffer); if($this->params['ELEMENT_NOT_CHANGE_SECTIONS']=='Y') { unset($arFieldsElement['IBLOCK_SECTION'], $arFieldsElement['IBLOCK_SECTION_ID']); } elseif(!isset($arFieldsElement['IBLOCK_SECTION_ID']) && isset($arFieldsElement['IBLOCK_SECTION']) && is_array($arFieldsElement['IBLOCK_SECTION']) && count($arFieldsElement['IBLOCK_SECTION']) > 0) { reset($arFieldsElement['IBLOCK_SECTION']); $arFieldsElement['IBLOCK_SECTION_ID'] = current($arFieldsElement['IBLOCK_SECTION']); } if(array_key_exists('IBLOCK_SECTION', $arFieldsElement)) { if(!is_array($arElementSections)) $arElementSections = $this->GetElementSections($ID, $arElement['IBLOCK_SECTION_ID'], false); $arElement['IBLOCK_SECTION'] = $arElementSections; } if($this->params['ELEMENT_IMAGES_FORCE_UPDATE']!='Y') { foreach($arFieldsElement as $k=>$v) { if($k=='IBLOCK_SECTION' && is_array($v)) { if(count($v)==count($arElementSections) && count(array_diff($v, $arElementSections))==0 && (!isset($arFieldsElement['IBLOCK_SECTION_ID']) || $arFieldsElement['IBLOCK_SECTION_ID']==$arElement['IBLOCK_SECTION_ID'])) { unset($arFieldsElement[$k]); unset($arFieldsElement['IBLOCK_SECTION_ID']); } } elseif($k=='PREVIEW_PICTURE' || $k=='DETAIL_PICTURE') { if(!$this->IsChangedImage($arElement[$k], $arFieldsElement[$k])) { unset($arFieldsElement[$k]); } elseif(empty($arFieldsElement[$k])) { unset($arFieldsElement[$k]); } } elseif($v==$arElement[$k]) { unset($arFieldsElement[$k]); } } } if(isset($arFieldsElement['IBLOCK_SECTION']) && is_array($arFieldsElement['IBLOCK_SECTION']) && count($arFieldsElement['IBLOCK_SECTION']) > 0 && !isset($arFieldsElement['IBLOCK_SECTION_ID'])) { reset($arFieldsElement['IBLOCK_SECTION']); $arFieldsElement['IBLOCK_SECTION_ID'] = current($arFieldsElement['IBLOCK_SECTION']); } if(isset($arFieldsElement['DETAIL_PICTURE']) && is_array($arFieldsElement['DETAIL_PICTURE']) && empty($arFieldsElement['DETAIL_PICTURE'])) unset($arFieldsElement['DETAIL_PICTURE']); if(isset($arFieldsElement['DETAIL_PICTURE'])) { if(is_array($arFieldsElement['DETAIL_PICTURE']) && (!isset($arFieldsElement['PREVIEW_PICTURE']) || !is_array($arFieldsElement['PREVIEW_PICTURE']))) $arFieldsElement['PREVIEW_PICTURE'] = array(); } elseif(isset($arFieldsElement['PREVIEW_PICTURE']) && is_array($arFieldsElement['PREVIEW_PICTURE']) && empty($arFieldsElement['PREVIEW_PICTURE'])) unset($arFieldsElement['PREVIEW_PICTURE']); if($arFieldsElement['IPROPERTY_TEMPLATES']) { $ipropValues = new \Bitrix\Iblock\InheritedProperty\ElementValues($IBLOCK_ID, $ID); $arValues = $ipropValues->queryValues(); $arElement['IPROPERTY_TEMPLATES'] = array(); foreach($arValues as $k=>$v) { $arElement['IPROPERTY_TEMPLATES'][$k] = ($v['ENTITY_TYPE']=='E' ? $v['VALUE'] : ''); } if($this->params['ELEMENT_IMAGES_FORCE_UPDATE']!='Y') { foreach($arFieldsElement['IPROPERTY_TEMPLATES'] as $k=>$v) { if($v==$arElement['IPROPERTY_TEMPLATES'][$k]) { unset($arFieldsElement['IPROPERTY_TEMPLATES'][$k]); } } if(count($arFieldsElement['IPROPERTY_TEMPLATES'])==0) unset($arFieldsElement['IPROPERTY_TEMPLATES']); } } } if(empty($arFieldsElement) && $this->params['ELEMENT_NOT_UPDATE_WO_CHANGES']=='Y') { if($this->IsChangedElement()) { $this->el->Update($ID, array('TIMESTAMP_X'=>new \Bitrix\Main\Type\DateTime())); \Bitrix\KdaImportexcel\DataManager\InterhitedpropertyValues::ClearElementValues($IBLOCK_ID, $ID); } if($this->IsFacetChanges() && class_exists('\Bitrix\Iblock\PropertyIndex\Manager')) \Bitrix\Iblock\PropertyIndex\Manager::updateElementIndex($IBLOCK_ID, $ID); return true; } //$el = new CIblockElement(); if(!isset($arFieldsElement['MODIFIED_BY']) && $this->GetCurUserID() > 0 && $arElement['MODIFIED_BY']!=$this->GetCurUserID()) $arFieldsElement['MODIFIED_BY'] = $this->GetCurUserID(); if($this->el->UpdateComp($ID, $arFieldsElement, false, true, false)) { $this->AddTagIblock($IBLOCK_ID); $this->logger->AddElementChanges('IE_', $arFieldsElement, $arElement); \Bitrix\KdaImportexcel\DataManager\InterhitedpropertyValues::ClearElementValues($IBLOCK_ID, $ID); return true; } else { $this->SetLastError($this->el->LAST_ERROR); return false; } } public function PrepareElementPictures(&$arFieldsElement, $IBLOCK_ID, $arElement, $isOffer=false) { $iblockFields = $this->GetIblockFields($IBLOCK_ID); if(isset($arFieldsElement['DETAIL_PICTURE']) && isset($iblockFields['PREVIEW_PICTURE']['DEFAULT_VALUE']) && is_array($iblockFields['PREVIEW_PICTURE']['DEFAULT_VALUE'])) { $remove = (bool)((!is_array($arFieldsElement['DETAIL_PICTURE']) && trim($arFieldsElement['DETAIL_PICTURE'])=='-') || (is_array($arFieldsElement['DETAIL_PICTURE']) && in_array('-', $arFieldsElement['DETAIL_PICTURE']))); if((!$remove && $iblockFields['PREVIEW_PICTURE']['DEFAULT_VALUE']['FROM_DETAIL']=='Y' && (!$arFieldsElement['PREVIEW_PICTURE'] || $iblockFields['PREVIEW_PICTURE']['DEFAULT_VALUE']['UPDATE_WITH_DETAIL']=='Y')) || ($remove && $iblockFields['PREVIEW_PICTURE']['DEFAULT_VALUE']['DELETE_WITH_DETAIL']=='Y' && !$arFieldsElement['PREVIEW_PICTURE'])) { $arFieldsElement['PREVIEW_PICTURE'] = $arFieldsElement['DETAIL_PICTURE']; } } $arPictures = array('PREVIEW_PICTURE', 'DETAIL_PICTURE'); foreach($arPictures as $picName) { if($arFieldsElement[$picName]) { $val = $arFieldsElement[$picName]; $arFileParams = array('FILETYPE'=>'IMAGE', 'PICTURE_PROCESSING'=>isset($iblockFields[$picName]['DEFAULT_VALUE']) ? $iblockFields[$picName]['DEFAULT_VALUE'] : array()); $arFile = $this->GetFileArray($val, $arFileParams, ($isOffer ? 'OFFER_' : '').'IE_'.$picName, $arElement[$picName]); $sep = $this->params['ELEMENT_MULTIPLE_SEPARATOR']; if(empty($arFile) && preg_match('/[;,\|\s'.preg_quote($sep, '/').']/s', $val)) { if(strpos($val, $sep)!==false) $arVals = explode($sep, $val); else $arVals = preg_split('/[;,\|\s]+/s', $val); $arVals = array_diff(array_map('trim', $arVals), array('')); if(count($arVals) > 0 && ($newVal = current($arVals))) { $arFile = $this->GetFileArray($newVal, $arFileParams, ($isOffer ? 'OFFER_' : '').'IE_'.$picName, $arElement[$picName], $val); } } $arFieldsElement[$picName] = $arFile; } if(isset($arFieldsElement[$picName.'_DESCRIPTION'])) { if(!is_array($arFieldsElement[$picName])) $arFieldsElement[$picName] = array(); $arFieldsElement[$picName]['description'] = $arFieldsElement[$picName.'_DESCRIPTION']; unset($arFieldsElement[$picName.'_DESCRIPTION']); } } $arTexts = array('PREVIEW_TEXT', 'DETAIL_TEXT'); foreach($arTexts as $keyText) { if($arFieldsElement[$keyText]) { if($this->fieldSettings[($isOffer ? 'OFFER_' : '').'IE_'.$keyText]['LOAD_BY_EXTLINK']=='Y') { $arFieldsElement[$keyText] = \Bitrix\KdaImportexcel\IUtils::DownloadTextTextByLink($arFieldsElement[$keyText]); } else { $textFile = $_SERVER["DOCUMENT_ROOT"].$arFieldsElement[$keyText]; if(file_exists($textFile) && is_file($textFile) && is_readable($textFile)) { $arFieldsElement[$keyText] = file_get_contents($textFile); } } } } } public function SaveStatusImport($end = false) { if(($time = time())==$this->timeSaveResult) return; $this->timeSaveResult = $time; if($this->procfile) { $writeParams = $this->GetStepParams(); unset($writeParams['currentelement']); unset($writeParams['currentelementitem']); $writeParams['action'] = ($end ? 'finish' : 'continue'); file_put_contents($this->procfile, CUtil::PhpToJSObject($writeParams)); } } public function PrepareSectionPictures(&$arFields, $arSection=array()) { $arPictures = array('PICTURE', 'DETAIL_PICTURE'); foreach($arPictures as $picName) { if($arFields[$picName]) { $val = $arFields[$picName]; if(is_array($val)) $val = current($val); $arFile = $this->GetFileArray($val, array('FILETYPE'=>'IMAGE'), '', $arSection[$picName]); if(empty($arFile) && strpos($val, $this->params['ELEMENT_MULTIPLE_SEPARATOR'])!==false) { $arVals = array_diff(array_map('trim', explode($this->params['ELEMENT_MULTIPLE_SEPARATOR'], $val)), array('')); if(count($arVals) > 0 && ($val = current($arVals))) { $arFile = $this->GetFileArray($val, array(), array('FILETYPE'=>'IMAGE'), $arSection[$picName]); } } $arFields[$picName] = $arFile; } else unset($arFields[$picName]); } } public function SetSkuMode($isSku, $ID=0, $IBLOCK_ID=0) { if($isSku) { $this->conv->SetSkuMode(true, $this->GetCachedOfferIblock($IBLOCK_ID), $ID); $this->offerParentId = $ID; } else { $this->conv->SetSkuMode(false); $this->offerParentId = null; } } public function SaveSKUWithGenerate($ID, $NAME, $IBLOCK_ID, $arItem) { $ret = false; $this->SetSkuMode(true, $ID, $IBLOCK_ID); if(!empty($this->fieldsForSkuGen)) { $filedList = $this->params['FIELDS_LIST'][$this->worksheetNumForSave]; $arItemParams = array(); $arGenFields = array(); foreach($this->fieldsForSkuGen as $key) { $conversions = (isset($this->fieldSettingsExtra[$key]) ? $this->fieldSettingsExtra[$key]['CONVERSION'] : $this->fieldSettings[$filedList[$key]]['CONVERSION']); if(strpos($key, '_') > 0 && !isset($arItem[$key]) && isset($arItem[substr($key, 0 , strpos($key, '_'))])) $arItem[$key] = $arItem[substr($key, 0 , strpos($key, '_'))]; $arItem['~~'.$key] = $arItem[$key]; $arItem[$key] = $this->ApplyConversions($arItem[$key], $conversions, $arItem); $arItemParams[$key] = array_diff(array_map(array($this, 'Trim'), explode($this->params['ELEMENT_MULTIPLE_SEPARATOR'], $arItem[$key])), array('')); if(count($arItemParams[$key])==0) $arItemParams[$key] = array(''); $convertedFields[] = $key; $arGenFields[] = $filedList[$key]; } $arItemSKUParams = array(); $this->GenerateSKUParamsRecursion($arItemSKUParams, $arItemParams); $extraFields = array(); foreach($filedList as $key=>$field) { if(in_array((string)$key, $this->fieldsForSkuGen)) continue; $conversions = $this->fieldSettings[$filedList[$key]]['CONVERSION']; $valOrig = (isset($arItem[$key]) ? $arItem[$key] : $arItem[current(explode('_', $key))]); $val = $this->ApplyConversions($valOrig, $conversions, $arItem); if((preg_match('/^OFFER_(IE_PREVIEW_PICTURE|IE_DETAIL_PICTURE|IE_ACTIVE|IE_SORT|ICAT_QUANTITY|ICAT_PURCHASING_PRICE|ICAT_PRICE\d+_PRICE|ICAT_STORE\d+_AMOUNT|ICAT_WEIGHT|ICAT_DISCOUNT_.*)$/', $field) || in_array($key, $this->fieldsBindToGenSku) || in_array($field, $arGenFields)) && (is_array($val) || strpos(preg_replace('/\{[^\}]*\}/', '', $val), $this->params['ELEMENT_MULTIPLE_SEPARATOR'])!==false)) { $arItem['~~'.$key] = $valOrig; $arItem[$key] = $val; $extraFields[$key] = (is_array($val) ? $val : array_map('trim', explode($this->params['ELEMENT_MULTIPLE_SEPARATOR'], $val))); $convertedFields[] = $key; } } $firstKey = -1; if(isset($this->stepparams['lastoffergenkey'])) { $firstKey = (int)$this->stepparams['lastoffergenkey']; unset($this->stepparams['lastoffergenkey']); } $lastKey = count($arItemSKUParams) - 1; foreach($arItemSKUParams as $k=>$v) { if($k <= $firstKey) continue; $arSubItem = $arItem; foreach($v as $k2=>$v2) $arSubItem[$k2] = $v2; foreach($extraFields as $k2=>$v2) { if(isset($extraFields[$k2][$k])) $arSubItem[$k2] = $extraFields[$k2][$k]; else $arSubItem[$k2] = current($extraFields[$k2]); } $this->currentOfferGenKey = $k; //use in conversions $ret = (bool)($this->SaveSKU($ID, $NAME, $IBLOCK_ID, $arSubItem, $convertedFields) || $ret); $this->SaveStatusImport(); if($k < $lastKey && $this->CheckTimeEnding()) { $this->stepparams['lastoffergenkey'] = $k; $this->worksheetCurrentRow--; return 'timesup'; } } } else { $ret = $this->SaveSKU($ID, $NAME, $IBLOCK_ID, $arItem); } if($ret) { CIBlockElement::UpdateSearch($ID, true); /*if(class_exists('\Bitrix\Iblock\PropertyIndex\Manager')) { \Bitrix\Iblock\PropertyIndex\Manager::updateElementIndex($IBLOCK_ID, $ID); }*/ } $this->SetSkuMode(false); return $ret; } public function GenerateSKUParamsRecursion(&$arItemSKUParams, $arItemParams, $arSubItem = array()) { if(!empty($arItemParams)) { $arKey = array_keys($arItemParams); $key = $arKey[0]; $arCurParams = $arItemParams[$key]; unset($arItemParams[$key]); foreach($arCurParams as $k=>$v) { $arSubItem[$key] = $v; $arSubItem['~'.$key] = $v; $this->GenerateSKUParamsRecursion($arItemSKUParams, $arItemParams, $arSubItem); } } else { $arItemSKUParams[] = $arSubItem; } } public function SaveSKU($ID, $NAME, $IBLOCK_ID, $arItem, $convertedFields=array()) { //\Bitrix\Catalog\Product\Sku::disableUpdateAvailable(); if(!($arOfferIblock = $this->GetCachedOfferIblock($IBLOCK_ID))) return false; $OFFERS_IBLOCK_ID = $arOfferIblock['OFFERS_IBLOCK_ID']; $OFFERS_PROPERTY_ID = $arOfferIblock['OFFERS_PROPERTY_ID']; $filedList = $this->params['FIELDS_LIST'][$this->worksheetNumForSave]; $propsDef = $this->GetIblockProperties($OFFERS_IBLOCK_ID); $iblockFields = $this->GetIblockFields($OFFERS_IBLOCK_ID); $this->currentItemValues = $arItem; $arFieldsElement = array(); $arFieldsElementOrig = array(); $arFieldsPrices = array(); $arFieldsProduct = array(); $arFieldsProductStores = array(); $arFieldsProductDiscount = array(); if($ID > 0) { $arFieldsProps = array($OFFERS_PROPERTY_ID => $ID); $arFieldsPropsOrig = array($OFFERS_PROPERTY_ID => $ID); } else { $arFieldsProps = array(); $arFieldsPropsOrig = array(); } $arFieldsIpropTemp = array(); $arFieldsForSkuGen = array_map('strval', $this->fieldsForSkuGen); foreach($filedList as $key=>$field) { if(strpos($field, 'OFFER_')!==0) continue; $conversions = (isset($this->fieldSettingsExtra[$key]) ? $this->fieldSettingsExtra[$key]['CONVERSION'] : $this->fieldSettings[$field]['CONVERSION']); $copyCell = (bool)($this->fieldSettings[$field]['COPY_CELL_ON_OFFERS']=='Y'); $field = substr($field, 6); $k = $key; if(strpos($k, '_')!==false && !isset($arItem[$k])) $k = substr($k, 0, strpos($k, '_')); $value = $arItem[$k]; if($this->fieldSettings[$field]['NOT_TRIM']=='Y') $value = $arItem['~'.$k]; if($this->fieldSettings[$field]['EXCEL_STYLES_TO_HTML']=='Y') $value = $arItem['html_'.$k]; $origValue = $arItem['~'.$k]; if(!$value && $copyCell && $this->stepparams['currentelementitem']) { $value = $this->stepparams['currentelementitem'][$k]; $origValue = $this->stepparams['currentelementitem']['~'.$k]; } //if(!empty($conversions) && !in_array($key, $arFieldsForSkuGen)) if(!empty($conversions) && !in_array($key, $convertedFields)) { $value = $this->ApplyConversions($value, $conversions, $arItem, array('KEY'=>$k, 'NAME'=>$field, 'PARENT_ID'=>$ID), $iblockFields); $origValue = $this->ApplyConversions($origValue, $conversions, $arItem, array('KEY'=>$k, 'NAME'=>$field, 'PARENT_ID'=>$ID), $iblockFields); if($value===false) continue; } if(strpos($field, 'IE_')===0) { $fieldKey = substr($field, 3); if($this->params['ELEMENT_LOAD_IMAGES']=='Y' && in_array($fieldKey, array('DETAIL_PICTURE', 'PREVIEW_PICTURE')) && isset($arItem['i~'.$k])) { $arFieldsElement[$fieldKey] = $arItem['i~'.$k]; $arFieldsElementOrig[$fieldKey] = $arItem['i~'.$k]; } else { if(strpos($fieldKey, '|')!==false) { list($fieldKey, $adata) = explode('|', $fieldKey); $adata = explode('=', $adata); if(count($adata) > 1) { $arFieldsElement[$adata[0]] = $adata[1]; } } $arFieldsElement[$fieldKey] = $value; $arFieldsElementOrig[$fieldKey] = $origValue; } } elseif(strpos($field, 'ICAT_PRICE')===0) { $val = $value; if(substr($field, -6)=='_PRICE') { if(!in_array($val, array('', '-'))) { //$val = $this->GetFloatVal($val); $val = $this->ApplyMargins($val, $this->fieldSettingsExtra[$key]); } } elseif(substr($field, -6)=='_EXTRA') { $val = $this->GetFloatVal($val, 0, true); } $arPrice = explode('_', substr($field, 10), 2); $pkey = $arPrice[1]; if($pkey=='PRICE' && $this->fieldSettingsExtra[$key]['PRICE_USE_EXT']=='Y') { $pkey = $pkey.'|QUANTITY_FROM='.$this->CalcFloatValue($this->fieldSettingsExtra[$key]['PRICE_QUANTITY_FROM']).'|QUANTITY_TO='.$this->CalcFloatValue($this->fieldSettingsExtra[$key]['PRICE_QUANTITY_TO']); } $arFieldsPrices[$arPrice[0]][$pkey] = $val; } elseif(strpos($field, 'ICAT_LIST_STORES')===0) { $this->GetStoreAmountList($arFieldsProductStores, $this->fieldSettingsExtra[$key], $value); } elseif(strpos($field, 'ICAT_STORE')===0) { $arStore = explode('_', substr($field, 10), 2); $arFieldsProductStores[$arStore[0]][$arStore[1]] = $value; } elseif(strpos($field, 'ICAT_DISCOUNT_')===0) { if(strpos($field, 'ICAT_DISCOUNT_VALUE')===0 && in_array(trim($value), array('', '0')) && isset($arFieldsProductDiscount['VALUE'])) continue; if(strpos($field, '|')!==false) { list($field, $adata) = explode('|', $field); $adata = explode('=', $adata); if(count($adata) > 1) { $arFieldsProductDiscount[$adata[0]] = $adata[1]; } } $field = substr($field, 14); if($field=='VALUE' && isset($this->fieldSettingsExtra[$key])) { $fse = $this->fieldSettingsExtra[$key]; if(!empty($fse['CATALOG_GROUP_IDS'])) { $arFieldsProductDiscount['CATALOG_GROUP_IDS'] = $fse['CATALOG_GROUP_IDS']; } if(is_array($fse['SITE_IDS']) && !empty($fse['SITE_IDS'])) { foreach($fse['SITE_IDS'] as $siteId) { $arFieldsProductDiscount['LID_VALUES'][$siteId] = array('VALUE'=>$value); if(isset($arFieldsProductDiscount['VALUE_TYPE'])) $arFieldsProductDiscount['LID_VALUES'][$siteId]['VALUE_TYPE'] = $arFieldsProductDiscount['VALUE_TYPE']; } } } $arFieldsProductDiscount[$field] = $value; } elseif(strpos($field, 'ICAT_')===0) { $val = $value; if($field=='ICAT_PURCHASING_PRICE') { if($val=='') continue; $val = $this->GetFloatVal($val); } $arFieldsProduct[substr($field, 5)] = $val; } elseif(strpos($field, 'IP_PROP')===0) { $fieldName = substr($field, 7); if(substr($fieldName, -12)=='_DESCRIPTION') $currentPropDef = $propsDef[substr($fieldName, 0, -12)]; else $currentPropDef = $propsDef[$fieldName]; $this->GetPropField($arFieldsProps, $arFieldsPropsOrig, $this->fieldSettingsExtra[$key], $currentPropDef, $fieldName, $value, $origValue); } elseif(strpos($field, 'IP_LIST_PROPS')===0) { $this->GetPropList($arFieldsProps, $arFieldsPropsOrig, $this->fieldSettingsExtra[$key], $OFFERS_IBLOCK_ID, $value, array($OFFERS_PROPERTY_ID)); } elseif(strpos($field, 'IPROP_TEMP_')===0) { $fieldName = substr($field, 11); $arFieldsIpropTemp[$fieldName] = $value; } } $arUid = $this->GetFilterUids($arFieldsElement, $arFieldsElementOrig, $arFieldsProps, $arFieldsPropsOrig, $OFFERS_IBLOCK_ID, $OFFERS_PROPERTY_ID, $ID); $emptyFields = $notEmptyFields = array(); foreach($arUid as $k=>$v) { if((is_array($v['valUid']) && count(array_diff($v['valUid'], array('')))>0) || (!is_array($v['valUid']) && strlen(trim($v['valUid']))>0)) $notEmptyFields[] = $v['uid']; else $emptyFields[] = $v['uid']; } if(($ID > 0 && count($notEmptyFields) < 2) || ($ID <= 0 && (count($notEmptyFields) < 1 || count($emptyFields) > 0))) { return false; } if(array_key_exists($OFFERS_PROPERTY_ID, $arFieldsProps)) unset($arFieldsProps[$OFFERS_PROPERTY_ID]); $arDates = array('ACTIVE_FROM', 'ACTIVE_TO', 'DATE_CREATE'); foreach($arDates as $keyDate) { if(isset($arFieldsElement[$keyDate]) && strlen($arFieldsElement[$keyDate]) > 0) { $arFieldsElement[$keyDate] = $this->GetDateVal($arFieldsElement[$keyDate]); } } if(isset($arFieldsElement['ACTIVE'])) { $arFieldsElement['ACTIVE'] = $this->GetBoolValue($arFieldsElement['ACTIVE']); } elseif($this->params['ELEMENT_LOADING_ACTIVATE']=='Y') { $arFieldsElement['ACTIVE'] = 'Y'; } $arKeys = array_merge(array('ID', 'NAME', 'IBLOCK_SECTION_ID', 'MODIFIED_BY', 'PREVIEW_PICTURE'), array_keys($arFieldsElement)); if(!$ID) $arKeys[] = 'PROPERTY_'.$OFFERS_PROPERTY_ID; $arFilter = array('IBLOCK_ID'=>$OFFERS_IBLOCK_ID, 'CHECK_PERMISSIONS' => 'N'); foreach($arUid as $v) { if(!$v['substring']) { if(is_array($v['valUid'])) $arSubfilter = array_map(array($this, 'Trim'), $v['valUid']); else { $arSubfilter = array($this->Trim($v['valUid'])); if($this->Trim($v['valUid']) != $v['valUid2']) { $arSubfilter[] = $this->Trim($v['valUid2']); if(strlen($v['valUid2']) != strlen($this->Trim($v['valUid2']))) { $arSubfilter[] = $v['valUid2']; } } if(strlen($v['valUid']) != strlen($this->Trim($v['valUid']))) { $arSubfilter[] = $v['valUid']; } } if(count($arSubfilter) == 1) { $arSubfilter = $arSubfilter[0]; } $arFilter['='.$v['uid']] = $arSubfilter; } else { if(is_array($v['valUid'])) $v['valUid'] = array_map(array($this, 'Trim'), $v['valUid']); else $v['valUid'] = $this->Trim($v['valUid']); if($v['substring']=='B') $arFilter[$v['uid']] = (is_array($v['valUid']) ? array_map(array('CKDAImportUtils', 'GetFilterBeginWith'), $v['valUid']) : $v['valUid'].'%'); elseif($v['substring']=='E') $arFilter[$v['uid']] = (is_array($v['valUid']) ? array_map(array('CKDAImportUtils', 'GetFilterEndOn'), $v['valUid']) : '%'.$v['valUid']); else $arFilter['%'.$v['uid']] = $v['valUid']; } } if(!empty($arFieldsIpropTemp)) { $arFieldsElement['IPROPERTY_TEMPLATES'] = $arFieldsIpropTemp; } $arProductIds = array(); if($ID) $arProductIds[] = $ID; $elemName = ''; $duplicate = false; //$dbRes = CIblockElement::GetList(array(), $arFilter, false, false, $arKeys); $dbRes = \Bitrix\KdaImportexcel\DataManager\IblockElementTable::GetListComp($arFilter, $arKeys); while($arElement = $dbRes->Fetch()) { $updated = false; $OFFER_ID = $arElement['ID']; $arFieldsProps2 = $arFieldsProps; $arFieldsElement2 = $arFieldsElement; $arFieldsProduct2 = $arFieldsProduct; $arFieldsPrices2 = $arFieldsPrices; $arFieldsProductStores2 = $arFieldsProductStores; $arFieldsProductDiscount2 = $arFieldsProductDiscount; if($this->conv->SetElementId($OFFER_ID, $duplicate) && $this->conv->UpdateProperties($arFieldsProps2, $OFFER_ID)!==false && $this->conv->UpdateElementFields($arFieldsElement2, $OFFER_ID)!==false && $this->conv->UpdateProduct($arFieldsProduct2, $arFieldsPrices2, $arFieldsProductStores2, $OFFER_ID)!==false && $this->conv->UpdateDiscountFields($arFieldsProductDiscount2, $OFFER_ID)!==false && $this->conv->SetElementId(0)) { $this->BeforeElementSave($OFFER_ID, 'update'); if($this->params['ONLY_CREATE_MODE_OFFER']!='Y') { $this->UnsetUidFields($arFieldsElement2, $arFieldsProps2, $this->params['CURRENT_ELEMENT_UID_SKU']); if(!empty($this->fieldOnlyNewOffer)) { $this->UnsetExcessFields($this->fieldOnlyNewOffer, $arFieldsElement2, $arFieldsProps2, $arFieldsProduct2, $arFieldsPrices2, $arFieldsProductStores2, $arFieldsProductDiscount2); } $this->RemoveProperties($OFFER_ID, $OFFERS_IBLOCK_ID, true); $this->SaveProperties($OFFER_ID, $OFFERS_IBLOCK_ID, $arFieldsProps2); $this->SaveProduct($OFFER_ID, $OFFERS_IBLOCK_ID, $arFieldsProduct2, $arFieldsPrices2, $arFieldsProductStores2, $ID); $this->AfterSaveProduct($arFieldsElement2, $OFFER_ID, $OFFERS_IBLOCK_ID, true); if($this->CheckRequiredProps($arFieldsProps2, $OFFERS_IBLOCK_ID, $OFFER_ID) && $this->UpdateElement($OFFER_ID, $OFFERS_IBLOCK_ID, $arFieldsElement2, $arElement, true)) { //$this->SetTimeBegin($OFFER_ID); } else { $this->Err(sprintf(Loc::getMessage("KDA_IE_UPDATE_OFFER_ERROR"), $this->GetLastError(), $this->worksheetNumForSave+1, $this->worksheetCurrentRow)); } $elemName = $arElement['NAME']; $this->SaveDiscount($OFFER_ID, $OFFERS_IBLOCK_ID, $arFieldsProductDiscount2, $elemName, true); $updated = true; } } if($this->SaveElementId($OFFER_ID, 'O')) { if($updated) { $this->stepparams['sku_updated_line']++; if($this->IsChangedElement()) $this->stepparams['sku_changed_line']++; } if(!$ID && ($eid = $arElement['PROPERTY_'.$OFFERS_PROPERTY_ID.'_VALUE'])) { $arProductIds[] = $eid; if($this->SaveElementId($eid)) $this->lastOffElemId = $eid; } } $duplicate = true; } if($elemName && !$arFieldsElement['NAME']) $arFieldsElement['NAME'] = $elemName; if(\Bitrix\KdaImportexcel\DataManager\IblockElementTable::SelectedRowsCountComp($dbRes)==0 && $ID && ($this->params['SEARCH_OFFERS_WO_PRODUCTS']!='Y' || $this->params['CREATE_NEW_OFFERS']=='Y')) { if($this->params['ONLY_UPDATE_MODE_OFFER']!='Y' || $this->params['CREATE_NEW_OFFERS']=='Y') { //$this->UnsetUidFields($arFieldsElement, $arFieldsProps, $this->params['CURRENT_ELEMENT_UID_SKU'], true); if(!$this->CheckIdForNewElement($arFieldsElement, true)) return false; if(strlen($arFieldsElement['NAME'])==0) { $arFieldsElement['NAME'] = $NAME; } if($this->params['ELEMENT_NEW_DEACTIVATE']=='Y' && !isset($arFieldsElement['ACTIVE'])) { $arFieldsElement['ACTIVE'] = 'N'; } elseif(!$arFieldsElement['ACTIVE']) { $arFieldsElement['ACTIVE'] = 'Y'; } $arFieldsElement['IBLOCK_ID'] = $OFFERS_IBLOCK_ID; $this->GetDefaultElementFields($arFieldsElement, $iblockFields); if($this->CheckRequiredProps($arFieldsProps, $OFFERS_IBLOCK_ID) && ($OFFER_ID = $this->AddElement(array_merge($arFieldsElement, array('PROPERTY_VALUES'=>array($OFFERS_PROPERTY_ID => $ID))), true))) { $this->AddTagIblock($OFFERS_IBLOCK_ID); $this->BeforeElementSave($OFFER_ID, 'add'); $this->logger->AddElementChanges('IE_', $arFieldsElement); //$this->SetTimeBegin($OFFER_ID); $this->SaveProperties($OFFER_ID, $OFFERS_IBLOCK_ID, $arFieldsProps, true, $arFieldsElement); $this->PrepareProductAdd($arFieldsProduct, $OFFER_ID, $OFFERS_IBLOCK_ID); $this->SaveProduct($OFFER_ID, $OFFERS_IBLOCK_ID, $arFieldsProduct, $arFieldsPrices, $arFieldsProductStores, $ID); $this->AfterSaveProduct($arFieldsElement, $OFFER_ID, $OFFERS_IBLOCK_ID); $this->SaveDiscount($OFFER_ID, $OFFERS_IBLOCK_ID, $arFieldsProductDiscount, $arFieldsElement['NAME'], true); $this->AfterElementAdd($OFFERS_IBLOCK_ID, $OFFER_ID); if($this->SaveElementId($OFFER_ID, 'O')) $this->stepparams['sku_added_line']++; } else { $this->Err(sprintf(Loc::getMessage("KDA_IE_ADD_OFFER_ERROR"), $this->GetLastError(), $this->worksheetNumForSave+1, $this->worksheetCurrentRow)); return false; } } else { $this->logger->AddElementMassChanges($arFieldsElement, $arFieldsProps, $arFieldsProduct, $arFieldsProductStores, $arFieldsPrices); $this->logger->SaveElementNotFound($arFilter, $this->worksheetCurrentRow); } } if($OFFER_ID) { if($this->params['ONAFTERSAVE_HANDLER']) { $this->ExecuteOnAfterSaveHandler($this->params['ONAFTERSAVE_HANDLER'], $OFFER_ID); } } /*Update product*/ if($OFFER_ID && ($this->params['ELEMENT_NO_QUANTITY_DEACTIVATE']=='Y' || $this->params['ELEMENT_NO_PRICE_DEACTIVATE']=='Y' || ($this->params['ELEMENT_LOADING_ACTIVATE']=='Y' && !$ID)) && class_exists('\Bitrix\Catalog\ProductTable') && class_exists('\Bitrix\Catalog\PriceTable')) { foreach($arProductIds as $prodId) { $arOfferIds = array(); $offersActive = false; $dbRes = CIblockElement::GetList(array(), array( 'IBLOCK_ID' => $OFFERS_IBLOCK_ID, 'PROPERTY_'.$OFFERS_PROPERTY_ID => $prodId, 'CHECK_PERMISSIONS' => 'N'), false, false, array('ID', 'ACTIVE')); while($arr = $dbRes->Fetch()) { $arOfferIds[] = $arr['ID']; $offersActive = (bool)($offersActive || ($arr['ACTIVE']=='Y')); } if(!empty($arOfferIds)) { $active = false; if(!$offersActive) $active = 'N'; else { if($this->params['ELEMENT_LOADING_ACTIVATE']=='Y') $active = 'Y'; if($this->params['ELEMENT_NO_QUANTITY_DEACTIVATE']=='Y') { $existQuantity = \Bitrix\Catalog\ProductTable::getList(array( 'select' => array('ID', 'QUANTITY'), 'filter' => array('@ID' => $arOfferIds, '>QUANTITY' => '0'), 'limit' => 1 ))->fetch(); if(!$existQuantity) $active = 'N'; } if($this->params['ELEMENT_NO_PRICE_DEACTIVATE']=='Y') { $existPrice = \Bitrix\Catalog\PriceTable::getList(array( 'select' => array('ID', 'PRICE'), 'filter' => array('@PRODUCT_ID' => $arOfferIds, '>PRICE' => '0'), 'limit' => 1 ))->fetch(); if(!$existPrice) $active = 'N'; } } if($active!==false) { $arElem = \Bitrix\KdaImportexcel\DataManager\IblockElementTable::GetListComp(array('ID'=>$prodId, 'CHECK_PERMISSIONS' => 'N'), array('ACTIVE'))->Fetch(); if($arElem['ACTIVE']!=$active) { $el = new CIblockElement(); $el->Update($prodId, array('ACTIVE'=>$active, 'MODIFIED_BY' => $this->GetCurUserID()), false, true, true); $this->AddTagIblock($IBLOCK_ID); } } } } } if($ID && $OFFER_ID && defined('\Bitrix\Catalog\ProductTable::TYPE_SKU')) { $this->SaveProduct($ID, $IBLOCK_ID, array('TYPE'=>\Bitrix\Catalog\ProductTable::TYPE_SKU), array(), array()); } /*/Update product*/ return (bool)($OFFER_ID && $OFFER_ID > 0); } public function GetFilterUids($arFieldsElement, $arFieldsElementOrig, $arFieldsProps, $arFieldsPropsOrig, $IBLOCK_ID, $offerPropId=false, $parentId=0) { $arFieldsDef = $this->fl->GetFields($IBLOCK_ID); $propsDef = $this->GetIblockProperties($IBLOCK_ID); $currentUid = $this->params[$offerPropId===false ? 'CURRENT_ELEMENT_UID' : 'CURRENT_ELEMENT_UID_SKU']; if(!is_array($currentUid)) $currentUid = array($currentUid); if($offerPropId!==false && $parentId > 0 && !in_array('OFFER_IP_PROP'.$offerPropId, $currentUid)) $currentUid[] = 'OFFER_IP_PROP'.$offerPropId; $arUid = array(); foreach($currentUid as $tuid) { $fs = $this->fieldSettings[$tuid]; if($offerPropId!==false) $tuid = substr($tuid, 6); $uid = $valUid = $valUid2 = $nameUid = ''; $canSubstring = true; if(strpos($tuid, 'IE_')===0) { $nameUid = $arFieldsDef['element']['items'][$tuid]; $uid = substr($tuid, 3); if(strpos($uid, '|')!==false) $uid = current(explode('|', $uid)); $valUid = $arFieldsElementOrig[$uid]; $valUid2 = $arFieldsElement[$uid]; if($uid == 'ACTIVE_FROM' || $uid == 'ACTIVE_TO') { $uid = 'DATE_'.$uid; $valUid = $this->GetDateVal($valUid); $valUid2 = $this->GetDateVal($valUid2); } } elseif(strpos($tuid, 'IP_PROP')===0) { $nameUid = $arFieldsDef['prop']['items'][$tuid]; $uid = substr($tuid, 7); $valUid = $arFieldsPropsOrig[$uid]; $valUid2 = $arFieldsProps[$uid]; $p = $propsDef[$uid]; if($p['MULTIPLE']=='Y') { if(!is_array($valUid)) { $valUid = $this->GetMultipleProperty($valUid, $uid); $valUid2 = $this->GetMultipleProperty($valUid2, $uid); } elseif(array_key_exists('VALUE', $valUid) && !is_array($valUid['VALUE'])) { $valUid['VALUE'] = $this->GetMultipleProperty($valUid['VALUE'], $uid); $valUid2['VALUE'] = $this->GetMultipleProperty($valUid2['VALUE'], $uid); } } if($p['PROPERTY_TYPE']=='L') { $uid = 'PROPERTY_'.$uid.'_VALUE'; if(is_array($valUid)) { if(array_key_exists('VALUE', $valUid)) $valUid = $valUid['VALUE']; elseif(($lval = $this->GetListPropertyValue($p, $valUid))!==false) { $valUid = $valUid2 = $lval; $uid = str_replace('_VALUE', '', $uid); } if(is_array($valUid2) && array_key_exists('VALUE', $valUid2)) $valUid2 = $valUid2['VALUE']; } } elseif($p['PROPERTY_TYPE']=='N' && ((!is_array($valUid) && !is_numeric($this->Trim($valUid))) || (is_array($valUid) && count(preg_grep('/^\s*\d+\s*$/', $valUid))==0))) { $valUid = $valUid2 = ''; } else { if($p['PROPERTY_TYPE']=='S') { if($p['USER_TYPE']=='directory') { $valUid = $this->GetHighloadBlockValue($p, $valUid); $valUid2 = $this->GetHighloadBlockValue($p, $valUid2); $canSubstring = false; } elseif($p['USER_TYPE']=='Date') { $valUid = $this->GetDateValToDB($valUid, 'PART'); $valUid2 = $this->GetDateValToDB($valUid2, 'PART'); } elseif($p['USER_TYPE']=='DateTime') { $valUid = $this->GetDateValToDB($valUid); $valUid2 = $this->GetDateValToDB($valUid2); } elseif($p['USER_TYPE']=='HTML') { $valUid = array($valUid, serialize(array('TEXT'=>$valUid, 'TYPE'=>'TEXT')), serialize(array('TEXT'=>$valUid, 'TYPE'=>'HTML'))); $valUid2 = array($valUid2, serialize(array('TEXT'=>$valUid2, 'TYPE'=>'TEXT')), serialize(array('TEXT'=>$valUid2, 'TYPE'=>'HTML'))); } } elseif($p['PROPERTY_TYPE']=='E' && $uid!=$offerPropId) { $valUid = $this->GetIblockElementValue($p, $valUid, $fs, true, true, true); $valUid2 = $this->GetIblockElementValue($p, $valUid2, $fs, true, true, true); if($valUid===false) $valUid = ''; if($valUid2===false) $valUid2 = ''; $canSubstring = false; } $uid = 'PROPERTY_'.$uid; } } if($uid) { $substringMode = $fs['UID_SEARCH_SUBSTRING']; if(!in_array($substringMode, array('Y', 'B', 'E'))) $substringMode = ''; $arUid[] = array( 'uid' => $uid, 'nameUid' => $nameUid, 'valUid' => $valUid, 'valUid2' => $valUid2, 'substring' => ($substringMode && $canSubstring ? $substringMode : '') ); } } return $arUid; } public function GetElementSections($ID, $SECTION_ID, $unique=true) { $arSections = array(); $main = 0; if($SECTION_ID > 0) $main = $SECTION_ID; $dbRes = \CIBlockElement::GetElementGroups($ID, true, array('ID')); if($unique) { if($SECTION_ID > 0) $arSections[] = $SECTION_ID; while($arr = $dbRes->Fetch()) { if(!in_array($arr['ID'], $arSections)) $arSections[] = $arr['ID']; } } else { while($arr = $dbRes->Fetch()) { if($arr['ID']==$main) array_unshift($arSections, $arr['ID']); else $arSections[] = $arr['ID']; } } return $arSections; } public function UnsetUidFields(&$arFieldsElement, &$arFieldsProps, $arUids, $saveVal=false) { $arFilter = array(); foreach($arUids as $field) { if(strpos($field, 'OFFER_')===0) $field = substr($field, 6); if(strpos($field, 'IE_')===0) { $fieldKey = substr($field, 3); if(isset($arFieldsElement[$fieldKey])) { $arFilter[$field] = $arFieldsElement[$fieldKey]; if(is_array($arFieldsElement[$fieldKey])) { if($saveVal) { $arFieldsElement[$fieldKey] = array_diff($arFieldsElement[$fieldKey], array('')); if(count($arFieldsElement[$fieldKey]) > 0) $arFieldsElement[$fieldKey] = end($arFieldsElement[$fieldKey]); else $arFieldsElement[$fieldKey] = ''; } else unset($arFieldsElement[$fieldKey]); } elseif(!$saveVal) { unset($arFieldsElement[$fieldKey]); } } } elseif(strpos($field, 'IP_PROP')===0) { $fieldKey = substr($field, 7); if(isset($arFieldsProps[$fieldKey])) { $arFilter[$field] = $arFieldsProps[$fieldKey]; if(is_array($arFieldsProps[$fieldKey])) { if($saveVal) { $arFieldsProps[$fieldKey] = array_diff($arFieldsProps[$fieldKey], array('')); if(array_key_exists('PRIMARY', $arFieldsProps[$fieldKey]) || count(preg_grep('/\D/', array_keys($arFieldsProps[$fieldKey]))) > 0){} elseif(count($arFieldsProps[$fieldKey]) > 0) $arFieldsProps[$fieldKey] = end($arFieldsProps[$fieldKey]); else $arFieldsProps[$fieldKey] = ''; } else unset($arFieldsProps[$fieldKey]); } elseif(!$saveVal) { unset($arFieldsProps[$fieldKey]); } } } } $this->logger->AddElementData('FILTER_', $arFilter); } public function UnsetExcessFields($fieldsList, &$arFieldsElement, &$arFieldsProps, &$arFieldsProduct, &$arFieldsPrices, &$arFieldsProductStores, &$arFieldsProductDiscount) { foreach($fieldsList as $field) { if(strpos($field, 'IE_')===0) { if(strpos($field, '|')!==false) { list($field, $adata) = explode('|', $field); $adata = explode('=', $adata); if(count($adata) > 1) { unset($arFieldsElement[$adata[0]]); } } unset($arFieldsElement[substr($field, 3)]); } elseif(strpos($field, 'ISECT')===0) { unset($arFieldsElement['IBLOCK_SECTION']); } elseif(strpos($field, 'ICAT_PRICE')===0) { $arPrice = explode('_', substr($field, 10), 2); unset($arFieldsPrices[$arPrice[0]][$arPrice[1]]); if(empty($arFieldsPrices[$arPrice[0]])) unset($arFieldsPrices[$arPrice[0]]); } elseif(strpos($field, 'ICAT_STORE')===0) { $arStore = explode('_', substr($field, 10), 2); unset($arFieldsProductStores[$arStore[0]][$arStore[1]]); if(empty($arFieldsProductStores[$arStore[0]])) unset($arFieldsProductStores[$arStore[0]]); } elseif(strpos($field, 'ICAT_DISCOUNT_')===0) { if(strpos($field, '|')!==false) { list($field, $adata) = explode('|', $field); $adata = explode('=', $adata); if(count($adata) > 1) { unset($arFieldsProductDiscount[$adata[0]]); } } unset($arFieldsProductDiscount[substr($field, 14)]); } elseif(strpos($field, 'ICAT_')===0) { unset($arFieldsProduct[substr($field, 5)]); } elseif(strpos($field, 'IP_PROP')===0) { unset($arFieldsProps[substr($field, 7)]); } elseif(strpos($field, 'IPROP_TEMP_')===0) { unset($arFieldsElement['IPROPERTY_TEMPLATES'][substr($field, 11)]); } } } public function UnsetExcessSectionFields($fieldsList, &$arFieldsSections, &$arFieldsElement) { foreach($fieldsList as $field) { if(strpos($field, 'ISECT')===0) { $adata = false; if(strpos($field, '|')!==false) { list($field, $adata) = explode('|', $field); $adata = explode('=', $adata); } $arSect = explode('_', substr($field, 5), 2); unset($arFieldsSections[$arSect[0]][$arSect[1]]); if(is_array($adata) && count($adata) > 1) { unset($arFieldsSections[$arSect[0]][$adata[0]]); } } elseif($field=='IE_SECTION_PATH') { $field = substr($field, 3); unset($arFieldsElement[$field]); } } } public function GetPropField(&$arFieldsProps, &$arFieldsPropsOrig, $fieldSettingsExtra, $propDef, $fieldName, $value, $origValue, $arUids = array()) { if(!isset($arFieldsProps[$fieldName])) $arFieldsProps[$fieldName] = null; if(!isset($arFieldsPropsOrig[$fieldName])) $arFieldsPropsOrig[$fieldName] = null; $arFieldsPropsItem = &$arFieldsProps[$fieldName]; $arFieldsPropsOrigItem = &$arFieldsPropsOrig[$fieldName]; if($propDef) { if($propDef['USER_TYPE']=='directory') { if($fieldSettingsExtra['HLBL_FIELD']) $key2 = $fieldSettingsExtra['HLBL_FIELD']; else $key2 = 'UF_NAME'; if(!isset($arFieldsPropsItem[$key2])) $arFieldsPropsItem[$key2] = null; if(!isset($arFieldsPropsOrigItem[$key2])) $arFieldsPropsOrigItem[$key2] = null; $arFieldsPropsItem = &$arFieldsPropsItem[$key2]; $arFieldsPropsOrigItem = &$arFieldsPropsOrigItem[$key2]; } elseif($propDef['PROPERTY_TYPE']=='E' && $propDef['MULTIPLE']!='Y') { if($fieldSettingsExtra['REL_ELEMENT_EXTRA_FIELD']) $key1 = $fieldSettingsExtra['REL_ELEMENT_EXTRA_FIELD']; else $key1 = 'PRIMARY'; if($fieldSettingsExtra['REL_ELEMENT_FIELD']) $key2 = $fieldSettingsExtra['REL_ELEMENT_FIELD']; else $key2 = 'IE_ID'; if(!isset($arFieldsPropsItem[$key1][$key2])) $arFieldsPropsItem[$key1][$key2] = null; if(!isset($arFieldsPropsOrigItem[$key1][$key2])) $arFieldsPropsOrigItem[$key1][$key2] = null; $arFieldsPropsItem = &$arFieldsPropsItem[$key1][$key2]; $arFieldsPropsOrigItem = &$arFieldsPropsOrigItem[$key1][$key2]; } elseif($propDef['PROPERTY_TYPE']=='L') { if($fieldSettingsExtra['PROPLIST_FIELD']) $key2 = $fieldSettingsExtra['PROPLIST_FIELD']; else $key2 = 'VALUE'; if(!isset($arFieldsPropsItem[$key2])) $arFieldsPropsItem[$key2] = null; if(!isset($arFieldsPropsOrigItem[$key2])) $arFieldsPropsOrigItem[$key2] = null; $arFieldsPropsItem = &$arFieldsPropsItem[$key2]; $arFieldsPropsOrigItem = &$arFieldsPropsOrigItem[$key2]; } } if(($propDef['MULTIPLE']=='Y' || in_array('IP_PROP'.$fieldName, $arUids)) && !is_null($arFieldsPropsItem)) { if(is_array($arFieldsPropsItem)) { if(isset($arFieldsPropsItem['VALUE'])) $arFieldsPropsItem = array($arFieldsPropsItem); if(isset($arFieldsPropsOrigItem['VALUE'])) $arFieldsPropsOrigItem = array($arFieldsPropsOrigItem); $arFieldsPropsItem[] = $value; $arFieldsPropsOrigItem[] = $origValue; } else { $arFieldsPropsItem = array($arFieldsPropsItem, $value); $arFieldsPropsOrigItem = array($arFieldsPropsOrigItem, $origValue); } } else { $arFieldsPropsItem = $value; $arFieldsPropsOrigItem = $origValue; } } public function GetPropList(&$arFieldsProps, &$arFieldsPropsOrig, $fieldSettingsExtra, $IBLOCK_ID, $value, $arExcluded=array()) { if(strlen($fieldSettingsExtra['PROPLIST_PROPS_SEP'])==0 || strlen($fieldSettingsExtra['PROPLIST_PROPVALS_SEP'])==0) return; $propsSep = $this->GetSeparator($fieldSettingsExtra['PROPLIST_PROPS_SEP']); $propValsSep = $this->GetSeparator($fieldSettingsExtra['PROPLIST_PROPVALS_SEP']); $propDescSep = $this->GetSeparator($fieldSettingsExtra['PROPLIST_VALDESC_SEP']); $arProps = explode($propsSep, $value); foreach($arProps as $prop) { $arCurProp = explode($propValsSep, $prop); if(count($arCurProp) < 2) continue; $arCurProp = array_map('trim', $arCurProp); $name = array_shift($arCurProp); if(strlen($name)==0) continue; $createNew = ($fieldSettingsExtra['PROPLIST_CREATE_NEW']=='Y'); $propDef = $this->GetIblockPropertyByName($name, $IBLOCK_ID, $createNew, $fieldSettingsExtra); if(!$createNew) { if($propDef===false) $propDef = $this->GetIblockPropertyByCode($name, $IBLOCK_ID); if($propDef===false) $propDef = $this->GetIblockPropertyById($name, $IBLOCK_ID); } if($propDef!==false && !in_array($propDef['ID'], $arExcluded)) { while(count($arCurProp) > 0) { $val = array_shift($arCurProp); if(strlen($propDescSep) > 0 && strpos($val, $propDescSep)!==false) { if($propDef['MULTIPLE']=='Y') $arVals = explode($this->params['ELEMENT_MULTIPLE_SEPARATOR'], $val); else $arVals = array($val); $val = $desc = ''; foreach($arVals as $k=>$subval) { list($subval, $subdesc) = explode($propDescSep, $subval, 2); if($k > 0) { $val .= $this->params['ELEMENT_MULTIPLE_SEPARATOR']; $desc .= $this->params['ELEMENT_MULTIPLE_SEPARATOR']; } $val .= $subval; $desc .= $subdesc; } $this->GetPropField($arFieldsProps, $arFieldsPropsOrig, array(), $propDef, $propDef['ID'].'_DESCRIPTION', $desc, $desc); } $this->GetPropField($arFieldsProps, $arFieldsPropsOrig, array(), $propDef, $propDef['ID'], $val, $val); if($propDef['PROPERTY_TYPE']=='E') $this->fieldSettings['IP_PROP'.$propDef['ID']]['REL_ELEMENT_FIELD'] = 'IE_NAME'; } } } } public function GetStoreAmountList(&$arFieldsProductStores, $arParams, $value) { if(!class_exists('\Bitrix\Catalog\StoreTable')) return; if(!isset($this->storeKeys) || !is_array($this->storeKeys)) $this->storeKeys = array(); $sep1 = (strlen(trim($arParams['STORELIST_STORES_SEP'])) > 0 ? trim($arParams['STORELIST_STORES_SEP']) : ';'); $sep2 = (strlen(trim($arParams['STORELIST_STOREVALS_SEP'])) > 0 ? trim($arParams['STORELIST_STOREVALS_SEP']) : ':'); $arStores = array_map('trim', explode($sep1, $value)); foreach($arStores as $strStore) { $arStoreParts = array_map('trim', explode($sep2, $strStore, 2)); $storeName = ToLower($arStoreParts[0]); if(count($arStoreParts) < 2 && strlen($storeName)==0) continue; if(!array_key_exists($storeName, $this->storeKeys)) { $dbRes = \Bitrix\Catalog\StoreTable::getList(array('filter'=>array('LOGIC'=>'OR', array('TITLE'=>$storeName), array('ADDRESS'=>$storeName), array('CODE'=>$storeName), array('XML_ID'=>$storeName)), 'select'=>array('ID'))); if($arr = $dbRes->Fetch()) $this->storeKeys[$storeName] = $arr['ID']; else $this->storeKeys[$storeName] = 0; } if($this->storeKeys[$storeName] > 0) { $arFieldsProductStores[$this->storeKeys[$storeName]]['AMOUNT'] = $this->GetFloatVal($arStoreParts[1]); } } } public function SaveElementId($ID, $type='E') { $oProfile = CKDAImportProfile::getInstance(); $isNew = $oProfile->SaveElementId($ID, $type); if($type=='S') $this->logger->SaveSectionChanges($ID); else $this->logger->SaveElementChanges($ID); return $isNew; } public function IsChangedElement() { return $this->logger->IsChangedElement(); } public function IsFacetChanges($val=null) { if(is_bool($val)) $this->facetChanges = $val; else return $this->facetChanges; } public function AfterElementAdd($IBLOCK_ID, $ID) { \Bitrix\KdaImportexcel\DataManager\InterhitedpropertyValues::ClearElementValues($IBLOCK_ID, $ID); if($this->IsFacetChanges() && class_exists('\Bitrix\Iblock\PropertyIndex\Manager')) \Bitrix\Iblock\PropertyIndex\Manager::updateElementIndex($IBLOCK_ID, $ID); } public function BeforeElementSave($ID, $type="update") { $this->IsFacetChanges(false); $this->logger->SetNewElement($ID, $type, $this->worksheetCurrentRow); } public function DeleteElement($ID, $IBLOCK_ID) { $this->BeforeElementDelete($ID, $IBLOCK_ID); CIblockElement::Delete($ID); $this->AfterElementDelete($ID, $IBLOCK_ID); } public function BeforeElementDelete($ID, $IBLOCK_ID) { $this->logger->SetNewElement($ID, 'delete', $this->worksheetCurrentRow); } public function AfterElementDelete($ID, $IBLOCK_ID) { $this->AddTagIblock($IBLOCK_ID); $this->logger->AddElementChanges('IE_', array('ID'=>$ID)); $this->logger->SaveElementChanges($ID); } public function BeforeSectionSave($ID, $type="update") { $this->logger->SetNewSection($ID, $type, $this->worksheetCurrentRow); } public function DeleteSection($ID, $IBLOCK_ID) { $this->BeforeSectionDelete($ID, $IBLOCK_ID); CIBlockSection::Delete($ID); $this->AfterSectionDelete($ID, $IBLOCK_ID); } public function BeforeSectionDelete($ID, $IBLOCK_ID) { $this->logger->SetNewSection($ID, 'delete', $this->worksheetCurrentRow); } public function AfterSectionDelete($ID, $IBLOCK_ID) { $this->AddTagIblock($IBLOCK_ID); $this->logger->AddSectionChanges(array('ID'=>$ID)); $this->logger->SaveSectionChanges($ID); } public function AfterSectionSave($ID, $IBLOCK_ID, $arFields, $arSection=array()) { $this->AddTagIblock($IBLOCK_ID); $this->logger->AddSectionChanges($arFields, $arSection); if(array_key_exists('SECTION_PROPERTIES', $arFields)) { if(!isset($this->iblockSP) || !isset($this->iblockSP[$IBLOCK_ID])) { if(\CIBlock::GetArrayByID($IBLOCK_ID, "SECTION_PROPERTY") != "Y") { $ib = new \CIBlock; $ib->Update($IBLOCK_ID, array('SECTION_PROPERTY'=>'Y')); } $this->iblockSP[$IBLOCK_ID] = true; $this->sectionProps[$IBLOCK_ID] = array(); $dbRes = \Bitrix\Iblock\SectionPropertyTable::getList(array("select" => array("SECTION_ID", "PROPERTY_ID"), "filter" => array("=IBLOCK_ID" => $IBLOCK_ID))); while($arr = $dbRes->Fetch()) { $this->sectionProps[$IBLOCK_ID][$arr['SECTION_ID']][$arr['PROPERTY_ID']] = $arr['PROPERTY_ID']; } if(!isset($this->iblockProps)) $this->iblockProps = array(); $this->iblockProps[$IBLOCK_ID] = array('IDS'=>array(), 'CODES'=>array(), 'NAMES'=>array()); $arFilter = array('IBLOCK_ID'=>$IBLOCK_ID); if($arOfferIblock = $this->GetCachedOfferIblock($IBLOCK_ID)) { $OFFERS_IBLOCK_ID = $arOfferIblock['OFFERS_IBLOCK_ID']; $arFilter['IBLOCK_ID'] = array($IBLOCK_ID, $OFFERS_IBLOCK_ID); } $dbRes = \Bitrix\Iblock\PropertyTable::getList(array('filter'=>$arFilter, 'select'=>array('ID', 'CODE', 'NAME', 'IBLOCK_ID'))); while($arr = $dbRes->Fetch()) { $this->iblockProps[$IBLOCK_ID]['IDS'][$arr['ID']] = $arr['ID']; if($arr['IBLOCK_ID']==$IBLOCK_ID || !isset($this->iblockProps[$IBLOCK_ID]['CODES'][$arr['CODE']])) $this->iblockProps[$IBLOCK_ID]['CODES'][$arr['CODE']] = $arr['ID']; if($arr['IBLOCK_ID']==$IBLOCK_ID || !isset($this->iblockProps[$IBLOCK_ID]['NAMES'][$arr['NAME']])) $this->iblockProps[$IBLOCK_ID]['NAMES'][$arr['NAME']] = $arr['ID']; } } $arPropCodes = array_diff(array_map('trim', explode($this->params['ELEMENT_MULTIPLE_SEPARATOR'], $arFields['SECTION_PROPERTIES'])), array('')); $arPropIds = array(); if(!empty($arPropCodes)) { foreach($arPropCodes as $code) { $propId = 0; if(isset($this->iblockProps[$IBLOCK_ID]['IDS'][$code])) $propId = $this->iblockProps[$IBLOCK_ID]['IDS'][$code]; elseif(isset($this->iblockProps[$IBLOCK_ID]['CODES'][$code])) $propId = $this->iblockProps[$IBLOCK_ID]['CODES'][$code]; elseif(isset($this->iblockProps[$IBLOCK_ID]['NAMES'][$code])) $propId = $this->iblockProps[$IBLOCK_ID]['NAMES'][$code]; if($propId > 0) $arPropIds[$propId] = $propId; } } if(!isset($this->sectionProps[$IBLOCK_ID][$ID])) $this->sectionProps[$IBLOCK_ID][$ID] = array(); if(!empty($arPropIds)) { $fs = $this->fieldSettings['ISECT_SECTION_PROPERTIES']; $arPropFields = array(); if(strlen($fs['SECTPROPS_SMART_FILTER']) > 0) $arPropFields['SMART_FILTER'] = $fs['SECTPROPS_SMART_FILTER']; if(strlen($fs['SECTPROPS_DISPLAY_EXPANDED']) > 0) $arPropFields['DISPLAY_EXPANDED'] = $fs['SECTPROPS_DISPLAY_EXPANDED']; foreach($arPropIds as $propId) { if(isset($this->sectionProps[$IBLOCK_ID][0][$propId])) { \CIBlockSectionPropertyLink::Delete(0, $propId); unset($this->sectionProps[$IBLOCK_ID][0][$propId]); } if(!isset($this->sectionProps[$IBLOCK_ID][$ID][$propId]) || !empty($arPropFields)) { \CIBlockSectionPropertyLink::Set($ID, $propId, $arPropFields); $this->sectionProps[$IBLOCK_ID][$ID][$propId] = $propId; } } foreach($this->sectionProps[$IBLOCK_ID][$ID] as $propId) { if(!isset($arPropIds[$propId])) { \CIBlockSectionPropertyLink::Delete($ID, $propId); unset($this->sectionProps[$IBLOCK_ID][$ID][$propId]); } } } elseif(in_array('-', $arPropCodes)) { foreach($this->sectionProps[$IBLOCK_ID][$ID] as $propId) { \CIBlockSectionPropertyLink::Delete($ID, $propId); unset($this->sectionProps[$IBLOCK_ID][$ID][$propId]); } } } if($this->params['REMOVE_COMPOSITE_CACHE_PART']=='Y') { if($arSection = \CIblockSection::GetList(array(), array('ID'=>$ID, 'CHECK_PERMISSIONS' => 'N'), false, array('SECTION_PAGE_URL'))->GetNext()) { $this->ClearCompositeCache($arSection['SECTION_PAGE_URL']); } } } public function ApplyMargins($val, $fieldKey) { if(is_array($fieldKey)) $arParams = $fieldKey; else $arParams = $this->fieldSettings[$fieldKey]; $val = $this->GetFloatVal($val); $sval = $val; $margins = $arParams['MARGINS']; if(is_array($margins) && count($margins) > 0) { foreach($margins as $margin) { if((strlen(trim($margin['PRICE_FROM']))==0 || $sval >= $this->GetFloatVal($margin['PRICE_FROM'])) && (strlen(trim($margin['PRICE_TO']))==0 || $sval <= $this->GetFloatVal($margin['PRICE_TO']))) { if($margin['PERCENT_TYPE']=='F') $val += ($margin['TYPE'] > 0 ? 1 : -1)*$this->GetFloatVal($margin['PERCENT']); else $val *= (1 + ($margin['TYPE'] > 0 ? 1 : -1)*$this->GetFloatVal($margin['PERCENT'])/100); } } } /*Rounding*/ $roundRule = $arParams['PRICE_ROUND_RULE']; $roundRatio = $arParams['PRICE_ROUND_COEFFICIENT']; $roundRatio = str_replace(',', '.', $roundRatio); if(!preg_match('/^[\d\.]+$/', $roundRatio)) $roundRatio = 1; if($roundRule=='ROUND') $val = round($val / $roundRatio) * $roundRatio; elseif($roundRule=='CEIL') $val = ceil($val / $roundRatio) * $roundRatio; elseif($roundRule=='FLOOR') $val = floor($val / $roundRatio) * $roundRatio; /*/Rounding*/ return $val; } public function SetTimeBegin($ID) { if($this->stepparams['begin_time']) return; $dbRes = CIblockElement::GetList(array(), array('ID'=>$ID, 'CHECK_PERMISSIONS' => 'N'), false, false, array('TIMESTAMP_X')); if($arr = $dbRes->Fetch()) { $this->stepparams['begin_time'] = $arr['TIMESTAMP_X']; } } public function IsEmptyPrice($arPrices) { if(is_array($arPrices)) { foreach($arPrices as $arPrice) { if($arPrice['PRICE'] > 0) { return false; } } } return true; } public function GetHLBoolValue($val) { $res = $this->GetBoolValue($val); if($res=='Y') return 1; else return 0; } public function GetBoolValue($val, $numReturn = false, $defaultValue = false) { $trueVals = array_map('trim', explode(',', Loc::getMessage("KDA_IE_FIELD_VAL_Y"))); $falseVals = array_map('trim', explode(',', Loc::getMessage("KDA_IE_FIELD_VAL_N"))); if(in_array(ToLower($val), $trueVals)) { return ($numReturn ? 1 : 'Y'); } elseif(in_array(ToLower($val), $falseVals)) { return ($numReturn ? 0 : 'N'); } else { return $defaultValue; } } public function GetFieldExtraKey($fieldName) { $key = ''; if(strpos($fieldName, 'IP_PROP')===0) $key = 'P'.substr($fieldName, 7); if(strlen($key) > 0) $key = '__'.$key; return $key; } public function GetShareFieldSettings($fieldName) { if(strlen($fieldName)==0) return array(); $fieldSettings = array(); if(isset($this->fieldSettings[$fieldName])) { $fieldSettings = $this->fieldSettings[$fieldName]; } elseif(($extraKey = $this->GetFieldExtraKey($fieldName)) && isset($this->fieldSettingsExtra[$extraKey])) { $fieldSettings = $this->fieldSettingsExtra[$extraKey]; } if(!is_array($fieldSettings)) $fieldSettings = array(); return $fieldSettings; } public function GetStyleCellValue($arItem, $level) { $sectName = ''; $sectKey = -1; if($this->sectioncolumn!==false) { $sectName = $arItem[$this->sectioncolumn]; $sectKey = $this->sectioncolumn; } else { foreach($arItem as $k=>$v) { if(is_numeric($k) && strlen($v) > 0) { $sectName = $v; $sectKey = $k; break; } } } $levelSettings = (isset($this->fieldSettingsExtra['__'.$level]) ? $this->fieldSettingsExtra['__'.$level] : array()); $conversions = array(); if($sectKey >= 0 && isset($this->fieldSettingsExtra['SECTION_'.$sectKey])) $conversions = $this->fieldSettingsExtra['SECTION_'.$sectKey]['CONVERSION']; elseif(isset($levelSettings['CONVERSION'])) $conversions = $levelSettings['CONVERSION']; if(!empty($conversions)) { $sectName = $this->ApplyConversions($sectName, $conversions, $arItem); } return $sectName; } public function SetSectionSeparate($arItem, $IBLOCK_ID, $SECTION_ID, $level) { $sectName = $this->GetStyleCellValue($arItem, $level); if(!$sectName) return false; $pVersion = \CKDAImportProfile::getInstance()->GetImportParam('PROFILE_VERSION'); if($pVersion > 2) $sectName = preg_replace("/^'(\s+)(\S)/", '$2', $sectName); $arFields = array(); $filedList = $this->params['FIELDS_LIST'][$this->worksheetNumForSave]; $iblockFields = $this->GetIblockFields($IBLOCK_ID); $levelSettings = (isset($this->fieldSettingsExtra['__'.$level]) ? $this->fieldSettingsExtra['__'.$level] : array()); foreach($filedList as $key=>$field) { if(!preg_match('/^ISECT'.(intval($level) > 0 ? '('.$level.')?' : '').'_/', $field)) continue; $k = $key; if(strpos($k, '_')!==false) $k = substr($k, 0, strpos($k, '_')); $value = $arItem[$k]; if($this->fieldSettings[$field]['NOT_TRIM']=='Y') $value = $arItem['~'.$k]; $origValue = $arItem['~'.$k]; $conversions = (isset($this->fieldSettingsExtra[$key]) ? $this->fieldSettingsExtra[$key]['CONVERSION'] : $this->fieldSettings[$field]['CONVERSION']); if(!empty($conversions)) { $value = $this->ApplyConversions($value, $conversions, $arItem, array('KEY'=>$k, 'NAME'=>$field), $iblockFields); $origValue = $this->ApplyConversions($origValue, $conversions, $arItem, array('KEY'=>$k, 'NAME'=>$field), $iblockFields); if($value===false) continue; } $fieldKey = preg_replace('/^ISECT\d*_/', '', $field); $adata = false; if(strpos($field, '|')!==false) { list($field, $adata) = explode('|', $field); $adata = explode('=', $adata); } $arSect = explode('_', substr($field, 5), 2); $arFields[$fieldKey] = $value; if(is_array($adata) && count($adata) > 1) { $arFields[$fieldKey] = $adata[1]; } } foreach($this->arSectionNames as $l=>$n) { if($l > $level) unset($this->arSectionNames[$l]); } $this->arSectionNames[$level] = $sectName; if($this->skipSepSection && $level > 1) { for($i=$level-1; $i>0; $i--) { if($this->skipSepSectionLevels[$i]) return true; } } $this->skipSepSection = false; $this->skipSepSectionLevels[$level] = false; if($this->UniCheckSkipLine($sectName, $levelSettings)) { //$this->stepparams['cursections'.$IBLOCK_ID] = array(); //unset($this->stepparams['cursections'.$IBLOCK_ID]); $this->skipSepSection = true; $this->skipSepSectionLevels[$level] = true; return true; } $arSections = $this->stepparams['cursections'.$IBLOCK_ID]; if(!is_array($arSections)) { $arSections = array(); if($SECTION_ID > 0) { $dbRes = CIBlockSection::GetList(array(), array('ID'=>$SECTION_ID, 'IBLOCK_ID'=>$IBLOCK_ID, 'CHECK_PERMISSIONS' => 'N'), false, array('ID', 'DEPTH_LEVEL')); if($arr = $dbRes->Fetch()) { $arSections[$arr['DEPTH_LEVEL']] = $arr['ID']; $this->stepparams['fsectionlevel'.$IBLOCK_ID] = $arr['DEPTH_LEVEL']; } } } $fLevel = (isset($this->stepparams['fsectionlevel'.$IBLOCK_ID]) ? $this->stepparams['fsectionlevel'.$IBLOCK_ID] : 0); /*Section path*/ if($level==0) { $sep = $this->GetSeparator($levelSettings['SECTION_PATH_SEPARATOR']); if(strlen(trim($sep))==0) $sep = '/'; $arNames = array_map('trim', explode($sep, $sectName)); $this->stepparams['last_section'] = end($arNames); $parent = 0; if($fLevel > 0) { $parent = $arSections[$fLevel - 1]; $level = $fLevel + 1; } foreach($arNames as $sectName) { $arFields = array_merge($arFields, array('NAME' => $sectName)); $sectId = $this->SaveSection($arFields, $IBLOCK_ID, $parent); if(is_array($sectId)) { if(count($sectId)==0) return true; $sectId = current($sectId); } if(!$sectId) return false; $arSections[$level] = $parent = $sectId; $level++; } foreach($arSections as $k=>$v) { if($k > $level-1) unset($arSections[$k]); } $this->stepparams['cursections'.$IBLOCK_ID] = $arSections; return true; } /*/Section path*/ if($fLevel > 0 /*&& $this->sectionstylesFl <= $fLevel*/) { $level += $fLevel - $this->sectionstylesFl + 1; } $parent = 0; $diff = 1; while(!isset($arSections[$level - $diff]) && ($level - $diff) >= 0) $diff++; if($arSections[$level - $diff]) $parent = $arSections[$level - $diff]; $this->stepparams['last_section'] = $sectName; $arFields = array_merge($arFields, array('NAME' => $sectName)); $sectId = $this->SaveSection($arFields, $IBLOCK_ID, $parent, 0, $levelSettings); if(is_array($sectId)) { if(count($sectId)==0) return true; $sectId = current($sectId); } if(!$sectId) return false; $arSections[$level] = $sectId; foreach($arSections as $k=>$v) { if($k > $level) unset($arSections[$k]); } $this->stepparams['cursections'.$IBLOCK_ID] = $arSections; return true; } public function SaveSection($arFields, $IBLOCK_ID, $parent=0, $level=0, $arParams=array()) { $sectionFields = $this->GetIblockSectionFields($IBLOCK_ID); $sectId = false; if(isset($arFields['ACTIVE'])) { $arFields['ACTIVE'] = $this->GetBoolValue($arFields['ACTIVE']); } $arTexts = array('DESCRIPTION'); foreach($arTexts as $keyText) { if($arFields[$keyText]) { $textFile = $_SERVER["DOCUMENT_ROOT"].$arFields[$keyText]; if(file_exists($textFile) && is_file($textFile) && is_readable($textFile)) { $arFields[$keyText] = file_get_contents($textFile); } } } foreach($arFields as $k=>$v) { $fieldSettings = array(); if(isset($this->fieldSettings['ISECT'.$level.'_'.$k])) $fieldSettings = $this->fieldSettings['ISECT'.$level.'_'.$k]; elseif($level==1 && isset($this->fieldSettings['ISECT_'.$k])) $fieldSettings = $this->fieldSettings['ISECT_'.$k]; if(isset($sectionFields[$k])) { $sParams = $sectionFields[$k]; if($sParams['MULTIPLE']=='Y') { $separator = $this->params['ELEMENT_MULTIPLE_SEPARATOR']; if($fieldSettings['CHANGE_MULTIPLE_SEPARATOR']=='Y') { $separator = $this->GetSeparator($fieldSettings['MULTIPLE_SEPARATOR']); } $arFields[$k] = array_map('trim', explode($separator, $arFields[$k])); $newVals = array(); foreach($arFields[$k] as $k2=>$v2) { $arFields[$k][$k2] = $this->GetSectionField($v2, $sParams, $fieldSettings); if(is_array($arFields[$k][$k2]) && isset($arFields[$k][$k2]['VALUES'])) { $newVals = array_merge($newVals, $arFields[$k][$k2]['VALUES']); unset($arFields[$k][$k2]); } } if(!empty($newVals)) $arFields[$k] = array_merge($arFields[$k], $newVals); } else { $arFields[$k] = $this->GetSectionField($arFields[$k], $sParams, $fieldSettings); } } if(strpos($k, 'IPROP_TEMP_')===0) { $arFields['IPROPERTY_TEMPLATES'][substr($k, 11)] = $v; unset($arFields[$k]); } elseif($k=='IBLOCK_SECTION_ID') { $arFields[$k] = $this->GetIblockSectionValue(array('LINK_IBLOCK_ID'=>$IBLOCK_ID), $v, $fieldSettings); } } if($parent > 0 && !$arFields['IBLOCK_SECTION_ID']) $arFields['IBLOCK_SECTION_ID'] = $parent; $sectionUid = $this->params['SECTION_UID']; if(!$arFields[$sectionUid]) $sectionUid = 'NAME'; $arFilter = array( $sectionUid=>$arFields[$sectionUid], 'IBLOCK_ID'=>$IBLOCK_ID, 'CHECK_PERMISSIONS' => 'N' ); if((!isset($arFields['IGNORE_PARENT_SECTION']) || $arFields['IGNORE_PARENT_SECTION']!='Y') && ($arParams['SECTION_SEARCH_WITHOUT_PARENT']!='Y' || $parent > 0)) $arFilter['SECTION_ID'] = $parent; else unset($arFields['IGNORE_PARENT_SECTION']); if($arParams['SECTION_SEARCH_IN_SUBSECTIONS']=='Y') { if($parent && $arParams['SECTION_SEARCH_WITHOUT_PARENT']!='Y') { //$dbRes2 = CIBlockSection::GetList(array(), array('IBLOCK_ID'=>$IBLOCK_ID, 'ID'=>$parent, 'CHECK_PERMISSIONS' => 'N'), false, array('ID', 'LEFT_MARGIN', 'RIGHT_MARGIN')); $dbRes2 = $this->GetListSection(array('IBLOCK_ID'=>$IBLOCK_ID, 'ID'=>$parent, 'CHECK_PERMISSIONS' => 'N'), array('ID', 'LEFT_MARGIN', 'RIGHT_MARGIN')); if($arParentSection = $dbRes2->Fetch()) { $arFilter['>LEFT_MARGIN'] = $arParentSection['LEFT_MARGIN']; $arFilter['<RIGHT_MARGIN'] = $arParentSection['RIGHT_MARGIN']; } } unset($arFilter['SECTION_ID']); } //$dbRes = CIBlockSection::GetList(array(), $arFilter, false, array_merge(array('ID'), array_keys($arFields))); $dbRes = $this->GetListSection($arFilter, array_merge(array('ID'), array_keys($arFields))); $arSections = array(); while($arSect = $dbRes->Fetch()) { $sectId = $arSect['ID']; if($this->params['ONLY_CREATE_MODE_SECTION']!='Y') { $this->PrepareSectionPictures($arFields, $arSect); if(($arParams['SECTION_SEARCH_IN_SUBSECTIONS']=='Y' || $arParams['SECTION_SEARCH_WITHOUT_PARENT']=='Y') && isset($arFields['IBLOCK_SECTION_ID'])) { unset($arFields['IBLOCK_SECTION_ID']); } $this->UpdateSection($sectId, $IBLOCK_ID, $arFields, $arSect, $sectionUid); } $arSections[] = $sectId; } if(empty($arSections) && $this->params['ONLY_UPDATE_MODE_SECTION']!='Y' && ($parent > 0 || $level < 2)) { if(!$arFields['NAME']) return false; $this->PrepareSectionPictures($arFields); $this->PrepareNewSectionFields($arFields, $IBLOCK_ID); $bs = new CIBlockSection; $sectId = $j = 0; $code = $arFields['CODE']; $jmax = ($sectionUid=='CODE' ? 1 : 1000); while($j<$jmax && !($sectId = $bs->Add($arFields, true, true, true)) && ($arFields['CODE'] = $code.strval(++$j))){} if($sectId) { $this->BeforeSectionSave($sectId, "add"); \Bitrix\KdaImportexcel\DataManager\InterhitedpropertyValues::ClearSectionValues($IBLOCK_ID, $sectId, $arFields); $this->AfterSectionSave($sectId, $IBLOCK_ID, $arFields); $this->SaveElementId($sectId, 'S'); $this->stepparams['section_added_line']++; } else { $this->errors[] = sprintf(Loc::getMessage("KDA_IE_ADD_SECTION_ERROR"), $arFields['NAME'], $bs->LAST_ERROR, $this->worksheetNumForSave+1, $this->worksheetCurrentRow); } $arSections[] = $sectId; } return $arSections; } public function PrepareNewSectionFields(&$arFields, $IBLOCK_ID) { $iblockFields = $this->GetIblockFields($IBLOCK_ID); if(!isset($arFields['ACTIVE'])) $arFields['ACTIVE'] = 'Y'; $arFields['IBLOCK_ID'] = $IBLOCK_ID; if(($iblockFields['SECTION_CODE']['IS_REQUIRED']=='Y' || $iblockFields['SECTION_CODE']['DEFAULT_VALUE']['TRANSLITERATION']=='Y') && strlen($arFields['CODE'])==0) { $arFields['CODE'] = $this->Str2Url($arFields['NAME'], $iblockFields['SECTION_CODE']['DEFAULT_VALUE']); } $sectionFields = $this->GetIblockSectionFields($IBLOCK_ID); foreach($sectionFields as $fname=>$arField) { if($arField['MANDATORY']=='Y' && !array_key_exists($fname, $arFields)) { if(is_array($arField['SETTINGS']) && array_key_exists('DEFAULT_VALUE', $arField['SETTINGS'])) { $arFields[$fname] = $arField['SETTINGS']['DEFAULT_VALUE']; } else { $userType = $arField['USER_TYPE_ID']; if($userType=='enumeration') { $arFields[$fname] = $this->GetUserFieldEnumDefaultVal($arField); } } } } } public function GetListSection($arFilter, $arSelect, $arOrder=array()) { if(class_exists('\Bitrix\Iblock\SectionTable') && count(preg_grep('/^UF_/', array_merge(array_keys($arFilter), $arSelect)))==0) { if(array_key_exists('SECTION_ID', $arFilter)) { $arFilter['IBLOCK_SECTION_ID'] = $arFilter['SECTION_ID']; unset($arFilter['SECTION_ID']); } $arFields = array_keys(\Bitrix\Iblock\SectionTable::getMap()); $arKeys = array_flip($arFields); $arFilter = array_intersect_key($arFilter, $arKeys); $arSelect = array_intersect($arSelect, $arFields); $dbRes = \Bitrix\Iblock\SectionTable::GetList(array('filter'=>$arFilter, 'select'=>$arSelect, 'order'=>$arOrder)); } else { $dbRes = \CIBlockSection::GetList($arOrder, $arFilter, false, $arKeys); } return $dbRes; } public function UpdateSection($ID, $IBLOCK_ID, $arFields, $arSection, $sectionUid=false) { $this->BeforeSectionSave($ID, "update"); foreach($arSection as $k=>$v) { if($k=='PICTURE' || $k=='DETAIL_PICTURE') { if(empty($arFields[$k]) || !$this->IsChangedImage($v, $arFields[$k])) unset($arFields[$k]); } elseif(isset($arFields[$k]) && ($arFields[$k]==$v || ($k=='NAME' && ToLower($arFields[$k])==ToLower($v)) || $k==$sectionUid)) unset($arFields[$k]); } if(isset($arFields['IPROPERTY_TEMPLATES']) && is_array($arFields['IPROPERTY_TEMPLATES']) && count($arFields['IPROPERTY_TEMPLATES']) > 0) { $ipropValues = new \Bitrix\Iblock\InheritedProperty\SectionTemplates($IBLOCK_ID, $ID); $arTemplates = $ipropValues->findTemplates(); foreach($arFields['IPROPERTY_TEMPLATES'] as $k=>$v) { if(isset($arTemplates[$k]) && is_array($arTemplates[$k]) && isset($arTemplates[$k]['TEMPLATE'])) { if(($arTemplates[$k]['ENTITY_TYPE']=='S' && $arTemplates[$k]['TEMPLATE']==$v) || ($arTemplates[$k]['ENTITY_TYPE']!='S' && strlen($v)==0)) unset($arFields['IPROPERTY_TEMPLATES'][$k]); } } if(empty($arFields['IPROPERTY_TEMPLATES'])) unset($arFields['IPROPERTY_TEMPLATES']); } if(!empty($arFields)) { $bs = new CIBlockSection; $bs->Update($ID, $arFields, true, true, true); $this->AfterSectionSave($ID, $IBLOCK_ID, $arFields, $arSection); \Bitrix\KdaImportexcel\DataManager\InterhitedpropertyValues::ClearSectionValues($IBLOCK_ID, $ID, $arFields); } if($sectionUid) { if($this->SaveElementId($ID, 'S')) $this->stepparams['section_updated_line']++; } else { $this->logger->SaveSectionChanges($ID); } } public function GetSectionField($val, $sParams, $fieldSettings) { $userType = $sParams['USER_TYPE_ID']; if($userType=='file') { $val = $this->GetFileArray($val, array('MULTIPLE'=>$sParams['MULTIPLE'])); } elseif($userType=='boolean') { $val = $this->GetBoolValue($val, true); } elseif($userType=='enumeration') { $val = $this->GetUserFieldEnum($val, $sParams); } elseif($userType=='iblock_element') { $arProp = array('LINK_IBLOCK_ID' => $sParams['SETTINGS']['IBLOCK_ID']); $val = $this->GetIblockElementValue($arProp, $val, $fieldSettings); } elseif($userType=='iblock_section') { $arProp = array('LINK_IBLOCK_ID' => $sParams['SETTINGS']['IBLOCK_ID']); $val = $this->GetIblockSectionValue($arProp, $val, $fieldSettings); } return $val; } public function GetSections(&$arElement, $IBLOCK_ID, $SECTION_ID, $arSections) { if(!empty($this->sectionstyles) && !empty($this->stepparams['cursections'.$IBLOCK_ID])) { $sid = end($this->stepparams['cursections'.$IBLOCK_ID]); if($this->params['ELEMENT_ADD_NEW_SECTIONS']=='Y' && is_array($arElement['IBLOCK_SECTION'])) $arElement['IBLOCK_SECTION'][] = $sid; else $arElement['IBLOCK_SECTION'] = array($sid); return true; } $fromSectionWoLevel = (bool)(!empty($arSections) && count($arSections)==1 && isset($arSections[0]) && count(array_diff($arSections[0], array(''))) > 0); $arMultiSections = array(); if(isset($arSections[0]) && isset($arSections[0]['PATH_NAMES'])) { if(!is_array($arElement['SECTION_PATH']) && $fromSectionWoLevel && strlen($arSections[0]['PATH_NAMES']) > 0) { $sep = (isset($this->fieldSettings['ISECT_PATH_NAMES']['SECTION_PATH_SEPARATOR']) && strlen($this->fieldSettings['ISECT_PATH_NAMES']['SECTION_PATH_SEPARATOR']) > 0 ? $this->fieldSettings['ISECT_PATH_NAMES']['SECTION_PATH_SEPARATOR'] : '/'); $arSectionPaths = array_diff(array_map('trim', explode($sep, $arSections[0]['PATH_NAMES'])), array('')); if(count($arSectionPaths) > 0) $arElement['SECTION_PATH'] = array($arSectionPaths); } unset($arSections[0]['PATH_NAMES']); } if(is_array($arElement['SECTION_PATH'])) { foreach($arElement['SECTION_PATH'] as $sectionPath) { if(is_array($sectionPath)) { $tmpSections = array(); foreach($sectionPath as $k=>$name) { $tmpSections[$k+1]['NAME'] = $name; } $arMultiSections[] = $tmpSections; } } unset($arElement['SECTION_PATH']); } /*if no 1st level*/ if($SECTION_ID > 0 && !empty($arSections) && !isset($arSections[1]) && !$fromSectionWoLevel) { $minKey = min(array_keys($arSections)); $arSectionsOld = $arSections; $arSections = array(); foreach($arSectionsOld as $k=>$v) { $arSections[$k - $minKey + 1] = $v; } } /*/if no 1st level*/ if((empty($arSections) /*|| !isset($arSections[1]) || count(array_diff($arSections[1], array('')))==0*/) && empty($arMultiSections) && !$fromSectionWoLevel) { if($SECTION_ID > 0) { if($this->params['ELEMENT_ADD_NEW_SECTIONS']=='Y' && is_array($arElement['IBLOCK_SECTION'])) $arElement['IBLOCK_SECTION'][] = $SECTION_ID; else $arElement['IBLOCK_SECTION'] = array($SECTION_ID); return true; } return false; } $iblockFields = $this->GetIblockFields($IBLOCK_ID); if(empty($arMultiSections)) { if(isset($arSections[0]) && count($arSections) > 1) { while(count($arSections) > 1 && ($lkey = max(array_keys($arSections))) && !$arSections[$lkey][$this->params['SECTION_UID']] && !$arSections[$lkey][$this->params['NAME']]) { unset($arSections[$lkey]); } $lkey = max(array_keys($arSections)); $arSections[$lkey] = array_merge($arSections[$lkey], $arSections[0]); unset($arSections[0]); } $arMultiSections[] = $arSections; $fromSectionPath = false; } else { if(count($arMultiSections) > 0 && !empty($arSections)) { foreach($arMultiSections as $k=>$v) { foreach($arSections as $k2=>$v2) { $lkey = $k2; if($v2[$this->params['SECTION_UID']]) { $fsKey = 'ISECT'.$k2.'_'.$this->params['SECTION_UID']; if($this->fieldSettings[$fsKey]['SECTION_SEARCH_IN_SUBSECTIONS'] == 'Y') { $lkey = max(array_keys($v)); $v2['IGNORE_PARENT_SECTION'] = 'Y'; } } if($lkey==0) $lkey = max(array_keys($v)); if(isset($v[$lkey])) { $arMultiSections[$k][$lkey] = array_merge($v[$lkey], $v2); } elseif($v2[$this->params['SECTION_UID']]) { $arMultiSections[$k][$lkey] = $v2; } } } } $fromSectionPath = true; } foreach($arMultiSections as $arSections) { $parent = $i = 0; $arParents = array(); if($SECTION_ID) { $parent = $SECTION_ID; $arParents[] = $SECTION_ID; } if($fromSectionWoLevel && !$fromSectionPath) { $arSections = array(1 => array_merge($arSections[0], array('IGNORE_PARENT_SECTION'=>($SECTION_ID ? 'N' : 'Y')))); } while(++$i && !empty($arSections[$i])) { $sectionUid = $this->params['SECTION_UID']; if(!isset($arSections[$i][$sectionUid]) || strlen($arSections[$i][$sectionUid])==0) $sectionUid = 'NAME'; if(!isset($arSections[$i][$sectionUid]) || strlen($arSections[$i][$sectionUid])==0) continue; if($fromSectionPath) $fsKey = 'IE_SECTION_PATH'; else { $ii = $i; if($SECTION_ID > 0 && isset($minKey)) $ii = $i + $minKey - 1; $fsKey = 'ISECT'.$ii.'_'.$sectionUid; } if(($this->fieldSettings[$fsKey]['SECTION_UID_SEPARATED']=='Y' || $fromSectionWoLevel) /*&& empty($arSections[$i+1])*/) { $arNames = array_map('trim', explode($this->params['ELEMENT_MULTIPLE_SEPARATOR'], $arSections[$i][$sectionUid])); $arNames = array_diff($arNames, array('')); } else { $arNames = array($arSections[$i][$sectionUid]); } if(empty($arNames)) continue; $arParents = array(); $parentLvl = array(); $parent2 = (is_array($parent) ? $parent : array($parent)); foreach($parent2 as $parent) { foreach($arNames as $name) { if(isset($this->sections[$parent][$name]) && !empty($this->sections[$parent][$name]) && count($arSections[$i]) < 2) { $parentLvl = array_merge($parentLvl, $this->sections[$parent][$name]); } else { $arFields = $arSections[$i]; $arFields[$sectionUid] = $name; $sectId = $this->SaveSection($arFields, $IBLOCK_ID, $parent, $i, $this->fieldSettings[$fsKey]); $this->sections[$parent][$name] = $sectId; if(!empty($sectId)) $parentLvl = array_merge($parentLvl, $sectId); } $arParents = array_merge($arParents, $parentLvl); } } $parent = array_diff($parentLvl, array(0, false)); if(is_array($parent) && count($parent)==1) $parent = current($parent); if(!$parent) { $parent = 0; /*continue;*/ break; } } if(!empty($arParents)) { if(!is_array($arElement['IBLOCK_SECTION'])) $arElement['IBLOCK_SECTION'] = array(); $arElement['IBLOCK_SECTION'] = array_unique(array_merge($arElement['IBLOCK_SECTION'], $arParents)); $arElement['IBLOCK_SECTION_ID'] = current($arElement['IBLOCK_SECTION']); } elseif($sectionUid=='ID' && count($arSections)==1 && isset($arSections[1][$sectionUid]) && $arSections[1][$sectionUid]==='0') { $arElement['IBLOCK_SECTION_ID'] = 0; } } } public function GetIblockDefaultProperties($IBLOCK_ID) { if(!array_key_exists($IBLOCK_ID, $this->defprops)) { $arSectionProps = array(); if(class_exists('\Bitrix\Iblock\SectionPropertyTable')) { $dbRes = \Bitrix\Iblock\SectionPropertyTable::getList(array('filter'=>array( 'IBLOCK_ID' => $IBLOCK_ID, '>SECTION_ID' => 0 ), 'select'=>array('PROPERTY_ID'), 'group'=>array('PROPERTY_ID'))); $arSectionProps = array(); while($arr = $dbRes->Fetch()) { $arSectionProps[$arr['PROPERTY_ID']] = $arr['PROPERTY_ID']; } } $arDefProps = array(); $arListsId = array(); $arProps = $this->GetIblockProperties($IBLOCK_ID); foreach($arProps as $arProp) { if(isset($arSectionProps[$arProp['ID']])) continue; if($arProp['PROPERTY_TYPE']=='L') { $arListsId[] = $arProp['ID']; } elseif($arProp['USER_TYPE']=='directory') { $val = $this->GetHighloadBlockValue($arProp, array('UF_DEF'=>1)); if(!is_array($val) && $val!==false && strlen($val) > 0 && $val!='purple') $arDefProps[$arProp['ID']] = $val; } elseif(!is_array($arProp['DEFAULT_VALUE']) && strlen(trim($arProp['DEFAULT_VALUE'])) > 0) { $arDefProps[$arProp['ID']] = $arProp['DEFAULT_VALUE']; } } if(count($arListsId) > 0 && class_exists('\Bitrix\Iblock\PropertyEnumerationTable')) { $dbRes = \Bitrix\Iblock\PropertyEnumerationTable::getList(array('filter'=>array('PROPERTY_ID'=>$arListsId, 'DEF'=>'Y'), 'select'=>array('PROPERTY_ID', 'ID'))); while($arr = $dbRes->Fetch()) { $arDefProps[$arr['PROPERTY_ID']] = $arr['ID']; } } $this->defprops[$IBLOCK_ID] = $arDefProps; } return $this->defprops[$IBLOCK_ID]; } public function GetIblockProperties($IBLOCK_ID, $byName = false) { if(!$this->props[$IBLOCK_ID]) { $this->props[$IBLOCK_ID] = array(); $this->propsByNames[$IBLOCK_ID] = array(); $this->propsByCodes[$IBLOCK_ID] = array(); $dbRes = CIBlockProperty::GetList(array(), array('IBLOCK_ID'=>$IBLOCK_ID)); while($arProp = $dbRes->Fetch()) { $this->props[$IBLOCK_ID][$arProp['ID']] = $arProp; $this->propsByNames[$IBLOCK_ID][ToLower($arProp['NAME'])] = $arProp; $this->propsByCodes[$IBLOCK_ID][ToLower($arProp['CODE'])] = $arProp; } } if(is_string($byName) && $byName=='CODE') return $this->propsByCodes[$IBLOCK_ID]; elseif($byName) return $this->propsByNames[$IBLOCK_ID]; else return $this->props[$IBLOCK_ID]; } public function GetIblockPropertyByName($name, $IBLOCK_ID, $createNew = false, $params = array()) { $lowerName = ToLower($name); $arProps = $this->GetIblockProperties($IBLOCK_ID, true); if(isset($arProps[$lowerName])) return $arProps[$lowerName]; $arPropsByCode = $this->GetIblockProperties($IBLOCK_ID, 'CODE'); if(isset($arPropsByCode[$lowerName])) return $arPropsByCode[$lowerName]; if($createNew) { $arParams = array( 'max_len' => 50, 'change_case' => 'U', 'replace_space' => '_', 'replace_other' => '_', 'delete_repeat_replace' => 'Y', ); $code = CUtil::translit($name, LANGUAGE_ID, $arParams); $code = preg_replace('/[^a-zA-Z0-9_]/', '', $code); $code = preg_replace('/^[0-9_]+/', '', $code); if(isset($params['PROPLIST_NEWPROP_PREFIX']) && is_string($params['PROPLIST_NEWPROP_PREFIX'])) { $code = trim($params['PROPLIST_NEWPROP_PREFIX']).$code; } if(isset($arPropsByCode[ToLower($code)])) return $arPropsByCode[ToLower($code)]; $arFields = Array( "NAME" => $name, "ACTIVE" => "Y", "CODE" => $code, "PROPERTY_TYPE" => "S", "IBLOCK_ID" => $IBLOCK_ID ); if(isset($params['PROPLIST_NEWPROP_SORT']) && strlen(trim($params['PROPLIST_NEWPROP_SORT'])) > 0) $arFields['SORT'] = (int)$params['PROPLIST_NEWPROP_SORT']; if(isset($params['PROPLIST_NEWPROP_TYPE'])) { if(in_array($params['PROPLIST_NEWPROP_TYPE'], array('S', 'N', 'L'))) $arFields['PROPERTY_TYPE'] = $params['PROPLIST_NEWPROP_TYPE']; elseif(strpos($params['PROPLIST_NEWPROP_TYPE'], ':')!==false) { $arFields['PROPERTY_TYPE'] = current(explode(':', $params['PROPLIST_NEWPROP_TYPE'])); $arFields['USER_TYPE'] = end(explode(':', $params['PROPLIST_NEWPROP_TYPE'])); } } $ibp = new CIBlockProperty; if(isset($params['PROPLIST_NEWPROP_MULTIPLE']) && $params['PROPLIST_NEWPROP_MULTIPLE']=='Y') $arFields['MULTIPLE'] = 'Y'; if(isset($params['PROPLIST_NEWPROP_SMART_FILTER']) && $params['PROPLIST_NEWPROP_SMART_FILTER']=='Y') { $arFields['SMART_FILTER'] = 'Y'; if(\CIBlock::GetArrayByID($arFields["IBLOCK_ID"], "SECTION_PROPERTY") != "Y") { $ib = new \CIBlock; $ib->Update($arFields["IBLOCK_ID"], array('SECTION_PROPERTY'=>'Y')); } } if(isset($params['PROPLIST_NEWPROP_DISPLAY_EXPANDED']) && $params['PROPLIST_NEWPROP_DISPLAY_EXPANDED']=='Y') $arFields['DISPLAY_EXPANDED'] = 'Y'; if(strlen($arFields['CODE']) > 0) { $index = 0; while(($dbRes2 = CIBlockProperty::GetList(array(), array('CODE'=>$arFields['CODE'], 'IBLOCK_ID'=>$arFields['IBLOCK_ID']))) && ($arr2 = $dbRes2->Fetch())) { $index++; $arFields['CODE'] = substr($arFields['CODE'], 0, 50 - strlen($index)).$index; } } $propID = $ibp->Add($arFields); if(!$propID) return false; if(is_callable(array('\Bitrix\Iblock\Model\PropertyFeature', 'isEnabledFeatures')) && \Bitrix\Iblock\Model\PropertyFeature::isEnabledFeatures()) { $arFeaturesFields = array(); $arFeaturesKeys = preg_grep('/^PROPLIST_NEWPROP_FEATURE_.+:.+/', array_keys($params)); foreach($arFeaturesKeys as $fKey) { if($params[$fKey]!='Y') continue; $fKey = substr($fKey, 25); $arKeys = explode(':', $fKey); $arFeaturesFields[$fKey] = array( 'PROPERTY_ID' => $propID, 'MODULE_ID' => $arKeys[0], 'FEATURE_ID' => $arKeys[1], 'IS_ENABLED' => 'Y' ); } if(!empty($arFeaturesFields)) \Bitrix\Iblock\Model\PropertyFeature::setFeatures($propID, $arFeaturesFields); } $dbRes = CIBlockProperty::GetList(array(), array('ID'=>$propID)); if($arProp = $dbRes->Fetch()) { $this->props[$IBLOCK_ID][$arProp['ID']] = $arProp; $this->propsByNames[$IBLOCK_ID][ToLower($arProp['NAME'])] = $arProp; return $arProp; } } return false; } public function GetIblockPropertyByCode($code, $IBLOCK_ID) { $code = trim($code); $lowerCode = ToLower($code); $arProps = $this->GetIblockProperties($IBLOCK_ID, 'CODE'); if(isset($arProps[$lowerCode])) return $arProps[$lowerCode]; return false; } public function GetIblockPropertyById($id, $IBLOCK_ID) { $id = (int)$id; $arProps = $this->GetIblockProperties($IBLOCK_ID); if(isset($arProps[$id])) return $arProps[$id]; return false; } public function RemoveProperties($ID, $IBLOCK_ID, $isOffer=false) { if($this->conv->IsAlreadyLoaded($ID)) { if($this->lastOffElemId==$ID) $this->lastOffElemId = 0; else return false; } if(is_array($this->params['ADDITIONAL_SETTINGS'][$this->worksheetNum]['ELEMENT_PROPERTIES_REMOVE'])) { $arIds = $this->params['ADDITIONAL_SETTINGS'][$this->worksheetNum]['ELEMENT_PROPERTIES_REMOVE']; } else { $arIds = $this->params['ELEMENT_PROPERTIES_REMOVE']; } if(is_array($arIds) && !empty($arIds)) { $arIblockProps = $this->GetIblockProperties($IBLOCK_ID); $arProps = $arFieldsProductStores = $arFieldsProduct = $arFieldsPrices = array(); foreach($arIds as $k=>$v) { if(strpos($v, 'ICAT_STORE')===0) { $arStore = explode('_', substr($v, 10), 2); $arFieldsProductStores[$arStore[0]][$arStore[1]] = '-'; } else { if(strpos($v, 'IP_PROP')===0) $pid = (int)substr($v, strlen('IP_PROP')); else $pid = (int)$v; if($pid > 0) { if($arIblockProps[$pid]['PROPERTY_TYPE']=='F') $arProps[$pid] = array("del"=>"Y"); else $arProps[$pid] = false; } } } if(!empty($arProps) && !$isOffer) { \CIBlockElement::SetPropertyValuesEx($ID, $IBLOCK_ID, $arProps); } if(!empty($arFieldsProductStores)) { $this->SaveProduct($ID, $IBLOCK_ID, $arFieldsProduct, $arFieldsPrices, $arFieldsProductStores); } } } public function GetMultiplePropertyChange(&$val) { if(is_array($val)) { if(isset($val['VALUE']) && !is_array($val['VALUE'])) { $val2 = $val['VALUE']; $valOrig = $val; if($this->GetMultiplePropertyChangeItem($val2)) { $val = array(); foreach($val2 as $k=>$v) { $val[$k] = array_merge($valOrig, array('VALUE'=>$v)); } return true; } } else { $newVals = array(); foreach($val as $k=>$v) { if(is_numeric($k) && $this->GetMultiplePropertyChange($v)) { $newVals = array_merge($newVals, $v); unset($val[$k]); } } if(count($newVals) > 0) { $val = array_merge($val, $newVals); return true; } } } else { if($this->GetMultiplePropertyChangeItem($val)) return true; } return false; } public function GetMultiplePropertyChangeItem(&$val) { if(preg_match_all('/(\+|\-)\s*\{\s*(((["\'])(.*)\4[,\s]*)+)\s*\}/Uis', $val, $m)) { $rest = $val; foreach($m[0] as $k=>$v) { $rest = str_replace($v, '', $rest); } if(strlen(trim($rest))==0) { $addVals = array(); $removeVals = array(); foreach($m[0] as $k=>$v) { if(preg_match_all('/(["\'])(.*)\1/Uis', $v, $m2)) { $sign = $m[1][$k]; foreach($m2[2] as $v2) { if($sign=='+') $addVals[] = $v2; elseif($sign=='-') $removeVals[] = $v2; } } } if(count($addVals) > 0 || count($removeVals) > 0) { $val = array(); foreach($addVals as $av) $val['ADD_'.md5($av)] = $av; foreach($removeVals as $rv) $val['REMOVE_'.md5($rv)] = $rv; return true; } } } return false; } public function GetMultipleProperty($val, $k) { $separator = $this->params['ELEMENT_MULTIPLE_SEPARATOR']; $fsKey = ($this->conv->GetSkuMode() ? 'OFFER_' : '').'IP_PROP'.$k; if($this->fieldSettings[$fsKey]['CHANGE_MULTIPLE_SEPARATOR']=='Y') { $separator = $this->GetSeparator($this->fieldSettings[$fsKey]['MULTIPLE_SEPARATOR']); } if(is_array($val)) { if(count(preg_grep('/\D/', array_keys($val))) > 0 && count(preg_grep('/^\d+$/', array_keys($val))) == 0) { /*Exception for user types*/ $arVal = array($val); } else { $arVal = array(); foreach($val as $subval) { if(is_array($subval)) $arVal[] = $subval; else $arVal = array_merge($arVal, array_map('trim', explode($separator, $subval))); } } } else { if(is_array($val)) $arVal = $val; else $arVal = array_map('trim', explode($separator, $val)); } return $arVal; } public function CheckRequiredProps($arProps, $IBLOCK_ID, $ID=false) { if($this->needCheckReqProps) { $arErrors = array(); $arReqProps = $this->GetRequiredProps($IBLOCK_ID); foreach($arReqProps as $propId=>$propName) { if(array_key_exists($propId, $arProps) && $this->IsEmptyVal($arProps[$propId])) { $arErrors[] = sprintf(Loc::getMessage("KDA_IE_REQPROP_EMPTY"), $propName); } elseif($ID==false && !array_key_exists($propId, $arProps)) { $arErrors[] = sprintf(Loc::getMessage("KDA_IE_REQPROP_EMPTY_NOT_SET"), $propName); } } if(count($arErrors) > 0) { $this->SetLastError(implode('<br>', $arErrors)); return false; } } return true; } public function IsEmptyVal($propVal) { return (bool)((!is_array($propVal) && strlen($propVal)==0) || (is_array($propVal) && count(array_diff($propVal, array('')))==0)); } public function GetRequiredProps($IBLOCK_ID) { if(!isset($this->arRequiredProperties)) $this->arRequiredProperties = array(); if(!isset($this->arRequiredProperties[$IBLOCK_ID])) { $arProps = array(); if(class_exists('\Bitrix\Iblock\PropertyTable')) { $dbRes = \Bitrix\Iblock\PropertyTable::getList(array('filter'=>array('IBLOCK_ID'=>$IBLOCK_ID, 'IS_REQUIRED'=>'Y'), 'select'=>array('ID', 'NAME'))); while($arr = $dbRes->fetch()) { $arProps[$arr['ID']] = $arr['NAME']; } } $this->arRequiredProperties[$IBLOCK_ID] = $arProps; } return $this->arRequiredProperties[$IBLOCK_ID]; } public function PropReplaceId(&$v, $k=false) { if(strpos($v, '#ID#')!==false) $v = str_replace('#ID#', $this->propReplaceProdId, $v); } public function SaveProperties($ID, $IBLOCK_ID, $arProps, $needUpdate = false, $arFieldsElement=array()) { if(empty($arProps)/* && !$needUpdate*/) return false; $propsDef = $this->GetIblockProperties($IBLOCK_ID); $fieldList = $this->params['FIELDS_LIST'][$this->worksheetNumForSave]; $this->propReplaceProdId = $ID; foreach($arProps as $k=>$prop) { if(!is_array($prop)) $this->PropReplaceId($arProps[$k]); else array_walk_recursive($arProps[$k], array($this, 'PropReplaceId')); if(!is_numeric($k)) continue; if(($propsDef[$k]['USER_TYPE']=='directory' || $propsDef[$k]['PROPERTY_TYPE']=='L') && $propsDef[$k]['MULTIPLE']=='Y' && is_array($prop)) { $newProp = array(); foreach($prop as $k2=>$v2) { $arVal = $this->GetMultipleProperty($v2, $k); foreach($arVal as $k3=>$v3) { $newProp[$k3][$k2] = $v3; } } $arProps[$k] = $newProp; } //if($propsDef[$k]['PROPERTY_TYPE']=='F' && $propsDef[$k]['MULTIPLE']=='Y' && is_array($prop)) if($propsDef[$k]['ACTIVE']=='N') { unset($arProps[$k]); } } if(!empty($arProps)) { $arOldProps = array(); $arOldPropIds = array(); $dbRes = CIBlockElement::GetProperty($IBLOCK_ID, $ID, array(), Array("ID"=>array_keys($arProps))); while($arr = $dbRes->Fetch()) { if(isset($arProps[$arr['ID']])) { $propVal = $arr['VALUE']; $propValId = $arr['PROPERTY_VALUE_ID']; if(is_array($propVal)) $propVal = serialize($propVal); $newPropVal = $arProps[$arr['ID']]; if(is_array($newPropVal) && isset($newPropVal[0])) $newPropVal = $newPropVal[0]; if(is_array($newPropVal)) { if(isset($newPropVal['VALUE'], $newPropVal['DESCRIPTION'])) { $propVal = array( 'VALUE' => $arr['VALUE'], 'DESCRIPTION' => (is_array($newPropVal['DESCRIPTION']) && is_array(unserialize($arr['DESCRIPTION'])) ? unserialize($arr['DESCRIPTION']) : $arr['DESCRIPTION']), ); } elseif(isset($newPropVal['VALUE'])) $propVal = array('VALUE' => $arr['VALUE']); } if($arr['MULTIPLE']=='Y') { if(!is_array($arOldProps[$arr['ID']])) $arOldProps[$arr['ID']] = array(); if(!is_array($arOldPropIds[$arr['ID']])) $arOldPropIds[$arr['ID']] = array(); //Fix error with some similar values if(/*(!is_string($propVal) || !in_array($propVal, $arOldProps[$arr['ID']])) &&*/ ($arr['PROPERTY_TYPE']!='F' || !empty($propVal))) { $arOldProps[$arr['ID']][] = $propVal; $arOldPropIds[$arr['ID']][] = $propValId; } } else { $arOldProps[$arr['ID']] = $propVal; $arOldPropIds[$arr['ID']] = $propValId; } } } foreach($arProps as $pk=>$pv) { if(!array_key_exists($pk, $arOldProps) && is_numeric($pk)) $arOldProps[$pk] = ''; } } foreach($arProps as $k=>$prop) { if(strpos($k, '_DESCRIPTION')!==false) continue; if($propsDef[$k]['MULTIPLE']=='Y') { $isChanges = $this->GetMultiplePropertyChange($prop); if($propsDef[$k]['USER_TYPE']=='directory' || $propsDef[$k]['PROPERTY_TYPE']=='L') $arVal = (is_array($prop) ? $prop : array($prop)); elseif($isChanges && is_array($prop)) $arVal = $prop; else $arVal = $this->GetMultipleProperty($prop, $k); $origVals = $arVal; $newVals = array(); foreach($arVal as $k2=>$val) { $arVal[$k2] = $this->GetPropValue($propsDef[$k], (is_string($val) ? trim($val) : $val), $arOldProps[$k], $origVals); if(is_array($arVal[$k2]) && isset($arVal[$k2]['VALUES'])) { $newVals = array_merge($newVals, $arVal[$k2]['VALUES']); unset($arVal[$k2]); } elseif((is_array($arVal[$k2]) && empty($arVal[$k2])) && (count($arVal) > 1 || $propsDef[$k]['PROPERTY_TYPE']=='F')) { unset($arVal[$k2]); if(is_string($arProps[$k.'_DESCRIPTION']) && strlen($arProps[$k.'_DESCRIPTION']) > 0) { $arProps[$k.'_DESCRIPTION'] = $this->GetMultipleProperty($arProps[$k.'_DESCRIPTION'], $k.'_DESCRIPTION'); } if(is_array($arProps[$k.'_DESCRIPTION']) && array_key_exists($k2, $arProps[$k.'_DESCRIPTION'])) { unset($arProps[$k.'_DESCRIPTION'][$k2]); } } } if(!empty($newVals)) $arVal = array_merge($arVal, $newVals); $fsKey = ($this->conv->GetSkuMode() ? 'OFFER_' : '').'IP_PROP'.$k; $fromValue = $this->fieldSettings[$fsKey]['MULTIPLE_FROM_VALUE']; $toValue = $this->fieldSettings[$fsKey]['MULTIPLE_TO_VALUE']; if(is_numeric($fromValue) || is_numeric($toValue)) { $from = (is_numeric($fromValue) ? ((int)$fromValue >= 0 ? ((int)$fromValue - 1) : (int)$fromValue) : 0); $to = (is_numeric($toValue) ? ((int)$toValue >= 0 ? ((int)$toValue - max(0, $from)) : (int)$toValue) : 0); if($to!=0) $arVal = array_slice($arVal, $from, $to); else $arVal = array_slice($arVal, $from); } $arProps[$k] = ($isChanges ? $arVal : array_values($arVal)); if(is_array($arProps[$k.'_DESCRIPTION'])) $arProps[$k.'_DESCRIPTION'] = array_values($arProps[$k.'_DESCRIPTION']); } else { $arProps[$k] = $this->GetPropValue($propsDef[$k], $prop, $arOldProps[$k]); } if($propsDef[$k]['PROPERTY_TYPE']=='F' && is_array($arProps[$k]) && count(array_diff($arProps[$k], array('')))==0) { unset($arProps[$k]); } elseif($propsDef[$k]['PROPERTY_TYPE']=='S' && $propsDef[$k]['USER_TYPE']=='video') { \CIBlockElement::SetPropertyValueCode($ID, $k, $arProps[$k]); unset($arProps[$k]); } } foreach($arProps as $k=>$prop) { if(strpos($k, '_DESCRIPTION')===false) continue; $pk = substr($k, 0, strpos($k, '_')); if(!isset($arProps[$pk])) { $dbRes = CIBlockElement::GetProperty($IBLOCK_ID, $ID, array(), Array("ID"=>$pk)); while($arPropValue = $dbRes->Fetch()) { if($propsDef[$pk]['MULTIPLE']=='Y') { $arProps[$pk][] = $arPropValue['VALUE']; } else { $arProps[$pk] = $arPropValue['VALUE']; } } if(isset($arProps[$pk])) { if($propsDef[$pk]['PROPERTY_TYPE']=='F') { if(is_array($arProps[$pk])) { foreach($arProps[$pk] as $k2=>$v2) { $arProps[$pk][$k2] = self::MakeFileArray($v2); } } else { $arProps[$pk] = self::MakeFileArray($arProps[$pk]); } } } } if(isset($arProps[$pk])) { if($propsDef[$pk]['MULTIPLE']=='Y') { $arVal = $this->GetMultipleProperty($prop, $pk); foreach($arProps[$pk] as $k2=>$v2) { if(isset($arVal[$k2])) { if(is_array($v2) && isset($v2['VALUE'])) { $v2['DESCRIPTION'] = $arVal[$k2]; $arProps[$pk][$k2] = $v2; } else { $arProps[$pk][$k2] = array( 'VALUE' => $v2, 'DESCRIPTION' => $arVal[$k2] ); } if($propsDef[$pk]['PROPERTY_TYPE']=='F' && empty($arProps[$pk][$k2]['VALUE'])) unset($arProps[$pk][$k2]); elseif(!is_array($arProps[$pk][$k2]['DESCRIPTION']) && strlen(trim($arProps[$pk][$k2]['DESCRIPTION'])) > 0 && !is_array($arProps[$pk][$k2]['VALUE']) && strlen($arProps[$pk][$k2]['VALUE'])==0) $arProps[$pk][$k2]['VALUE'] = ' '; } } } else { if(is_array($arProps[$pk]) && isset($arProps[$pk]['VALUE'])) { $arProps[$pk]['DESCRIPTION'] = $prop; } else { $arProps[$pk] = array( 'VALUE' => $arProps[$pk], 'DESCRIPTION' => $prop ); } } } unset($arProps[$k]); } /*Delete unchanged props*/ if(!empty($arProps)) { foreach($arOldProps as $pk=>$pv) { $fsKey = ($this->conv->GetSkuMode() ? 'OFFER_' : '').'IP_PROP'.$pk; $saveOldVals = false; if($propsDef[$pk]['MULTIPLE']=='Y') { $saveOldVals = (bool)($this->fieldSettings[$fsKey]['MULTIPLE_SAVE_OLD_VALUES']=='Y'); if(!in_array($fsKey, $fieldList) && $this->fieldSettings['IP_LIST_PROPS']['PROPLIST_NEWPROP_SAVE_OLD_VALUES']=='Y') $saveOldVals = true; if(!$saveOldVals && isset($arProps[$pk]) && is_array($arProps[$pk]) && count(preg_grep('/^(ADD|REMOVE)_/', array_keys($arProps[$pk])))>0) $saveOldVals = true; } if($this->params['ELEMENT_IMAGES_FORCE_UPDATE']=='Y' && !$saveOldVals) continue; if($propsDef[$pk]['MULTIPLE']=='Y') { $isEmptyVals = false; foreach($arProps[$pk] as $fpk2=>$fpv2) { if(count($arProps[$pk]) > 1 && ((!is_array($fpv2) && strlen($fpv2)==0) || (is_array($fpv2) && isset($fpv2['VALUE']) && !is_array($fpv2['VALUE']) && strlen($fpv2['VALUE'])==0))) { $isEmptyVals = true; unset($arProps[$pk][$fpk2]); } } if($isEmptyVals) $arProps[$pk] = array_values($arProps[$pk]); if($propsDef[$pk]['PROPERTY_TYPE']!='F' && $saveOldVals) { $pv2 = $pv; foreach($arProps[$pk] as $fpk2=>$fpv2) { foreach($pv2 as $fpk=>$fpv) { if($this->IsEqProps($fpv, $fpv2) || (is_array($fpv) && is_array($fpv2) && $fpv['VALUE']==$fpv2['VALUE'])) { if(strpos($fpk2, 'REMOVE_')===0) unset($pv2[$fpk]); unset($arProps[$pk][$fpk2]); break; } } if(strpos($fpk2, 'REMOVE_')===0) unset($arProps[$pk][$fpk2]); } $arProps[$pk] = array_merge($pv2, $arProps[$pk]); $arProps[$pk] = array_diff($arProps[$pk], array('')); if($propsDef[$pk]['PROPERTY_TYPE']=='L') $arProps[$pk] = array_unique($arProps[$pk], SORT_REGULAR); if(count($arProps[$pk])==0 && count($pv) > 0) $arProps[$pk] = false; } } if($this->IsEqProps($arProps[$pk], $pv, $saveOldVals)) { unset($arProps[$pk]); } elseif(in_array($propsDef[$pk]['PROPERTY_TYPE'], array('L', 'E', 'G')) && $propsDef[$pk]['MULTIPLE']=='Y' && is_array($arProps[$pk]) && is_array($pv) && !isset($pv['VALUE']) && (count($arProps[$pk])==count($pv) || (($arProps[$pk]=CKDAImportUtils::ArrayUnique($arProps[$pk])) && count($arProps[$pk])==count($pv)))) { $newVal1 = array(); $newVal2 = array(); foreach($arProps[$pk] as $tmpKey=>$tmpVal) { if(is_array($tmpVal)){ksort($tmpVal); $tmpVal = serialize($tmpVal);} $newVal1[$tmpKey] = $tmpVal; } foreach($pv as $tmpKey=>$tmpVal) { if(is_array($tmpVal)){ksort($tmpVal); $tmpVal = serialize($tmpVal);} $newVal2[$tmpKey] = $tmpVal; } if(count(array_diff($newVal1, $newVal2))==0 && count(array_diff($newVal2, $newVal1))==0) unset($arProps[$pk]); } elseif($propsDef[$pk]['PROPERTY_TYPE']=='S' && $propsDef[$pk]['USER_TYPE']=='HTML') { if(!is_array($pv) && strlen($pv) > 0 && is_array($newVal2 = unserialize($pv))) { if((!is_array($arProps[$pk]) && $arProps[$pk]==$newVal2['TEXT']) || $arProps[$pk]['VALUE']==$newVal2) { unset($arProps[$pk]); } } } elseif($propsDef[$pk]['PROPERTY_TYPE']=='F') { if($propsDef[$pk]['MULTIPLE']=='Y') { if($saveOldVals) { foreach($arProps[$pk] as $fpk2=>$fpv2) { foreach($pv as $fpk=>$fpv) { if(!$this->IsChangedImage($fpv, $fpv2)) { unset($arProps[$pk][$fpk2]); break; } } } if(!is_array($arProps[$pk])) $arProps[$pk] = array(); $arProps[$pk] = array_merge($pv, $arProps[$pk]); foreach($arProps[$pk] as $fpk2=>$fpv2) { if(is_numeric($fpv2)) $arProps[$pk][$fpk2] = self::MakeFileArray($fpv2); } $arProps[$pk] = array_diff($arProps[$pk], array('')); } $isChange = false; $arTmpProp = array(); foreach($arProps[$pk] as $fpk=>$fpv) { $isOneChange = true; foreach($pv as $fpk2=>$fpv2) { if(!$this->IsChangedImage($fpv2, $fpv)) { $arTmpProp[$arOldPropIds[$pk][$fpk2]] = array('VALUE'=>array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0), 'DESCRIPTION'=>(isset($arOldProps[$pk][$fpk2]['DESCRIPTION']) ? $arOldProps[$pk][$fpk2]['DESCRIPTION'] : '')); $isOneChange = false; if($fpk!=$fpk2) $isChange = true; unset($pv[$fpk2]); break; } } if($isOneChange) { $arTmpProp['n'.$fpk] = $fpv; $isChange = true; } } if(count($pv) > 0) { $isChange = true; foreach($pv as $fpk=>$fpv) { $arTmpProp[$arOldPropIds[$pk][$fpk]] = array('VALUE'=>array('del'=>'Y')); } } if(!$isChange) unset($arProps[$pk]); else $arProps[$pk] = $arTmpProp; } else { if(!$this->IsChangedImage($pv, $arProps[$pk])) { unset($arProps[$pk]); } } } } } /*/Delete unchanged props*/ $isProps = !empty($arProps); if($isProps) { CIBlockElement::SetPropertyValuesEx($ID, $IBLOCK_ID, $arProps); $this->logger->AddElementChanges('IP_PROP', $arProps, $arOldProps); } if($needUpdate) { /*$this->conv->SetElementId($ID); $this->conv->GetChangedElementFields($arFieldsElement, $ID); $this->conv->SetElementId(0);*/ $arFieldsElement = array(); if($isProps || !empty($arFieldsElement)) { $el = new CIblockElement(); $this->el->UpdateComp($ID, $arFieldsElement, false, true); $this->AddTagIblock($IBLOCK_ID); } } elseif($isProps && $this->params['ELEMENT_NOT_UPDATE_WO_CHANGES']=='Y') { $arFilterProp = $this->GetFilterProperties($IBLOCK_ID); if(!empty($arFilterProp) && count(array_intersect(array_keys($arProps), $arFilterProp)) > 0) { $this->IsFacetChanges(true); } $arSearchProp = $this->GetSearchProperties($IBLOCK_ID); if(!empty($arSearchProp) && count(array_intersect(array_keys($arProps), $arSearchProp)) > 0) { \CIBlockElement::UpdateSearch($ID, true); } } } public function IsEqProps($v1, $v2, $saveOldVals=false) { $eq = true; if(is_array($v1) || is_array($v2)) { if(!is_array($v1)) { if(is_array($v2) && array_key_exists('VALUE', $v2)) { $v1 = array('VALUE'=>$v1); if(array_key_exists('DESCRIPTION', $v2)) $v1['DESCRIPTION'] = ''; } else $v1 = array($v1); } if(!is_array($v2)) { if(is_array($v1) && array_key_exists('VALUE', $v1)) { $v2 = array('VALUE'=>$v2); if(array_key_exists('DESCRIPTION', $v1)) $v2['DESCRIPTION'] = ''; } else $v2 = array($v2); } if($saveOldVals) { if(isset($v1['TYPE'])) unset($v1['TYPE']); if(isset($v2['TYPE'])) unset($v2['TYPE']); } if(count($v1)==count($v2)) { foreach($v1 as $k=>$v) { if(!$this->IsEqProps($v, $v2[$k])) $eq = false; } } else $eq = false; } else $eq = (bool)($v1==$v2 && (is_array($v1) || is_array($v2) || strlen($v1)==strlen($v2))); return $eq; } public function GetFilterProperties($IBLOCK_ID) { if(!isset($this->arFilterProperties)) $this->arFilterProperties = array(); if(!isset($this->arFilterProperties[$IBLOCK_ID])) { $arProps = array(); if(class_exists('\Bitrix\Iblock\SectionPropertyTable')) { if(($arOfferIblock = \CKDAImportUtils::GetOfferIblockByOfferIblock($IBLOCK_ID)) && isset($arOfferIblock['IBLOCK_ID']) && $arOfferIblock['IBLOCK_ID'] > 0) $IBLOCK_ID = $arOfferIblock['IBLOCK_ID']; $dbRes = \Bitrix\Iblock\SectionPropertyTable::getList(array('filter'=>array('IBLOCK_ID'=>$IBLOCK_ID, 'SMART_FILTER'=>'Y'), 'group'=>array('PROPERTY_ID'), 'select'=>array('PROPERTY_ID'))); while($arr = $dbRes->fetch()) { $arProps[] = $arr['PROPERTY_ID']; } } $this->arFilterProperties[$IBLOCK_ID] = $arProps; } return $this->arFilterProperties[$IBLOCK_ID]; } public function GetSearchProperties($IBLOCK_ID) { if(!isset($this->arSearchProperties)) $this->arSearchProperties = array(); if(!isset($this->arSearchProperties[$IBLOCK_ID])) { $arProps = array(); if(class_exists('\Bitrix\Iblock\PropertyTable')) { $dbRes = \Bitrix\Iblock\PropertyTable::getList(array('filter'=>array('IBLOCK_ID'=>$IBLOCK_ID, 'SEARCHABLE'=>'Y'), 'select'=>array('ID'))); while($arr = $dbRes->fetch()) { $arProps[] = $arr['ID']; } } $this->arSearchProperties[$IBLOCK_ID] = $arProps; } return $this->arSearchProperties[$IBLOCK_ID]; } public function GetPropValue($arProp, $val, $oldVal=false, $arOrigVals=array()) { $fieldName = (isset($this->fieldSettings['OFFER_IP_PROP'.$arProp['ID']]) ? 'OFFER_' : '').'IP_PROP'.$arProp['ID']; $fieldSettings = $this->GetShareFieldSettings($fieldName); if($arProp['PROPERTY_TYPE']=='F') { $arFile = $this->GetFileArray($val, $arProp, $fieldName, $oldVal); if(empty($arFile) && isset($arOrigVals[0]) && preg_match('#^(http|https|ftp|ftps)://#i', trim($arOrigVals[0])) && !preg_match('#^(http|https|ftp|ftps)://#', trim($val))) { $newVal = preg_replace('#^((http|https|ftp|ftps)://[^/]*)/.*$#i', '$1', trim($arOrigVals[0])).trim($val); $arFile = $this->GetFileArray($newVal, $arProp, $fieldName, $oldVal, $val); } if(empty($arFile) && strpos($val, $this->params['ELEMENT_MULTIPLE_SEPARATOR'])!==false) { $arVals = array_diff(array_map('trim', explode($this->params['ELEMENT_MULTIPLE_SEPARATOR'], $val)), array('')); if(count($arVals) > 0 && ($newVal = current($arVals))) { $arFile = $this->GetFileArray($newVal, $arProp, $fieldName, $oldVal, $val); } } $val = $arFile; } elseif($arProp['PROPERTY_TYPE']=='L') { $val = $this->GetListPropertyValue($arProp, $val, (bool)($fieldSettings['PROPLIST_NOT_CREATE_VALS']!='Y')); } elseif($arProp['PROPERTY_TYPE']=='S' && $arProp['USER_TYPE']=='directory') { $val = $this->GetHighloadBlockValue($arProp, $val, true); } elseif($arProp['PROPERTY_TYPE']=='S' && $arProp['USER_TYPE']=='HTML') { if($fieldSettings['TEXT_HTML']=='text') $val = array('VALUE'=>array('TEXT'=>$val, 'TYPE'=>'TEXT')); elseif($fieldSettings['TEXT_HTML']=='html') $val = array('VALUE'=>array('TEXT'=>$val, 'TYPE'=>'HTML')); else $val = array('VALUE'=>array('TEXT'=>$val)); } elseif($arProp['PROPERTY_TYPE']=='S' && $arProp['USER_TYPE']=='video') { if(!is_array($val)) { $width = (int)$this->GetFloatVal($fieldSettings['VIDEO_WIDTH']); $height = (int)$this->GetFloatVal($fieldSettings['VIDEO_HEIGHT']); $val = Array('VALUE' => Array( 'PATH' => $val, 'WIDTH' => ($width > 0 ? $width : 400), 'HEIGHT' => ($height > 0 ? $height : 300), 'TITLE' => '', 'DURATION' => '', 'AUTHOR' => '', 'DATE' => '', 'DESC' => '' )); } } elseif($arProp['PROPERTY_TYPE']=='S' && $arProp['USER_TYPE']=='SAsproMaxRegionPhone') { if(!is_array($val) && strlen($val) > 0)$val = array('VALUE'=>\CUtil::JsObjectToPhp($val)); } elseif($arProp['USER_TYPE']=='DateTime' || $arProp['USER_TYPE']=='Date') { $val = $this->GetDateVal($val, ($arProp['USER_TYPE']=='Date' ? 'PART' : 'FULL')); } elseif($arProp['PROPERTY_TYPE']=='N' && $arProp['USER_TYPE']=='ym_service_category') { $val = $this->GetYMCategoryValue($val); } elseif($arProp['PROPERTY_TYPE']=='N' && $arProp['USER_TYPE']=='mcart_property_with_measure_units') { $lib = intval($arProp["LINK_IBLOCK_ID"]); $fm = trim($arProp["USER_TYPE_SETTINGS"]["FIELD_MULTIPLIER"]); $fb = trim($arProp["USER_TYPE_SETTINGS"]["FIELD_BASE"]); $ei = trim($arProp["USER_TYPE_SETTINGS"]["ELEMENT_ID"]); if($lib && $ei && strlen($fm) > 0 && strlen($fb) > 0) { if(!isset($this->mcartPropMeasure)) $this->mcartPropMeasure = array(); if(!isset($this->mcartPropMeasure[$arProp['ID']])) { $arMes = array(); $dbRes = \CIblockElement::GetList(array(), array('IBLOCK_ID'=>$lib, array('LOGIC'=>'OR', array('PROPERTY_'.$fb=>$ei), array('ID'=>$ei))), false, array('nTopCount'=>100), array('ID', 'NAME', 'PROPERTY_'.$fm, 'PROPERTY_ALTERNATIVE')); while($arr = $dbRes->Fetch()) { if(!array_key_exists($arr['ID'], $arMes)) { $arMes[$arr['ID']] = array( 'NAMES' => array($arr['NAME']), 'MULTIPLIER' => $arr['PROPERTY_'.$fm.'_VALUE'], ); } if(strlen($arr['PROPERTY_ALTERNATIVE_VALUE']) > 0) { $arMes[$arr['ID']]['NAMES'][] = $arr['PROPERTY_ALTERNATIVE_VALUE']; } } $this->mcartPropMeasure[$arProp['ID']] = $arMes; } $vName = $vMpl = $vId = ''; foreach($this->mcartPropMeasure[$arProp['ID']] as $mesId=>$mes) { foreach($mes['NAMES'] as $key=>$name) { if((strpos(ToLower($val), ToLower($name))!==false && strlen($name) > strlen($vName)) || (strpos($val, $name)!==false && strlen($name)==strlen($vName))) { $vName = $name; $vMpl = $mes['MULTIPLIER']; $vId = $mesId; } } } if(strlen($vName) > 0) { $valWoUnit = trim(str_replace(ToLower($vName), '', ToLower($val))); $val = array('VALUE'=>array('VALUE'=>$valWoUnit, 'ELEMENT_ID'=>$vId, 'BASE_VALUE'=>$this->GetFloatVal($valWoUnit)*$this->GetFloatVal($vMpl))); } } } elseif($arProp['PROPERTY_TYPE']=='N') { /*if(preg_match('/\d/', $val)) $val = $this->GetFloatVal($val); else $val = '';*/ } elseif($arProp['PROPERTY_TYPE']=='E' || $arProp['USER_TYPE']=='ElementXmlID') { $isMultiple = (bool)($arProp['MULTIPLE']=='Y'); $allowNF = !(bool)($fieldSettings['REL_ELEMENT_ALLOW_ORIG'] == 'Y'); $val = $this->GetIblockElementValue($arProp, $val, $fieldSettings, true, $allowNF, $isMultiple); if($isMultiple && is_array($val)) { $val = array('VALUES'=>$val); } } elseif($arProp['PROPERTY_TYPE']=='G') { $val = $this->GetIblockSectionValue($arProp, $val, $fieldSettings, true); } elseif($arProp['PROPERTY_TYPE']=='R' && $arProp['USER_TYPE']=='RegionsList' && \Bitrix\Main\Loader::includeModule("sotbit.regions")) { if(strlen($val) > 0) { if($arRegion = \Sotbit\Regions\Internals\RegionsTable::getList(array('filter'=>array('LOGIC'=>'OR', array('=NAME'=>trim($val)), array('ID'=>trim($val))), 'select'=>array('ID')))->Fetch()) $val = $arRegion['ID']; } } return $val; } public function GetDefaultElementFields(&$arElement, $iblockFields) { $arDefaultFields = array('ACTIVE', 'ACTIVE_FROM', 'ACTIVE_TO', 'NAME', 'PREVIEW_TEXT_TYPE', 'PREVIEW_TEXT', 'DETAIL_TEXT_TYPE', 'DETAIL_TEXT'); foreach($arDefaultFields as $fieldName) { if(!isset($arElement[$fieldName]) && $iblockFields[$fieldName]['IS_REQUIRED']=='Y' && isset($iblockFields[$fieldName]['DEFAULT_VALUE']) && is_string($iblockFields[$fieldName]['DEFAULT_VALUE']) && strlen($iblockFields[$fieldName]['DEFAULT_VALUE']) > 0) { $arElement[$fieldName] = $iblockFields[$fieldName]['DEFAULT_VALUE']; if($fieldName=='ACTIVE_FROM') { if($arElement[$fieldName]=='=now') $arElement[$fieldName] = ConvertTimeStamp(false, "FULL"); elseif($arElement[$fieldName]=='=today') $arElement[$fieldName] = ConvertTimeStamp(false, "SHORT"); else unset($arElement[$fieldName]); } elseif($fieldName=='ACTIVE_TO') { if((int)$arElement[$fieldName] > 0) $arElement[$fieldName] = ConvertTimeStamp(time()+(int)$arElement[$fieldName]*24*60*60, "FULL"); } } } $this->GenerateElementCode($arElement, $iblockFields); } public function GenerateElementCode(&$arElement, $iblockFields) { if(($iblockFields['CODE']['IS_REQUIRED']=='Y' || $iblockFields['CODE']['DEFAULT_VALUE']['TRANSLITERATION']=='Y') && strlen($arElement['CODE'])==0 && strlen($arElement['NAME'])>0) { $arElement['CODE'] = $this->Str2Url($arElement['NAME'], $iblockFields['CODE']['DEFAULT_VALUE']); if($iblockFields['CODE']['DEFAULT_VALUE']['UNIQUE']=='Y') { $i = 0; while(($tmpCode = $arElement['CODE'].($i ? '-'.mt_rand() : '')) && \Bitrix\KdaImportexcel\DataManager\IblockElementTable::ExistsElement(array('IBLOCK_ID'=>$arElement['IBLOCK_ID'], '=CODE'=>$tmpCode)) && ++$i){} $arElement['CODE'] = $tmpCode; } } } public function GetIblockFields($IBLOCK_ID) { if(!$this->iblockFields[$IBLOCK_ID]) { $this->iblockFields[$IBLOCK_ID] = CIBlock::GetFields($IBLOCK_ID); } return $this->iblockFields[$IBLOCK_ID]; } public function GetIblockSectionFields($IBLOCK_ID) { if(!isset($this->iblockSectionFields[$IBLOCK_ID])) { $dbRes = CUserTypeEntity::GetList(array(), array('ENTITY_ID' => 'IBLOCK_'.$IBLOCK_ID.'_SECTION')); $arProps = array(); while($arr = $dbRes->Fetch()) { $arProps[$arr['FIELD_NAME']] = $arr; } $this->iblockSectionFields[$IBLOCK_ID] = $arProps; } return $this->iblockSectionFields[$IBLOCK_ID]; } public function GetIblockElementValue($arProp, $val, $fsettings, $bAdd = false, $allowNF = false, $allowMultiple = false) { if(is_array($val) && count(preg_grep('/\D/', array_keys($val)))==0) { foreach($val as $k=>$v) { $val[$k] = $this->GetIblockElementValue($arProp, $v, $fsettings, $bAdd, $allowNF); } return $val; } if($arProp['USER_TYPE']=='ElementXmlID') { $bAdd = false; if(!$arProp['LINK_IBLOCK_ID']) { if($fsettings['CHANGE_LINKED_IBLOCK']=='Y' && !empty($fsettings['LINKED_IBLOCK'])) $arProp['LINK_IBLOCK_ID'] = $fsettings['LINKED_IBLOCK']; else $arProp['LINK_IBLOCK_ID'] = $this->iblockId; } } if(is_array($val) && isset($val['PRIMARY'])) return $this->GetIblockElementValueEx($arProp, $val, $bAdd, $allowNF, $allowMultiple); if(is_array($val)) $val = current($val); if(strlen($val)==0) return $val; $relField = $fsettings['REL_ELEMENT_FIELD']; if((!$relField || $relField=='IE_ID') && !is_numeric($val)) { $relField = 'IE_NAME'; $bAdd = false; } if(!$relField) $relField = 'IE_ID'; if(($relField && $arProp['LINK_IBLOCK_ID']) || $relField=='IE_ID') { $IBLOCK_ID = (int)(is_array($arProp['LINK_IBLOCK_ID']) ? current($arProp['LINK_IBLOCK_ID']) : $arProp['LINK_IBLOCK_ID']); $propsDef = ($IBLOCK_ID > 0 ? $this->GetIblockProperties($IBLOCK_ID) : array()); $arFilter = ($arProp['LINK_IBLOCK_ID'] ? array('IBLOCK_ID'=>$arProp['LINK_IBLOCK_ID']) : array()); $filterVal = $val; if(!is_array($filterVal) && strlen($this->Trim($filterVal))!=strlen($filterVal)) $filterVal = array($filterVal, $this->Trim($filterVal)); if(strpos($relField, 'IE_')===0) { $arFilter['='.substr($relField, 3)] = $filterVal; } elseif(strpos($relField, 'IP_PROP')===0) { $uid = substr($relField, 7); if($propsDef[$uid]['PROPERTY_TYPE']=='L') { $arFilter['=PROPERTY_'.$uid.'_VALUE'] = $filterVal; } else { /*if($arProp['PROPERTY_TYPE']=='S' && $arProp['USER_TYPE']=='directory') { $val = $this->GetHighloadBlockValue($arProp, $val); }*/ $arFilter['=PROPERTY_'.$uid] = $filterVal; } } $resField = ($arProp['USER_TYPE']=='ElementXmlID' ? 'XML_ID' : 'ID'); //$dbRes = CIblockElement::GetList(array('ID'=>'ASC'), $arFilter, false, array('nTopCount'=>1), array('ID')); $dbRes = \Bitrix\KdaImportexcel\DataManager\IblockElementTable::GetListComp($arFilter, array('ID', 'XML_ID'), array('ID'=>'ASC'), ($allowMultiple ? false : 1)); if($arElem = $dbRes->Fetch()) { $val = $arElem[$resField]; if($allowMultiple) { $arVals = array(); while($arElem = $dbRes->Fetch()) { $arVals[] = $arElem[$resField]; } if(count($arVals) > 0) { array_unshift($arVals, $val); $val = array_values($arVals); } } } elseif($bAdd && ($arFilter['NAME'] || $arFilter['=NAME']) && ($arFilter['IBLOCK_ID'] || $arFilter['=IBLOCK_ID'])) { $arFields = array(); foreach($arFilter as $k=>$v) { $arFields[str_replace('=', '', $k)] = $v; } $iblockFields = $this->GetIblockFields($arFields['IBLOCK_ID']); $this->GenerateElementCode($arFields, $iblockFields); $el = new CIblockElement(); $val = $el->Add($arFields, false, true, true); $this->AddTagIblock($arFields['IBLOCK_ID']); } elseif($allowNF) { return false; } } return $val; } public function GetIblockElementValueEx($arProp, $val, $bAdd = false, $allowNF = false, $allowMultiple = false) { $IBLOCK_ID = (int)$arProp['LINK_IBLOCK_ID']; $propsDef = ($IBLOCK_ID > 0 ? $this->GetIblockProperties($IBLOCK_ID) : array()); $defaultVal = current($val['PRIMARY']); $arElemFields = $arPropFields = $arElemFields2 = $arPropFields2 = array(); if(isset($val['EXTRA']) && is_array($val['EXTRA'])) { foreach($val['EXTRA'] as $fn=>$fv) { if(strpos($fn, 'IE_')===0) { $uid = substr($fn, 3); if($uid!=='ID') $arElemFields[$uid] = $fv; } elseif(strpos($fn, 'IP_PROP')===0) { $uid = substr($fn, 7); $arPropFields[$uid] = $fv; } } $arElemFields2 = $arElemFields; $arPropFields2 = $arPropFields; } $arFilter = array(); foreach($val['PRIMARY'] as $fn=>$fv) { if(!is_array($fv) && strlen($this->Trim($fv))!=strlen($fv)) $fv = array($fv, $this->Trim($fv)); elseif(!is_array($fv) && strlen($fv)==0) continue; if(strpos($fn, 'IE_')===0) { $uid = substr($fn, 3); //so slow /*if($uid=='ID') $arFilter[] = array('LOGIC'=>'OR', array('=ID' => $fv), array('=NAME' => $fv)); else {*/ if($uid=='ID' && !is_numeric($fv)){$uid = 'NAME'; $bAdd = false;} $arFilter['='.$uid] = $fv; $arElemFields2[$uid] = $fv; //} } elseif(strpos($fn, 'IP_PROP')===0) { $uid = substr($fn, 7); if($propsDef[$uid]['PROPERTY_TYPE']=='L') { $arFilter['=PROPERTY_'.$uid.'_VALUE'] = $fv; } elseif($propsDef[$uid]['PROPERTY_TYPE']=='S' && $propsDef[$uid]['USER_TYPE']=='directory') { $arFilter['=PROPERTY_'.$uid] = $this->GetHighloadBlockValue($propsDef[$uid], $fv); } elseif($propsDef[$uid]['PROPERTY_TYPE']=='E') { $arFilter['=PROPERTY_'.$uid] = $this->GetIblockElementValue($propsDef[$uid], $fv, $this->fieldSettings[$fn]); } else $arFilter['=PROPERTY_'.$uid] = $fv; $arPropFields2[$uid] = $fv; } } if(count($arFilter) > 0 && $IBLOCK_ID > 0) { $arFilter['IBLOCK_ID'] = $arElemFields2['IBLOCK_ID'] = $IBLOCK_ID; $arFilter['CHECK_PERMISSIONS'] = 'N'; } else return $defaultVal; $this->logger->SetDisableLog(); $resField = ($arProp['USER_TYPE']=='ElementXmlID' ? 'XML_ID' : 'ID'); $arKeys = array_merge(array('ID', 'XML_ID', 'NAME', 'IBLOCK_SECTION_ID', 'PREVIEW_PICTURE'), array_keys($arElemFields)); $dbRes = \Bitrix\KdaImportexcel\DataManager\IblockElementTable::GetListComp($arFilter, $arKeys, array('ID'=>'ASC'), ($allowMultiple ? false : 1)); if($arElem = $dbRes->Fetch()) { $val = $arElem[$resField]; if($allowMultiple) { $arVals = array(); while($arElem = $dbRes->Fetch()) { $arVals[] = $arElem[$resField]; } if(count($arVals) > 0) { array_unshift($arVals, $val); $val = array_values($arVals); } } else { if(count($arElemFields) > 0) { $this->UpdateElement($arElem['ID'], $IBLOCK_ID, $arElemFields, $arElem); } if(count($arPropFields) > 0) $this->SaveProperties($arElem['ID'], $IBLOCK_ID, $arPropFields); } } elseif($bAdd && $arElemFields2['NAME'] && $IBLOCK_ID > 0) { $iblockFields = $this->GetIblockFields($IBLOCK_ID); $this->GetDefaultElementFields($arElemFields2, $iblockFields); if($val = $this->AddElement($arElemFields2)) { if(count($arPropFields2) > 0) $this->SaveProperties($val, $IBLOCK_ID, $arPropFields2); $this->AddTagIblock($IBLOCK_ID); } } elseif($allowNF) $val = false; else $val = $defaultVal; $this->logger->SetEnableLog(); return $val; } public function GetIblockSectionValue($arProp, $val, $fsettings, $bAdd = false, $allowNF = false) { $relField = $fsettings['REL_SECTION_FIELD']; if((!$relField || $relField=='ID') && !is_numeric($val)) { $bAdd = false; $relField = 'NAME'; } if($relField && $relField!='ID' && $val && $arProp['LINK_IBLOCK_ID']) { $IBLOCK_ID = $arProp['LINK_IBLOCK_ID']; $arFilter = array( 'IBLOCK_ID' => $IBLOCK_ID , $relField => $val, 'CHECK_PERMISSIONS' => 'N' ); $dbRes = CIblockSection::GetList(array('ID'=>'ASC'), $arFilter, false, array('ID'), array('nTopCount'=>1)); if($arElem = $dbRes->Fetch()) { $val = $arElem['ID']; } elseif($bAdd && $relField=='NAME') { $arFields = array( "IBLOCK_ID" => $IBLOCK_ID , "NAME" => $val ); $iblockFields = $this->GetIblockFields($IBLOCK_ID ); if(($iblockFields['SECTION_CODE']['IS_REQUIRED']=='Y' || $iblockFields['SECTION_CODE']['DEFAULT_VALUE']['TRANSLITERATION']=='Y') && strlen($arFields['CODE'])==0) { $arFields['CODE'] = $this->Str2Url($arFields['NAME'], $iblockFields['SECTION_CODE']['DEFAULT_VALUE']); } $bs = new CIBlockSection; $sectId = $j = 0; $code = $arFields['CODE']; while($j<1000 && !($sectId = $bs->Add($arFields, true, true, true)) && ($arFields['CODE'] = $code.strval(++$j))){} $val = $sectId; } else $val = ''; } return $val; } public function GetUserFieldEnum($val, $fieldParam) { if(!isset($this->ufEnum)) $this->ufEnum = array(); if(!$this->ufEnum[$fieldParam['ID']]) { $arEnumVals = array(); $fenum = new \CUserFieldEnum(); $dbRes = $fenum->GetList(array(), array('USER_FIELD_ID'=>$fieldParam['ID'])); while($arr = $dbRes->Fetch()) { $arEnumVals[trim($arr['VALUE'])] = $arr['ID']; } $this->ufEnum[$fieldParam['ID']] = $arEnumVals; } $val = trim($val); $arEnumVals = $this->ufEnum[$fieldParam['ID']]; if(!isset($arEnumVals[$val])) { $fenum = new \CUserFieldEnum(); $arEnumValsOrig = array(); $dbRes = $fenum->GetList(array(), array('USER_FIELD_ID'=>$fieldParam['ID'])); while($arr = $dbRes->Fetch()) { $arEnumValsOrig[$arr['ID']] = $arr; } $arEnumValsOrig['n0'] = array('VALUE'=>$val); $fenum->SetEnumValues($fieldParam['ID'], $arEnumValsOrig); $arEnumVals = array(); $dbRes = $fenum->GetList(array(), array('USER_FIELD_ID'=>$fieldParam['ID'])); while($arr = $dbRes->Fetch()) { $arEnumVals[trim($arr['VALUE'])] = $arr['ID']; } $this->ufEnum[$fieldParam['ID']] = $arEnumVals; } return $arEnumVals[$val]; } public function GetUserFieldEnumDefaultVal($fieldParam) { if(!isset($this->ufEnumDefault)) $this->ufEnumDefault = array(); if(!array_key_exists($fieldParam['ID'], $this->ufEnumDefault)) { $val = ($fieldParam['MULTIPLE']=='Y' ? array() : ''); $fenum = new \CUserFieldEnum(); $dbRes = $fenum->GetList(array(), array('USER_FIELD_ID'=>$fieldParam['ID'], 'DEF'=>'Y')); while($arr = $dbRes->Fetch()) { if($fieldParam['MULTIPLE']=='Y') $val[] = $arr['ID']; else $val = $arr['ID']; } $this->ufEnumDefault[$fieldParam['ID']] = $val; } return $this->ufEnumDefault[$fieldParam['ID']]; } public function GetYMCategoryValue($val) { if($val && Loader::includeModule('yandex.market') && is_callable('\Yandex\Market\Ui\UserField\ServiceCategory\Provider', 'GetList')) { if(!isset($this->ymCategories) || !is_array($this->ymCategories)) { $arResult = \Yandex\Market\Ui\UserField\ServiceCategory\Provider::GetList(); $arCategories = array(); $currentTree = array(); $currentTreeDepth = 0; foreach ($arResult as $sectionKey => $section) { if ($section['DEPTH_LEVEL'] < $currentTreeDepth) { array_splice($currentTree, $section['DEPTH_LEVEL']); } $currentTree[$section['DEPTH_LEVEL']] = $section['NAME']; $currentTreeDepth = $section['DEPTH_LEVEL']; $arCategories[implode(' / ', $currentTree)] = $section['ID']; } $this->ymCategories = $arCategories; } return (isset($this->ymCategories[$val]) ? $this->ymCategories[$val] : $val); } return $val; } public function GetListPropertyValue($arProp, $val, $create=true) { if(!is_array($val)) $val = array('VALUE'=>$val); if($val['VALUE']!==false && strlen($val['VALUE']) > 0) { $cacheVals = $val['VALUE']; if(!isset($this->propVals[$arProp['ID']][$cacheVals])) { $dbRes = $this->GetIblockPropEnum(array("PROPERTY_ID"=>$arProp['ID'], "=VALUE"=>$val['VALUE'])); if($arPropEnum = $dbRes->Fetch()) { $arPropFields = $val; unset($arPropFields['VALUE']); $this->CheckXmlIdOfListProperty($arPropFields, $arProp['ID']); if(count($arPropFields) > 0) { $ibpenum = new CIBlockPropertyEnum; $ibpenum->Update($arPropEnum['ID'], $arPropFields); } $this->propVals[$arProp['ID']][$cacheVals] = $arPropEnum['ID']; } else { $this->propVals[$arProp['ID']][$cacheVals] = false; if($create) { if(!isset($val['XML_ID'])) $val['XML_ID'] = $this->Str2Url($val['VALUE']); $this->CheckXmlIdOfListProperty($val, $arProp['ID']); $ibpenum = new CIBlockPropertyEnum; if($propId = $ibpenum->Add(array_merge($val, array('PROPERTY_ID'=>$arProp['ID'])))) { $this->propVals[$arProp['ID']][$cacheVals] = $propId; } } } } $val = $this->propVals[$arProp['ID']][$cacheVals]; } elseif(!isset($val['VALUE']) && strlen($val['XML_ID']) > 0) { $cacheVals = 'XML_ID|||'.$val['XML_ID']; if(!isset($this->propVals[$arProp['ID']][$cacheVals])) { $dbRes = $this->GetIblockPropEnum(array("PROPERTY_ID"=>$arProp['ID'], "=XML_ID"=>$val['XML_ID'])); if($arPropEnum = $dbRes->Fetch()) { $this->propVals[$arProp['ID']][$cacheVals] = $arPropEnum['ID']; } else { $this->propVals[$arProp['ID']][$cacheVals] = false; } } $val = $this->propVals[$arProp['ID']][$cacheVals]; } return (!is_array($val) ? $val : false); } public function CheckXmlIdOfListProperty(&$val, $propID) { if(isset($val['XML_ID'])) { $val['XML_ID'] = trim($val['XML_ID']); if(strlen($val['XML_ID'])==0) { unset($val['XML_ID']); } else { $dbRes2 = $this->GetIblockPropEnum(array("PROPERTY_ID"=>$propID, "=XML_ID"=>$val['XML_ID'])); if($arPropEnum2 = $dbRes2->Fetch()) { unset($val['XML_ID']); } } } } public function GetHighloadBlockValue($arProp, $val, $bAdd=false) { if(is_array($val)) { if(count($val)==1 && array_key_exists('UF_NAME', $val) && is_array($val['UF_NAME'])) { $val = $val['UF_NAME']; } if(count(preg_grep('/\D/', array_keys($val)))==0) { foreach($val as $k=>$v) { $val[$k] = $this->GetHighloadBlockValue($arProp, $v, $bAdd); } return $val; } } if($val && Loader::includeModule('highloadblock') && $arProp['USER_TYPE_SETTINGS']['TABLE_NAME']) { $arFields = $val; if(!is_array($arFields)) { $arFields = array('UF_NAME'=>$arFields); } if($arFields['UF_XML_ID']) $cacheKey = 'UF_XML_ID_'.$arFields['UF_XML_ID']; elseif($arFields['UF_NAME']) $cacheKey = 'UF_NAME_'.$arFields['UF_NAME']; else $cacheKey = 'CUSTOM_'.md5(serialize($arFields)); if(!isset($this->propVals[$arProp['ID']][$cacheKey])) { if(!$this->hlbl[$arProp['ID']] || !$this->hlblFields[$arProp['ID']]) { $hlblock = \Bitrix\Highloadblock\HighloadBlockTable::getList(array('filter'=>array('TABLE_NAME'=>$arProp['USER_TYPE_SETTINGS']['TABLE_NAME'])))->fetch(); if(!$hlblock) return false; if(!$this->hlbl[$arProp['ID']]) { $entity = \Bitrix\Highloadblock\HighloadBlockTable::compileEntity($hlblock); $this->hlbl[$arProp['ID']] = $entity->getDataClass(); } if(!$this->hlblFields[$arProp['ID']]) { $dbRes = CUserTypeEntity::GetList(array(), array('ENTITY_ID'=>'HLBLOCK_'.$hlblock['ID'])); $arHLFields = array(); while($arHLField = $dbRes->Fetch()) { $arHLFields[$arHLField['FIELD_NAME']] = $arHLField; } $this->hlblFields[$arProp['ID']] = $arHLFields; } } $entityDataClass = $this->hlbl[$arProp['ID']]; $arHLFields = $this->hlblFields[$arProp['ID']]; foreach($arFields as $k=>$v) { if(!array_key_exists($k, $arHLFields)) unset($arFields[$k]); } /*if(count($arFields) > 1 && !$arFields['UF_NAME'] && !$arFields['UF_XML_ID'] || (!isset($arHLFields['UF_NAME']) || !isset($arHLFields['UF_XML_ID']))) return false;*/ if(empty($arFields) || !isset($arHLFields['UF_XML_ID'])) return false; $arFilter = array(); if(count($arFields)==1) { $this->PrepareHighLoadBlockFields($arFields, $arHLFields); $arFilter = $arFields; } elseif(isset($arFields['UF_XML_ID']) && strlen($arFields['UF_XML_ID']) > 0) $arFilter = array("UF_XML_ID"=>$arFields['UF_XML_ID']); elseif(isset($arFields['UF_NAME']) && strlen($arFields['UF_NAME']) > 0) $arFilter = array("UF_NAME"=>$arFields['UF_NAME']); if(count($arFilter)==0) return false; $dbRes2 = $entityDataClass::GetList(array('filter'=>$arFilter, 'select'=>array_merge(array('ID', 'UF_XML_ID'), array_keys($arFields)), 'limit'=>1)); if($arr2 = $dbRes2->Fetch()) { if(count($arFields) > 1) { $this->PrepareHighLoadBlockFields($arFields, $arHLFields, $arr2); $entityDataClass::Update($arr2['ID'], $arFields); } $this->propVals[$arProp['ID']][$cacheKey] = $arr2['UF_XML_ID']; } else { $this->PrepareHighLoadBlockFields($arFields, $arHLFields); if(!$arFields['UF_NAME']) return false; if(!$arFields['UF_XML_ID']) $arFields['UF_XML_ID'] = $this->Str2Url($arFields['UF_NAME'], array(), false); if(!$bAdd) return $arFields['UF_XML_ID']; if(!array_key_exists('UF_XML_ID', $arFilter)) { $xmlId = $arFields['UF_XML_ID']; while($entityDataClass::GetList(array('filter'=>array('=UF_XML_ID'=>$arFields['UF_XML_ID']), 'select'=>array('ID'), 'limit'=>1))->Fetch()) { $arFields['UF_XML_ID'] = $xmlId.'-'.mt_rand(); } } $dbRes = $entityDataClass::Add($arFields); if($dbRes->isSuccess()) { $this->propVals[$arProp['ID']][$cacheKey] = $arFields['UF_XML_ID']; } else { $this->propVals[$arProp['ID']][$cacheKey] = false; $this->Err(sprintf(Loc::getMessage("KDA_IE_ADD_HLBLELEM_ERROR"), implode(', ', $dbRes->GetErrorMessages()), $arProp['NAME'], $this->worksheetNumForSave+1, $this->worksheetCurrentRow)); } } } return $this->propVals[$arProp['ID']][$cacheKey]; } return $val; } public function PrepareHighLoadBlockFields(&$arFields, $arHLFields, $arOldVals=array()) { foreach($arFields as $k=>$v) { if(!isset($arHLFields[$k])) { unset($arFields[$k]); continue; } $type = $arHLFields[$k]['USER_TYPE_ID']; $settings = $arHLFields[$k]['SETTINGS']; if($arHLFields[$k]['MULTIPLE']=='Y') { $v = array_map('trim', explode($this->params['ELEMENT_MULTIPLE_SEPARATOR'], $v)); $arFields[$k] = array(); foreach($v as $k2=>$v2) { $arFields[$k][$k2] = $this->GetHighLoadBlockFieldVal($v2, $type, $settings, $arOldVals[$k]); } if($type=='file' && count(array_diff($arFields[$k], array('')))==0) unset($arFields[$k]); } else { $arFields[$k] = $this->GetHighLoadBlockFieldVal($v, $type, $settings, $arOldVals[$k]); if($type=='file' && !is_array($arFields[$k])) unset($arFields[$k]); } } } public function GetHighLoadBlockFieldVal($v, $type, $settings, $oldVal='') { if($type=='file') { $arFile = $this->GetFileArray($v, array(), '', $oldVal); if(array_key_exists('old_id', $arFile)) { $arFile = ''; } else { $arFile['del'] = 'Y'; $arFile['old_id'] = $oldVal; } return $arFile; } elseif($type=='integer' || $type=='double') { return $this->GetFloatVal($v); } elseif($type=='datetime') { return $this->GetDateVal($v); } elseif($type=='date') { return $this->GetDateVal($v, 'PART'); } elseif($type=='boolean') { return $this->GetHLBoolValue($v); } elseif($type=='hlblock') { return $this->GetHLHLValue($v, $settings); } else { return $v; } } public function GetHLHLValue($val, $arSettings) { if(!Loader::includeModule('highloadblock')) return $val; $hlblId = $arSettings['HLBLOCK_ID']; $fieldId = $arSettings['HLFIELD_ID']; if($val && $hlblId && $fieldId) { if(!is_array($this->hlhlbl)) $this->hlhlbl = array(); if(!is_array($this->hlhlblFields)) $this->hlhlblFields = array(); if(!is_array($this->hlPropVals)) $this->hlPropVals = array(); if(!isset($this->hlPropVals[$fieldId][$val])) { if(!$this->hlhlbl[$hlblId] || !$this->hlhlblFields[$hlblId]) { $hlblock = \Bitrix\Highloadblock\HighloadBlockTable::getList(array('filter'=>array('ID'=>$hlblId)))->fetch(); if(!$this->hlhlbl[$hlblId]) { $entity = \Bitrix\Highloadblock\HighloadBlockTable::compileEntity($hlblock); $this->hlhlbl[$hlblId] = $entity->getDataClass(); } if(!$this->hlhlblFields[$hlblId]) { $dbRes = CUserTypeEntity::GetList(array(), array('ENTITY_ID'=>'HLBLOCK_'.$hlblock['ID'])); $arHLFields = array(); while($arHLField = $dbRes->Fetch()) { $arHLFields[$arHLField['ID']] = $arHLField; } $this->hlhlblFields[$hlblId] = $arHLFields; } } $entityDataClass = $this->hlhlbl[$hlblId]; $arHLFields = $this->hlhlblFields[$hlblId]; if(!$arHLFields[$fieldId]) return false; $dbRes2 = $entityDataClass::GetList(array('filter'=>array($arHLFields[$fieldId]['FIELD_NAME']=>$val), 'select'=>array('ID'), 'limit'=>1)); if($arr2 = $dbRes2->Fetch()) { $this->hlPropVals[$fieldId][$val] = $arr2['ID']; } else { $arFields = array($arHLFields[$fieldId]['FIELD_NAME']=>$val); $dbRes2 = $entityDataClass::Add($arFields); $this->hlPropVals[$fieldId][$val] = $dbRes2->GetID(); } } return $this->hlPropVals[$fieldId][$val]; } return $val; } public function PrepareProductAdd(&$arFieldsProduct, $ID, $IBLOCK_ID) { if(!empty($arFieldsProduct)) return; if(!isset($this->catalogIblocks)) $this->catalogIblocks = array(); if(!isset($this->catalogIblocks[$IBLOCK_ID])) { $this->catalogIblocks[$IBLOCK_ID] = false; if(is_callable(array('\Bitrix\Catalog\CatalogIblockTable', 'getList'))) { if($arCatalog = \Bitrix\Catalog\CatalogIblockTable::getList(array('filter'=>array('IBLOCK_ID'=>$IBLOCK_ID), 'limit'=>1))->Fetch()) { $this->catalogIblocks[$IBLOCK_ID] = true; } } } if($this->catalogIblocks[$IBLOCK_ID]) $arFieldsProduct['ID'] = $ID; } public function AfterSaveProduct(&$arFieldsElement, $ID, $IBLOCK_ID, $isUpdate=false, $isOffer=false) { $this->SetProductQuantity($ID, $IBLOCK_ID); if(($this->params['ELEMENT_NO_QUANTITY_DEACTIVATE']=='Y' && floatval($this->productor->GetProductQuantity($ID, $IBLOCK_ID))<=0) || ($this->params['ELEMENT_NO_PRICE_DEACTIVATE']=='Y' && floatval($this->productor->GetProductPrice($ID, $IBLOCK_ID))<=0)) { if($isUpdate) $arFieldsElement['ACTIVE'] = 'N'; elseif(!isset($arFieldsElement['ACTIVE']) || $arFieldsElement['ACTIVE']!='N') { $el = new \CIblockElement(); $el->Update($ID, array('ACTIVE'=>'N', 'MODIFIED_BY' => $this->GetCurUserID()), false, true, true); $this->AddTagIblock($IBLOCK_ID); if($isOffer && ($arOfferIblock = CKDAImportUtils::GetOfferIblockByOfferIblock($IBLOCK_ID))) { $propId = $arOfferIblock['OFFERS_PROPERTY_ID']; $arOffer = \CIblockElement::GetList(array(), array('ID'=>$ID), false, false, array('PROPERTY_'.$propId, 'PROPERTY_'.$propId.'.ACTIVE'))->Fetch(); if($arOffer['PROPERTY_'.$propId.'_VALUE'] > 0) { $arElem = array('ACTIVE'=>$arOffer['PROPERTY_'.$propId.'ACTIVE']); $this->AfterSaveProduct($arElem, $arOffer['PROPERTY_'.$propId.'_VALUE'], $arOfferIblock['IBLOCK_ID']); } } } } } public function UpdateSectionPropertyLinks($IBLOCK_ID, $propId) { $arSectionIds = array(); $dbRes = \CIblockElement::GetList(array(), array('IBLOCK_ID'=>$IBLOCK_ID, '!PROPERTY_'.$propId=>false, '!IBLOCK_SECTION_ID'=>false), array('IBLOCK_SECTION_ID'), false, array('IBLOCK_SECTION_ID')); while($arr = $dbRes->Fetch()) { $arSectionIds[] = $arr['IBLOCK_SECTION_ID']; } if(1 || !empty($arSectionIds)) { $dbRes = \Bitrix\Iblock\SectionPropertyTable::getList(array("select" => array("SECTION_ID"), "filter" => array("=IBLOCK_ID" => $IBLOCK_ID, "=PROPERTY_ID"=>$propId))); while($arr = $dbRes->Fetch()) { if(!in_array($arr['SECTION_ID'], $arSectionIds)) { \Bitrix\Iblock\SectionPropertyTable::delete(array("IBLOCK_ID" => $IBLOCK_ID, "PROPERTY_ID"=>$propId, "SECTION_ID"=>$arr['SECTION_ID'])); } else { $arSectionIds = array_diff($arSectionIds, array($arr['SECTION_ID'])); } } foreach($arSectionIds as $sectionId) { \Bitrix\Iblock\SectionPropertyTable::add(array("IBLOCK_ID" => $IBLOCK_ID, "PROPERTY_ID"=>$propId, "SECTION_ID"=>$sectionId)); } } } public function SaveProduct($ID, $IBLOCK_ID, $arProduct, $arPrices=array(), $arStores=array(), $parentID=false) { $this->productor->SaveProduct($ID, $IBLOCK_ID, $arProduct, $arPrices, $arStores, $parentID); } public function SetProductQuantity($ID, $IBLOCK_ID=0) { $this->productor->SetProductQuantity($ID, $IBLOCK_ID); } public function SaveDiscount($ID, $IBLOCK_ID, $arFieldsProductDiscount, $name, $isOffer = false) { $this->GetDiscountManager()->SaveDiscount($ID, $IBLOCK_ID, $arFieldsProductDiscount, $name, $isOffer); } public function RemoveExpiredDiscount() { $this->GetDiscountManager()->RemoveExpiredDiscount(); } public function GetDiscountManager() { if(!isset($this->discountManager)) $this->discountManager = new \Bitrix\KdaImportexcel\DataManager\Discount($this); return $this->discountManager; } public function GetMeasureByStr($val) { if(!$val) return $val; if(!isset($this->measureList) || !is_array($this->measureList)) { $this->measureList = array(); $dbRes = CCatalogMeasure::getList(array(), array()); while($arr = $dbRes->Fetch()) { $this->measureList[$arr['ID']] = array_map('ToLower', $arr); } } $valCmp = trim(ToLower($val)); foreach($this->measureList as $k=>$v) { if(in_array($valCmp, array($v['MEASURE_TITLE'], $v['SYMBOL_RUS'], $v['SYMBOL_INTL'], $v['SYMBOL_LETTER_INTL']))) { return $k; } } if(array_key_exists($val, $this->measureList)) return $val; else return ''; } public function GetCurrencyRates() { if(!isset($this->currencyRates)) { $arRates = unserialize(\Bitrix\Main\Config\Option::get(static::$moduleId, 'CURRENCY_RATES', '')); if(!is_array($arRates)) $arRates = array(); if(!isset($arRates['TIME']) || $arRates['TIME'] < time() - 6*60*60) { $arRates2 = array(); $client = new \Bitrix\Main\Web\HttpClient(array('socketTimeout'=>20, 'disableSslVerification'=>true)); $res = $client->get('http://www.cbr.ru/scripts/XML_daily.asp'); if($res) { $xml = simplexml_load_string($res); if($xml->Valute) { foreach($xml->Valute as $val) { $numVal = $this->GetFloatVal((string)$val->Value); if($numVal > 0)$arRates2[(string)$val->CharCode] = (string)$numVal; } } } if(count($arRates2) > 1) { $arRates = $arRates2; $arRates['TIME'] = time(); \Bitrix\Main\Config\Option::set(static::$moduleId, 'CURRENCY_RATES', serialize($arRates)); } } if(Loader::includeModule('currency') && is_callable(array('\Bitrix\Currency\CurrencyTable', 'getList'))) { $dbRes = \Bitrix\Currency\CurrencyTable::getList(array('select'=>array('CURRENCY'))); while($arr = $dbRes->Fetch()) { if(!isset($arRates[$arr['CURRENCY']])) $arRates[$arr['CURRENCY']] = \CCurrencyRates::ConvertCurrency(1, $arr['CURRENCY'], 'RUB'); } } $this->currencyRates = $arRates; } return $this->currencyRates; } public function ConversionReplaceValuesFloat($m) { return $this->GetFloatVal($this->ConversionReplaceValues($m)); } public function ConversionReplaceValues($m) { $value = ''; $paramName = $m[0]; $quot = "'"; $isVar = false; if(preg_match('/^\$\{([\'"])(.*)[\'"]\}?$/', $paramName, $m2)) { $quot = $m2[1]; $paramName = $m2[2]; $isVar = true; } if(preg_match('/#CELL\d+#/', $paramName)) { $k = intval(substr($paramName, 5, -1)) - 1; if(is_array($this->currentItemValues) && isset($this->currentItemValues[$k])) $value = $this->currentItemValues[$k]; elseif($this->worksheet && ($val = $this->worksheet->getCellByColumnAndRow($k, $this->worksheetCurrentRow))) { $value = $this->GetCalculatedValue($val); } } elseif(preg_match('/#CELL(\d+)([\-\+]\d+)#/', $paramName, $m2)) { if($this->worksheet && ($val = $this->worksheet->getCellByColumnAndRow((int)$m2[1] - 1, $this->worksheetCurrentRow + (int)$m2[2]))) { $value = $this->GetCalculatedValue($val); } } elseif(preg_match('/#CELL_([A-Z]+\d+)#/', $paramName, $m2)) { if($this->worksheet && ($val = $this->worksheet->getCell($m2[1]))) { $value = $this->GetCalculatedValue($val); } } elseif(preg_match('/#CELL(~+)(\d+)#/', $paramName, $m2)) { $k = $m2[1].(intval($m2[2]) - 1); if(is_array($this->currentItemValues) && isset($this->currentItemValues[$k])) $value = $this->currentItemValues[$k]; } elseif($paramName=='#CLINK#') { if($this->useHyperlinks && strlen($this->currentFieldKey) > 0) { $value = $this->hyperlinks[$this->currentFieldKey]; } } elseif($paramName=='#CNOTE#') { if($this->useNotes && strlen($this->currentFieldKey) > 0) { $value = $this->notes[$this->currentFieldKey]; } } elseif($paramName=='#SEP_SECTION#') { $value = $this->stepparams['last_section']; } elseif($paramName=='#HASH#') { $hash = md5(serialize($this->currentItemValues).serialize($this->params['FIELDS_LIST'][$this->worksheetNumForSave])); $value = $hash; } elseif($paramName=='#FILENAME#') { $value = bx_basename($this->filename); } elseif($paramName=='#SHEETNAME#') { if(array_key_exists($this->worksheetNum, $this->worksheetNames)) $value = $this->worksheetNames[$this->worksheetNum]; else $value = (is_callable(array($this->worksheet, 'getTitle')) ? $this->worksheet->getTitle() : ''); } elseif($paramName=='#IMPORT_PROCESS_ID#') { $value = $this->stepparams['loggerExecId']; } elseif($paramName=='#DATETIME#') { $value = ConvertTimeStamp(false, 'FULL'); } elseif(in_array($paramName, $this->rcurrencies)) { $arRates = $this->GetCurrencyRates(); $k = trim($paramName, '#'); $value = (isset($arRates[$k]) ? floatval($arRates[$k]) : 1); } if($isVar) { $this->extraConvParams[$paramName] = $value; return '$this->extraConvParams['.$quot.$paramName.$quot.']'; } else return $value; } public function ApplyConversions($val, $arConv, $arItem, $field=false, $iblockFields=array()) { $arExpParams = array(); $fieldName = $fieldKey = false; if(!is_array($field)) { $fieldName = $field; } else { if($field['NAME']) $fieldName = $field['NAME']; if(strlen($field['KEY']) > 0) $fieldKey = $field['KEY']; if(strlen($field['PARENT_ID']) > 0) $arExpParams['PARENT_ID'] = $field['PARENT_ID']; } if(is_array($arConv)) { $execConv = false; $this->currentItemValues = $arItem; $prefixPattern = '#CELL~*\d+#|#CELL\d+[\-\+]\d+#|#CELL_[A-Z]+\d+#|#CLINK#|#CNOTE#|#HASH#|#FILENAME#|#SHEETNAME#|#IMPORT_PROCESS_ID#|#SEP_SECTION#|#DATETIME#|'.implode('|', $this->rcurrencies); $prefixPattern = '/(\$\{[\'"]('.$prefixPattern.')[\'"]\}|('.$prefixPattern.'))/'; foreach($arConv as $k=>$v) { $condVal = (string)$val; if((int)$v['CELL'] > 0) { $numCell = (int)$v['CELL'] - 1; if(array_key_exists($numCell, $arItem)) { $condVal = (array_key_exists('~~'.$numCell, $arItem) ? $arItem['~~'.$numCell] : $arItem[$numCell]); } else { $condVal = $this->GetCalculatedValue($this->worksheet->getCellByColumnAndRow($numCell, $this->worksheetCurrentRow)); } } if(strlen($v['FROM']) > 0) $v['FROM'] = preg_replace_callback($prefixPattern, array($this, 'ConversionReplaceValues'), $v['FROM']); if($v['CELL']=='ELSE') $v['WHEN'] = ''; $condValNum = $this->GetFloatVal($condVal); $fromNum = $this->GetFloatVal($v['FROM']); if(($v['CELL']=='ELSE' && !$execConv) || ($v['WHEN']=='EQ' && $condVal==$v['FROM']) || ($v['WHEN']=='NEQ' && $condVal!=$v['FROM']) || ($v['WHEN']=='GT' && $condValNum > $fromNum) || ($v['WHEN']=='LT' && $condValNum < $fromNum) || ($v['WHEN']=='GEQ' && $condValNum >= $fromNum) || ($v['WHEN']=='LEQ' && $condValNum <= $fromNum) || ($v['WHEN']=='BETWEEN' && $condValNum >= $this->GetFloatVal(explode('-', $v['FROM'])[0]) && $condValNum <= $this->GetFloatVal(explode('-', $v['FROM'])[1])) || ($v['WHEN']=='CONTAIN' && strpos($condVal, $v['FROM'])!==false) || ($v['WHEN']=='NOT_CONTAIN' && strpos($condVal, $v['FROM'])===false) || ($v['WHEN']=='BEGIN_WITH' && strpos($condVal, $v['FROM'])===0) || ($v['WHEN']=='ENDS_IN' && mb_substr($condVal, -mb_strlen($v['FROM']))===$v['FROM']) || ($v['WHEN']=='REGEXP' && preg_match('/'.ToLower($v['FROM']).'/i'.CKDAImportUtils::getUtfModifier(), ToLower($condVal))) || ($v['WHEN']=='NOT_REGEXP' && !preg_match('/'.ToLower($v['FROM']).'/i'.CKDAImportUtils::getUtfModifier(), ToLower($condVal))) || ($v['WHEN']=='EMPTY' && strlen($condVal)==0) || ($v['WHEN']=='NOT_EMPTY' && strlen($condVal) > 0) || ($v['WHEN']=='ANY')) { $this->currentFieldKey = $fieldKey; if(strlen($v['TO']) > 0) $v['TO'] = preg_replace_callback($prefixPattern, array($this, 'ConversionReplaceValues'), $v['TO']); if($v['THEN']=='REPLACE_TO') $val = $v['TO']; elseif($v['THEN']=='REMOVE_SUBSTRING' && strlen($v['TO']) > 0) $val = str_replace($v['TO'], '', $val); elseif($v['THEN']=='REPLACE_SUBSTRING_TO' && strlen($v['FROM']) > 0) { if($v['WHEN']=='REGEXP') { if(preg_match('/'.$v['FROM'].'/i'.CKDAImportUtils::getUtfModifier(), $val)) $val = preg_replace('/'.$v['FROM'].'/i'.CKDAImportUtils::getUtfModifier(), $v['TO'], $val); else $val = preg_replace('/'.ToLower($v['FROM']).'/i'.CKDAImportUtils::getUtfModifier(), $v['TO'], $val); } else $val = str_replace($v['FROM'], $v['TO'], $val); } elseif($v['THEN']=='ADD_TO_BEGIN') $val = $v['TO'].$val; elseif($v['THEN']=='ADD_TO_END') $val = $val.$v['TO']; elseif($v['THEN']=='LCASE') $val = ToLower($val); elseif($v['THEN']=='UCASE') $val = ToUpper($val); elseif($v['THEN']=='UFIRST') $val = preg_replace_callback('/^(\s*)(.*)$/', array('\Bitrix\KdaImportexcel\Conversion', 'UFirstCallback'), $val); elseif($v['THEN']=='UWORD') $val = implode(' ', array_map(array('\Bitrix\KdaImportexcel\Conversion', 'UWordCallback'), explode(' ', $val))); elseif($v['THEN']=='MATH_ROUND') $val = round($this->GetFloatVal($val), $this->GetFloatVal($v['TO'])); elseif($v['THEN']=='MATH_MULTIPLY') $val = \Bitrix\KdaImportexcel\IUtils::GetFloatRoundVal($this->GetFloatVal($val) * $this->GetFloatVal($v['TO'])); elseif($v['THEN']=='MATH_DIVIDE') $val = \Bitrix\KdaImportexcel\IUtils::GetFloatRoundVal($this->GetFloatVal($val) / $this->GetFloatVal($v['TO'])); elseif($v['THEN']=='MATH_ADD') $val = \Bitrix\KdaImportexcel\IUtils::GetFloatRoundVal($this->GetFloatVal($val) + $this->GetFloatVal($v['TO'])); elseif($v['THEN']=='MATH_SUBTRACT') $val = \Bitrix\KdaImportexcel\IUtils::GetFloatRoundVal($this->GetFloatVal($val) - $this->GetFloatVal($v['TO'])); elseif($v['THEN']=='MATH_ADD_PERCENT') $val = (strlen($val) > 0 ? \Bitrix\KdaImportexcel\IUtils::GetFloatRoundVal($this->GetFloatVal($val) * (1 + $this->GetFloatVal($v['TO'])/100)) : ''); elseif($v['THEN']=='MATH_SUBTRACT_PERCENT') $val = (strlen($val) > 0 ? \Bitrix\KdaImportexcel\IUtils::GetFloatRoundVal($this->GetFloatVal($val) * (1 - $this->GetFloatVal($v['TO'])/100)) : ''); elseif($v['THEN']=='NOT_LOAD') $val = false; elseif($v['THEN']=='EXPRESSION') $val = $this->ExecuteFilterExpression($val, $v['TO'], '', $arExpParams); elseif($v['THEN']=='STRIP_TAGS') $val = strip_tags($val); elseif($v['THEN']=='CLEAR_TAGS') $val = preg_replace('/<([a-z][a-z0-9:]*)[^>]*(\/?)>/i','<$1$2>', $val); elseif($v['THEN']=='TRANSLIT') { $arParams = array(); if($fieldName && !empty($iblockFields)) { $paramName = ''; if($fieldName=='IE_CODE') $paramName = 'CODE'; if(preg_match('/^ISECT\d*_CODE$/', $fieldName)) $paramName = 'SECTION_CODE'; if($paramName && $iblockFields[$paramName]['DEFAULT_VALUE']['TRANSLITERATION']=='Y') { $arParams = $iblockFields[$paramName]['DEFAULT_VALUE']; } } if(strlen($v['TO']) > 0) $val = $v['TO']; $val = $this->Str2Url($val, $arParams); } elseif($v['THEN']=='DOWNLOAD_BY_LINK') { $val = \Bitrix\KdaImportexcel\IUtils::DownloadTextTextByLink($val, $v['TO']); } elseif($v['THEN']=='DOWNLOAD_IMAGES') { $val = \Bitrix\KdaImportexcel\IUtils::DownloadImagesFromText($val, $v['TO']); } $execConv = true; } } } return $val; } public function CalcFloatValue($val) { $val = preg_replace_callback('/#CELL\d+#/', array($this, 'ConversionReplaceValuesFloat'), $val); if(preg_match('/[+\-\/*]/', $val)) { try{ $val = eval('return '.str_replace(',', '.', $val).';'); }catch(Exception $ex){} } return $val; } public function GetCurrentItemValues() { if(is_array($this->currentItemValues)) return $this->currentItemValues; else return array(); } public static function GetPreviewData($file, $showLines, $arParams=array(), $colsCount=false, $pid=false, $list=false) { if($pid!==false) \CKDAImportProfile::getInstance()->SetImportParams($pid, '', array(), $arParams); $selfobj = new CKDAImportExcelStatic($arParams, $file); $file = $_SERVER['DOCUMENT_ROOT'].$file; $objReader = KDAPHPExcel_IOFactory::createReaderForFile($file); if($arParams['ELEMENT_NOT_LOAD_STYLES']=='Y' && $arParams['ELEMENT_NOT_LOAD_FORMATTING']=='Y') { $objReader->setReadDataOnly(true); } if(isset($arParams['CSV_PARAMS'])) { $objReader->setCsvParams($arParams['CSV_PARAMS']); } $chunkFilter = new KDAChunkReadFilter(); $objReader->setReadFilter($chunkFilter); $maxLine = 1000; if(!$colsCount) $maxLine = max($showLines + 50, 50); $chunkFilter->setRows(1, $maxLine); $efile = $objReader->load($file); $arWorksheets = array(); foreach($efile->getWorksheetIterator() as $k=>$worksheet) { if($list!==false && $list!=$k) continue; $maxDrawCol = 0; $draws = array(); if($arParams['ELEMENT_LOAD_IMAGES']=='Y') { $drawCollection = $worksheet->getDrawingCollection(); if($drawCollection) { foreach($drawCollection as $drawItem) { $coord = $drawItem->getCoordinates(); $arCoords = KDAPHPExcel_Cell::coordinateFromString($coord); $maxDrawCol = max($maxDrawCol, KDAPHPExcel_Cell::columnIndexFromString($arCoords[0])); } } //$draws = self::GetWorksheetDraws($worksheet); //$worksheet->getMergeCells(); } $columns_count = max(KDAPHPExcel_Cell::columnIndexFromString($worksheet->getHighestDataColumn()), $maxDrawCol); $columns_count = min($columns_count, 5000); $rows_count = $worksheet->getHighestDataRow(); $arLines = array(); $cntLines = $emptyLines = 0; for ($row = 0; ($row < $rows_count && count($arLines) < min($showLines+$emptyLines, $maxLine)); $row++) { $arLine = array(); $bEmpty = true; for ($column = 0; $column < $columns_count; $column++) { $val = $worksheet->getCellByColumnAndRow($column, $row+1); $valText = $selfobj->GetCalculatedValue($val); if(strlen(trim($valText)) > 0) $bEmpty = false; $curLine = array('VALUE' => $valText); if($arParams['ELEMENT_NOT_LOAD_STYLES']!='Y') { $curLine['STYLE'] = $selfobj->GetCellStyle($val, true); } $arLine[] = $curLine; } $arLines[$row] = $arLine; if($bEmpty) { $emptyLines++; } $cntLines++; } if($colsCount) { $columns_count = $colsCount; $arLines = array(); $lastEmptyLines = 0; for ($row = $cntLines; $row < $rows_count; $row++) { $arLine = array(); $bEmpty = true; for ($column = 0; $column < $columns_count; $column++) { $val = $worksheet->getCellByColumnAndRow($column, $row+1); $valText = $selfobj->GetCalculatedValue($val); if(strlen(trim($valText)) > 0) $bEmpty = false; $curLine = array('VALUE' => $valText); if($arParams['ELEMENT_NOT_LOAD_STYLES']!='Y') { $curLine['STYLE'] = $selfobj->GetCellStyle($val, true); } $arLine[] = $curLine; } if($bEmpty) $lastEmptyLines++; else $lastEmptyLines = 0; $arLines[$row] = $arLine; } if($lastEmptyLines > 0) { $arLines = array_slice($arLines, 0, -$lastEmptyLines, true); } } $arCells = explode(':', $worksheet->getSelectedCells()); $heghestRow = intval(preg_replace('/\D+/', '', end($arCells))); if(is_callable(array($worksheet, 'getRealHighestRow'))) $heghestRow = intval($worksheet->getRealHighestRow()); elseif($worksheet->getHighestDataRow() > $heghestRow) $heghestRow = intval($worksheet->getHighestDataRow()); if(stripos($file, '.csv')) { $heghestRow = CKDAImportUtils::GetFileLinesCount($file); } $arWorksheets[$k] = array( 'title' => self::CorrectCalculatedValue($worksheet->GetTitle()), 'show_more' => ($row < $rows_count), 'lines_count' => $heghestRow, 'lines' => $arLines ); } return $arWorksheets; } public function GetOfferParentId() { return (isset($this->offerParentId) ? $this->offerParentId : false); } public function GetFieldSettings($key) { $fieldSettings = $this->fieldSettings[$key]; if(!is_array($fieldSettings)) $fieldSettings = array(); return $fieldSettings; } public function GetCurrentIblock() { return $this->iblockId; } public function GetCachedOfferIblock($IBLOCK_ID) { if(!$this->iblockoffers || !isset($this->iblockoffers[$IBLOCK_ID])) { $this->iblockoffers[$IBLOCK_ID] = CKDAImportUtils::GetOfferIblock($IBLOCK_ID, true); } return $this->iblockoffers[$IBLOCK_ID]; } public function SavePropertiesHints($arItem) { $filedList = $this->params['FIELDS_LIST'][$this->worksheetNumForSave]; $IBLOCK_ID = $this->params['IBLOCK_ID'][$this->worksheetNumForSave]; foreach($filedList as $key=>$field) { if(strpos($field, 'IP_PROP')!==0 && substr($field, -12)=='_DESCRIPTION') continue; $k = $key; if(strpos($k, '_')!==false) $k = substr($k, 0, strpos($k, '_')); $value = $arItem[$k]; $propId = substr($field, 7); $ibp = new CIBlockProperty; $ibp->Update($propId, array('HINT'=>$value)); $dbRes2 = \Bitrix\Iblock\SectionPropertyTable::getList(array("select" => array("SECTION_ID", "PROPERTY_ID"), "filter" => array("=IBLOCK_ID" => $IBLOCK_ID ,"=PROPERTY_ID" => $propId))); while($arr2 = $dbRes2->Fetch()) { CIBlockSectionPropertyLink::Set($arr2['SECTION_ID'], $arr2['PROPERTY_ID'], array('FILTER_HINT'=>$value)); } } return false; } public function ClearCompositeCache($link='') { if(!class_exists('\Bitrix\Main\Composite\Helper')) return; require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/classes/general/cache_files_cleaner.php"); if(!isset($this->compositDomains) || !is_array($this->compositDomains)) { $compositeOptions = \CHTMLPagesCache::getOptions(); $compositDomains = $compositeOptions['DOMAINS']; if(!is_array($compositDomains)) $compositDomains = array(); $this->compositDomains = $compositDomains; } if(strlen($link) > 0 && !empty($this->compositDomains)) { foreach($this->compositDomains as $host) { $page = new \Bitrix\Main\Composite\Page($link, $host); $page->delete(); } } } public function AddTagIblock($IBLOCK_ID) { $IBLOCK_ID = (int)$IBLOCK_ID; if($IBLOCK_ID <= 0) return; $this->tagIblocks[$IBLOCK_ID] = $IBLOCK_ID; } public function ClearIblocksTagCache($checkTime = false) { if($this->params['REMOVE_CACHE_AFTER_IMPORT']=='Y') return; if($checkTime && (time() - $this->timeBeginTagCache < 60)) return; if(is_callable(array('\CIBlock', 'clearIblockTagCache'))) { if(is_callable(array('\CIBlock', 'enableClearTagCache'))) \CIBlock::enableClearTagCache(); foreach($this->tagIblocks as $IBLOCK_ID) { \CIBlock::clearIblockTagCache($IBLOCK_ID); } if(is_callable(array('\CIBlock', 'disableClearTagCache'))) \CIBlock::disableClearTagCache(); } $this->tagIblocks = array(); $this->timeBeginTagCache = time(); } public function GetIblockPropEnum($arFilter) { if(class_exists('\Bitrix\Iblock\PropertyEnumerationTable')) $dbRes = \Bitrix\Iblock\PropertyEnumerationTable::getList(array('filter'=>$arFilter)); else { foreach(array('XML_ID', 'TMP_ID', 'VALUE') as $key) { if(isset($arFilter['='.$key]) && !isset($arFilter[$key])) { $arFilter[$key] = $arFilter['='.$key]; unset($arFilter['='.$key]); } } $dbRes = \CIBlockPropertyEnum::GetList(array(), $arFilter); } return $dbRes; } public function GetCellStyle($val, $modify = false) { $style = $val->getStyle(); if(!is_object($style)) return array(); $arStyle = array( 'COLOR' => $style->getFont()->getColor()->getRGB(), 'FONT-FAMILY' => $style->getFont()->getName(), 'FONT-SIZE' => $style->getFont()->getSize(), 'FONT-WEIGHT' => $style->getFont()->getBold(), 'FONT-STYLE' => $style->getFont()->getItalic(), 'TEXT-DECORATION' => $style->getFont()->getUnderline(), 'BACKGROUND' => ($style->getFill()->getFillType()=='solid' ? $style->getFill()->getStartColor()->getRGB() : ''), ); $outlineLevel = (int)$val->getWorksheet()->getRowDimension($val->getRow())->getOutlineLevel(); if($outlineLevel > 0) { $arStyle['TEXT-INDENT'] = $outlineLevel; } $pVersion = \CKDAImportProfile::getInstance()->GetImportParam('PROFILE_VERSION'); $indent = (int)$style->getAlignment()->getIndent(); if($indent==0 && $pVersion > 2) { $strVal = $val->getCalculatedValue(); if(preg_match("/^'(\s+)\S/", $strVal, $m)) $indent = strlen($m[1]); } if($indent > 0 && $pVersion > 1) $arStyle['PADDING-LEFT'] = $indent; if($modify) { $arStyle['EXT'] = array( 'COLOR' => $style->getFont()->getColor()->getRealRGB(), 'BACKGROUND' => ($style->getFill()->getFillType()=='solid' ? $style->getFill()->getStartColor()->getRealRGB() : ''), ); } $arExclude = (isset($this->params['ELEMENT_NOT_LOAD_STYLES_LIST']) && is_array($this->params['ELEMENT_NOT_LOAD_STYLES_LIST']) ? $this->params['ELEMENT_NOT_LOAD_STYLES_LIST'] : array()); foreach($arExclude as $ex) { if(array_key_exists($ex, $arStyle)) unset($arStyle[$ex]); if(array_key_exists('EXT', $arStyle) && array_key_exists($ex, $arStyle['EXT'])) unset($arStyle['EXT'][$ex]); } return $arStyle; } public function GetStyleByColumn($column, $param) { $val = $this->worksheet->getCellByColumnAndRow($column, $this->worksheetCurrentRow); $arStyle = $this->GetCellStyle($val); if(isset($arStyle[$param])) return $arStyle[$param]; else return ''; } public function GetOrigValueByColumn($column) { $val = $this->worksheet->getCellByColumnAndRow($column, $this->worksheetCurrentRow); return $val->getValue(); } public function GetValueByColumn($column) { $val = $this->worksheet->getCellByColumnAndRow($column, $this->worksheetCurrentRow); $valOrig = $this->GetCalculatedValue($val); return $valOrig; } public function GetCalculatedValue($val) { try{ if($this->params['ELEMENT_NOT_LOAD_FORMATTING']=='Y') $val = $val->getCalculatedValue(); else $val = $val->getFormattedValue(); }catch(Exception $ex){} /*$encoding = (isset($this->worksheet) && is_callable(array($this->worksheet, 'getDataEncoding')) ? $this->worksheet->getDataEncoding() : false);*/ return self::CorrectCalculatedValue($val); } public static function CorrectCalculatedValue($val, $encoding='UTF-8') { $val = str_ireplace('_x000D_', '', $val); if((!defined('BX_UTF') || !BX_UTF) && ($encoding=='UTF-8' || \CUtil::DetectUTF8($val))) { $val = self::ReplaceCpSpecChars($val); if(function_exists('iconv')) { $newVal = iconv("UTF-8", "CP1251//IGNORE", $val); if(strlen(trim($newVal))==0 && strlen(trim($val))>0) { $newVal2 = utf8win1251($val); if(strpos(trim($newVal2), '?')!==0) $newVal = $newVal2; } $val = $newVal; } else $val = utf8win1251($val); } return $val; } public static function ReplaceCpSpecChars($val) { return \Bitrix\KdaImportexcel\IUtils::ReplaceCpSpecChars($val); } public function GetFloatVal($val, $precision=0, $allowEmpty=false) { if(is_array($val)) $val = current($val); $val = preg_replace('/&#\d+;/', '', $val); if(preg_match('/^\s*\d+(,\s*\d{3})+\.\d{2}\s*$/', $val)) $val = str_replace(',', '', $val); $val = trim(preg_replace('/[^\d\.\-]+/', '', str_replace(',', '.', $val)), '.'); if($allowEmpty && strlen($val)==0) return $val; $val = floatval($val); if($precision > 0) $val = round($val, $precision); return $val; } public function GetDateVal($val, $format = 'FULL') { $time = strtotime($val); if($time!==false) { return ConvertTimeStamp($time, $format); } return false; } public function GetDateValToDB($val, $format = 'FULL') { if(is_array($val)) { foreach($val as $k=>$v) { $val[$k] = $this->GetDateValToDB($v, $format); } return $val; } $time = strtotime($val); if($time!==false) { return date('Y-m-d'.($format=='FULL' ? ' H:i:s' : ''), $time); } return false; } public function GetSeparator($sep) { return strtr((string)$sep, array('\r'=>"\r", '\n'=>"\n", '\t'=>"\t")); } public function Trim($str) { return \Bitrix\KdaImportexcel\IUtils::Trim($str); } public function Str2Url($string, $arParams=array(), $allowEmpty=true) { return \Bitrix\KdaImportexcel\IUtils::Str2Url($string, $arParams, $allowEmpty); } public function Translate($string, $langFrom, $langTo=false) { return \Bitrix\KdaImportexcel\IUtils::Translate($string, $langFrom, $langTo); } public function GetCurUserID() { return \Bitrix\KdaImportexcel\IUtils::GetCurUserID(); } public function Err($e) { if(++$this->stepparams['error_line'] <= 10000) $this->errors[] = $e; } public function SetLastError($error=false) { $this->lastError = $error; } public function GetLastError() { return $this->lastError; } public function OnShutdown() { $arError = error_get_last(); if(!is_array($arError) || !isset($arError['type']) || !in_array($arError['type'], array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR))) return; if($this->worksheetCurrentRow > 0) { $this->EndWithError(sprintf(Loc::getMessage("KDA_IE_FATAL_ERROR_IN_LINE"), $this->worksheetNumForSave+1, $this->worksheetCurrentRow, $arError['type'], $arError['message'], $arError['file'], $arError['line'])); } else { $this->EndWithError(sprintf(Loc::getMessage("KDA_IE_FATAL_ERROR"), $arError['type'], $arError['message'], $arError['file'], $arError['line'])); } } public function HandleError($code, $message, $file, $line) { return true; } public function HandleException($exception) { $error = ''; if($this->worksheetCurrentRow > 0) { $error .= sprintf(Loc::getMessage("KDA_IE_ERROR_LINE"), $this->worksheetNumForSave+1, $this->worksheetCurrentRow); } if(is_callable(array('\Bitrix\Main\Diag\ExceptionHandlerFormatter', 'format')) && mb_strpos($exception->getMessage(), $_SERVER['DOCUMENT_ROOT'])===false) { $error .= (isset($this->phpExpression) ? "<br>".htmlspecialcharsbx($this->phpExpression)."<br>" : "").\Bitrix\Main\Diag\ExceptionHandlerFormatter::format($exception); } else { $error .= sprintf(Loc::getMessage("KDA_IE_FATAL_ERROR"), '', $exception->getMessage(), $exception->getFile(), $exception->getLine()); } $this->EndWithError($error); } public function EndWithError($error) { global $APPLICATION; $APPLICATION->RestartBuffer(); ob_end_clean(); $this->errors[] = $error; $this->SaveStatusImport(); $oProfile = CKDAImportProfile::getInstance(); $oProfile->OnBreakImport($error); echo '<!--module_return_data-->'.CUtil::PhpToJSObject($this->GetBreakParams()); die(); } } class CKDAImportExcelStatic extends CKDAImportExcel { function __construct($params, $file='') { $this->params = $params; $this->filename = $_SERVER['DOCUMENT_ROOT'].$file; $this->SetZipClass(); } } class KDAChunkReadFilter implements KDAPHPExcel_Reader_IReadFilter { private $_startRow = 0; private $_endRow = 0; private $_arFilePos = array(); private $_arMerge = array(); private $_arLines = array(); private $_params = array(); /** Set the list of rows that we want to read */ public function setParams($arParams=array()) { $this->_params = $arParams; } public function getParam($paramName) { return (array_key_exists($paramName, $this->_params) ? $this->_params[$paramName] : false); } public function setLoadLines($arLines) { $this->_arLines = $arLines; } public function getLoadLines() { return $this->_arLines; } public function setMergeCells($mergeRef) { if(preg_match('/^([A-Z]+)(\d+):([A-Z]+)(\d+)$/', trim($mergeRef), $m) && $m[2]!=$m[4]) { /*$this->_arMerge[$m[1]][$m[2].':'.$m[4]] = array($m[2], $m[4]); $this->_arMerge[$m[3]][$m[2].':'.$m[4]] = array($m[2], $m[4]);*/ $this->_arMerge[$m[2].':'.$m[4]] = array($m[2], $m[4]); } } public function setRows($startRow, $chunkSize) { $this->_startRow = $startRow; $this->_endRow = $startRow + $chunkSize; $this->_arMerge = array(); } public function readCell($column, $row, $worksheetName = '') { // Only read the heading row, and the rows that are configured in $this->_startRow and $this->_endRow if (($row == 1) || ($row >= $this->_startRow && $row < $this->_endRow) || in_array($row, $this->_arLines)){ return true; } elseif(count($this->_arMerge) > 0){ foreach($this->_arMerge as $range){ if($row >= $range[0] && $row <= $range[1] && (($this->_startRow >= $range[0] && $this->_startRow <= $range[1]) || ($this->_endRow >= $range[0] && $this->_endRow <= $range[1]))){ return true; } } } return false; } public function getStartRow() { return $this->_startRow; } public function getEndRow() { return $this->_endRow; } public function setFilePosRow($row, $pos) { $this->_arFilePos[$row] = $pos; } public function getFilePosRow($row) { $nextRow = $row + 1; $pos = 0; if(!empty($this->_arFilePos)) { if(isset($this->_arFilePos[$nextRow])) $pos = (int)$this->_arFilePos[$nextRow]; else { $arKeys = array_keys($this->_arFilePos); if(!empty($arKeys)) { $maxKey = max($arKeys); if($nextRow > $maxKey); { $nextRow = $maxKey; $pos = (int)$this->_arFilePos[$maxKey]; } } } } return array( 'row' => $nextRow, 'pos' => $pos ); } } ?>