101 parent::__construct();
104 throw new \Exception(
'Wrong "$connection" parametr');
120 throw new \Exception(
'"$fields" tree configuratin array');
128 $this->_select = $this->_conn->select();
129 $this->_select->from($this->_table);
160 public function load($parentNode =
null, $recursionLevel = 0)
162 if (!$this->_loaded) {
166 if ($parentNode instanceof
Node) {
167 $parentPath = $parentNode->getData($this->_pathField);
168 $startLevel = $parentNode->getData($this->_levelField);
169 }
elseif (is_numeric($parentNode)) {
170 $select = $this->_conn->select()
171 ->from($this->_table, [$this->_pathField, $this->_levelField])
172 ->where(
"{$this->_idField} = ?", $parentNode);
173 $parent = $this->_conn->fetchRow(
$select);
178 }
elseif (is_string($parentNode)) {
179 $parentPath = $parentNode;
180 $startLevel = count(explode(
',', $parentPath)) - 1;
186 $select->order($this->_table .
'.' . $this->_orderField .
' ASC');
188 $pathField = $this->_conn->quoteIdentifier([$this->_table, $this->_pathField]);
189 $select->where(
"{$pathField} LIKE ?",
"{$parentPath}/%");
191 if ($recursionLevel != 0) {
192 $levelField = $this->_conn->quoteIdentifier([$this->_table, $this->_levelField]);
193 $select->where(
"{$levelField} <= ?", $startLevel + $recursionLevel);
196 $arrNodes = $this->_conn->fetchAll(
$select);
200 foreach ($arrNodes as $nodeInfo) {
201 $pathToParent = explode(
'/', $nodeInfo[$this->_pathField]);
202 array_pop($pathToParent);
203 $pathToParent = implode(
'/', $pathToParent);
204 $childrenItems[$pathToParent][] = $nodeInfo;
207 $this->
addChildNodes($childrenItems, $parentPath, $parentNode);
209 $this->_loaded =
true;
228 $nodeId = isset($child[$this->_idField]) ? $child[
$this->_idField] :
false;
229 if ($parentNode && $nodeId && ($node = $parentNode->getChildren()->searchById($nodeId))) {
230 $node->addData($child);
232 $node =
new Node($child, $this->_idField, $this, $parentNode);
236 $node->setLevel($node->getData($this->_levelField));
237 $node->setPathId($node->getData($this->_pathField));
238 $this->
addNode($node, $parentNode);
241 $childrenPath = explode(
'/',
$path);
245 $childrenPath[] = $node->getId();
246 $childrenPath = implode(
'/', $childrenPath);
262 if (is_numeric($nodeId)) {
263 $condField = $this->_conn->quoteIdentifier([$this->_table, $this->_idField]);
265 $condField = $this->_conn->quoteIdentifier([$this->_table, $this->_pathField]);
268 $select->where(
"{$condField} = ?", $nodeId);
285 if (is_numeric($node)) {
292 foreach ($node->getChildren() as $child) {
294 if ($child->getChildren()) {
313 public function move($node, $newParent, $prevNode =
null)
317 $oldPath = $node->getData($this->_pathField);
318 $newPath = $newParent->getData($this->_pathField);
320 $newPath = $newPath .
'/' . $node->getId();
321 $oldPathLength = strlen($oldPath);
323 $newLevel = $newParent->getLevel() + 1;
324 $levelDisposition = $newLevel - $node->getLevel();
327 $this->_levelField => new \Zend_Db_Expr(
"{$this->_levelField} + '{$levelDisposition}'"),
328 $this->_pathField => new \Zend_Db_Expr(
329 "CONCAT('{$newPath}', RIGHT({$this->_pathField}, LENGTH({$this->_pathField}) - {$oldPathLength}))" 332 $condition = $this->_conn->quoteInto(
"{$this->_pathField} REGEXP ?",
"^{$oldPath}(/|\$)");
334 $this->_conn->beginTransaction();
336 $reorderData = [$this->_orderField => new \Zend_Db_Expr(
"{$this->_orderField} + 1")];
338 if ($prevNode && $prevNode->getId()) {
339 $reorderCondition =
"{$this->_orderField} > {$prevNode->getData($this->_orderField)}";
340 $position = $prevNode->getData($this->_orderField) + 1;
342 $reorderCondition = $this->_conn->quoteInto(
343 "{$this->_pathField} REGEXP ?",
344 "^{$newParent->getData($this->_pathField)}/[0-9]+\$" 346 $select = $this->_conn->select()->from(
353 $position = (int)$this->_conn->fetchOne(
$select);
355 $this->_conn->update($this->_table, $reorderData, $reorderCondition);
356 $this->_conn->update($this->_table,
$data, $condition);
357 $this->_conn->update(
359 [$this->_orderField => $position, $this->_levelField => $newLevel],
360 $this->_conn->quoteInto(
"{$this->_idField} = ?", $node->getId())
363 $this->_conn->commit();
364 }
catch (\Exception $e) {
365 $this->_conn->rollBack();
366 throw new \Exception(
"Can't move tree node due to error: " . $e->getMessage());
380 $rootNodeId = $rootNode->getId();
381 $rootNodePath = $rootNode->getData($this->_pathField);
384 $select->order($this->_table .
'.' . $this->_orderField .
' ASC');
387 $condition = $this->_conn->quoteInto(
"{$this->_table}.{$this->_idField} in (?)", $pathIds);
391 $arrNodes = $this->_conn->fetchAll(
$select);
395 foreach ($arrNodes as $nodeInfo) {
397 if ($nodeId <= $rootNodeId) {
401 $pathToParent = explode(
'/', $nodeInfo[$this->_pathField]);
402 array_pop($pathToParent);
403 $pathToParent = implode(
'/', $pathToParent);
404 $childrenItems[$pathToParent][] = $nodeInfo;
407 $this->
_addChildNodes($childrenItems, $rootNodePath, $rootNode,
true);
425 $nodeId = isset($child[$this->_idField]) ? $child[
$this->_idField] :
false;
426 if ($parentNode && $nodeId && ($node = $parentNode->getChildren()->searchById($nodeId))) {
427 $node->addData($child);
429 $node =
new Node($child, $this->_idField, $this, $parentNode);
430 $node->setLevel($node->getData($this->_levelField));
431 $node->setPathId($node->getData($this->_pathField));
432 $this->
addNode($node, $parentNode);
436 $this->_loaded =
false;
437 $node->loadChildren(1);
438 $this->_loaded =
false;
442 $childrenPath = explode(
'/',
$path);
446 $childrenPath[] = $node->getId();
447 $childrenPath = implode(
'/', $childrenPath);
getChildren($node, $recursive=true, $result=[])
load($parentNode=null, $recursionLevel=0)
elseif(isset( $params[ 'redirect_parent']))
__construct(\Magento\Framework\DB\Adapter\AdapterInterface $connection, $table, $fields)
addNode($node, $parent=null)
_addChildNodes($children, $path, $parentNode, $withChildren=false, $level=0)
loadEnsuredNodes($category, $rootNode)
move($node, $newParent, $prevNode=null)
addChildNodes($children, $path, $parentNode, $level=0)