81 'CODE' =>
'DELETE_ALL',
82 'CALLBACK' =>
'stageDeleteAll',
83 'SUBPERCENT_CALLBACK' =>
'getSubpercentForstageDeleteAll'
90 'CODE' =>
'DOWNLOAD_FILES',
91 'CALLBACK' =>
'stageDownloadFiles',
92 'SUBPERCENT_CALLBACK' =>
'getSubpercentForStageDownloadFiles'
95 if(
$options[
'REQUEST'][
'OPTIONS'][
'DROP_ALL'])
99 'CODE' =>
'DELETE_ALL',
100 'CALLBACK' =>
'stageDeleteAll',
101 'SUBPERCENT_CALLBACK' =>
'getSubpercentForstageDeleteAll'
107 'CODE' =>
'DROP_INDEXES',
108 'CALLBACK' =>
'stageDropIndexes',
109 'SUBPERCENT_CALLBACK' =>
'getSubpercentForStageDropIndexes'
115 'CODE' =>
'PROCESS_FILES',
116 'CALLBACK' =>
'stageProcessFiles',
117 'SUBPERCENT_CALLBACK' =>
'getSubpercentForStageProcessFiles'
120 if(
$options[
'REQUEST'][
'OPTIONS'][
'INTEGRITY_PRESERVE'])
125 'CODE' =>
'INTEGRITY_PRESERVE',
126 'CALLBACK' =>
'stageIntegrityPreserve'
133 'CODE' =>
'REBALANCE_WALK_TREE',
134 'CALLBACK' =>
'stageRebalanceWalkTree',
135 'SUBPERCENT_CALLBACK' =>
'getSubpercentForStageRebalanceWalkTree'
141 'CODE' =>
'REBALANCE_CLEANUP_TEMP_TABLE',
142 'CALLBACK' =>
'stageRebalanceCleanupTempTable'
148 'CODE' =>
'RESTORE_INDEXES',
149 'CALLBACK' =>
'stageRestoreIndexes',
150 'SUBPERCENT_CALLBACK' =>
'getSubpercentForStageRestoreIndexes'
155 $this->dbConnType = $this->dbConnection->getType();
156 $this->dbHelper = $this->dbConnection->getSqlHelper();
168 $options[
'LANGUAGE_ID'] = trim((
string)(
$options[
'LANGUAGE_ID'] ?? LANGUAGE_ID));
171 $options[
'LANGUAGE_ID'] = LANGUAGE_ID;
175 if (is_object(
$options[
'REQUEST']) && method_exists(
$options[
'REQUEST'],
'toArray'))
183 $options[
'REQUEST'][
'OPTIONS'] ??= [];
184 if (!is_array(
$options[
'REQUEST'][
'OPTIONS']))
186 $options[
'REQUEST'][
'OPTIONS'] = [];
189 $requestOptions = &
$options[
'REQUEST'][
'OPTIONS'];
190 $requestOptions[
'DROP_ALL'] ??=
null;
191 $requestOptions[
'INTEGRITY_PRESERVE'] ??=
null;
192 $requestOptions[
'EXCLUDE_COUNTRY_DISTRICT'] ??=
null;
193 $requestOptions[
'SOURCE'] ??=
null;
194 $requestOptions[
'TIME_LIMIT'] = (int)($requestOptions[
'TIME_LIMIT'] ?? 0);
195 unset($requestOptions);
197 $options[
'REQUEST'][
'ADDITIONAL'] ??= [];
198 if (!is_array(
$options[
'REQUEST'][
'ADDITIONAL']))
200 $options[
'REQUEST'][
'ADDITIONAL'] = [];
204 if (!is_array(
$options[
'LOCATION_SETS']))
214 if ($this->options[
'ONLY_DELETE_ALL'])
219 $this->data[
'inited'] ??=
false;
220 if (!$this->data[
'inited'])
222 if((
string)($this->data[
'LOCAL_PATH'] ??
'') ===
'')
227 $opts = $this->options[
'REQUEST'][
'OPTIONS'];
229 if(!in_array($opts[
'SOURCE'],
array(self::SOURCE_REMOTE, self::SOURCE_FILE)))
233 if($opts[
'SOURCE'] == self::SOURCE_REMOTE)
240 $this->data[
'settings'] =
array(
245 if($opts[
'SOURCE'] == self::SOURCE_REMOTE)
247 $this->data[
'settings'][
'additional'] = is_array($this->options[
'REQUEST'][
'ADDITIONAL']) ? array_flip(array_values($this->options[
'REQUEST'][
'ADDITIONAL'])) :
array();
249 if(isset($this->data[
'settings'][
'additional'][
'ZIP']))
250 $this->data[
'settings'][
'additional'][
'ZIP_LOWER'] = $this->data[
'settings'][
'additional'][
'ZIP'];
254 $this->data[
'settings'][
'additional'] =
false;
260 $this->data[
'inited'] =
true;
263 if ($this->data[
'inited'] && $this->data[
'LOCAL_PATH_CREATED'])
265 $this->touchImportTmpFiles((
string)$this->data[
'LOCAL_PATH']);
268 $timeLimit = $this->data[
'settings'][
'options'][
'TIME_LIMIT'];
278 private function touchImportTmpFiles(
string $localPath): void
280 $iterator = new \RecursiveIteratorIterator(
290 touch($file->getPathname());
301 if((
string) $_SESSION[self::USER_FILE_DIRECTORY_SESSION_KEY] ==
'')
304 $srcFilePath = $_SESSION[self::USER_FILE_DIRECTORY_SESSION_KEY].
'/'.static::USER_FILE_TEMP_NAME;
305 $dstFilePath = $this->data[
'LOCAL_PATH'].self::getFileNameByIndex(0);
308 $this->
createDirectory($this->data[
'LOCAL_PATH'].
'/'.self::LOCAL_SETS_PATH);
310 if(!@copy($srcFilePath, $dstFilePath))
312 $lastError = error_get_last();
316 $this->data[
'files'] =
array(
318 'size' => filesize($dstFilePath),
319 'memgroup' =>
'static'
329 $this->data[
'files'] =
array();
340 $this->data[
'requiredGroups'] =
array();
341 foreach($typeGroups as
$code => $types)
343 if(
$code ==
'LAYOUT')
346 foreach($types as
$type)
348 if(isset($this->data[
'types'][
'allowed'][
$type]))
350 $this->data[
'requiredGroups'][] = mb_strtolower(
$code);
358 $packPath = self::REMOTE_SETS_PATH.($this->data[
'settings'][
'options'][
'PACK'] == self::PACK_EXTENDED ? self::PACK_EXTENDED : self::PACK_STANDARD).
'/';
363 $this->data[
'files'][0] =
array(
364 'size' => static::downloadFile(self::REMOTE_LAYOUT_FILE, self::getFileNameByIndex(0),
false, $this->data[
'LOCAL_PATH']),
365 'onlyThese' => array_flip($this->data[
'settings'][
'bundles'][
'allpoints']),
366 'memgroup' =>
'static'
369 $this->data[
'fileDownload'][
'currentEndPoint'] = 0;
370 $this->data[
'fileDownload'][
'currentFileOffset'] = 1;
373 $i =& $this->data[
'fileDownload'][
'currentEndPoint'];
374 $j =& $this->data[
'fileDownload'][
'currentFileOffset'];
376 while($this->
checkQuota() && isset($this->data[
'settings'][
'bundles'][
'endpoints'][
$i]))
378 $ep = $this->data[
'settings'][
'bundles'][
'endpoints'][
$i];
380 foreach($this->data[
'requiredGroups'] as
$code)
383 $file = $packPath.$ep.
'_'.
$code.
'.csv';
386 $this->data[
'files'][$j] =
array(
387 'size' => static::downloadFile($file,
$name,
false, $this->data[
'LOCAL_PATH']),
399 if(!isset($this->data[
'settings'][
'bundles'][
'endpoints'][
$i]))
401 unset($this->data[
'requiredGroups']);
402 unset($this->data[
'settings'][
'bundles'][
'endpoints']);
417 $currEp = (int)($this->data[
'fileDownload'][
'currentEndPoint'] ?? 0);
424 return round($pRange * ($currEp /
count($this->data[
'settings'][
'bundles'][
'endpoints'])));
464 if(
$step >= $stepsCount)
468 return round($pRange * (
$step / $stepsCount));
478 'IX_B_SALE_LOC_MARGINS',
479 'IX_B_SALE_LOC_MARGINS_REV',
480 'IX_B_SALE_LOC_PARENT',
482 'IX_B_SALE_LOC_TYPE',
483 'IX_B_SALE_LOC_NAME_NAME_U',
484 'IX_B_SALE_LOC_NAME_LI_LI',
485 'IX_B_SALE_LOC_EXT_LID_SID',
488 'IXS_LOCATION_COUNTRY_ID',
489 'IXS_LOCATION_REGION_ID',
490 'IXS_LOCATION_CITY_ID',
491 'IX_B_SALE_LOCATION_1',
492 'IX_B_SALE_LOCATION_2',
493 'IX_B_SALE_LOCATION_3'
496 if(!isset($indexes[$this->
getStep()]))
513 if(
$step >= $indexCount)
517 return round($pRange * (
$step / $indexCount));
526 $fIndex = $this->data[
'current'][
'fIndex'];
528 $onlyThese =& $this->data[
'files'][$fIndex][
'onlyThese'];
532 if(!isset($this->hitData[
'csv']))
534 $file = $this->data[
'LOCAL_PATH'].$fName;
536 if(!file_exists($file) || !is_readable($file))
542 $this->hitData[
'csv']->LoadFile($file);
543 $this->hitData[
'csv']->AddEventCallback(
'AFTER_ASSOC_LINE_READ',
array($this,
'provideEnFromRu'));
546 $block = $this->hitData[
'csv']->ReadBlockLowLevel($this->data[
'current'][
'bytesRead'], 100);
548 $this->data[
'current'][
'linesRead'] +=
count($block);
555 if($this->hitData[
'csv']->CheckFileIsLegacy())
560 if(is_array($onlyThese))
562 foreach($block as
$i => $line)
564 if(is_array($onlyThese) && !isset($onlyThese[$line[
'CODE']]))
584 return $res[
'ID'] ??
false;
599 return mb_strtoupper($value);
601 array_keys(
Location\Admin\NameHelper::getLanguageList()))
610 if (!!($this->options[
'REQUEST'][
'OPTIONS'][
'EXCLUDE_COUNTRY_DISTRICT']))
612 if (!isset($this->data[
'COUNTRY_2_DISTRICT']))
614 $this->data[
'COUNTRY_2_DISTRICT'] = [];
617 if (
$data[
'TYPE_CODE'] ==
'COUNTRY')
619 $this->data[
'LAST_COUNTRY'] =
$data[
'CODE'];
623 $this->data[
'COUNTRY_2_DISTRICT'][
$code] = $this->data[
'LAST_COUNTRY'];
628 if (isset($this->data[
'COUNTRY_2_DISTRICT'][
$data[
'PARENT_CODE']]))
630 $data[
'PARENT_CODE'] = $this->data[
'COUNTRY_2_DISTRICT'][
$data[
'PARENT_CODE']];
637 if (!!($this->options[
'REQUEST'][
'OPTIONS'][
'EXCLUDE_COUNTRY_DISTRICT']))
639 if (!isset($this->data[
'COUNTRY_2_DISTRICT']))
641 $this->data[
'COUNTRY_2_DISTRICT'] = [];
644 if (
$data[
'TYPE_CODE'] ==
'COUNTRY')
646 $this->data[
'LAST_COUNTRY'] =
$data[
'CODE'];
650 $this->data[
'COUNTRY_2_DISTRICT'][
$code] = $this->data[
'LAST_COUNTRY'];
655 if (isset($this->data[
'COUNTRY_2_DISTRICT'][
$data[
'PARENT_CODE']]))
657 $data[
'PARENT_CODE'] = $this->data[
'COUNTRY_2_DISTRICT'][
$data[
'PARENT_CODE']];
662 if(isset($this->data[
'existedlocs'][
'static'][
$code]) || isset($this->data[
'existedlocs'][$gid][
$code]))
665 if(!isset($this->data[
'types'][
'allowed'][
$data[
'TYPE_CODE']]))
669 if(!$this->data[
'TABLE_WERE_EMPTY'])
673 if(intval($existedId))
675 $this->data[
'existedlocs'][$gid][
$code] = $existedId;
682 if(
$data[
'PARENT_CODE'] <>
'')
684 if(isset($this->data[
'existedlocs'][
'static'][
$data[
'PARENT_CODE']]))
686 $data[
'PARENT_ID'] = $this->data[
'existedlocs'][
'static'][
$data[
'PARENT_CODE']];
688 elseif(isset($this->data[
'existedlocs'][$gid][
$data[
'PARENT_CODE']]))
690 $data[
'PARENT_ID'] = $this->data[
'existedlocs'][$gid][
$data[
'PARENT_CODE']];
694 $data[
'PARENT_ID'] = 0;
699 $data[
'PARENT_ID'] = 0;
702 unset(
$data[
'PARENT_CODE']);
706 $data[
'TYPE_ID'] = $this->data[
'types'][
'code2id'][
$data[
'TYPE_CODE']];
707 unset(
$data[
'TYPE_CODE']);
711 $names =
$data[
'NAME'];
712 unset(
$data[
'NAME']);
714 $external =
$data[
'EXT'];
717 $data[
'LONGITUDE'] = (float)(
$data[
'LONGITUDE'] ?? 0);
718 $data[
'LATITUDE'] = (float)(
$data[
'LATITUDE'] ?? 0);
721 $data[
'LONGITUDE'] = 0;
722 $data[
'LATITUDE'] = 0;
725 $locationId = $this->hitData[
'HANDLES'][
'LOCATION']->insert(
$data);
729 $this->data[
'existedlocs'][$gid][
$data[
'CODE']] = $locationId;
733 if(is_array($names) && !empty($names))
739 $lid = mb_strtolower($lid);
740 $toAdd = static::getTranslatedName($names, $lid);
742 $this->hitData[
'HANDLES'][
'NAME']->insert(
array(
743 'NAME' => $toAdd[
'NAME'],
744 'NAME_UPPER' => mb_strtoupper($toAdd[
'NAME']),
745 'LANGUAGE_ID' => $lid,
746 'LOCATION_ID' => $locationId
754 if(is_array($external) && !empty($external))
756 foreach($external as $sCode => $values)
760 $serviceId = $this->data[
'externalService'][
'code2id'][$sCode];
765 if($sCode ==
'ZIP_LOWER')
770 $values = explode(
',', $values);
772 if(!is_array($values))
775 $values = array_unique($values);
778 if(is_array($values))
780 foreach($values as
$val)
785 $this->hitData[
'HANDLES'][
'EXTERNAL']->insert(
array(
786 'SERVICE_ID' => $serviceId,
788 'LOCATION_ID' => $locationId
800 return $this->data[
'files'][$this->data[
'current'][
'fIndex']][
'memgroup'];
805 if($this->dbConnType == self::DB_TYPE_ORACLE)
806 $mtu = self::INSERTER_MTU_ORACLE;
808 $mtu = self::INSERTER_MTU;
811 'entityName' =>
'\Bitrix\Sale\Location\LocationTable',
812 'exactFields' =>
array(
'CODE',
'TYPE_ID',
'PARENT_ID',
'LATITUDE',
'LONGITUDE'),
813 'parameters' =>
array(
814 'autoIncrementFld' =>
'ID',
820 'entityName' =>
'\Bitrix\Sale\Location\Name\LocationTable',
821 'exactFields' =>
array(
'NAME',
'NAME_UPPER',
'LANGUAGE_ID',
'LOCATION_ID'),
822 'parameters' =>
array(
823 'autoIncrementFld' =>
'ID',
829 'entityName' =>
'\Bitrix\Sale\Location\ExternalTable',
830 'exactFields' =>
array(
'SERVICE_ID',
'XML_ID',
'LOCATION_ID'),
831 'parameters' =>
array(
832 'autoIncrementFld' =>
'ID',
840 $this->data[
'current'] =
array(
846 $this->hitData[
'HANDLES'][
'LOCATION']->resetAutoIncrementFromIndex();
868 unset($this->hitData[
'csv']);
869 $this->data[
'current'][
'fIndex']++;
870 $this->data[
'current'][
'bytesRead'] = 0;
871 $this->data[
'current'][
'linesRead'] = 0;
872 $this->data[
'current'][
'legacy'] =
array();
877 unset($this->data[
'existedlocs']);
887 $this->hitData[
'HANDLES'][
'LOCATION']->flush();
888 $this->hitData[
'HANDLES'][
'NAME']->flush();
889 $this->hitData[
'HANDLES'][
'EXTERNAL']->flush();
903 if(!isset($this->data[
'current'][
'fIndex']))
906 $fIndex = $this->data[
'current'][
'fIndex'];
909 foreach($this->data[
'files'] as $file)
914 $fileBytesRead += $file[
'size'];
916 $totalSize += $file[
'size'];
922 return round($pRange * (intval($fileBytesRead + $this->data[
'current'][
'bytesRead']) / $totalSize));
934 $res = Location\LocationTable::getList(
array(
942 $relations =
array();
944 while($item =
$res->fetch())
946 if(isset($lay[$item[
'CODE']]) && ((
string) $lay[$item[
'CODE']][
'PARENT_CODE'] !=
''))
947 $relations[$item[
'CODE']] = $lay[$item[
'CODE']][
'PARENT_CODE'];
950 $code2id[$item[
'CODE']] = $item[
'ID'];
955 foreach($code2id as
$code => $id)
957 if (!isset($relations[
$code]))
961 if ((
string)($parentCode2id[$relations[
$code]] ??
'') !==
'')
965 [
'PARENT_ID' => $parentCode2id[$relations[
$code]]]
967 if (!
$res->isSuccess())
982 if(!isset($this->data[
'rebalance'][
'queue']))
988 $this->data[
'rebalance'][
'margin'] = -1;
989 $this->data[
'processed'] = 0;
990 $this->data[
'rebalance'][
'queue'] =
array(
array(
'I' =>
'root',
'D' => 0));
995 $this->data[
'rebalance'][
'cnt'] = intval(
$res[
'CNT']);
999 while(!empty($this->data[
'rebalance'][
'queue']) && $this->
checkQuota())
1003 $node =& $this->data[
'rebalance'][
'queue'][0];
1005 if(isset($node[
'L']))
1008 array_shift($this->data[
'rebalance'][
'queue']);
1009 if($node[
'I'] !=
'root')
1011 $this->acceptRebalancedNode(
array(
1015 'R' => ++$this->data[
'rebalance'][
'margin']
1019 $this->data[
'rebalance'][
'margin']++;
1023 $a = $this->getCachedBundle($node[
'I']);
1028 $node[
'L'] = ++$this->data[
'rebalance'][
'margin'];
1032 if($this->checkNodeIsParent($id))
1034 array_unshift($this->data[
'rebalance'][
'queue'],
array(
'I' => $id,
'D' => $node[
'D'] + 1));
1038 $this->acceptRebalancedNode(
array(
1040 'D' => $node[
'D'] + 1,
1041 'L' => ++$this->data[
'rebalance'][
'margin'],
1042 'R' => ++$this->data[
'rebalance'][
'margin']
1049 array_shift($this->data[
'rebalance'][
'queue']);
1050 $this->acceptRebalancedNode(
array(
1053 'L' => ++$this->data[
'rebalance'][
'margin'],
1054 'R' => ++$this->data[
'rebalance'][
'margin']
1060 $this->
logMessage(
'Q size is '.
count($this->data[
'rebalance'][
'queue']).
' already processed: '.$this->data[
'processed'].
'/'.$this->data[
'rebalance'][
'cnt']);
1063 if(empty($this->data[
'rebalance'][
'queue']))
1066 $this->mergeRebalancedNodes();
1072 if($this->rebalanceInserter)
1073 $this->rebalanceInserter->flush();
1080 $processed = $this->data[
'processed'] ?? 0;
1081 $cnt = $this->data[
'rebalance'][
'cnt'] ?? 0;
1082 if (!$processed || !$cnt)
1086 $part = round($pRange * ($processed / $cnt));
1088 return min($part, $pRange);
1096 $this->dropTempTable();
1106 'IX_B_SALE_LOC_MARGINS',
1107 'IX_B_SALE_LOC_MARGINS_REV',
1110 'IX_B_SALE_LOC_TYPE',
1111 'IX_B_SALE_LOC_NAME_NAME_U',
1112 'IX_B_SALE_LOC_NAME_LI_LI',
1113 'IX_B_SALE_LOC_EXT_LID_SID',
1116 'IXS_LOCATION_COUNTRY_ID',
1117 'IXS_LOCATION_REGION_ID',
1118 'IXS_LOCATION_CITY_ID',
1121 if(isset($indexes[$this->
getStep()]))
1141 if(
$step >= $stepCount)
1147 return round($pRange * (
$step / $stepCount));
1156 return $this->options[
'LANGUAGE_ID'];
1165 $res = Location\TypeTable::getList(
array(
1167 'CODE',
'TNAME' =>
'NAME.NAME'
1174 'NAME.NAME' =>
'asc'
1177 while($item =
$res->fetch())
1178 $result[$item[
'CODE']] = $item[
'TNAME'];
1192 if(empty($this->stat))
1194 $types = \Bitrix\Sale\Location\Admin\TypeHelper::getTypes(
array(
'LANGUAGE_ID' => $this->
getLanguageId()));
1196 $res = Location\LocationTable::getList(
array(
1199 'TCODE' =>
'TYPE.CODE'
1207 while($item =
$res->fetch())
1209 $total += intval($item[
'CNT']);
1210 $stat[$item[
'TCODE']] = $item[
'CNT'];
1216 'NAME' =>
$data[
'NAME_CURRENT'],
1222 $this->stat[
'TOTAL'] =
array(
'CNT' => $total,
'CODE' =>
'TOTAL');
1224 $res = Location\GroupTable::getList(
array(
1227 'data_type' =>
'integer',
1228 'expression' =>
array(
1238 $this->stat[
'GROUPS'] =
array(
'CNT' => intval(
$res[
'CNT']),
'CODE' =>
'GROUPS');
1241 return intval($this->stat[
$type][
'CNT']);
1248 $parentness =
array();
1249 foreach($lay as
$data)
1251 $parentCode = (string)(
$data[
'PARENT_CODE'] ??
'');
1252 if ($parentCode ===
'')
1256 $parentness[$parentCode] ??= 0;
1257 $parentness[$parentCode]++;
1260 $bundles = array_flip($this->data[
'settings'][
'sets']);
1262 $selectedLayoutParts =
array();
1263 foreach($bundles as $bundle => $void)
1265 if(!isset($lay[$bundle]))
1271 $currentBundle = $bundle;
1273 while($currentBundle)
1278 throw new Main\SystemException(
'Too deep recursion got when building chains. Layout file is broken');
1280 if(isset($lay[$currentBundle]))
1282 $chain[] = $currentBundle;
1283 if($lay[$currentBundle][
'PARENT_CODE'] <>
'')
1285 $currentBundle = $lay[$currentBundle][
'PARENT_CODE'];
1287 if(!isset($lay[$currentBundle]))
1289 throw new Main\SystemException(
'Unknown parent bundle found ('.$currentBundle.
'). Layout file is broken');
1294 $currentBundle =
false;
1299 if(is_array($chain) && !empty($chain))
1301 $chain = array_reverse($chain);
1304 $subChain =
array();
1305 foreach($chain as
$i => $node)
1307 if(isset($bundles[$node]))
1309 $subChain = array_slice($chain,
$i);
1314 if(!empty($subChain))
1315 $selectedLayoutParts = array_merge($selectedLayoutParts, $subChain);
1320 $selectedLayoutParts = array_unique($selectedLayoutParts);
1322 $this->data[
'settings'][
'bundles'] =
array(
'endpoints' =>
array(),
'allpoints' => $selectedLayoutParts);
1324 foreach($selectedLayoutParts as $bCode)
1326 if(!isset($parentness[$bCode]))
1327 $this->data[
'settings'][
'bundles'][
'endpoints'][] = $bCode;
1331 unset($this->data[
'settings'][
'sets']);
1336 $converted =
array();
1338 foreach($block as $line)
1341 $typeCode =
'COUNTRY';
1343 $typeCode =
'REGION';
1349 $code = md5(implode(
':', $line));
1351 if($typeCode ==
'REGION')
1352 $parentCode = $this->data[
'current'][
'legacy'][
'lastCOUNTRY'];
1353 elseif($typeCode ==
'CITY')
1354 $parentCode = $this->data[
'current'][
'legacy'][
'lastParent'];
1358 if($typeCode !=
'CITY')
1360 $this->data[
'current'][
'legacy'][
'last'.$typeCode] =
$code;
1361 $this->data[
'current'][
'legacy'][
'lastParent'] =
$code;
1366 'TYPE_CODE' => $typeCode,
1367 'PARENT_CODE' => $parentCode
1372 $lineLen =
count($line);
1373 for(
$k = 1;
$k < $lineLen;
$k++)
1381 $cLine[
'NAME'][mb_strtoupper(
$lang)][
'NAME'] = $line[
$k];
1384 $expectLang = !$expectLang;
1387 $converted[] = $cLine;
1395 return $this->data[
'settings'][
'options'][
'SOURCE'] == $sType;
1403 static::downloadFile(self::REMOTE_LAYOUT_FILE, self::LOCAL_LAYOUT_FILE,
false,
$localPath);
1406 $csv->AddEventCallback(
'AFTER_ASSOC_LINE_READ',
array($this,
'provideEnFromRu'));
1412 foreach(
$res as $line)
1413 $result[$line[
'CODE']] = $line;
1420 foreach(
$res as $line)
1422 $line[
'NAME'][mb_strtoupper(
$lang)] = static::getTranslatedName($line[
'NAME'],
$lang);
1423 $result[$line[
'PARENT_CODE']][$line[
'CODE']] = $line;
1438 if(!$this->useCache || !isset($this->data[
'settings'][
'remote'][
'types']))
1442 static::downloadFile(self::REMOTE_TYPE_FILE, self::LOCAL_TYPE_FILE,
false,
$localPath);
1445 $csv->AddEventCallback(
'AFTER_ASSOC_LINE_READ',
array($this,
'provideEnFromRu'));
1449 foreach(
$res as $line)
1450 $result[$line[
'CODE']] = $line;
1452 $this->data[
'settings'][
'remote'][
'types'] =
$result;
1460 return $this->data[
'settings'][
'remote'][
'types'];
1466 if(!$this->useCache || !isset($this->data[
'settings'][
'remote'][
'external_services']))
1470 static::downloadFile(self::REMOTE_EXTERNAL_SERVICE_FILE, self::LOCAL_EXTERNAL_SERVICE_FILE,
false,
$localPath);
1473 $res = $csv->ReadBlock(
$localPath.self::LOCAL_EXTERNAL_SERVICE_FILE);
1476 foreach(
$res as $line)
1477 $result[$line[
'CODE']] = $line;
1479 $this->data[
'settings'][
'remote'][
'external_services'] =
$result;
1487 return $this->data[
'settings'][
'remote'][
'external_services'];
1493 if(!$this->useCache || !isset($this->data[
'settings'][
'remote'][
'typeGroups']))
1497 static::downloadFile(self::REMOTE_TYPE_GROUP_FILE, self::LOCAL_TYPE_GROUP_FILE,
false,
$localPath);
1503 foreach(
$res as $line)
1505 $result[$line[
'CODE']] = explode(
':', $line[
'TYPES']);
1508 $this->data[
'settings'][
'remote'][
'typeGroups'] =
$result;
1516 return $this->data[
'settings'][
'remote'][
'typeGroups'];
1529 foreach($types as
$type)
1531 if(
$type[
'SELECTORLEVEL'] = intval(
$type[
'SELECTORLEVEL']))
1533 $name = static::getTranslatedName(
$type[
'NAME'], $langId);
1534 $levels[
$type[
'SELECTORLEVEL']][
'NAMES'][] =
$name[
'NAME'];
1535 $levels[
$type[
'SELECTORLEVEL']][
'TYPES'][] =
$type[
'CODE'];
1537 $levels[
$type[
'SELECTORLEVEL']][
'DEFAULT'] = (
$type[
'DEFAULTSELECT'] ==
'1');
1541 foreach($levels as &$group)
1542 $group[
'NAMES'] = implode(
', ', $group[
'NAMES']);
1544 ksort($levels, SORT_NUMERIC);
1558 while($item =
$res->fetch())
1560 $langs[mb_strtoupper($item[
'LANGUAGE_ID'])] =
true;
1573 $langs = Location\Admin\NameHelper::getLanguageList();
1577 return array_unique(array_merge($required, static::getSiteLanguages()));
1583 $this->data[
'types_processed'] ??=
false;
1584 if ($this->data[
'types_processed'])
1590 $existed = static::getExistedTypes();
1597 $existed = static::createTypes($rTypes, $existed);
1599 if(intval($dl = $this->data[
'settings'][
'options'][
'DEPTH_LIMIT']))
1605 if(!isset($typesGroupped[$dl]))
1609 foreach($typesGroupped as $gId => $group)
1614 foreach($group[
'TYPES'] as
$type)
1618 $this->data[
'types'][
'allowed'] = $allowed;
1623 foreach($rTypes as
$type)
1625 $allowed[] =
$type[
'CODE'];
1627 $this->data[
'types'][
'allowed'] = $allowed;
1633 if(!empty($existed) && is_array($existed))
1635 $codes = array_keys($existed);
1638 $this->data[
'types'][
'allowed'] = $codes;
1641 if (empty($this->data[
'types'][
'allowed']))
1643 $this->data[
'types'][
'last'] =
null;
1647 $this->data[
'types'][
'last'] = $this->data[
'types'][
'allowed'][
count($this->data[
'types'][
'allowed']) - 1];
1649 $this->data[
'types'][
'allowed'] = array_flip($this->data[
'types'][
'allowed']);
1651 $this->data[
'types'][
'code2id'] = $existed;
1652 $this->data[
'types_processed'] =
true;
1657 if($this->data[
'settings'][
'additional'] ===
false)
1660 if(
$code ==
'ZIP_LOWER')
1663 return isset($this->data[
'settings'][
'additional'][
$code]);
1668 $this->data[
'external_processed'] ??=
false;
1669 if ($this->data[
'external_processed'])
1675 $existed = static::getExistedServices();
1680 foreach($external as $line)
1684 $existed[$line[
'CODE']] = static::createService($line);
1687 unset($this->data[
'settings'][
'remote'][
'external_services']);
1690 $this->data[
'externalService'][
'code2id'] = $existed;
1691 $this->data[
'external_processed'] =
true;
1696 $parameters =
array(
1697 'select' =>
array(
'ID',
'CODE')
1701 $parameters[
'filter'] =
array(
'TYPE.CODE' =>
array(
'COUNTRY',
'COUNTRY_DISTRICT',
'REGION'));
1703 $this->data[
'existedlocs'] =
array(
'static' =>
array());
1704 $res = Location\LocationTable::getList($parameters);
1705 while($item =
$res->fetch())
1706 $this->data[
'existedlocs'][
'static'][$item[
'CODE']] = $item[
'ID'];
1712 while($item =
$res->fetch())
1713 $result[$item[
'CODE']] = $item[
'ID'];
1724 foreach($codes as
$code)
1728 if(
$i == self::MAX_CODE_FETCH_BLOCK_LEN)
1750 $before = implode(
', ', array_keys($this->data[
'existedlocs']));
1753 foreach($this->data[
'existedlocs'] as $gid => $bundles)
1755 if($gid ==
'static' || in_array($gid, $memGroups))
1760 $this->
logMessage(
'Memory clean: REMOVING Group '.$gid);
1761 unset($this->data[
'existedlocs'][$gid]);
1766 $this->
logMessage(
'BEFORE memgroups: '.$before);
1767 $this->
logMessage(
'Clear all but '.$memGroups[0]);
1769 $this->
logMessage(
'AFTER memgroups: '.implode(
', ', array_keys($this->data[
'existedlocs'])));
1778 $indexName = $this->dbHelper->forSql(trim($indexName));
1779 $tableName = $this->dbHelper->forSql(trim($tableName));
1781 if(!mb_strlen($indexName) || !mb_strlen($tableName))
1784 if($this->dbConnType == self::DB_TYPE_MYSQL)
1785 $res = $this->dbConnection->query(
"show index from ".$tableName);
1786 elseif($this->dbConnType == self::DB_TYPE_ORACLE)
1787 $res = $this->dbConnection->query(
"SELECT INDEX_NAME as Key_name FROM USER_IND_COLUMNS WHERE TABLE_NAME = '".mb_strtoupper($tableName).
"'");
1788 elseif($this->dbConnType == self::DB_TYPE_MSSQL)
1790 $res = $this->dbConnection->query(
"SELECT si.name Key_name
1792 INNER JOIN syscolumns c ON s.id = c.id AND s.colid = c.colid
1793 INNER JOIN sysobjects o ON s.id = o.Id AND o.xtype = 'U'
1794 LEFT JOIN sysindexes si ON si.indid = s.indid AND si.id = s.id
1795 WHERE o.name = '".mb_strtoupper($tableName).
"'");
1798 while($item =
$res->fetch())
1800 if (isset($item[
'Key_name']) && $item[
'Key_name'] === $indexName)
1804 if (isset($item[
'KEY_NAME']) && $item[
'KEY_NAME'] === $indexName)
1815 $indexName = $this->dbHelper->forSql(trim($indexName));
1816 $tableName = $this->dbHelper->forSql(trim($tableName));
1818 if(!mb_strlen($indexName) || !mb_strlen($tableName))
1824 if($this->dbConnType == self::DB_TYPE_MYSQL)
1825 $this->dbConnection->query(
"alter table {$tableName} drop index {$indexName}");
1826 elseif($this->dbConnType == self::DB_TYPE_ORACLE)
1827 $this->dbConnection->query(
"drop index {$indexName}");
1828 elseif($this->dbConnType == self::DB_TYPE_MSSQL)
1829 $this->dbConnection->query(
"drop index {$indexName} on {$tableName}");
1840 if (
Main\HttpApplication::getConnection()->getType() ===
'pgsql')
1843 'ix_b_sale_location_left_margin_right_margin' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'LEFT_MARGIN',
'RIGHT_MARGIN']],
1844 'ix_b_sale_location_right_margin_left_margin' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'RIGHT_MARGIN',
'LEFT_MARGIN']],
1845 'ix_b_sale_location_parent_id' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'PARENT_ID']],
1846 'ix_b_sale_location_depth_level' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'DEPTH_LEVEL']],
1847 'ix_b_sale_location_type_id' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'TYPE_ID']],
1848 'ix_b_sale_location_type_id_left_margin_right_margin' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'TYPE_ID',
'LEFT_MARGIN',
'RIGHT_MARGIN']],
1850 'ix_b_sale_loc_name_name_upper' => [
'TABLE' => $locationNameTable,
'COLUMNS' => [
'NAME_UPPER']],
1851 'ix_b_sale_loc_name_location_id_language_id' => [
'TABLE' => $locationNameTable,
'COLUMNS' => [
'LOCATION_ID',
'LANGUAGE_ID']],
1853 'ix_b_sale_loc_ext_location_id_service_id' => [
'TABLE' => $locationExternalTable,
'COLUMNS' => [
'LOCATION_ID',
'SERVICE_ID']],
1856 'ix_b_sale_location_country_id' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'COUNTRY_ID']],
1857 'ix_b_sale_location_region_id' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'REGION_ID']],
1858 'ix_b_sale_location_city_id' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'CITY_ID']],
1861 'ix_b_sale_location_1' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'COUNTRY_ID'],
'DROP_ONLY' =>
true],
1862 'ix_b_sale_location_2' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'REGION_ID'],
'DROP_ONLY' =>
true],
1863 'ix_b_sale_location_3' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'CITY_ID'],
'DROP_ONLY' =>
true],
1868 'IX_SALE_LOCATION_MARGINS' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'LEFT_MARGIN',
'RIGHT_MARGIN']],
1869 'IX_SALE_LOCATION_MARGINS_REV' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'RIGHT_MARGIN',
'LEFT_MARGIN']],
1870 'IX_SALE_LOCATION_PARENT' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'PARENT_ID']],
1871 'IX_SALE_LOCATION_DL' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'DEPTH_LEVEL']],
1872 'IX_SALE_LOCATION_TYPE' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'TYPE_ID']],
1873 'IX_SALE_L_NAME_NAME_UPPER' => [
'TABLE' => $locationNameTable,
'COLUMNS' => [
'NAME_UPPER']],
1874 'IX_SALE_L_NAME_LID_LID' => [
'TABLE' => $locationNameTable,
'COLUMNS' => [
'LOCATION_ID',
'LANGUAGE_ID']],
1875 'IX_B_SALE_LOC_EXT_LID_SID' => [
'TABLE' => $locationExternalTable,
'COLUMNS' => [
'LOCATION_ID',
'SERVICE_ID']],
1876 'IX_SALE_LOCATION_TYPE_MARGIN' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'TYPE_ID',
'LEFT_MARGIN',
'RIGHT_MARGIN']],
1879 'IXS_LOCATION_COUNTRY_ID' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'COUNTRY_ID']],
1880 'IXS_LOCATION_REGION_ID' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'REGION_ID']],
1881 'IXS_LOCATION_CITY_ID' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'CITY_ID']],
1884 'IX_B_SALE_LOCATION_1' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'COUNTRY_ID'],
'DROP_ONLY' =>
true],
1885 'IX_B_SALE_LOCATION_2' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'REGION_ID'],
'DROP_ONLY' =>
true],
1886 'IX_B_SALE_LOCATION_3' => [
'TABLE' => $locationTable,
'COLUMNS' => [
'CITY_ID'],
'DROP_ONLY' =>
true],
1892 $map = static::getIndexMap();
1894 foreach(
$map as $index => $ixData)
1896 if($certainIndex !==
false && $certainIndex != $index)
1907 foreach(
$map as $ixName => $ixData)
1909 if (($ixData[
'DROP_ONLY'] ??
null) ===
true)
1914 if($certainIndex !==
false && $certainIndex != $ixName)
1920 $this->dbConnection->query(
'CREATE INDEX '.$ixName.
' ON '.$ixData[
'TABLE'].
' ('.implode(
', ', $ixData[
'COLUMNS']).
')');
1926 private function getCachedBundle($id)
1931 $res = $this->dbConnection->query(
"select ID from {$locationTable} where PARENT_ID = ".($id ==
'root' ?
'0' : intval($id)));
1932 while($item =
$res->fetch())
1933 $bundle[] = $item[
'ID'];
1938 private function checkNodeIsParent($id)
1942 $res = $this->dbConnection->query(
"select count(*) as CNT from {$locationTable} where PARENT_ID = ".($id ==
'root' ?
'0' : intval($id)))->fetch();
1944 return intval(
$res[
'CNT']);
1947 private function mergeRebalancedNodes()
1949 if($this->rebalanceInserter)
1951 $this->
logMessage(
'Finally, MERGE is in progress');
1953 $this->rebalanceInserter->flush();
1961 private function acceptRebalancedNode($node)
1963 $this->createTempTable();
1965 if(!$this->rebalanceInserter)
1967 if($this->dbConnType == self::DB_TYPE_ORACLE)
1968 $mtu = self::TREE_REBALANCE_TEMP_BLOCK_LEN_O;
1970 $mtu = self::TREE_REBALANCE_TEMP_BLOCK_LEN;
1972 $this->rebalanceInserter =
new BlockInserter(
array(
1973 'tableName' => self::TREE_REBALANCE_TEMP_TABLE_NAME,
1974 'exactFields' =>
array(
1975 'I' =>
array(
'data_type' =>
'integer'),
1976 'L' =>
array(
'data_type' =>
'integer'),
1977 'R' =>
array(
'data_type' =>
'integer'),
1978 'D' =>
array(
'data_type' =>
'integer'),
1980 'parameters' =>
array(
1986 $this->data[
'processed']++;
1988 $this->rebalanceInserter->insert($node);
1991 private function dropTempTable()
1993 if($this->dbConnection->isTableExists(self::TREE_REBALANCE_TEMP_TABLE_NAME))
1994 $this->dbConnection->query(
"drop table ".self::TREE_REBALANCE_TEMP_TABLE_NAME);
1997 private function createTempTable()
1999 $this->data[
'rebalance'][
'tableCreated'] ??=
false;
2000 if ($this->data[
'rebalance'][
'tableCreated'])
2005 $tableName = self::TREE_REBALANCE_TEMP_TABLE_NAME;
2007 if ($this->dbConnection->isTableExists($tableName))
2009 $this->dbConnection->query(
"truncate table {$tableName}");
2014 if($this->dbConnType == self::DB_TYPE_ORACLE)
2016 $this->dbConnection->query(
"create table {$tableName} (
2025 $this->dbConnection->query(
"create table {$tableName} (
2035 $this->data[
'rebalance'][
'tableCreated'] =
true;
2040 return $this->data[
'current'][
'bytesRead'] >= $this->data[
'files'][$this->data[
'current'][
'fIndex']][
'size'];
2045 return $this->data[
'current'][
'fIndex'] >=
count($this->data[
'files']);
2057 $storeTo = \CTempFile::GetDirectoryName(1);
2059 $storeTo .= $storeAs;
2061 if(file_exists($storeTo))
2063 if(!is_writable($storeTo))
2070 if (!defined(
'SALE_LOCATIONS_IMPORT_SOURCE_URL'))
2072 if (self::checkRegion())
2074 $query =
'https://' . self::DISTRIBUTOR_HOST . self::REMOTE_PATH .
$fileName;
2079 $query =
'http://' . SALE_LOCATIONS_IMPORT_SOURCE_URL .
'/' .
$fileName;
2089 if(!$client->download(
$query, $storeTo))
2091 $eFormatted =
array();
2092 foreach($client->getError() as
$code =>
$desc)
2098 $status = intval($client->getStatus());
2100 if(
$status != 200 && file_exists($storeTo))
2109 return filesize($storeTo);
2121 return self::LOCAL_SETS_PATH.sprintf(self::LOCAL_LOCATION_FILE,
$i);
2134 'application/vnd.ms-excel',
2135 'application/octet-stream'
2148 $lastError = error_get_last();
2152 $_SESSION[static::USER_FILE_DIRECTORY_SESSION_KEY] =
$localPath;
2162 case UPLOAD_ERR_INI_SIZE:
2163 $message =
'The uploaded file exceeds the upload_max_filesize directive in php.ini';
2165 case UPLOAD_ERR_FORM_SIZE:
2166 $message =
'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form';
2168 case UPLOAD_ERR_PARTIAL:
2169 $message =
'The uploaded file was only partially uploaded';
2171 case UPLOAD_ERR_NO_FILE:
2172 $message =
'No file were uploaded';
2174 case UPLOAD_ERR_NO_TMP_DIR:
2175 $message =
'Missing a temporary folder';
2177 case UPLOAD_ERR_CANT_WRITE:
2178 $message =
'Failed to write file to disk';
2180 case UPLOAD_ERR_EXTENSION:
2181 $message =
'File upload stopped by extension';
2194 $dataLocalPath = trim((
string)($this->data[
'LOCAL_PATH'] ??
''));
2195 $wasCreated =
false;
2196 if ($dataLocalPath !==
'' && \
Bitrix\
Main\
IO\Directory::isDirectoryExists($dataLocalPath))
2203 $localPath = \CTempFile::GetDirectoryName(10);
2235 if(is_array($value))
2237 foreach($value as $v)
2254 $value = mb_strtolower(trim($value));
2256 if(!preg_match(
'#^[a-z0-9]+$#i', $value))
2264 $this->useCache =
false;
2267 ########################################################
2268 ## static part is used in places like wizards, etc
2273 $res = Location\TypeTable::getList(
array(
'select' =>
array(
'ID',
'CODE',
'SORT')));
2274 while($item =
$res->fetch())
2275 $existed[$item[
'CODE']] = $item[
'ID'];
2283 $res = Location\ExternalServiceTable::getList(
array(
'select' =>
array(
'ID',
'CODE')));
2284 while($item =
$res->fetch())
2285 $existed[$item[
'CODE']] = $item[
'ID'];
2293 if($existed ===
false)
2294 $existed = static::getExistedTypes();
2297 $langs = Location\Admin\NameHelper::getLanguageList();
2299 foreach($types as $line)
2302 unset($line[
'SELECTORLEVEL']);
2303 unset($line[
'DEFAULTSELECT']);
2307 if(!is_array($line[
'NAME']))
2308 $line[
'NAME'] =
array();
2314 $names[mb_strtoupper($lid)] = static::getTranslatedName($line[
'NAME'], $lid);
2316 $line[
'NAME'] = $names;
2319 if(!isset($existed[$line[
'CODE']]))
2321 $existed[$line[
'CODE']] = static::createType($line);
2336 $languageIdMapped = mb_strtoupper(
Location\Admin\NameHelper::mapLanguage($languageId));
2337 $languageId = mb_strtoupper($languageId);
2339 if ((
string)($names[$languageId][
'NAME'] ??
null) !==
'')
2341 return $names[$languageId];
2344 if ((
string)($names[$languageIdMapped][
'NAME'] ??
null) !==
'')
2346 return $names[$languageIdMapped];
2349 return $names[
'EN'];
2360 if(!isset(
$map[$fld]))
2368 if(!
$res->isSuccess())
2371 return $res->getId();
2377 if(!
$res->isSuccess())
2380 return $res->getId();
2386 $csvReader->LoadFile($file);
2390 while(
$type = $csvReader->FetchAssoc())
2394 unset(
$type[
'SELECTORLEVEL']);
2395 unset(
$type[
'DEFAULTSELECT']);
2409 $csvReader->LoadFile($file);
2411 $services =
array();
2412 while(
$service = $csvReader->FetchAssoc())
2422 if (
$timeLimit < $descriptior[
'TIME_LIMIT']) set_time_limit($descriptior[
'TIME_LIMIT'] + 5);
2424 $endTime = time() + $descriptior[
'TIME_LIMIT'];
2426 if($descriptior[
'STEP'] ==
'rebalance')
2430 $descriptior[
'STEP'] =
'done';
2433 if($descriptior[
'STEP'] ==
'import')
2435 if(!isset($descriptior[
'DO_SYNC']))
2437 $res = \Bitrix\Sale\Location\LocationTable::getList(
array(
'select' =>
array(
'CNT')))->fetch();
2438 $descriptior[
'DO_SYNC'] = intval(
$res[
'CNT'] > 0);
2441 if(!isset($descriptior[
'TYPES']))
2443 $descriptior[
'TYPE_MAP'] = static::getTypeMap($descriptior[
'TYPE_FILE']);
2444 $descriptior[
'TYPES'] = static::createTypes($descriptior[
'TYPE_MAP']);
2446 $descriptior[
'SERVICE_MAP'] = static::getServiceMap($descriptior[
'SERVICE_FILE']);
2447 $descriptior[
'SERVICES'] = static::getExistedServices();
2451 $csvReader->LoadFile($descriptior[
'FILE']);
2453 while(time() < $endTime)
2455 $block = $csvReader->ReadBlockLowLevel($descriptior[
'POS'], 10);
2460 foreach($block as $item)
2462 if($descriptior[
'DO_SYNC'])
2464 $id = static::checkLocationCodeExists($item[
'CODE']);
2467 $descriptior[
'CODES'][$item[
'CODE']] = $id;
2473 $item[
'TYPE_ID'] = $descriptior[
'TYPES'][$item[
'TYPE_CODE']];
2474 unset($item[
'TYPE_CODE']);
2477 if($item[
'PARENT_CODE'] <>
'')
2479 if(!isset($descriptior[
'CODES'][$item[
'PARENT_CODE']]))
2481 $descriptior[
'CODES'][$item[
'PARENT_CODE']] = static::checkLocationCodeExists($item[
'PARENT_CODE']);
2484 $item[
'PARENT_ID'] = $descriptior[
'CODES'][$item[
'PARENT_CODE']];
2486 unset($item[
'PARENT_CODE']);
2489 if(is_array($item[
'EXT']))
2491 foreach($item[
'EXT'] as
$code => $values)
2495 if(!isset($descriptior[
'SERVICES'][
$code]))
2497 $descriptior[
'SERVICES'][
$code] = static::createService(
array(
2502 if(
$code ==
'ZIP_LOWER')
2504 if($values[0] ==
'')
2507 $values = explode(
',', $values[0]);
2509 if(!is_array($values))
2512 $values = array_unique($values);
2515 if(is_array($values))
2517 foreach($values as $value)
2522 $item[
'EXTERNAL'][] =
array(
2523 'SERVICE_ID' => $descriptior[
'SERVICES'][
$code],
2531 unset($item[
'EXT'], $item[
'ZIP_LOWER']);
2536 'RESET_LEGACY' =>
false,
2537 'REBALANCE' =>
false
2541 if(!
$res->isSuccess())
2544 $descriptior[
'CODES'][$item[
'CODE']] =
$res->getId();
2550 unset($descriptior[
'CODES']);
2551 $descriptior[
'STEP'] =
'rebalance';
2555 return $descriptior[
'STEP'] ==
'done';
2561 if (!is_array(
$data))
2565 if (!isset(
$data[
'NAME'][
'RU']))
2569 if (!is_array(
$data[
'NAME'][
'RU']))
2573 $data[
'NAME'][
'EN'] ??= [];
2575 foreach (
$data[
'NAME'][
'RU'] as
$k => $v)
2577 if ((
string)(
$data[
'NAME'][
'EN'][
$k] ??
'') ===
'')
2579 $data[
'NAME'][
'EN'][
$k] = Location\Admin\NameHelper::translitFromUTF8(
$data[
'NAME'][
'RU'][
$k]);
2584 private static function checkRegion(): bool
2586 $region = Application::getInstance()->getLicense()->getRegion();
static getConnection($name="")
static createDirectory($path)
static deleteDirectory($path)
static getList(array $parameters=array())
const MAX_CODE_FETCH_BLOCK_LEN
static createDirectory($path)
const REMOTE_TYPE_GROUP_FILE
getRemoteExternalServices()
const TREE_REBALANCE_TEMP_BLOCK_LEN
getSubpercentForStageRestoreIndexes()
static getServiceMap($file)
readBlockFromCurrentFile2()
static deleteDirectory($path)
getSubpercentForstageDeleteAll()
const USER_FILE_TEMP_NAME
getSubpercentForStageDropIndexes()
static downloadFile($fileName, $storeAs, $skip404=false, $storeTo=false)
const LOCAL_EXTERNAL_SERVICE_FILE
static cleanWorkDirectory()
getSubpercentForStageDownloadFiles()
restoreIndexes($certainIndex=false)
const USER_FILE_DIRECTORY_SESSION_KEY
prepareImportProcessOptions($options)
getLocationCodeToIdMap($codes)
const LOCAL_TYPE_GROUP_FILE
static checkLocationCodeExists($code)
static createTypes($types, $existed=false)
buildStaticLocationIndex()
static getTranslatedName($names, $languageId)
stageRebalanceCleanupTempTable()
const LOCAL_LOCATION_FILE
const REMOTE_EXTERNAL_SERVICE_FILE
getRemoteLayout($getFlat=false)
static getExistedServices()
getSubpercentForStageProcessFiles()
dropIndexByName($indexName, $tableName)
static getSiteLanguages()
normalizeQueryArray($value)
checkIndexExistsByName($indexName, $tableName)
determineLayoutToImport()
checkExternalServiceAllowed($code)
static explainFileUploadError($error)
const TREE_REBALANCE_TEMP_TABLE_NAME
const INSERTER_MTU_ORACLE
checkFileCompletelyRead()
manageExistedLocationIndex($memGroups)
getLocationCodeToIdMapQuery($buffer, &$result)
const TREE_REBALANCE_TEMP_BLOCK_LEN_O
static importFile(&$descriptior)
getStatistics($type='TOTAL')
getSubpercentForStageRebalanceWalkTree()
static parseQueryCode($value)
buildExternalSerivceTable()
onBeforePerformIteration()
static createService($service)
dropIndexes($certainIndex=false)
getTypeLevels($langId=LANGUAGE_ID)
checkBufferIsFull($bufferSize)
static addExtended(array $data, array $additional=array())
static update($primary, array $data)
static addAbsentForOwner($primaryOwner, $names, $behaviour=array('TREAT_EMPTY_AS_ABSENT'=> true))
static resort($dontCareEvents=false)
static mergeRelationsFromTemporalTable($temporalTabName, $additinalFlds=array(), $fldMap=array())
static getCountByFilter($filter=array())
getStagePercent($sNum=false)
Percentage.
logMessage($message='', $addTimeStamp=true)
if(!defined("ADMIN_AJAX_MODE") &&(($_REQUEST["mode"] ?? '') !='excel')) $buffer
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
$isBitrixSiteManagementOnly
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
if(!defined('SITE_ID')) $lang
if(mb_strlen($order)< 6) $desc
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"