Completed
Push — develop ( cf0b6f...baacde )
by Bartko
06:00
created

Doctrine2DBALAdapter::delete()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 2

Importance

Changes 3
Bugs 1 Features 2
Metric Value
c 3
b 1
f 2
dl 0
loc 23
ccs 16
cts 16
cp 1
rs 9.0856
cc 2
eloc 14
nc 2
nop 3
crap 2
1
<?php
2
namespace StefanoTree\NestedSet\Adapter;
3
4
use Doctrine\DBAL\Connection as DbConnection;
5
use Doctrine\DBAL\Query\QueryBuilder;
6
use StefanoLockTable\Adapter\AdapterInterface as LockSqlBuilderInterface;
7
use StefanoLockTable\Factory as LockSqlBuilderFactory;
8
use StefanoTree\NestedSet\NodeInfo;
9
use StefanoTree\NestedSet\Options;
10
11
class Doctrine2DBALAdapter
12
    implements AdapterInterface
0 ignored issues
show
Coding Style introduced by
The implements keyword must be on the same line as the class name
Loading history...
13
{
14
    private $options;
15
16
    private $connection;
17
18
    private $defaultDbSelect;
19
20
    /**
21
     * @param Options $options
22
     * @param DbConnection $connection
23
     */
24 35
    public function __construct(Options $options, DbConnection $connection)
25
    {
26 35
        $this->options = $options;
27 35
        $this->connection = $connection;
28 35
    }
29
30
    /**
31
     * @return Options
32
     */
33 34
    private function getOptions()
34
    {
35 34
        return $this->options;
36
    }
37
38
    /**
39
     * @return DbConnection
40
     */
41 33
    private function getConnection()
42
    {
43 33
        return $this->connection;
44
    }
45
46
47
    /**
48
     * Data cannot contain keys like idColumnName, levelColumnName, ...
49
     *
50
     * @param array $data
51
     * @return array
52
     */
53 2
    private function cleanData(array $data)
54
    {
55 2
        $options = $this->getOptions();
56
57
        $disallowedDataKeys = array(
58 2
            $options->getIdColumnName(),
59 2
            $options->getLeftColumnName(),
60 2
            $options->getRightColumnName(),
61 2
            $options->getLevelColumnName(),
62 2
            $options->getParentIdColumnName(),
63 2
            $options->getScopeColumnName(),
64 2
        );
65
66 2
        return array_diff_key($data, array_flip($disallowedDataKeys));
67
    }
68
69
    /**
70
     * @param QueryBuilder $dbSelect
71
     * @return void
72
     */
73 1
    public function setDefaultDbSelect(QueryBuilder $dbSelect)
74
    {
75 1
        $this->defaultDbSelect = $dbSelect;
76 1
    }
77
78
    /**
79
     * Return clone of default db select
80
     * @return QueryBuilder
81
     */
82 33
    public function getDefaultDbSelect()
83
    {
84 33
        $options = $this->getOptions();
85
86 33
        if (null == $this->defaultDbSelect) {
87 32
            $queryBuilder = $this->getConnection()
88 32
                                 ->createQueryBuilder();
89
90 32
            $queryBuilder->select('*')
91 32
                         ->from($options->getTableName(), null);
92
93 32
            $this->defaultDbSelect = $queryBuilder;
94 32
        }
95
96 33
        $dbSelect = clone $this->defaultDbSelect;
97
98 33
        return $dbSelect;
99
    }
100
101 14
    public function lockTree($scope)
102
    {
103 14
        $options = $this->getOptions();
104
105 14
        $connection = $this->getConnection();
106
107 14
        $sql = $this->getDefaultDbSelect();
108 14
        $sql->select($options->getIdColumnName() . ' AS i');
109
110 14
        if ($options->getScopeColumnName()) {
111 4
            $sql->where($options->getScopeColumnName() . ' = ' . $connection->quote($scope));
112 4
        }
113
114 14
        $sql = $sql->getSQL() . ' FOR UPDATE';
115
116 14
        $connection->executeQuery($sql);
117 14
    }
118
119 15
    public function beginTransaction()
120
    {
121 15
        $this->getConnection()
122 15
             ->beginTransaction();
123 15
    }
124
125 14
    public function commitTransaction()
126
    {
127 14
        $this->getConnection()
128 14
             ->commit();
129 14
    }
130
131 1
    public function rollbackTransaction()
132
    {
133 1
        $this->getConnection()
134 1
             ->rollBack();
135 1
    }
136
137 2
    public function update($nodeId, array $data)
138
    {
139 2
        $options = $this->getOptions();
140
141 2
        $connection = $this->getConnection();
142
143 2
        $data = $this->cleanData($data);
144
145 2
        $sql = $connection->createQueryBuilder();
146
147 2
        $sql->update($options->getTableName(), null)
148 2
            ->where($options->getIdColumnName() . ' = :' . $options->getIdColumnName());
149
150 2
        foreach ($data as $key => $value) {
151 2
            $sql->set($connection->quoteIdentifier($key), ':' . $key);
152 2
        }
153
154 2
        $data[$options->getIdColumnName()] = $nodeId;
155
156 2
        $connection->executeUpdate($sql, $data);
157 2
    }
158
159 9
    public function insert(NodeInfo $nodeInfo, array $data)
160
    {
161 9
        $options = $this->getOptions();
162
163 9
        $connection = $this->getConnection();
164
165 9
        $data[$options->getParentIdColumnName()] = $nodeInfo->getParentId();
166 9
        $data[$options->getLevelColumnName()]    = $nodeInfo->getLevel();
167 9
        $data[$options->getLeftColumnName()]     = $nodeInfo->getLeft();
168 9
        $data[$options->getRightColumnName()]    = $nodeInfo->getRight();
169
170 9
        if ($options->getScopeColumnName()) {
171 3
            $data[$options->getScopeColumnName()] = $nodeInfo->getScope();
172 3
        }
173
174 9
        $connection->insert($options->getTableName(), $data);
175
176 9
        return $connection->lastInsertId($options->getSequenceName());
177
    }
178
179 2
    public function delete($leftIndex, $rightIndex, $scope=null)
180
    {
181 2
        $options = $this->getOptions();
182
183 2
        $connection = $this->getConnection();
184
185 2
        $sql = $connection->createQueryBuilder();
186 2
        $sql->delete($options->getTableName())
187 2
            ->where($options->getLeftColumnName() . ' >= :leftIndex'
188 2
                . ' AND ' . $options->getRightColumnName() . ' <= :rightIndex');
189
190
        $params = array(
191 2
            ':leftIndex' => $leftIndex,
192 2
            ':rightIndex' => $rightIndex,
193 2
        );
194
195 2
        if ($options->getScopeColumnName()) {
196 1
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
197 1
            $params[':scope'] = $scope;
198 1
        }
199
200 2
        $connection->executeQuery($sql, $params);
201 2
    }
202
203 12
    public function moveLeftIndexes($fromIndex, $shift, $scope=null)
204
    {
205 12
        $options = $this->getOptions();
206
207 12
        if (0 == $shift) {
208
            return;
209
        }
210
211 12
        $connection = $this->getConnection();
212
213 12
        $sql = $connection->createQueryBuilder();
214 12
        $sql->update($options->getTableName())
215 12
            ->set($options->getLeftColumnName(), $options->getLeftColumnName() . ' + :shift')
216 12
            ->where($options->getLeftColumnName() . ' > :fromIndex');
217
218
        $params = array(
219 12
            ':shift' => $shift,
220 12
            ':fromIndex' => $fromIndex,
221 12
        );
222
223 12
        if ($options->getScopeColumnName()) {
224 3
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
225 3
            $params[':scope'] = $scope;
226 3
        }
227
228 12
        $connection->executeUpdate($sql, $params);
229 12
    }
230
231 12
    public function moveRightIndexes($fromIndex, $shift, $scope=null)
232
    {
233 12
        $options = $this->getOptions();
234
235 12
        if (0 == $shift) {
236
            return;
237
        }
238
239 12
        $connection = $this->getConnection();
240
241 12
        $sql = $connection->createQueryBuilder();
242 12
        $sql->update($options->getTableName())
243 12
            ->set($options->getRightColumnName(), $options->getRightColumnName() . ' + :shift')
244 12
            ->where($options->getRightColumnName() . ' > :fromIndex');
245
246
        $params = array(
247 12
            ':shift' => $shift,
248 12
            ':fromIndex' => $fromIndex,
249 12
        );
250
251 12
        if ($options->getScopeColumnName()) {
252 3
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
253 3
            $params[':scope'] = $scope;
254 3
        }
255
256 12
        $connection->executeUpdate($sql, $params);
257 12
    }
258
259 4
    public function updateParentId($nodeId, $newParentId)
260
    {
261 4
        $options = $this->getOptions();
262
263 4
        $connection = $this->getConnection();
264
265 4
        $sql = $connection->createQueryBuilder();
266 4
        $sql->update($options->getTableName())
267 4
            ->set($options->getParentIdColumnName(), ':parentId')
268 4
            ->where($options->getIdColumnName() . ' = :nodeId');
269
270
        $params = array(
271 4
            ':parentId' => $newParentId,
272 4
            ':nodeId' => $nodeId,
273 4
        );
274
275 4
        $connection->executeUpdate($sql, $params);
276 4
    }
277
278 5
    public function updateLevels($leftIndexFrom, $rightIndexTo, $shift, $scope=null)
279
    {
280 5
        $options = $this->getOptions();
281
282 5
        if (0 == $shift) {
283 1
            return;
284
        }
285
286 4
        $connection = $this->getConnection();
287
288 4
        $sql = $connection->createQueryBuilder();
289 4
        $sql->update($options->getTableName())
290 4
            ->set($options->getLevelColumnName(), $options->getLevelColumnName() . ' + :shift')
291 4
            ->where($options->getLeftColumnName() . ' >= :leftFrom'
292 4
                    . ' AND ' . $options->getRightColumnName() . ' <= :rightTo');
293
294
        $params = array(
295 4
            ':shift' => $shift,
296 4
            ':leftFrom' => $leftIndexFrom,
297 4
            ':rightTo' => $rightIndexTo,
298 4
        );
299
300 4
        if ($options->getScopeColumnName()) {
301
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
302
            $params[':scope'] = $scope;
303
        }
304
305 4
        $connection->executeUpdate($sql, $params);
306 4
    }
307
308 5
    public function moveBranch($leftIndexFrom, $rightIndexTo, $shift, $scope=null)
309
    {
310 5
        if (0 == $shift) {
311
            return;
312
        }
313
314 5
        $options = $this->getOptions();
315
316 5
        $connection = $this->getConnection();
317
318 5
        $sql = $connection->createQueryBuilder();
319 5
        $sql->update($options->getTableName())
320 5
            ->set($options->getLeftColumnName(), $options->getLeftColumnName() . ' + :shift')
321 5
            ->set($options->getRightColumnName(), $options->getRightColumnName() . ' + :shift')
322 5
            ->where($options->getLeftColumnName() . ' >= :leftFrom'
323 5
                . ' AND ' . $options->getRightColumnName() . ' <= :rightTo');
324
325
        $params = array(
326 5
            ':shift' => $shift,
327 5
            ':leftFrom' => $leftIndexFrom,
328 5
            ':rightTo' => $rightIndexTo,
329 5
        );
330
331 5
        if ($options->getScopeColumnName()) {
332 1
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
333 1
            $params[':scope'] = $scope;
334 1
        }
335
336 5
        $connection->executeUpdate($sql, $params);
337 5
    }
338
339 8
    public function getRoots($scope=null)
340
    {
341 8
        $options = $this->getOptions();
342
343 8
        $connection = $this->getConnection();
344
345 8
        $sql = $this->getDefaultDbSelect();
346 8
        $sql->where($options->getParentIdColumnName() . ' = :parentId');
347
348
        $params = array(
349 8
            'parentId' => 0,
350 8
        );
351
352 8
        if (null != $scope && $options->getScopeColumnName()) {
353 2
            $sql->where($options->getScopeColumnName() . ' = :scope');
354 2
            $params[':scope'] = $scope;
355 2
        }
356
357 8
        $stmt = $connection->executeQuery($sql, $params);
358
359 8
        $node = $stmt->fetchAll();
360
361 8
        return $node;
362
    }
363
364 7
    public function getRoot($scope=null)
365
    {
366 7
        $roots = $this->getRoots($scope);
367 7
        return ($roots) ?  $roots[0] : array();
368
    }
369
370 22
    public function getNode($nodeId)
371
    {
372 22
        $options = $this->getOptions();
373
374 22
        $nodeId = (int) $nodeId;
375
376 22
        $connection = $this->getConnection();
377
378
379 22
        $sql = $this->getDefaultDbSelect();
380 22
        $sql->where($options->getIdColumnName() . ' = :' . $options->getIdColumnName());
381
382
        $params = array(
383 22
            $options->getIdColumnName() => $nodeId,
384 22
        );
385
386 22
        $stmt = $connection->executeQuery($sql, $params);
387
388 22
        $node = $stmt->fetch();
389
390 22
        if (is_array($node)) {
391 21
            return $node;
392
        }
393 7
    }
394
395 20
    public function getNodeInfo($nodeId)
396
    {
397 20
        $options = $this->getOptions();
398 20
        $result = $this->getNode($nodeId);
399
400 20
        if (null == $result) {
401 6
            $result = null;
402 6
        } else {
403 19
            $id        = $result[$options->getIdColumnName()];
404 19
            $parentId  = $result[$options->getParentIdColumnName()];
405 19
            $level     = $result[$options->getLevelColumnName()];
406 19
            $left      = $result[$options->getLeftColumnName()];
407 19
            $right     = $result[$options->getRightColumnName()];
408
409 19
            if (isset($result[$options->getScopeColumnName()])) {
410 6
                $scope = $result[$options->getScopeColumnName()];
411 6
            } else {
412 13
                $scope = null;
413
            }
414
415 19
            $result = new NodeInfo($id, $parentId, $level, $left, $right, $scope);
416
        }
417
418 20
        return $result;
419
    }
420
421 2
    public function getPath($nodeId, $startLevel = 0, $excludeLastNode = false)
422
    {
423 2
        $options = $this->getOptions();
424
425 2
        $startLevel = (int) $startLevel;
426
427
        // node does not exist
428 2
        if (!$nodeInfo = $this->getNodeInfo($nodeId)) {
429 1
            return;
430
        }
431
432 2
        $connection = $this->getConnection();
433
434 2
        $sql = $this->getDefaultDbSelect();
435 2
        $sql->where($options->getLeftColumnName() . ' <= :leftIndex')
436 2
            ->andWhere($options->getRightColumnName() . ' >= :rightIndex')
437 2
            ->orderBy($options->getLeftColumnName(), 'ASC');
438
439
        $params = array(
440 2
            'leftIndex' => $nodeInfo->getLeft(),
441 2
            'rightIndex' => $nodeInfo->getRight(),
442 2
        );
443
444 2
        if (0 < $startLevel) {
445 1
            $sql->andWhere($options->getLevelColumnName() . ' >= :startLevel');
446
447 1
            $params['startLevel'] = $startLevel;
448 1
        }
449
450 2
        if (true == $excludeLastNode) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
451 1
            $sql->andWhere($options->getLevelColumnName() . ' < :level');
452
453 1
            $params['level'] = $nodeInfo->getLevel();
454 1
        }
455
456 2
        $stmt = $connection->executeQuery($sql, $params);
457
458 2
        $result = $stmt->fetchAll();
459
460 2
        if (is_array($result)) {
461 2
            return $result;
462
        }
463
    }
464
465 3
    public function getDescendants($nodeId = 1, $startLevel = 0, $levels = null, $excludeBranch = null)
466
    {
467 3
        $options = $this->getOptions();
468
469 3
        if (!$nodeInfo = $this->getNodeInfo($nodeId)) {
470 2
            return;
471
        }
472
473 3
        $connection = $this->getConnection();
474 3
        $sql = $this->getDefaultDbSelect();
475 3
        $sql->orderBy($options->getLeftColumnName(), 'ASC');
476
477 3
        $params = array();
478
479 3
        if ($options->getScopeColumnName()) {
480 1
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
481 1
            $params['scope'] = $nodeInfo->getScope();
482 1
        }
483
484 3
        if (0 != $startLevel) {
485 2
            $sql->andWhere($options->getLevelColumnName() . ' >= :startLevel');
486
487 2
            $params['startLevel'] = $nodeInfo->getLevel() + (int) $startLevel;
488 2
        }
489
490 3
        if (null != $levels) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $levels of type integer|null against null; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
491 2
            $sql->andWhere($options->getLevelColumnName() . '< :endLevel');
492 2
            $params['endLevel'] = $nodeInfo->getLevel() + (int) $startLevel + abs($levels);
493 2
        }
494
495 3
        if (null != $excludeBranch && null != ($excludeNodeInfo = $this->getNodeInfo($excludeBranch))) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $excludeBranch of type integer|null against null; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
496 1
            $sql->andWhere('(' . $options->getLeftColumnName() . ' BETWEEN :left AND :exLeftMinusOne'
497 1
                    . ') OR (' . $options->getLeftColumnName() . ' BETWEEN :exRightPlusOne AND :right)')
498 1
                ->andWhere('(' . $options->getRightColumnName() . ' BETWEEN :exRightPlusOne AND :right'
499 1
                    . ') OR (' . $options->getRightColumnName() . ' BETWEEN :left AND :exLeftMinusOne)');
500
501 1
            $params['left']           = $nodeInfo->getLeft();
502 1
            $params['exLeftMinusOne'] = $excludeNodeInfo->getLeft() - 1;
503 1
            $params['exRightPlusOne'] = $excludeNodeInfo->getRight() + 1;
504 1
            $params['right']          = $nodeInfo->getRight();
505 1
        } else {
506 3
            $sql->andWhere($options->getLeftColumnName() . ' >= :left')
507 3
                ->andWhere($options->getRightColumnName() . ' <= :right');
508
509 3
            $params['left']  = $nodeInfo->getLeft();
510 3
            $params['right'] = $nodeInfo->getRight();
511
        }
512
513 3
        $stmt = $connection->executeQuery($sql, $params);
514
515 3
        $result = $stmt->fetchAll();
516
517 3
        if (0 < count($result)) {
518 3
            return $result;
519
        }
520 1
    }
521
}
522