12namespace Bitrix\Sale\Location;
16use Bitrix\Main\Entity;
17use Bitrix\Main\Localization\Loc;
19use Bitrix\Sale\Location\Util\Assert;
20use Bitrix\Sale\Location\DB\BlockInserter;
21use Bitrix\Sale\Location\DB\Helper;
23Loc::loadMessages(__FILE__);
25abstract class Tree extends Entity\DataManager
39 return self::addExtended(
$data);
48 $rebalance = !isset($additional[
'REBALANCE']) || $additional[
'REBALANCE'] !==
false;
51 $parentId = (int)(
$data[
'PARENT_ID'] ?? 0);
56 $node = self::getNodeInfo($parentId);
60 $data[
'LEFT_MARGIN'] = $node[
'RIGHT_MARGIN'];
61 $data[
'RIGHT_MARGIN'] = $node[
'RIGHT_MARGIN'] + 1;
62 $data[
'DEPTH_LEVEL'] = $node[
'DEPTH_LEVEL'] + 1;
63 $data[
'PARENT_ID'] = $node[
'ID'];
70 $rm = self::getMaxMargin();
73 $data[
'LEFT_MARGIN'] = $rm > 1 ? $rm + 1 : 1;
74 $data[
'RIGHT_MARGIN'] = $rm > 1 ? $rm + 2 : 2;
76 $data[
'DEPTH_LEVEL'] = 1;
77 $data[
'PARENT_ID'] = 0;
83 $addResult = parent::add(
$data);
85 if ($addResult->isSuccess() && $needResort && $rebalance)
87 self::rebalance($node, $addResult->getId());
95 self::manageFreeSpace($node[
'RIGHT_MARGIN'], 2, self::SPACE_ADD, $id);
106 foreach (static::getEntity()->getFields() as $field)
108 if($field->getName() ==
'PARENT_ID' && mb_strlen(
$data[
'PARENT_ID']))
111 if(intval($primary[
'ID']) == intval(
$data[
'PARENT_ID']))
115 Loc::getMessage(
'SALE_LOCATION_TREE_ENTITY_CANNOT_MOVE_STRAIGHT_TO_ITSELF_EXCEPTION'),
116 Entity\FieldError::INVALID_VALUE
123 $node = self::getNodeInfo($primary[
'ID']);
124 $nodeDst = self::getNodeInfo(
$data[
'PARENT_ID']);
127 if($node[
'PARENT_ID'] != $nodeDst[
'ID'])
129 if($nodeDst[
'LEFT_MARGIN'] >= $node[
'LEFT_MARGIN'] && $nodeDst[
'RIGHT_MARGIN'] <= $node[
'RIGHT_MARGIN'])
133 Loc::getMessage(
'SALE_LOCATION_TREE_ENTITY_CANNOT_MOVE_TO_ITSELF_EXCEPTION'),
134 Entity\FieldError::INVALID_VALUE
150 return self::update($primary,
$data);
159 $rebalance = !isset($additional[
'REBALANCE']) || $additional[
'REBALANCE'] !==
false;
160 $node = self::getNodeInfo($primary);
162 if(isset(
$data[
'PARENT_ID']) && !mb_strlen(
$data[
'PARENT_ID']))
163 $data[
'PARENT_ID'] = 0;
165 $updResult = parent::update($primary,
$data);
168 if($updResult->isSuccess() && isset(
$data[
'PARENT_ID']) && (intval($node[
'PARENT_ID']) != intval(
$data[
'PARENT_ID'])) && $rebalance)
169 self::moveSubtree($primary,
$data[
'PARENT_ID']);
174 public static function delete($primary)
176 static::deleteExtended($primary);
193 $rebalance = !isset($additional[
'REBALANCE']) || $additional[
'REBALANCE'] !==
false;
194 $deleteSubtree = !isset($additional[
'DELETE_SUBTREE']) || $additional[
'DELETE_SUBTREE'] !==
false;
201 $node = self::getNodeInfo($primary);
202 if(intval($node[
'ID']))
204 static::checkNodeThrowException($node);
206 Main\HttpApplication::getConnection()->query(
'delete from '.static::getTableName().
' where LEFT_MARGIN > '.$node[
'LEFT_MARGIN'].
' and RIGHT_MARGIN < '.$node[
'RIGHT_MARGIN']);
211 self::manageFreeSpace(
212 $node[
'RIGHT_MARGIN'],
213 ($node[
'RIGHT_MARGIN'] - $node[
'LEFT_MARGIN']) + 1,
224 return parent::delete($primary);
234 $primary = Assert::expectIntegerPositive($primary,
'$primary');
238 $node = self::getNodeInfo($primary);
239 if(!intval($node[
'ID']))
245 static::checkNodeThrowException($node);
247 $query =
new Main\Entity\Query(static::getEntity());
250 '>LEFT_MARGIN' => $node[
'LEFT_MARGIN'],
251 '<RIGHT_MARGIN' => $node[
'RIGHT_MARGIN']
254 return $query->getQuery();
259 return !self::getList([
263 [
'LEFT_MARGIN' =>
false],
264 [
'RIGHT_MARGIN' =>
false]
272 $primary = Assert::expectIntegerPositive($primary,
'$primary');
273 $childPrimary = Assert::expectIntegerPositive($childPrimary,
'$childPrimary');
275 return static::checkNodeIsParentOfNodeByCondition(
array(
'=ID' => $primary),
array(
'=ID' => $childPrimary), $behaviour);
280 $parent = static::getList(
array(
'filter' => $parentNodeFilter,
'limit' => 1))->fetch();
281 $child = static::getList(
array(
'filter' => $nodeFilter,
'limit' => 1))->fetch();
283 if(!intval($parent[
'ID']))
285 if(!intval($child[
'ID']))
288 if($behaviour[
'CHECK_DIRECT'])
289 return $parent[
'ID'] == $child[
'PARENT_ID'];
291 return $parent[
'LEFT_MARGIN'] < $child[
'LEFT_MARGIN'] && $parent[
'RIGHT_MARGIN'] > $child[
'RIGHT_MARGIN'];
296 public static function resort($dontCareEvents =
false)
301 $res = parent::getList(
array(
'select' =>
array(
'ID',
'PARENT_ID',
'LEFT_MARGIN',
'RIGHT_MARGIN')));
302 while($item =
$res->Fetch())
304 $nodes[$item[
'ID']] =
array(
305 'LEFT_MARGIN' => $item[
'LEFT_MARGIN'],
306 'RIGHT_MARGIN' => $item[
'RIGHT_MARGIN']
309 if(!intval($item[
'PARENT_ID']))
310 $edges[
'ROOT'][] = $item[
'ID'];
312 $edges[$item[
'PARENT_ID']][] = $item[
'ID'];
316 self::walkTreeInDeep(
'ROOT', $edges, $nodes, 0, 0, $dontCareEvents);
319 $tabName =
'b_sale_location_temp_'.rand(99, 9999);
320 $entityTableName = static::getTableName();
324 $dbConnection->query(
"create table ".$tabName.
" (
325 ID ".Helper::getSqlForDataType(
'int').
",
326 LEFT_MARGIN ".Helper::getSqlForDataType(
'int').
",
327 RIGHT_MARGIN ".Helper::getSqlForDataType(
'int').
",
328 DEPTH_LEVEL ".Helper::getSqlForDataType(
'int').
"
332 'tableName' => $tabName,
333 'exactFields' =>
array(
334 'ID' =>
array(
'data_type' =>
'integer'),
335 'LEFT_MARGIN' =>
array(
'data_type' =>
'integer'),
336 'RIGHT_MARGIN' =>
array(
'data_type' =>
'integer'),
337 'DEPTH_LEVEL' =>
array(
'data_type' =>
'integer'),
339 'parameters' =>
array(
340 'mtu' => self::BLOCK_INSERT_MTU
343 foreach($nodes as $id => $node)
351 Helper::mergeTables($entityTableName, $tabName,
array(
352 'LEFT_MARGIN' =>
'LEFT_MARGIN',
353 'RIGHT_MARGIN' =>
'RIGHT_MARGIN',
354 'DEPTH_LEVEL' =>
'DEPTH_LEVEL'
355 ),
array(
'ID' =>
'ID'));
357 $dbConnection->query(
"drop table {$tabName}");
362 $primary = Assert::expectIntegerPositive($primary,
'$primary');
363 if(!is_array($behaviour))
364 $behaviour =
array();
365 if(!isset($behaviour[
'SHOW_LEAF']))
366 $behaviour[
'SHOW_LEAF'] =
true;
368 return self::getPathToNodeByCondition(
array(
'ID' => $primary), $parameters, $behaviour);
383 if(!is_array($behaviour))
384 $behaviour =
array();
385 if(!isset($behaviour[
'SHOW_LEAF']))
386 $behaviour[
'SHOW_LEAF'] =
true;
388 if(empty($parameters))
389 $parameters =
array();
393 $node = self::getList(
array(
'filter' =>
$filter,
'limit' => 1))->fetch();
394 if(!isset($node[
'ID']))
395 throw new Main\SystemException(Loc::getMessage(
'SALE_LOCATION_TREE_ENTITY_NODE_NOT_FOUND_EXCEPTION'));
397 $parameters[
'filter'][
'<=LEFT_MARGIN'] = intval($node[
'LEFT_MARGIN']);
398 $parameters[
'filter'][
'>=RIGHT_MARGIN'] = intval($node[
'RIGHT_MARGIN']);
400 if(!$behaviour[
'SHOW_LEAF'])
401 $parameters[
'filter'][
'!=ID'] = $node[
'ID'];
403 $parameters[
'order'] =
array(
404 'LEFT_MARGIN' =>
'asc'
407 return self::getList($parameters);
412 Assert::expectNotEmptyArray($nodeInfo,
'$nodeInfo');
414 if(!is_array($behaviour))
415 $behaviour =
array();
416 if(!isset($behaviour[
'SHOW_LEAF']))
417 $behaviour[
'SHOW_LEAF'] =
true;
419 if(empty($parameters))
420 $parameters =
array();
422 if(is_array($parameters[
'select']))
423 $originSelect = $parameters[
'select'];
425 $originSelect =
array();
427 $parameters[
'order'] =
array(
428 'LEFT_MARGIN' =>
'asc'
430 $parameters[
'select'][] =
'ID';
431 $parameters[
'select'][] =
'PARENT_ID';
434 foreach($nodeInfo as $node)
436 Assert::expectNotEmptyArray($node,
'$nodeInfo[]');
437 $node[
'ID'] = Assert::expectIntegerPositive($node[
'ID'],
'$nodeInfo[][ID]');
438 $node[
'LEFT_MARGIN'] = Assert::expectIntegerNonNegative($node[
'LEFT_MARGIN'],
'$nodeInfo[][LEFT_MARGIN]');
439 $node[
'RIGHT_MARGIN'] = Assert::expectIntegerPositive($node[
'RIGHT_MARGIN'],
'$nodeInfo[][RIGHT_MARGIN]');
442 '<=LEFT_MARGIN' => intval($node[
'LEFT_MARGIN']),
443 '>=RIGHT_MARGIN' => intval($node[
'RIGHT_MARGIN'])
446 if(!$behaviour[
'SHOW_LEAF'])
451 $parameters[
'filter'][] =
$filter;
453 $res = self::getList($parameters);
457 while($item =
$res->Fetch())
459 $index[$item[
'ID']] =
array(
461 'PARENT_ID' => $item[
'PARENT_ID']
465 $depthLimit =
count($index);
468 foreach($nodeInfo as $node)
476 if(
$i >= $depthLimit)
479 if(!isset($index[$id]))
482 $resultNode = $index[$id][
'NODE'];
483 if(!in_array(
'PARENT_ID', $originSelect))
484 unset($resultNode[
'PARENT_ID']);
485 if(!in_array(
'ID', $originSelect))
486 unset($resultNode[
'ID']);
487 $path[$id] = $resultNode;
489 $id = intval($index[$id][
'PARENT_ID']);
494 $pathes[$node[
'ID']] =
array(
505 Assert::expectNotEmptyArray($nodeInfo,
'$nodeInfo');
511 foreach($nodeInfo as $node)
513 Assert::expectNotEmptyArray($node,
'$nodeInfo[]');
514 $node[
'LEFT_MARGIN'] = Assert::expectIntegerNonNegative($node[
'LEFT_MARGIN'],
'$nodeInfo[][LEFT_MARGIN]');
515 $node[
'RIGHT_MARGIN'] = Assert::expectIntegerPositive($node[
'RIGHT_MARGIN'],
'$nodeInfo[][RIGHT_MARGIN]');
517 if($min ===
false || $node[
'LEFT_MARGIN'] < $min)
518 $min = $node[
'LEFT_MARGIN'];
520 if(
$max ===
false || $node[
'RIGHT_MARGIN'] >
$max)
521 $max = $node[
'RIGHT_MARGIN'];
524 if(empty($parameters))
525 $parameters =
array();
527 if(!is_array($parameters[
'order']))
528 $parameters[
'order'] =
array();
530 $parameters[
'filter'][
'<LEFT_MARGIN'] = $min;
531 $parameters[
'filter'][
'>RIGHT_MARGIN'] =
$max;
533 $parameters[
'order'] = array_merge(
array(
534 'LEFT_MARGIN' =>
'desc',
535 'RIGHT_MARGIN' =>
'asc'
536 ), $parameters[
'order']);
538 $parameters[
'limit'] = 1;
540 return static::getList($parameters);
545 if(empty($parameters))
546 $parameters =
array();
548 if($primary = intval($primary))
550 $node = self::getNodeInfo($primary);
552 $parameters[
'filter'][
'>=LEFT_MARGIN'] = intval($node[
'LEFT_MARGIN']);
553 $parameters[
'filter'][
'<=RIGHT_MARGIN'] = intval($node[
'RIGHT_MARGIN']);
554 $parameters[
'filter'][
'!=ID'] = $primary;
555 $parameters[
'filter'][
'DEPTH_LEVEL'] = intval($node[
'DEPTH_LEVEL']) + 1;
558 $parameters[
'filter'][
'DEPTH_LEVEL'] = 1;
560 return self::getList($parameters);
568 if(empty($parameters))
569 $parameters =
array();
571 if($primary = intval($primary))
573 $node = self::getNodeInfo($primary);
575 $parameters[
'filter'][
'>=LEFT_MARGIN'] = intval($node[
'LEFT_MARGIN']);
576 $parameters[
'filter'][
'<=RIGHT_MARGIN'] = intval($node[
'RIGHT_MARGIN']);
579 if(!is_array($parameters[
'order']) || empty($parameters[
'order']))
580 $parameters[
'order'] =
array(
'LEFT_MARGIN' =>
'asc');
582 return self::getList($parameters);
592 public static function getParentTree($primary, $parameters =
array(), $behaviour =
array(
'SHOW_CHILDREN' =>
true,
'START_FROM' =>
false))
594 $primary = Assert::expectIntegerPositive($primary,
'$primary');
596 if(!is_array($behaviour))
597 $behaviour =
array();
598 if(!isset($behaviour[
'SHOW_CHILDREN']))
599 $behaviour[
'SHOW_CHILDREN'] =
true;
600 if(!isset($behaviour[
'START_FROM']))
601 $behaviour[
'START_FROM'] =
false;
603 if(empty($parameters))
604 $parameters =
array();
606 $startFrom = intval($behaviour[
'START_FROM']);
607 $showChildren = $behaviour[
'SHOW_CHILDREN'];
611 $conditions[] =
array(
619 $res = self::getPathToNode($primary,
array(
620 'select' =>
array(
'ID')
623 $started = !$startFrom;
624 while($item =
$res->Fetch())
626 if($item[
'ID'] == $startFrom)
632 if(!$showChildren && $item[
'ID'] == $primary)
635 $conditions[] =
array(
636 'PARENT_ID' => $item[
'ID']
640 $conditions[
'LOGIC'] =
'OR';
642 $parameters[
'filter'][] = $conditions;
644 if(!is_array($parameters[
'order']) || empty($parameters[
'order']))
645 $parameters[
'order'] =
array(
'LEFT_MARGIN' =>
'asc');
648 return self::getList($parameters);
662 protected final static function moveSubtree($primary, $primaryDst)
664 $node = self::getNodeInfo($primary);
666 if(!($primaryDst = intval($primaryDst)))
668 $rm = self::getMaxMargin();
676 $nodeDst = self::getNodeInfo($primaryDst);
678 $lDst = intval($nodeDst[
'LEFT_MARGIN']);
679 $rDst = intval($nodeDst[
'RIGHT_MARGIN']);
680 $dDst = intval($nodeDst[
'DEPTH_LEVEL']);
683 $lSub = intval($node[
'LEFT_MARGIN']);
684 $rSub = intval($node[
'RIGHT_MARGIN']);
685 $dSub = intval($node[
'DEPTH_LEVEL']);
687 $tableName = static::getTableName();
689 $sql =
"update ".$tableName.
" set
694 LEFT_MARGIN between {$lSub} and {$rSub}
696 DEPTH_LEVEL + ".($dDst - $dSub + 1).
"
706 if ($lDst < $lSub && $rDst > $rSub && $dDst < ($dSub - 1))
713 RIGHT_MARGIN between ".($rSub + 1).
" and ".($rDst - 1).
"
715 RIGHT_MARGIN - ".($rSub - $lSub + 1).
"
718 LEFT_MARGIN between ".$lSub.
" and ".$rSub.
"
720 RIGHT_MARGIN + ".((($rDst - $rSub - $dSub + $dDst) / 2) * 2 + $dSub - $dDst - 1).
"
728 LEFT_MARGIN between ".($rSub + 1).
" and ".($rDst - 1).
"
730 LEFT_MARGIN - ".($rSub - $lSub + 1).
"
733 LEFT_MARGIN between ".$lSub.
" and ".$rSub.
"
735 LEFT_MARGIN + ".((($rDst - $rSub - $dSub + $dDst) / 2) * 2 + $dSub - $dDst - 1).
"
741 where LEFT_MARGIN between ".($lDst + 1).
" and ".($rDst - 1);
750 LEFT_MARGIN between ".$rDst.
" and ".($lSub-1).
"
752 LEFT_MARGIN + ".($rSub - $lSub + 1).
"
755 LEFT_MARGIN between ".$lSub.
" and ".$rSub.
"
757 LEFT_MARGIN - ".($lSub - $rDst).
"
766 RIGHT_MARGIN between ".$rDst.
" and ".$lSub.
"
768 RIGHT_MARGIN + ".($rSub - $lSub + 1).
"
771 RIGHT_MARGIN between ".$lSub.
" and ".$rSub.
"
773 RIGHT_MARGIN - ".($lSub - $rDst).
"
779 where LEFT_MARGIN between ".$lDst.
" and ".$rSub.
" or RIGHT_MARGIN between ".$lDst.
" and ".$rSub;
788 LEFT_MARGIN between ".$rSub.
" and ".$rDst.
"
790 LEFT_MARGIN - ".($rSub - $lSub + 1).
"
793 LEFT_MARGIN between ".$lSub.
" and ".$rSub.
"
795 LEFT_MARGIN + ".($rDst - $rSub - 1).
"
804 RIGHT_MARGIN between ".($rSub + 1).
" and ".($rDst - 1).
"
805 then RIGHT_MARGIN - ".($rSub - $lSub + 1).
"
808 RIGHT_MARGIN between ".$lSub.
" and ".$rSub.
"
809 then RIGHT_MARGIN + ".($rDst - $rSub - 1).
"
814 where LEFT_MARGIN between ".$lSub.
" and ".$rDst.
" or RIGHT_MARGIN between ".$lSub.
" and ".$rDst;
822 $data[
'INSERT_AFTER'] = intval(
$data[
'INSERT_AFTER']);
823 $data[
'INSERT_BEFORE'] = intval(
$data[
'INSERT_BEFORE']);
825 if(
$data[
'INSERT_AFTER'] ||
$data[
'INSERT_BEFORE'])
827 $neighbourId =
$data[
'INSERT_BEFORE'] ?
$data[
'INSERT_BEFORE'] :
$data[
'INSERT_AFTER'];
829 $sort = self::makeSortSpace(
831 (
$data[
'INSERT_BEFORE'] ? self::SORT_FREE_BEFORE : self::SORT_FREE_AFTER),
833 $data[
'SORT'] ??
false
836 unset(
$data[
'INSERT_AFTER']);
837 unset(
$data[
'INSERT_BEFORE']);
840 $data[
'SORT'] = $sort;
846 if($length <= 1 ||
$right <= 0)
851 $sign = $op == self::SPACE_ADD ?
'+' :
'-';
853 $tableName = static::getTableName();
854 $exceptId = intval($exceptId);
856 $query =
"update {$tableName} set
857 LEFT_MARGIN = case when LEFT_MARGIN > {$right} then LEFT_MARGIN {$sign} {$length} else LEFT_MARGIN end,
858 RIGHT_MARGIN = case when RIGHT_MARGIN >= {$right} then RIGHT_MARGIN {$sign} {$length} else RIGHT_MARGIN end
859 where RIGHT_MARGIN >= {$right}".($exceptId ?
" and ID <> {$exceptId}" :
"");
864 throw new Main\SystemException(
'Query failed: managing free space in a tree', 0, __FILE__, __LINE__);
870 $primary = Assert::expectIntegerPositive($primary,
'$primary');
871 $primaryParent = Assert::expectIntegerPositive($primary,
'$primaryParent');
880 $res = self::getChildren($primaryParent,
array(
'select' =>
array(
'ID',
'SORT',
'CODE'),
'order' =>
array(
'SORT' =>
'asc')));
881 while($item =
$res->Fetch())
883 if($nodeFound && !$nextNodeId)
884 $nextNodeId = $item[
'ID'];
886 if($item[
'ID'] == $primary)
892 $sorts[$item[
'ID']] = $item[
'SORT'];
904 $sorts =
array(
'FH' => 0) + $sorts;
909 $sorts[
'FT'] = PHP_INT_MAX;
916 if($knownSort && ($knownSort < $sorts[$prevNodeId]) && ($knownSort < $sorts[$primary]))
920 if($sorts[$primary] - $sorts[$prevNodeId] > 1)
921 return $sorts[$prevNodeId] + 1;
923 $startShift = $primary;
924 $return = $sorts[$prevNodeId] + self::SORT_HOLE_SIZE_HALF;
928 if($knownSort && ($knownSort < $sorts[$primary]) && ($knownSort < $sorts[$nextNodeId]))
932 if($sorts[$nextNodeId] - $sorts[$primary] > 1)
933 return $sorts[$primary] + 1;
935 $startShift = $nextNodeId;
936 $return = $sorts[$primary] + self::SORT_HOLE_SIZE_HALF;
941 $shift = $sorts[$startShift] + self::SORT_HOLE_SIZE;
943 foreach($sorts as $id => $sVal)
945 if($id == $startShift)
948 if($begin && $sVal <= $shift)
950 $shift = $sVal + self::SORT_HOLE_SIZE;
951 parent::update($id,
array(
'SORT' => $shift));
959 protected final static function walkTreeInDeep($primary, $edges, &$nodes,
$margin, $depth = 0, $dontCareEvents =
false)
963 if(empty($edges[$primary]))
968 foreach($edges[$primary] as $sNode)
969 $offset = self::walkTreeInDeep($sNode, $edges, $nodes, $offset, $depth+1, $dontCareEvents);
975 if($primary !=
'ROOT')
977 $nodes[$primary][
'LEFT_MARGIN'] = intval($lMargin);
978 $nodes[$primary][
'RIGHT_MARGIN'] = intval($rMargin);
979 $nodes[$primary][
'DEPTH_LEVEL'] = $depth;
987 unset(
$data[
'LEFT_MARGIN']);
988 unset(
$data[
'RIGHT_MARGIN']);
989 unset(
$data[
'DEPTH_LEVEL']);
994 $primary = Assert::expectIntegerPositive($primary,
'$primary');
996 $node = self::getById($primary)->fetch();
997 if(!isset($node[
'ID']))
999 throw new Main\SystemException(Loc::getMessage(
'SALE_LOCATION_TREE_ENTITY_NODE_NOT_FOUND_EXCEPTION'));
1007 $row = static::getRow([
1012 'RIGHT_MARGIN' =>
'DESC',
1016 return (
int)($row[
'RIGHT_MARGIN'] ?? 0);
1022 $dbHelper = $dbConnection->getSqlHelper();
1024 $temporalTabName = Assert::expectStringNotNull($temporalTabName,
false,
'Name of temporal table must be a non-zero length string');
1025 $temporalTabName = $dbHelper->forSql($temporalTabName);
1027 $entityTableName = static::getTableName();
1029 if(!is_array($additinalFlds))
1030 $additinalFlds =
array();
1032 $additinalFlds = array_merge(
array(
'LEFT_MARGIN',
'RIGHT_MARGIN',
'DEPTH_LEVEL'), $additinalFlds);
1034 $fldReplace =
array();
1035 foreach($additinalFlds as &$fld)
1037 $fld = $dbHelper->forSql($fld);
1038 $fldReplace[$fld] = is_array($fldMap) && isset($fldMap[$fld]) ? $dbHelper->forSql($fldMap[$fld]) : $fld;
1041 $idReplace = is_array($fldMap) && isset($fldMap[
'ID']) ? $dbHelper->forSql($fldMap[
'ID']) :
'ID';
1043 if ($dbConnection->getType() ===
'mysql')
1045 $sql =
'update '.$entityTableName.
', '.$temporalTabName.
' set ';
1046 $additFldCnt =
count($additinalFlds);
1048 for(
$i = 0;
$i < $additFldCnt;
$i++)
1050 $sql .= $entityTableName.
'.'.$additinalFlds[
$i].
' = '.$temporalTabName.
'.'.$fldReplace[$additinalFlds[
$i]].($i ==
count($additinalFlds) - 1 ?
'' :
', ');
1053 $sql .=
' where '.$entityTableName.
'.ID = '.$temporalTabName.
'.'.$idReplace;
1055 elseif ($dbConnection->getType() ===
'pgsql')
1057 $sql =
'update '.$entityTableName.
' set ('.
1058 implode(
', ', $additinalFlds).
1060 implode(
', ', $fldReplace).
1061 ' from '.$temporalTabName.
' where '.$entityTableName.
'.ID = '.$temporalTabName.
'.'.$idReplace.
')';
1063 elseif ($dbConnection->getType() ===
'mssql')
1065 $sql =
'update '.$entityTableName.
' set ';
1066 $additFldCnt =
count($additinalFlds);
1068 for(
$i = 0;
$i < $additFldCnt;
$i++)
1070 $sql .= $additinalFlds[
$i].
' = '.$temporalTabName.
'.'.$fldReplace[$additinalFlds[
$i]].($i ==
count($additinalFlds) - 1 ?
'' :
', ');
1073 $sql .=
' from '.$entityTableName.
' join '.$temporalTabName.
' on '.$entityTableName.
'.ID = '.$temporalTabName.
'.'.$idReplace;
1075 elseif ($dbConnection->getType() ===
'oracle')
1079 $sql =
'update '.$entityTableName.
' set ('.
1080 implode(
', ', $additinalFlds).
1082 implode(
', ', $fldReplace).
1083 ' from '.$temporalTabName.
' where '.$entityTableName.
'.ID = '.$temporalTabName.
'.'.$idReplace.
')';
1086 $dbConnection->query($sql);
1094 'data_type' =>
'integer',
1095 'expression' =>
array(
'COUNT(*)')
1098 'select' =>
array(
'CNT')
1106 return intval(
$res[
'CNT']);
1112 if(!is_numeric($node[
'LEFT_MARGIN']) || (
int) $node[
'LEFT_MARGIN'] < 0 || !intval($node[
'RIGHT_MARGIN']) || !intval($node[
'ID']))
1118 'ID' => $node[
'ID'],
1119 'CODE' => $node[
'CODE'],
1120 'LEFT_MARGIN' => $node[
'LEFT_MARGIN'],
1121 'RIGHT_MARGIN' => $node[
'RIGHT_MARGIN']
1129 return static::checkNodeIsParentOfNodeByCondition($parentNodeFilter, $nodeFilter, $behaviour);
static getConnection($name="")
static getPathToNode($primary, $parameters, $behaviour=array('SHOW_LEAF'=> true))
static getDeepestCommonParent($nodeInfo=array(), $parameters=array())
static updateExtended($primary, array $data, array $additional=array())
static checkNodeIsParentOfNodeByFilters($parentNodeFilter, $nodeFilter, $behaviour=array('CHECK_DIRECT'=> false))
static walkTreeInDeep($primary, $edges, &$nodes, $margin, $depth=0, $dontCareEvents=false)
static getParentTree($primary, $parameters=array(), $behaviour=array('SHOW_CHILDREN'=> true, 'START_FROM'=> false))
static applyRestrictions(&$data)
static getSubtreeRangeSqlForNode($primary, $node=array())
static processInsertInstruction(&$data)
static getNodeInfo($primary)
const SORT_HOLE_SIZE_HALF
static resort($dontCareEvents=false)
static makeSortSpace($primary, $direction, $primaryParent, $knownSort=false)
static mergeRelationsFromTemporalTable($temporalTabName, $additinalFlds=array(), $fldMap=array())
static rebalance($node, $id)
static checkNodeIsParentOfNodeById($primary, $childPrimary, $behaviour=array('CHECK_DIRECT'=> false))
static getChildren($primary, $parameters=array())
static moveSubtree($primary, $primaryDst)
PROTECTED.
static getPathToMultipleNodes($nodeInfo=array(), $parameters=array(), $behaviour=array('SHOW_LEAF'=> true))
static checkNodeThrowException($node)
static getCountByFilter($filter=array())
static checkFields(Entity\Result $result, $primary, array $data)
static addExtended(array $data, array $additional=array())
static checkNodeIsParentOfNodeByCondition($parentNodeFilter, $nodeFilter, $behaviour=array('CHECK_DIRECT'=> false))
static getPathToNodeByCondition($filter, $parameters=array(), $behaviour=array('SHOW_LEAF'=> true))
static deleteExtended($primary, array $additional=array())
static update($primary, array $data)
static manageFreeSpace($right, $length=2, $op=self::SPACE_ADD, $exceptId=false)
static getSubTree($primary, $parameters=array())
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
if(CSalePaySystemAction::GetParamValue('BACKGROUND', false)) $margin
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']