Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
compiler.php
1<?
9/*
10//HOWTO call:
11
12$compiler = new Compiler\Compiler(array(
13 'workDir' => 'locations_data/',
14 'grabbedStuffDir' => 'locations_data/grabber/output/',
15 'grabber' => $grabber,
16 'includeYaInfo2Name' => false,
17 'fiasAddrobjFile' => 'locations_data/addrobj.xml'
18));
19$compiler->compile();
20*/
21
23
25
26final class Compiler {
27
28 const OUTPUT_DIR = 'compiled/';
29 const MAPS_DIR = 'maps/';
30 const INPUT_DIR = 'output/';
31 const OUTPUT_FILE = 'output.txt';
32 const CODE_LENGTH = 10;
33 const TMP_DATA_DIR = 'tmp/';
34 const STATIC_CSV_DIR = 'static_csv/';
35
36 const GROUP_FILE = 'typegroup.csv';
37
38 const KAZAKHSTAN_SOURCE = 'ukrain_kazakhstan/loc_kz.csv';
39 const USA_SOURCE = 'ukrain_kazakhstan/loc_usa.csv';
40 const WORLD_SOURCE = 'ukrain_kazakhstan/loc_cntr.csv';
41 const CIS_SOURCE = 'ukrain_kazakhstan/loc_ussr_cut.csv';
42
43 const RUSSIA_YANDEX_CODE = 225;
45 const UKRAIN_YANDEX_CODE = 187;
47
48 const SOURCE_YANDEX = 'Y'; // got from yandex
49 const SOURCE_FIAS = 'F'; // got from fias
50 const SOURCE_UKRAIN = 'U'; // data sent by the office in ukrain
51 const SOURCE_LEGACY = 'L'; // got from old location files
52
53 const TMP_DATA_RUS_EXPORT_INDEX = 'rus_exp_index';
54 const TMP_DATA_RUS_GLOBAL_INDEX = 'glob_exp_index';
55
56 private $queue = false;
57
58 private $typeMap = array(
59 'SUBJECT_FEDERATION' => 'REGION'
60 );
61
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'/*, 'EXT.ZIP.1', 'EXT.ZIP.2', 'EXT.ZIP.3'*/),
65 'GROUP_FILE' => array('CODE', 'TYPES')
66 );
67
68 private $typeGroups = array(
69 'LAYOUT' => array(
70 'CODE' => 'LAYOUT',
71 'TYPES' => array('COUNTRY', 'COUNTRY_DISTRICT', 'REGION'),
72 'HEADER' => 'LONG',
73 'FILE_NAME_TEMPLATE' => 'layout.csv'
74 ),
75 /*
76 'SELECTABLE' => array(
77 'TYPES' => array('COUNTRY', 'COUNTRY_DISTRICT', 'REGION'),
78 'HEADER' => 'LONG',
79 'FILE_NAME_TEMPLATE' => 'selectable.csv'
80 ),
81 */
82 'AREAS' => array(
83 'CODE' => 'AREAS',
84 'TYPES' => array('CITY', 'SUBREGION', 'VILLAGE'/*, 'CITY_DISTRICT', 'METRO_STATION', 'OTHER'*/),
85 'PARENT' => 'LAYOUT',
86 'HEADER' => 'LONG',
87 'FILE_NAME_TEMPLATE' => '%BASE_PARENT_ITEM_CODE%_%CODE%.csv'
88 ),
89 'STREETS' => array(
90 'CODE' => 'STREETS',
91 'TYPES' => array('STREET'),
92 'PARENT' => 'LAYOUT',
93 'HEADER' => 'LONG',
94 'FILE_NAME_TEMPLATE' => '%BASE_PARENT_ITEM_CODE%_%CODE%.csv'
95 )
96 );
97
98 private $fiasToBaseType = array(
99 'COUNTRY' => array(),
100 'COUNTRY_DISTRICT' => array(
101 'округ' => array('R' => 'округ', 'U' => true),
102 ),
103 'REGION' => array(
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)
110 ),
111
112 'SUBREGION' => array(
113 'р-н' => array('R' => 'район', 'U' => true),
114
115 'улус' => array('R' => 'улус', 'U' => true),
116 'у' => array('R' => 'улус', 'U' => true),
117 ),
118
119 'CITY' => array(
120 'г' => array('R' => 'город', 'U' => true),
121 ),
122 'VILLAGE' => array(
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' => 'остров'),
144
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)
160 ),
161
162 //'CITY_DISTRICT' => array(),
163 //'METRO_STATION' => array(),
164
165 'STREET' => array(
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)
197 )
198 );
199
200 private $forbiddenPathTypes = array(
201 'ул' => 1,
202 'пр-кт' => 1,
203 'проезд' => 1,
204 'ш' => 1,
205 'кв-л' => 1,
206 'км' => 1,
207 'просек' => 1,
208 'пер' => 1,
209 'б-р' => 1,
210 'наб' => 1,
211 'ж/д_будка' => 1,
212 'тракт' => 1,
213 'дор' => 1,
214 'рзд' => 1,
215 'пл' => 1,
216 'высел' => 1,
217 'сад' => 1,
218 'уч-к' => 1,
219 'промзона' => 1,
220 'автодорога' => 1,
221 'ж/д_платф' => 1,
222 );
223
224 private $forbiddenPathIds = array(
225 'af7cdb7f-e47d-4f65-93d5-3a2b70a809ce' => true, // Боровой микрорайон should be placed inside village, not street
226 '762758bb-18b9-440f-bc61-8e1e77ff3fd8' => true, // московский посёлок cannot be inside московский город, those are the same
227 );
228
229 private $allowedFiasStats = array(
230 'ACTSTATUS' => array(
231 1 // актуальный
232 ),
233 'LIVESTATUS' => array(
234 1 // жив!
235 ),
236 'CURRSTATUS' => array(
237 0, // актуальный
238 51, // переподчинённый
239 )
240 );
241
242 private $filePools = array(
243
244 'ukrain_kazakhstan' => array(
245 'DIR' => 'ukrain_kazakhstan/'
246 ),
247
248 // where we store clean and split fias data:
249 'fias_tree' => array(
250 'DIR' => 'fias_tree/'
251 ),
252
253 // where we keep maps from yandex to fias (REGIONS, CITIES and VILLAGES)
254 'fias_yamarket_links' => array(
255 'DIR' => 'fias_yamarket_links/'
256 ),
257
258 // where we keep result data
259 'assets' => array(
260 'DIR' => 'compiled/bundles/extended/'
261 ),
262 // where we keep result data, only for russia
263 'assets_standard' => array(
264 'DIR' => 'compiled/bundles/standard/'
265 ),
266
267 // where we keep result data
268 'demo' => array(
269 'DIR' => 'demo/'
270 ),
271 );
272
273 private $workDir = '';
274 private $grabbedStuffDir = '';
275
276 private $yaIdType = array();
277 private $relations = array();
278
279 private $options = array();
280
281 // tree builder
282 private $data = array();
283
284 private $optionConvertNames = false;
285 private $sysMaps = array();
286
287 private $fiasCPath = array();
288
289 private $fiasDB = null;
290 private $eTreeDB = null;
291 private $eTreeDBRussia = null;
292
293 public function __construct($options)
294 {
295 $this->workDir = $options['workDir'];
296 $this->grabbedStuffDir = $options['grabbedStuffDir'];
297
298 $this->options = $options;
299
300 //if(!file_exists($_SERVER['DOCUMENT_ROOT'].$this->workDir.self::OUTPUT_DIR))
301 // mkdir($_SERVER['DOCUMENT_ROOT'].$this->workDir.self::OUTPUT_DIR, 0700, true);
302
303 foreach($this->typeGroups as $id => &$params)
304 $params['I_TYPES'] = array_flip($params['TYPES']);
305
306 foreach($this->fiasToBaseType as $type => $fTypes)
307 {
308 foreach($fTypes as $fType => $fReplace)
309 {
310 if(strlen($fType) && !empty($fReplace))
311 {
312 $this->sysMaps['FIAS2BASETYPE'][$fType] = $type;
313 $this->sysMaps['FIASTYPEREPLACE'][$fType] = $fReplace['R'];
314 }
315 }
316 }
317
318 foreach($this->typeGroups as $groupId => $group)
319 {
320 //$this->output($group);
321
322 foreach($group['TYPES'] as $type)
323 {
324 $this->sysMaps['BASETYPE2GROUP'][$type] = $groupId;
325 }
326 }
327
328 $this->cleanOutput();
329 }
330
331 public function compile()
332 {
333 // step 1: build main tree from yandex market data
334 //$this->buildMainTree();
335
336 ##########################################################
337 #### MAP FIAS TO YANDEX
338 ##########################################################
339
340 // step 2: processing huge fias file
341 //$this->splitFiasOnRegions(); // split huge fias file onto small pieces of bundles
342 /*
343 Handwriting:
344 move 0c5b2444-70a0-4932-980c-b4dc0d3f02b5;1;1;Москва;г; TO 29251dcf-00a1-4e34-98d4-5c47484a36d4.csv
345 move c2deb16a-0330-4f05-821f-1d09c93331e6;1;1;Санкт-Петербург;г;190000 TO 6d1ebb35-70c6-4129-bd55-da3969658f5d.csv
346 move 6fdecb78-893a-4e3f-a5ba-aa062459463b;1;1;Севастополь;г; TO bd8e6511-e4b9-4841-90de-6bbc231a789e.csv
347 */
348 //$this->copyFias2DB(); // place fias to db
349
350 // step 3: map fias to yandex id. There were some handwriting to map files, so do not uncomment unless you want files to be overwritten
351 //$this->mapFiasRootV2(); // process fias root and find matches by regions
352 // then we have a little handwriting on rootv2.csv
353 //$this->mapFiasCities(); // find cities and villages matches
354 // again, handwriting here
355
356 ##########################################################
357 #### FIAS 2 DB
358 ##########################################################
359
360 /*
361 $this->copyFias2DB();
362
363 update b_tmp_fias set PARENTGUID = '29251dcf-00a1-4e34-98d4-5c47484a36d4' where AOGUID = '0c5b2444-70a0-4932-980c-b4dc0d3f02b5' and AOID = '5c8b06f1-518e-496e-b683-7bf917e0d70b';
364 update b_tmp_fias set PARENTGUID = '6d1ebb35-70c6-4129-bd55-da3969658f5d' where AOGUID = 'c2deb16a-0330-4f05-821f-1d09c93331e6' and AOID = 'aad1469e-54ff-4605-af4f-f016c75b84d2';
365 update b_tmp_fias set PARENTGUID = 'bd8e6511-e4b9-4841-90de-6bbc231a789e' where AOGUID = '6fdecb78-893a-4e3f-a5ba-aa062459463b' and AOID = '6fdecb78-893a-4e3f-a5ba-aa062459463b';
366 */
367
368 ##########################################################
369 #### MAKE EXPORT TABLE
370 ##########################################################
371
372 /*
373 $res = YandexGeoCoder::query(array(
374 'query' => 'Ненецкий автономный округ Шойна село Школьная улица',
375 'kind' => YandexGeoCoder::KIND_STREET
376 ));
377 */
378
379 $this->output('Build main tree');
380 $this->buildMainTree();
381
382 $this->createExportTables();
383
384 /*
385 ###################################################################
386 ###################################################################
387 ###################################################################
388
389 // making world
390 $this->eTreeDB->cleanup();
391 $this->eTreeDB->dropIndexes();
392
393 $this->output('Generate export tree: Belarus');
394 $this->generateExportTreeBelorussia();
395
396 $this->output('Generate export tree: Kazakhstan');
397 $this->generateExportTreeLegacy(self::KAZAKHSTAN_SOURCE);
398
399 $this->output('Generate export tree: Ukrain');
400 $this->generateExportTreeUkrain();
401
402 $this->output('Generate export tree: USA');
403 $this->generateExportTreeUSA();
404
405 $this->output('Generate export tree: World Countries');
406 $this->generateExportTreeWorld();
407
408 $this->output('Generate export tree: EX-CIS');
409 $this->generateExportTreeLegacy(self::CIS_SOURCE);
410
411 ###################################################################
412 ###################################################################
413 ###################################################################
414
415 $this->output('Last occupied: '.$this->eTreeDB->getLastOccupiedCode());
416 $this->output('Next free: '.$this->eTreeDB->getNextFreeCode());
417
418 // making russia
419 $this->eTreeDBRussia->cleanup();
420 $this->eTreeDBRussia->dropIndexes();
421
422 $this->output('Generate export tree: Russia');
423 $this->generateExportTreeRussia();
424
425 $this->output('Last occupied: '.$this->eTreeDBRussia->getLastOccupiedCode());
426 $this->output('Next free: '.$this->eTreeDBRussia->getNextFreeCode());
427
428 ###################################################################
429 ###################################################################
430 ###################################################################
431 */
432
433 $this->restoreExportTablesIndexes();
434
435 $this->output('Build export files');
436
437 /*
438 $this->cleanPoolDir('assets');
439
440 $this->eTreeDB->walkInDeep(array($this, 'generateExportFilesFromTableBundle')); // world
441 $this->eTreeDBRussia->walkInDeep(array($this, 'generateExportFilesFromTableBundle')); // russia
442 */
443
444 $this->cleanPoolDir('assets_standard');
445 $this->eTreeDB->walkInDeep(array(
446 'ITEM' => array($this, 'generateExportFilesFromTableBundle_Standard')
447 )); // world
448 $this->eTreeDBRussia->walkInDeep(array(
449 'ITEM' => array($this, 'generateExportFilesFromTableBundle_Standard_YandexOnly')
450 )); // russia
451
452 /*
453 // types by groups
454 $this->makeTypeGroupFile(self::GROUP_FILE);
455
456 $this->copyStaticCSV();
457 */
458
459 ###################################################################
460 ###################################################################
461 ###################################################################
462
463 /*
464 $this->output('Build demo files');
465
466 $this->cleanPoolDir('demo');
467
468 $this->eTreeDB->walkInDeep(array($this, 'generateDemoFilesWorld'), array('VILLAGE' => 1)); // world
469 $this->eTreeDBRussia->walkInDeep(array($this, 'generateDemoFilesRussia'), array('VILLAGE' => 1)); // world
470 */
471
472 /*
473 добавить сюда генерацию файла country_codes.php с содержимым:
474
475 <?
476 $LOCALIZATION_COUNTRY_CODE_MAP = array(
477 'ru' => '0000028023',
478 'ua' => '0000000364',
479 'kz' => '0000000276',
480 'bl' => '0000000001'
481 );
482
483 этот файл потом идёт в мастер установки интернет-магазина, вместе с демо-данными, types.csv и externalservice.csv
484
485 */
486
487 $this->output('DONE');
488 }
489
490 #######################################################
491 ### ABOUT EXPORT TABLE
492 #######################################################
493
494 private $allowedForDemo = array('COUNTRY' => 1, 'COUNTRY_DISTRICT' => 1, 'REGION' => 1, 'SUBREGION' => 1, 'CITY' => 1);
495 private $demoCategory = false;
496
497 public function generateDemoFilesWorld($item, $table)
498 {
499 if(!isset($this->allowedForDemo[$item['TYPE_CODE']]))
500 return;
501
502 if($item['TYPE_CODE'] == 'COUNTRY')
503 {
504 $this->addItemToCSV('world', 'demo', $item);
505
506 // this part must not depend on codes, which may flow left and right. in future we may add
507 // some markers like "is_ukrain" or "is_russia" etc to database instead of relying on names
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';
516 else
517 $this->demoCategory = false;
518 }
519
520 //$this->output($table->getWalkPathString());
521 //$this->output($this->demoCategory);
522
523 if($this->demoCategory !== false)
524 $this->addItemToCSV($this->demoCategory, 'demo', $item);
525 }
526
527 public function generateDemoFilesRussia($item, $table)
528 {
529 if(!isset($this->allowedForDemo[$item['TYPE_CODE']]))
530 return;
531
532 if($item['TYPE_CODE'] == 'COUNTRY')
533 $this->addItemToCSV('world', 'demo', $item);
534
535 $this->addItemToCSV('russia', 'demo', $item);//done
536 }
537
538 private function createExportTables()
539 {
540 $this->eTreeDB = new Db\ExportTreeTable();
541 $this->eTreeDB->create();
542
543 $this->eTreeDBRussia = new Db\ExportTreeRussiaTable();
544 $this->eTreeDBRussia->create();
545 }
546
547 private function cleanUpExportTables()
548 {
549 $this->eTreeDB->cleanup();
550 $this->eTreeDB->dropIndexes();
551
552 $this->eTreeDBRussia->cleanup();
553 $this->eTreeDBRussia->dropIndexes();
554 }
555
556 private function restoreExportTablesIndexes()
557 {
558 $this->eTreeDB->restoreIndexes();
559 $this->eTreeDBRussia->restoreIndexes();
560 }
561
562 private function copyStaticCSV()
563 {
564 $workDir = $_SERVER['DOCUMENT_ROOT'].'/'.$this->workDir;
565
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);
568 }
569
570 private $currentParentGroup = '';
571
572 private function addItemToCSV($fName, $group, $item)
573 {
574 $data = array(
575 'CODE' => $item['CODE'],
576 'PARENT_CODE' => $item['PARENT_CODE'],
577 'TYPE_CODE' => $item['TYPE_CODE']
578 );
579
580 $data['NAME.RU.NAME'] = '';
581 $data['NAME.EN.NAME'] = '';
582 $data['NAME.UA.NAME'] = '';
583
584 $name = unserialize($item['LANGNAMES']);
585 foreach($name as $lid => $values)
586 {
587 foreach($values as $i => $val)
588 $data['NAME.'.$lid.'.'.$i] = $val;
589 }
590
591 $data['EXT.YAMARKET.0'] = '';
592 $data['EXT.ZIP.0'] = '';
593
594 $externals = unserialize($item['EXTERNALS']);
595 if(!empty($externals))
596 {
597 foreach($externals as $type => $values)
598 {
599 if(is_array($values))
600 {
601 foreach($values as $i => $val)
602 $data['EXT.'.$type.'.'.$i] = $val;
603 }
604 }
605 }
606
607 $data['LONGITUDE'] = $item['LONGITUDE'];
608 $data['LATITUDE'] = $item['LATITUDE'];
609
610 /*
611 $this->output($data);
612 $this->output($group);
613 $this->output($fName);
614 */
615
616 $this->putToFile2(
617 $data,
618 $group,
619 $fName,
620 true
621 );
622 }
623
624 public function generateExportFilesFromTableBundle($item, $table)
625 {
626 if(in_array($item['TYPE_CODE'], $this->typeGroups['LAYOUT']['TYPES']))
627 $this->currentParentGroup = $item['CODE'];
628
629 ########################################################
630 ########################################################
631 ########################################################
632
633 $cat = $this->sysMaps['BASETYPE2GROUP'][$item['TYPE_CODE']];
634 $fName = $this->typeGroups[$cat]['FILE_NAME_TEMPLATE'];
635
636 $fName = str_replace(array(
637 '%BASE_PARENT_ITEM_CODE%',
638 '%CODE%',
639 '.csv'
640 ), array(
641 $cat == 'LAYOUT' ? '' : $this->currentParentGroup,
642 ToLower($cat),
643 ''
644 ), $fName);
645
646 $this->addItemToCSV($fName, 'assets', $item);
647
648 ########################################################
649 ########################################################
650 ########################################################
651 }
652
653 public function generateExportFilesFromTableBundle_Standard($item, $table)
654 {
655 if(in_array($item['TYPE_CODE'], $this->typeGroups['LAYOUT']['TYPES']))
656 $this->currentParentGroup = $item['CODE'];
657
658 ########################################################
659 ########################################################
660 ########################################################
661
662 $cat = $this->sysMaps['BASETYPE2GROUP'][$item['TYPE_CODE']];
663 $fName = $this->typeGroups[$cat]['FILE_NAME_TEMPLATE'];
664
665 $fName = str_replace(array(
666 '%BASE_PARENT_ITEM_CODE%',
667 '%CODE%',
668 '.csv'
669 ), array(
670 $cat == 'LAYOUT' ? '' : $this->currentParentGroup,
671 ToLower($cat),
672 ''
673 ), $fName);
674
675 $this->addItemToCSV($fName, 'assets_standard', $item);
676
677 ########################################################
678 ########################################################
679 ########################################################
680 }
681
683 {
684 if(in_array($item['TYPE_CODE'], $this->typeGroups['LAYOUT']['TYPES']))
685 $this->currentParentGroup = $item['CODE'];
686
687 ########################################################
688 ########################################################
689 ########################################################
690
691 if($item['TYPE_CODE'] == 'VILLAGE' && strpos($item['EXTERNALS'], 'YAMARKET') === false/*not from yandex database*/)
692 {
693 //$this->output($item['NAME'].' skipped');
694 return false;
695 }
696
697 $cat = $this->sysMaps['BASETYPE2GROUP'][$item['TYPE_CODE']];
698 $fName = $this->typeGroups[$cat]['FILE_NAME_TEMPLATE'];
699
700 $fName = str_replace(array(
701 '%BASE_PARENT_ITEM_CODE%',
702 '%CODE%',
703 '.csv'
704 ), array(
705 $cat == 'LAYOUT' ? '' : $this->currentParentGroup,
706 ToLower($cat),
707 ''
708 ), $fName);
709
710 $this->addItemToCSV($fName, 'assets_standard', $item);
711
712 ########################################################
713 ########################################################
714 ########################################################
715
716 return true;
717 }
718
719 private function generateExportTreeRussia()
720 {
721 $this->fiasDB = new Db\FiasTable();
722
723 $this->eTreeDBRussia->dropCodeIndex();
724 $this->eTreeDBRussia->setExportOffset(intval($this->eTreeDB->getNextFreeCode())); // start where the previous table ended
725
726 // get yandex regions
727 $regions = $this->readFiasRootMapV2();
728
729 // add Russia (country), districts and regions, that are taken from yandex
730 $this->generateExportTreePutRussiaBundle(array(self::RUSSIA_YANDEX_CODE), $regions, 0);
731
732 // add all precious content from fias: subregions, cities, villages, streets
733 $this->generateExportTreePutRussiaInner();
734
735 $this->eTreeDBRussia->doneInsert();
736 $this->eTreeDBRussia->switchIndexes(true);
737 }
738
739 private function getYandexToFiasCityMap($yandexRegionId)
740 {
741 $result = array();
742 $fias2yandex = $this->getDataFromCSV('fias_yamarket_links', 'region_'.$yandexRegionId);
743 foreach($fias2yandex as $map)
744 {
745 unset($map['HZ']); // csv viewer would crash without this key (wonder why)
746 $result[$map['AOGUID']] = $map;
747 }
748
749 return $result;
750 }
751
752 private function generateExportTreePutRussiaInner()
753 {
754 // get yandex-to-fias region code map
755 $links = $this->getFias2YamarketRootLinks(false, true);
756
757 $i = -1;
758 // for each region we must dump its content
759 // $yRId is a yandex id for the target region
760 // $fiasRegions is one (mostly) or several corresponding "regions" from fias
761 foreach($links as $yRId => $fiasRegions)
762 {
763 $i++;
764
765 // get yandex-to-fias city code map for the current region
766 $this->fias2yandexCityMap = $this->getYandexToFiasCityMap($yRId);
767 $this->currentRegion = $this->mapETCodeAsYandex($yRId);
768
769 $this->eTreeDBRussia->dropCodeIndex(); // drop previous region index
770
771 foreach($fiasRegions as $regionGuid)
772 {
773 $this->fiasPath = array();
774 $this->generateExportTreePutRussiaInnerBundle($regionGuid);
775 }
776
777 //break;
778 }
779 }
780
781 private function checkIsAllowedCityVillage($item)
782 {
783 $baseType = $this->sysMaps['FIAS2BASETYPE'][$item['SHORTNAME']];
784
785 //if($baseType == 'CITY' || $baseType == 'VILLAGE')
786 // $this->output('Doubtfull city\village: '.$item['FORMALNAME'].' ('.$item['SHORTNAME'].')');
787
788 $skip = array('5544bf6a-0ec1-4b5f-bbc5-49294f71de16'/*тягловая подстанция*/, '22a77f13-3764-41dc-aa23-db680b03ef5d'/*6 км АЗС*/, '3f2ab130-274e-4fd6-b611-a94467b04f57'/*Велтон Парк duplicate*/, '762758bb-18b9-440f-bc61-8e1e77ff3fd8', /*Московский посёлок, not exists*/);
789
790 return ($baseType == 'CITY' || $baseType == 'VILLAGE') &&
791 (
792 $this->fiasToBaseType[$baseType][$item['SHORTNAME']]['U'] /*code is in a list of allowed types for export*/
793 ||
794 isset($this->fias2yandexCityMap[$item['AOGUID']] /*code is present in yandex2fias city map*/
795 ) &&
796 !in_array($item['AOGUID'], $skip) // not one of those forbidden broken items
797 );
798 }
799
800 private function checkIsAllowedStreet($item)
801 {
802 $baseType = $this->sysMaps['FIAS2BASETYPE'][$item['SHORTNAME']];
803
804 return ($baseType == 'STREET' && $this->fiasToBaseType[$baseType][$item['SHORTNAME']]['U']); /*street code is in a list of allowed types for export*/
805 }
806
808 {
809 /*
810 $object = $path[count($path) - 1];
811 if($object['AOGUID'] == 'da99f366-1a88-43b1-9aa8-c1b66334c97f')
812 {
813 $found = true;
814
815 \_print_r('Wow: da99f366-1a88-43b1-9aa8-c1b66334c97f');
816 \_print_r($object);
817 }
818 */
819
820 //$path = array_reverse($path);
821
822 $newPath = array();
823 $lastValidId = false;
824 $neepPasteLastValid = false;
825 foreach($path as $item)
826 {
827 if(isset($this->forbiddenPathTypes[$item['SHORTNAME']]) || isset($this->forbiddenPathIds[$item['AOGUID']]) || $this->checkIsAllowedStreet($item['SHORTNAME']))
828 {
829 $neepPasteLastValid = true;
830 continue;
831 }
832 else
833 {
834 if($lastValidId !== false && $neepPasteLastValid)
835 {
836 $item['PARENTGUID'] = $lastValidId;
837 $neepPasteLastValid = false;
838 }
839
840 $lastValidId = $item['AOGUID'];
841 }
842
843 $newPath[] = $item;
844 }
845
846 /*
847 if($found)
848 {
849 \_print_r('Path is now:');
850 \_print_r($newPath);
851 die();
852 }
853 */
854
855 return $newPath;
856 }
857
858 private function generateExportTreePutRussiaFiasPath($targetItem)
859 {
860 // pre-process, cut off unwanted types (actually, streets)
861 $newPath = $this->generateExportTreePutRussiaFiasPathCutForbidden($this->fiasPath);
862
863 $i = -1;
864 foreach($newPath as $item)
865 {
866 $i++;
867
868 // external data
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'];
874
875 // type and name
876 $itemType = $item['SHORTNAME'];
877 $baseType = $this->sysMaps['FIAS2BASETYPE'][$itemType];
878 $typeNameReplace = $baseType != 'CITY' ? $this->sysMaps['FIASTYPEREPLACE'][$itemType] : ''; // replace base type (e.g. "п" => "посёлок", "д" => "деревня", ...)
879 $name = trim($item['FORMALNAME']).(strlen($typeNameReplace) ? ' '.$typeNameReplace : '');
880
881 $this->eTreeDBRussia->insert(array(
882 'TYPE_CODE' => $baseType,
883 'FIAS_TYPE' => $itemType,
884 'NAME' => $name,
885 'LANGNAMES' => array('RU' => array('NAME' => $name)),
886 'EXTERNALS' => $externals,
887 'SOURCE' => self::SOURCE_FIAS,
888
889 'SYS_CODE' => $this->mapETCodeAsFias($item['AOGUID']),
890 'PARENT_SYS_CODE' => $i ? $this->mapETCodeAsFias($item['PARENTGUID']) : $this->currentRegion
891 ));
892 }
893 }
894
895 private function generateExportTreePutRussiaStreets($parentGuid)
896 {
897 if(!strlen($parentGuid))
898 return;
899
900 $res = $this->fiasDB->getActualChildren($parentGuid);
901 while($item = $res->fetch())
902 {
903 $itemType = $item['SHORTNAME'];
904 if($this->checkIsAllowedStreet($item))
905 {
906 $externals = array();
907 if(strlen($item['POSTALCODE']))
908 $externals['ZIP'][] = $item['POSTALCODE'];
909
910 $baseType = $this->sysMaps['FIAS2BASETYPE'][$itemType];
911 $name = trim($item['FORMALNAME']).' '.$this->sysMaps['FIASTYPEREPLACE'][$itemType];
912
913 $this->eTreeDBRussia->insert(array(
914 'TYPE_CODE' => $baseType,
915 'FIAS_TYPE' => $itemType,
916 'NAME' => $name,
917 'LANGNAMES' => array('RU' => array('NAME' => $name)),
918 'EXTERNALS' => $externals,
919 'SOURCE' => self::SOURCE_FIAS,
920
921 'SYS_CODE' => $this->mapETCodeAsFias($item['AOGUID']),
922 'PARENT_SYS_CODE' => $this->mapETCodeAsFias($parentGuid),
923 ));
924 }
925 }
926 }
927
928 private function generateExportTreePutRussiaInnerBundle($parentGuid)
929 {
930 if(!strlen($parentGuid))
931 return;
932
933 $res = $this->fiasDB->getActualChildren($parentGuid);
934 while($item = $res->fetch())
935 {
936 $item['PARENTGUID'] = $parentGuid;
937 array_push($this->fiasPath, $item);
938
939 if($this->checkIsAllowedCityVillage($item)) // check if this is a village or city or what else we should add to export
940 {
941 //$this->output('Allowed city\village '.$item['FORMALNAME']);
942
943 $this->generateExportTreePutRussiaFiasPath($item); // ALSO store intermediate locations from current region-to-city(village, etc) being stored
944 $this->generateExportTreePutRussiaStreets($item['AOGUID']); // store all streets of current village\city\...
945 }
946
947 $this->generateExportTreePutRussiaInnerBundle($item['AOGUID']);
948
949 array_pop($this->fiasPath);
950 }
951
952 }
953
954 private function generateExportTreePutRussiaBundle($bundle, $regions, $dl = 0)
955 {
956 foreach($bundle as $id)
957 {
958 $node = $this->data['TREES']['MAIN']['NODES'][$id];
959
960 $edges = array();
961 if(isset($this->data['TREES']['MAIN']['EDGES'][$id]))
962 $edges = $this->data['TREES']['MAIN']['EDGES'][$id];
963
964 if(in_array($node['TYPE_CODE'], array('COUNTRY', 'COUNTRY_DISTRICT', 'REGION')))
965 {
966 if($node['TYPE_CODE'] == 'REGION')
967 {
968 // get fias code & postal code, if any
969 $fNode = $this->fiasDB->getByAOGUID($regions[$node['ID']]['AOGUID']);
970 if(strlen($fNode['POSTALCODE']))
971 $node['EXT']['ZIP'][] = $fNode['POSTALCODE'];
972
973 $edges = array(); // no way farther
974 }
975
976 // set english name for Russia
977 if($node['TYPE_CODE'] == 'COUNTRY')
978 $node['NAME']['EN']['NAME'] = 'Russian Federation';
979
980 if($node['NAME']['RU']['NAME'] == 'Москва и Московская область')
981 $node['NAME']['RU']['NAME'] = 'Московская область';
982
983 if($node['NAME']['RU']['NAME'] == 'Санкт-Петербург и Ленинградская область')
984 $node['NAME']['RU']['NAME'] = 'Ленинградская область';
985
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,
992
993 'SYS_CODE' => $this->mapETCodeAsYandex($node['ID']),
994 'PARENT_SYS_CODE' => strlen($node['PARENT_ID']) && $dl > 0 ? $this->mapETCodeAsYandex($node['PARENT_ID']) : ''
995 ));
996
997 if(!empty($edges))
998 $this->generateExportTreePutRussiaBundle($edges, $regions, $dl+1);
999 }
1000 }
1001 }
1002
1003 #########################
1004
1005 private function generateExportTreeWorld()
1006 {
1007 $this->eTreeDB->dropCodeIndex();
1008 $this->eTreeDB->restoreExportOffset();
1009
1010 $this->eTreeDB->switchIndexes(false);
1011
1012 $csv = new Import\CSVReader();
1013 $csv->loadFile($_SERVER['DOCUMENT_ROOT'].'/locations_data/'.self::WORLD_SOURCE);
1014
1015 $countries = array();
1016
1017 while($item = $csv->Fetch())
1018 {
1019 $item = explode(',', $item[0]);
1020
1021 if(!isset($item[1])) // its a language marker
1022 continue;
1023
1024 // exclude the following countries, kz we got an extended file for them
1025 if(in_array($item[2], array('USA', 'Kazakhstan', 'Ukraine', 'Byelorussia', 'Russian Federation', 'Azerbaijan', 'Estonia', 'Georgia', 'Latvia', 'Lithuania', 'Moldavia', 'Turkmenistan', 'Armenia', 'Tadjikistan', 'Uzbekistan')))
1026 continue;
1027
1028 $id = implode(':', $item);
1029
1030 $countries[] = $item[2].' - '.$item[4];
1031
1032 $this->eTreeDB->insert(array(
1033 'TYPE_CODE' => 'COUNTRY',
1034 'NAME' => $item[4],
1035 'LANGNAMES' => serialize(array(
1036 'RU' => array('NAME' => $item[4]),
1037 'EN' => array('NAME' => $item[2])
1038 )),
1039 'EXTERNALS' => '',
1040 'SOURCE' => self::SOURCE_LEGACY,
1041
1042 'SYS_CODE' => $this->mapETCodeAsLegacy($id),
1043 'PARENT_SYS_CODE' => ''
1044 ));
1045 }
1046
1047 $this->eTreeDB->doneInsert();
1048 $this->eTreeDB->switchIndexes(true);
1049 }
1050
1051 #########################
1052
1053 private function generateExportTreeLegacy($source)
1054 {
1055 $this->eTreeDB->dropCodeIndex();
1056 $this->eTreeDB->restoreExportOffset();
1057
1058 $this->eTreeDB->switchIndexes(false);
1059
1060 $csv = new Import\CSVReader();
1061 $csv->loadFile($_SERVER['DOCUMENT_ROOT'].'/locations_data/'.$source);
1062
1063 $lastOnes = array();
1064
1065 while($item = $csv->Fetch())
1066 {
1067 $item = explode(',', $item[0]);
1068
1069 if(!isset($item[1])) // its a language marker
1070 continue;
1071
1072 if($item[0] == 'R')
1073 {
1074 $item[2] = preg_replace('# obl$#', ' region', $item[2]);
1075 $item[4] = preg_replace('# обл$#', ' область', $item[4]);
1076 }
1077
1078 $parentId = '';
1079
1080 if($item[0] == 'S')
1081 $type = 'COUNTRY';
1082 if($item[0] == 'R')
1083 $type = 'REGION';
1084 if($item[0] == 'T')
1085 $type = 'CITY';
1086
1087 $id = implode(':', $item);
1088
1089 if($type == 'REGION')
1090 $parentId = $lastOnes['COUNTRY'];
1091 elseif($type == 'CITY')
1092 $parentId = $lastOnes['PARENT'];
1093 else
1094 $parentId = '';
1095
1096 if($type != 'CITY')
1097 {
1098 $lastOnes[$type] = $id;
1099 $lastOnes['PARENT'] = $id;
1100 }
1101
1102 $this->eTreeDB->insert(array(
1103 'TYPE_CODE' => $type,
1104 'NAME' => $item[4],
1105 'LANGNAMES' => serialize(array(
1106 'RU' => array('NAME' => $item[4]),
1107 'EN' => array('NAME' => $item[2])
1108 )),
1109 'EXTERNALS' => '',
1110 'SOURCE' => self::SOURCE_LEGACY,
1111
1112 'SYS_CODE' => $this->mapETCodeAsLegacy($id),
1113 'PARENT_SYS_CODE' => strlen($parentId) ? $this->mapETCodeAsLegacy($parentId) : ''
1114 ));
1115 }
1116
1117 $this->eTreeDB->doneInsert();
1118 $this->eTreeDB->switchIndexes(true);
1119 }
1120
1121 #########################
1122
1123 private function generateExportTreeUSA()
1124 {
1125 $this->eTreeDB->dropCodeIndex();
1126 $this->eTreeDB->restoreExportOffset();
1127
1128 $this->eTreeDB->switchIndexes(false);
1129
1130 $csv = new Import\CSVReader();
1131 $csv->loadFile($_SERVER['DOCUMENT_ROOT'].'/locations_data/'.self::USA_SOURCE);
1132
1133 $lastOnes = array();
1134
1135 while($item = $csv->Fetch())
1136 {
1137 $item = explode(',', $item[0]);
1138
1139 if(!isset($item[1])) // its a language marker
1140 continue;
1141
1142 $parentId = '';
1143
1144 if($item[0] == 'S')
1145 $type = 'COUNTRY';
1146 if($item[0] == 'R')
1147 $type = 'REGION';
1148 if($item[0] == 'T')
1149 $type = 'CITY';
1150
1151 $id = implode(':', $item);
1152
1153 if($type == 'REGION')
1154 $parentId = $lastOnes['COUNTRY'];
1155 elseif($type == 'CITY')
1156 $parentId = $lastOnes['PARENT'];
1157 else
1158 $parentId = '';
1159
1160 if($type != 'CITY')
1161 {
1162 $lastOnes[$type] = $id;
1163 $lastOnes['PARENT'] = $id;
1164 }
1165
1166 if($item['2'] == 'USA')
1167 $item['4'] = 'США';
1168
1169 $this->eTreeDB->insert(array(
1170 'TYPE_CODE' => $type,
1171 'NAME' => $item[4],
1172 'LANGNAMES' => serialize(array(
1173 'RU' => array('NAME' => $item[4]),
1174 'EN' => array('NAME' => $item[2])
1175 )),
1176 'EXTERNALS' => '',
1177 'SOURCE' => self::SOURCE_LEGACY,
1178
1179 'SYS_CODE' => $this->mapETCodeAsLegacy($id),
1180 'PARENT_SYS_CODE' => strlen($parentId) ? $this->mapETCodeAsLegacy($parentId) : ''
1181 ));
1182 }
1183
1184 $this->eTreeDB->doneInsert();
1185 $this->eTreeDB->switchIndexes(true);
1186 }
1187
1188 #########################
1189
1190 private function generateExportTreeBelorussia()
1191 {
1192 $this->eTreeDB->dropCodeIndex();
1193 $this->eTreeDB->restoreExportOffset();
1194
1195 $this->eTreeDB->switchIndexes(false);
1196
1197 $this->generateExportTreePutBelorussiaBundle(array(self::BELORUSSIA_YANDEX_CODE));
1198
1199 $this->eTreeDB->doneInsert();
1200 $this->eTreeDB->switchIndexes(true);
1201 }
1202
1203 private function generateExportTreePutBelorussiaBundle($bundle)
1204 {
1205 foreach($bundle as $id)
1206 {
1207 $node = $this->data['TREES']['MAIN']['NODES'][$id];
1208
1209 $edges = array();
1210 if(isset($this->data['TREES']['MAIN']['EDGES'][$id]))
1211 $edges = $this->data['TREES']['MAIN']['EDGES'][$id];
1212
1213 // attach to belorussia its en-name
1214 if($node['TYPE_CODE'] == 'COUNTRY')
1215 $node['NAME']['EN']['NAME'] = 'Belarus';
1216
1217 // these two types are not allowed currently, because we do not have the corresponding types in fias
1218 if($node['TYPE_CODE'] == 'METRO_STATION' || $node['TYPE_CODE'] == 'CITY_DISTRICT')
1219 continue;
1220
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,
1227
1228 'SYS_CODE' => $this->mapETCodeAsYandex($node['ID']),
1229 'PARENT_SYS_CODE' => strlen($node['PARENT_ID']) ? $this->mapETCodeAsYandex($node['PARENT_ID']) : ''
1230 ));
1231
1232 if(!empty($edges))
1233 $this->generateExportTreePutBelorussiaBundle($edges);
1234 }
1235 }
1236
1237 #########################
1238
1239 private function generateExportTreeUkrain()
1240 {
1241 $this->eTreeDB->dropCodeIndex();
1242 $this->eTreeDB->restoreExportOffset();
1243
1244 $cd2r = $this->getDataFromCSV('ukrain_kazakhstan', 'ukrain_district2region');
1245
1246 $tree = array();
1247
1248 $tree['NODES'][self::UKRAIN_YANDEX_CODE] = array(
1249 'NAME' => array(
1250 'RU' => array('NAME' => 'Украина'),
1251 'UA' => array('NAME' => 'Україна'),
1252 'EN' => array('NAME' => 'Ukraine')
1253 ),
1254 'TYPE_CODE' => 'COUNTRY',
1255 'SOURCE' => self::SOURCE_YANDEX,
1256 'ID' => self::UKRAIN_YANDEX_CODE,
1257 'EXT' => array(
1258 'YAMARKET' => array(
1259 self::UKRAIN_YANDEX_CODE
1260 )
1261 )
1262 );
1263
1264 foreach($cd2r as $line)
1265 {
1266 // add country district
1267 if(!isset($tree['NODES'][$line['CDID']]))
1268 {
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,
1275 'EXT' => array(
1276 'YAMARKET' => array(
1277 $line['CDID'] // country district id in file
1278 ),
1279 )
1280 );
1281 }
1282
1283 $tree['EDGES'][self::UKRAIN_YANDEX_CODE][$line['CDID']] = true;
1284
1285 $regionId = 'r'.md5($line['RNAME']['UA']['NAME']);
1286
1287 if($line['RNAME']['UA']['NAME'] == 'Севастополь, Місто' || $line['RNAME']['UA']['NAME'] == 'Автономна Республіка Крим')
1288 $source = self::SOURCE_UKRAIN;
1289 else
1290 $source = self::SOURCE_YANDEX;
1291
1292 if($line['RNAME']['UA']['NAME'] == 'Севастополь, Місто')
1293 {
1294 $typeCode = 'SUBREGION';
1295 }
1296 else
1297 {
1298 $typeCode = 'REGION';
1299 }
1300
1301 // add region
1302 if(!isset($tree['NODES'][$regionId]))
1303 {
1304 $tree['NODES'][$regionId] = array(
1305 'NAME' => $line['RNAME'],
1306 'TYPE_CODE' => $typeCode,
1307 'SOURCE' => $source,
1308 'ID' => $regionId,
1309 'PARENT_ID' => $line['CDID'],
1310 );
1311
1312 if($source == self::SOURCE_YANDEX)
1313 $tree['NODES'][$regionId]['EXT']['YAMARKET'][] = $line['RID'];
1314 }
1315
1316 $tree['EDGES'][$line['CDID']][$regionId] = true;
1317 }
1318
1319 $res = $this->getDataFromCSV('ukrain_kazakhstan', 'ukrain');
1320
1321 foreach($res as $line)
1322 {
1323 if($line['REGION'] == 'Автономна республіка Крим')
1324 $line['REGION'] = 'Автономна Республіка Крим';
1325
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']);
1329
1330 $regionId = 'r'.md5($line['REGION']);
1331 $subRegionId = 'sr'.md5($line['SUBREGION']);
1332 $cityId = 'c'.md5($line['CITY']);
1333
1334 if($line['REGION'] != 'Севастополь, Місто')
1335 {
1336 if(!isset($tree['NODES'][$subRegionId]))
1337 {
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,
1344 'EXT' => array()
1345 );
1346 if(!isset($tree['EDGES'][$regionId][$subRegionId]))
1347 $tree['EDGES'][$regionId][$subRegionId] = true;
1348 }
1349 }
1350
1351 if(!isset($tree['NODES'][$cityId]))
1352 {
1353 $tree['NODES'][$cityId] = array(
1354 'NAME' => array('UA' => array('NAME' => $line['CITY'])),
1355 'TYPE_CODE' => 'CITY',
1356 'SOURCE' => self::SOURCE_UKRAIN,
1357 'ID' => $cityId,
1358 'PARENT_ID' => $subRegionId,
1359 'EXT' => array()
1360 );
1361 if(!isset($tree['EDGES'][$subRegionId][$cityId]))
1362 $tree['EDGES'][$subRegionId][$cityId] = true;
1363 }
1364 }
1365
1366 foreach($tree['EDGES'] as $k => $edges)
1367 $tree['EDGES'][$k] = array_keys($edges);
1368
1369 $this->data['TREES']['UKRAIN'] = $tree;
1370
1371 $this->generateExportTreePutUkrainBundle(array(self::UKRAIN_YANDEX_CODE));
1372
1373 unset($this->data['TREES']['UKRAIN']);
1374
1375 $this->eTreeDB->doneInsert();
1376 }
1377
1378 private function generateExportTreePutUkrainBundle($bundle)
1379 {
1380 foreach($bundle as $id)
1381 {
1382 $node = $this->data['TREES']['UKRAIN']['NODES'][$id];
1383
1384 $edges = array();
1385 if(isset($this->data['TREES']['UKRAIN']['EDGES'][$id]))
1386 $edges = $this->data['TREES']['UKRAIN']['EDGES'][$id];
1387
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'],
1394
1395 'SYS_CODE' => $this->mapETCodeAsUkrainian($node['ID']),
1396 'PARENT_SYS_CODE' => strlen($node['PARENT_ID']) ? $this->mapETCodeAsUkrainian($node['PARENT_ID']) : ''
1397 ));
1398
1399 if(!empty($edges))
1400 $this->generateExportTreePutUkrainBundle($edges);
1401 }
1402 }
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416 private function mapETCodeAsYandex($code)
1417 {
1418 return 'Y_'.$code;
1419 }
1420
1421 private function mapETCodeAsFias($code)
1422 {
1423 return 'F_'.$code;
1424 }
1425
1426 private function mapETCodeAsUkrainian($name)
1427 {
1428 return 'U_'.md5($name);
1429 }
1430
1431 private function mapETCodeAsLegacy($name)
1432 {
1433 return 'L_'.md5($name);
1434 }
1435
1436 #######################################################
1437 ### ABOUT EXPORT TREE GENERATION
1438 #######################################################
1439
1440 private function mapETCodeBySource($value, $source)
1441 {
1442 if($source == self::SOURCE_YANDEX)
1443 return 'Y_'.$value;
1444 if($source == self::SOURCE_FIAS)
1445 return 'F_'.$value;
1446 if($source == self::SOURCE_UKRAIN)
1447 return 'U_'.md5($name);
1448 if($source == self::SOURCE_KAZAKHSTAN)
1449 return 'K_'.md5($name);
1450 }
1451
1452 private function startExportFromScratch()
1453 {
1454 $this->cleanTemporalData(self::TMP_DATA_RUS_EXPORT_INDEX);
1455 $this->cleanTemporalData(self::TMP_DATA_RUS_GLOBAL_INDEX);
1456
1457 $this->cleanPoolDir('assets');
1458 }
1459
1460 private function generateExportTreeRussiaRoot()
1461 {
1462 $this->restoreTDRusExpIndex();
1463
1464 if(!empty($this->alreadyDumped))
1465 return;
1466
1467 $regions = $this->readFiasRootMapV2();
1468 $this->generateExportTreePutRussiaBundleOld(array(self::RUSSIA_YANDEX_CODE), $regions, 0);
1469
1470 $this->storeTemporalData(self::TMP_DATA_RUS_EXPORT_INDEX, $this->alreadyDumped);
1471 }
1472
1473 private function restoreTDRusExpIndex()
1474 {
1475 if(!empty($this->alreadyDumped))
1476 return;
1477
1478 $this->alreadyDumped = $this->getStoredTemporalData(self::TMP_DATA_RUS_EXPORT_INDEX);
1479 }
1480
1481 private function storeTDGlobalExpIndex()
1482 {
1483 $this->storeTemporalData(self::TMP_DATA_RUS_GLOBAL_INDEX, array('I' => $this->exportOffset));
1484 }
1485
1486 private function restoreTDGlobalExpIndex()
1487 {
1488 if($this->exportOffset == 0)
1489 {
1490 $data = $this->getStoredTemporalData(self::TMP_DATA_RUS_GLOBAL_INDEX);
1491 $this->exportOffset = intval($data['I']);
1492 }
1493 }
1494
1495 private function generateExportTreePutRussiaBundleOld($bundle, $regions, $dl = 0)
1496 {
1497 foreach($bundle as $id)
1498 {
1499 $node = $this->data['TREES']['MAIN']['NODES'][$id];
1500
1501 $edges = array();
1502 if(isset($this->data['TREES']['MAIN']['EDGES'][$id]))
1503 $edges = $this->data['TREES']['MAIN']['EDGES'][$id];
1504
1505 if(in_array($node['TYPE_CODE'], array('COUNTRY', 'COUNTRY_DISTRICT', 'REGION')))
1506 {
1507 if($node['TYPE_CODE'] == 'REGION')
1508 {
1509 // get fias code & postal code, if any
1510 //$node['EXT']['FIAS'][] = $regions[$node['ID']]['AOGUID'];
1511
1512 $fNode = $this->fiasGetByAOGUID($regions[$node['ID']]['AOGUID']);
1513 if(strlen($fNode['POSTALCODE']))
1514 $node['EXT']['ZIP'][] = $fNode['POSTALCODE'];
1515
1516 $edges = array(); // no way farther
1517 }
1518
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'],
1525 'SOURCE' => self::SOURCE_YANDEX,
1526 ));
1527
1528 if(!empty($edges))
1529 $this->generateExportTreePutRussiaBundle($edges, $regions, $dl+1);
1530 }
1531 }
1532 }
1533
1534 private $fiasPath = array();
1535 private $alreadyStoredPathItems = array();
1536 private $fias2yandexMap = array();
1537
1538 private $alreadyDumped = array();
1539
1540 private $currentRegion = false;
1541
1542 private function generateExportTreeRussiaInner()
1543 {
1544 $links = $this->getFias2YamarketRootLinks(false, true);
1545
1546 //$this->output($links);
1547
1548 $i = -1;
1549 foreach($links as $yRId => $regions)
1550 {
1551 $i++;
1552
1553 $this->restoreTDGlobalExpIndex();
1554 $this->alreadyDumped = array();
1555 $this->restoreTDRusExpIndex();
1556
1557 $this->fias2yandexMap = array();
1558 $fias2yandex = $this->getDataFromCSV('fias_yamarket_links', 'region_'.$yRId);
1559 foreach($fias2yandex as $map)
1560 {
1561 $this->fias2yandexMap[$map['AOGUID']] = $map;
1562 }
1563 unset($fias2yandex);
1564
1565 $this->currentRegion = $this->mapETCodeBySource($yRId, self::SOURCE_YANDEX);
1566
1567 foreach($regions as $regionId)
1568 {
1569 $this->fiasPath = array();
1570
1571 $this->output('CCCurrent REGION is '.$this->currentRegion);
1572 //$this->output($this->alreadyDumped);
1573
1574 $this->generateExportTreeRussiaInnerBundle($regionId);
1575 }
1576
1577 $this->storeTDGlobalExpIndex();
1578
1579 //break; // tmp
1580 //if($i == 1)break;
1581 }
1582 }
1583
1584 private function generateExportTreeRussiaInnerBundle($parentGuid)
1585 {
1586 if(!strlen($parentGuid))
1587 return;
1588
1589 $res = $this->getDataFromCSV('fias_tree', $parentGuid);
1590 foreach($res as $item)
1591 {
1592 if($item['LIVESTATUS'] != '1' || $item['ACTSTATUS'] != '1')
1593 continue;
1594
1595 $item['PARENT_ID'] = $parentGuid;
1596 array_push($this->fiasPath, $item);
1597
1598 if($this->checkIsAllowedCityVillage($item['ID'], $item['TYPE']))
1599 {
1600 // ADD!!!
1601 $this->storeCurrentFiasPath2();
1602 $this->generateExportTreeRussiaInnerStreets($item['ID']);
1603 }
1604
1605 $this->generateExportTreeRussiaInnerBundle($item['ID']);
1606
1607 array_pop($this->fiasPath);
1608 }
1609
1610 }
1611
1612
1613 private function addItemToExportTree($item)
1614 {
1615 $this->exportOffset++;
1616
1617 $this->output('ADD: '.$item['NAME']['RU']['NAME'].' '.$item['TYPE']);
1618 //$this->output($item);
1619
1620 $cat = $this->sysMaps['BASETYPE2GROUP'][$item['TYPE']];
1621 $fName = $this->typeGroups[$cat]['FILE_NAME_TEMPLATE'];
1622
1623 $header = $this->typeGroups[$cat];
1624 $this->alreadyDumped[$item['ID']] = $this->exportOffset;
1625
1626 $parentCode = strlen($item['PARENT_ID']) ? $this->addLeadingZero($this->alreadyDumped[$item['PARENT_ID']], self::CODE_LENGTH) : '';
1627
1628 $data = array(
1629 'CODE' => $this->addLeadingZero($this->exportOffset, self::CODE_LENGTH),
1630 'PARENT_CODE' => $parentCode,
1631 'TYPE_CODE' => $item['TYPE']
1632 );
1633
1634 foreach($item['NAME'] as $lid => $values)
1635 {
1636 foreach($values as $i => $val)
1637 $data['NAME.'.$lid.'.'.$i] = $val;
1638 }
1639
1640 $data['EXT.YAMARKET.0'] = '';
1641 $data['EXT.ZIP.0'] = '';
1642 if(!empty($item['EXTERNALS']))
1643 {
1644 foreach($item['EXTERNALS'] as $type => $values)
1645 {
1646 foreach($values as $i => $val)
1647 $data['EXT.'.$type.'.'.$i] = $val;
1648 }
1649 }
1650
1651 $parentGroupId = strlen($item['PARENT_GROUP_ID']) ? $this->addLeadingZero($this->alreadyDumped[$item['PARENT_GROUP_ID']], self::CODE_LENGTH) : '';
1652
1653 $data['LONGITUDE'] = '';
1654 $data['LATITUDE'] = '';
1655 //$this->output('PGID is set to '.$parentGroupId);
1656
1657 $fName = str_replace(array(
1658 '%BASE_PARENT_ITEM_CODE%',
1659 '%CODE%',
1660 '.csv'
1661 ), array(
1662 $parentGroupId,
1663 ToLower($cat),
1664 ''
1665 ), $fName);
1666
1667 $this->output('PUT:');
1668 $this->output($data);
1669
1670 $this->output('TO:');
1671 $this->output($fName);
1672
1673 $this->putToFile2(
1674 $data,
1675 'assets',
1676 $fName,
1677 true
1678 );
1679 }
1680
1681 #######################################################
1682 ### ABOUT MAIN TREE
1683 #######################################################
1684
1685 // map yandex cities to fias cities
1686 public function buildMainTree()
1687 {
1688 $this->queue = false;
1689 $this->data['TREES']['MAIN'] = array();
1690 $this->data['MAPS'] = array();
1691 $this->data['INDEXES'] = array();
1692
1693 $done = false;
1694 while(!$done)
1695 $done = $this->buildMainTreeNext();
1696
1697 // build name-path index for russia
1698 $this->buildRussiaPathIndex($this->data['TREES']['MAIN']['EDGES'][self::RUSSIA_YANDEX_CODE], array());
1699 }
1700
1701 private function buildMainTreeNext()
1702 {
1703 $next = $this->queueShift();
1704 $bundle = $this->getBundleFromFile($next);
1705
1706 if(!empty($bundle))
1707 {
1708 foreach($bundle as $item)
1709 {
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'];
1713
1714 if($item['CHILDREN_COUNT'] > 0)
1715 $this->queue[] = $item['ID'];
1716 }
1717 }
1718
1719 return empty($this->queue);
1720 }
1721
1722 #######################################################
1723 ### ABOUT FIAS PROCESS
1724 #######################################################
1725
1726 // temporal function
1727 private function checkFiasMaps()
1728 {
1729 $links = $res = $this->getDataFromCSV('fias_yamarket_links', 'rootv2');
1730 $uTotal = 0;
1731 foreach($links as $reg)
1732 {
1733 if($reg['CITIES_MAPPED'] != '1')
1734 {
1735 //$this->output($reg);
1736 $rMap = $this->getDataFromCSV('fias_yamarket_links', 'region_'.$reg['YAMARKET']);
1737
1738 $this->output('============================ For: '.$reg['YAMARKET_NAME'].' '.$reg['YAMARKET']);
1739
1740 $unmapped = 0;
1741 foreach($rMap as $map)
1742 {
1743 if(!strlen($map['AOGUID']))
1744 {
1745 $unmapped++;
1746
1747 $this->output($map);
1748
1749 $res = DB\FiasTable::getList(array('filter' => array(
1750 'FORMALNAME' => $map['NAME'],
1751 '!SHORTNAME' => array('ул', 'пер'),
1752 'ACTSTATUS' => '1',
1753 'LIVESTATUS' => '1'
1754 )));
1755 while($item = $res->fetch())
1756 {
1757 $this->output($item);
1758 }
1759 }
1760 }
1761
1762 $this->output('Unmapped: '.$unmapped);
1763 $uTotal += $unmapped;
1764 }
1765 }
1766 $this->output('TOTAL: '.$uTotal);
1767 }
1768
1769 private function showChildren($pId)
1770 {
1771 $res = DB\FiasTable::getList(array('filter' => array(
1772 'PARENTGUID' => $pId,
1773 'ACTSTATUS' => '1',
1774 'LIVESTATUS' => '1'
1775 )));
1776 while($item = $res->fetch())
1777 {
1778 $this->output($item);
1779 }
1780 }
1781
1782 private function findPathes()
1783 {
1784 $pathes = array(
1785 'aea7bac4-f9b4-4160-95f2-3d667b4d3f92', // отрадное, калиниградская область, 10857
1786 'bda061ac-cbd0-4db8-8d18-69db43e76c2d', // отрадное, калиниградская область, 10857
1787 '436b841d-a44f-431e-b1ec-7d76456d4a11', // отрадное, калиниградская область, 10857
1788 '807943cc-31c0-4a86-a3fe-46d9262101e9', // дагомыс, краснодарский край, 10995
1789 );
1790
1791 foreach($pathes as $id)
1792 {
1793 $this->fiasFindPath($id);
1794 }
1795 }
1796
1797 private function fiasFindPath($aoguid)
1798 {
1799 $pId = $aoguid;
1800
1801 while($pId && $res = DB\FiasTable::getList(array('filter' => array(
1802 'AOGUID' => $pId,
1803 'ACTSTATUS' => '1',
1804 'LIVESTATUS' => '1'
1805 )))->fetch())
1806 {
1807 $this->output($res);
1808 if($res['PARENTGUID'])
1809 $pId = $res['PARENTGUID'];
1810 else
1811 $pId = false;
1812 }
1813 }
1814
1815 private function fiasFind2()
1816 {
1817 $res = DB\FiasTable::getList(array('filter' => array(
1818 'FORMALNAME' => array(
1819
1820
1821 ),
1822 //'ACTSTATUS' => '1',
1823 //'LIVESTATUS' => '1'
1824 )));
1825 while($item = $res->fetch())
1826 {
1827 $this->output($item);
1828 }
1829 }
1830
1831 private function fiasFind()
1832 {
1833 $findInFias = array(
1834 //СС А РРР ГГГ ВВВ ППП УУУУ ЭЭЭЭ ЦЦЦ
1835
1836 '11 0 007 000 000 009 0000 0000 000', // кажым, коми, 10939
1837 '35 0 003 000 000 001 0000 0000 000', // им бабушкина, волог. обл, 10853
1838 '05 0 017 000 000 019 0000 0000 000', // ачи-су, дагестан, 11010
1839 '20 0 028 000 000 001 0000 0000 000', // итум-кали, чечня, 11024
1840 '16 0 022 000 000 023 0000 0000 000', // куланга, татарстан, 11119
1841 '59 0 020 000 000 003 0000 0000 000', // гамово, пермский край, 11108
1842 '56 0 000 000 000 002 0000 0000 000', // зато комаровский, оренбургская область, 11084
1843 '86 0 003 000 000 031 0000 0000 000', // узюм-юрганская гкс, ханты-мансийскиий ао, 11193
1844 '70 0 007 000 000 000 0000 0047 000', // игол, томская область, 11353
1845 '27 0 009 000 000 001 0000 0000 000', // им полины осипенко, хабаровскйи край, 11457
1846 '28 0 014 000 000 045 0000 0000 000', // свободный-21, амурская область, 11375
1847 '14 0 010 000 000 001 0000 0000 000', // багатай, саха якутия, 11443
1848
1849 );
1850
1851 $res = DB\FiasTable::getList(array('filter' => array(
1852 'CODE' => array_values($findInFias),
1853 'ACTSTATUS' => '1',
1854 'LIVESTATUS' => '1'
1855 )));
1856 while($item = $res->fetch())
1857 {
1858 $this->output($item);
1859 }
1860 }
1861
1862 private function fiasGetByAOGUID($fiasId)
1863 {
1864 return DB\FiasTable::getList(array('filter' => array(
1865 '=AOGUID' => $fiasId,
1866 )))->fetch();
1867 }
1868
1869 /*
1870 private function parseFiasCode($code)
1871 {
1872 //СС(0) А(1) РРР(2) ГГГ(3) ВВВ(4) ППП(5) УУУУ(6) ЭЭЭЭ(7) ЦЦЦ(8)
1873 $code = explode(' ', $code);
1874 return array(
1875 'REGIONCODE' => $code[0],
1876 'AREACODE' => $code[2],
1877 'AUTOCODE' => $code[1],
1878 'CITYCODE' => $code[3],
1879 'CTARCODE' => $code[4],
1880 'PLACECODE' => $code[5],
1881 'STREETCODE' => $code[6],
1882 'EXTRCODE' => $code[7],
1883 'SEXTCODE' => $code[8]
1884 );
1885 }
1886
1887 private function checkFitItemByCode($code, $item)
1888 {
1889 $code = $this->parseFiasCode($code);
1890
1891 return (
1892 $item['REGIONCODE'] == $code['REGIONCODE']
1893 &&
1894 $item['AREACODE'] == $code['AREACODE']
1895 &&
1896 $item['AUTOCODE'] == $code['AUTOCODE']
1897 &&
1898 $item['CITYCODE'] == $code['CITYCODE']
1899 &&
1900 $item['CTARCODE'] == $code['CTARCODE']
1901 &&
1902 $item['PLACECODE'] == $code['PLACECODE']
1903 &&
1904 $item['STREETCODE'] == $code['STREETCODE']
1905 &&
1906 $item['EXTRCODE'] == $code['EXTRCODE']
1907 &&
1908 $item['SEXTCODE'] == $code['SEXTCODE']
1909 );
1910 }
1911 */
1912
1913 private function mapFiasCities()
1914 {
1915 //$this->output($this->data['MAPS']['REGIONS']);
1916 $links = $this->getFias2YamarketRootLinks();
1917
1918 //$this->output($links);
1919
1920 $typesToSearch = array('CITY', 'VILLAGE');
1921
1922 // for each region and city we choose the correpongind ones from fias, saving routes
1923 foreach($links as $id => $fiasSource)
1924 {
1925 $region = $this->data['MAPS']['REGIONS'][$id];
1926
1927 $this->output('FOR region: '.$region);
1928 $this->output($region);
1929
1930 $toBeFound = array(); // among all nodes get only ones with following types
1931 $this->getMainTreeNodesOfType(array($id), $typesToSearch, $toBeFound);
1932
1933 //$this->output(count($toBeFound));
1934
1935 if(!empty($toBeFound)) // search them in fias prepared tree
1936 {
1937 foreach($fiasSource as $fiasId)
1938 {
1939 $this->output('In: '.$fiasId);
1940 $this->walkFiasTreeAndKeepFollowing($fiasId, $toBeFound, $typesToSearch);
1941 }
1942 }
1943
1944 $this->cleanUpFile('fias_yamarket_links', 'region_'.$region['ID']);
1945 foreach($toBeFound as $node)
1946 {
1947 $exactId = '';
1948 $exactName = '';
1949 $exactType = '';
1950 $exactCode = '';
1951
1952 if(!empty($node['MATCH']))
1953 {
1954 $match = array_shift($node['MATCH']);
1955
1956 $exactId = $match['ID'];
1957 $exactName = $match['NAME'];
1958 $exactType = $match['TYPE'];
1959
1960 $item = $this->fiasGetByAOGUID($exactId);
1961 if($item)
1962 {
1963 $exactCode = $item['CODE'];
1964 }
1965 else
1966 $this->output('no record in fias for: '.$exactId);
1967 }
1968
1969 $data = array(
1970 'HZ' => 'libre',
1971 'ID' => $node['ID'],
1972 'NAME' => $node['NAME']['RU']['NAME'],
1973 'AOGUID' => $exactId,
1974 'FNAME' => $exactName,
1975 'FTYPE' => $exactType,
1976 'CODE' => $exactCode
1977 );
1978
1979 for($i = 0; $i < 3; $i++)
1980 {
1981 $data['VAR_AOGUID_'.$i] = '';
1982 $data['VAR_NAME_'.$i] = '';
1983 $data['VAR_TYPE_'.$i] = '';
1984 }
1985
1986 $i = 0;
1987 if(!empty($node['MATCH']))
1988 {
1989 foreach($node['MATCH'] as $item)
1990 {
1991 $data['VAR_AOGUID_'.$i] = $item['ID'];
1992 $data['VAR_NAME_'.$i] = $item['NAME'];
1993 $data['VAR_TYPE_'.$i] = $item['TYPE'];
1994
1995 $i++;
1996 }
1997 }
1998
1999 if(!empty($node['POSSIBLE']))
2000 {
2001 foreach($node['POSSIBLE'] as $item)
2002 {
2003 $data['VAR_AOGUID_'.$i] = $item['ID'];
2004 $data['VAR_NAME_'.$i] = $item['NAME'];
2005 $data['VAR_TYPE_'.$i] = $item['TYPE'];
2006
2007 $i++;
2008 }
2009 }
2010
2011 $this->putToFile2(
2012 $data,
2013 'fias_yamarket_links',
2014 'region_'.$region['ID'],
2015 true
2016 );
2017 }
2018
2019 //break;//tmp
2020 }
2021 }
2022
2023 private function checkAllowedState($node)
2024 {
2025 return $node['ACTSTATUS'] == '1' && $node['LIVESTATUS'] == '1';
2026 }
2027
2028 private function mb_str_replace($needle, $replace_text, $haystack)
2029 {
2030 return implode($replace_text, mb_split($needle, $haystack));
2031 }
2032
2033 private function checkNamesEqual($one, $two)
2034 {
2035 // try trim-lc
2036 $one = $this->makeNameIndexKey($one);
2037 $two = $this->makeNameIndexKey($two);
2038
2039 if($one == $two)
2040 return true;
2041
2042 // try ё => e
2043
2044 $one = $this->mb_str_replace('ё', 'е', $one);
2045 $two = $this->mb_str_replace('ё', 'е', $two);
2046
2047 if($one == $two)
2048 return true;
2049
2050 // try й => и
2051
2052 $one = $this->mb_str_replace('й', 'и', $one);
2053 $two = $this->mb_str_replace('й', 'и', $two);
2054
2055 if($one == $two)
2056 return true;
2057
2058 // there could be also multiple spaces between
2059
2060 //if(!($keptNode['NAME_I'] == $name || strpos($keptNode['NAME_I'], $name) !== false || strpos($name, $keptNode['NAME_I']) !== false))
2061 // continue;
2062
2063 return false;
2064 }
2065
2066 private function checkNamesAlmostEqual($one, $two)
2067 {
2068 $one = $this->makeNameIndexKey($one);
2069 $two = $this->makeNameIndexKey($two);
2070
2071 if(strpos($one, $two) !== false || strpos($two, $one) !== false)
2072 return true;
2073
2074 $one = $this->mb_str_replace('ё', 'е', $one);
2075 $two = $this->mb_str_replace('ё', 'е', $two);
2076
2077 if(strpos($one, $two) !== false || strpos($two, $one) !== false)
2078 return true;
2079
2080 $one = $this->mb_str_replace('й', 'и', $one);
2081 $two = $this->mb_str_replace('й', 'и', $two);
2082
2083 if(strpos($one, $two) !== false || strpos($two, $one) !== false)
2084 return true;
2085
2086
2087 $one = preg_replace('#\s+-\s+#', '-', $one);
2088 $two = preg_replace('#\s+-\s+#', '-', $two);
2089
2090 if(strpos($one, $two) !== false || strpos($two, $one) !== false)
2091 return true;
2092
2093 return false;
2094 }
2095
2096 private function walkFiasTreeAndKeepFollowing($node, &$toBeFound, $typesToSearch)
2097 {
2098 $bundle = $this->getDataFromCSV('fias_tree', $node);
2099
2100 if(is_array($bundle) && !empty($bundle))
2101 {
2102 //$this->output($bundle);
2103 foreach($bundle as $node)
2104 {
2105 $name = $this->makeNameIndexKey($node['NAME']);
2106
2107 //$this->output($node);
2108
2109 // check if we need this
2110 if(strlen($node['TYPE']) && isset($this->sysMaps['FIAS2BASETYPE'][$node['TYPE']]))
2111 {
2112 $type = $this->sysMaps['FIAS2BASETYPE'][$node['TYPE']];
2113
2114 if(in_array($type, $typesToSearch)) // type fits
2115 {
2116 // check if name fits too
2117 foreach($toBeFound as &$keptNode)
2118 {
2119 if($keptNode['TYPE_CODE'] != $type)
2120 continue;
2121
2122 if(!$this->checkAllowedState($node))
2123 continue;
2124
2125 if($this->checkNamesEqual($name, $keptNode['NAME']['RU']['NAME']))
2126 {
2127 $keptNode['MATCH'][$node['AOGUID']] = $node;
2128 }
2129 elseif($this->checkNamesAlmostEqual($name, $keptNode['NAME']['RU']['NAME']))
2130 {
2131 $keptNode['POSSIBLE'][$node['AOGUID']] = $node;
2132 }
2133 }
2134 }
2135 }
2136
2137 $this->walkFiasTreeAndKeepFollowing($node['ID'], $toBeFound, $typesToSearch);
2138 }
2139 }
2140 }
2141
2142 private function getFias2YamarketRootLinks($skipMapped = true, $skipCompiled = false)
2143 {
2144 $res = $this->getDataFromCSV('fias_yamarket_links', 'rootv2');
2145
2146 $result = array();
2147 foreach($res as $reg)
2148 {
2149 if($skipMapped && $reg['CITIES_MAPPED'] == '1')
2150 continue;
2151
2152 if($skipCompiled && $reg['COMPILED'] == '1')
2153 continue;
2154
2155 $fias = array($reg['AOGUID']);
2156
2157 if(strlen($reg['ADDITIONAL']))
2158 {
2159 $variants = explode(', ', $reg['ADDITIONAL']);
2160 foreach($variants as $var)
2161 {
2162 $id = explode(':', $var);
2163 $fias[] = $id[0];
2164 }
2165 }
2166
2167 $result[$reg['YAMARKET']] = $fias;
2168 }
2169
2170 return $result;
2171 }
2172
2173 public function splitFiasOnRegions()
2174 {
2175 $this->cleanPoolDir('fias_tree');
2176 $this->walkFias('fiasGotOneSplit');
2177 }
2178
2179 public function copyFias2DB()
2180 {
2181 $this->fiasDB = new Db\FiasTable();
2182 $this->fiasDB->create();
2183
2184 $this->fiasDB->switchIndexes(false);
2185 $this->fiasDB->deleteAll();
2186 $this->walkFias('fiasGotOneAdd2DB');
2187 $this->fiasDB->doneInsert();
2188 $this->fiasDB->switchIndexes(true);
2189 }
2190
2191 /*
2192 public function dropFiasTreeDuplicates()
2193 {
2194 foreach(new \DirectoryIterator($this->getPoolDirName('fias_tree')) as $file)
2195 {
2196 if($file->isDot() || $file->isDir())
2197 continue;
2198
2199 $csv = $this->getDataFromCSV('fias_tree', str_replace('.csv', '', $file->getFilename()));
2200
2201 $index = array();
2202 foreach($csv as $id => $line)
2203 {
2204 if(isset($index[$line['ID']]))
2205 {
2206 unset($csv[$id]);
2207 continue;
2208 }
2209
2210 $index[$line['ID']] = true;
2211 }
2212
2213 $this->putDataToCSV($csv, 'fias_tree', str_replace('.csv', '', $file->getFilename()));
2214
2215 unset($index);
2216 unset($csv);
2217 }
2218 }
2219 */
2220
2221 public function fiasGotOneSplit($data)
2222 {
2223 $item = $data['__ATTR'];
2224
2225 //$this->manageFiasPath($item);
2226
2227 //$this->output(str_repeat('-', intval($item['AOLEVEL']) - 1).$item['FORMALNAME']);
2228 //$this->output($this->printCurrentFiasPath());
2229
2230 //$this->test[$item['PARENTGUID']][] = $item['AOGUID'];
2231
2232 $this->putToFile2(
2233 array(
2234 'ID' => $item['AOGUID'],
2235 'ACTSTATUS' => $item['ACTSTATUS'],
2236 'LIVESTATUS' => $item['LIVESTATUS'],
2237 'NAME' => $item['FORMALNAME'],
2238 'TYPE' => $item['SHORTNAME'],
2239 'POSTALCODE' => $item['POSTALCODE']
2240 ),
2241 'fias_tree',
2242 strlen($item['PARENTGUID']) ? $item['PARENTGUID'] : 'root',
2243 true
2244 );
2245 }
2246
2247 public function fiasGotOneAdd2DB($data)
2248 {
2249 $item = $data['__ATTR'];
2250
2251 $code = implode(' ', array(
2252 $item['REGIONCODE'],
2253 $item['AUTOCODE'],
2254 $item['AREACODE'],
2255 $item['CITYCODE'],
2256 $item['CTARCODE'],
2257 $item['PLACECODE'],
2258 $item['STREETCODE'],
2259 $item['EXTRCODE'],
2260 $item['SEXTCODE'],
2261 ));
2262
2263 // if db works in cp1251
2264 /*
2265 $formalName = \CharsetConverter::ConvertCharset($item['FORMALNAME'], 'UTF-8', SITE_CHARSET);
2266 $nameLC = \CharsetConverter::ConvertCharset($this->makeNameIndexKey($item['FORMALNAME']), 'UTF-8', SITE_CHARSET);
2267 $shortName = \CharsetConverter::ConvertCharset($item['SHORTNAME'], 'UTF-8', SITE_CHARSET);
2268 */
2269
2270 $formalName = $item['FORMALNAME'];
2271 $nameLC = $this->makeNameIndexKey($item['FORMALNAME']);
2272 $shortName = $item['SHORTNAME'];
2273
2274 $this->fiasDB->insert(array(
2275 'AOGUID' => $item['AOGUID'],
2276 'PARENTGUID' => $item['PARENTGUID'],
2277
2278 'AOID' => $item['AOID'],
2279 'NEXTID' => $item['NEXTID'],
2280
2281 'FORMALNAME' => $formalName,
2282 'SHORTNAME' => $shortName,
2283 'POSTALCODE' => $item['POSTALCODE'],
2284
2285 'ACTSTATUS' => $item['ACTSTATUS'],
2286 'LIVESTATUS' => $item['LIVESTATUS'],
2287
2288 'NAME_LC' => $nameLC,
2289 'CODE' => $code
2290 ));
2291 }
2292
2293 private function getByAOID($aoid)
2294 {
2295 $id = explode('-', $aoid);
2296 }
2297
2298 private function printCurrentFiasPath()
2299 {
2300 $path = array();
2301 foreach($this->fiasCPath as $item)
2302 $path[] = $item['NAME'];
2303
2304 return implode('>', $path);
2305 }
2306
2307 private function manageFiasPath($item)
2308 {
2309 $guid = $item['AOGUID'];
2310 $parentGUID = $item['PARENTGUID'];
2311
2312 //$this->truncateCurrentFiasPath($parentGUID);
2313 //$this->fiasCPath[] = array('GUID' => $guid, 'NAME' => $item['FORMALNAME']);
2314 }
2315
2316 private function truncateCurrentFiasPath($guid)
2317 {
2318 foreach($this->fiasCPath as $i => $node)
2319 {
2320 if($node['GUID'] == $guid)
2321 {
2322 array_splice($this->fiasCPath, $i + 1);
2323 return;
2324 }
2325 }
2326 }
2327
2328 #######################################################
2329 ### ABOUT FIAS PROCESS ROOT v2
2330 #######################################################
2331
2332 public function mapFiasRootV2()
2333 {
2334 $this->cleanUpFile('fias_yamarket_links', 'rootv2');
2335 $this->walkFias('fiasGotOneMapRootV2');
2336
2337 foreach($this->data['MAPS']['REGIONS'] as $id => $reg)
2338 {
2339 $foundId = '';
2340 $foundName = '';
2341 $additResults = '';
2342
2343 if(count($reg['MATCH']))
2344 {
2345 $foundId = $reg['MATCH'][0]['ID'];
2346 $foundName = $reg['MATCH'][0]['NAME'];
2347
2348 array_shift($reg['MATCH']);
2349
2350 if(count($reg['MATCH']))
2351 {
2352 $additResults = array();
2353 foreach($reg['MATCH'] as $additRes)
2354 $additResults[] = $additRes['ID'].':"'.$additRes['NAME'].'"';
2355
2356 $additResults = implode(', ', $additResults);
2357 }
2358 }
2359
2360 $this->putToFile(
2361 array(
2362 'YAMARKET' => $id,
2363 'YAMARKET_NAME' => $reg['NAME']['RU']['NAME'],
2364 'AOGUID' => $foundId,
2365 'FIAS_NAME' => $foundName,
2366 'ADDITIONAL' => $additResults
2367 ),
2368 'fias_yamarket_links',
2369 'rootv2'
2370 );
2371 }
2372 }
2373
2374 public function fiasGotOneMapRootV2($data)
2375 {
2376 $item = $data['__ATTR'];
2377
2378 $type = $item['SHORTNAME'];
2379 $name = $this->makeNameIndexKey($item['FORMALNAME']);
2380
2381 if($this->sysMaps['FIAS2BASETYPE'][$type] == 'REGION') // this is fias-region
2382 {
2383 $result = array();
2384 foreach($this->data['MAPS']['REGIONS'] as $id => &$node)
2385 {
2386 $rName = $this->makeNameIndexKey($node['NAME']['RU']['NAME']);
2387
2388 if($rName == $name || strpos($rName, $name) !== false)
2389 {
2390 $node['MATCH'][] = array(
2391 'ID' => $item['AOGUID'],
2392 'NAME' => $item['FORMALNAME'].' '.$item['SHORTNAME']
2393 );
2394 }
2395 }
2396 }
2397 }
2398
2399 private function readFiasRootMapV2()
2400 {
2401 try
2402 {
2403 $csv = new Import\CSVReader('R', false);
2404 $result = array();
2405 $data = $csv->ReadBlock($this->getPoolFileName('fias_yamarket_links', 'rootv2', false));
2406 foreach($data as $region)
2407 $result[$region['YAMARKET']] = $region;
2408
2409 return $result;
2410 }
2411 catch(\Exception $e)
2412 {
2413 return array();
2414 }
2415 }
2416
2417 private function walkFias($callback, $limit = -1)
2418 {
2419 $sax = new SAXParser(array(
2420 'watch4Tag' => 'Object',
2421 'onEachParseResult' => array($this, $callback),
2422 'limit' => $limit,
2423 'collapseAttr' => true
2424 ));
2425
2426 $fd = fopen($_SERVER['DOCUMENT_ROOT'].$this->options['fiasAddrobjFile'], 'r');
2427 while($block = fread($fd, 1024))
2428 {
2429 if(!$sax->putToParser($block))
2430 break;
2431 }
2432
2433 unset($sax);
2434 }
2435
2436 #######################################################
2437 ### ABOUT MAIN DATA
2438 #######################################################
2439
2440 private function buildRussiaPathIndex($bundle, $parentPath = array())
2441 {
2442 foreach($bundle as $id)
2443 {
2444 $node = $this->data['TREES']['MAIN']['NODES'][$id];
2445 $name = $this->makeNameIndexKey($node['NAME']['RU']['NAME']);
2446
2447 //regions:
2448 if($node['TYPE_CODE'] == 'REGION')
2449 $this->data['MAPS']['REGIONS'][$id] = $node;
2450
2451 if(isset($this->data['TREES']['MAIN']['EDGES'][$id]))
2452 $this->buildRussiaPathIndex($this->data['TREES']['MAIN']['EDGES'][$id], $ppp);
2453 }
2454 }
2455
2456 private function getMainTreeNodesOfType($bundle, $types = array(), &$buffer)
2457 {
2458 foreach($bundle as $id)
2459 {
2460 $node = $this->data['TREES']['MAIN']['NODES'][$id];
2461
2462 if(in_array($node['TYPE_CODE'], $types))
2463 {
2464 //$node['NAME_I'] = $this->makeNameIndexKey($node['NAME']['RU']['NAME']);
2465 $buffer[$id] = $node;
2466 }
2467
2468 if(isset($this->data['TREES']['MAIN']['EDGES'][$id]))
2469 $this->getMainTreeNodesOfType($this->data['TREES']['MAIN']['EDGES'][$id], $types, $buffer);
2470 }
2471 }
2472
2473 #######################################################
2474 ### ABOUT FILE POOL
2475 #######################################################
2476
2477 private function putToFile($data, $poolName, $fileSubname)
2478 {
2479 $dir = $_SERVER['DOCUMENT_ROOT'].$this->workDir.$this->filePools[$poolName]['DIR'];
2480 if(!file_exists($dir))
2481 mkdir($dir, 0755, true);
2482
2483 if(!isset($this->filePoolsp[$poolName][$fileSubname]))
2484 {
2485 $fd = $this->filePoolsp[$poolName][$fileSubname] = fopen($dir.$fileSubname.'.csv', 'w');
2486 $head = implode(';', array_keys($data));
2487 fputs($fd, $head.PHP_EOL);
2488
2489 $this->filePoolsp[$poolName][$fileSubname] = $fd;
2490 }
2491
2492 fputs($this->filePoolsp[$poolName][$fileSubname], implode(';', $data).PHP_EOL);
2493 }
2494
2495 private function putToFile2($data, $poolName, $fileSubname, $checkDir = false)
2496 {
2497 $dir = $_SERVER['DOCUMENT_ROOT'].$this->workDir.$this->filePools[$poolName]['DIR'];
2498 $fName = $dir.$fileSubname.'.csv';
2499
2500 if($checkDir && !file_exists($dir))
2501 mkdir($dir, 0755, true);
2502
2503 if(!file_exists($fName))
2504 file_put_contents($fName, implode(';', array_keys($data)).PHP_EOL, FILE_APPEND);
2505
2506 file_put_contents($fName, implode(';', $data).PHP_EOL, FILE_APPEND);
2507 }
2508
2509 private function cleanUpFile($poolName, $fileSubname)
2510 {
2511 $name = $_SERVER['DOCUMENT_ROOT'].$this->workDir.$this->filePools[$poolName]['DIR'].$fileSubname.'.csv';
2512
2513 if(file_exists($name))
2514 unlink($name);
2515 }
2516
2517 private function getPoolFileName($poolName, $fileSubname, $docRoot = true)
2518 {
2519 return ($docRoot ? $_SERVER['DOCUMENT_ROOT'] : '/').$this->workDir.$this->filePools[$poolName]['DIR'].$fileSubname.'.csv';
2520 }
2521
2522 private function getPoolDirName($poolName, $docRoot = true)
2523 {
2524 return ($docRoot ? $_SERVER['DOCUMENT_ROOT'] : '/').$this->workDir.$this->filePools[$poolName]['DIR'];
2525 }
2526
2527 private function cleanPoolDir($poolName)
2528 {
2529 $dir = $_SERVER['DOCUMENT_ROOT'].$this->workDir.$this->filePools[$poolName]['DIR'];
2530 if(file_exists($dir))
2531 system('rm -rf '.$dir);
2532
2533 mkdir($dir, 0755, true);
2534 }
2535
2536 private function getDataFromCSV($poolName, $fileSubname)
2537 {
2538 try
2539 {
2540 $csv = new Import\CSVReader('R', false);
2541 return $csv->ReadBlock($this->getPoolFileName($poolName, $fileSubname, false));
2542 }
2543 catch(\Exception $e)
2544 {
2545 return array();
2546 }
2547 }
2548
2549 private function putDataToCSV($data, $poolName, $fileSubname)
2550 {
2551 $fName = $this->getPoolFileName($poolName, $fileSubname);
2552 if(file_exists($fName))
2553 {
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);
2558 }
2559 }
2560
2561 #######################################################
2562 ### ABOUT COMPILER
2563 #######################################################
2564
2565 private function mapFiasTypeToMain($fiasType)
2566 {
2567 return isset($this->sysMaps['FIAS2BASETYPE'][$fiasType]) ? $this->sysMaps['FIAS2BASETYPE'][$fiasType] : false;
2568 }
2569
2570 private function makeNameIndexKey($name)
2571 {
2572 return trim(mb_strtolower($name, 'UTF-8'));
2573 }
2574
2575 private function makeTypeGroupFile($file = '')
2576 {
2577 $fd = $this->fileOpen(strlen($file) ? $file : self::GROUP_FILE);
2578
2579 fputs($fd, implode(';', $this->headers['GROUP_FILE']).PHP_EOL);
2580 foreach($this->typeGroups as $code => $group)
2581 {
2582 $line = array();
2583 foreach($this->headers['GROUP_FILE'] as $colCode)
2584 $line[] = is_array($group[$colCode]) ? implode(':', $group[$colCode]) : $group[$colCode];
2585
2586 fputs($fd, implode(';', $line).PHP_EOL);
2587 }
2588
2589 fclose($fd);
2590 }
2591
2592 private function makeNext()
2593 {
2594 $next = $this->queueShift();
2595 $bundle = $this->getBundleFromFile($next);
2596
2597 if(!empty($bundle))
2598 {
2599 foreach($bundle as $item)
2600 {
2601 $this->putToGroups($item);
2602
2603 if($item['CHILDREN_COUNT'] > 0)
2604 $this->queue[] = $item['ID'];
2605 }
2606 }
2607
2608 return empty($this->queue);
2609 }
2610
2611 private function queueShift()
2612 {
2613 if($this->queue !== false)
2614 return array_shift($this->queue);
2615
2616 return 'root';
2617 }
2618
2619 private function getBundleFromFile($id)
2620 {
2621 $data = unserialize(file_get_contents($_SERVER['DOCUMENT_ROOT'].$this->grabbedStuffDir.$id));
2622
2623 foreach($data as $k => &$item)
2624 {
2625 if(in_array($item['NAME'], array('Прочее', 'Общероссийские', 'Универсальное', 'Другие города региона')))
2626 {
2627 unset($data[$k]);
2628 continue;
2629 }
2630
2631 //$item['NAME'] = \CharsetConverter::ConvertCharset($item['NAME'], 'UTF-8', SITE_CHARSET); // temp
2632 if(isset($this->typeMap[$item['TYPE_CODE']]))
2633 $item['TYPE_CODE'] = $this->typeMap[$item['TYPE_CODE']];
2634
2635 // type "OTHER" which is a child of type "REGION" is actually a "SUBREGION"
2636 if($item['TYPE_CODE'] == 'OTHER')
2637 {
2638 $parentType = $this->yaIdType[$item['PARENT_ID']];
2639
2640 if($parentType == 'REGION')
2641 $item['TYPE_CODE'] = 'SUBREGION';
2642 }
2643
2644 $code = $this->addLeadingZero($this->codeOffset, $this->leading);
2645 $this->yaIdType[$item['ID']] = $item['TYPE_CODE'];
2646
2647 $this->relations[$item['CODE']] = $item['PARENT_CODE'];
2648 $this->code2type[$item['CODE']] = $item['TYPE_CODE'];
2649
2650 $ruName = $item['NAME'];
2651
2652 //if($this->optionConvertNames)
2653 // $ruName = \CharsetConverter::ConvertCharset($ruName, 'UTF-8', SITE_CHARSET);
2654
2655 $item['NAME'] = array();
2656 $item['NAME']['RU']['NAME'] = $ruName.($this->options['includeYaInfo2Name'] ? ' ('.$item['TYPE_CODE'].', '.$item['ID'].')' : '');
2657 //$item['NAME.EN.NAME'] = '[no-translation]'; // attach translations from old import files
2658 //$item['NAME.UA.NAME'] = '[no-translation]'; // attach translations from old import files
2659
2660 $item['EXT']['YAMARKET'][] = $item['ID'];
2661
2662 //unset($item['ID']);
2663 //unset($item['PARENT_ID']);
2664 }
2665
2666 return $data;
2667 }
2668
2669 private function getParentOfType($code, $types)
2670 {
2671 if(empty($types))
2672 return '';
2673
2674 $nextCode = $code;
2675 $i = -1;
2676 while($nextCode)
2677 {
2678 $i++;
2679
2680 if($i > 50)
2681 throw new Main\SystemException('Recursion gone too deep when trying to find parent of type');
2682
2683 if(isset($types[$this->code2type[$nextCode]]))
2684 return $nextCode;
2685
2686 $nextCode = $this->relations[$nextCode];
2687 }
2688
2689 return '';
2690 }
2691
2692 private function putToGroups($item)
2693 {
2694 foreach($this->typeGroups as $gCode => &$group)
2695 {
2696 //_dump_r('Item '.$item['NAME.RU.NAME'].' ('.$item['TYPE_CODE'].')');
2697
2698 if(!isset($group['I_TYPES'][$item['TYPE_CODE']]))
2699 continue;
2700
2701 //_dump_r('Goes to group: '.$gCode);
2702
2703 $baseParent = $this->getParentOfType($item['CODE'], $this->typeGroups[$group['PARENT']]['I_TYPES']);
2704
2705 //_dump_r('Base parent is: '.$baseParent);
2706
2707 if(!$group['FD'][$baseParent])
2708 {
2709 $fName = str_replace(array(
2710 '%BASE_PARENT_ITEM_CODE%',
2711 '%CODE%'
2712 ), array(
2713 $baseParent,
2714 ToLower($gCode)
2715 ), $group['FILE_NAME_TEMPLATE']);
2716
2717 $group['FD'][$baseParent] = $this->fileOpen($fName);
2718 fputs($group['FD'][$baseParent], implode(';', $this->headers[$group['HEADER']]).PHP_EOL);
2719 }
2720
2721 $header = $this->headers[$group['HEADER']];
2722 $line = array();
2723 foreach($header as $code)
2724 $line[] = isset($item[$code]) ? $item[$code] : '';
2725
2726 fputs($group['FD'][$baseParent], implode(';', $line).PHP_EOL);
2727 }
2728 }
2729
2730 private function fileOpen($name)
2731 {
2732 return fopen($_SERVER['DOCUMENT_ROOT'].$this->workDir.self::OUTPUT_DIR.$name, 'w');
2733 }
2734
2735 private static function addLeadingZero($value, $length)
2736 {
2737 if(strlen($value) >= $length)
2738 return $value;
2739
2740 $diff = abs($length - strlen($value));
2741
2742 for($i = 0; $i < $diff; $i++)
2743 $value = '0'.$value;
2744
2745 return $value;
2746 }
2747
2748 #######################################################
2749 ### ABOUT DATA
2750 #######################################################
2751
2752 private function storeTemporalData($dataCode, $data)
2753 {
2754 $dir = $_SERVER['DOCUMENT_ROOT'].$this->workDir.self::TMP_DATA_DIR;
2755 if(!file_exists($dir))
2756 mkdir($dir, 0755, true);
2757
2758 file_put_contents($dir.$dataCode, serialize($data));
2759 }
2760
2761 private function getStoredTemporalData($dataCode)
2762 {
2763 $file = $_SERVER['DOCUMENT_ROOT'].$this->workDir.self::TMP_DATA_DIR.$dataCode;
2764
2765 if(is_readable($file))
2766 return unserialize(file_get_contents($file));
2767 else
2768 return array();
2769 }
2770
2771 private function cleanTemporalData($dataCode)
2772 {
2773 $file = $_SERVER['DOCUMENT_ROOT'].$this->workDir.self::TMP_DATA_DIR.$dataCode;
2774
2775 if(is_readable($file))
2776 unlink($file);
2777 }
2778
2779 /*
2780 private function dropTemporalFile()
2781 {
2782 $file = $_SERVER['DOCUMENT_ROOT'].$this->workDir.self::TMP_DATA_FILE;
2783
2784 if(is_readable($file))
2785 unlink($file);
2786 }
2787 */
2788
2789 public function cleanOutput()
2790 {
2791 $file = $_SERVER['DOCUMENT_ROOT'].$this->workDir.self::OUTPUT_FILE;
2792
2793 if(is_readable($file))
2794 unlink($file);
2795 }
2796
2797 public function output($data, $important = true)
2798 {
2799 if(!$important)
2800 return false;
2801
2802 ob_start();
2803 print_r($data);
2804 $data = ob_get_contents();
2805 ob_end_clean();
2806
2807 file_put_contents($_SERVER['DOCUMENT_ROOT'].$this->workDir.self::OUTPUT_FILE, $data.PHP_EOL, FILE_APPEND);
2808 }
2809}
generateExportFilesFromTableBundle_Standard_YandexOnly($item, $table)
Definition compiler.php:682
if(!function_exists(__NAMESPACE__.'\\___1034172934'))
Definition license.php:1