1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
location.php
См. документацию.
1<?php
8namespace Bitrix\Sale\Location;
9
10use Bitrix\Main;
11use Bitrix\Main\DB;
12use Bitrix\Main\Entity;
13use Bitrix\Main\Localization\Loc;
14
15use Bitrix\Sale\Location\Name;
16use Bitrix\Sale\Location\Util\Assert;
17use Bitrix\Sale\Location\Search;
18use Bitrix\Sale\Location\DB\Helper;
19
20Loc::loadMessages(__FILE__);
21
38final class LocationTable extends Tree
39{
40 public static function getFilePath()
41 {
42 return __FILE__;
43 }
44
45 public static function getTableName()
46 {
47 return 'b_sale_location';
48 }
49
59 public static function getByCode($code = '', $parameters = array())
60 {
61 $code = Assert::expectStringNotNull($code, '$code');
62
63 if(!is_array($parameters))
64 $parameters = array();
65
66 $parameters['filter']['=CODE'] = $code;
67 $parameters['limit'] = 1;
68
69 return self::getList($parameters);
70 }
71
72 public static function checkFields(Entity\Result $result, $primary, array $data)
73 {
74 parent::checkFields($result, $primary, $data);
75
76 foreach(static::getEntity()->getFields() as $field)
77 {
78 $error = false;
79
80 if ($field->getName() === 'LATITUDE')
81 {
82 $latitude = (string)($data['LATITUDE'] ?? null);
83 if ($latitude !== '')
84 {
85 // latitude is set in data and not empty, it must lay between -90 and 90
86 if (!is_numeric($latitude))
87 {
88 $error = Loc::getMessage('SALE_LOCATION_LOCATION_ENTITY_LATITUDE_TYPE_ERROR');
89 }
90 else
91 {
92 $latitude = (float)$latitude;
93 if ($latitude < -90 || $latitude > 90)
94 {
95 $error = Loc::getMessage('SALE_LOCATION_LOCATION_ENTITY_LATITUDE_RANGE_ERROR');
96 }
97 }
98 }
99 }
100
101 if ($field->getName() === 'LONGITUDE')
102 {
103 $longitude = (string)($data['LONGITUDE'] ?? null);
104 if ($longitude !== '')
105 {
106 // longitude is set in data and not empty, it must lay between -180 and 180
107 if (!is_numeric($longitude))
108 {
109 $error = Loc::getMessage('SALE_LOCATION_LOCATION_ENTITY_LONGITUDE_TYPE_ERROR');
110 }
111 else
112 {
113 $longitude = (float)$longitude;
114 if ($longitude < -180 || $longitude > 180)
115 {
116 $error = Loc::getMessage('SALE_LOCATION_LOCATION_ENTITY_LONGITUDE_RANGE_ERROR');
117 }
118 }
119 }
120 }
121
122 if ($error !== false)
123 {
124 $result->addError(new Entity\FieldError(
125 $field,
126 $error,
127 Entity\FieldError::INVALID_VALUE
128 ));
129 }
130 }
131 }
132
133 public static function add(array $data)
134 {
135 return self::addExtended($data);
136 }
137
162 public static function addExtended(array $data, array $additional = array())
163 {
164 $resetLegacy = !isset($additional['RESET_LEGACY']) || $additional['RESET_LEGACY'] !== false;
165
166 if(isset($data['EXTERNAL']))
167 {
168 $external = $data['EXTERNAL'];
169 unset($data['EXTERNAL']);
170 }
171
172 if(isset($data['NAME']))
173 {
174 $name = $data['NAME'];
175 unset($data['NAME']);
176 }
177
178 // force code to lowercase
179 if(isset($data['CODE']))
180 $data['CODE'] = mb_strtolower($data['CODE']);
181
182 // you are not allowed to modify tree data over LocationTable::add()
184
185 // store tree data and basic
186 $addResult = parent::addExtended($data, $additional);
187
188 // add connected data
189 if($addResult->isSuccess())
190 {
191 $primary = $addResult->getId();
192
193 // external
194 if(isset($external))
195 ExternalTable::addMultipleForOwner($primary, $external);
196
197 // names
198 if(isset($name))
200
201 if(intval($data['TYPE_ID']) > 0 && $resetLegacy)
202 self::resetLegacy(intval($data['TYPE_ID']));
203
205 $GLOBALS['CACHE_MANAGER']->ClearByTag('sale-location-data');
206 }
207
208 return $addResult;
209 }
210
211 protected static function resetLegacy($typeId)
212 {
213 $type = TypeTable::getList(array('filter' => array('=ID' => $typeId), 'select' => array('CODE')))->fetch();
214 if(mb_strlen($type['CODE']) && in_array($type['CODE'], array('COUNTRY', 'REGION', 'CITY')))
215 static::resetLegacyPath();
216 }
217
218 public static function update($primary, array $data)
219 {
220 return self::updateExtended($primary, $data);
221 }
222
247 public static function updateExtended($primary, array $data, array $additional = array())
248 {
249 $primary = Assert::expectIntegerPositive($primary, '$primary');
250 $resetLegacy = !isset($additional['RESET_LEGACY']) || $additional['RESET_LEGACY'] !== false;
251
252 // first update parent, and if it succeed, do updates of the connected data
253
254 if(isset($data['EXTERNAL']))
255 {
256 $external = $data['EXTERNAL'];
257 unset($data['EXTERNAL']);
258 }
259
260 if(isset($data['NAME']))
261 {
262 $name = $data['NAME'];
263 unset($data['NAME']);
264 }
265
266 // force code to lowercase
267 if(isset($data['CODE']))
268 $data['CODE'] = mb_strtolower($data['CODE']);
269
270 // you are not allowed to modify tree data over LocationTable::update()
272
273 $updResult = parent::updateExtended($primary, $data, $additional);
274
275 // update connected data
276 if($updResult->isSuccess())
277 {
278 // external
279 if(isset($external))
280 ExternalTable::updateMultipleForOwner($primary, $external);
281
282 // names
283 if(isset($name))
285
286 if($resetLegacy && (intval($data['TYPE_ID']) > 0 || isset($data['PARENT_ID'])))
287 self::resetLegacy(intval($data['TYPE_ID']));
288
289 $GLOBALS['CACHE_MANAGER']->ClearByTag('sale-location-data');
290
291 if(isset($name) || isset($data['PARENT_ID']))
293 }
294
295 return $updResult;
296 }
297
298 public static function delete($primary)
299 {
300 return self::deleteExtended($primary);
301 }
302
312 public static function deleteExtended($primary, array $additional = array())
313 {
314 $primary = Assert::expectIntegerPositive($primary, '$primary');
315 $resetLegacy = !isset($additional['RESET_LEGACY']) || $additional['RESET_LEGACY'] !== false;
316 $deleteSubtree = !isset($additional['DELETE_SUBTREE']) || $additional['DELETE_SUBTREE'] !== false;
317
318 // delete connected data of sub-nodes
319 if($deleteSubtree)
320 {
321 $rangeSql = parent::getSubtreeRangeSqlForNode($primary);
324 }
325
326 if($resetLegacy)
327 $data = static::getList(array('filter' => array('=ID' => $primary), 'select' => array('TYPE_ID')))->fetch();
328
329 $delResult = parent::deleteExtended($primary, $additional);
330
331 // delete connected data
332 if($delResult->isSuccess())
333 {
336
337 if($resetLegacy && intval($data['TYPE_ID']))
338 {
339 $type = TypeTable::getList(array('filter' => array('=ID' => $data['TYPE_ID']), 'select' => array('CODE')))->fetch();
340 if(mb_strlen($type['CODE']) && in_array($type['CODE'], array('COUNTRY', 'REGION', 'CITY')))
341 static::resetLegacyPath();
342 }
343
344 $GLOBALS['CACHE_MANAGER']->ClearByTag('sale-location-data');
346 }
347
348 return $delResult;
349 }
350
356 public static function getExternalData($primary, $parameters = array())
357 {
358 $primary = Assert::expectIntegerPositive($primary, '$primary');
359
360 if(!is_array($parameters) || empty($parameters))
361 $parameters = array();
362
363 $parameters['filter']['LOCATION_ID'] = $primary;
364
365 return ExternalTable::getList($parameters);
366 }
367
368 // todo: make getList with SITE_ID parameter to have an ability to filter by SITE_ID using orm (even slowly)
369
376 public static function getPathToNodeByCode($code, $parameters, $behaviour = array('SHOW_LEAF' => true))
377 {
378 $code = Assert::expectStringNotNull($code, '$code');
379
380 return self::getPathToNodeByCondition(array('=CODE' => $code), $parameters, $behaviour);
381 }
382
383 public static function checkNodeIsParentOfNode($primary, $childPrimary, $behaviour = array('ACCEPT_CODE' => false, 'CHECK_DIRECT' => false))
384 {
385 if(!$behaviour['ACCEPT_CODE'])
386 return static::checkNodeIsParentOfNodeById($primary, $childPrimary, $behaviour);
387
388 $primary = Assert::expectStringNotNull($primary, '$primary');
389 $childPrimary = Assert::expectStringNotNull($childPrimary, '$childPrimary');
390
391 return static::checkNodeIsParentOfNodeByFilters(array('=CODE' => $primary), array('=CODE' => $childPrimary), $behaviour);
392 }
393
394 public static function resetLegacyPath()
395 {
396 $dbConnection = Main\HttpApplication::getConnection();
397 $locTable = static::getTableName();
398
399 $types = array();
400 $res = TypeTable::getList(array(
401 'filter' => array('CODE' => array('COUNTRY', 'REGION', 'CITY')),
402 'select' => array('ID', 'CODE')
403 ));
404 while($item = $res->fetch())
405 $types[$item['CODE']] = $item['ID'];
406
407 if(!empty($types))
408 {
409 if(!$dbConnection->isTableExists('b_sale_loc_rebind'))
410 $dbConnection->query("create temporary table b_sale_loc_rebind (TARGET_ID ".Helper::getSqlForDataType('int').", LOCATION_ID ".Helper::getSqlForDataType('int').")");
411 else
412 $dbConnection->query("truncate table b_sale_loc_rebind");
413
414 $sqlWhere = array();
415 foreach($types as $code => $id)
416 $sqlWhere[] = "'".intval($id)."'";
417
418 $dbConnection->query("update ".$locTable." set COUNTRY_ID = NULL, REGION_ID = NULL, CITY_ID = NULL where TYPE_ID in (".implode(', ', $sqlWhere).")");
419
420 if(intval($types['REGION']) && intval($types['COUNTRY']))
421 {
422 // countries for regions
423 $dbConnection->query("insert into b_sale_loc_rebind (TARGET_ID, LOCATION_ID) select A.ID as ONE, B.ID as TWO from ".$locTable." A inner join ".$locTable." B on A.TYPE_ID = '".intval($types['REGION'])."' and B.TYPE_ID = '".intval($types['COUNTRY'])."' and B.LEFT_MARGIN <= A.LEFT_MARGIN and B.RIGHT_MARGIN >= A.RIGHT_MARGIN");
424 Helper::mergeTables($locTable, 'b_sale_loc_rebind', array('COUNTRY_ID' => 'LOCATION_ID'), array('ID' => 'TARGET_ID'));
425 $dbConnection->query("truncate table b_sale_loc_rebind");
426 }
427
428 if(intval($types['REGION']) && intval($types['CITY']))
429 {
430 // regions for cities
431 $dbConnection->query("insert into b_sale_loc_rebind (TARGET_ID, LOCATION_ID) select A.ID as ONE, B.ID as TWO from ".$locTable." A inner join ".$locTable." B on A.TYPE_ID = '".intval($types['CITY'])."' and B.TYPE_ID = '".intval($types['REGION'])."' and B.LEFT_MARGIN <= A.LEFT_MARGIN and B.RIGHT_MARGIN >= A.RIGHT_MARGIN");
432 Helper::mergeTables($locTable, 'b_sale_loc_rebind', array('REGION_ID' => 'LOCATION_ID'), array('ID' => 'TARGET_ID'));
433 $dbConnection->query("truncate table b_sale_loc_rebind");
434 }
435
436 if(intval($types['COUNTRY']) && intval($types['CITY']))
437 {
438 // countries for cities
439 $dbConnection->query("insert into b_sale_loc_rebind (TARGET_ID, LOCATION_ID) select A.ID as ONE, B.ID as TWO from ".$locTable." A inner join ".$locTable." B on A.TYPE_ID = '".intval($types['CITY'])."' and B.TYPE_ID = '".intval($types['COUNTRY'])."' and B.LEFT_MARGIN <= A.LEFT_MARGIN and B.RIGHT_MARGIN >= A.RIGHT_MARGIN");
440 Helper::mergeTables($locTable, 'b_sale_loc_rebind', array('COUNTRY_ID' => 'LOCATION_ID'), array('ID' => 'TARGET_ID'));
441 }
442
443 $dbConnection->query('drop table if exists b_sale_loc_rebind');
444
445 if(intval($types['COUNTRY']))
446 $dbConnection->query("update ".$locTable." set COUNTRY_ID = ID where TYPE_ID = '".intval($types['COUNTRY'])."'");
447
448 if(intval($types['REGION']))
449 $dbConnection->query("update ".$locTable." set REGION_ID = ID where TYPE_ID = '".intval($types['REGION'])."'");
450
451 if(intval($types['CITY']))
452 $dbConnection->query("update ".$locTable." set CITY_ID = ID where TYPE_ID = '".intval($types['CITY'])."'");
453 }
454 }
455
456 public static function getCodeValidators()
457 {
458 return array(
459 new Entity\Validator\Unique(),
460 );
461 }
462
463 public static function getMap()
464 {
465 return array(
466
467 'ID' => array(
468 'data_type' => 'integer',
469 'primary' => true,
470 'autocomplete' => true,
471 'title' => 'ID'
472 ),
473 'CODE' => array(
474 'data_type' => 'string',
475 'title' => Loc::getMessage('SALE_LOCATION_LOCATION_ENTITY_CODE_FIELD'),
476 'required' => true,
477 'validation' => array(__CLASS__, 'getCodeValidators')
478 ),
479
480 'LEFT_MARGIN' => array(
481 'data_type' => 'integer',
482 ),
483 'RIGHT_MARGIN' => array(
484 'data_type' => 'integer',
485 ),
486 'DEPTH_LEVEL' => array(
487 'data_type' => 'integer',
488 ),
489 'SORT' => array(
490 'data_type' => 'integer',
491 'default_value' => 100,
492 'title' => Loc::getMessage('SALE_LOCATION_LOCATION_ENTITY_SORT_FIELD')
493 ),
494 'PARENT_ID' => array(
495 'data_type' => 'integer',
496 'default_value' => 0,
497 'title' => Loc::getMessage('SALE_LOCATION_LOCATION_ENTITY_PARENT_ID_FIELD')
498 ),
499 'TYPE_ID' => array(
500 'data_type' => 'integer',
501 'required' => true,
502 'title' => Loc::getMessage('SALE_LOCATION_LOCATION_ENTITY_TYPE_ID_FIELD')
503 ),
504 'LATITUDE' => array(
505 'data_type' => 'float',
506 'title' => Loc::getMessage('SALE_LOCATION_LOCATION_ENTITY_LATITUDE_FIELD')
507 ),
508 'LONGITUDE' => array(
509 'data_type' => 'float',
510 'title' => Loc::getMessage('SALE_LOCATION_LOCATION_ENTITY_LONGITUDE_FIELD')
511 ),
512
513 // virtual
514 'TYPE' => array(
515 'data_type' => 'Bitrix\Sale\Location\Type',
516 'reference' => array(
517 '=this.TYPE_ID' => 'ref.ID'
518 ),
519 'join_type' => "inner"
520 ),
521 'NAME' => array(
522 'data_type' => 'Bitrix\Sale\Location\Name\Location',
523 'reference' => array(
524 '=this.ID' => 'ref.LOCATION_ID'
525 ),
526 'join_type' => "inner"
527 ),
528 'PARENT' => array(
529 'data_type' => 'Bitrix\Sale\Location\Location',
530 'reference' => array(
531 '=this.PARENT_ID' => 'ref.ID'
532 )
533 ),
534 'PARENTS' => array(
535 'data_type' => 'Bitrix\Sale\Location\Location',
536 'reference' => array(
537 '<=ref.LEFT_MARGIN' => 'this.LEFT_MARGIN',
538 '>=ref.RIGHT_MARGIN' => 'this.RIGHT_MARGIN'
539 )
540 ),
541 'CHILDREN' => array(
542 'data_type' => 'Bitrix\Sale\Location\Location',
543 'reference' => array(
544 '=this.ID' => 'ref.PARENT_ID'
545 )
546 ),
547 'EXTERNAL' => array(
548 'data_type' => 'Bitrix\Sale\Location\External',
549 'reference' => array(
550 '=this.ID' => 'ref.LOCATION_ID'
551 )
552 ),
553 'DEFAULT_SITE' => array(
554 'data_type' => 'Bitrix\Sale\Location\DefaultSite',
555 'reference' => array(
556 '=this.CODE' => 'ref.LOCATION_CODE'
557 )
558 ),
559
560 'CNT' => array(
561 'data_type' => 'integer',
562 'expression' => array(
563 'count(*)'
564 )
565 ),
566 'CHILDREN_CNT' => array(
567 'data_type' => 'integer',
568 'expression' => array(
569 'count(%s)',
570 'CHILD.ID'
571 )
572 ),
573 'IS_PARENT' => array(
574 'data_type' => 'boolean',
575 'expression' => array(
576 'case when count(%s) > 0 then 1 else 0 end',
577 'CHILD.ID'
578 )
579 ),
580
581 // do not remove unless you want migrator to be dead
582 'COUNTRY_ID' => array(
583 'data_type' => 'integer',
584 ),
585 'REGION_ID' => array(
586 'data_type' => 'integer',
587 ),
588 'CITY_ID' => array(
589 'data_type' => 'integer',
590 ),
591 'LOC_DEFAULT' => array(
592 'data_type' => 'string',
593 ),
594
595 // deprecated aliases
596 'CHILD' => array(
597 'data_type' => 'Bitrix\Sale\Location\Location',
598 'reference' => array(
599 '=this.ID' => 'ref.PARENT_ID'
600 )
601 ),
602 'CHILD_CNT' => array(
603 'data_type' => 'integer',
604 'expression' => array(
605 'count(%s)',
606 'CHILD.ID'
607 )
608 ),
609 'DEFAULT_SORT' => array(
610 'data_type' => 'Bitrix\Sale\Location\DefaultSiteTable',
611 'reference' => array(
612 '=this.CODE' => 'ref.LOCATION_CODE'
613 )
614 ),
615
616 );
617 }
618
622 public static function getListFast($parameters = array())
623 {
624 // here $parameters conversion required
625
626 if(isset($parameters['filter']['NAME']))
627 {
628 $parameters['filter']['PHRASE'] = $parameters['filter']['NAME'];
629 unset($parameters['filter']['NAME']);
630 }
631
632 if(isset($parameters['filter']['LANGUAGE_ID']))
633 {
634 $parameters['filter']['NAME.LANGUAGE_ID'] = $parameters['filter']['LANGUAGE_ID'];
635 unset($parameters['filter']['LANGUAGE_ID']);
636 }
637
638 return \Bitrix\Sale\Location\Search\Finder::find($parameters, array('USE_INDEX' => false, 'USE_ORM' => false));
639 }
640}
641
$type
Определения options.php:106
static getConnection($name="")
Определения application.php:638
static updateMultipleForOwner($primaryOwner, $external)
Определения external.php:73
static deleteMultipleForOwner($primaryOwner)
Определения external.php:134
static addMultipleForOwner($primaryOwner, $external=array())
Определения external.php:46
static deleteMultipleByParentRangeSql($sql)
Определения external.php:155
static updateExtended($primary, array $data, array $additional=array())
Определения location.php:247
static resetLegacyPath()
Определения location.php:394
static getMap()
Определения location.php:463
static getExternalData($primary, $parameters=array())
Определения location.php:356
static getCodeValidators()
Определения location.php:456
static getListFast($parameters=array())
Определения location.php:622
static getFilePath()
Определения location.php:40
static add(array $data)
Определения location.php:133
static resetLegacy($typeId)
Определения location.php:211
static getByCode($code='', $parameters=array())
Определения location.php:59
static checkFields(Entity\Result $result, $primary, array $data)
Определения location.php:72
static addExtended(array $data, array $additional=array())
Определения location.php:162
static checkNodeIsParentOfNode($primary, $childPrimary, $behaviour=array('ACCEPT_CODE'=> false, 'CHECK_DIRECT'=> false))
Определения location.php:383
static deleteExtended($primary, array $additional=array())
Определения location.php:312
static update($primary, array $data)
Определения location.php:218
static getTableName()
Определения location.php:45
static getPathToNodeByCode($code, $parameters, $behaviour=array('SHOW_LEAF'=> true))
Определения location.php:376
static deleteMultipleForOwner($primaryOwner)
Определения nameentity.php:165
static addMultipleForOwner($primaryOwner, $names=array())
Определения nameentity.php:34
static deleteMultipleByParentRangeSql($sql)
Определения nameentity.php:249
static updateMultipleForOwner($primaryOwner, $names)
Определения nameentity.php:93
static setIndexInvalid()
Определения finder.php:40
static applyRestrictions(&$data)
Определения tree.php:985
static getPathToNodeByCondition($filter, $parameters=array(), $behaviour=array('SHOW_LEAF'=> true))
Определения tree.php:379
$data['IS_AVAILABLE']
Определения .description.php:13
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
Определения options.php:195
$name
Определения menu_edit.php:35
Определения ufield.php:9
$GLOBALS['____1690880296']
Определения license.php:1
$error
Определения subscription_card_product.php:20