Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
baseconverter.php
1<?php
2
4
14
26abstract class BaseConverter
27{
29 protected const COUNTRY_ADMIN_LEVEL = 2;
30
32 protected $details = [];
33
35 protected $addressComponents = [];
36
42 public function convert(string $languageId, array $details): ?Location
43 {
44 $this->details = $details;
45
46 if (!$this->isDetailsValid())
47 {
48 return null;
49 }
50
51 $addressFieldCollection = $this->makeAddressFieldCollection($languageId);
52 $locationTypeField = $this->getLocationTypeField($addressFieldCollection);
53
54 if ($locationTypeField === null)
55 {
56 return null;
57 }
58
59 list($latitude, $longitude) = $this->getCoordinates();
60
61 $address = (new Address($languageId))
62 ->setLatitude($latitude)
63 ->setLongitude($longitude)
64 ->setFieldCollection($addressFieldCollection);
65
66 if ($addressLine1 = $this->createAddressLine1($address))
67 {
68 $address->setFieldValue(FieldType::ADDRESS_LINE_1, $addressLine1);
69 }
70
72 $this->details['osm_type'],
73 $this->details['osm_id']
74 );
75
76 if (!$externalId)
77 {
78 return null;
79 }
80
81 $location =
82 (new Location())
83 ->setSourceCode(Repository::getSourceCode())
84 ->setExternalId($externalId)
85 ->setType($locationTypeField->getType())
86 ->setName($locationTypeField->getValue())
87 ->setLatitude($latitude)
88 ->setLongitude($longitude)
89 ->setLanguageId($languageId)
90 ->setAddress($address);
91
92 if($address->isFieldExist(FieldType::POSTAL_CODE))
93 {
94 $location->setFieldValue(
95 FieldType::POSTAL_CODE,
96 $address->getFieldValue(FieldType::POSTAL_CODE)
97 );
98 }
99
100 return $location;
101 }
102
106 private function isDetailsValid(): bool
107 {
108 if (!isset($this->details['osm_type']))
109 {
110 return false;
111 }
112
113 if (!isset($this->details['osm_id']))
114 {
115 return false;
116 }
117
118 if (!isset($this->details['address']) || !is_array($this->details['address']))
119 {
120 return false;
121 }
122
126 $this->addressComponents = array_filter(
127 $this->details['address'],
128 static function (array $addressComponent)
129 {
130 if (!isset($addressComponent['isaddress']))
131 {
132 return false;
133 }
134
135 return (bool)$addressComponent['isaddress'];
136 }
137 );
138
139 if (empty($this->details['address']))
140 {
141 return false;
142 }
143
144 if (!isset($this->details['country_code']))
145 {
146 return false;
147 }
148
149 if (!$this->getCountry())
150 {
151 return false;
152 }
153
154 if (!$this->getCoordinates())
155 {
156 return false;
157 }
158
159 return true;
160 }
161
166 private function makeAddressFieldCollection(string $languageId): Address\FieldCollection
167 {
168 $result = new Address\FieldCollection();
169
170 $postalCode = $this->getPostalCode();
171 if ($postalCode)
172 {
173 $result->addItem(
174 (new Field(FieldType::POSTAL_CODE))->setValue($postalCode)
175 );
176 }
177
178 $country = $this->getCountry();
179 if ($country && isset($country['localname']))
180 {
181 $result->addItem(
182 (new Field(FieldType::COUNTRY))->setValue($country['localname'])
183 );
184 }
185
186 $adminLevel1 = $this->getAdminLevel1();
187 if ($adminLevel1 && isset($adminLevel1['localname']))
188 {
189 $result->addItem(
190 (new Field(FieldType::ADM_LEVEL_1))->setValue($adminLevel1['localname'])
191 );
192 }
193
194 $adminLevel2 = $this->getAdminLevel2();
195 if ($adminLevel2 && isset($adminLevel2['localname']))
196 {
197 $result->addItem(
198 (new Field(FieldType::ADM_LEVEL_2))->setValue($adminLevel2['localname'])
199 );
200 }
201
202 $adminLevel3 = $this->getAdminLevel3();
203 if ($adminLevel3 && isset($adminLevel3['localname']))
204 {
205 $result->addItem(
206 (new Field(FieldType::ADM_LEVEL_3))->setValue($adminLevel3['localname'])
207 );
208 }
209
210 $adminLevel4 = $this->getAdminLevel4();
211 if ($adminLevel4 && isset($adminLevel4['localname']))
212 {
213 $result->addItem(
214 (new Field(FieldType::ADM_LEVEL_4))->setValue($adminLevel4['localname'])
215 );
216 }
217
218 $locality = $this->getLocality();
219 if ($locality && isset($locality['localname']))
220 {
221 $result->addItem(
222 (new Field(FieldType::LOCALITY))->setValue($locality['localname'])
223 );
224 }
225
226 $subLocality = $this->getSubLocality();
227 if ($subLocality && isset($subLocality['localname']))
228 {
229 $result->addItem(
230 (new Field(FieldType::SUB_LOCALITY))->setValue($subLocality['localname'])
231 );
232 }
233
234 $subLocalityLevel1 = $this->getSubLocalityLevel1();
235 if ($subLocalityLevel1 && isset($subLocalityLevel1['localname']))
236 {
237 $result->addItem(
238 (new Field(FieldType::SUB_LOCALITY_LEVEL_1))->setValue($subLocalityLevel1['localname'])
239 );
240 }
241
242 $subLocalityLevel2 = $this->getSubLocalityLevel2();
243 if ($subLocalityLevel2 && isset($subLocalityLevel2['localname']))
244 {
245 $result->addItem(
246 (new Field(FieldType::SUB_LOCALITY_LEVEL_2))->setValue($subLocalityLevel2['localname'])
247 );
248 }
249
250 $street = $this->getStreet();
251 if ($street && isset($street['localname']))
252 {
253 $result->addItem(
254 (new Field(FieldType::STREET))->setValue($street['localname'])
255 );
256 }
257
258 $house = $this->getHouse();
259 if ($house && isset($house['localname']))
260 {
261 $result->addItem(
262 (new Field(FieldType::BUILDING))->setValue($house['localname'])
263 );
264 }
265
266 $addressLine2 = $this->getAddressLine2();
267 if ($addressLine2 && isset($addressLine2['localname']))
268 {
269 $result->addItem(
270 (new Field(FieldType::ADDRESS_LINE_2))->setValue($addressLine2['localname'])
271 );
272 }
273
274 return $result;
275 }
276
281 private function createAddressLine1(Address $address): ?string
282 {
283 $format = FormatService::getInstance()->findDefault($address->getLanguageId());
284
285 return StringConverter::convertToStringTemplate(
286 $address,
287 $format->getTemplate(TemplateType::ADDRESS_LINE_1),
288 StringConverter::STRATEGY_TYPE_TEMPLATE,
289 StringConverter::CONTENT_TYPE_TEXT
290 );
291 }
292
296 private function getCountry(): ?array
297 {
305 foreach ($this->addressComponents as $addressComponent)
306 {
307 if ($addressComponent['class'] === 'boundary'
308 && $addressComponent['type'] === 'administrative'
309 && $addressComponent['admin_level'] === static::COUNTRY_ADMIN_LEVEL
310 )
311 {
312 return $addressComponent;
313 }
314 }
315
323 foreach ($this->addressComponents as $addressComponent)
324 {
325 if ($addressComponent['class'] === 'place' && $addressComponent['type'] === 'country')
326 {
327 return $addressComponent;
328 }
329 }
330
331 return null;
332 }
333
337 abstract protected function getAdminLevel1(): ?array;
338
342 protected function getAdminLevel2(): ?array
343 {
344 return null;
345 }
346
350 protected function getAdminLevel3(): ?array
351 {
352 return null;
353 }
354
358 protected function getAdminLevel4(): ?array
359 {
360 return null;
361 }
362
366 protected function getLocality(): ?array
367 {
371 $settlementTypePriorityList = $this->getSettlementTypes();
372 foreach ($this->addressComponents as $addressComponent)
373 {
374 $componentPlaceType = $this->getAddressComponentPlaceType($addressComponent);
375
376 $isItself = (
377 $this->details['osm_type'] === $addressComponent['osm_type']
378 && $this->details['osm_id'] === $addressComponent['osm_id']
379 );
380
381 if ($isItself && in_array($componentPlaceType, $settlementTypePriorityList, true))
382 {
383 return $addressComponent;
384 }
385 }
386
387 $addressComponent = $this->getLocalityConcrete();
388 if ($addressComponent)
389 {
390 return $addressComponent;
391 }
392
393 if ($this->isCityState())
394 {
395 return $this->getAdminLevel1();
396 }
397
398 return null;
399 }
400
404 protected function isCityState(): bool
405 {
406 $adminLevel1 = $this->getAdminLevel1();
407
408 return (
409 $adminLevel1['osm_type'] === 'R'
410 && in_array($adminLevel1['osm_id'], $this->getCityStateRelationIds(), true)
411 );
412 }
413
417 protected function getLocalityConcrete(): ?array
418 {
419 $addressComponent = $this->getLocalityByTypes(['R', 'W']);
420 if ($addressComponent)
421 {
422 return $addressComponent;
423 }
424
425 $addressComponent = $this->getLocalityByTypes(['N']);
426 if ($addressComponent)
427 {
428 return $addressComponent;
429 }
430
431 return null;
432 }
433
437 protected function getCityStateRelationIds(): array
438 {
439 return [];
440 }
441
445 protected function getSubLocality(): ?array
446 {
447 return null;
448 }
449
453 protected function getSubLocalityLevel1(): ?array
454 {
455 return null;
456 }
457
461 protected function getSubLocalityLevel2(): ?array
462 {
463 return null;
464 }
465
472 protected function getStreet(): ?array
473 {
474 foreach ($this->addressComponents as $addressComponent)
475 {
476 if (in_array($addressComponent['rank_address'], [26, 27], true))
477 {
478 return $addressComponent;
479 }
480 }
481
482 if (!empty($this->details['addresstags']['street']))
483 {
484 return [
485 'localname' => $this->details['addresstags']['street'],
486 ];
487 }
488
489 return null;
490 }
491
498 protected function getHouse(): ?array
499 {
500 foreach ($this->addressComponents as $addressComponent)
501 {
502 if ($addressComponent['rank_address'] == 28)
503 {
504 return $addressComponent;
505 }
506 }
507
508 if (!empty($this->details['addresstags']['housenumber']))
509 {
510 return [
511 'localname' => $this->details['addresstags']['housenumber'],
512 ];
513 }
514
515 return null;
516 }
517
524 protected function getAddressLine2(): ?array
525 {
526 foreach ($this->addressComponents as $addressComponent)
527 {
528 if ($addressComponent['rank_address'] >= 29)
529 {
530 return $addressComponent;
531 }
532 }
533
534 return null;
535 }
536
540 private function getPostalCode(): ?string
541 {
542 return $this->details['calculated_postcode'] ?? null;
543 }
544
549 private function getLocationTypeField(Address\FieldCollection $addressFieldCollection): ?Field
550 {
552 $items = array_reverse($addressFieldCollection->getSortedItems());
553
554 foreach ($items as $item)
555 {
556 if (!Location\Type::isValueExist($item->getType()))
557 {
558 continue;
559 }
560
561 return $item;
562 }
563
564 return null;
565 }
566
570 private function getCoordinates(): ?array
571 {
572 if (!isset($this->details['centroid'])
573 || !isset($this->details['centroid']['type'])
574 || $this->details['centroid']['type'] !== 'Point'
575 || !isset($this->details['centroid']['coordinates'])
576 || !is_array($this->details['centroid']['coordinates'])
577 || count($this->details['centroid']['coordinates']) != 2
578 )
579 {
580 return null;
581 }
582
583 return [
584 (float)$this->details['centroid']['coordinates'][1],
585 (float)$this->details['centroid']['coordinates'][0],
586 ];
587 }
588
593 protected function isAdministrativeBoundary($addressComponent): bool
594 {
595 return (
596 $addressComponent['class'] === 'boundary'
597 && $addressComponent['type'] === 'administrative'
598 );
599 }
600
605 protected function getBoundaryAdministrativeByLevel(int $level): ?array
606 {
607 foreach ($this->addressComponents as $addressComponent)
608 {
609 if ($this->isAdministrativeBoundary($addressComponent)
610 && $addressComponent['admin_level'] == $level
611 )
612 {
613 return $addressComponent;
614 }
615 }
616
617 return null;
618 }
619
626 protected function getSettlementTypes(): array
627 {
628 return [
629 'city',
630 'town',
631 'village',
632 'hamlet',
633 'isolated_dwelling',
634 'farm',
635 'allotments',
636 ];
637 }
638
643 protected function getAddressComponentPlaceType(array $addressComponent)
644 {
645 if (isset($addressComponent['class']) && $addressComponent['class'] === 'place')
646 {
647 return $addressComponent['type'];
648 }
649
650 if (isset($addressComponent['place_type']))
651 {
652 return $addressComponent['place_type'];
653 }
654
655 return null;
656 }
657
662 protected function getLocalityByTypes(array $types): ?array
663 {
664 $settlementTypePriorityList = $this->getSettlementTypes();
665
666 foreach ($settlementTypePriorityList as $settlementType)
667 {
668 foreach ($this->addressComponents as $addressComponent)
669 {
670 if (!in_array($addressComponent['osm_type'], $types, true))
671 {
672 continue;
673 }
674
675 $componentPlaceType = $this->getAddressComponentPlaceType($addressComponent);
676 if (!$componentPlaceType)
677 {
678 continue;
679 }
680
681 if ($componentPlaceType === $settlementType)
682 {
683 return $addressComponent;
684 }
685 }
686 }
687
688 return null;
689 }
690}
convert(string $languageId, array $details)
static buildExternalId(string $osmType, int $osmId)