56 private $queue =
false;
58 private $typeMap = array(
59 'SUBJECT_FEDERATION' =>
'REGION'
62 private $headers = array(
63 'SHORT' => array(
'CODE',
'PARENT_CODE',
'NAME.RU.NAME',
'NAME.EN.NAME',
'NAME.UA.NAME'),
64 'LONG' => array(
'CODE',
'PARENT_CODE',
'TYPE_CODE',
'NAME.RU.NAME',
'NAME.EN.NAME',
'NAME.UA.NAME',
'LONGITUDE',
'LATITUDE',
'EXT.YAMARKET.0',
'EXT.ZIP.0'),
65 'GROUP_FILE' => array(
'CODE',
'TYPES')
68 private $typeGroups = array(
71 'TYPES' => array(
'COUNTRY',
'COUNTRY_DISTRICT',
'REGION'),
73 'FILE_NAME_TEMPLATE' =>
'layout.csv'
84 'TYPES' => array(
'CITY',
'SUBREGION',
'VILLAGE'),
87 'FILE_NAME_TEMPLATE' =>
'%BASE_PARENT_ITEM_CODE%_%CODE%.csv'
91 'TYPES' => array(
'STREET'),
94 'FILE_NAME_TEMPLATE' =>
'%BASE_PARENT_ITEM_CODE%_%CODE%.csv'
98 private $fiasToBaseType = array(
100 'COUNTRY_DISTRICT' => array(
101 'округ' => array(
'R' =>
'округ',
'U' =>
true),
104 'АО' => array(
'R' =>
'автономный округ',
'U' =>
true),
105 'Аобл' => array(
'R' =>
'автономная область',
'U' =>
true),
106 'край' => array(
'R' =>
'край',
'U' =>
true),
107 'обл' => array(
'R' =>
'область',
'U' =>
true),
108 'Респ' => array(
'R' =>
'республика',
'U' =>
true),
109 'Чувашия' => array(
'R' =>
'республика',
'U' =>
true)
112 'SUBREGION' => array(
113 'р-н' => array(
'R' =>
'район',
'U' =>
true),
115 'улус' => array(
'R' =>
'улус',
'U' =>
true),
116 'у' => array(
'R' =>
'улус',
'U' =>
true),
120 'г' => array(
'R' =>
'город',
'U' =>
true),
123 'пгт' => array(
'R' =>
'посёлок городского типа',
'U' =>
true),
124 'п' => array(
'R' =>
'посёлок',
'U' =>
true),
125 'дп' => array(
'R' =>
'дачный посёлок',
'U' =>
true),
126 'с/п' => array(
'R' =>
'сельское поселение',
'U' =>
true),
127 'аал' => array(
'R' =>
'аал',
'U' =>
true),
128 'аул' => array(
'R' =>
'аул',
'U' =>
true),
129 'арбан' => array(
'R' =>
'арбан',
'U' =>
true),
130 'д' => array(
'R' =>
'деревня',
'U' =>
true),
131 'нп' => array(
'R' =>
'населённый пункт',
'U' =>
true),
132 'сл' => array(
'R' =>
'слобода',
'U' =>
true),
133 'х' => array(
'R' =>
'хутор',
'U' =>
true),
134 'ферма' => array(
'R' =>
'ферма',
'U' =>
true),
135 'с' => array(
'R' =>
'село',
'U' =>
true),
136 'рп' => array(
'R' =>
'рабочий посёлок',
'U' =>
true),
137 'ст' => array(
'R' =>
'станция',
'U' =>
true),
138 'п/ст' => array(
'R' =>
'посёлок',
'U' =>
true),
139 'ст-ца' => array(
'R' =>
'станица',
'U' =>
true),
140 'кп' => array(
'R' =>
'курортный поселок',
'U' =>
true),
141 'ж/д_ст' => array(
'R' =>
'железнодорожная станция'),
142 'тер' => array(
'R' =>
'территория'),
143 'остров' => array(
'R' =>
'остров'),
145 'мкр' => array(
'R' =>
'микрорайон',
'U' =>
true),
146 'с/с' => array(
'R' =>
'сельсовет',
'U' =>
true),
147 'п/о' => array(
'R' =>
'почтовое отделение',
'U' =>
true),
148 'м' => array(
'R' =>
'местечко',
'U' =>
true),
149 'с/мо' => array(
'R' =>
'смо',
'U' =>
true),
150 'жилрайон' => array(
'R' =>
'жилрайон',
'U' =>
true),
151 'массив' => array(
'R' =>
'массив'),
152 'ж/д_оп' => array(
'R' =>
'ж/д остановка'),
153 'с/а' => array(
'R' =>
'сельская администрация',
'U' =>
true),
154 'п/р' => array(
'R' =>
'планировочный район'),
155 'ж/д_рзд' => array(
'R' =>
'ж/д разъезд'),
156 'снт' => array(
'R' =>
'снт',
'U' =>
true),
157 'с/о' => array(
'R' =>
'сельский округ'),
158 'заимка' => array(
'R' =>
'заимка'),
159 'городок' => array(
'R' =>
'городок',
'U' =>
true)
166 'ул' => array(
'R' =>
'улица',
'U' =>
true),
167 'кв-л' => array(
'R' =>
'квартал',
'U' =>
true),
168 'аллея' => array(
'R' =>
'аллея',
'U' =>
true),
169 'вал' => array(
'R' =>
'вал',
'U' =>
true),
170 'въезд' => array(
'R' =>
'въезд',
'U' =>
true),
171 'наб' => array(
'R' =>
'набережная',
'U' =>
true),
172 'пер' => array(
'R' =>
'переулок',
'U' =>
true),
173 'пл' => array(
'R' =>
'площадь',
'U' =>
true),
174 'пр-кт' => array(
'R' =>
'проспект',
'U' =>
true),
175 'проезд' => array(
'R' =>
'проезд',
'U' =>
true),
176 'проулок' => array(
'R' =>
'проулок',
'U' =>
true),
177 'рзд' => array(
'R' =>
'разъезд',
'U' =>
true),
178 'сад' => array(
'R' =>
'сад',
'U' =>
true),
179 'сквер' => array(
'R' =>
'сквер',
'U' =>
true),
180 'спуск' => array(
'R' =>
'спуск',
'U' =>
true),
181 'тоннель' => array(
'R' =>
'тоннель',
'U' =>
true),
182 'тракт' => array(
'R' =>
'тракт',
'U' =>
true),
183 'туп' => array(
'R' =>
'тупик',
'U' =>
true),
184 'эстакада' => array(
'R' =>
'эстакада',
'U' =>
true),
185 'б-р' => array(
'R' =>
'бульвар',
'U' =>
true),
186 'бугор' => array(
'R' =>
'бугор',
'U' =>
true),
187 'заезд' => array(
'R' =>
'заезд',
'U' =>
true),
188 'канал' => array(
'R' =>
'канал',
'U' =>
true),
189 'км' => array(
'R' =>
'километр',
'U' =>
true),
190 'кольцо' => array(
'R' =>
'кольцо',
'U' =>
true),
191 'парк' => array(
'R' =>
'парк',
'U' =>
true),
192 'переезд' => array(
'R' =>
'переезд',
'U' =>
true),
193 'стр' => array(
'R' =>
'строение',
'U' =>
true),
194 'просек' => array(
'R' =>
'просек',
'U' =>
true),
195 'ш' => array(
'R' =>
'шоссе',
'U' =>
true),
196 'автодорога' => array(
'R' =>
'дорога',
'U' =>
true)
200 private $forbiddenPathTypes = array(
224 private $forbiddenPathIds = array(
225 'af7cdb7f-e47d-4f65-93d5-3a2b70a809ce' =>
true,
226 '762758bb-18b9-440f-bc61-8e1e77ff3fd8' =>
true,
229 private $allowedFiasStats = array(
230 'ACTSTATUS' => array(
233 'LIVESTATUS' => array(
236 'CURRSTATUS' => array(
242 private $filePools = array(
244 'ukrain_kazakhstan' => array(
245 'DIR' =>
'ukrain_kazakhstan/'
249 'fias_tree' => array(
250 'DIR' =>
'fias_tree/'
254 'fias_yamarket_links' => array(
255 'DIR' =>
'fias_yamarket_links/'
260 'DIR' =>
'compiled/bundles/extended/'
263 'assets_standard' => array(
264 'DIR' =>
'compiled/bundles/standard/'
273 private $workDir =
'';
274 private $grabbedStuffDir =
'';
276 private $yaIdType = array();
277 private $relations = array();
279 private $options = array();
282 private $data = array();
284 private $optionConvertNames =
false;
285 private $sysMaps = array();
287 private $fiasCPath = array();
289 private $fiasDB =
null;
290 private $eTreeDB =
null;
291 private $eTreeDBRussia =
null;
295 $this->workDir = $options[
'workDir'];
296 $this->grabbedStuffDir = $options[
'grabbedStuffDir'];
298 $this->options = $options;
303 foreach($this->typeGroups as $id => &$params)
304 $params[
'I_TYPES'] = array_flip($params[
'TYPES']);
306 foreach($this->fiasToBaseType as $type => $fTypes)
308 foreach($fTypes as $fType => $fReplace)
310 if(strlen($fType) && !empty($fReplace))
312 $this->sysMaps[
'FIAS2BASETYPE'][$fType] = $type;
313 $this->sysMaps[
'FIASTYPEREPLACE'][$fType] = $fReplace[
'R'];
318 foreach($this->typeGroups as $groupId => $group)
322 foreach($group[
'TYPES'] as $type)
324 $this->sysMaps[
'BASETYPE2GROUP'][$type] = $groupId;
336 ##########################################################
337 #### MAP FIAS TO YANDEX
338 ##########################################################
356 ##########################################################
358 ##########################################################
368 ##########################################################
369 #### MAKE EXPORT TABLE
370 ##########################################################
379 $this->
output(
'Build main tree');
382 $this->createExportTables();
433 $this->restoreExportTablesIndexes();
435 $this->
output(
'Build export files');
444 $this->cleanPoolDir(
'assets_standard');
445 $this->eTreeDB->walkInDeep(array(
446 'ITEM' => array($this,
'generateExportFilesFromTableBundle_Standard')
448 $this->eTreeDBRussia->walkInDeep(array(
449 'ITEM' => array($this,
'generateExportFilesFromTableBundle_Standard_YandexOnly')
459 ###################################################################
460 ###################################################################
461 ###################################################################
490 #######################################################
491 ### ABOUT EXPORT TABLE
492 #######################################################
494 private $allowedForDemo = array(
'COUNTRY' => 1,
'COUNTRY_DISTRICT' => 1,
'REGION' => 1,
'SUBREGION' => 1,
'CITY' => 1);
495 private $demoCategory =
false;
499 if(!isset($this->allowedForDemo[$item[
'TYPE_CODE']]))
502 if($item[
'TYPE_CODE'] ==
'COUNTRY')
504 $this->addItemToCSV(
'world',
'demo', $item);
508 if($item[
'NAME'] ==
'Україна')
509 $this->demoCategory =
'ukrain';
510 elseif($item[
'NAME'] ==
'Казахстан')
511 $this->demoCategory =
'kazakhstan';
512 elseif($item[
'NAME'] ==
'Беларусь')
513 $this->demoCategory =
'belarus';
514 elseif($item[
'NAME'] ==
'США')
515 $this->demoCategory =
'usa';
517 $this->demoCategory =
false;
523 if($this->demoCategory !==
false)
524 $this->addItemToCSV($this->demoCategory,
'demo', $item);
529 if(!isset($this->allowedForDemo[$item[
'TYPE_CODE']]))
532 if($item[
'TYPE_CODE'] ==
'COUNTRY')
533 $this->addItemToCSV(
'world',
'demo', $item);
535 $this->addItemToCSV(
'russia',
'demo', $item);
538 private function createExportTables()
541 $this->eTreeDB->create();
544 $this->eTreeDBRussia->create();
547 private function cleanUpExportTables()
549 $this->eTreeDB->cleanup();
550 $this->eTreeDB->dropIndexes();
552 $this->eTreeDBRussia->cleanup();
553 $this->eTreeDBRussia->dropIndexes();
556 private function restoreExportTablesIndexes()
558 $this->eTreeDB->restoreIndexes();
559 $this->eTreeDBRussia->restoreIndexes();
562 private function copyStaticCSV()
564 $workDir = $_SERVER[
'DOCUMENT_ROOT'].
'/'.$this->workDir;
566 system(
'cp '.$workDir.self::STATIC_CSV_DIR.
'externalservice.csv '.$workDir.
'/'.self::OUTPUT_DIR);
567 system(
'cp '.$workDir.self::STATIC_CSV_DIR.
'type.csv '.$workDir.
'/'.self::OUTPUT_DIR);
570 private $currentParentGroup =
'';
572 private function addItemToCSV($fName, $group, $item)
575 'CODE' => $item[
'CODE'],
576 'PARENT_CODE' => $item[
'PARENT_CODE'],
577 'TYPE_CODE' => $item[
'TYPE_CODE']
580 $data[
'NAME.RU.NAME'] =
'';
581 $data[
'NAME.EN.NAME'] =
'';
582 $data[
'NAME.UA.NAME'] =
'';
584 $name = unserialize($item[
'LANGNAMES']);
585 foreach($name as $lid => $values)
587 foreach($values as $i => $val)
588 $data[
'NAME.'.$lid.
'.'.$i] = $val;
591 $data[
'EXT.YAMARKET.0'] =
'';
592 $data[
'EXT.ZIP.0'] =
'';
594 $externals = unserialize($item[
'EXTERNALS']);
595 if(!empty($externals))
597 foreach($externals as $type => $values)
599 if(is_array($values))
601 foreach($values as $i => $val)
602 $data[
'EXT.'.$type.
'.'.$i] = $val;
607 $data[
'LONGITUDE'] = $item[
'LONGITUDE'];
608 $data[
'LATITUDE'] = $item[
'LATITUDE'];
626 if(in_array($item[
'TYPE_CODE'], $this->typeGroups[
'LAYOUT'][
'TYPES']))
627 $this->currentParentGroup = $item[
'CODE'];
629 ########################################################
630 ########################################################
631 ########################################################
633 $cat = $this->sysMaps[
'BASETYPE2GROUP'][$item[
'TYPE_CODE']];
634 $fName = $this->typeGroups[$cat][
'FILE_NAME_TEMPLATE'];
636 $fName = str_replace(array(
637 '%BASE_PARENT_ITEM_CODE%',
641 $cat ==
'LAYOUT' ?
'' : $this->currentParentGroup,
646 $this->addItemToCSV($fName,
'assets', $item);
648 ########################################################
649 ########################################################
650 ########################################################
655 if(in_array($item[
'TYPE_CODE'], $this->typeGroups[
'LAYOUT'][
'TYPES']))
656 $this->currentParentGroup = $item[
'CODE'];
658 ########################################################
659 ########################################################
660 ########################################################
662 $cat = $this->sysMaps[
'BASETYPE2GROUP'][$item[
'TYPE_CODE']];
663 $fName = $this->typeGroups[$cat][
'FILE_NAME_TEMPLATE'];
665 $fName = str_replace(array(
666 '%BASE_PARENT_ITEM_CODE%',
670 $cat ==
'LAYOUT' ?
'' : $this->currentParentGroup,
675 $this->addItemToCSV($fName,
'assets_standard', $item);
677 ########################################################
678 ########################################################
679 ########################################################
684 if(in_array($item[
'TYPE_CODE'], $this->typeGroups[
'LAYOUT'][
'TYPES']))
685 $this->currentParentGroup = $item[
'CODE'];
687 ########################################################
688 ########################################################
689 ########################################################
691 if($item[
'TYPE_CODE'] ==
'VILLAGE' && strpos($item[
'EXTERNALS'],
'YAMARKET') ===
false)
697 $cat = $this->sysMaps[
'BASETYPE2GROUP'][$item[
'TYPE_CODE']];
698 $fName = $this->typeGroups[$cat][
'FILE_NAME_TEMPLATE'];
700 $fName = str_replace(array(
701 '%BASE_PARENT_ITEM_CODE%',
705 $cat ==
'LAYOUT' ?
'' : $this->currentParentGroup,
710 $this->addItemToCSV($fName,
'assets_standard', $item);
712 ########################################################
713 ########################################################
714 ########################################################
719 private function generateExportTreeRussia()
723 $this->eTreeDBRussia->dropCodeIndex();
724 $this->eTreeDBRussia->setExportOffset(intval($this->eTreeDB->getNextFreeCode()));
727 $regions = $this->readFiasRootMapV2();
730 $this->generateExportTreePutRussiaBundle(array(self::RUSSIA_YANDEX_CODE), $regions, 0);
733 $this->generateExportTreePutRussiaInner();
735 $this->eTreeDBRussia->doneInsert();
736 $this->eTreeDBRussia->switchIndexes(
true);
739 private function getYandexToFiasCityMap($yandexRegionId)
742 $fias2yandex = $this->getDataFromCSV(
'fias_yamarket_links',
'region_'.$yandexRegionId);
743 foreach($fias2yandex as $map)
746 $result[$map[
'AOGUID']] = $map;
752 private function generateExportTreePutRussiaInner()
755 $links = $this->getFias2YamarketRootLinks(
false,
true);
761 foreach($links as $yRId => $fiasRegions)
766 $this->fias2yandexCityMap = $this->getYandexToFiasCityMap($yRId);
767 $this->currentRegion = $this->mapETCodeAsYandex($yRId);
769 $this->eTreeDBRussia->dropCodeIndex();
771 foreach($fiasRegions as $regionGuid)
773 $this->fiasPath = array();
774 $this->generateExportTreePutRussiaInnerBundle($regionGuid);
781 private function checkIsAllowedCityVillage($item)
783 $baseType = $this->sysMaps[
'FIAS2BASETYPE'][$item[
'SHORTNAME']];
788 $skip = array(
'5544bf6a-0ec1-4b5f-bbc5-49294f71de16',
'22a77f13-3764-41dc-aa23-db680b03ef5d',
'3f2ab130-274e-4fd6-b611-a94467b04f57',
'762758bb-18b9-440f-bc61-8e1e77ff3fd8', );
790 return ($baseType ==
'CITY' || $baseType ==
'VILLAGE') &&
792 $this->fiasToBaseType[$baseType][$item[
'SHORTNAME']][
'U']
794 isset($this->fias2yandexCityMap[$item[
'AOGUID']]
796 !in_array($item[
'AOGUID'], $skip)
800 private function checkIsAllowedStreet($item)
802 $baseType = $this->sysMaps[
'FIAS2BASETYPE'][$item[
'SHORTNAME']];
804 return ($baseType ==
'STREET' && $this->fiasToBaseType[$baseType][$item[
'SHORTNAME']][
'U']);
823 $lastValidId =
false;
824 $neepPasteLastValid =
false;
825 foreach($path as $item)
827 if(isset($this->forbiddenPathTypes[$item[
'SHORTNAME']]) || isset($this->forbiddenPathIds[$item[
'AOGUID']]) || $this->checkIsAllowedStreet($item[
'SHORTNAME']))
829 $neepPasteLastValid =
true;
834 if($lastValidId !==
false && $neepPasteLastValid)
836 $item[
'PARENTGUID'] = $lastValidId;
837 $neepPasteLastValid =
false;
840 $lastValidId = $item[
'AOGUID'];
858 private function generateExportTreePutRussiaFiasPath($targetItem)
861 $newPath = $this->generateExportTreePutRussiaFiasPathCutForbidden($this->fiasPath);
864 foreach($newPath as $item)
869 $externals = array();
870 if(strlen($item[
'POSTALCODE']))
871 $externals[
'ZIP'][] = $item[
'POSTALCODE'];
872 if(isset($this->fias2yandexCityMap[$item[
'AOGUID']]))
873 $externals[
'YAMARKET'][] = $this->fias2yandexCityMap[$item[
'AOGUID']][
'ID'];
876 $itemType = $item[
'SHORTNAME'];
877 $baseType = $this->sysMaps[
'FIAS2BASETYPE'][$itemType];
878 $typeNameReplace = $baseType !=
'CITY' ? $this->sysMaps[
'FIASTYPEREPLACE'][$itemType] :
'';
879 $name = trim($item[
'FORMALNAME']).(strlen($typeNameReplace) ?
' '.$typeNameReplace :
'');
881 $this->eTreeDBRussia->insert(array(
882 'TYPE_CODE' => $baseType,
883 'FIAS_TYPE' => $itemType,
885 'LANGNAMES' => array(
'RU' => array(
'NAME' => $name)),
886 'EXTERNALS' => $externals,
887 'SOURCE' => self::SOURCE_FIAS,
889 'SYS_CODE' => $this->mapETCodeAsFias($item[
'AOGUID']),
890 'PARENT_SYS_CODE' => $i ? $this->mapETCodeAsFias($item[
'PARENTGUID']) : $this->currentRegion
895 private function generateExportTreePutRussiaStreets($parentGuid)
897 if(!strlen($parentGuid))
900 $res = $this->fiasDB->getActualChildren($parentGuid);
901 while($item = $res->fetch())
903 $itemType = $item[
'SHORTNAME'];
904 if($this->checkIsAllowedStreet($item))
906 $externals = array();
907 if(strlen($item[
'POSTALCODE']))
908 $externals[
'ZIP'][] = $item[
'POSTALCODE'];
910 $baseType = $this->sysMaps[
'FIAS2BASETYPE'][$itemType];
911 $name = trim($item[
'FORMALNAME']).
' '.$this->sysMaps[
'FIASTYPEREPLACE'][$itemType];
913 $this->eTreeDBRussia->insert(array(
914 'TYPE_CODE' => $baseType,
915 'FIAS_TYPE' => $itemType,
917 'LANGNAMES' => array(
'RU' => array(
'NAME' => $name)),
918 'EXTERNALS' => $externals,
919 'SOURCE' => self::SOURCE_FIAS,
921 'SYS_CODE' => $this->mapETCodeAsFias($item[
'AOGUID']),
922 'PARENT_SYS_CODE' => $this->mapETCodeAsFias($parentGuid),
928 private function generateExportTreePutRussiaInnerBundle($parentGuid)
930 if(!strlen($parentGuid))
933 $res = $this->fiasDB->getActualChildren($parentGuid);
934 while($item = $res->fetch())
936 $item[
'PARENTGUID'] = $parentGuid;
937 array_push($this->fiasPath, $item);
939 if($this->checkIsAllowedCityVillage($item))
943 $this->generateExportTreePutRussiaFiasPath($item);
944 $this->generateExportTreePutRussiaStreets($item[
'AOGUID']);
947 $this->generateExportTreePutRussiaInnerBundle($item[
'AOGUID']);
949 array_pop($this->fiasPath);
954 private function generateExportTreePutRussiaBundle($bundle, $regions, $dl = 0)
956 foreach($bundle as $id)
958 $node = $this->data[
'TREES'][
'MAIN'][
'NODES'][$id];
961 if(isset($this->data[
'TREES'][
'MAIN'][
'EDGES'][$id]))
962 $edges = $this->data[
'TREES'][
'MAIN'][
'EDGES'][$id];
964 if(in_array($node[
'TYPE_CODE'], array(
'COUNTRY',
'COUNTRY_DISTRICT',
'REGION')))
966 if($node[
'TYPE_CODE'] ==
'REGION')
969 $fNode = $this->fiasDB->getByAOGUID($regions[$node[
'ID']][
'AOGUID']);
970 if(strlen($fNode[
'POSTALCODE']))
971 $node[
'EXT'][
'ZIP'][] = $fNode[
'POSTALCODE'];
977 if($node[
'TYPE_CODE'] ==
'COUNTRY')
978 $node[
'NAME'][
'EN'][
'NAME'] =
'Russian Federation';
980 if($node[
'NAME'][
'RU'][
'NAME'] ==
'Москва и Московская область')
981 $node[
'NAME'][
'RU'][
'NAME'] =
'Московская область';
983 if($node[
'NAME'][
'RU'][
'NAME'] ==
'Санкт-Петербург и Ленинградская область')
984 $node[
'NAME'][
'RU'][
'NAME'] =
'Ленинградская область';
986 $this->eTreeDBRussia->insert(array(
987 'TYPE_CODE' => $node[
'TYPE_CODE'],
988 'NAME' => $node[
'NAME'][
'RU'][
'NAME'],
989 'LANGNAMES' => $node[
'NAME'],
990 'EXTERNALS' => $node[
'EXT'],
991 'SOURCE' => self::SOURCE_YANDEX,
993 'SYS_CODE' => $this->mapETCodeAsYandex($node[
'ID']),
994 'PARENT_SYS_CODE' => strlen($node[
'PARENT_ID']) && $dl > 0 ? $this->mapETCodeAsYandex($node[
'PARENT_ID']) :
''
998 $this->generateExportTreePutRussiaBundle($edges, $regions, $dl+1);
1003 #########################
1005 private function generateExportTreeWorld()
1007 $this->eTreeDB->dropCodeIndex();
1008 $this->eTreeDB->restoreExportOffset();
1010 $this->eTreeDB->switchIndexes(
false);
1012 $csv =
new Import\CSVReader();
1013 $csv->loadFile($_SERVER[
'DOCUMENT_ROOT'].
'/locations_data/'.self::WORLD_SOURCE);
1015 $countries = array();
1017 while($item = $csv->Fetch())
1019 $item = explode(
',', $item[0]);
1021 if(!isset($item[1]))
1025 if(in_array($item[2], array(
'USA',
'Kazakhstan',
'Ukraine',
'Byelorussia',
'Russian Federation',
'Azerbaijan',
'Estonia',
'Georgia',
'Latvia',
'Lithuania',
'Moldavia',
'Turkmenistan',
'Armenia',
'Tadjikistan',
'Uzbekistan')))
1028 $id = implode(
':', $item);
1030 $countries[] = $item[2].
' - '.$item[4];
1032 $this->eTreeDB->insert(array(
1033 'TYPE_CODE' =>
'COUNTRY',
1035 'LANGNAMES' => serialize(array(
1036 'RU' => array(
'NAME' => $item[4]),
1037 'EN' => array(
'NAME' => $item[2])
1040 'SOURCE' => self::SOURCE_LEGACY,
1042 'SYS_CODE' => $this->mapETCodeAsLegacy($id),
1043 'PARENT_SYS_CODE' =>
''
1047 $this->eTreeDB->doneInsert();
1048 $this->eTreeDB->switchIndexes(
true);
1051 #########################
1053 private function generateExportTreeLegacy($source)
1055 $this->eTreeDB->dropCodeIndex();
1056 $this->eTreeDB->restoreExportOffset();
1058 $this->eTreeDB->switchIndexes(
false);
1060 $csv =
new Import\CSVReader();
1061 $csv->loadFile($_SERVER[
'DOCUMENT_ROOT'].
'/locations_data/'.$source);
1063 $lastOnes = array();
1065 while($item = $csv->Fetch())
1067 $item = explode(
',', $item[0]);
1069 if(!isset($item[1]))
1074 $item[2] = preg_replace(
'# obl$#',
' region', $item[2]);
1075 $item[4] = preg_replace(
'# обл$#',
' область', $item[4]);
1087 $id = implode(
':', $item);
1089 if($type ==
'REGION')
1090 $parentId = $lastOnes[
'COUNTRY'];
1091 elseif($type ==
'CITY')
1092 $parentId = $lastOnes['PARENT'];
1098 $lastOnes[$type] = $id;
1099 $lastOnes[
'PARENT'] = $id;
1102 $this->eTreeDB->insert(array(
1103 'TYPE_CODE' => $type,
1105 'LANGNAMES' => serialize(array(
1106 'RU' => array(
'NAME' => $item[4]),
1107 'EN' => array(
'NAME' => $item[2])
1110 'SOURCE' => self::SOURCE_LEGACY,
1112 'SYS_CODE' => $this->mapETCodeAsLegacy($id),
1113 'PARENT_SYS_CODE' => strlen($parentId) ? $this->mapETCodeAsLegacy($parentId) :
''
1117 $this->eTreeDB->doneInsert();
1118 $this->eTreeDB->switchIndexes(
true);
1121 #########################
1123 private function generateExportTreeUSA()
1125 $this->eTreeDB->dropCodeIndex();
1126 $this->eTreeDB->restoreExportOffset();
1128 $this->eTreeDB->switchIndexes(
false);
1130 $csv =
new Import\CSVReader();
1131 $csv->loadFile($_SERVER[
'DOCUMENT_ROOT'].
'/locations_data/'.self::USA_SOURCE);
1133 $lastOnes = array();
1135 while($item = $csv->Fetch())
1137 $item = explode(
',', $item[0]);
1139 if(!isset($item[1]))
1151 $id = implode(
':', $item);
1153 if($type ==
'REGION')
1154 $parentId = $lastOnes[
'COUNTRY'];
1155 elseif($type ==
'CITY')
1156 $parentId = $lastOnes['PARENT'];
1162 $lastOnes[$type] = $id;
1163 $lastOnes[
'PARENT'] = $id;
1166 if($item[
'2'] ==
'USA')
1169 $this->eTreeDB->insert(array(
1170 'TYPE_CODE' => $type,
1172 'LANGNAMES' => serialize(array(
1173 'RU' => array(
'NAME' => $item[4]),
1174 'EN' => array(
'NAME' => $item[2])
1177 'SOURCE' => self::SOURCE_LEGACY,
1179 'SYS_CODE' => $this->mapETCodeAsLegacy($id),
1180 'PARENT_SYS_CODE' => strlen($parentId) ? $this->mapETCodeAsLegacy($parentId) :
''
1184 $this->eTreeDB->doneInsert();
1185 $this->eTreeDB->switchIndexes(
true);
1188 #########################
1190 private function generateExportTreeBelorussia()
1192 $this->eTreeDB->dropCodeIndex();
1193 $this->eTreeDB->restoreExportOffset();
1195 $this->eTreeDB->switchIndexes(
false);
1197 $this->generateExportTreePutBelorussiaBundle(array(self::BELORUSSIA_YANDEX_CODE));
1199 $this->eTreeDB->doneInsert();
1200 $this->eTreeDB->switchIndexes(
true);
1203 private function generateExportTreePutBelorussiaBundle($bundle)
1205 foreach($bundle as $id)
1207 $node = $this->data[
'TREES'][
'MAIN'][
'NODES'][$id];
1210 if(isset($this->data[
'TREES'][
'MAIN'][
'EDGES'][$id]))
1211 $edges = $this->data[
'TREES'][
'MAIN'][
'EDGES'][$id];
1214 if($node[
'TYPE_CODE'] ==
'COUNTRY')
1215 $node[
'NAME'][
'EN'][
'NAME'] =
'Belarus';
1218 if($node[
'TYPE_CODE'] ==
'METRO_STATION' || $node[
'TYPE_CODE'] ==
'CITY_DISTRICT')
1221 $this->eTreeDB->insert(array(
1222 'TYPE_CODE' => $node[
'TYPE_CODE'],
1223 'NAME' => $node[
'NAME'][
'RU'][
'NAME'],
1224 'LANGNAMES' => serialize($node[
'NAME']),
1225 'EXTERNALS' => serialize($node[
'EXT']),
1226 'SOURCE' => self::SOURCE_YANDEX,
1228 'SYS_CODE' => $this->mapETCodeAsYandex($node[
'ID']),
1229 'PARENT_SYS_CODE' => strlen($node[
'PARENT_ID']) ? $this->mapETCodeAsYandex($node[
'PARENT_ID']) :
''
1233 $this->generateExportTreePutBelorussiaBundle($edges);
1237 #########################
1239 private function generateExportTreeUkrain()
1241 $this->eTreeDB->dropCodeIndex();
1242 $this->eTreeDB->restoreExportOffset();
1244 $cd2r = $this->getDataFromCSV(
'ukrain_kazakhstan',
'ukrain_district2region');
1248 $tree[
'NODES'][self::UKRAIN_YANDEX_CODE] = array(
1250 'RU' => array(
'NAME' =>
'Украина'),
1251 'UA' => array(
'NAME' =>
'Україна'),
1252 'EN' => array(
'NAME' =>
'Ukraine')
1254 'TYPE_CODE' =>
'COUNTRY',
1255 'SOURCE' => self::SOURCE_YANDEX,
1256 'ID' => self::UKRAIN_YANDEX_CODE,
1258 'YAMARKET' => array(
1259 self::UKRAIN_YANDEX_CODE
1264 foreach($cd2r as $line)
1267 if(!isset($tree[
'NODES'][$line[
'CDID']]))
1269 $tree[
'NODES'][$line[
'CDID']] = array(
1270 'NAME' => $line[
'CDNAME'],
1271 'TYPE_CODE' =>
'COUNTRY_DISTRICT',
1272 'SOURCE' => self::SOURCE_YANDEX,
1273 'ID' => $line[
'CDID'],
1274 'PARENT_ID' => self::UKRAIN_YANDEX_CODE,
1276 'YAMARKET' => array(
1283 $tree[
'EDGES'][self::UKRAIN_YANDEX_CODE][$line[
'CDID']] =
true;
1285 $regionId =
'r'.md5($line[
'RNAME'][
'UA'][
'NAME']);
1287 if($line[
'RNAME'][
'UA'][
'NAME'] ==
'Севастополь, Місто' || $line[
'RNAME'][
'UA'][
'NAME'] ==
'Автономна Республіка Крим')
1288 $source = self::SOURCE_UKRAIN;
1290 $source = self::SOURCE_YANDEX;
1292 if($line[
'RNAME'][
'UA'][
'NAME'] ==
'Севастополь, Місто')
1294 $typeCode =
'SUBREGION';
1298 $typeCode =
'REGION';
1302 if(!isset($tree[
'NODES'][$regionId]))
1304 $tree[
'NODES'][$regionId] = array(
1305 'NAME' => $line[
'RNAME'],
1306 'TYPE_CODE' => $typeCode,
1307 'SOURCE' => $source,
1309 'PARENT_ID' => $line[
'CDID'],
1312 if($source == self::SOURCE_YANDEX)
1313 $tree[
'NODES'][$regionId][
'EXT'][
'YAMARKET'][] = $line[
'RID'];
1316 $tree[
'EDGES'][$line[
'CDID']][$regionId] =
true;
1319 $res = $this->getDataFromCSV(
'ukrain_kazakhstan',
'ukrain');
1321 foreach($res as $line)
1323 if($line[
'REGION'] ==
'Автономна республіка Крим')
1324 $line[
'REGION'] =
'Автономна Республіка Крим';
1326 $line[
'REGION'] = $this->mb_str_replace(
'Місто',
'місто', $line[
'REGION']);
1327 $line[
'SUBREGION'] = $this->mb_str_replace(
'Місто',
'місто', $line[
'SUBREGION']);
1328 $line[
'CITY'] = $this->mb_str_replace(
'Місто',
'місто', $line[
'CITY']);
1330 $regionId =
'r'.md5($line[
'REGION']);
1331 $subRegionId =
'sr'.md5($line[
'SUBREGION']);
1332 $cityId =
'c'.md5($line[
'CITY']);
1334 if($line[
'REGION'] !=
'Севастополь, Місто')
1336 if(!isset($tree[
'NODES'][$subRegionId]))
1338 $tree[
'NODES'][$subRegionId] = array(
1339 'NAME' => array(
'UA' => array(
'NAME' => $line[
'SUBREGION'])),
1340 'TYPE_CODE' =>
'SUBREGION',
1341 'SOURCE' => self::SOURCE_UKRAIN,
1342 'ID' => $subRegionId,
1343 'PARENT_ID' => $regionId,
1346 if(!isset($tree[
'EDGES'][$regionId][$subRegionId]))
1347 $tree[
'EDGES'][$regionId][$subRegionId] =
true;
1351 if(!isset($tree[
'NODES'][$cityId]))
1353 $tree[
'NODES'][$cityId] = array(
1354 'NAME' => array(
'UA' => array(
'NAME' => $line[
'CITY'])),
1355 'TYPE_CODE' =>
'CITY',
1356 'SOURCE' => self::SOURCE_UKRAIN,
1358 'PARENT_ID' => $subRegionId,
1361 if(!isset($tree[
'EDGES'][$subRegionId][$cityId]))
1362 $tree[
'EDGES'][$subRegionId][$cityId] =
true;
1366 foreach($tree[
'EDGES'] as $k => $edges)
1367 $tree[
'EDGES'][$k] = array_keys($edges);
1369 $this->data[
'TREES'][
'UKRAIN'] = $tree;
1371 $this->generateExportTreePutUkrainBundle(array(self::UKRAIN_YANDEX_CODE));
1373 unset($this->data[
'TREES'][
'UKRAIN']);
1375 $this->eTreeDB->doneInsert();
1378 private function generateExportTreePutUkrainBundle($bundle)
1380 foreach($bundle as $id)
1382 $node = $this->data[
'TREES'][
'UKRAIN'][
'NODES'][$id];
1385 if(isset($this->data[
'TREES'][
'UKRAIN'][
'EDGES'][$id]))
1386 $edges = $this->data[
'TREES'][
'UKRAIN'][
'EDGES'][$id];
1388 $this->eTreeDB->insert(array(
1389 'TYPE_CODE' => $node[
'TYPE_CODE'],
1390 'NAME' => $node[
'NAME'][
'UA'][
'NAME'],
1391 'LANGNAMES' => serialize($node[
'NAME']),
1392 'EXTERNALS' => serialize($node[
'EXT']),
1393 'SOURCE' => $node[
'SOURCE'],
1395 'SYS_CODE' => $this->mapETCodeAsUkrainian($node[
'ID']),
1396 'PARENT_SYS_CODE' => strlen($node[
'PARENT_ID']) ? $this->mapETCodeAsUkrainian($node[
'PARENT_ID']) :
''
1400 $this->generateExportTreePutUkrainBundle($edges);
1416 private function mapETCodeAsYandex($code)
1421 private function mapETCodeAsFias($code)
1426 private function mapETCodeAsUkrainian($name)
1428 return 'U_'.md5($name);
1431 private function mapETCodeAsLegacy($name)
1433 return 'L_'.md5($name);
1436 #######################################################
1437 ### ABOUT EXPORT TREE GENERATION
1438 #######################################################
1440 private function mapETCodeBySource($value, $source)
1442 if($source == self::SOURCE_YANDEX)
1444 if($source == self::SOURCE_FIAS)
1446 if($source == self::SOURCE_UKRAIN)
1447 return 'U_'.md5($name);
1448 if($source == self::SOURCE_KAZAKHSTAN)
1449 return 'K_'.md5($name);
1452 private function startExportFromScratch()
1454 $this->cleanTemporalData(self::TMP_DATA_RUS_EXPORT_INDEX);
1455 $this->cleanTemporalData(self::TMP_DATA_RUS_GLOBAL_INDEX);
1457 $this->cleanPoolDir(
'assets');
1460 private function generateExportTreeRussiaRoot()
1462 $this->restoreTDRusExpIndex();
1464 if(!empty($this->alreadyDumped))
1467 $regions = $this->readFiasRootMapV2();
1468 $this->generateExportTreePutRussiaBundleOld(array(self::RUSSIA_YANDEX_CODE), $regions, 0);
1470 $this->storeTemporalData(self::TMP_DATA_RUS_EXPORT_INDEX, $this->alreadyDumped);
1473 private function restoreTDRusExpIndex()
1475 if(!empty($this->alreadyDumped))
1478 $this->alreadyDumped = $this->getStoredTemporalData(self::TMP_DATA_RUS_EXPORT_INDEX);
1481 private function storeTDGlobalExpIndex()
1483 $this->storeTemporalData(self::TMP_DATA_RUS_GLOBAL_INDEX, array(
'I' => $this->exportOffset));
1486 private function restoreTDGlobalExpIndex()
1488 if($this->exportOffset == 0)
1490 $data = $this->getStoredTemporalData(self::TMP_DATA_RUS_GLOBAL_INDEX);
1491 $this->exportOffset = intval($data[
'I']);
1495 private function generateExportTreePutRussiaBundleOld($bundle, $regions, $dl = 0)
1497 foreach($bundle as $id)
1499 $node = $this->data[
'TREES'][
'MAIN'][
'NODES'][$id];
1502 if(isset($this->data[
'TREES'][
'MAIN'][
'EDGES'][$id]))
1503 $edges = $this->data[
'TREES'][
'MAIN'][
'EDGES'][$id];
1505 if(in_array($node[
'TYPE_CODE'], array(
'COUNTRY',
'COUNTRY_DISTRICT',
'REGION')))
1507 if($node[
'TYPE_CODE'] ==
'REGION')
1512 $fNode = $this->fiasGetByAOGUID($regions[$node[
'ID']][
'AOGUID']);
1513 if(strlen($fNode[
'POSTALCODE']))
1514 $node[
'EXT'][
'ZIP'][] = $fNode[
'POSTALCODE'];
1519 $this->addItemToExportTree(array(
1520 'ID' => $this->mapETCodeAsYandex($node[
'ID']),
1521 'PARENT_ID' => strlen($node[
'PARENT_ID']) && $dl > 0 ? $this->mapETCodeAsYandex($node[
'PARENT_ID']) :
'',
1522 'TYPE' => $node[
'TYPE_CODE'],
1523 'NAME' => $node[
'NAME'],
1524 'EXTERNALS' => $node[
'EXT'],
1529 $this->generateExportTreePutRussiaBundle($edges, $regions, $dl+1);
1534 private $fiasPath = array();
1535 private $alreadyStoredPathItems = array();
1536 private $fias2yandexMap = array();
1538 private $alreadyDumped = array();
1540 private $currentRegion =
false;
1542 private function generateExportTreeRussiaInner()
1544 $links = $this->getFias2YamarketRootLinks(
false,
true);
1549 foreach($links as $yRId => $regions)
1553 $this->restoreTDGlobalExpIndex();
1554 $this->alreadyDumped = array();
1555 $this->restoreTDRusExpIndex();
1557 $this->fias2yandexMap = array();
1558 $fias2yandex = $this->getDataFromCSV(
'fias_yamarket_links',
'region_'.$yRId);
1559 foreach($fias2yandex as $map)
1561 $this->fias2yandexMap[$map[
'AOGUID']] = $map;
1563 unset($fias2yandex);
1565 $this->currentRegion = $this->mapETCodeBySource($yRId, self::SOURCE_YANDEX);
1567 foreach($regions as $regionId)
1569 $this->fiasPath = array();
1571 $this->
output(
'CCCurrent REGION is '.$this->currentRegion);
1574 $this->generateExportTreeRussiaInnerBundle($regionId);
1577 $this->storeTDGlobalExpIndex();
1584 private function generateExportTreeRussiaInnerBundle($parentGuid)
1586 if(!strlen($parentGuid))
1589 $res = $this->getDataFromCSV(
'fias_tree', $parentGuid);
1590 foreach($res as $item)
1592 if($item[
'LIVESTATUS'] !=
'1' || $item[
'ACTSTATUS'] !=
'1')
1595 $item[
'PARENT_ID'] = $parentGuid;
1596 array_push($this->fiasPath, $item);
1598 if($this->checkIsAllowedCityVillage($item[
'ID'], $item[
'TYPE']))
1601 $this->storeCurrentFiasPath2();
1602 $this->generateExportTreeRussiaInnerStreets($item[
'ID']);
1605 $this->generateExportTreeRussiaInnerBundle($item[
'ID']);
1607 array_pop($this->fiasPath);
1613 private function addItemToExportTree($item)
1615 $this->exportOffset++;
1617 $this->
output(
'ADD: '.$item[
'NAME'][
'RU'][
'NAME'].
' '.$item[
'TYPE']);
1620 $cat = $this->sysMaps[
'BASETYPE2GROUP'][$item[
'TYPE']];
1621 $fName = $this->typeGroups[$cat][
'FILE_NAME_TEMPLATE'];
1623 $header = $this->typeGroups[$cat];
1624 $this->alreadyDumped[$item[
'ID']] = $this->exportOffset;
1626 $parentCode = strlen($item[
'PARENT_ID']) ? $this->addLeadingZero($this->alreadyDumped[$item[
'PARENT_ID']], self::CODE_LENGTH) :
'';
1629 'CODE' => $this->addLeadingZero($this->exportOffset, self::CODE_LENGTH),
1630 'PARENT_CODE' => $parentCode,
1631 'TYPE_CODE' => $item[
'TYPE']
1634 foreach($item[
'NAME'] as $lid => $values)
1636 foreach($values as $i => $val)
1637 $data[
'NAME.'.$lid.
'.'.$i] = $val;
1640 $data[
'EXT.YAMARKET.0'] =
'';
1641 $data[
'EXT.ZIP.0'] =
'';
1642 if(!empty($item[
'EXTERNALS']))
1644 foreach($item[
'EXTERNALS'] as $type => $values)
1646 foreach($values as $i => $val)
1647 $data[
'EXT.'.$type.
'.'.$i] = $val;
1651 $parentGroupId = strlen($item[
'PARENT_GROUP_ID']) ? $this->addLeadingZero($this->alreadyDumped[$item[
'PARENT_GROUP_ID']], self::CODE_LENGTH) :
'';
1653 $data[
'LONGITUDE'] =
'';
1654 $data[
'LATITUDE'] =
'';
1657 $fName = str_replace(array(
1658 '%BASE_PARENT_ITEM_CODE%',
1681 #######################################################
1683 #######################################################
1688 $this->queue =
false;
1689 $this->data[
'TREES'][
'MAIN'] = array();
1690 $this->data[
'MAPS'] = array();
1691 $this->data[
'INDEXES'] = array();
1695 $done = $this->buildMainTreeNext();
1698 $this->buildRussiaPathIndex($this->data[
'TREES'][
'MAIN'][
'EDGES'][self::RUSSIA_YANDEX_CODE], array());
1701 private function buildMainTreeNext()
1703 $next = $this->queueShift();
1704 $bundle = $this->getBundleFromFile($next);
1708 foreach($bundle as $item)
1710 $this->data[
'TREES'][
'MAIN'][
'NODES'][$item[
'ID']] = $item;
1711 $parent = isset($item[
'PARENT_ID']) ? $item[
'PARENT_ID'] :
'ROOT';
1712 $this->data[
'TREES'][
'MAIN'][
'EDGES'][$parent][] = $item[
'ID'];
1714 if($item[
'CHILDREN_COUNT'] > 0)
1715 $this->queue[] = $item[
'ID'];
1719 return empty($this->queue);
1722 #######################################################
1723 ### ABOUT FIAS PROCESS
1724 #######################################################
1727 private function checkFiasMaps()
1729 $links = $res = $this->getDataFromCSV(
'fias_yamarket_links',
'rootv2');
1731 foreach($links as $reg)
1733 if($reg[
'CITIES_MAPPED'] !=
'1')
1736 $rMap = $this->getDataFromCSV(
'fias_yamarket_links',
'region_'.$reg[
'YAMARKET']);
1738 $this->output(
'============================ For: '.$reg[
'YAMARKET_NAME'].
' '.$reg[
'YAMARKET']);
1741 foreach($rMap as $map)
1743 if(!strlen($map[
'AOGUID']))
1747 $this->output($map);
1749 $res = DB\FiasTable::getList(array(
'filter' => array(
1750 'FORMALNAME' => $map[
'NAME'],
1751 '!SHORTNAME' => array(
'ул',
'пер'),
1755 while($item = $res->fetch())
1757 $this->output($item);
1762 $this->
output(
'Unmapped: '.$unmapped);
1763 $uTotal += $unmapped;
1766 $this->
output(
'TOTAL: '.$uTotal);
1769 private function showChildren($pId)
1771 $res = DB\FiasTable::getList(array(
'filter' => array(
1772 'PARENTGUID' => $pId,
1776 while($item = $res->fetch())
1782 private function findPathes()
1785 'aea7bac4-f9b4-4160-95f2-3d667b4d3f92',
1786 'bda061ac-cbd0-4db8-8d18-69db43e76c2d',
1787 '436b841d-a44f-431e-b1ec-7d76456d4a11',
1788 '807943cc-31c0-4a86-a3fe-46d9262101e9',
1791 foreach($pathes as $id)
1793 $this->fiasFindPath($id);
1797 private function fiasFindPath($aoguid)
1801 while($pId && $res = DB\FiasTable::getList(array(
'filter' => array(
1808 if($res[
'PARENTGUID'])
1809 $pId = $res[
'PARENTGUID'];
1815 private function fiasFind2()
1817 $res = DB\FiasTable::getList(array(
'filter' => array(
1818 'FORMALNAME' => array(
1825 while($item = $res->fetch())
1831 private function fiasFind()
1833 $findInFias = array(
1836 '11 0 007 000 000 009 0000 0000 000',
1837 '35 0 003 000 000 001 0000 0000 000',
1838 '05 0 017 000 000 019 0000 0000 000',
1839 '20 0 028 000 000 001 0000 0000 000',
1840 '16 0 022 000 000 023 0000 0000 000',
1841 '59 0 020 000 000 003 0000 0000 000',
1842 '56 0 000 000 000 002 0000 0000 000',
1843 '86 0 003 000 000 031 0000 0000 000',
1844 '70 0 007 000 000 000 0000 0047 000',
1845 '27 0 009 000 000 001 0000 0000 000',
1846 '28 0 014 000 000 045 0000 0000 000',
1847 '14 0 010 000 000 001 0000 0000 000',
1851 $res = DB\FiasTable::getList(array(
'filter' => array(
1852 'CODE' => array_values($findInFias),
1856 while($item = $res->fetch())
1862 private function fiasGetByAOGUID($fiasId)
1864 return DB\FiasTable::getList(array(
'filter' => array(
1865 '=AOGUID' => $fiasId,
1913 private function mapFiasCities()
1916 $links = $this->getFias2YamarketRootLinks();
1920 $typesToSearch = array(
'CITY',
'VILLAGE');
1923 foreach($links as $id => $fiasSource)
1925 $region = $this->data[
'MAPS'][
'REGIONS'][$id];
1927 $this->
output(
'FOR region: '.$region);
1930 $toBeFound = array();
1931 $this->getMainTreeNodesOfType(array($id), $typesToSearch, $toBeFound);
1935 if(!empty($toBeFound))
1937 foreach($fiasSource as $fiasId)
1939 $this->
output(
'In: '.$fiasId);
1940 $this->walkFiasTreeAndKeepFollowing($fiasId, $toBeFound, $typesToSearch);
1944 $this->cleanUpFile(
'fias_yamarket_links',
'region_'.$region[
'ID']);
1945 foreach($toBeFound as $node)
1952 if(!empty($node[
'MATCH']))
1954 $match = array_shift($node[
'MATCH']);
1956 $exactId = $match[
'ID'];
1957 $exactName = $match[
'NAME'];
1958 $exactType = $match[
'TYPE'];
1960 $item = $this->fiasGetByAOGUID($exactId);
1963 $exactCode = $item[
'CODE'];
1966 $this->
output(
'no record in fias for: '.$exactId);
1971 'ID' => $node[
'ID'],
1972 'NAME' => $node[
'NAME'][
'RU'][
'NAME'],
1973 'AOGUID' => $exactId,
1974 'FNAME' => $exactName,
1975 'FTYPE' => $exactType,
1976 'CODE' => $exactCode
1979 for($i = 0; $i < 3; $i++)
1981 $data[
'VAR_AOGUID_'.$i] =
'';
1982 $data[
'VAR_NAME_'.$i] =
'';
1983 $data[
'VAR_TYPE_'.$i] =
'';
1987 if(!empty($node[
'MATCH']))
1989 foreach($node[
'MATCH'] as $item)
1991 $data[
'VAR_AOGUID_'.$i] = $item[
'ID'];
1992 $data[
'VAR_NAME_'.$i] = $item[
'NAME'];
1993 $data[
'VAR_TYPE_'.$i] = $item[
'TYPE'];
1999 if(!empty($node[
'POSSIBLE']))
2001 foreach($node[
'POSSIBLE'] as $item)
2003 $data[
'VAR_AOGUID_'.$i] = $item[
'ID'];
2004 $data[
'VAR_NAME_'.$i] = $item[
'NAME'];
2005 $data[
'VAR_TYPE_'.$i] = $item[
'TYPE'];
2013 'fias_yamarket_links',
2014 'region_'.$region[
'ID'],
2023 private function checkAllowedState($node)
2025 return $node[
'ACTSTATUS'] ==
'1' && $node[
'LIVESTATUS'] ==
'1';
2028 private function mb_str_replace($needle, $replace_text, $haystack)
2030 return implode($replace_text, mb_split($needle, $haystack));
2033 private function checkNamesEqual($one, $two)
2036 $one = $this->makeNameIndexKey($one);
2037 $two = $this->makeNameIndexKey($two);
2044 $one = $this->mb_str_replace(
'ё',
'е', $one);
2045 $two = $this->mb_str_replace(
'ё',
'е', $two);
2052 $one = $this->mb_str_replace(
'й',
'и', $one);
2053 $two = $this->mb_str_replace(
'й',
'и', $two);
2066 private function checkNamesAlmostEqual($one, $two)
2068 $one = $this->makeNameIndexKey($one);
2069 $two = $this->makeNameIndexKey($two);
2071 if(strpos($one, $two) !==
false || strpos($two, $one) !==
false)
2074 $one = $this->mb_str_replace(
'ё',
'е', $one);
2075 $two = $this->mb_str_replace(
'ё',
'е', $two);
2077 if(strpos($one, $two) !==
false || strpos($two, $one) !==
false)
2080 $one = $this->mb_str_replace(
'й',
'и', $one);
2081 $two = $this->mb_str_replace(
'й',
'и', $two);
2083 if(strpos($one, $two) !==
false || strpos($two, $one) !==
false)
2087 $one = preg_replace(
'#\s+-\s+#',
'-', $one);
2088 $two = preg_replace(
'#\s+-\s+#',
'-', $two);
2090 if(strpos($one, $two) !==
false || strpos($two, $one) !==
false)
2096 private function walkFiasTreeAndKeepFollowing($node, &$toBeFound, $typesToSearch)
2098 $bundle = $this->getDataFromCSV(
'fias_tree', $node);
2100 if(is_array($bundle) && !empty($bundle))
2103 foreach($bundle as $node)
2105 $name = $this->makeNameIndexKey($node[
'NAME']);
2110 if(strlen($node[
'TYPE']) && isset($this->sysMaps[
'FIAS2BASETYPE'][$node[
'TYPE']]))
2112 $type = $this->sysMaps[
'FIAS2BASETYPE'][$node[
'TYPE']];
2114 if(in_array($type, $typesToSearch))
2117 foreach($toBeFound as &$keptNode)
2119 if($keptNode[
'TYPE_CODE'] != $type)
2122 if(!$this->checkAllowedState($node))
2125 if($this->checkNamesEqual($name, $keptNode[
'NAME'][
'RU'][
'NAME']))
2127 $keptNode[
'MATCH'][$node[
'AOGUID']] = $node;
2129 elseif($this->checkNamesAlmostEqual($name, $keptNode[
'NAME'][
'RU'][
'NAME']))
2131 $keptNode[
'POSSIBLE'][$node[
'AOGUID']] = $node;
2137 $this->walkFiasTreeAndKeepFollowing($node[
'ID'], $toBeFound, $typesToSearch);
2142 private function getFias2YamarketRootLinks($skipMapped =
true, $skipCompiled =
false)
2144 $res = $this->getDataFromCSV(
'fias_yamarket_links',
'rootv2');
2147 foreach($res as $reg)
2149 if($skipMapped && $reg[
'CITIES_MAPPED'] ==
'1')
2152 if($skipCompiled && $reg[
'COMPILED'] ==
'1')
2155 $fias = array($reg[
'AOGUID']);
2157 if(strlen($reg[
'ADDITIONAL']))
2159 $variants = explode(
', ', $reg[
'ADDITIONAL']);
2160 foreach($variants as $var)
2162 $id = explode(
':', $var);
2167 $result[$reg[
'YAMARKET']] = $fias;
2175 $this->cleanPoolDir(
'fias_tree');
2176 $this->walkFias(
'fiasGotOneSplit');
2182 $this->fiasDB->create();
2184 $this->fiasDB->switchIndexes(
false);
2185 $this->fiasDB->deleteAll();
2186 $this->walkFias(
'fiasGotOneAdd2DB');
2187 $this->fiasDB->doneInsert();
2188 $this->fiasDB->switchIndexes(
true);
2223 $item = $data[
'__ATTR'];
2234 'ID' => $item[
'AOGUID'],
2235 'ACTSTATUS' => $item[
'ACTSTATUS'],
2236 'LIVESTATUS' => $item[
'LIVESTATUS'],
2237 'NAME' => $item[
'FORMALNAME'],
2238 'TYPE' => $item[
'SHORTNAME'],
2239 'POSTALCODE' => $item[
'POSTALCODE']
2242 strlen($item[
'PARENTGUID']) ? $item[
'PARENTGUID'] :
'root',
2249 $item = $data[
'__ATTR'];
2251 $code = implode(
' ', array(
2252 $item[
'REGIONCODE'],
2258 $item[
'STREETCODE'],
2270 $formalName = $item[
'FORMALNAME'];
2271 $nameLC = $this->makeNameIndexKey($item[
'FORMALNAME']);
2272 $shortName = $item[
'SHORTNAME'];
2274 $this->fiasDB->insert(array(
2275 'AOGUID' => $item[
'AOGUID'],
2276 'PARENTGUID' => $item[
'PARENTGUID'],
2278 'AOID' => $item[
'AOID'],
2279 'NEXTID' => $item[
'NEXTID'],
2281 'FORMALNAME' => $formalName,
2282 'SHORTNAME' => $shortName,
2283 'POSTALCODE' => $item[
'POSTALCODE'],
2285 'ACTSTATUS' => $item[
'ACTSTATUS'],
2286 'LIVESTATUS' => $item[
'LIVESTATUS'],
2288 'NAME_LC' => $nameLC,
2293 private function getByAOID($aoid)
2295 $id = explode(
'-', $aoid);
2298 private function printCurrentFiasPath()
2301 foreach($this->fiasCPath as $item)
2302 $path[] = $item[
'NAME'];
2304 return implode(
'>', $path);
2307 private function manageFiasPath($item)
2309 $guid = $item[
'AOGUID'];
2310 $parentGUID = $item[
'PARENTGUID'];
2316 private function truncateCurrentFiasPath($guid)
2318 foreach($this->fiasCPath as $i => $node)
2320 if($node[
'GUID'] == $guid)
2322 array_splice($this->fiasCPath, $i + 1);
2328 #######################################################
2329 ### ABOUT FIAS PROCESS ROOT v2
2330 #######################################################
2334 $this->cleanUpFile(
'fias_yamarket_links',
'rootv2');
2335 $this->walkFias(
'fiasGotOneMapRootV2');
2337 foreach($this->data[
'MAPS'][
'REGIONS'] as $id => $reg)
2343 if(count($reg[
'MATCH']))
2345 $foundId = $reg[
'MATCH'][0][
'ID'];
2346 $foundName = $reg[
'MATCH'][0][
'NAME'];
2348 array_shift($reg[
'MATCH']);
2350 if(count($reg[
'MATCH']))
2352 $additResults = array();
2353 foreach($reg[
'MATCH'] as $additRes)
2354 $additResults[] = $additRes[
'ID'].
':"'.$additRes[
'NAME'].
'"';
2356 $additResults = implode(
', ', $additResults);
2363 'YAMARKET_NAME' => $reg[
'NAME'][
'RU'][
'NAME'],
2364 'AOGUID' => $foundId,
2365 'FIAS_NAME' => $foundName,
2366 'ADDITIONAL' => $additResults
2368 'fias_yamarket_links',
2376 $item = $data[
'__ATTR'];
2378 $type = $item[
'SHORTNAME'];
2379 $name = $this->makeNameIndexKey($item[
'FORMALNAME']);
2381 if($this->sysMaps[
'FIAS2BASETYPE'][$type] ==
'REGION')
2384 foreach($this->data[
'MAPS'][
'REGIONS'] as $id => &$node)
2386 $rName = $this->makeNameIndexKey($node[
'NAME'][
'RU'][
'NAME']);
2388 if($rName == $name || strpos($rName, $name) !==
false)
2390 $node[
'MATCH'][] = array(
2391 'ID' => $item[
'AOGUID'],
2392 'NAME' => $item[
'FORMALNAME'].
' '.$item[
'SHORTNAME']
2399 private function readFiasRootMapV2()
2405 $data = $csv->ReadBlock($this->getPoolFileName(
'fias_yamarket_links',
'rootv2',
false));
2406 foreach($data as $region)
2407 $result[$region[
'YAMARKET']] = $region;
2417 private function walkFias($callback, $limit = -1)
2419 $sax =
new SAXParser(array(
2420 'watch4Tag' =>
'Object',
2421 'onEachParseResult' => array($this, $callback),
2423 'collapseAttr' =>
true
2426 $fd = fopen($_SERVER[
'DOCUMENT_ROOT'].$this->options[
'fiasAddrobjFile'],
'r');
2427 while($block = fread($fd, 1024))
2429 if(!$sax->putToParser($block))
2436 #######################################################
2438 #######################################################
2440 private function buildRussiaPathIndex($bundle, $parentPath = array())
2442 foreach($bundle as $id)
2444 $node = $this->data[
'TREES'][
'MAIN'][
'NODES'][$id];
2445 $name = $this->makeNameIndexKey($node[
'NAME'][
'RU'][
'NAME']);
2448 if($node[
'TYPE_CODE'] ==
'REGION')
2449 $this->data[
'MAPS'][
'REGIONS'][$id] = $node;
2451 if(isset($this->data[
'TREES'][
'MAIN'][
'EDGES'][$id]))
2452 $this->buildRussiaPathIndex($this->data[
'TREES'][
'MAIN'][
'EDGES'][$id], $ppp);
2456 private function getMainTreeNodesOfType($bundle, $types = array(), &$buffer)
2458 foreach($bundle as $id)
2460 $node = $this->data[
'TREES'][
'MAIN'][
'NODES'][$id];
2462 if(in_array($node[
'TYPE_CODE'], $types))
2465 $buffer[$id] = $node;
2468 if(isset($this->data[
'TREES'][
'MAIN'][
'EDGES'][$id]))
2469 $this->getMainTreeNodesOfType($this->data[
'TREES'][
'MAIN'][
'EDGES'][$id], $types, $buffer);
2473 #######################################################
2475 #######################################################
2477 private function putToFile($data, $poolName, $fileSubname)
2479 $dir = $_SERVER[
'DOCUMENT_ROOT'].$this->workDir.$this->filePools[$poolName][
'DIR'];
2480 if(!file_exists($dir))
2481 mkdir($dir, 0755,
true);
2483 if(!isset($this->filePoolsp[$poolName][$fileSubname]))
2485 $fd = $this->filePoolsp[$poolName][$fileSubname] = fopen($dir.$fileSubname.
'.csv',
'w');
2486 $head = implode(
';', array_keys($data));
2487 fputs($fd, $head.PHP_EOL);
2489 $this->filePoolsp[$poolName][$fileSubname] = $fd;
2492 fputs($this->filePoolsp[$poolName][$fileSubname], implode(
';', $data).PHP_EOL);
2495 private function putToFile2($data, $poolName, $fileSubname, $checkDir =
false)
2497 $dir = $_SERVER[
'DOCUMENT_ROOT'].$this->workDir.$this->filePools[$poolName][
'DIR'];
2498 $fName = $dir.$fileSubname.
'.csv';
2500 if($checkDir && !file_exists($dir))
2501 mkdir($dir, 0755,
true);
2503 if(!file_exists($fName))
2504 file_put_contents($fName, implode(
';', array_keys($data)).PHP_EOL, FILE_APPEND);
2506 file_put_contents($fName, implode(
';', $data).PHP_EOL, FILE_APPEND);
2509 private function cleanUpFile($poolName, $fileSubname)
2511 $name = $_SERVER[
'DOCUMENT_ROOT'].$this->workDir.$this->filePools[$poolName][
'DIR'].$fileSubname.
'.csv';
2513 if(file_exists($name))
2517 private function getPoolFileName($poolName, $fileSubname, $docRoot =
true)
2519 return ($docRoot ? $_SERVER[
'DOCUMENT_ROOT'] :
'/').$this->workDir.$this->filePools[$poolName][
'DIR'].$fileSubname.
'.csv';
2522 private function getPoolDirName($poolName, $docRoot =
true)
2524 return ($docRoot ? $_SERVER[
'DOCUMENT_ROOT'] :
'/').$this->workDir.$this->filePools[$poolName][
'DIR'];
2527 private function cleanPoolDir($poolName)
2529 $dir = $_SERVER[
'DOCUMENT_ROOT'].$this->workDir.$this->filePools[$poolName][
'DIR'];
2530 if(file_exists($dir))
2531 system(
'rm -rf '.$dir);
2533 mkdir($dir, 0755,
true);
2536 private function getDataFromCSV($poolName, $fileSubname)
2540 $csv =
new Import\CSVReader(
'R',
false);
2541 return $csv->ReadBlock($this->getPoolFileName($poolName, $fileSubname,
false));
2543 catch(\Exception $e)
2549 private function putDataToCSV($data, $poolName, $fileSubname)
2551 $fName = $this->getPoolFileName($poolName, $fileSubname);
2552 if(file_exists($fName))
2554 $header = implode(
';', array_keys($data[0])).PHP_EOL;
2555 file_put_contents($fName, $header);
2556 foreach($data as $line)
2557 file_put_contents($fName, implode(
';', $line).PHP_EOL, FILE_APPEND);
2561 #######################################################
2563 #######################################################
2565 private function mapFiasTypeToMain($fiasType)
2567 return isset($this->sysMaps[
'FIAS2BASETYPE'][$fiasType]) ? $this->sysMaps[
'FIAS2BASETYPE'][$fiasType] :
false;
2570 private function makeNameIndexKey($name)
2572 return trim(mb_strtolower($name,
'UTF-8'));
2575 private function makeTypeGroupFile($file =
'')
2577 $fd = $this->fileOpen(strlen($file) ? $file : self::
GROUP_FILE);
2579 fputs($fd, implode(
';', $this->headers[
'GROUP_FILE']).PHP_EOL);
2580 foreach($this->typeGroups as $code => $group)
2583 foreach($this->headers[
'GROUP_FILE'] as $colCode)
2584 $line[] = is_array($group[$colCode]) ? implode(
':', $group[$colCode]) : $group[$colCode];
2586 fputs($fd, implode(
';', $line).PHP_EOL);
2592 private function makeNext()
2594 $next = $this->queueShift();
2595 $bundle = $this->getBundleFromFile($next);
2599 foreach($bundle as $item)
2601 $this->putToGroups($item);
2603 if($item[
'CHILDREN_COUNT'] > 0)
2604 $this->queue[] = $item[
'ID'];
2608 return empty($this->queue);
2611 private function queueShift()
2613 if($this->queue !==
false)
2614 return array_shift($this->queue);
2619 private function getBundleFromFile($id)
2621 $data = unserialize(file_get_contents($_SERVER[
'DOCUMENT_ROOT'].$this->grabbedStuffDir.$id));
2623 foreach($data as $k => &$item)
2625 if(in_array($item[
'NAME'], array(
'Прочее',
'Общероссийские',
'Универсальное',
'Другие города региона')))
2632 if(isset($this->typeMap[$item[
'TYPE_CODE']]))
2633 $item[
'TYPE_CODE'] = $this->typeMap[$item[
'TYPE_CODE']];
2636 if($item[
'TYPE_CODE'] ==
'OTHER')
2638 $parentType = $this->yaIdType[$item[
'PARENT_ID']];
2640 if($parentType ==
'REGION')
2641 $item[
'TYPE_CODE'] =
'SUBREGION';
2644 $code = $this->addLeadingZero($this->codeOffset, $this->leading);
2645 $this->yaIdType[$item[
'ID']] = $item[
'TYPE_CODE'];
2647 $this->relations[$item[
'CODE']] = $item[
'PARENT_CODE'];
2648 $this->code2type[$item[
'CODE']] = $item[
'TYPE_CODE'];
2650 $ruName = $item[
'NAME'];
2655 $item[
'NAME'] = array();
2656 $item[
'NAME'][
'RU'][
'NAME'] = $ruName.($this->options[
'includeYaInfo2Name'] ?
' ('.$item[
'TYPE_CODE'].
', '.$item[
'ID'].
')' :
'');
2660 $item[
'EXT'][
'YAMARKET'][] = $item[
'ID'];
2669 private function getParentOfType($code, $types)
2681 throw new Main\SystemException(
'Recursion gone too deep when trying to find parent of type');
2683 if(isset($types[$this->code2type[$nextCode]]))
2686 $nextCode = $this->relations[$nextCode];
2692 private function putToGroups($item)
2694 foreach($this->typeGroups as $gCode => &$group)
2698 if(!isset($group[
'I_TYPES'][$item[
'TYPE_CODE']]))
2703 $baseParent = $this->getParentOfType($item[
'CODE'], $this->typeGroups[$group[
'PARENT']][
'I_TYPES']);
2707 if(!$group[
'FD'][$baseParent])
2709 $fName = str_replace(array(
2710 '%BASE_PARENT_ITEM_CODE%',
2715 ), $group[
'FILE_NAME_TEMPLATE']);
2717 $group[
'FD'][$baseParent] = $this->fileOpen($fName);
2718 fputs($group[
'FD'][$baseParent], implode(
';', $this->headers[$group[
'HEADER']]).PHP_EOL);
2721 $header = $this->headers[$group[
'HEADER']];
2723 foreach($header as $code)
2724 $line[] = isset($item[$code]) ? $item[$code] :
'';
2726 fputs($group[
'FD'][$baseParent], implode(
';', $line).PHP_EOL);
2730 private function fileOpen($name)
2732 return fopen($_SERVER[
'DOCUMENT_ROOT'].$this->workDir.self::OUTPUT_DIR.$name,
'w');
2735 private static function addLeadingZero($value, $length)
2737 if(strlen($value) >= $length)
2740 $diff = abs($length - strlen($value));
2742 for($i = 0; $i < $diff; $i++)
2743 $value =
'0'.$value;
2748 #######################################################
2750 #######################################################
2752 private function storeTemporalData($dataCode, $data)
2754 $dir = $_SERVER[
'DOCUMENT_ROOT'].$this->workDir.self::TMP_DATA_DIR;
2755 if(!file_exists($dir))
2756 mkdir($dir, 0755,
true);
2758 file_put_contents($dir.$dataCode, serialize($data));
2761 private function getStoredTemporalData($dataCode)
2763 $file = $_SERVER[
'DOCUMENT_ROOT'].$this->workDir.self::TMP_DATA_DIR.$dataCode;
2765 if(is_readable($file))
2766 return unserialize(file_get_contents($file));
2771 private function cleanTemporalData($dataCode)
2773 $file = $_SERVER[
'DOCUMENT_ROOT'].$this->workDir.self::TMP_DATA_DIR.$dataCode;
2775 if(is_readable($file))
2791 $file = $_SERVER[
'DOCUMENT_ROOT'].$this->workDir.self::OUTPUT_FILE;
2793 if(is_readable($file))
2797 public function output($data, $important =
true)
2804 $data = ob_get_contents();
2807 file_put_contents($_SERVER[
'DOCUMENT_ROOT'].$this->workDir.self::OUTPUT_FILE, $data.PHP_EOL, FILE_APPEND);