25abstract class Tree extends Entity\DataManager
37 public static function add(array $data)
39 return self::addExtended($data);
46 public static function addExtended(array $data, array $additional = array())
48 $rebalance = !isset($additional[
'REBALANCE']) || $additional[
'REBALANCE'] !==
false;
51 if($data[
'PARENT_ID'] = intval($data[
'PARENT_ID']))
54 $node = self::getNodeInfo($data[
'PARENT_ID']);
58 $data[
'LEFT_MARGIN'] = $node[
'RIGHT_MARGIN'];
59 $data[
'RIGHT_MARGIN'] = $node[
'RIGHT_MARGIN'] + 1;
60 $data[
'DEPTH_LEVEL'] = $node[
'DEPTH_LEVEL'] + 1;
61 $data[
'PARENT_ID'] = $node[
'ID'];
68 $rm = self::getMaxMargin();
71 $data[
'LEFT_MARGIN'] = $rm > 1 ? $rm + 1 : 1;
72 $data[
'RIGHT_MARGIN'] = $rm > 1 ? $rm + 2 : 2;
74 $data[
'DEPTH_LEVEL'] = 1;
75 $data[
'PARENT_ID'] = 0;
81 $addResult = parent::add($data);
83 if($addResult->isSuccess() && $needResort && $rebalance)
84 self::rebalance($node, $addResult->getId());
91 self::manageFreeSpace($node[
'RIGHT_MARGIN'], 2, self::SPACE_ADD, $id);
97 parent::checkFields($result, $primary, $data);
102 foreach (static::getEntity()->getFields() as $field)
104 if($field->getName() ==
'PARENT_ID' && mb_strlen($data[
'PARENT_ID']))
107 if(intval($primary[
'ID']) == intval($data[
'PARENT_ID']))
111 Loc::getMessage(
'SALE_LOCATION_TREE_ENTITY_CANNOT_MOVE_STRAIGHT_TO_ITSELF_EXCEPTION'),
112 Entity\FieldError::INVALID_VALUE
119 $node = self::getNodeInfo($primary[
'ID']);
120 $nodeDst = self::getNodeInfo($data[
'PARENT_ID']);
123 if($node[
'PARENT_ID'] != $nodeDst[
'ID'])
125 if($nodeDst[
'LEFT_MARGIN'] >= $node[
'LEFT_MARGIN'] && $nodeDst[
'RIGHT_MARGIN'] <= $node[
'RIGHT_MARGIN'])
129 Loc::getMessage(
'SALE_LOCATION_TREE_ENTITY_CANNOT_MOVE_TO_ITSELF_EXCEPTION'),
130 Entity\FieldError::INVALID_VALUE
144 public static function update($primary, array $data)
146 return self::update($primary, $data);
153 public static function updateExtended($primary, array $data, array $additional = array())
155 $rebalance = !isset($additional[
'REBALANCE']) || $additional[
'REBALANCE'] !==
false;
156 $node = self::getNodeInfo($primary);
158 if(isset($data[
'PARENT_ID']) && !mb_strlen($data[
'PARENT_ID']))
159 $data[
'PARENT_ID'] = 0;
161 $updResult = parent::update($primary, $data);
164 if($updResult->isSuccess() && isset($data[
'PARENT_ID']) && (intval($node[
'PARENT_ID']) != intval($data[
'PARENT_ID'])) && $rebalance)
165 self::moveSubtree($primary, $data[
'PARENT_ID']);
170 public static function delete($primary)
172 static::deleteExtended($primary);
189 $rebalance = !isset($additional[
'REBALANCE']) || $additional[
'REBALANCE'] !==
false;
190 $deleteSubtree = !isset($additional[
'DELETE_SUBTREE']) || $additional[
'DELETE_SUBTREE'] !==
false;
197 $node = self::getNodeInfo($primary);
198 if(intval($node[
'ID']))
200 static::checkNodeThrowException($node);
202 Main\HttpApplication::getConnection()->query(
'delete from '.static::getTableName().
' where LEFT_MARGIN > '.$node[
'LEFT_MARGIN'].
' and RIGHT_MARGIN < '.$node[
'RIGHT_MARGIN']);
207 self::manageFreeSpace(
208 $node[
'RIGHT_MARGIN'],
209 ($node[
'RIGHT_MARGIN'] - $node[
'LEFT_MARGIN']) + 1,
220 return parent::delete($primary);
230 $primary = Assert::expectIntegerPositive($primary,
'$primary');
234 $node = self::getNodeInfo($primary);
235 if(!intval($node[
'ID']))
241 static::checkNodeThrowException($node);
243 $query =
new Main\Entity\Query(static::getEntity());
244 $query->setSelect(array(
'ID'));
245 $query->setFilter(array(
246 '>LEFT_MARGIN' => $node[
'LEFT_MARGIN'],
247 '<RIGHT_MARGIN' => $node[
'RIGHT_MARGIN']
250 return $query->getQuery();
255 return !self::getList([
259 [
'LEFT_MARGIN' =>
false],
260 [
'RIGHT_MARGIN' =>
false]
268 $primary = Assert::expectIntegerPositive($primary,
'$primary');
269 $childPrimary = Assert::expectIntegerPositive($childPrimary,
'$childPrimary');
271 return static::checkNodeIsParentOfNodeByCondition(array(
'=ID' => $primary), array(
'=ID' => $childPrimary), $behaviour);
276 $parent = static::getList(array(
'filter' => $parentNodeFilter,
'limit' => 1))->fetch();
277 $child = static::getList(array(
'filter' => $nodeFilter,
'limit' => 1))->fetch();
279 if(!intval($parent[
'ID']))
281 if(!intval($child[
'ID']))
284 if($behaviour[
'CHECK_DIRECT'])
285 return $parent[
'ID'] == $child[
'PARENT_ID'];
287 return $parent[
'LEFT_MARGIN'] < $child[
'LEFT_MARGIN'] && $parent[
'RIGHT_MARGIN'] > $child[
'RIGHT_MARGIN'];
292 public static function resort($dontCareEvents =
false)
297 $res = parent::getList(array(
'select' => array(
'ID',
'PARENT_ID',
'LEFT_MARGIN',
'RIGHT_MARGIN')));
298 while($item = $res->Fetch())
300 $nodes[$item[
'ID']] = array(
301 'LEFT_MARGIN' => $item[
'LEFT_MARGIN'],
302 'RIGHT_MARGIN' => $item[
'RIGHT_MARGIN']
305 if(!intval($item[
'PARENT_ID']))
306 $edges[
'ROOT'][] = $item[
'ID'];
308 $edges[$item[
'PARENT_ID']][] = $item[
'ID'];
312 self::walkTreeInDeep(
'ROOT', $edges, $nodes, 0, 0, $dontCareEvents);
315 $tabName =
'b_sale_location_temp_'.rand(99, 9999);
316 $entityTableName = static::getTableName();
318 $dbConnection = Main\HttpApplication::getConnection();
320 $dbConnection->query(
"create table ".$tabName.
" (
321 ID ".Helper::getSqlForDataType(
'int').
",
322 LEFT_MARGIN ".Helper::getSqlForDataType(
'int').
",
323 RIGHT_MARGIN ".Helper::getSqlForDataType(
'int').
",
324 DEPTH_LEVEL ".Helper::getSqlForDataType(
'int').
"
328 'tableName' => $tabName,
329 'exactFields' => array(
330 'ID' => array(
'data_type' =>
'integer'),
331 'LEFT_MARGIN' => array(
'data_type' =>
'integer'),
332 'RIGHT_MARGIN' => array(
'data_type' =>
'integer'),
333 'DEPTH_LEVEL' => array(
'data_type' =>
'integer'),
335 'parameters' => array(
336 'mtu' => self::BLOCK_INSERT_MTU
339 foreach($nodes as $id => $node)
342 $handle->insert($node);
347 Helper::mergeTables($entityTableName, $tabName, array(
348 'LEFT_MARGIN' =>
'LEFT_MARGIN',
349 'RIGHT_MARGIN' =>
'RIGHT_MARGIN',
350 'DEPTH_LEVEL' =>
'DEPTH_LEVEL'
351 ), array(
'ID' =>
'ID'));
353 $dbConnection->query(
"drop table {$tabName}");
356 public static function getPathToNode($primary, $parameters, $behaviour = array(
'SHOW_LEAF' =>
true))
358 $primary = Assert::expectIntegerPositive($primary,
'$primary');
359 if(!is_array($behaviour))
360 $behaviour = array();
361 if(!isset($behaviour[
'SHOW_LEAF']))
362 $behaviour[
'SHOW_LEAF'] =
true;
364 return self::getPathToNodeByCondition(array(
'ID' => $primary), $parameters, $behaviour);
377 $filter = Assert::expectNotEmptyArray($filter,
'$filter');
379 if(!is_array($behaviour))
380 $behaviour = array();
381 if(!isset($behaviour[
'SHOW_LEAF']))
382 $behaviour[
'SHOW_LEAF'] =
true;
384 if(empty($parameters))
385 $parameters = array();
389 $node = self::getList(array(
'filter' => $filter,
'limit' => 1))->fetch();
390 if(!isset($node[
'ID']))
393 $parameters[
'filter'][
'<=LEFT_MARGIN'] = intval($node[
'LEFT_MARGIN']);
394 $parameters[
'filter'][
'>=RIGHT_MARGIN'] = intval($node[
'RIGHT_MARGIN']);
396 if(!$behaviour[
'SHOW_LEAF'])
397 $parameters[
'filter'][
'!=ID'] = $node[
'ID'];
399 $parameters[
'order'] = array(
400 'LEFT_MARGIN' =>
'asc'
403 return self::getList($parameters);
406 public static function getPathToMultipleNodes($nodeInfo = array(), $parameters = array(), $behaviour = array(
'SHOW_LEAF' =>
true))
408 Assert::expectNotEmptyArray($nodeInfo,
'$nodeInfo');
410 if(!is_array($behaviour))
411 $behaviour = array();
412 if(!isset($behaviour[
'SHOW_LEAF']))
413 $behaviour[
'SHOW_LEAF'] =
true;
415 if(empty($parameters))
416 $parameters = array();
418 if(is_array($parameters[
'select']))
419 $originSelect = $parameters[
'select'];
421 $originSelect = array();
423 $parameters[
'order'] = array(
424 'LEFT_MARGIN' =>
'asc'
426 $parameters[
'select'][] =
'ID';
427 $parameters[
'select'][] =
'PARENT_ID';
430 foreach($nodeInfo as $node)
432 Assert::expectNotEmptyArray($node,
'$nodeInfo[]');
433 $node[
'ID'] = Assert::expectIntegerPositive($node[
'ID'],
'$nodeInfo[][ID]');
434 $node[
'LEFT_MARGIN'] = Assert::expectIntegerNonNegative($node[
'LEFT_MARGIN'],
'$nodeInfo[][LEFT_MARGIN]');
435 $node[
'RIGHT_MARGIN'] = Assert::expectIntegerPositive($node[
'RIGHT_MARGIN'],
'$nodeInfo[][RIGHT_MARGIN]');
438 '<=LEFT_MARGIN' => intval($node[
'LEFT_MARGIN']),
439 '>=RIGHT_MARGIN' => intval($node[
'RIGHT_MARGIN'])
442 if(!$behaviour[
'SHOW_LEAF'])
443 $filter[
'!=ID'] = $node[
'ID'];
445 $filter[
'LOGIC'] =
'OR';
447 $parameters[
'filter'][] = $filter;
449 $res = self::getList($parameters);
453 while($item = $res->Fetch())
455 $index[$item[
'ID']] = array(
457 'PARENT_ID' => $item[
'PARENT_ID']
461 $depthLimit = count($index);
464 foreach($nodeInfo as $node)
472 if($i >= $depthLimit)
475 if(!isset($index[$id]))
478 $resultNode = $index[$id][
'NODE'];
479 if(!in_array(
'PARENT_ID', $originSelect))
480 unset($resultNode[
'PARENT_ID']);
481 if(!in_array(
'ID', $originSelect))
482 unset($resultNode[
'ID']);
483 $path[$id] = $resultNode;
485 $id = intval($index[$id][
'PARENT_ID']);
490 $pathes[$node[
'ID']] = array(
501 Assert::expectNotEmptyArray($nodeInfo,
'$nodeInfo');
507 foreach($nodeInfo as $node)
509 Assert::expectNotEmptyArray($node,
'$nodeInfo[]');
510 $node[
'LEFT_MARGIN'] = Assert::expectIntegerNonNegative($node[
'LEFT_MARGIN'],
'$nodeInfo[][LEFT_MARGIN]');
511 $node[
'RIGHT_MARGIN'] = Assert::expectIntegerPositive($node[
'RIGHT_MARGIN'],
'$nodeInfo[][RIGHT_MARGIN]');
513 if($min ===
false || $node[
'LEFT_MARGIN'] < $min)
514 $min = $node[
'LEFT_MARGIN'];
516 if($max ===
false || $node[
'RIGHT_MARGIN'] > $max)
517 $max = $node[
'RIGHT_MARGIN'];
520 if(empty($parameters))
521 $parameters = array();
523 if(!is_array($parameters[
'order']))
524 $parameters[
'order'] = array();
526 $parameters[
'filter'][
'<LEFT_MARGIN'] = $min;
527 $parameters[
'filter'][
'>RIGHT_MARGIN'] = $max;
529 $parameters[
'order'] = array_merge(array(
530 'LEFT_MARGIN' =>
'desc',
531 'RIGHT_MARGIN' =>
'asc'
532 ), $parameters[
'order']);
534 $parameters[
'limit'] = 1;
536 return static::getList($parameters);
539 public static function getChildren($primary, $parameters = array())
541 if(empty($parameters))
542 $parameters = array();
544 if($primary = intval($primary))
546 $node = self::getNodeInfo($primary);
548 $parameters[
'filter'][
'>=LEFT_MARGIN'] = intval($node[
'LEFT_MARGIN']);
549 $parameters[
'filter'][
'<=RIGHT_MARGIN'] = intval($node[
'RIGHT_MARGIN']);
550 $parameters[
'filter'][
'!=ID'] = $primary;
551 $parameters[
'filter'][
'DEPTH_LEVEL'] = intval($node[
'DEPTH_LEVEL']) + 1;
554 $parameters[
'filter'][
'DEPTH_LEVEL'] = 1;
556 return self::getList($parameters);
562 public static function getSubTree($primary, $parameters = array())
564 if(empty($parameters))
565 $parameters = array();
567 if($primary = intval($primary))
569 $node = self::getNodeInfo($primary);
571 $parameters[
'filter'][
'>=LEFT_MARGIN'] = intval($node[
'LEFT_MARGIN']);
572 $parameters[
'filter'][
'<=RIGHT_MARGIN'] = intval($node[
'RIGHT_MARGIN']);
575 if(!is_array($parameters[
'order']) || empty($parameters[
'order']))
576 $parameters[
'order'] = array(
'LEFT_MARGIN' =>
'asc');
578 return self::getList($parameters);
588 public static function getParentTree($primary, $parameters = array(), $behaviour = array(
'SHOW_CHILDREN' =>
true,
'START_FROM' =>
false))
590 $primary = Assert::expectIntegerPositive($primary,
'$primary');
592 if(!is_array($behaviour))
593 $behaviour = array();
594 if(!isset($behaviour[
'SHOW_CHILDREN']))
595 $behaviour[
'SHOW_CHILDREN'] =
true;
596 if(!isset($behaviour[
'START_FROM']))
597 $behaviour[
'START_FROM'] =
false;
599 if(empty($parameters))
600 $parameters = array();
602 $startFrom = intval($behaviour[
'START_FROM']);
603 $showChildren = $behaviour[
'SHOW_CHILDREN'];
607 $conditions[] = array(
615 $res = self::getPathToNode($primary, array(
616 'select' => array(
'ID')
619 $started = !$startFrom;
620 while($item = $res->Fetch())
622 if($item[
'ID'] == $startFrom)
628 if(!$showChildren && $item[
'ID'] == $primary)
631 $conditions[] = array(
632 'PARENT_ID' => $item[
'ID']
636 $conditions[
'LOGIC'] =
'OR';
638 $parameters[
'filter'][] = $conditions;
640 if(!is_array($parameters[
'order']) || empty($parameters[
'order']))
641 $parameters[
'order'] = array(
'LEFT_MARGIN' =>
'asc');
644 return self::getList($parameters);
658 protected final static function moveSubtree($primary, $primaryDst)
660 $node = self::getNodeInfo($primary);
662 if(!($primaryDst = intval($primaryDst)))
664 $rm = self::getMaxMargin();
672 $nodeDst = self::getNodeInfo($primaryDst);
674 $lDst = intval($nodeDst[
'LEFT_MARGIN']);
675 $rDst = intval($nodeDst[
'RIGHT_MARGIN']);
676 $dDst = intval($nodeDst[
'DEPTH_LEVEL']);
679 $lSub = intval($node[
'LEFT_MARGIN']);
680 $rSub = intval($node[
'RIGHT_MARGIN']);
681 $dSub = intval($node[
'DEPTH_LEVEL']);
683 $tableName = static::getTableName();
685 $sql =
"update ".$tableName.
" set
690 LEFT_MARGIN between {$lSub} and {$rSub}
692 DEPTH_LEVEL + ".($dDst - $dSub + 1).
"
702 if ($lDst < $lSub && $rDst > $rSub && $dDst < ($dSub - 1))
709 RIGHT_MARGIN between ".($rSub + 1).
" and ".($rDst - 1).
"
711 RIGHT_MARGIN - ".($rSub - $lSub + 1).
"
714 LEFT_MARGIN between ".$lSub.
" and ".$rSub.
"
716 RIGHT_MARGIN + ".((($rDst - $rSub - $dSub + $dDst) / 2) * 2 + $dSub - $dDst - 1).
"
724 LEFT_MARGIN between ".($rSub + 1).
" and ".($rDst - 1).
"
726 LEFT_MARGIN - ".($rSub - $lSub + 1).
"
729 LEFT_MARGIN between ".$lSub.
" and ".$rSub.
"
731 LEFT_MARGIN + ".((($rDst - $rSub - $dSub + $dDst) / 2) * 2 + $dSub - $dDst - 1).
"
737 where LEFT_MARGIN between ".($lDst + 1).
" and ".($rDst - 1);
739 elseif($lDst < $lSub)
746 LEFT_MARGIN between ".$rDst.
" and ".($lSub-1).
"
748 LEFT_MARGIN + ".($rSub - $lSub + 1).
"
751 LEFT_MARGIN between ".$lSub.
" and ".$rSub.
"
753 LEFT_MARGIN - ".($lSub - $rDst).
"
762 RIGHT_MARGIN between ".$rDst.
" and ".$lSub.
"
764 RIGHT_MARGIN + ".($rSub - $lSub + 1).
"
767 RIGHT_MARGIN between ".$lSub.
" and ".$rSub.
"
769 RIGHT_MARGIN - ".($lSub - $rDst).
"
775 where LEFT_MARGIN between ".$lDst.
" and ".$rSub.
" or RIGHT_MARGIN between ".$lDst.
" and ".$rSub;
784 LEFT_MARGIN between ".$rSub.
" and ".$rDst.
"
786 LEFT_MARGIN - ".($rSub - $lSub + 1).
"
789 LEFT_MARGIN between ".$lSub.
" and ".$rSub.
"
791 LEFT_MARGIN + ".($rDst - $rSub - 1).
"
800 RIGHT_MARGIN between ".($rSub + 1).
" and ".($rDst - 1).
"
801 then RIGHT_MARGIN - ".($rSub - $lSub + 1).
"
804 RIGHT_MARGIN between ".$lSub.
" and ".$rSub.
"
805 then RIGHT_MARGIN + ".($rDst - $rSub - 1).
"
810 where LEFT_MARGIN between ".$lSub.
" and ".$rDst.
" or RIGHT_MARGIN between ".$lSub.
" and ".$rDst;
813 Main\HttpApplication::getConnection()->query($sql);
818 $data[
'INSERT_AFTER'] = intval($data[
'INSERT_AFTER']);
819 $data[
'INSERT_BEFORE'] = intval($data[
'INSERT_BEFORE']);
821 if($data[
'INSERT_AFTER'] || $data[
'INSERT_BEFORE'])
823 $neighbourId = $data[
'INSERT_BEFORE'] ? $data[
'INSERT_BEFORE'] : $data[
'INSERT_AFTER'];
825 $sort = self::makeSortSpace(
827 ($data[
'INSERT_BEFORE'] ? self::SORT_FREE_BEFORE : self::SORT_FREE_AFTER),
829 $data[
'SORT'] ??
false
832 unset($data[
'INSERT_AFTER']);
833 unset($data[
'INSERT_BEFORE']);
836 $data[
'SORT'] = $sort;
840 protected final static function manageFreeSpace($right, $length = 2, $op = self::SPACE_ADD, $exceptId =
false)
842 if($length <= 1 || $right <= 0)
847 $sign = $op == self::SPACE_ADD ?
'+' :
'-';
849 $tableName = static::getTableName();
850 $exceptId = intval($exceptId);
852 $query =
"update {$tableName} set
853 LEFT_MARGIN = case when LEFT_MARGIN > {$right} then LEFT_MARGIN {$sign} {$length} else LEFT_MARGIN end,
854 RIGHT_MARGIN = case when RIGHT_MARGIN >= {$right} then RIGHT_MARGIN {$sign} {$length} else RIGHT_MARGIN end
855 where RIGHT_MARGIN >= {$right}".($exceptId ?
" and ID <> {$exceptId}" :
"");
857 $shifted = Main\HttpApplication::getConnection()->query($query);
860 throw new Main\SystemException(
'Query failed: managing free space in a tree', 0, __FILE__, __LINE__);
864 protected final static function makeSortSpace($primary, $direction, $primaryParent, $knownSort =
false)
866 $primary = Assert::expectIntegerPositive($primary,
'$primary');
867 $primaryParent = Assert::expectIntegerPositive($primary,
'$primaryParent');
876 $res = self::getChildren($primaryParent, array(
'select' => array(
'ID',
'SORT',
'CODE'),
'order' => array(
'SORT' =>
'asc')));
877 while($item = $res->Fetch())
879 if($nodeFound && !$nextNodeId)
880 $nextNodeId = $item[
'ID'];
882 if($item[
'ID'] == $primary)
888 $sorts[$item[
'ID']] = $item[
'SORT'];
900 $sorts = array(
'FH' => 0) + $sorts;
905 $sorts[
'FT'] = PHP_INT_MAX;
910 if($direction == self::SORT_FREE_BEFORE)
912 if($knownSort && ($knownSort < $sorts[$prevNodeId]) && ($knownSort < $sorts[$primary]))
916 if($sorts[$primary] - $sorts[$prevNodeId] > 1)
917 return $sorts[$prevNodeId] + 1;
919 $startShift = $primary;
920 $return = $sorts[$prevNodeId] + self::SORT_HOLE_SIZE_HALF;
924 if($knownSort && ($knownSort < $sorts[$primary]) && ($knownSort < $sorts[$nextNodeId]))
928 if($sorts[$nextNodeId] - $sorts[$primary] > 1)
929 return $sorts[$primary] + 1;
931 $startShift = $nextNodeId;
932 $return = $sorts[$primary] + self::SORT_HOLE_SIZE_HALF;
937 $shift = $sorts[$startShift] + self::SORT_HOLE_SIZE;
939 foreach($sorts as $id => $sVal)
941 if($id == $startShift)
944 if($begin && $sVal <= $shift)
946 $shift = $sVal + self::SORT_HOLE_SIZE;
947 parent::update($id, array(
'SORT' => $shift));
955 protected final static function walkTreeInDeep($primary, $edges, &$nodes, $margin, $depth = 0, $dontCareEvents =
false)
959 if(empty($edges[$primary]))
960 $rMargin = $margin + 1;
963 $offset = $margin + 1;
964 foreach($edges[$primary] as $sNode)
965 $offset = self::walkTreeInDeep($sNode, $edges, $nodes, $offset, $depth+1, $dontCareEvents);
971 if($primary !=
'ROOT')
973 $nodes[$primary][
'LEFT_MARGIN'] = intval($lMargin);
974 $nodes[$primary][
'RIGHT_MARGIN'] = intval($rMargin);
975 $nodes[$primary][
'DEPTH_LEVEL'] = $depth;
983 unset($data[
'LEFT_MARGIN']);
984 unset($data[
'RIGHT_MARGIN']);
985 unset($data[
'DEPTH_LEVEL']);
990 $primary = Assert::expectIntegerPositive($primary,
'$primary');
992 $node = self::getById($primary)->fetch();
993 if(!isset($node[
'ID']))
1003 $tableName = static::getTableName();
1006 $res = Main\HttpApplication::getConnection()->query(
"select A.RIGHT_MARGIN from {$tableName} A order by A.RIGHT_MARGIN desc")->fetch();
1007 return intval($res[
'RIGHT_MARGIN']);
1012 $dbConnection = Main\HttpApplication::getConnection();
1013 $dbHelper = $dbConnection->getSqlHelper();
1015 $temporalTabName = Assert::expectStringNotNull($temporalTabName,
false,
'Name of temporal table must be a non-zero length string');
1016 $temporalTabName = $dbHelper->forSql($temporalTabName);
1018 $entityTableName = static::getTableName();
1020 if(!is_array($additinalFlds))
1021 $additinalFlds = array();
1023 $additinalFlds = array_merge(array(
'LEFT_MARGIN',
'RIGHT_MARGIN',
'DEPTH_LEVEL'), $additinalFlds);
1025 $fldReplace = array();
1026 foreach($additinalFlds as &$fld)
1028 $fld = $dbHelper->forSql($fld);
1029 $fldReplace[$fld] = is_array($fldMap) && isset($fldMap[$fld]) ? $dbHelper->forSql($fldMap[$fld]) : $fld;
1032 $idReplace = is_array($fldMap) && isset($fldMap[
'ID']) ? $dbHelper->forSql($fldMap[
'ID']) :
'ID';
1034 if($dbConnection->getType() ==
'mysql')
1036 $sql =
'update '.$entityTableName.
', '.$temporalTabName.
' set ';
1037 $additFldCnt = count($additinalFlds);
1039 for($i = 0; $i < $additFldCnt; $i++)
1041 $sql .= $entityTableName.
'.'.$additinalFlds[$i].
' = '.$temporalTabName.
'.'.$fldReplace[$additinalFlds[$i]].($i == count($additinalFlds) - 1 ?
'' :
', ');
1044 $sql .=
' where '.$entityTableName.
'.ID = '.$temporalTabName.
'.'.$idReplace;
1046 elseif($dbConnection->getType() ==
'mssql')
1048 $sql =
'update '.$entityTableName.
' set ';
1049 $additFldCnt = count($additinalFlds);
1051 for($i = 0; $i < $additFldCnt; $i++)
1053 $sql .= $additinalFlds[$i].
' = '.$temporalTabName.
'.'.$fldReplace[$additinalFlds[$i]].($i == count($additinalFlds) - 1 ?
'' :
', ');
1056 $sql .=
' from '.$entityTableName.
' join '.$temporalTabName.
' on '.$entityTableName.
'.ID = '.$temporalTabName.
'.'.$idReplace;
1058 elseif($dbConnection->getType() ==
'oracle')
1062 $sql =
'update '.$entityTableName.
' set ('.
1063 implode(
', ', $additinalFlds).
1065 implode(
', ', $fldReplace).
1066 ' from '.$temporalTabName.
' where '.$entityTableName.
'.ID = '.$temporalTabName.
'.'.$idReplace.
')';
1069 $dbConnection->query($sql);
1077 'data_type' =>
'integer',
1078 'expression' => array(
'COUNT(*)')
1081 'select' => array(
'CNT')
1084 if(is_array($filter))
1085 $params[
'filter'] = $filter;
1087 $res = static::getList($params)->fetch();
1089 return intval($res[
'CNT']);
1095 if(!is_numeric($node[
'LEFT_MARGIN']) || (
int) $node[
'LEFT_MARGIN'] < 0 || !intval($node[
'RIGHT_MARGIN']) || !intval($node[
'ID']))
1101 'ID' => $node[
'ID'],
1102 'CODE' => $node[
'CODE'],
1103 'LEFT_MARGIN' => $node[
'LEFT_MARGIN'],
1104 'RIGHT_MARGIN' => $node[
'RIGHT_MARGIN']
1112 return static::checkNodeIsParentOfNodeByCondition($parentNodeFilter, $nodeFilter, $behaviour);
static loadMessages($file)
static getMessage($code, $replace=null, $language=null)
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())