Completed
Push — master ( 2e5d0e...583994 )
by Bartko
06:02
created

Doctrine2DBALAdapter::update()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2

Importance

Changes 5
Bugs 1 Features 2
Metric Value
c 5
b 1
f 2
dl 0
loc 21
ccs 12
cts 12
cp 1
rs 9.3142
cc 2
eloc 11
nc 2
nop 2
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 StefanoTree\NestedSet\NodeInfo;
7
use StefanoTree\NestedSet\Options;
8
9
class Doctrine2DBALAdapter
10
    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...
11
{
12
    private $options;
13
14
    private $connection;
15
16
    private $defaultDbSelect;
17
18
    /**
19
     * @param Options $options
20
     * @param DbConnection $connection
21
     */
22 38
    public function __construct(Options $options, DbConnection $connection)
23
    {
24 38
        $this->options = $options;
25 38
        $this->connection = $connection;
26 38
    }
27
28
    /**
29
     * @return Options
30
     */
31 37
    private function getOptions()
32
    {
33 37
        return $this->options;
34
    }
35
36
    /**
37
     * @return DbConnection
38
     */
39 36
    private function getConnection()
40
    {
41 36
        return $this->connection;
42
    }
43
44
45
    /**
46
     * Data cannot contain keys like idColumnName, levelColumnName, ...
47
     *
48
     * @param array $data
49
     * @return array
50
     */
51 2
    private function cleanData(array $data)
52
    {
53 2
        $options = $this->getOptions();
54
55
        $disallowedDataKeys = array(
56 2
            $options->getIdColumnName(),
57 2
            $options->getLeftColumnName(),
58 2
            $options->getRightColumnName(),
59 2
            $options->getLevelColumnName(),
60 2
            $options->getParentIdColumnName(),
61 2
            $options->getScopeColumnName(),
62
        );
63
64 2
        return array_diff_key($data, array_flip($disallowedDataKeys));
65
    }
66
67
    /**
68
     * @param QueryBuilder $dbSelect
69
     * @return void
70
     */
71 1
    public function setDefaultDbSelect(QueryBuilder $dbSelect)
72
    {
73 1
        $this->defaultDbSelect = $dbSelect;
74 1
    }
75
76
    /**
77
     * Return clone of default db select
78
     * @return QueryBuilder
79
     */
80 36
    public function getDefaultDbSelect()
81
    {
82 36
        $options = $this->getOptions();
83
84 36
        if (null === $this->defaultDbSelect) {
85 35
            $queryBuilder = $this->getConnection()
86 35
                                 ->createQueryBuilder();
87
88 35
            $queryBuilder->select('*')
89 35
                         ->from($options->getTableName(), null);
90
91 35
            $this->defaultDbSelect = $queryBuilder;
92
        }
93
94 36
        $dbSelect = clone $this->defaultDbSelect;
95
96 36
        return $dbSelect;
97
    }
98
99 14
    public function lockTree($scope)
100
    {
101 14
        $options = $this->getOptions();
102
103 14
        $connection = $this->getConnection();
104
105 14
        $sql = $this->getDefaultDbSelect();
106 14
        $sql->select($options->getIdColumnName() . ' AS i');
107
108 14
        if ($options->getScopeColumnName()) {
109 4
            $sql->where($options->getScopeColumnName() . ' = ' . $connection->quote($scope));
110
        }
111
112 14
        $sql = $sql->getSQL() . ' FOR UPDATE';
113
114 14
        $connection->executeQuery($sql);
115 14
    }
116
117 15
    public function beginTransaction()
118
    {
119 15
        $this->getConnection()
120 15
             ->beginTransaction();
121 15
    }
122
123 14
    public function commitTransaction()
124
    {
125 14
        $this->getConnection()
126 14
             ->commit();
127 14
    }
128
129 1
    public function rollbackTransaction()
130
    {
131 1
        $this->getConnection()
132 1
             ->rollBack();
133 1
    }
134
135 2
    public function update($nodeId, array $data)
136
    {
137 2
        $options = $this->getOptions();
138
139 2
        $connection = $this->getConnection();
140
141 2
        $data = $this->cleanData($data);
142
143 2
        $sql = $connection->createQueryBuilder();
144
145 2
        $sql->update($options->getTableName(), null)
146 2
            ->where($options->getIdColumnName() . ' = :' . $options->getIdColumnName());
147
148 2
        foreach ($data as $key => $value) {
149 2
            $sql->set($connection->quoteIdentifier($key), ':' . $key);
150
        }
151
152 2
        $data[$options->getIdColumnName()] = $nodeId;
153
154 2
        $connection->executeUpdate($sql, $data);
155 2
    }
156
157 9
    public function insert(NodeInfo $nodeInfo, array $data)
158
    {
159 9
        $options = $this->getOptions();
160
161 9
        $connection = $this->getConnection();
162
163 9
        $data[$options->getParentIdColumnName()] = $nodeInfo->getParentId();
164 9
        $data[$options->getLevelColumnName()]    = $nodeInfo->getLevel();
165 9
        $data[$options->getLeftColumnName()]     = $nodeInfo->getLeft();
166 9
        $data[$options->getRightColumnName()]    = $nodeInfo->getRight();
167
168 9
        if ($options->getScopeColumnName()) {
169 3
            $data[$options->getScopeColumnName()] = $nodeInfo->getScope();
170
        }
171
172 9
        $connection->insert($options->getTableName(), $data);
173
174 9
        return $connection->lastInsertId($options->getSequenceName());
175
    }
176
177 2
    public function delete($leftIndex, $rightIndex, $scope = null)
178
    {
179 2
        $options = $this->getOptions();
180
181 2
        $connection = $this->getConnection();
182
183 2
        $sql = $connection->createQueryBuilder();
184 2
        $sql->delete($options->getTableName())
185 2
            ->where($options->getLeftColumnName() . ' >= :leftIndex'
186 2
                . ' AND ' . $options->getRightColumnName() . ' <= :rightIndex');
187
188
        $params = array(
189 2
            ':leftIndex' => $leftIndex,
190 2
            ':rightIndex' => $rightIndex,
191
        );
192
193 2
        if ($options->getScopeColumnName()) {
194 1
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
195 1
            $params[':scope'] = $scope;
196
        }
197
198 2
        $connection->executeQuery($sql, $params);
199 2
    }
200
201 12
    public function moveLeftIndexes($fromIndex, $shift, $scope = null)
202
    {
203 12
        $options = $this->getOptions();
204
205 12
        if (0 == $shift) {
206
            return;
207
        }
208
209 12
        $connection = $this->getConnection();
210
211 12
        $sql = $connection->createQueryBuilder();
212 12
        $sql->update($options->getTableName())
213 12
            ->set($options->getLeftColumnName(), $options->getLeftColumnName() . ' + :shift')
214 12
            ->where($options->getLeftColumnName() . ' > :fromIndex');
215
216
        $params = array(
217 12
            ':shift' => $shift,
218 12
            ':fromIndex' => $fromIndex,
219
        );
220
221 12
        if ($options->getScopeColumnName()) {
222 3
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
223 3
            $params[':scope'] = $scope;
224
        }
225
226 12
        $connection->executeUpdate($sql, $params);
227 12
    }
228
229 12
    public function moveRightIndexes($fromIndex, $shift, $scope = null)
230
    {
231 12
        $options = $this->getOptions();
232
233 12
        if (0 == $shift) {
234
            return;
235
        }
236
237 12
        $connection = $this->getConnection();
238
239 12
        $sql = $connection->createQueryBuilder();
240 12
        $sql->update($options->getTableName())
241 12
            ->set($options->getRightColumnName(), $options->getRightColumnName() . ' + :shift')
242 12
            ->where($options->getRightColumnName() . ' > :fromIndex');
243
244
        $params = array(
245 12
            ':shift' => $shift,
246 12
            ':fromIndex' => $fromIndex,
247
        );
248
249 12
        if ($options->getScopeColumnName()) {
250 3
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
251 3
            $params[':scope'] = $scope;
252
        }
253
254 12
        $connection->executeUpdate($sql, $params);
255 12
    }
256
257 4
    public function updateParentId($nodeId, $newParentId)
258
    {
259 4
        $options = $this->getOptions();
260
261 4
        $connection = $this->getConnection();
262
263 4
        $sql = $connection->createQueryBuilder();
264 4
        $sql->update($options->getTableName())
265 4
            ->set($options->getParentIdColumnName(), ':parentId')
266 4
            ->where($options->getIdColumnName() . ' = :nodeId');
267
268
        $params = array(
269 4
            ':parentId' => $newParentId,
270 4
            ':nodeId' => $nodeId,
271
        );
272
273 4
        $connection->executeUpdate($sql, $params);
274 4
    }
275
276 5
    public function updateLevels($leftIndexFrom, $rightIndexTo, $shift, $scope = null)
277
    {
278 5
        $options = $this->getOptions();
279
280 5
        if (0 == $shift) {
281 1
            return;
282
        }
283
284 4
        $connection = $this->getConnection();
285
286 4
        $sql = $connection->createQueryBuilder();
287 4
        $sql->update($options->getTableName())
288 4
            ->set($options->getLevelColumnName(), $options->getLevelColumnName() . ' + :shift')
289 4
            ->where($options->getLeftColumnName() . ' >= :leftFrom'
290 4
                    . ' AND ' . $options->getRightColumnName() . ' <= :rightTo');
291
292
        $params = array(
293 4
            ':shift' => $shift,
294 4
            ':leftFrom' => $leftIndexFrom,
295 4
            ':rightTo' => $rightIndexTo,
296
        );
297
298 4
        if ($options->getScopeColumnName()) {
299
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
300
            $params[':scope'] = $scope;
301
        }
302
303 4
        $connection->executeUpdate($sql, $params);
304 4
    }
305
306 5
    public function moveBranch($leftIndexFrom, $rightIndexTo, $shift, $scope = null)
307
    {
308 5
        if (0 == $shift) {
309
            return;
310
        }
311
312 5
        $options = $this->getOptions();
313
314 5
        $connection = $this->getConnection();
315
316 5
        $sql = $connection->createQueryBuilder();
317 5
        $sql->update($options->getTableName())
318 5
            ->set($options->getLeftColumnName(), $options->getLeftColumnName() . ' + :shift')
319 5
            ->set($options->getRightColumnName(), $options->getRightColumnName() . ' + :shift')
320 5
            ->where($options->getLeftColumnName() . ' >= :leftFrom'
321 5
                . ' AND ' . $options->getRightColumnName() . ' <= :rightTo');
322
323
        $params = array(
324 5
            ':shift' => $shift,
325 5
            ':leftFrom' => $leftIndexFrom,
326 5
            ':rightTo' => $rightIndexTo,
327
        );
328
329 5
        if ($options->getScopeColumnName()) {
330 1
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
331 1
            $params[':scope'] = $scope;
332
        }
333
334 5
        $connection->executeUpdate($sql, $params);
335 5
    }
336
337 8
    public function getRoots($scope = null)
338
    {
339 8
        $options = $this->getOptions();
340
341 8
        $connection = $this->getConnection();
342
343 8
        $sql = $this->getDefaultDbSelect();
344 8
        $sql->where($options->getParentIdColumnName() . ' = :parentId');
345
346
        $params = array(
347 8
            'parentId' => 0,
348
        );
349
350 8
        if (null != $scope && $options->getScopeColumnName()) {
351 2
            $sql->where($options->getScopeColumnName() . ' = :scope');
352 2
            $params[':scope'] = $scope;
353
        }
354
355 8
        $stmt = $connection->executeQuery($sql, $params);
356
357 8
        $node = $stmt->fetchAll();
358
359 8
        return $node;
360
    }
361
362 7
    public function getRoot($scope = null)
363
    {
364 7
        $roots = $this->getRoots($scope);
365 7
        return ($roots) ?  $roots[0] : array();
366
    }
367
368 25
    public function getNode($nodeId)
369
    {
370 25
        $options = $this->getOptions();
371
372 25
        $nodeId = (int) $nodeId;
373
374 25
        $connection = $this->getConnection();
375
376
377 25
        $sql = $this->getDefaultDbSelect();
378 25
        $sql->where($options->getIdColumnName() . ' = :' . $options->getIdColumnName());
379
380
        $params = array(
381 25
            $options->getIdColumnName() => $nodeId,
382
        );
383
384 25
        $stmt = $connection->executeQuery($sql, $params);
385
386 25
        $node = $stmt->fetch();
387
388 25
        return is_array($node) ? $node : null;
389
    }
390
391
    /**
392
     * @param array $data
393
     * @return NodeInfo
394
     */
395 22
    private function _buildNodeInfoObject(array $data)
396
    {
397 22
        $options = $this->getOptions();
398
399 22
        $id        = $data[$options->getIdColumnName()];
400 22
        $parentId  = $data[$options->getParentIdColumnName()];
401 22
        $level     = $data[$options->getLevelColumnName()];
402 22
        $left      = $data[$options->getLeftColumnName()];
403 22
        $right     = $data[$options->getRightColumnName()];
404
405 22
        if (isset($data[$options->getScopeColumnName()])) {
406 9
            $scope = $data[$options->getScopeColumnName()];
407
        } else {
408 16
            $scope = null;
409
        }
410
411 22
        return new NodeInfo($id, $parentId, $level, $left, $right, $scope);
412
    }
413
414 23
    public function getNodeInfo($nodeId)
415
    {
416 23
        $data = $this->getNode($nodeId);
417
418 23
        $result = ($data) ? $this->_buildNodeInfoObject($data) : null;
419
420 23
        return $result;
421
    }
422
423 3
    public function getChildrenNodeInfo($parentNodeId)
424
    {
425 3
        $connection = $this->getConnection();
426 3
        $options = $this->getOptions();
427
428 3
        $queryBuilder = $connection->createQueryBuilder();
429
430
        $columns = array(
431 3
            $options->getIdColumnName(),
432 3
            $options->getLeftColumnName(),
433 3
            $options->getRightColumnName(),
434 3
            $options->getParentIdColumnName(),
435 3
            $options->getLevelColumnName(),
436
        );
437
438 3
        $sql = $queryBuilder->select($columns)
439 3
                            ->from($options->getTableName())
440 3
                            ->where($options->getParentIdColumnName() . ' = :parentId')
441 3
                            ->orderBy($options->getLeftColumnName(), 'ASC');
442
443
        $params = array(
444 3
            'parentId' => $parentNodeId,
445
        );
446
447 3
        $stmt = $connection->executeQuery($sql, $params);
448
449 3
        $data = $stmt->fetchAll();
450
451 3
        $result = array();
452
453 3
        foreach ($data as $nodeData) {
454 3
            $result[] = $this->_buildNodeInfoObject($nodeData);
455
        }
456
457 3
        return $result;
458
    }
459
460 1
    public function updateNodeMetadata(NodeInfo $nodeInfo)
461
    {
462 1
        $options = $this->getOptions();
463
464 1
        $connection = $this->getConnection();
465
466 1
        $sql = $connection->createQueryBuilder();
467 1
        $sql->update($options->getTableName())
468 1
            ->set($options->getRightColumnName(), $nodeInfo->getRight())
469 1
            ->set($options->getLeftColumnName(), $nodeInfo->getLeft())
470 1
            ->set($options->getLevelColumnName(), $nodeInfo->getLevel())
471 1
            ->where($options->getIdColumnName() . ' = :nodeId');
472
473
        $params = array(
474 1
            ':nodeId' => $nodeInfo->getId(),
475
        );
476
477 1
        $connection->executeUpdate($sql, $params);
478 1
    }
479
480 2
    public function getPath($nodeId, $startLevel = 0, $excludeLastNode = false)
481
    {
482 2
        $options = $this->getOptions();
483
484 2
        $startLevel = (int) $startLevel;
485
486
        // node does not exist
487 2
        $nodeInfo = $this->getNodeInfo($nodeId);
488 2
        if (!$nodeInfo) {
489 1
            return;
490
        }
491
492 2
        $connection = $this->getConnection();
493
494 2
        $sql = $this->getDefaultDbSelect();
495 2
        $sql->where($options->getLeftColumnName() . ' <= :leftIndex')
496 2
            ->andWhere($options->getRightColumnName() . ' >= :rightIndex')
497 2
            ->orderBy($options->getLeftColumnName(), 'ASC');
498
499
        $params = array(
500 2
            'leftIndex' => $nodeInfo->getLeft(),
501 2
            'rightIndex' => $nodeInfo->getRight(),
502
        );
503
504 2
        if (0 < $startLevel) {
505 1
            $sql->andWhere($options->getLevelColumnName() . ' >= :startLevel');
506
507 1
            $params['startLevel'] = $startLevel;
508
        }
509
510 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...
511 1
            $sql->andWhere($options->getLevelColumnName() . ' < :level');
512
513 1
            $params['level'] = $nodeInfo->getLevel();
514
        }
515
516 2
        $stmt = $connection->executeQuery($sql, $params);
517
518 2
        $result = $stmt->fetchAll();
519
520 2
        return (is_array($result)) ? $result : null;
521
    }
522
523 3
    public function getDescendants($nodeId = 1, $startLevel = 0, $levels = null, $excludeBranch = null)
524
    {
525 3
        $options = $this->getOptions();
526
527 3
        if (!$nodeInfo = $this->getNodeInfo($nodeId)) {
528 2
            return;
529
        }
530
531 3
        $connection = $this->getConnection();
532 3
        $sql = $this->getDefaultDbSelect();
533 3
        $sql->orderBy($options->getLeftColumnName(), 'ASC');
534
535 3
        $params = array();
536
537 3
        if ($options->getScopeColumnName()) {
538 1
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
539 1
            $params['scope'] = $nodeInfo->getScope();
540
        }
541
542 3
        if (0 != $startLevel) {
543 2
            $sql->andWhere($options->getLevelColumnName() . ' >= :startLevel');
544
545 2
            $params['startLevel'] = $nodeInfo->getLevel() + (int) $startLevel;
546
        }
547
548 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...
549 2
            $sql->andWhere($options->getLevelColumnName() . '< :endLevel');
550 2
            $params['endLevel'] = $nodeInfo->getLevel() + (int) $startLevel + abs($levels);
551
        }
552
553 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...
554 1
            $sql->andWhere('(' . $options->getLeftColumnName() . ' BETWEEN :left AND :exLeftMinusOne'
555 1
                    . ') OR (' . $options->getLeftColumnName() . ' BETWEEN :exRightPlusOne AND :right)')
556 1
                ->andWhere('(' . $options->getRightColumnName() . ' BETWEEN :exRightPlusOne AND :right'
557 1
                    . ') OR (' . $options->getRightColumnName() . ' BETWEEN :left AND :exLeftMinusOne)');
558
559 1
            $params['left']           = $nodeInfo->getLeft();
560 1
            $params['exLeftMinusOne'] = $excludeNodeInfo->getLeft() - 1;
561 1
            $params['exRightPlusOne'] = $excludeNodeInfo->getRight() + 1;
562 1
            $params['right']          = $nodeInfo->getRight();
563
        } else {
564 3
            $sql->andWhere($options->getLeftColumnName() . ' >= :left')
565 3
                ->andWhere($options->getRightColumnName() . ' <= :right');
566
567 3
            $params['left']  = $nodeInfo->getLeft();
568 3
            $params['right'] = $nodeInfo->getRight();
569
        }
570
571 3
        $stmt = $connection->executeQuery($sql, $params);
572
573 3
        $result = $stmt->fetchAll();
574
575 3
        return (0 < count($result)) ? $result : null;
576
    }
577
}
578