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 | * @link https://github.com/paulzi/yii2-nested-sets |
||
4 | * @copyright Copyright (c) 2015 PaulZi <[email protected]> |
||
5 | * @license MIT (https://github.com/paulzi/yii2-nested-sets/blob/master/LICENSE) |
||
6 | */ |
||
7 | |||
8 | namespace paulzi\nestedsets; |
||
9 | |||
10 | use Yii; |
||
11 | use yii\base\Behavior; |
||
12 | use yii\base\Exception; |
||
13 | use yii\base\NotSupportedException; |
||
14 | use yii\db\ActiveRecord; |
||
15 | use yii\db\Expression; |
||
16 | |||
17 | /** |
||
18 | * Nested Sets Behavior for Yii2 |
||
19 | * @author PaulZi <[email protected]> |
||
20 | * @author Alexander Kochetov <https://github.com/creocoder> |
||
21 | * |
||
22 | * @property ActiveRecord $owner |
||
23 | */ |
||
24 | class NestedSetsBehavior extends Behavior |
||
25 | { |
||
26 | const OPERATION_MAKE_ROOT = 1; |
||
27 | const OPERATION_PREPEND_TO = 2; |
||
28 | const OPERATION_APPEND_TO = 3; |
||
29 | const OPERATION_INSERT_BEFORE = 4; |
||
30 | const OPERATION_INSERT_AFTER = 5; |
||
31 | const OPERATION_DELETE_ALL = 6; |
||
32 | |||
33 | |||
34 | /** |
||
35 | * @var string|null |
||
36 | */ |
||
37 | public $treeAttribute; |
||
38 | |||
39 | /** |
||
40 | * @var string |
||
41 | */ |
||
42 | public $leftAttribute = 'lft'; |
||
43 | |||
44 | /** |
||
45 | * @var string |
||
46 | */ |
||
47 | public $rightAttribute = 'rgt'; |
||
48 | |||
49 | /** |
||
50 | * @var string |
||
51 | */ |
||
52 | public $depthAttribute = 'depth'; |
||
53 | |||
54 | /** |
||
55 | * @var string|null |
||
56 | */ |
||
57 | protected $operation; |
||
58 | |||
59 | /** |
||
60 | * @var ActiveRecord|self|null |
||
61 | */ |
||
62 | protected $node; |
||
63 | |||
64 | /** |
||
65 | * @var string |
||
66 | */ |
||
67 | protected $treeChange; |
||
68 | |||
69 | |||
70 | /** |
||
71 | * @inheritdoc |
||
72 | */ |
||
73 | 201 | public function events() |
|
74 | { |
||
75 | return [ |
||
76 | 201 | ActiveRecord::EVENT_BEFORE_INSERT => 'beforeInsert', |
|
77 | ActiveRecord::EVENT_AFTER_INSERT => 'afterInsert', |
||
78 | ActiveRecord::EVENT_BEFORE_UPDATE => 'beforeUpdate', |
||
79 | ActiveRecord::EVENT_AFTER_UPDATE => 'afterUpdate', |
||
80 | ActiveRecord::EVENT_BEFORE_DELETE => 'beforeDelete', |
||
81 | ActiveRecord::EVENT_AFTER_DELETE => 'afterDelete', |
||
82 | ]; |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * @param int|null $depth |
||
87 | * @return \yii\db\ActiveQuery |
||
88 | */ |
||
89 | 6 | public function getParents($depth = null) |
|
90 | { |
||
91 | 6 | $tableName = $this->owner->tableName(); |
|
92 | $condition = [ |
||
93 | 6 | 'and', |
|
94 | 6 | ['<', "{$tableName}.[[{$this->leftAttribute}]]", $this->owner->getAttribute($this->leftAttribute)], |
|
95 | 6 | ['>', "{$tableName}.[[{$this->rightAttribute}]]", $this->owner->getAttribute($this->rightAttribute)], |
|
96 | ]; |
||
97 | 6 | View Code Duplication | if ($depth !== null) { |
0 ignored issues
–
show
|
|||
98 | 6 | $condition[] = ['>=', "{$tableName}.[[{$this->depthAttribute}]]", $this->owner->getAttribute($this->depthAttribute) - $depth]; |
|
99 | } |
||
100 | |||
101 | 6 | $query = $this->owner->find() |
|
102 | 6 | ->andWhere($condition) |
|
103 | 6 | ->andWhere($this->treeCondition()) |
|
104 | 6 | ->addOrderBy(["{$tableName}.[[{$this->leftAttribute}]]" => SORT_ASC]); |
|
105 | 6 | $query->multiple = true; |
|
106 | |||
107 | 6 | return $query; |
|
108 | } |
||
109 | |||
110 | /** |
||
111 | * @return \yii\db\ActiveQuery |
||
112 | */ |
||
113 | 3 | View Code Duplication | public function getParent() |
0 ignored issues
–
show
This method seems to be duplicated in 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. ![]() |
|||
114 | { |
||
115 | 3 | $tableName = $this->owner->tableName(); |
|
116 | 3 | $query = $this->getParents(1) |
|
117 | 3 | ->orderBy(["{$tableName}.[[{$this->leftAttribute}]]" => SORT_DESC]) |
|
118 | 3 | ->limit(1); |
|
119 | 3 | $query->multiple = false; |
|
120 | 3 | return $query; |
|
121 | } |
||
122 | |||
123 | /** |
||
124 | * @return \yii\db\ActiveQuery |
||
125 | */ |
||
126 | 3 | View Code Duplication | public function getRoot() |
0 ignored issues
–
show
This method seems to be duplicated in 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. ![]() |
|||
127 | { |
||
128 | 3 | $tableName = $this->owner->tableName(); |
|
129 | 3 | $query = $this->owner->find() |
|
130 | 3 | ->andWhere(["{$tableName}.[[{$this->leftAttribute}]]" => 1]) |
|
131 | 3 | ->andWhere($this->treeCondition()) |
|
132 | 3 | ->limit(1); |
|
133 | 3 | $query->multiple = false; |
|
134 | 3 | return $query; |
|
135 | } |
||
136 | |||
137 | /** |
||
138 | * @param int|null $depth |
||
139 | * @param bool $andSelf |
||
140 | * @param bool $backOrder |
||
141 | * @return \yii\db\ActiveQuery |
||
142 | */ |
||
143 | 78 | public function getDescendants($depth = null, $andSelf = false, $backOrder = false) |
|
144 | { |
||
145 | 78 | $tableName = $this->owner->tableName(); |
|
146 | 78 | $attribute = $backOrder ? $this->rightAttribute : $this->leftAttribute; |
|
147 | $condition = [ |
||
148 | 78 | 'and', |
|
149 | 78 | [$andSelf ? '>=' : '>', "{$tableName}.[[{$attribute}]]", $this->owner->getAttribute($this->leftAttribute)], |
|
150 | 78 | [$andSelf ? '<=' : '<', "{$tableName}.[[{$attribute}]]", $this->owner->getAttribute($this->rightAttribute)], |
|
151 | ]; |
||
152 | |||
153 | 78 | View Code Duplication | if ($depth !== null) { |
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. ![]() |
|||
154 | 12 | $condition[] = ['<=', "{$tableName}.[[{$this->depthAttribute}]]", $this->owner->getAttribute($this->depthAttribute) + $depth]; |
|
155 | } |
||
156 | |||
157 | 78 | $query = $this->owner->find() |
|
158 | 78 | ->andWhere($condition) |
|
159 | 78 | ->andWhere($this->treeCondition()) |
|
160 | 78 | ->addOrderBy(["{$tableName}.[[{$attribute}]]" => $backOrder ? SORT_DESC : SORT_ASC]); |
|
161 | 78 | $query->multiple = true; |
|
162 | |||
163 | 78 | return $query; |
|
164 | } |
||
165 | |||
166 | /** |
||
167 | * @return \yii\db\ActiveQuery |
||
168 | */ |
||
169 | 3 | public function getChildren() |
|
170 | { |
||
171 | 3 | return $this->getDescendants(1); |
|
172 | } |
||
173 | |||
174 | /** |
||
175 | * @param int|null $depth |
||
176 | * @return \yii\db\ActiveQuery |
||
177 | */ |
||
178 | 3 | public function getLeaves($depth = null) |
|
179 | { |
||
180 | 3 | $tableName = $this->owner->tableName(); |
|
181 | 3 | $query = $this->getDescendants($depth) |
|
182 | 3 | ->andWhere(["{$tableName}.[[{$this->leftAttribute}]]" => new Expression("{$tableName}.[[{$this->rightAttribute}]] - 1")]); |
|
183 | 3 | $query->multiple = true; |
|
184 | 3 | return $query; |
|
185 | } |
||
186 | |||
187 | /** |
||
188 | * @return \yii\db\ActiveQuery |
||
189 | */ |
||
190 | 3 | View Code Duplication | public function getPrev() |
0 ignored issues
–
show
This method seems to be duplicated in 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. ![]() |
|||
191 | { |
||
192 | 3 | $tableName = $this->owner->tableName(); |
|
193 | 3 | $query = $this->owner->find() |
|
194 | 3 | ->andWhere(["{$tableName}.[[{$this->rightAttribute}]]" => $this->owner->getAttribute($this->leftAttribute) - 1]) |
|
195 | 3 | ->andWhere($this->treeCondition()) |
|
196 | 3 | ->limit(1); |
|
197 | 3 | $query->multiple = false; |
|
198 | 3 | return $query; |
|
199 | } |
||
200 | |||
201 | /** |
||
202 | * @return \yii\db\ActiveQuery |
||
203 | */ |
||
204 | 3 | View Code Duplication | public function getNext() |
0 ignored issues
–
show
This method seems to be duplicated in 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. ![]() |
|||
205 | { |
||
206 | 3 | $tableName = $this->owner->tableName(); |
|
207 | 3 | $query = $this->owner->find() |
|
208 | 3 | ->andWhere(["{$tableName}.[[{$this->leftAttribute}]]" => $this->owner->getAttribute($this->rightAttribute) + 1]) |
|
209 | 3 | ->andWhere($this->treeCondition()) |
|
210 | 3 | ->limit(1); |
|
211 | 3 | $query->multiple = false; |
|
212 | 3 | return $query; |
|
213 | } |
||
214 | |||
215 | /** |
||
216 | * Populate children relations for self and all descendants |
||
217 | * @param int $depth = null |
||
218 | * @param string|array $with = null |
||
219 | * @return static |
||
220 | */ |
||
221 | 3 | public function populateTree($depth = null, $with = null) |
|
222 | { |
||
223 | /** @var ActiveRecord[]|static[] $nodes */ |
||
224 | 3 | $query = $this->getDescendants($depth); |
|
225 | 3 | if ($with) { |
|
226 | $query->with($with); |
||
227 | } |
||
228 | 3 | $nodes = $query->all(); |
|
229 | |||
230 | 3 | $key = $this->owner->getAttribute($this->leftAttribute); |
|
231 | 3 | $relates = []; |
|
232 | 3 | $parents = [$key]; |
|
233 | 3 | $prev = $this->owner->getAttribute($this->depthAttribute); |
|
234 | 3 | foreach($nodes as $node) |
|
235 | { |
||
236 | 3 | $level = $node->getAttribute($this->depthAttribute); |
|
237 | 3 | if ($level <= $prev) { |
|
238 | 3 | $parents = array_slice($parents, 0, $level - $prev - 1); |
|
239 | } |
||
240 | |||
241 | 3 | $key = end($parents); |
|
242 | 3 | if (!isset($relates[$key])) { |
|
243 | 3 | $relates[$key] = []; |
|
244 | } |
||
245 | 3 | $relates[$key][] = $node; |
|
246 | |||
247 | 3 | $parents[] = $node->getAttribute($this->leftAttribute); |
|
248 | 3 | $prev = $level; |
|
249 | } |
||
250 | |||
251 | 3 | $ownerDepth = $this->owner->getAttribute($this->depthAttribute); |
|
252 | 3 | $nodes[] = $this->owner; |
|
253 | 3 | foreach ($nodes as $node) { |
|
254 | 3 | $key = $node->getAttribute($this->leftAttribute); |
|
255 | 3 | if (isset($relates[$key])) { |
|
256 | 3 | $node->populateRelation('children', $relates[$key]); |
|
257 | 3 | } elseif ($depth === null || $ownerDepth + $depth > $node->getAttribute($this->depthAttribute)) { |
|
258 | 3 | $node->populateRelation('children', []); |
|
259 | } |
||
260 | } |
||
261 | |||
262 | 3 | return $this->owner; |
|
263 | } |
||
264 | |||
265 | /** |
||
266 | * @return bool |
||
267 | */ |
||
268 | 72 | public function isRoot() |
|
269 | { |
||
270 | 72 | return $this->owner->getAttribute($this->leftAttribute) === 1; |
|
271 | } |
||
272 | |||
273 | /** |
||
274 | * @param ActiveRecord $node |
||
275 | * @return bool |
||
276 | */ |
||
277 | 69 | public function isChildOf($node) |
|
278 | { |
||
279 | 69 | $result = $this->owner->getAttribute($this->leftAttribute) > $node->getAttribute($this->leftAttribute) |
|
280 | 69 | && $this->owner->getAttribute($this->rightAttribute) < $node->getAttribute($this->rightAttribute); |
|
281 | |||
282 | 69 | View Code Duplication | if ($result && $this->treeAttribute !== null) { |
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. ![]() |
|||
283 | 6 | $result = $this->owner->getAttribute($this->treeAttribute) === $node->getAttribute($this->treeAttribute); |
|
284 | } |
||
285 | |||
286 | 69 | return $result; |
|
287 | } |
||
288 | |||
289 | /** |
||
290 | * @return bool |
||
291 | */ |
||
292 | 6 | public function isLeaf() |
|
293 | { |
||
294 | 6 | return $this->owner->getAttribute($this->rightAttribute) - $this->owner->getAttribute($this->leftAttribute) === 1; |
|
295 | } |
||
296 | |||
297 | /** |
||
298 | * @return ActiveRecord |
||
299 | */ |
||
300 | 12 | public function makeRoot() |
|
301 | { |
||
302 | 12 | $this->operation = self::OPERATION_MAKE_ROOT; |
|
0 ignored issues
–
show
It seems like
self::OPERATION_MAKE_ROOT of type integer is incompatible with the declared type string|null of property $operation .
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.. ![]() |
|||
303 | 12 | return $this->owner; |
|
304 | } |
||
305 | |||
306 | /** |
||
307 | * @param ActiveRecord $node |
||
308 | * @return ActiveRecord |
||
309 | */ |
||
310 | 33 | public function prependTo($node) |
|
311 | { |
||
312 | 33 | $this->operation = self::OPERATION_PREPEND_TO; |
|
0 ignored issues
–
show
It seems like
self::OPERATION_PREPEND_TO of type integer is incompatible with the declared type string|null of property $operation .
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.. ![]() |
|||
313 | 33 | $this->node = $node; |
|
314 | 33 | return $this->owner; |
|
315 | } |
||
316 | |||
317 | /** |
||
318 | * @param ActiveRecord $node |
||
319 | * @return ActiveRecord |
||
320 | */ |
||
321 | 33 | public function appendTo($node) |
|
322 | { |
||
323 | 33 | $this->operation = self::OPERATION_APPEND_TO; |
|
0 ignored issues
–
show
It seems like
self::OPERATION_APPEND_TO of type integer is incompatible with the declared type string|null of property $operation .
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.. ![]() |
|||
324 | 33 | $this->node = $node; |
|
325 | 33 | return $this->owner; |
|
326 | } |
||
327 | |||
328 | /** |
||
329 | * @param ActiveRecord $node |
||
330 | * @return ActiveRecord |
||
331 | */ |
||
332 | 27 | public function insertBefore($node) |
|
333 | { |
||
334 | 27 | $this->operation = self::OPERATION_INSERT_BEFORE; |
|
0 ignored issues
–
show
It seems like
self::OPERATION_INSERT_BEFORE of type integer is incompatible with the declared type string|null of property $operation .
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.. ![]() |
|||
335 | 27 | $this->node = $node; |
|
336 | 27 | return $this->owner; |
|
337 | } |
||
338 | |||
339 | /** |
||
340 | * @param ActiveRecord $node |
||
341 | * @return ActiveRecord |
||
342 | */ |
||
343 | 30 | public function insertAfter($node) |
|
344 | { |
||
345 | 30 | $this->operation = self::OPERATION_INSERT_AFTER; |
|
0 ignored issues
–
show
It seems like
self::OPERATION_INSERT_AFTER of type integer is incompatible with the declared type string|null of property $operation .
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.. ![]() |
|||
346 | 30 | $this->node = $node; |
|
347 | 30 | return $this->owner; |
|
348 | } |
||
349 | |||
350 | /** |
||
351 | * Need for paulzi/auto-tree |
||
352 | */ |
||
353 | public function preDeleteWithChildren() |
||
354 | { |
||
355 | $this->operation = self::OPERATION_DELETE_ALL; |
||
0 ignored issues
–
show
It seems like
self::OPERATION_DELETE_ALL of type integer is incompatible with the declared type string|null of property $operation .
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.. ![]() |
|||
356 | } |
||
357 | |||
358 | /** |
||
359 | * @return bool|int |
||
360 | * @throws \Exception |
||
361 | * @throws \yii\db\Exception |
||
362 | */ |
||
363 | 9 | public function deleteWithChildren() |
|
364 | { |
||
365 | 9 | $this->operation = self::OPERATION_DELETE_ALL; |
|
0 ignored issues
–
show
It seems like
self::OPERATION_DELETE_ALL of type integer is incompatible with the declared type string|null of property $operation .
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.. ![]() |
|||
366 | 9 | if (!$this->owner->isTransactional(ActiveRecord::OP_DELETE)) { |
|
367 | $transaction = $this->owner->getDb()->beginTransaction(); |
||
368 | try { |
||
369 | $result = $this->deleteWithChildrenInternal(); |
||
370 | if ($result === false) { |
||
371 | $transaction->rollBack(); |
||
372 | } else { |
||
373 | $transaction->commit(); |
||
374 | } |
||
375 | return $result; |
||
376 | } catch (\Exception $e) { |
||
377 | $transaction->rollBack(); |
||
378 | throw $e; |
||
379 | } |
||
380 | } else { |
||
381 | 9 | $result = $this->deleteWithChildrenInternal(); |
|
382 | } |
||
383 | 6 | return $result; |
|
384 | } |
||
385 | |||
386 | /** |
||
387 | * @throws Exception |
||
388 | * @throws NotSupportedException |
||
389 | */ |
||
390 | 48 | public function beforeInsert() |
|
391 | { |
||
392 | 48 | if ($this->node !== null && !$this->node->getIsNewRecord()) { |
|
0 ignored issues
–
show
The method
getIsNewRecord does only exist in yii\db\ActiveRecord , but not in paulzi\nestedsets\NestedSetsBehavior .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
393 | 27 | $this->node->refresh(); |
|
0 ignored issues
–
show
The method
refresh does only exist in yii\db\ActiveRecord , but not in paulzi\nestedsets\NestedSetsBehavior .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
394 | } |
||
395 | 48 | switch ($this->operation) { |
|
396 | 48 | case self::OPERATION_MAKE_ROOT: |
|
397 | 6 | $condition = array_merge([$this->leftAttribute => 1], $this->treeCondition()); |
|
398 | 6 | if ($this->owner->find()->andWhere($condition)->one() !== null) { |
|
399 | 3 | throw new Exception('Can not create more than one root.'); |
|
400 | } |
||
401 | 3 | $this->owner->setAttribute($this->leftAttribute, 1); |
|
402 | 3 | $this->owner->setAttribute($this->rightAttribute, 2); |
|
403 | 3 | $this->owner->setAttribute($this->depthAttribute, 0); |
|
404 | 3 | break; |
|
405 | |||
406 | 42 | case self::OPERATION_PREPEND_TO: |
|
407 | 9 | $this->insertNode($this->node->getAttribute($this->leftAttribute) + 1, 1); |
|
0 ignored issues
–
show
The method
getAttribute does only exist in yii\db\ActiveRecord , but not in paulzi\nestedsets\NestedSetsBehavior .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
408 | 6 | break; |
|
409 | |||
410 | 33 | case self::OPERATION_APPEND_TO: |
|
411 | 9 | $this->insertNode($this->node->getAttribute($this->rightAttribute), 1); |
|
412 | 6 | break; |
|
413 | |||
414 | 24 | case self::OPERATION_INSERT_BEFORE: |
|
415 | 9 | $this->insertNode($this->node->getAttribute($this->leftAttribute), 0); |
|
416 | 6 | break; |
|
417 | |||
418 | 15 | case self::OPERATION_INSERT_AFTER: |
|
419 | 12 | $this->insertNode($this->node->getAttribute($this->rightAttribute) + 1, 0); |
|
420 | 6 | break; |
|
421 | |||
422 | default: |
||
423 | 3 | throw new NotSupportedException('Method "'. $this->owner->className() . '::insert" is not supported for inserting new nodes.'); |
|
0 ignored issues
–
show
The method
yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
424 | } |
||
425 | 27 | } |
|
426 | |||
427 | /** |
||
428 | * @throws Exception |
||
429 | */ |
||
430 | 27 | public function afterInsert() |
|
431 | { |
||
432 | 27 | if ($this->operation === self::OPERATION_MAKE_ROOT && $this->treeAttribute !== null && $this->owner->getAttribute($this->treeAttribute) === null) { |
|
433 | 3 | $id = $this->owner->getPrimaryKey(); |
|
434 | 3 | $this->owner->setAttribute($this->treeAttribute, $id); |
|
435 | |||
436 | 3 | $primaryKey = $this->owner->primaryKey(); |
|
437 | 3 | if (!isset($primaryKey[0])) { |
|
438 | throw new Exception('"' . $this->owner->className() . '" must have a primary key.'); |
||
0 ignored issues
–
show
The method
yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
439 | } |
||
440 | |||
441 | 3 | $this->owner->updateAll([$this->treeAttribute => $id], [$primaryKey[0] => $id]); |
|
442 | } |
||
443 | 27 | $this->operation = null; |
|
444 | 27 | $this->node = null; |
|
445 | 27 | } |
|
446 | |||
447 | /** |
||
448 | * @throws Exception |
||
449 | */ |
||
450 | 93 | public function beforeUpdate() |
|
451 | { |
||
452 | 93 | if ($this->node !== null && !$this->node->getIsNewRecord()) { |
|
0 ignored issues
–
show
The method
getIsNewRecord does only exist in yii\db\ActiveRecord , but not in paulzi\nestedsets\NestedSetsBehavior .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
453 | 78 | $this->node->refresh(); |
|
0 ignored issues
–
show
The method
refresh does only exist in yii\db\ActiveRecord , but not in paulzi\nestedsets\NestedSetsBehavior .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
454 | } |
||
455 | |||
456 | 93 | switch ($this->operation) { |
|
457 | 93 | case self::OPERATION_MAKE_ROOT: |
|
458 | 6 | if ($this->treeAttribute === null) { |
|
459 | throw new Exception('Can not move a node as the root when "treeAttribute" is not set.'); |
||
460 | } |
||
461 | 6 | if ($this->owner->getOldAttribute($this->treeAttribute) !== $this->owner->getAttribute($this->treeAttribute)) { |
|
462 | 3 | $this->treeChange = $this->owner->getAttribute($this->treeAttribute); |
|
463 | 3 | $this->owner->setAttribute($this->treeAttribute, $this->owner->getOldAttribute($this->treeAttribute)); |
|
464 | } |
||
465 | 6 | break; |
|
466 | |||
467 | 87 | case self::OPERATION_INSERT_BEFORE: |
|
468 | 69 | case self::OPERATION_INSERT_AFTER: |
|
0 ignored issues
–
show
|
|||
469 | 36 | if ($this->node->isRoot()) { |
|
0 ignored issues
–
show
The method
isRoot does only exist in paulzi\nestedsets\NestedSetsBehavior , but not in yii\db\ActiveRecord .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
470 | throw new Exception('Can not move a node before/after root.'); |
||
471 | } |
||
472 | |||
473 | 51 | case self::OPERATION_PREPEND_TO: |
|
474 | 27 | case self::OPERATION_APPEND_TO: |
|
475 | 84 | if ($this->node->getIsNewRecord()) { |
|
476 | 6 | throw new Exception('Can not move a node when the target node is new record.'); |
|
477 | } |
||
478 | |||
479 | 78 | if ($this->owner->equals($this->node)) { |
|
0 ignored issues
–
show
It seems like
$this->node can also be of type null or object<paulzi\nestedsets\NestedSetsBehavior> ; however, yii\db\ActiveRecord::equals() does only seem to accept object<yii\db\ActiveRecord> , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. ![]() |
|||
480 | 12 | throw new Exception('Can not move a node when the target node is same.'); |
|
481 | } |
||
482 | |||
483 | 66 | if ($this->node->isChildOf($this->owner)) { |
|
0 ignored issues
–
show
The method
isChildOf does only exist in paulzi\nestedsets\NestedSetsBehavior , but not in yii\db\ActiveRecord .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
484 | 12 | throw new Exception('Can not move a node when the target node is child.'); |
|
485 | } |
||
486 | } |
||
487 | 63 | } |
|
488 | |||
489 | /** |
||
490 | * |
||
491 | */ |
||
492 | 63 | public function afterUpdate() |
|
493 | { |
||
494 | 63 | switch ($this->operation) { |
|
495 | 63 | case self::OPERATION_MAKE_ROOT: |
|
496 | 6 | if ($this->treeChange || !$this->isRoot() || $this->owner->getIsNewRecord()) { |
|
497 | 3 | $this->moveNodeAsRoot(); |
|
498 | } |
||
499 | 6 | break; |
|
500 | |||
501 | 57 | case self::OPERATION_PREPEND_TO: |
|
502 | 15 | $this->moveNode($this->node->getAttribute($this->leftAttribute) + 1, 1); |
|
0 ignored issues
–
show
The method
getAttribute does only exist in yii\db\ActiveRecord , but not in paulzi\nestedsets\NestedSetsBehavior .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
503 | 15 | break; |
|
504 | |||
505 | 42 | case self::OPERATION_APPEND_TO: |
|
506 | 15 | $this->moveNode($this->node->getAttribute($this->rightAttribute), 1); |
|
507 | 15 | break; |
|
508 | |||
509 | 27 | case self::OPERATION_INSERT_BEFORE: |
|
510 | 12 | $this->moveNode($this->node->getAttribute($this->leftAttribute), 0); |
|
511 | 12 | break; |
|
512 | |||
513 | 15 | case self::OPERATION_INSERT_AFTER: |
|
514 | 12 | $this->moveNode($this->node->getAttribute($this->rightAttribute) + 1, 0); |
|
515 | 12 | break; |
|
516 | } |
||
517 | 63 | $this->operation = null; |
|
518 | 63 | $this->node = null; |
|
519 | 63 | $this->treeChange = null; |
|
520 | 63 | } |
|
521 | |||
522 | /** |
||
523 | * @throws Exception |
||
524 | */ |
||
525 | 18 | public function beforeDelete() |
|
526 | { |
||
527 | 18 | if ($this->owner->getIsNewRecord()) { |
|
528 | 6 | throw new Exception('Can not delete a node when it is new record.'); |
|
529 | } |
||
530 | 12 | if ($this->isRoot() && $this->operation !== self::OPERATION_DELETE_ALL) { |
|
531 | 3 | throw new Exception('Method "'. $this->owner->className() . '::delete" is not supported for deleting root nodes.'); |
|
0 ignored issues
–
show
The method
yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
532 | } |
||
533 | 9 | $this->owner->refresh(); |
|
534 | 9 | } |
|
535 | |||
536 | /** |
||
537 | * |
||
538 | */ |
||
539 | 9 | public function afterDelete() |
|
540 | { |
||
541 | 9 | $left = $this->owner->getAttribute($this->leftAttribute); |
|
542 | 9 | $right = $this->owner->getAttribute($this->rightAttribute); |
|
543 | 9 | if ($this->operation === static::OPERATION_DELETE_ALL || $this->isLeaf()) { |
|
544 | 6 | $this->shift($right + 1, null, $left - $right - 1); |
|
545 | } else { |
||
546 | 3 | $this->owner->updateAll( |
|
547 | [ |
||
548 | 3 | $this->leftAttribute => new Expression("[[{$this->leftAttribute}]] - 1"), |
|
549 | 3 | $this->rightAttribute => new Expression("[[{$this->rightAttribute}]] - 1"), |
|
550 | 3 | $this->depthAttribute => new Expression("[[{$this->depthAttribute}]] - 1"), |
|
551 | ], |
||
552 | 3 | $this->getDescendants()->where |
|
553 | ); |
||
554 | 3 | $this->shift($right + 1, null, -2); |
|
555 | } |
||
556 | 9 | $this->operation = null; |
|
557 | 9 | $this->node = null; |
|
558 | 9 | } |
|
559 | |||
560 | /** |
||
561 | * @return int |
||
562 | */ |
||
563 | 9 | protected function deleteWithChildrenInternal() |
|
564 | { |
||
565 | 9 | if (!$this->owner->beforeDelete()) { |
|
566 | return false; |
||
567 | } |
||
568 | 6 | $result = $this->owner->deleteAll($this->getDescendants(null, true)->where); |
|
569 | 6 | $this->owner->setOldAttributes(null); |
|
570 | 6 | $this->owner->afterDelete(); |
|
571 | 6 | return $result; |
|
572 | } |
||
573 | |||
574 | /** |
||
575 | * @param int $to |
||
576 | * @param int $depth |
||
577 | * @throws Exception |
||
578 | */ |
||
579 | 39 | protected function insertNode($to, $depth = 0) |
|
580 | { |
||
581 | 39 | if ($this->node->getIsNewRecord()) { |
|
0 ignored issues
–
show
The method
getIsNewRecord does only exist in yii\db\ActiveRecord , but not in paulzi\nestedsets\NestedSetsBehavior .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
582 | 12 | throw new Exception('Can not create a node when the target node is new record.'); |
|
583 | } |
||
584 | |||
585 | 27 | if ($depth === 0 && $this->node->isRoot()) { |
|
0 ignored issues
–
show
The method
isRoot does only exist in paulzi\nestedsets\NestedSetsBehavior , but not in yii\db\ActiveRecord .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
586 | 3 | throw new Exception('Can not insert a node before/after root.'); |
|
587 | } |
||
588 | 24 | $this->owner->setAttribute($this->leftAttribute, $to); |
|
589 | 24 | $this->owner->setAttribute($this->rightAttribute, $to + 1); |
|
590 | 24 | $this->owner->setAttribute($this->depthAttribute, $this->node->getAttribute($this->depthAttribute) + $depth); |
|
0 ignored issues
–
show
The method
getAttribute does only exist in yii\db\ActiveRecord , but not in paulzi\nestedsets\NestedSetsBehavior .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
591 | 24 | if ($this->treeAttribute !== null) { |
|
592 | 24 | $this->owner->setAttribute($this->treeAttribute, $this->node->getAttribute($this->treeAttribute)); |
|
593 | } |
||
594 | 24 | $this->shift($to, null, 2); |
|
595 | 24 | } |
|
596 | |||
597 | /** |
||
598 | * @param int $to |
||
599 | * @param int $depth |
||
600 | * @throws Exception |
||
601 | */ |
||
602 | 54 | protected function moveNode($to, $depth = 0) |
|
603 | { |
||
604 | 54 | $left = $this->owner->getAttribute($this->leftAttribute); |
|
605 | 54 | $right = $this->owner->getAttribute($this->rightAttribute); |
|
606 | 54 | $depth = $this->owner->getAttribute($this->depthAttribute) - $this->node->getAttribute($this->depthAttribute) - $depth; |
|
0 ignored issues
–
show
The method
getAttribute does only exist in yii\db\ActiveRecord , but not in paulzi\nestedsets\NestedSetsBehavior .
It seems like the method you are trying to call exists only in some of the possible types. Let’s take a look at an example: class A
{
public function foo() { }
}
class B extends A
{
public function bar() { }
}
/**
* @param A|B $x
*/
function someFunction($x)
{
$x->foo(); // This call is fine as the method exists in A and B.
$x->bar(); // This method only exists in B and might cause an error.
}
Available Fixes
![]() |
|||
607 | 54 | if ($this->treeAttribute === null || $this->owner->getAttribute($this->treeAttribute) === $this->node->getAttribute($this->treeAttribute)) { |
|
608 | // same root |
||
609 | 42 | $this->owner->updateAll( |
|
610 | 42 | [$this->depthAttribute => new Expression("-[[{$this->depthAttribute}]]" . sprintf('%+d', $depth))], |
|
611 | 42 | $this->getDescendants(null, true)->where |
|
612 | ); |
||
613 | 42 | $delta = $right - $left + 1; |
|
614 | 42 | if ($left >= $to) { |
|
615 | 24 | $this->shift($to, $left - 1, $delta); |
|
616 | 24 | $delta = $to - $left; |
|
617 | } else { |
||
618 | 18 | $this->shift($right + 1, $to - 1, -$delta); |
|
619 | 18 | $delta = $to - $right - 1; |
|
620 | } |
||
621 | 42 | $this->owner->updateAll( |
|
622 | [ |
||
623 | 42 | $this->leftAttribute => new Expression("[[{$this->leftAttribute}]]" . sprintf('%+d', $delta)), |
|
624 | 42 | $this->rightAttribute => new Expression("[[{$this->rightAttribute}]]" . sprintf('%+d', $delta)), |
|
625 | 42 | $this->depthAttribute => new Expression("-[[{$this->depthAttribute}]]"), |
|
626 | ], |
||
627 | [ |
||
628 | 42 | 'and', |
|
629 | 42 | $this->getDescendants(null, true)->where, |
|
630 | 42 | ['<', $this->depthAttribute, 0], |
|
631 | ] |
||
632 | ); |
||
633 | } else { |
||
634 | // move from other root |
||
635 | 12 | $tree = $this->node->getAttribute($this->treeAttribute); |
|
636 | 12 | $this->shift($to, null, $right - $left + 1, $tree); |
|
637 | 12 | $delta = $to - $left; |
|
638 | 12 | $this->owner->updateAll( |
|
639 | [ |
||
640 | 12 | $this->leftAttribute => new Expression("[[{$this->leftAttribute}]]" . sprintf('%+d', $delta)), |
|
641 | 12 | $this->rightAttribute => new Expression("[[{$this->rightAttribute}]]" . sprintf('%+d', $delta)), |
|
642 | 12 | $this->depthAttribute => new Expression("[[{$this->depthAttribute}]]" . sprintf('%+d', -$depth)), |
|
643 | 12 | $this->treeAttribute => $tree, |
|
644 | ], |
||
645 | 12 | $this->getDescendants(null, true)->where |
|
646 | ); |
||
647 | 12 | $this->shift($right + 1, null, $left - $right - 1); |
|
648 | } |
||
649 | 54 | } |
|
650 | |||
651 | /** |
||
652 | * |
||
653 | */ |
||
654 | 3 | protected function moveNodeAsRoot() |
|
655 | { |
||
656 | 3 | $left = $this->owner->getAttribute($this->leftAttribute); |
|
657 | 3 | $right = $this->owner->getAttribute($this->rightAttribute); |
|
658 | 3 | $depth = $this->owner->getAttribute($this->depthAttribute); |
|
659 | 3 | $tree = $this->treeChange ? $this->treeChange : $this->owner->getPrimaryKey(); |
|
660 | |||
661 | 3 | $this->owner->updateAll( |
|
662 | [ |
||
663 | 3 | $this->leftAttribute => new Expression("[[{$this->leftAttribute}]]" . sprintf('%+d', 1 - $left)), |
|
664 | 3 | $this->rightAttribute => new Expression("[[{$this->rightAttribute}]]" . sprintf('%+d', 1 - $left)), |
|
665 | 3 | $this->depthAttribute => new Expression("[[{$this->depthAttribute}]]" . sprintf('%+d', -$depth)), |
|
666 | 3 | $this->treeAttribute => $tree, |
|
667 | ], |
||
668 | 3 | $this->getDescendants(null, true)->where |
|
669 | ); |
||
670 | 3 | $this->shift($right + 1, null, $left - $right - 1); |
|
671 | 3 | } |
|
672 | |||
673 | |||
674 | |||
675 | /** |
||
676 | * @param int $from |
||
677 | * @param int $to |
||
678 | * @param int $delta |
||
679 | * @param int|null $tree |
||
680 | */ |
||
681 | 90 | protected function shift($from, $to, $delta, $tree = null) |
|
682 | { |
||
683 | 90 | if ($delta !== 0 && ($to === null || $to >= $from)) { |
|
684 | 78 | View Code Duplication | if ($this->treeAttribute !== null && $tree === null) { |
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. ![]() |
|||
685 | 78 | $tree = $this->owner->getAttribute($this->treeAttribute); |
|
686 | } |
||
687 | 78 | foreach ([$this->leftAttribute, $this->rightAttribute] as $i => $attribute) { |
|
688 | 78 | $this->owner->updateAll( |
|
689 | 78 | [$attribute => new Expression("[[{$attribute}]]" . sprintf('%+d', $delta))], |
|
690 | [ |
||
691 | 78 | 'and', |
|
692 | 78 | $to === null ? ['>=', $attribute, $from] : ['between', $attribute, $from, $to], |
|
693 | 78 | $this->treeAttribute !== null ? [$this->treeAttribute => $tree] : [], |
|
694 | ] |
||
695 | ); |
||
696 | } |
||
697 | } |
||
698 | 90 | } |
|
699 | |||
700 | /** |
||
701 | * @return array |
||
702 | */ |
||
703 | 99 | protected function treeCondition() |
|
704 | { |
||
705 | 99 | $tableName = $this->owner->tableName(); |
|
706 | 99 | if ($this->treeAttribute === null) { |
|
707 | 84 | return []; |
|
708 | } else { |
||
709 | 96 | return ["{$tableName}.[[{$this->treeAttribute}]]" => $this->owner->getAttribute($this->treeAttribute)]; |
|
710 | } |
||
711 | } |
||
712 | } |
||
713 |
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.