This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace devgroup\JsTreeWidget\actions\nestedset; |
||
4 | |||
5 | use devgroup\JsTreeWidget\widgets\TreeWidget; |
||
6 | use yii\base\Action; |
||
7 | use Yii; |
||
8 | use yii\base\InvalidConfigException; |
||
9 | use yii\db\ActiveRecord; |
||
10 | use yii\db\Expression; |
||
11 | use yii\web\Response; |
||
12 | |||
13 | /** |
||
14 | * Class NodeMoveAction |
||
15 | * |
||
16 | * @package devgroup\JsTreeWidget\actions\nestedset |
||
17 | */ |
||
18 | class NodeMoveAction extends Action |
||
19 | { |
||
20 | /** @var ActiveRecord */ |
||
21 | public $className; |
||
22 | /** @var string set root column name for multi root tree */ |
||
23 | public $rootAttribute = false; |
||
24 | /** @var string */ |
||
25 | public $leftAttribute = 'lft'; |
||
26 | /** @var string */ |
||
27 | public $rightAttribute = 'rgt'; |
||
28 | /** @var string */ |
||
29 | public $depthAttribute = 'depth'; |
||
30 | /** @var int */ |
||
31 | public $depthLimit = false; |
||
32 | |||
33 | /** @var ActiveRecord */ |
||
34 | protected $node; |
||
35 | /** @var ActiveRecord */ |
||
36 | protected $parent; |
||
37 | /** @var string */ |
||
38 | protected $tableName; |
||
39 | |||
40 | /** |
||
41 | * @inheritdoc |
||
42 | */ |
||
43 | View Code Duplication | public function init() |
|
0 ignored issues
–
show
|
|||
44 | { |
||
45 | if (true === empty($this->className) || false === is_subclass_of($this->className, ActiveRecord::class)) { |
||
0 ignored issues
–
show
|
|||
46 | throw new InvalidConfigException('"className" param must be set and must be child of ActiveRecord'); |
||
47 | } |
||
48 | /** @var ActiveRecord $class */ |
||
49 | $class = $this->className; |
||
50 | $this->tableName = $class::tableName(); |
||
51 | $scheme = Yii::$app->getDb()->getTableSchema($this->tableName); |
||
52 | $columns = $scheme->columns; |
||
53 | if (false !== $this->rootAttribute && false === isset($columns[$this->rootAttribute])) { |
||
54 | throw new InvalidConfigException("Column '{$this->rootAttribute}' not found in the '{$this->tableName}' table"); |
||
55 | } |
||
56 | if (false === isset( |
||
57 | $columns[$this->leftAttribute], |
||
58 | $columns[$this->rightAttribute], |
||
59 | $columns[$this->depthAttribute] |
||
60 | ) |
||
61 | ) { |
||
62 | throw new InvalidConfigException( |
||
63 | "Some of the '{$this->leftAttribute}', '{$this->rightAttribute}', '{$this->depthAttribute}', " |
||
64 | . "not found in the '{$this->tableName}' columns list" |
||
65 | ); |
||
66 | } |
||
67 | TreeWidget::registerTranslations(); |
||
68 | parent::init(); |
||
69 | } |
||
70 | |||
71 | /** |
||
72 | * @inheritdoc |
||
73 | */ |
||
74 | public function run() |
||
75 | { |
||
76 | Yii::$app->response->format = Response::FORMAT_JSON; |
||
77 | $newParentId = Yii::$app->request->post('parent'); |
||
78 | $oldParentId = Yii::$app->request->post('old_parent'); |
||
79 | $position = Yii::$app->request->post('position'); |
||
80 | $oldPosition = Yii::$app->request->post('old_position'); |
||
81 | $nodeId = Yii::$app->request->post('node_id'); |
||
82 | $siblings = Yii::$app->request->post('siblings', []); |
||
83 | $class = $this->className; |
||
84 | if ((int)$newParentId == 0) { |
||
85 | return ['error' => Yii::t('jstw', 'Can not move node as root!')]; |
||
86 | } |
||
87 | if ((null === $node = $class::findOne($nodeId)) || (null === $parent = $class::findOne($newParentId))) { |
||
88 | return ['error' => Yii::t('jstw', 'Invalid node id or parent id received!')]; |
||
89 | } |
||
90 | if ($this->depthLimit) { |
||
91 | $nodeMaxDepth = $node->children()->select(new Expression('MAX(' . $this->depthAttribute . ')'))->scalar(); |
||
0 ignored issues
–
show
|
|||
92 | $nodeMaxDepth = $nodeMaxDepth ? $nodeMaxDepth : $node->{$this->depthAttribute}; |
||
93 | $nodeResultDepth = $parent->{$this->depthAttribute} + ($nodeMaxDepth - $node->{$this->depthAttribute} + 1); |
||
94 | if ($nodeResultDepth >= $this->depthLimit) { |
||
95 | return ['error' => Yii::t('jstw', 'Can not move node because max depth ({depthLimit}) is exceeded!', ['depthLimit' => $this->depthLimit])]; |
||
96 | } |
||
97 | } |
||
98 | $this->node = $node; |
||
0 ignored issues
–
show
It seems like
$node of type array or boolean is incompatible with the declared type object<yii\db\ActiveRecord> of property $node .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
99 | $this->parent = $parent; |
||
0 ignored issues
–
show
It seems like
$parent of type array or boolean is incompatible with the declared type object<yii\db\ActiveRecord> of property $parent .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
100 | if (false !== $this->rootAttribute && ($node->{$this->rootAttribute} != $parent->{$this->rootAttribute})) { |
||
101 | return $this->moveMultiRoot($position, $siblings, $oldParentId); |
||
102 | } |
||
103 | if ($newParentId == $oldParentId) { |
||
104 | return $this->reorder($oldPosition, $position, $siblings); |
||
105 | } else { |
||
106 | return $this->move($position, $siblings, $oldParentId); |
||
107 | } |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * Moves node inside one parent inside one root |
||
112 | * |
||
113 | * @param null $oldPosition |
||
114 | * @param null $position |
||
115 | * @param array $siblings |
||
116 | * @return array|bool |
||
0 ignored issues
–
show
|
|||
117 | * @throws \yii\db\Exception |
||
118 | */ |
||
119 | protected function reorder($oldPosition = null, $position = null, $siblings = []) |
||
120 | { |
||
121 | if (null === $oldPosition || null === $position || true === empty($siblings)) { |
||
122 | return ['error' => Yii::t('jstw', 'Invalid data provided!')]; |
||
123 | } |
||
124 | $nodeId = $siblings[$position]; |
||
125 | $class = $this->className; |
||
126 | if ($oldPosition > $position) { |
||
127 | //change next |
||
128 | $nodeOperator = '-'; |
||
129 | $siblingsOperator = '+'; |
||
130 | $workWith = array_slice($siblings, $position, $oldPosition - $position + 1); |
||
131 | } else if ($oldPosition < $position) { |
||
132 | //change previous |
||
133 | $nodeOperator = '+'; |
||
134 | $siblingsOperator = '-'; |
||
135 | $workWith = array_slice($siblings, $oldPosition, $position - $oldPosition + 1); |
||
136 | } else { |
||
137 | return true; |
||
138 | } |
||
139 | if (true === empty($workWith)) { |
||
140 | return ['error' => Yii::t('jstw', 'Invalid data provided!')]; |
||
141 | } |
||
142 | $lr = $workWithLr = $this->getLr($workWith); |
||
143 | if (true === empty($lr)) { |
||
144 | return ['error' => Yii::t('jstw', 'Invalid data provided!')]; |
||
145 | } |
||
146 | unset($workWithLr[$nodeId]); |
||
147 | $lft = array_column($workWithLr, $this->leftAttribute); |
||
148 | $lft = min($lft); |
||
149 | $rgt = array_column($workWithLr, $this->rightAttribute); |
||
150 | $rgt = max($rgt); |
||
151 | $nodeCondition = [ |
||
152 | 'and', |
||
153 | ['>=', $this->leftAttribute, $lft], |
||
154 | ['<=', $this->rightAttribute, $rgt] |
||
155 | ]; |
||
156 | $this->applyRootCondition($nodeCondition); |
||
157 | $nodeDelta = $this->getCount($nodeCondition); |
||
158 | $nodeDelta *= 2; |
||
159 | $siblingsCondition = [ |
||
160 | 'and', |
||
161 | ['>=', $this->leftAttribute, $lr[$nodeId][$this->leftAttribute]], |
||
162 | ['<=', $this->rightAttribute, $lr[$nodeId][$this->rightAttribute]] |
||
163 | ]; |
||
164 | $this->applyRootCondition($siblingsCondition); |
||
165 | $nodeChildren = $this->getChildIds($siblingsCondition); |
||
166 | $siblingsDelta = count($nodeChildren) * 2; |
||
167 | $db = Yii::$app->getDb(); |
||
168 | $transaction = $db->beginTransaction(); |
||
169 | try { |
||
170 | //updating necessary node siblings |
||
171 | $db->createCommand()->update( |
||
172 | $class::tableName(), |
||
173 | [ |
||
174 | $this->leftAttribute => new Expression($this->leftAttribute . sprintf('%s%d', $siblingsOperator, $siblingsDelta)), |
||
175 | $this->rightAttribute => new Expression($this->rightAttribute . sprintf('%s%d', $siblingsOperator, $siblingsDelta)), |
||
176 | ], |
||
177 | $nodeCondition |
||
178 | )->execute(); |
||
179 | //updating node |
||
180 | $db->createCommand()->update( |
||
181 | $class::tableName(), |
||
182 | [ |
||
183 | $this->leftAttribute => new Expression($this->leftAttribute . sprintf('%s%d', $nodeOperator, $nodeDelta)), |
||
184 | $this->rightAttribute => new Expression($this->rightAttribute . sprintf('%s%d', $nodeOperator, $nodeDelta)), |
||
185 | ], |
||
186 | ['id' => $nodeChildren] |
||
187 | )->execute(); |
||
188 | $transaction->commit(); |
||
189 | } catch (\Exception $e) { |
||
190 | $transaction->rollBack(); |
||
191 | return ['error' => $e->getMessage()]; |
||
192 | } |
||
193 | return true; |
||
194 | } |
||
195 | |||
196 | /** |
||
197 | * Moves node inside one root |
||
198 | * |
||
199 | * @param null $position |
||
200 | * @param array $siblings |
||
201 | * @param string | integer $oldParentId |
||
202 | * @return array|bool |
||
0 ignored issues
–
show
|
|||
203 | * @throws \yii\db\Exception |
||
204 | */ |
||
205 | protected function move($position = null, $siblings = [], $oldParentId) |
||
0 ignored issues
–
show
Parameters which have default values should be placed at the end.
If you place a parameter with a default value before a parameter with a default value, the default value of the first parameter will never be used as it will always need to be passed anyway: // $a must always be passed; it's default value is never used.
function someFunction($a = 5, $b) { }
![]() |
|||
206 | { |
||
207 | $class = $this->className; |
||
208 | View Code Duplication | if (null === $oldParent = $class::findOne($oldParentId)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
209 | return ['error' => Yii::t('jstw', "Old parent with id '{id}' not found!", ['id' => $oldParentId])]; |
||
210 | } |
||
211 | $nodeCountCondition = [ |
||
212 | 'and', |
||
213 | ['>=', $this->leftAttribute, $this->node{$this->leftAttribute}], |
||
214 | ['<=', $this->rightAttribute, $this->node{$this->rightAttribute}] |
||
215 | ]; |
||
216 | $this->applyRootCondition($nodeCountCondition); |
||
217 | $nodeChildren = $this->getChildIds($nodeCountCondition); |
||
218 | $siblingsDelta = count($nodeChildren) * 2; |
||
219 | View Code Duplication | if ($position == 0) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
220 | $compareRight = $this->parent->{$this->leftAttribute} + 1; |
||
221 | } else { |
||
222 | if (false === isset($siblings[$position - 1])) { |
||
223 | return ['error' => Yii::t('jstw', 'New previous sibling does not exist')]; |
||
224 | } |
||
225 | $newPrevSiblingId = $siblings[$position - 1]; |
||
226 | $newPrevSiblingData = $this->getLr($newPrevSiblingId); |
||
227 | $compareRight = $newPrevSiblingData[$newPrevSiblingId][$this->rightAttribute]; |
||
228 | } |
||
229 | if ($this->node->{$this->leftAttribute} > $compareRight) { |
||
230 | //move node up |
||
231 | if ($position == 0) { |
||
232 | $leftFrom = $compareRight; |
||
233 | } else { |
||
234 | $leftFrom = $compareRight + 1; |
||
235 | } |
||
236 | $rightTo = $this->node->{$this->leftAttribute}; |
||
237 | $nodeDelta = $this->node->{$this->leftAttribute} - $leftFrom; |
||
238 | $nodeOperator = '-'; |
||
239 | $parentOperator = $siblingsOperator = '+'; |
||
240 | $newParentUpdateField = $this->rightAttribute; |
||
241 | $oldParentUpdateField = $this->leftAttribute; |
||
242 | } else if ($this->node->{$this->leftAttribute} < $compareRight) { |
||
243 | //move node down |
||
244 | $leftFrom = $this->node->{$this->rightAttribute}; |
||
245 | if ($position == 0) { |
||
246 | $rightTo = $compareRight - 1; |
||
247 | } else { |
||
248 | $rightTo = $compareRight; |
||
249 | } |
||
250 | $nodeOperator = '+'; |
||
251 | $parentOperator = $siblingsOperator = '-'; |
||
252 | $nodeDelta = $rightTo - $siblingsDelta + 1 - $this->node->{$this->leftAttribute}; |
||
253 | $newParentUpdateField = $this->leftAttribute; |
||
254 | $oldParentUpdateField = $this->rightAttribute; |
||
255 | } else { |
||
256 | return ['error' => Yii::t('jstw', 'There are two nodes with same "left" value. This should not be.')]; |
||
257 | } |
||
258 | $siblingsCondition = [ |
||
259 | 'and', |
||
260 | ['>=', $this->leftAttribute, $leftFrom], |
||
261 | ['<=', $this->rightAttribute, $rightTo] |
||
262 | ]; |
||
263 | $this->applyRootCondition($siblingsCondition); |
||
264 | $db = Yii::$app->getDb(); |
||
265 | $transaction = $db->beginTransaction(); |
||
266 | $oldParentDepth = $oldParent->{$this->depthAttribute}; |
||
267 | $newParentDepth = $this->parent->{$this->depthAttribute}; |
||
268 | View Code Duplication | if ($newParentDepth < $oldParentDepth) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
269 | $depthOperator = '-'; |
||
270 | $depthDelta = $oldParentDepth - $newParentDepth; |
||
271 | } else { |
||
272 | $depthOperator = '+'; |
||
273 | $depthDelta = $newParentDepth - $oldParentDepth; |
||
274 | } |
||
275 | $commonParentsCondition = [ |
||
276 | 'and', |
||
277 | ['<', $this->leftAttribute, $leftFrom], |
||
278 | ['>', $this->rightAttribute, $rightTo] |
||
279 | ]; |
||
280 | $this->applyRootCondition($commonParentsCondition); |
||
281 | $commonParentsIds = $class::find()->select('id')->where($commonParentsCondition)->column(); |
||
282 | $commonCondition = [ |
||
283 | ['!=', $this->depthAttribute, 0], |
||
284 | ['not in', 'id', $commonParentsIds], |
||
285 | ]; |
||
286 | $this->applyRootCondition($commonCondition); |
||
287 | $newParentCondition = array_merge([ |
||
288 | 'and', |
||
289 | ['<=', $this->leftAttribute, $this->parent->{$this->leftAttribute}], |
||
290 | ['>=', $this->rightAttribute, $this->parent->{$this->rightAttribute}], |
||
291 | ], $commonCondition); |
||
292 | $oldParentsCondition = array_merge([ |
||
293 | 'and', |
||
294 | ['<', $this->leftAttribute, $this->node->{$this->leftAttribute}], |
||
295 | ['>', $this->rightAttribute, $this->node->{$this->rightAttribute}], |
||
296 | ], $commonCondition); |
||
297 | try { |
||
298 | //updating necessary node siblings |
||
299 | $db->createCommand()->update( |
||
300 | $class::tableName(), |
||
301 | [ |
||
302 | $this->leftAttribute => new Expression($this->leftAttribute . sprintf('%s%d', $siblingsOperator, $siblingsDelta)), |
||
303 | $this->rightAttribute => new Expression($this->rightAttribute . sprintf('%s%d', $siblingsOperator, $siblingsDelta)), |
||
304 | ], |
||
305 | $siblingsCondition |
||
306 | )->execute(); |
||
307 | //updating old parents |
||
308 | $db->createCommand()->update( |
||
309 | $class::tableName(), |
||
310 | [ |
||
311 | //down - right |
||
312 | $oldParentUpdateField => new Expression($oldParentUpdateField . sprintf('%s%d', $parentOperator, $siblingsDelta)), |
||
313 | ], |
||
314 | $oldParentsCondition |
||
315 | )->execute(); |
||
316 | //updating new parents |
||
317 | $db->createCommand()->update( |
||
318 | $class::tableName(), |
||
319 | [ |
||
320 | //down - left |
||
321 | $newParentUpdateField => new Expression($newParentUpdateField . sprintf('%s%d', $parentOperator, $siblingsDelta)), |
||
322 | ], |
||
323 | $newParentCondition |
||
324 | )->execute(); |
||
325 | //updating node with children |
||
326 | $db->createCommand()->update( |
||
327 | $class::tableName(), |
||
328 | [ |
||
329 | $this->leftAttribute => new Expression($this->leftAttribute . sprintf('%s%d', $nodeOperator, $nodeDelta)), |
||
330 | $this->rightAttribute => new Expression($this->rightAttribute . sprintf('%s%d', $nodeOperator, $nodeDelta)), |
||
331 | $this->depthAttribute => new Expression($this->depthAttribute . sprintf('%s%d', $depthOperator, $depthDelta)), |
||
332 | ], |
||
333 | ['id' => $nodeChildren] |
||
334 | )->execute(); |
||
335 | $transaction->commit(); |
||
336 | } catch (\Exception $e) { |
||
337 | $transaction->rollBack(); |
||
338 | return ['error' => $e->getMessage()]; |
||
339 | } |
||
340 | return true; |
||
341 | } |
||
342 | |||
343 | /** |
||
344 | * Moves node between two roots |
||
345 | * |
||
346 | * @param null $position |
||
347 | * @param array $siblings |
||
348 | * @param string | integer $oldParentId |
||
349 | * @return array|bool |
||
0 ignored issues
–
show
|
|||
350 | * @throws \yii\db\Exception |
||
351 | */ |
||
352 | protected function moveMultiRoot($position = null, $siblings = [], $oldParentId) |
||
0 ignored issues
–
show
Parameters which have default values should be placed at the end.
If you place a parameter with a default value before a parameter with a default value, the default value of the first parameter will never be used as it will always need to be passed anyway: // $a must always be passed; it's default value is never used.
function someFunction($a = 5, $b) { }
![]() |
|||
353 | { |
||
354 | $class = $this->className; |
||
355 | if ((int)$oldParentId == 0) { |
||
356 | return ['error' => Yii::t('jstw', 'Can not move root node as child!')]; |
||
357 | } |
||
358 | View Code Duplication | if (null === $oldParent = $class::findOne($oldParentId)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
359 | return ['error' => Yii::t('jstw', "Old parent with id '{id}' not found!", ['id' => $oldParentId])]; |
||
360 | } |
||
361 | $nodeCountCondition = [ |
||
362 | 'and', |
||
363 | ['>=', $this->leftAttribute, $this->node->{$this->leftAttribute}], |
||
364 | ['<=', $this->rightAttribute, $this->node->{$this->rightAttribute}], |
||
365 | [$this->rootAttribute => $this->node->{$this->rootAttribute}] |
||
366 | ]; |
||
367 | $nodeChildren = $this->getChildIds($nodeCountCondition); |
||
368 | $siblingsDelta = count($nodeChildren) * 2; |
||
369 | View Code Duplication | if ($position == 0) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
370 | $leftFrom = $this->parent->{$this->leftAttribute} + 1; |
||
371 | } else { |
||
372 | if (false === isset($siblings[$position - 1])) { |
||
373 | return ['error' => Yii::t('jstw', 'New previous sibling does not exist')]; |
||
374 | } |
||
375 | $newPrevSiblingId = $siblings[$position - 1]; |
||
376 | $newPrevSiblingData = $this->getLr($newPrevSiblingId); |
||
377 | $leftFrom = $newPrevSiblingData[$newPrevSiblingId][$this->rightAttribute] + 1; |
||
378 | } |
||
379 | if ($this->node->{$this->leftAttribute} > $leftFrom) { |
||
380 | $nodeDelta = $this->node->{$this->leftAttribute} - $leftFrom; |
||
381 | $nodeOperator = '-'; |
||
382 | } else { |
||
383 | $nodeDelta = $leftFrom - $this->node->{$this->leftAttribute}; |
||
384 | $nodeOperator = '+'; |
||
385 | } |
||
386 | $siblingsCondition = [ |
||
387 | 'and', |
||
388 | ['>=', $this->leftAttribute, $leftFrom], |
||
389 | [$this->rootAttribute => $this->parent->{$this->rootAttribute}] |
||
390 | ]; |
||
391 | $oldSiblingsCondition = [ |
||
392 | 'and', |
||
393 | ['>', $this->leftAttribute, $this->node->{$this->rightAttribute}], |
||
394 | [$this->rootAttribute => $this->node->{$this->rootAttribute}] |
||
395 | ]; |
||
396 | $db = Yii::$app->getDb(); |
||
397 | $transaction = $db->beginTransaction(); |
||
398 | $oldParentDepth = $oldParent->{$this->depthAttribute}; |
||
399 | $newParentDepth = $this->parent->{$this->depthAttribute}; |
||
400 | View Code Duplication | if ($newParentDepth < $oldParentDepth) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
401 | $depthOperator = '-'; |
||
402 | $depthDelta = $oldParentDepth - $newParentDepth; |
||
403 | } else { |
||
404 | $depthOperator = '+'; |
||
405 | $depthDelta = $newParentDepth - $oldParentDepth; |
||
406 | } |
||
407 | $newParentCondition = [ |
||
408 | 'and', |
||
409 | ['<=', $this->leftAttribute, $this->parent->{$this->leftAttribute}], |
||
410 | ['>=', $this->rightAttribute, $this->parent->{$this->rightAttribute}], |
||
411 | [$this->rootAttribute => $this->parent->{$this->rootAttribute}] |
||
412 | ]; |
||
413 | $oldParentsCondition = [ |
||
414 | 'and', |
||
415 | ['<=', $this->leftAttribute, $oldParent->{$this->leftAttribute}], |
||
416 | ['>=', $this->rightAttribute, $oldParent->{$this->rightAttribute}], |
||
417 | [$this->rootAttribute => $oldParent->{$this->rootAttribute}] |
||
418 | ]; |
||
419 | try { |
||
420 | //updating necessary node new siblings |
||
421 | $db->createCommand()->update( |
||
422 | $class::tableName(), |
||
423 | [ |
||
424 | $this->leftAttribute => new Expression($this->leftAttribute . sprintf('+%d', $siblingsDelta)), |
||
425 | $this->rightAttribute => new Expression($this->rightAttribute . sprintf('+%d', $siblingsDelta)), |
||
426 | ], |
||
427 | $siblingsCondition |
||
428 | )->execute(); |
||
429 | //updating necessary node old siblings |
||
430 | $db->createCommand()->update( |
||
431 | $class::tableName(), |
||
432 | [ |
||
433 | $this->leftAttribute => new Expression($this->leftAttribute . sprintf('-%d', $siblingsDelta)), |
||
434 | $this->rightAttribute => new Expression($this->rightAttribute . sprintf('-%d', $siblingsDelta)), |
||
435 | ], |
||
436 | $oldSiblingsCondition |
||
437 | )->execute(); |
||
438 | //updating old parents |
||
439 | $db->createCommand()->update( |
||
440 | $class::tableName(), |
||
441 | [ |
||
442 | $this->rightAttribute => new Expression($this->rightAttribute . sprintf('-%d', $siblingsDelta)), |
||
443 | ], |
||
444 | $oldParentsCondition |
||
445 | )->execute(); |
||
446 | //updating new parents |
||
447 | $db->createCommand()->update( |
||
448 | $class::tableName(), |
||
449 | [ |
||
450 | $this->rightAttribute => new Expression($this->rightAttribute . sprintf('+%d', $siblingsDelta)), |
||
451 | ], |
||
452 | $newParentCondition |
||
453 | )->execute(); |
||
454 | //updating node with children |
||
455 | $db->createCommand()->update( |
||
456 | $class::tableName(), |
||
457 | [ |
||
458 | $this->leftAttribute => new Expression($this->leftAttribute . sprintf('%s%d', $nodeOperator, $nodeDelta)), |
||
459 | $this->rightAttribute => new Expression($this->rightAttribute . sprintf('%s%d', $nodeOperator, $nodeDelta)), |
||
460 | $this->depthAttribute => new Expression($this->depthAttribute . sprintf('%s%d', $depthOperator, $depthDelta)), |
||
461 | $this->rootAttribute => $this->parent->{$this->rootAttribute} |
||
462 | ], |
||
463 | ['id' => $nodeChildren] |
||
464 | )->execute(); |
||
465 | $transaction->commit(); |
||
466 | } catch (\Exception $e) { |
||
467 | $transaction->rollBack(); |
||
468 | return ['error' => $e->getMessage()]; |
||
469 | } |
||
470 | return true; |
||
471 | } |
||
472 | |||
473 | /** |
||
474 | * Returns field set of rows to be modified while reordering |
||
475 | * |
||
476 | * @param array $ids |
||
477 | * @return array|\yii\db\ActiveRecord[] |
||
478 | */ |
||
479 | protected function getLr($ids) |
||
480 | { |
||
481 | $class = $this->className; |
||
482 | return $class::find() |
||
483 | ->select(['id', $this->leftAttribute, $this->rightAttribute]) |
||
484 | ->where(['id' => $ids]) |
||
485 | ->indexBy('id') |
||
486 | ->asArray(true) |
||
487 | ->all(); |
||
488 | } |
||
489 | |||
490 | /** |
||
491 | * Returns count of records to be modified while reordering |
||
492 | * |
||
493 | * @param array $condition |
||
494 | * @return int|string |
||
0 ignored issues
–
show
|
|||
495 | */ |
||
496 | protected function getCount($condition) |
||
497 | { |
||
498 | $class = $this->className; |
||
499 | return $class::find() |
||
500 | ->select(['id', $this->leftAttribute, $this->rightAttribute, $this->rootAttribute]) |
||
501 | ->where($condition) |
||
502 | ->count(); |
||
503 | } |
||
504 | |||
505 | |||
506 | /** |
||
507 | * Returns child ids of selected node |
||
508 | * |
||
509 | * @param array $condition |
||
510 | * @return array |
||
511 | */ |
||
512 | protected function getChildIds($condition) |
||
513 | { |
||
514 | $class = $this->className; |
||
515 | return $class::find() |
||
516 | ->select('id') |
||
517 | ->where($condition) |
||
518 | ->column(); |
||
519 | } |
||
520 | |||
521 | /** |
||
522 | * Applies tree root condition if multi root |
||
523 | * |
||
524 | * @param $condition |
||
525 | */ |
||
526 | protected function applyRootCondition(&$condition) |
||
527 | { |
||
528 | if (false !== $this->rootAttribute) { |
||
529 | $condition[] = [$this->rootAttribute => $this->node->{$this->rootAttribute}]; |
||
530 | } |
||
531 | } |
||
532 | } |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.