Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Dbp.php
Go to the documentation of this file.
1 <?php
7 
9 
19 {
20  const ID_FIELD = 'id';
21 
22  const PATH_FIELD = 'path';
23 
24  const ORDER_FIELD = 'order';
25 
26  const LEVEL_FIELD = 'level';
27 
33  protected $_conn;
34 
40  protected $_table;
41 
47  protected $_loaded = false;
48 
54  protected $_select;
55 
61  protected $_idField;
62 
68  protected $_pathField;
69 
75  protected $_orderField;
76 
82  protected $_levelField;
83 
99  public function __construct(\Magento\Framework\DB\Adapter\AdapterInterface $connection, $table, $fields)
100  {
101  parent::__construct();
102 
103  if (!$connection) {
104  throw new \Exception('Wrong "$connection" parametr');
105  }
106 
107  $this->_conn = $connection;
108  $this->_table = $table;
109 
110  if (!isset(
111  $fields[self::ID_FIELD]
112  ) || !isset(
113  $fields[self::PATH_FIELD]
114  ) || !isset(
115  $fields[self::LEVEL_FIELD]
116  ) || !isset(
117  $fields[self::ORDER_FIELD]
118  )
119  ) {
120  throw new \Exception('"$fields" tree configuratin array');
121  }
122 
123  $this->_idField = $fields[self::ID_FIELD];
124  $this->_pathField = $fields[self::PATH_FIELD];
125  $this->_orderField = $fields[self::ORDER_FIELD];
126  $this->_levelField = $fields[self::LEVEL_FIELD];
127 
128  $this->_select = $this->_conn->select();
129  $this->_select->from($this->_table);
130  }
131 
137  public function getDbSelect()
138  {
139  return $this->_select;
140  }
141 
148  public function setDbSelect($select)
149  {
150  $this->_select = $select;
151  }
152 
160  public function load($parentNode = null, $recursionLevel = 0)
161  {
162  if (!$this->_loaded) {
163  $startLevel = 1;
164  $parentPath = '';
165 
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);
174 
175  $startLevel = $parent[$this->_levelField];
176  $parentPath = $parent[$this->_pathField];
177  $parentNode = null;
178  } elseif (is_string($parentNode)) {
179  $parentPath = $parentNode;
180  $startLevel = count(explode(',', $parentPath)) - 1;
181  $parentNode = null;
182  }
183 
184  $select = clone $this->_select;
185 
186  $select->order($this->_table . '.' . $this->_orderField . ' ASC');
187  if ($parentPath) {
188  $pathField = $this->_conn->quoteIdentifier([$this->_table, $this->_pathField]);
189  $select->where("{$pathField} LIKE ?", "{$parentPath}/%");
190  }
191  if ($recursionLevel != 0) {
192  $levelField = $this->_conn->quoteIdentifier([$this->_table, $this->_levelField]);
193  $select->where("{$levelField} <= ?", $startLevel + $recursionLevel);
194  }
195 
196  $arrNodes = $this->_conn->fetchAll($select);
197 
198  $childrenItems = [];
199 
200  foreach ($arrNodes as $nodeInfo) {
201  $pathToParent = explode('/', $nodeInfo[$this->_pathField]);
202  array_pop($pathToParent);
203  $pathToParent = implode('/', $pathToParent);
204  $childrenItems[$pathToParent][] = $nodeInfo;
205  }
206 
207  $this->addChildNodes($childrenItems, $parentPath, $parentNode);
208 
209  $this->_loaded = true;
210  }
211 
212  return $this;
213  }
214 
224  public function addChildNodes($children, $path, $parentNode, $level = 0)
225  {
226  if (isset($children[$path])) {
227  foreach ($children[$path] as $child) {
228  $nodeId = isset($child[$this->_idField]) ? $child[$this->_idField] : false;
229  if ($parentNode && $nodeId && ($node = $parentNode->getChildren()->searchById($nodeId))) {
230  $node->addData($child);
231  } else {
232  $node = new Node($child, $this->_idField, $this, $parentNode);
233  }
234 
235  //$node->setLevel(count(explode('/', $node->getData($this->_pathField)))-1);
236  $node->setLevel($node->getData($this->_levelField));
237  $node->setPathId($node->getData($this->_pathField));
238  $this->addNode($node, $parentNode);
239 
240  if ($path) {
241  $childrenPath = explode('/', $path);
242  } else {
243  $childrenPath = [];
244  }
245  $childrenPath[] = $node->getId();
246  $childrenPath = implode('/', $childrenPath);
247 
248  $this->addChildNodes($children, $childrenPath, $node, $level + 1);
249  }
250  }
251  }
252 
259  public function loadNode($nodeId)
260  {
261  $select = clone $this->_select;
262  if (is_numeric($nodeId)) {
263  $condField = $this->_conn->quoteIdentifier([$this->_table, $this->_idField]);
264  } else {
265  $condField = $this->_conn->quoteIdentifier([$this->_table, $this->_pathField]);
266  }
267 
268  $select->where("{$condField} = ?", $nodeId);
269 
270  $node = new Node($this->_conn->fetchRow($select), $this->_idField, $this);
271  $this->addNode($node);
272  return $node;
273  }
274 
283  public function getChildren($node, $recursive = true, $result = [])
284  {
285  if (is_numeric($node)) {
286  $node = $this->getNodeById($node);
287  }
288  if (!$node) {
289  return $result;
290  }
291 
292  foreach ($node->getChildren() as $child) {
293  if ($recursive) {
294  if ($child->getChildren()) {
295  $result = $this->getChildren($child, $recursive, $result);
296  }
297  }
298  $result[] = $child->getId();
299  }
300  return $result;
301  }
302 
313  public function move($node, $newParent, $prevNode = null)
314  {
315  $position = 1;
316 
317  $oldPath = $node->getData($this->_pathField);
318  $newPath = $newParent->getData($this->_pathField);
319 
320  $newPath = $newPath . '/' . $node->getId();
321  $oldPathLength = strlen($oldPath);
322 
323  $newLevel = $newParent->getLevel() + 1;
324  $levelDisposition = $newLevel - $node->getLevel();
325 
326  $data = [
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}))"
330  ),
331  ];
332  $condition = $this->_conn->quoteInto("{$this->_pathField} REGEXP ?", "^{$oldPath}(/|\$)");
333 
334  $this->_conn->beginTransaction();
335 
336  $reorderData = [$this->_orderField => new \Zend_Db_Expr("{$this->_orderField} + 1")];
337  try {
338  if ($prevNode && $prevNode->getId()) {
339  $reorderCondition = "{$this->_orderField} > {$prevNode->getData($this->_orderField)}";
340  $position = $prevNode->getData($this->_orderField) + 1;
341  } else {
342  $reorderCondition = $this->_conn->quoteInto(
343  "{$this->_pathField} REGEXP ?",
344  "^{$newParent->getData($this->_pathField)}/[0-9]+\$"
345  );
346  $select = $this->_conn->select()->from(
347  $this->_table,
348  new \Zend_Db_Expr("MIN({$this->_orderField})")
349  )->where(
350  $reorderCondition
351  );
352 
353  $position = (int)$this->_conn->fetchOne($select);
354  }
355  $this->_conn->update($this->_table, $reorderData, $reorderCondition);
356  $this->_conn->update($this->_table, $data, $condition);
357  $this->_conn->update(
358  $this->_table,
359  [$this->_orderField => $position, $this->_levelField => $newLevel],
360  $this->_conn->quoteInto("{$this->_idField} = ?", $node->getId())
361  );
362 
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());
367  }
368  }
369 
377  public function loadEnsuredNodes($category, $rootNode)
378  {
379  $pathIds = $category->getPathIds();
380  $rootNodeId = $rootNode->getId();
381  $rootNodePath = $rootNode->getData($this->_pathField);
382 
383  $select = clone $this->_select;
384  $select->order($this->_table . '.' . $this->_orderField . ' ASC');
385 
386  if ($pathIds) {
387  $condition = $this->_conn->quoteInto("{$this->_table}.{$this->_idField} in (?)", $pathIds);
388  $select->where($condition);
389  }
390 
391  $arrNodes = $this->_conn->fetchAll($select);
392 
393  if ($arrNodes) {
394  $childrenItems = [];
395  foreach ($arrNodes as $nodeInfo) {
396  $nodeId = $nodeInfo[$this->_idField];
397  if ($nodeId <= $rootNodeId) {
398  continue;
399  }
400 
401  $pathToParent = explode('/', $nodeInfo[$this->_pathField]);
402  array_pop($pathToParent);
403  $pathToParent = implode('/', $pathToParent);
404  $childrenItems[$pathToParent][] = $nodeInfo;
405  }
406 
407  $this->_addChildNodes($childrenItems, $rootNodePath, $rootNode, true);
408  }
409  }
410 
421  protected function _addChildNodes($children, $path, $parentNode, $withChildren = false, $level = 0)
422  {
423  if (isset($children[$path])) {
424  foreach ($children[$path] as $child) {
425  $nodeId = isset($child[$this->_idField]) ? $child[$this->_idField] : false;
426  if ($parentNode && $nodeId && ($node = $parentNode->getChildren()->searchById($nodeId))) {
427  $node->addData($child);
428  } else {
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);
433  }
434 
435  if ($withChildren) {
436  $this->_loaded = false;
437  $node->loadChildren(1);
438  $this->_loaded = false;
439  }
440 
441  if ($path) {
442  $childrenPath = explode('/', $path);
443  } else {
444  $childrenPath = [];
445  }
446  $childrenPath[] = $node->getId();
447  $childrenPath = implode('/', $childrenPath);
448 
449  $this->_addChildNodes($children, $childrenPath, $node, $withChildren, $level + 1);
450  }
451  }
452  }
453 }
getChildren($node, $recursive=true, $result=[])
Definition: Dbp.php:283
load($parentNode=null, $recursionLevel=0)
Definition: Dbp.php:160
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
__construct(\Magento\Framework\DB\Adapter\AdapterInterface $connection, $table, $fields)
Definition: Dbp.php:99
$fields
Definition: details.phtml:14
addNode($node, $parent=null)
Definition: Tree.php:94
_addChildNodes($children, $path, $parentNode, $withChildren=false, $level=0)
Definition: Dbp.php:421
loadEnsuredNodes($category, $rootNode)
Definition: Dbp.php:377
move($node, $newParent, $prevNode=null)
Definition: Dbp.php:313
$children
Definition: actions.phtml:11
$connection
Definition: bulk.php:13
$table
Definition: trigger.php:14
addChildNodes($children, $path, $parentNode, $level=0)
Definition: Dbp.php:224