Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Db.php
Go to the documentation of this file.
1 <?php
7 
17 {
18  const ID_FIELD = 'id';
19 
20  const PARENT_FIELD = 'parent';
21 
22  const LEVEL_FIELD = 'level';
23 
24  const ORDER_FIELD = 'order';
25 
31  protected $_conn;
32 
38  protected $_table;
39 
45  protected $_select;
46 
52  protected $_idField;
53 
59  protected $_parentField;
60 
66  protected $_levelField;
67 
73  protected $_orderField;
74 
90  public function __construct(\Magento\Framework\DB\Adapter\AdapterInterface $connection, $table, $fields)
91  {
92  parent::__construct();
93 
94  if (!$connection) {
95  throw new \Exception('Wrong "$connection" parametr');
96  }
97 
98  $this->_conn = $connection;
99  $this->_table = $table;
100 
101  if (!isset(
102  $fields[self::ID_FIELD]
103  ) || !isset(
104  $fields[self::PARENT_FIELD]
105  ) || !isset(
106  $fields[self::LEVEL_FIELD]
107  ) || !isset(
108  $fields[self::ORDER_FIELD]
109  )
110  ) {
111  throw new \Exception('"$fields" tree configuratin array');
112  }
113 
114  $this->_idField = $fields[self::ID_FIELD];
115  $this->_parentField = $fields[self::PARENT_FIELD];
116  $this->_levelField = $fields[self::LEVEL_FIELD];
117  $this->_orderField = $fields[self::ORDER_FIELD];
118 
119  $this->_select = $this->_conn->select();
120  $this->_select->from($this->_table, array_values($fields));
121  }
122 
126  public function getDbSelect()
127  {
128  return $this->_select;
129  }
130 
135  public function setDbSelect($select)
136  {
137  $this->_select = $select;
138  }
139 
148  public function load($parentNode = null, $recursionLevel = 100)
149  {
150  if ($parentNode === null) {
151  $this->_loadFullTree();
152  return $this;
153  } elseif ($parentNode instanceof Node) {
154  $parentId = $parentNode->getId();
155  } elseif (is_numeric($parentNode)) {
156  $parentId = $parentNode;
157  $parentNode = null;
158  } else {
159  throw new \Exception('root node id is not defined');
160  }
161 
162  $select = clone $this->_select;
163  $select->order($this->_table . '.' . $this->_orderField . ' ASC');
164  $condition = $this->_conn->quoteInto("{$this->_table}.{$this->_parentField}=?", $parentId);
165  $select->where($condition);
166  $arrNodes = $this->_conn->fetchAll($select);
167  foreach ($arrNodes as $nodeInfo) {
168  $node = new Node($nodeInfo, $this->_idField, $this, $parentNode);
169  $this->addNode($node, $parentNode);
170 
171  if ($recursionLevel) {
172  $node->loadChildren($recursionLevel - 1);
173  }
174  }
175  return $this;
176  }
177 
182  public function loadNode($nodeId)
183  {
184  $select = clone $this->_select;
185  $condition = $this->_conn->quoteInto("{$this->_table}.{$this->_idField}=?", $nodeId);
186  $select->where($condition);
187  $node = new Node($this->_conn->fetchRow($select), $this->_idField, $this);
188  $this->addNode($node);
189  return $node;
190  }
191 
198  public function appendChild($data, $parentNode, $prevNode = null)
199  {
200  $orderSelect = $this->_conn->select();
201  $orderSelect->from(
202  $this->_table,
203  new \Zend_Db_Expr('MAX(' . $this->_conn->quoteIdentifier($this->_orderField) . ')')
204  )->where(
205  $this->_conn->quoteIdentifier($this->_parentField) . '=' . $parentNode->getId()
206  );
207 
208  $order = $this->_conn->fetchOne($orderSelect);
209  $data[$this->_parentField] = $parentNode->getId();
210  $data[$this->_levelField] = $parentNode->getData($this->_levelField) + 1;
212 
213  $this->_conn->insert($this->_table, $data);
214  $data[$this->_idField] = $this->_conn->lastInsertId();
215 
216  return parent::appendChild($data, $parentNode, $prevNode);
217  }
218 
228  public function moveNodeTo($node, $parentNode, $prevNode = null)
229  {
230  $data = [];
231  $data[$this->_parentField] = $parentNode->getId();
232  $data[$this->_levelField] = $parentNode->getData($this->_levelField) + 1;
233  // New node order
234  if ($prevNode === null || $prevNode->getData($this->_orderField) === null) {
236  } else {
237  $data[$this->_orderField] = $prevNode->getData($this->_orderField) + 1;
238  }
239  $condition = $this->_conn->quoteInto("{$this->_idField}=?", $node->getId());
240 
241  // For reorder new node branch
242  $dataReorderNew = [
243  $this->_orderField => new \Zend_Db_Expr($this->_conn->quoteIdentifier($this->_orderField) . '+1'),
244  ];
245  $conditionReorderNew = $this->_conn->quoteIdentifier(
246  $this->_parentField
247  ) . '=' . $parentNode->getId() . ' AND ' . $this->_conn->quoteIdentifier(
248  $this->_orderField
249  ) . '>=' . $data[$this->_orderField];
250 
251  // For reorder old node branch
252  $dataReorderOld = [
253  $this->_orderField => new \Zend_Db_Expr($this->_conn->quoteIdentifier($this->_orderField) . '-1'),
254  ];
255  $conditionReorderOld = $this->_conn->quoteIdentifier(
256  $this->_parentField
257  ) . '=' . $node->getData(
258  $this->_parentField
259  ) . ' AND ' . $this->_conn->quoteIdentifier(
260  $this->_orderField
261  ) . '>' . $node->getData(
262  $this->_orderField
263  );
264 
265  $this->_conn->beginTransaction();
266  try {
267  // Prepare new node branch
268  $this->_conn->update($this->_table, $dataReorderNew, $conditionReorderNew);
269  // Move node
270  $this->_conn->update($this->_table, $data, $condition);
271  // Update old node branch
272  $this->_conn->update($this->_table, $dataReorderOld, $conditionReorderOld);
273  $this->_updateChildLevels($node->getId(), $data[$this->_levelField]);
274  $this->_conn->commit();
275  } catch (\Exception $e) {
276  $this->_conn->rollBack();
277  throw new \Exception('Can\'t move tree node');
278  }
279  }
280 
286  protected function _updateChildLevels($parentId, $parentLevel)
287  {
288  $select = $this->_conn->select()->from(
289  $this->_table,
290  $this->_idField
291  )->where(
292  $this->_parentField . '=?',
293  $parentId
294  );
295  $ids = $this->_conn->fetchCol($select);
296 
297  if (!empty($ids)) {
298  $this->_conn->update(
299  $this->_table,
300  [$this->_levelField => $parentLevel + 1],
301  $this->_conn->quoteInto($this->_idField . ' IN (?)', $ids)
302  );
303  foreach ($ids as $id) {
304  $this->_updateChildLevels($id, $parentLevel + 1);
305  }
306  }
307  return $this;
308  }
309 
313  protected function _loadFullTree()
314  {
315  $select = clone $this->_select;
316  $select->order($this->_table . '.' . $this->_levelField)->order($this->_table . '.' . $this->_orderField);
317 
318  $arrNodes = $this->_conn->fetchAll($select);
319 
320  foreach ($arrNodes as $nodeInfo) {
321  $node = new Node($nodeInfo, $this->_idField, $this);
322  $parentNode = $this->getNodeById($nodeInfo[$this->_parentField]);
323  $this->addNode($node, $parentNode);
324  }
325 
326  return $this;
327  }
328 
334  public function removeNode($node)
335  {
336  // For reorder old node branch
337  $dataReorderOld = [
338  $this->_orderField => new \Zend_Db_Expr($this->_conn->quoteIdentifier($this->_orderField) . '-1'),
339  ];
340  $conditionReorderOld = $this->_conn->quoteIdentifier(
341  $this->_parentField
342  ) . '=' . $node->getData(
343  $this->_parentField
344  ) . ' AND ' . $this->_conn->quoteIdentifier(
345  $this->_orderField
346  ) . '>' . $node->getData(
347  $this->_orderField
348  );
349 
350  $this->_conn->beginTransaction();
351  try {
352  $condition = $this->_conn->quoteInto("{$this->_idField}=?", $node->getId());
353  $this->_conn->delete($this->_table, $condition);
354  // Update old node branch
355  $this->_conn->update($this->_table, $dataReorderOld, $conditionReorderOld);
356  $this->_conn->commit();
357  } catch (\Exception $e) {
358  $this->_conn->rollBack();
359  throw new \Exception('Can\'t remove tree node');
360  }
361  parent::removeNode($node);
362  return $this;
363  }
364 }
load($parentNode=null, $recursionLevel=100)
Definition: Db.php:148
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
__construct(\Magento\Framework\DB\Adapter\AdapterInterface $connection, $table, $fields)
Definition: Db.php:90
$id
Definition: fieldset.phtml:14
$order
Definition: order.php:55
$fields
Definition: details.phtml:14
addNode($node, $parent=null)
Definition: Tree.php:94
_updateChildLevels($parentId, $parentLevel)
Definition: Db.php:286
moveNodeTo($node, $parentNode, $prevNode=null)
Definition: Db.php:228
$connection
Definition: bulk.php:13
$table
Definition: trigger.php:14
appendChild($data, $parentNode, $prevNode=null)
Definition: Db.php:198