79 'CODE' =>
'DELETE_ALL',
80 'CALLBACK' =>
'stageDeleteAll',
81 'SUBPERCENT_CALLBACK' =>
'getSubpercentForstageDeleteAll'
88 'CODE' =>
'DOWNLOAD_FILES',
89 'CALLBACK' =>
'stageDownloadFiles',
90 'SUBPERCENT_CALLBACK' =>
'getSubpercentForStageDownloadFiles'
93 if(
$options[
'REQUEST'][
'OPTIONS'][
'DROP_ALL'])
97 'CODE' =>
'DELETE_ALL',
98 'CALLBACK' =>
'stageDeleteAll',
99 'SUBPERCENT_CALLBACK' =>
'getSubpercentForstageDeleteAll'
105 'CODE' =>
'DROP_INDEXES',
106 'CALLBACK' =>
'stageDropIndexes',
107 'SUBPERCENT_CALLBACK' =>
'getSubpercentForStageDropIndexes'
113 'CODE' =>
'PROCESS_FILES',
114 'CALLBACK' =>
'stageProcessFiles',
115 'SUBPERCENT_CALLBACK' =>
'getSubpercentForStageProcessFiles'
118 if(
$options[
'REQUEST'][
'OPTIONS'][
'INTEGRITY_PRESERVE'])
123 'CODE' =>
'INTEGRITY_PRESERVE',
124 'CALLBACK' =>
'stageIntegrityPreserve'
131 'CODE' =>
'REBALANCE_WALK_TREE',
132 'CALLBACK' =>
'stageRebalanceWalkTree',
133 'SUBPERCENT_CALLBACK' =>
'getSubpercentForStageRebalanceWalkTree'
139 'CODE' =>
'REBALANCE_CLEANUP_TEMP_TABLE',
140 'CALLBACK' =>
'stageRebalanceCleanupTempTable'
146 'CODE' =>
'RESTORE_INDEXES',
147 'CALLBACK' =>
'stageRestoreIndexes',
148 'SUBPERCENT_CALLBACK' =>
'getSubpercentForStageRestoreIndexes'
152 $this->dbConnection = Main\HttpApplication::getConnection();
153 $this->dbConnType = $this->dbConnection->getType();
154 $this->dbHelper = $this->dbConnection->getSqlHelper();
166 $options[
'LANGUAGE_ID'] = trim((
string)(
$options[
'LANGUAGE_ID'] ?? LANGUAGE_ID));
169 $options[
'LANGUAGE_ID'] = LANGUAGE_ID;
173 if (is_object(
$options[
'REQUEST']) && method_exists(
$options[
'REQUEST'],
'toArray'))
181 $options[
'REQUEST'][
'OPTIONS'] ??= [];
182 if (!is_array(
$options[
'REQUEST'][
'OPTIONS']))
184 $options[
'REQUEST'][
'OPTIONS'] = [];
187 $requestOptions = &
$options[
'REQUEST'][
'OPTIONS'];
188 $requestOptions[
'DROP_ALL'] ??=
null;
189 $requestOptions[
'INTEGRITY_PRESERVE'] ??=
null;
190 $requestOptions[
'EXCLUDE_COUNTRY_DISTRICT'] ??=
null;
191 $requestOptions[
'SOURCE'] ??=
null;
192 $requestOptions[
'TIME_LIMIT'] = (int)($requestOptions[
'TIME_LIMIT'] ?? 0);
193 unset($requestOptions);
195 $options[
'REQUEST'][
'ADDITIONAL'] ??= [];
196 if (!is_array(
$options[
'REQUEST'][
'ADDITIONAL']))
198 $options[
'REQUEST'][
'ADDITIONAL'] = [];
202 if (!is_array(
$options[
'LOCATION_SETS']))
212 if ($this->options[
'ONLY_DELETE_ALL'])
217 $this->data[
'inited'] ??=
false;
218 if (!$this->data[
'inited'])
220 if((
string)($this->data[
'LOCAL_PATH'] ??
'') ===
'')
225 $opts = $this->options[
'REQUEST'][
'OPTIONS'];
227 if(!in_array($opts[
'SOURCE'], array(self::SOURCE_REMOTE, self::SOURCE_FILE)))
231 if($opts[
'SOURCE'] == self::SOURCE_REMOTE)
238 $this->data[
'settings'] = array(
243 if($opts[
'SOURCE'] == self::SOURCE_REMOTE)
245 $this->data[
'settings'][
'additional'] = is_array($this->options[
'REQUEST'][
'ADDITIONAL']) ? array_flip(array_values($this->options[
'REQUEST'][
'ADDITIONAL'])) : array();
247 if(isset($this->data[
'settings'][
'additional'][
'ZIP']))
248 $this->data[
'settings'][
'additional'][
'ZIP_LOWER'] = $this->data[
'settings'][
'additional'][
'ZIP'];
252 $this->data[
'settings'][
'additional'] =
false;
258 $this->data[
'inited'] =
true;
261 if ($this->data[
'inited'] && $this->data[
'LOCAL_PATH_CREATED'])
263 $this->touchImportTmpFiles((
string)$this->data[
'LOCAL_PATH']);
266 $timeLimit = $this->data[
'settings'][
'options'][
'TIME_LIMIT'];
276 private function touchImportTmpFiles(
string $localPath): void
278 $iterator = new \RecursiveIteratorIterator(
279 new \RecursiveDirectoryIterator($localPath)
281 foreach ($iterator as $file) {
288 touch($file->getPathname());
299 if((
string) $_SESSION[self::USER_FILE_DIRECTORY_SESSION_KEY] ==
'')
303 $dstFilePath = $this->data[
'LOCAL_PATH'].self::getFileNameByIndex(0);
306 $this->
createDirectory($this->data[
'LOCAL_PATH'].
'/'.self::LOCAL_SETS_PATH);
308 if(!@copy($srcFilePath, $dstFilePath))
310 $lastError = error_get_last();
314 $this->data[
'files'] = array(
316 'size' => filesize($dstFilePath),
317 'memgroup' =>
'static'
327 $this->data[
'files'] = array();
338 $this->data[
'requiredGroups'] = array();
339 foreach($typeGroups as $code => $types)
341 if($code ==
'LAYOUT')
344 foreach($types as $type)
346 if(isset($this->data[
'types'][
'allowed'][$type]))
348 $this->data[
'requiredGroups'][] = ToLower($code);
361 $this->data[
'files'][0] = array(
362 'size' => static::downloadFile(self::REMOTE_LAYOUT_FILE, self::getFileNameByIndex(0),
false, $this->data[
'LOCAL_PATH']),
363 'onlyThese' => array_flip($this->data[
'settings'][
'bundles'][
'allpoints']),
364 'memgroup' =>
'static'
367 $this->data[
'fileDownload'][
'currentEndPoint'] = 0;
368 $this->data[
'fileDownload'][
'currentFileOffset'] = 1;
371 $i =& $this->data[
'fileDownload'][
'currentEndPoint'];
372 $j =& $this->data[
'fileDownload'][
'currentFileOffset'];
374 while($this->
checkQuota() && isset($this->data[
'settings'][
'bundles'][
'endpoints'][$i]))
376 $ep = $this->data[
'settings'][
'bundles'][
'endpoints'][$i];
378 foreach($this->data[
'requiredGroups'] as $code)
381 $file = $packPath.$ep.
'_'.$code.
'.csv';
384 $this->data[
'files'][$j] = array(
385 'size' => static::downloadFile($file, $name,
false, $this->data[
'LOCAL_PATH']),
397 if(!isset($this->data[
'settings'][
'bundles'][
'endpoints'][$i]))
399 unset($this->data[
'requiredGroups']);
400 unset($this->data[
'settings'][
'bundles'][
'endpoints']);
415 $currEp = (int)($this->data[
'fileDownload'][
'currentEndPoint'] ?? 0);
422 return round($pRange * ($currEp / count($this->data[
'settings'][
'bundles'][
'endpoints'])));
442 Location\GroupLocationTable::deleteAll();
445 Location\SiteLocationTable::deleteAll();
462 if(
$step >= $stepsCount)
466 return round($pRange * (
$step / $stepsCount));
476 'IX_B_SALE_LOC_MARGINS',
477 'IX_B_SALE_LOC_MARGINS_REV',
478 'IX_B_SALE_LOC_PARENT',
480 'IX_B_SALE_LOC_TYPE',
481 'IX_B_SALE_LOC_NAME_NAME_U',
482 'IX_B_SALE_LOC_NAME_LI_LI',
483 'IX_B_SALE_LOC_EXT_LID_SID',
486 'IXS_LOCATION_COUNTRY_ID',
487 'IXS_LOCATION_REGION_ID',
488 'IXS_LOCATION_CITY_ID',
489 'IX_B_SALE_LOCATION_1',
490 'IX_B_SALE_LOCATION_2',
491 'IX_B_SALE_LOCATION_3'
494 if(!isset($indexes[$this->
getStep()]))
511 if(
$step >= $indexCount)
515 return round($pRange * (
$step / $indexCount));
524 $fIndex = $this->data[
'current'][
'fIndex'];
526 $onlyThese =& $this->data[
'files'][$fIndex][
'onlyThese'];
530 if(!isset($this->hitData[
'csv']))
532 $file = $this->data[
'LOCAL_PATH'].$fName;
534 if(!file_exists($file) || !is_readable($file))
540 $this->hitData[
'csv']->LoadFile($file);
541 $this->hitData[
'csv']->AddEventCallback(
'AFTER_ASSOC_LINE_READ', array($this,
'provideEnFromRu'));
544 $block = $this->hitData[
'csv']->ReadBlockLowLevel($this->data[
'current'][
'bytesRead'], 100);
546 $this->data[
'current'][
'linesRead'] += count($block);
553 if($this->hitData[
'csv']->CheckFileIsLegacy())
558 if(is_array($onlyThese))
560 foreach($block as $i => $line)
562 if(is_array($onlyThese) && !isset($onlyThese[$line[
'CODE']]))
582 return $res[
'ID'] ??
false;
597 return mb_strtoupper($value);
599 array_keys(
Location\Admin\NameHelper::getLanguageList()))
602 foreach($block as $i =>
$data)
604 $code =
$data[
'CODE'];
608 if (!!($this->options[
'REQUEST'][
'OPTIONS'][
'EXCLUDE_COUNTRY_DISTRICT']))
610 if (!isset($this->data[
'COUNTRY_2_DISTRICT']))
612 $this->data[
'COUNTRY_2_DISTRICT'] = [];
615 if (
$data[
'TYPE_CODE'] ==
'COUNTRY')
617 $this->data[
'LAST_COUNTRY'] =
$data[
'CODE'];
619 elseif (
$data[
'TYPE_CODE'] ==
'COUNTRY_DISTRICT')
621 $this->data[
'COUNTRY_2_DISTRICT'][$code] = $this->data[
'LAST_COUNTRY'];
626 if (isset($this->data[
'COUNTRY_2_DISTRICT'][
$data[
'PARENT_CODE']]))
628 $data[
'PARENT_CODE'] = $this->data[
'COUNTRY_2_DISTRICT'][
$data[
'PARENT_CODE']];
635 if (!!($this->options[
'REQUEST'][
'OPTIONS'][
'EXCLUDE_COUNTRY_DISTRICT']))
637 if (!isset($this->data[
'COUNTRY_2_DISTRICT']))
639 $this->data[
'COUNTRY_2_DISTRICT'] = [];
642 if (
$data[
'TYPE_CODE'] ==
'COUNTRY')
644 $this->data[
'LAST_COUNTRY'] =
$data[
'CODE'];
646 elseif (
$data[
'TYPE_CODE'] ==
'COUNTRY_DISTRICT')
648 $this->data[
'COUNTRY_2_DISTRICT'][$code] = $this->data[
'LAST_COUNTRY'];
653 if (isset($this->data[
'COUNTRY_2_DISTRICT'][
$data[
'PARENT_CODE']]))
655 $data[
'PARENT_CODE'] = $this->data[
'COUNTRY_2_DISTRICT'][
$data[
'PARENT_CODE']];
660 if(isset($this->data[
'existedlocs'][
'static'][$code]) || isset($this->data[
'existedlocs'][$gid][$code]))
663 if(!isset($this->data[
'types'][
'allowed'][
$data[
'TYPE_CODE']]))
667 if(!$this->data[
'TABLE_WERE_EMPTY'])
671 if(intval($existedId))
673 $this->data[
'existedlocs'][$gid][$code] = $existedId;
680 if(
$data[
'PARENT_CODE'] <>
'')
682 if(isset($this->data[
'existedlocs'][
'static'][
$data[
'PARENT_CODE']]))
684 $data[
'PARENT_ID'] = $this->data[
'existedlocs'][
'static'][
$data[
'PARENT_CODE']];
686 elseif(isset($this->data[
'existedlocs'][$gid][
$data[
'PARENT_CODE']]))
688 $data[
'PARENT_ID'] = $this->data[
'existedlocs'][$gid][
$data[
'PARENT_CODE']];
692 $data[
'PARENT_ID'] = 0;
697 $data[
'PARENT_ID'] = 0;
700 unset(
$data[
'PARENT_CODE']);
704 $data[
'TYPE_ID'] = $this->data[
'types'][
'code2id'][
$data[
'TYPE_CODE']];
705 unset(
$data[
'TYPE_CODE']);
709 $names =
$data[
'NAME'];
710 unset(
$data[
'NAME']);
712 $external =
$data[
'EXT'];
715 $data[
'LONGITUDE'] = (float)(
$data[
'LONGITUDE'] ?? 0);
716 $data[
'LATITUDE'] = (float)(
$data[
'LATITUDE'] ?? 0);
719 $data[
'LONGITUDE'] = 0;
720 $data[
'LATITUDE'] = 0;
723 $locationId = $this->hitData[
'HANDLES'][
'LOCATION']->insert(
$data);
727 $this->data[
'existedlocs'][$gid][
$data[
'CODE']] = $locationId;
731 if(is_array($names) && !empty($names))
735 foreach($langs as $lid => $f)
737 $lid = ToLower($lid);
738 $toAdd = static::getTranslatedName($names, $lid);
740 $this->hitData[
'HANDLES'][
'NAME']->insert(array(
741 'NAME' => $toAdd[
'NAME'],
742 'NAME_UPPER' => ToUpper($toAdd[
'NAME']),
743 'LANGUAGE_ID' => $lid,
744 'LOCATION_ID' => $locationId
752 if(is_array($external) && !empty($external))
754 foreach($external as $sCode => $values)
758 $serviceId = $this->data[
'externalService'][
'code2id'][$sCode];
763 if($sCode ==
'ZIP_LOWER')
768 $values = explode(
',', $values);
770 if(!is_array($values))
773 $values = array_unique($values);
776 if(is_array($values))
778 foreach($values as $val)
783 $this->hitData[
'HANDLES'][
'EXTERNAL']->insert(array(
784 'SERVICE_ID' => $serviceId,
786 'LOCATION_ID' => $locationId
798 return $this->data[
'files'][$this->data[
'current'][
'fIndex']][
'memgroup'];
803 if($this->dbConnType == self::DB_TYPE_ORACLE)
808 $this->hitData[
'HANDLES'][
'LOCATION'] =
new BlockInserter(array(
809 'entityName' =>
'\Bitrix\Sale\Location\LocationTable',
810 'exactFields' => array(
'CODE',
'TYPE_ID',
'PARENT_ID',
'LATITUDE',
'LONGITUDE'),
811 'parameters' => array(
812 'autoIncrementFld' =>
'ID',
818 'entityName' =>
'\Bitrix\Sale\Location\Name\LocationTable',
819 'exactFields' => array(
'NAME',
'NAME_UPPER',
'LANGUAGE_ID',
'LOCATION_ID'),
820 'parameters' => array(
825 $this->hitData[
'HANDLES'][
'EXTERNAL'] =
new BlockInserter(array(
826 'entityName' =>
'\Bitrix\Sale\Location\ExternalTable',
827 'exactFields' => array(
'SERVICE_ID',
'XML_ID',
'LOCATION_ID'),
828 'parameters' => array(
836 $this->data[
'current'] = array(
842 $this->hitData[
'HANDLES'][
'LOCATION']->resetAutoIncrementFromIndex();
845 $this->data[
'TABLE_WERE_EMPTY'] = Location\LocationTable::getCountByFilter() == 0;
864 unset($this->hitData[
'csv']);
865 $this->data[
'current'][
'fIndex']++;
866 $this->data[
'current'][
'bytesRead'] = 0;
867 $this->data[
'current'][
'linesRead'] = 0;
868 $this->data[
'current'][
'legacy'] = array();
873 unset($this->data[
'existedlocs']);
883 $this->hitData[
'HANDLES'][
'LOCATION']->flush();
884 $this->hitData[
'HANDLES'][
'NAME']->flush();
885 $this->hitData[
'HANDLES'][
'EXTERNAL']->flush();
899 if(!isset($this->data[
'current'][
'fIndex']))
902 $fIndex = $this->data[
'current'][
'fIndex'];
905 foreach($this->data[
'files'] as $file)
910 $fileBytesRead += $file[
'size'];
912 $totalSize += $file[
'size'];
918 return round($pRange * (intval($fileBytesRead + $this->data[
'current'][
'bytesRead']) / $totalSize));
930 $res = Location\LocationTable::getList(array(
938 $relations = array();
940 while($item = $res->fetch())
942 if(isset($lay[$item[
'CODE']]) && ((
string) $lay[$item[
'CODE']][
'PARENT_CODE'] !=
''))
943 $relations[$item[
'CODE']] = $lay[$item[
'CODE']][
'PARENT_CODE'];
946 $code2id[$item[
'CODE']] = $item[
'ID'];
951 foreach($code2id as $code => $id)
953 if (!isset($relations[$code]))
957 if ((
string)($parentCode2id[$relations[$code]] ??
'') !==
'')
959 $res = Location\LocationTable::update(
961 [
'PARENT_ID' => $parentCode2id[$relations[$code]]]
963 if (!$res->isSuccess())
978 if(!isset($this->data[
'rebalance'][
'queue']))
984 $this->data[
'rebalance'][
'margin'] = -1;
985 $this->data[
'processed'] = 0;
986 $this->data[
'rebalance'][
'queue'] = array(array(
'I' =>
'root',
'D' => 0));
988 $tableName = Location\LocationTable::getTableName();
989 $res = Main\HttpApplication::getConnection()->query(
"select count(*) as CNT from {$tableName}")->fetch();
991 $this->data[
'rebalance'][
'cnt'] = intval($res[
'CNT']);
995 while(!empty($this->data[
'rebalance'][
'queue']) && $this->
checkQuota())
999 $node =& $this->data[
'rebalance'][
'queue'][0];
1001 if(isset($node[
'L']))
1004 array_shift($this->data[
'rebalance'][
'queue']);
1005 if($node[
'I'] !=
'root')
1007 $this->acceptRebalancedNode(array(
1011 'R' => ++$this->data[
'rebalance'][
'margin']
1015 $this->data[
'rebalance'][
'margin']++;
1019 $a = $this->getCachedBundle($node[
'I']);
1024 $node[
'L'] = ++$this->data[
'rebalance'][
'margin'];
1028 if($this->checkNodeIsParent($id))
1030 array_unshift($this->data[
'rebalance'][
'queue'], array(
'I' => $id,
'D' => $node[
'D'] + 1));
1034 $this->acceptRebalancedNode(array(
1036 'D' => $node[
'D'] + 1,
1037 'L' => ++$this->data[
'rebalance'][
'margin'],
1038 'R' => ++$this->data[
'rebalance'][
'margin']
1045 array_shift($this->data[
'rebalance'][
'queue']);
1046 $this->acceptRebalancedNode(array(
1049 'L' => ++$this->data[
'rebalance'][
'margin'],
1050 'R' => ++$this->data[
'rebalance'][
'margin']
1056 $this->
logMessage(
'Q size is '.count($this->data[
'rebalance'][
'queue']).
' already processed: '.$this->data[
'processed'].
'/'.$this->data[
'rebalance'][
'cnt']);
1059 if(empty($this->data[
'rebalance'][
'queue']))
1062 $this->mergeRebalancedNodes();
1068 if($this->rebalanceInserter)
1069 $this->rebalanceInserter->flush();
1076 $processed = $this->data[
'processed'] ?? 0;
1077 $cnt = $this->data[
'rebalance'][
'cnt'] ?? 0;
1078 if (!$processed || !$cnt)
1082 $part = round($pRange * ($processed / $cnt));
1084 return min($part, $pRange);
1092 $this->dropTempTable();
1102 'IX_B_SALE_LOC_MARGINS',
1103 'IX_B_SALE_LOC_MARGINS_REV',
1106 'IX_B_SALE_LOC_TYPE',
1107 'IX_B_SALE_LOC_NAME_NAME_U',
1108 'IX_B_SALE_LOC_NAME_LI_LI',
1109 'IX_B_SALE_LOC_EXT_LID_SID',
1112 'IXS_LOCATION_COUNTRY_ID',
1113 'IXS_LOCATION_REGION_ID',
1114 'IXS_LOCATION_CITY_ID',
1117 if(isset($indexes[$this->
getStep()]))
1125 Location\LocationTable::resetLegacyPath();
1137 if(
$step >= $stepCount)
1143 return round($pRange * (
$step / $stepCount));
1152 return $this->options[
'LANGUAGE_ID'];
1161 $res = Location\TypeTable::getList(array(
1163 'CODE',
'TNAME' =>
'NAME.NAME'
1170 'NAME.NAME' =>
'asc'
1173 while($item = $res->fetch())
1174 $result[$item[
'CODE']] = $item[
'TNAME'];
1188 if(empty($this->stat))
1190 $types = \Bitrix\Sale\Location\Admin\TypeHelper::getTypes(array(
'LANGUAGE_ID' => $this->
getLanguageId()));
1192 $res = Location\LocationTable::getList(array(
1195 'TCODE' =>
'TYPE.CODE'
1203 while($item = $res->fetch())
1205 $total += intval($item[
'CNT']);
1206 $stat[$item[
'TCODE']] = $item[
'CNT'];
1209 foreach($types as $code =>
$data)
1211 $this->stat[$code] = array(
1212 'NAME' =>
$data[
'NAME_CURRENT'],
1214 'CNT' => isset(
$stat[$code]) ? intval(
$stat[$code]) : 0,
1218 $this->stat[
'TOTAL'] = array(
'CNT' => $total,
'CODE' =>
'TOTAL');
1220 $res = Location\GroupTable::getList(array(
1223 'data_type' =>
'integer',
1224 'expression' => array(
1234 $this->stat[
'GROUPS'] = array(
'CNT' => intval($res[
'CNT']),
'CODE' =>
'GROUPS');
1237 return intval($this->stat[$type][
'CNT']);
1244 $parentness = array();
1245 foreach($lay as
$data)
1247 $parentCode = (string)(
$data[
'PARENT_CODE'] ??
'');
1248 if ($parentCode ===
'')
1252 $parentness[$parentCode] ??= 0;
1253 $parentness[$parentCode]++;
1256 $bundles = array_flip($this->data[
'settings'][
'sets']);
1258 $selectedLayoutParts = array();
1259 foreach($bundles as $bundle => $void)
1261 if(!isset($lay[$bundle]))
1267 $currentBundle = $bundle;
1269 while($currentBundle)
1274 throw new Main\SystemException(
'Too deep recursion got when building chains. Layout file is broken');
1276 if(isset($lay[$currentBundle]))
1278 $chain[] = $currentBundle;
1279 if($lay[$currentBundle][
'PARENT_CODE'] <>
'')
1281 $currentBundle = $lay[$currentBundle][
'PARENT_CODE'];
1283 if(!isset($lay[$currentBundle]))
1285 throw new Main\SystemException(
'Unknown parent bundle found ('.$currentBundle.
'). Layout file is broken');
1290 $currentBundle =
false;
1295 if(is_array($chain) && !empty($chain))
1297 $chain = array_reverse($chain);
1300 $subChain = array();
1301 foreach($chain as $i => $node)
1303 if(isset($bundles[$node]))
1305 $subChain = array_slice($chain, $i);
1310 if(!empty($subChain))
1311 $selectedLayoutParts = array_merge($selectedLayoutParts, $subChain);
1316 $selectedLayoutParts = array_unique($selectedLayoutParts);
1318 $this->data[
'settings'][
'bundles'] = array(
'endpoints' => array(),
'allpoints' => $selectedLayoutParts);
1320 foreach($selectedLayoutParts as $bCode)
1322 if(!isset($parentness[$bCode]))
1323 $this->data[
'settings'][
'bundles'][
'endpoints'][] = $bCode;
1327 unset($this->data[
'settings'][
'sets']);
1332 $converted = array();
1334 foreach($block as $line)
1337 $typeCode =
'COUNTRY';
1338 elseif($line[0] ==
'R')
1339 $typeCode =
'REGION';
1340 elseif($line[0] ==
'T')
1345 $code = md5(implode(
':', $line));
1347 if($typeCode ==
'REGION')
1348 $parentCode = $this->data[
'current'][
'legacy'][
'lastCOUNTRY'];
1349 elseif($typeCode ==
'CITY')
1350 $parentCode = $this->data[
'current'][
'legacy'][
'lastParent'];
1354 if($typeCode !=
'CITY')
1356 $this->data[
'current'][
'legacy'][
'last'.$typeCode] = $code;
1357 $this->data[
'current'][
'legacy'][
'lastParent'] = $code;
1362 'TYPE_CODE' => $typeCode,
1363 'PARENT_CODE' => $parentCode
1368 $lineLen = count($line);
1369 for($k = 1; $k < $lineLen; $k++)
1377 $cLine[
'NAME'][ToUpper($lang)][
'NAME'] = $line[$k];
1380 $expectLang = !$expectLang;
1383 $converted[] = $cLine;
1391 return $this->data[
'settings'][
'options'][
'SOURCE'] == $sType;
1399 static::downloadFile(self::REMOTE_LAYOUT_FILE, self::LOCAL_LAYOUT_FILE,
false, $localPath);
1402 $csv->AddEventCallback(
'AFTER_ASSOC_LINE_READ', array($this,
'provideEnFromRu'));
1403 $res = $csv->ReadBlock($localPath.self::LOCAL_LAYOUT_FILE);
1408 foreach($res as $line)
1409 $result[$line[
'CODE']] = $line;
1416 foreach($res as $line)
1418 $line[
'NAME'][ToUpper($lang)] = static::getTranslatedName($line[
'NAME'], $lang);
1419 $result[$line[
'PARENT_CODE']][$line[
'CODE']] = $line;
1434 if(!$this->useCache || !isset($this->data[
'settings'][
'remote'][
'types']))
1438 static::downloadFile(self::REMOTE_TYPE_FILE, self::LOCAL_TYPE_FILE,
false, $localPath);
1441 $csv->AddEventCallback(
'AFTER_ASSOC_LINE_READ', array($this,
'provideEnFromRu'));
1442 $res = $csv->ReadBlock($localPath.self::LOCAL_TYPE_FILE);
1445 foreach($res as $line)
1446 $result[$line[
'CODE']] = $line;
1448 $this->data[
'settings'][
'remote'][
'types'] = $result;
1456 return $this->data[
'settings'][
'remote'][
'types'];
1462 if(!$this->useCache || !isset($this->data[
'settings'][
'remote'][
'external_services']))
1466 static::downloadFile(self::REMOTE_EXTERNAL_SERVICE_FILE, self::LOCAL_EXTERNAL_SERVICE_FILE,
false, $localPath);
1469 $res = $csv->ReadBlock($localPath.self::LOCAL_EXTERNAL_SERVICE_FILE);
1472 foreach($res as $line)
1473 $result[$line[
'CODE']] = $line;
1475 $this->data[
'settings'][
'remote'][
'external_services'] = $result;
1483 return $this->data[
'settings'][
'remote'][
'external_services'];
1489 if(!$this->useCache || !isset($this->data[
'settings'][
'remote'][
'typeGroups']))
1493 static::downloadFile(self::REMOTE_TYPE_GROUP_FILE, self::LOCAL_TYPE_GROUP_FILE,
false, $localPath);
1496 $res = $csv->ReadBlock($localPath.self::LOCAL_TYPE_GROUP_FILE);
1499 foreach($res as $line)
1501 $result[$line[
'CODE']] = explode(
':', $line[
'TYPES']);
1504 $this->data[
'settings'][
'remote'][
'typeGroups'] = $result;
1512 return $this->data[
'settings'][
'remote'][
'typeGroups'];
1525 foreach($types as $type)
1527 if($type[
'SELECTORLEVEL'] = intval($type[
'SELECTORLEVEL']))
1529 $name = static::getTranslatedName($type[
'NAME'], $langId);
1530 $levels[$type[
'SELECTORLEVEL']][
'NAMES'][] = $name[
'NAME'];
1531 $levels[$type[
'SELECTORLEVEL']][
'TYPES'][] = $type[
'CODE'];
1533 $levels[$type[
'SELECTORLEVEL']][
'DEFAULT'] = ($type[
'DEFAULTSELECT'] ==
'1');
1537 foreach($levels as &$group)
1538 $group[
'NAMES'] = implode(
', ', $group[
'NAMES']);
1540 ksort($levels, SORT_NUMERIC);
1553 $res = \Bitrix\Main\SiteTable::getList(array(
'filter' => array(
'ACTIVE' =>
'Y'),
'select' => array(
'LANGUAGE_ID'),
'group' => array(
'LANGUAGE_ID')));
1554 while($item = $res->fetch())
1556 $langs[ToUpper($item[
'LANGUAGE_ID'])] =
true;
1559 $langs = array_unique(array_keys($langs));
1569 $langs = Location\Admin\NameHelper::getLanguageList();
1570 if(isset($langs[
'en']))
1573 return array_unique(array_merge($required, static::getSiteLanguages()));
1579 $this->data[
'types_processed'] ??=
false;
1580 if ($this->data[
'types_processed'])
1586 $existed = static::getExistedTypes();
1593 $existed = static::createTypes($rTypes, $existed);
1595 if(intval($dl = $this->data[
'settings'][
'options'][
'DEPTH_LIMIT']))
1601 if(!isset($typesGroupped[$dl]))
1605 foreach($typesGroupped as $gId => $group)
1610 foreach($group[
'TYPES'] as $type)
1614 $this->data[
'types'][
'allowed'] = $allowed;
1619 foreach($rTypes as $type)
1621 $allowed[] = $type[
'CODE'];
1623 $this->data[
'types'][
'allowed'] = $allowed;
1629 if(!empty($existed) && is_array($existed))
1631 $codes = array_keys($existed);
1634 $this->data[
'types'][
'allowed'] = $codes;
1637 if (empty($this->data[
'types'][
'allowed']))
1639 $this->data[
'types'][
'last'] =
null;
1643 $this->data[
'types'][
'last'] = $this->data[
'types'][
'allowed'][count($this->data[
'types'][
'allowed']) - 1];
1645 $this->data[
'types'][
'allowed'] = array_flip($this->data[
'types'][
'allowed']);
1647 $this->data[
'types'][
'code2id'] = $existed;
1648 $this->data[
'types_processed'] =
true;
1653 if($this->data[
'settings'][
'additional'] ===
false)
1656 if($code ==
'ZIP_LOWER')
1659 return isset($this->data[
'settings'][
'additional'][$code]);
1664 $this->data[
'external_processed'] ??=
false;
1665 if ($this->data[
'external_processed'])
1671 $existed = static::getExistedServices();
1676 foreach($external as $line)
1680 $existed[$line[
'CODE']] = static::createService($line);
1683 unset($this->data[
'settings'][
'remote'][
'external_services']);
1686 $this->data[
'externalService'][
'code2id'] = $existed;
1687 $this->data[
'external_processed'] =
true;
1692 $parameters = array(
1693 'select' => array(
'ID',
'CODE')
1697 $parameters[
'filter'] = array(
'TYPE.CODE' => array(
'COUNTRY',
'COUNTRY_DISTRICT',
'REGION'));
1699 $this->data[
'existedlocs'] = array(
'static' => array());
1700 $res = Location\LocationTable::getList($parameters);
1701 while($item = $res->fetch())
1702 $this->data[
'existedlocs'][
'static'][$item[
'CODE']] = $item[
'ID'];
1707 $res = Location\LocationTable::getList(array(
'filter' => array(
'CODE' => $buffer),
'select' => array(
'ID',
'CODE')));
1708 while($item = $res->fetch())
1709 $result[$item[
'CODE']] = $item[
'ID'];
1720 foreach($codes as $code)
1724 if($i == self::MAX_CODE_FETCH_BLOCK_LEN)
1746 $before = implode(
', ', array_keys($this->data[
'existedlocs']));
1749 foreach($this->data[
'existedlocs'] as $gid => $bundles)
1751 if($gid ==
'static' || in_array($gid, $memGroups))
1756 $this->
logMessage(
'Memory clean: REMOVING Group '.$gid);
1757 unset($this->data[
'existedlocs'][$gid]);
1762 $this->
logMessage(
'BEFORE memgroups: '.$before);
1763 $this->
logMessage(
'Clear all but '.$memGroups[0]);
1765 $this->
logMessage(
'AFTER memgroups: '.implode(
', ', array_keys($this->data[
'existedlocs'])));
1774 $indexName = $this->dbHelper->forSql(trim($indexName));
1775 $tableName = $this->dbHelper->forSql(trim($tableName));
1777 if(!mb_strlen($indexName) || !mb_strlen($tableName))
1780 if($this->dbConnType == self::DB_TYPE_MYSQL)
1781 $res = $this->dbConnection->query(
"show index from ".$tableName);
1782 elseif($this->dbConnType == self::DB_TYPE_ORACLE)
1783 $res = $this->dbConnection->query(
"SELECT INDEX_NAME as Key_name FROM USER_IND_COLUMNS WHERE TABLE_NAME = '".ToUpper($tableName).
"'");
1784 elseif($this->dbConnType == self::DB_TYPE_MSSQL)
1786 $res = $this->dbConnection->query(
"SELECT si.name Key_name
1788 INNER JOIN syscolumns c ON s.id = c.id AND s.colid = c.colid
1789 INNER JOIN sysobjects o ON s.id = o.Id AND o.xtype = 'U'
1790 LEFT JOIN sysindexes si ON si.indid = s.indid AND si.id = s.id
1791 WHERE o.name = '".ToUpper($tableName).
"'");
1794 while($item = $res->fetch())
1796 if (isset($item[
'Key_name']) && $item[
'Key_name'] === $indexName)
1800 if (isset($item[
'KEY_NAME']) && $item[
'KEY_NAME'] === $indexName)
1811 $indexName = $this->dbHelper->forSql(trim($indexName));
1812 $tableName = $this->dbHelper->forSql(trim($tableName));
1814 if(!mb_strlen($indexName) || !mb_strlen($tableName))
1820 if($this->dbConnType == self::DB_TYPE_MYSQL)
1821 $this->dbConnection->query(
"alter table {$tableName} drop index {$indexName}");
1822 elseif($this->dbConnType == self::DB_TYPE_ORACLE)
1823 $this->dbConnection->query(
"drop index {$indexName}");
1824 elseif($this->dbConnType == self::DB_TYPE_MSSQL)
1825 $this->dbConnection->query(
"drop index {$indexName} on {$tableName}");
1832 $locationTable = Location\LocationTable::getTableName();
1833 $locationNameTable = Location\Name\LocationTable::getTableName();
1834 $locationExternalTable = Location\ExternalTable::getTableName();
1837 'IX_SALE_LOCATION_MARGINS' => array(
'TABLE' => $locationTable,
'COLUMNS' => array(
'LEFT_MARGIN',
'RIGHT_MARGIN')),
1838 'IX_SALE_LOCATION_MARGINS_REV' => array(
'TABLE' => $locationTable,
'COLUMNS' => array(
'RIGHT_MARGIN',
'LEFT_MARGIN')),
1839 'IX_SALE_LOCATION_PARENT' => array(
'TABLE' => $locationTable,
'COLUMNS' => array(
'PARENT_ID')),
1840 'IX_SALE_LOCATION_DL' => array(
'TABLE' => $locationTable,
'COLUMNS' => array(
'DEPTH_LEVEL')),
1841 'IX_SALE_LOCATION_TYPE' => array(
'TABLE' => $locationTable,
'COLUMNS' => array(
'TYPE_ID')),
1842 'IX_SALE_L_NAME_NAME_UPPER' => array(
'TABLE' => $locationNameTable,
'COLUMNS' => array(
'NAME_UPPER')),
1843 'IX_SALE_L_NAME_LID_LID' => array(
'TABLE' => $locationNameTable,
'COLUMNS' => array(
'LOCATION_ID',
'LANGUAGE_ID')),
1844 'IX_B_SALE_LOC_EXT_LID_SID' => array(
'TABLE' => $locationExternalTable,
'COLUMNS' => array(
'LOCATION_ID',
'SERVICE_ID')),
1845 'IX_SALE_LOCATION_TYPE_MARGIN' => array(
'TABLE' => $locationTable,
'COLUMNS' => array(
'TYPE_ID',
'LEFT_MARGIN',
'RIGHT_MARGIN')),
1848 'IXS_LOCATION_COUNTRY_ID' => array(
'TABLE' => $locationTable,
'COLUMNS' => array(
'COUNTRY_ID')),
1849 'IXS_LOCATION_REGION_ID' => array(
'TABLE' => $locationTable,
'COLUMNS' => array(
'REGION_ID')),
1850 'IXS_LOCATION_CITY_ID' => array(
'TABLE' => $locationTable,
'COLUMNS' => array(
'CITY_ID')),
1853 'IX_B_SALE_LOCATION_1' => array(
'TABLE' => $locationTable,
'COLUMNS' => array(
'COUNTRY_ID'),
'DROP_ONLY' =>
true),
1854 'IX_B_SALE_LOCATION_2' => array(
'TABLE' => $locationTable,
'COLUMNS' => array(
'REGION_ID'),
'DROP_ONLY' =>
true),
1855 'IX_B_SALE_LOCATION_3' => array(
'TABLE' => $locationTable,
'COLUMNS' => array(
'CITY_ID'),
'DROP_ONLY' =>
true),
1861 $map = static::getIndexMap();
1863 foreach($map as $index => $ixData)
1865 if($certainIndex !==
false && $certainIndex != $index)
1876 foreach($map as $ixName => $ixData)
1878 if (($ixData[
'DROP_ONLY'] ??
null) ===
true)
1883 if($certainIndex !==
false && $certainIndex != $ixName)
1889 $this->dbConnection->query(
'CREATE INDEX '.$ixName.
' ON '.$ixData[
'TABLE'].
' ('.implode(
', ', $ixData[
'COLUMNS']).
')');
1895 private function getCachedBundle($id)
1897 $locationTable = Location\LocationTable::getTableName();
1900 $res = $this->dbConnection->query(
"select ID from {$locationTable} where PARENT_ID = ".($id ==
'root' ?
'0' : intval($id)));
1901 while($item = $res->fetch())
1902 $bundle[] = $item[
'ID'];
1907 private function checkNodeIsParent($id)
1909 $locationTable = Location\LocationTable::getTableName();
1911 $res = $this->dbConnection->query(
"select count(*) as CNT from {$locationTable} where PARENT_ID = ".($id ==
'root' ?
'0' : intval($id)))->fetch();
1913 return intval($res[
'CNT']);
1916 private function mergeRebalancedNodes()
1918 if($this->rebalanceInserter)
1920 $this->
logMessage(
'Finally, MERGE is in progress');
1922 $this->rebalanceInserter->flush();
1926 Location\LocationTable::mergeRelationsFromTemporalTable(self::TREE_REBALANCE_TEMP_TABLE_NAME,
false, array(
'LEFT_MARGIN' =>
'L',
'RIGHT_MARGIN' =>
'R',
'DEPTH_LEVEL' =>
'D',
'ID' =>
'I'));
1930 private function acceptRebalancedNode($node)
1932 $this->createTempTable();
1934 if(!$this->rebalanceInserter)
1936 if($this->dbConnType == self::DB_TYPE_ORACLE)
1941 $this->rebalanceInserter =
new BlockInserter(array(
1942 'tableName' => self::TREE_REBALANCE_TEMP_TABLE_NAME,
1943 'exactFields' => array(
1944 'I' => array(
'data_type' =>
'integer'),
1945 'L' => array(
'data_type' =>
'integer'),
1946 'R' => array(
'data_type' =>
'integer'),
1947 'D' => array(
'data_type' =>
'integer'),
1949 'parameters' => array(
1955 $this->data[
'processed']++;
1957 $this->rebalanceInserter->insert($node);
1960 private function dropTempTable()
1962 if($this->dbConnection->isTableExists(self::TREE_REBALANCE_TEMP_TABLE_NAME))
1963 $this->dbConnection->query(
"drop table ".self::TREE_REBALANCE_TEMP_TABLE_NAME);
1966 private function createTempTable()
1968 $this->data[
'rebalance'][
'tableCreated'] ??=
false;
1969 if ($this->data[
'rebalance'][
'tableCreated'])
1976 if ($this->dbConnection->isTableExists($tableName))
1978 $this->dbConnection->query(
"truncate table {$tableName}");
1983 if($this->dbConnType == self::DB_TYPE_ORACLE)
1985 $this->dbConnection->query(
"create table {$tableName} (
1994 $this->dbConnection->query(
"create table {$tableName} (
2004 $this->data[
'rebalance'][
'tableCreated'] =
true;
2009 return $this->data[
'current'][
'bytesRead'] >= $this->data[
'files'][$this->data[
'current'][
'fIndex']][
'size'];
2014 return $this->data[
'current'][
'fIndex'] >= count($this->data[
'files']);
2022 protected static function downloadFile($fileName, $storeAs, $skip404 =
false, $storeTo =
false)
2026 $storeTo = \CTempFile::GetDirectoryName(1);
2028 $storeTo .= $storeAs;
2030 if(file_exists($storeTo))
2032 if(!is_writable($storeTo))
2038 if(!defined(
'SALE_LOCATIONS_IMPORT_SOURCE_URL'))
2039 $query =
'http://'.self::DISTRIBUTOR_HOST.
':'.self::DISTRIBUTOR_PORT.self::REMOTE_PATH.$fileName;
2041 $query =
'http://'.SALE_LOCATIONS_IMPORT_SOURCE_URL.
'/'.$fileName;
2045 if(!$client->download($query, $storeTo))
2047 $eFormatted = array();
2048 foreach($client->getError() as $code => $desc)
2049 $eFormatted[] = trim($desc.
' ('.$code.
')');
2051 throw new Main\SystemException(
'File download failed: '.implode(
', ', $eFormatted).
' ('.$query.
')');
2054 $status = intval($client->getStatus());
2056 if($status != 200 && file_exists($storeTo))
2059 $okay = $status == 200 || ($status == 404 && $skip404);
2065 return filesize($storeTo);
2077 return self::LOCAL_SETS_PATH.sprintf(self::LOCAL_LOCATION_FILE, $i);
2082 if(is_array($_FILES[$inputName]))
2084 if($_FILES[$inputName][
'error'] > 0)
2087 if(!in_array($_FILES[$inputName][
'type'], array(
2090 'application/vnd.ms-excel',
2091 'application/octet-stream'
2100 $fileName = $localPath.
'/'.static::USER_FILE_TEMP_NAME;
2102 if(!@copy($_FILES[$inputName][
'tmp_name'], $fileName))
2104 $lastError = error_get_last();
2108 $_SESSION[static::USER_FILE_DIRECTORY_SESSION_KEY] = $localPath;
2118 case UPLOAD_ERR_INI_SIZE:
2119 $message =
'The uploaded file exceeds the upload_max_filesize directive in php.ini';
2121 case UPLOAD_ERR_FORM_SIZE:
2122 $message =
'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form';
2124 case UPLOAD_ERR_PARTIAL:
2125 $message =
'The uploaded file was only partially uploaded';
2127 case UPLOAD_ERR_NO_FILE:
2128 $message =
'No file were uploaded';
2130 case UPLOAD_ERR_NO_TMP_DIR:
2131 $message =
'Missing a temporary folder';
2133 case UPLOAD_ERR_CANT_WRITE:
2134 $message =
'Failed to write file to disk';
2136 case UPLOAD_ERR_EXTENSION:
2137 $message =
'File upload stopped by extension';
2141 $message =
'Unknown upload error';
2150 $dataLocalPath = trim((
string)($this->data[
'LOCAL_PATH'] ??
''));
2151 $wasCreated =
false;
2154 $localPath = $dataLocalPath;
2159 $localPath = \CTempFile::GetDirectoryName(10);
2162 \Bitrix\Main\IO\Directory::createDirectory($localPath);
2176 \Bitrix\Main\IO\Directory::createDirectory($path);
2184 \Bitrix\Main\IO\Directory::deleteDirectory($path);
2191 if(is_array($value))
2193 foreach($value as $v)
2202 $result = array_unique($result);
2203 sort($result, SORT_STRING);
2210 $value = ToLower(trim($value));
2212 if(!preg_match(
'#^[a-z0-9]+$#i', $value))
2220 $this->useCache =
false;
2223 ########################################################
2224 ## static part is used in places like wizards, etc
2229 $res = Location\TypeTable::getList(array(
'select' => array(
'ID',
'CODE',
'SORT')));
2230 while($item = $res->fetch())
2231 $existed[$item[
'CODE']] = $item[
'ID'];
2239 $res = Location\ExternalServiceTable::getList(array(
'select' => array(
'ID',
'CODE')));
2240 while($item = $res->fetch())
2241 $existed[$item[
'CODE']] = $item[
'ID'];
2249 if($existed ===
false)
2250 $existed = static::getExistedTypes();
2253 $langs = Location\Admin\NameHelper::getLanguageList();
2255 foreach($types as $line)
2258 unset($line[
'SELECTORLEVEL']);
2259 unset($line[
'DEFAULTSELECT']);
2263 if(!is_array($line[
'NAME']))
2264 $line[
'NAME'] = array();
2266 if(is_array($langs))
2268 foreach($langs as $lid => $f)
2270 $names[ToUpper($lid)] = static::getTranslatedName($line[
'NAME'], $lid);
2272 $line[
'NAME'] = $names;
2275 if(!isset($existed[$line[
'CODE']]))
2277 $existed[$line[
'CODE']] = static::createType($line);
2283 Location\Name\TypeTable::addAbsentForOwner($existed[$line[
'CODE']], $names);
2292 $languageIdMapped = ToUpper(
Location\Admin\NameHelper::mapLanguage($languageId));
2293 $languageId = ToUpper($languageId);
2295 if(is_array($names[$languageId]) && (
string) $names[$languageId][
'NAME'] !=
'')
2296 return $names[$languageId];
2298 if(is_array($names[$languageIdMapped]) && (
string) $names[$languageIdMapped][
'NAME'] !=
'')
2299 return $names[$languageIdMapped];
2301 return $names[
'EN'];
2306 $map = Location\TypeTable::getMap($type);
2310 foreach($type as $fld => $val)
2312 if(!isset($map[$fld]))
2319 $res = Location\TypeTable::add($type);
2320 if(!$res->isSuccess())
2321 throw new Main\SystemException(
'Type creation failed: '.implode(
', ', $res->getErrorMessages()));
2323 return $res->getId();
2328 $res = Location\ExternalServiceTable::add($service);
2329 if(!$res->isSuccess())
2330 throw new Main\SystemException(
'External service creation failed: '.implode(
', ', $res->getErrorMessages()));
2332 return $res->getId();
2338 $csvReader->LoadFile($file);
2342 while($type = $csvReader->FetchAssoc())
2346 unset($type[
'SELECTORLEVEL']);
2347 unset($type[
'DEFAULTSELECT']);
2349 $types[$type[
'CODE']] = $type;
2361 $csvReader->LoadFile($file);
2363 $services = array();
2364 while($service = $csvReader->FetchAssoc())
2365 $services[$service[
'CODE']] = $service;
2374 if (
$timeLimit < $descriptior[
'TIME_LIMIT']) set_time_limit($descriptior[
'TIME_LIMIT'] + 5);
2376 $endTime = time() + $descriptior[
'TIME_LIMIT'];
2378 if($descriptior[
'STEP'] ==
'rebalance')
2380 Location\LocationTable::resort();
2381 Location\LocationTable::resetLegacyPath();
2382 $descriptior[
'STEP'] =
'done';
2385 if($descriptior[
'STEP'] ==
'import')
2387 if(!isset($descriptior[
'DO_SYNC']))
2389 $res = \Bitrix\Sale\Location\LocationTable::getList(array(
'select' => array(
'CNT')))->fetch();
2390 $descriptior[
'DO_SYNC'] = intval($res[
'CNT'] > 0);
2393 if(!isset($descriptior[
'TYPES']))
2395 $descriptior[
'TYPE_MAP'] = static::getTypeMap($descriptior[
'TYPE_FILE']);
2396 $descriptior[
'TYPES'] = static::createTypes($descriptior[
'TYPE_MAP']);
2398 $descriptior[
'SERVICE_MAP'] = static::getServiceMap($descriptior[
'SERVICE_FILE']);
2399 $descriptior[
'SERVICES'] = static::getExistedServices();
2403 $csvReader->LoadFile($descriptior[
'FILE']);
2405 while(time() < $endTime)
2407 $block = $csvReader->ReadBlockLowLevel($descriptior[
'POS'], 10);
2412 foreach($block as $item)
2414 if($descriptior[
'DO_SYNC'])
2416 $id = static::checkLocationCodeExists($item[
'CODE']);
2419 $descriptior[
'CODES'][$item[
'CODE']] = $id;
2425 $item[
'TYPE_ID'] = $descriptior[
'TYPES'][$item[
'TYPE_CODE']];
2426 unset($item[
'TYPE_CODE']);
2429 if($item[
'PARENT_CODE'] <>
'')
2431 if(!isset($descriptior[
'CODES'][$item[
'PARENT_CODE']]))
2433 $descriptior[
'CODES'][$item[
'PARENT_CODE']] = static::checkLocationCodeExists($item[
'PARENT_CODE']);
2436 $item[
'PARENT_ID'] = $descriptior[
'CODES'][$item[
'PARENT_CODE']];
2438 unset($item[
'PARENT_CODE']);
2441 if(is_array($item[
'EXT']))
2443 foreach($item[
'EXT'] as $code => $values)
2447 if(!isset($descriptior[
'SERVICES'][$code]))
2449 $descriptior[
'SERVICES'][$code] = static::createService(array(
2454 if($code ==
'ZIP_LOWER')
2456 if($values[0] ==
'')
2459 $values = explode(
',', $values[0]);
2461 if(!is_array($values))
2464 $values = array_unique($values);
2467 if(is_array($values))
2469 foreach($values as $value)
2474 $item[
'EXTERNAL'][] = array(
2475 'SERVICE_ID' => $descriptior[
'SERVICES'][$code],
2483 unset($item[
'EXT'], $item[
'ZIP_LOWER']);
2485 $res = Location\LocationTable::addExtended(
2488 'RESET_LEGACY' =>
false,
2489 'REBALANCE' =>
false
2493 if(!$res->isSuccess())
2496 $descriptior[
'CODES'][$item[
'CODE']] = $res->getId();
2502 unset($descriptior[
'CODES']);
2503 $descriptior[
'STEP'] =
'rebalance';
2507 return $descriptior[
'STEP'] ==
'done';
2513 if (!is_array(
$data))
2517 if (!isset(
$data[
'NAME'][
'RU']))
2521 if (!is_array(
$data[
'NAME'][
'RU']))
2525 $data[
'NAME'][
'EN'] ??= [];
2527 foreach (
$data[
'NAME'][
'RU'] as $k => $v)
2529 if ((
string)(
$data[
'NAME'][
'EN'][$k] ??
'') ===
'')
2531 $data[
'NAME'][
'EN'][$k] = Location\Admin\NameHelper::translitFromUTF8(
$data[
'NAME'][
'RU'][$k]);
static isDirectoryExists($path)
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)
getStagePercent($sNum=false)
Percentage.
logMessage($message='', $addTimeStamp=true)