Completed
Push — develop ( 7ed4f7...32afc4 )
by Bartko
03:33 queued 49s
created

Doctrine2DBALAdapter::getPath()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 43
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 5.0014

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 0
loc 43
ccs 25
cts 26
cp 0.9615
rs 8.439
cc 5
eloc 23
nc 9
nop 3
crap 5.0014
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 35
    public function __construct(Options $options, DbConnection $connection)
23
    {
24 35
        $this->options = $options;
25 35
        $this->connection = $connection;
26 35
    }
27
28
    /**
29
     * @return Options
30
     */
31 34
    private function getOptions()
32
    {
33 34
        return $this->options;
34
    }
35
36
    /**
37
     * @return DbConnection
38
     */
39 33
    private function getConnection()
40
    {
41 33
        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 2
        );
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 33
    public function getDefaultDbSelect()
81
    {
82 33
        $options = $this->getOptions();
83
84 33
        if (null == $this->defaultDbSelect) {
85 32
            $queryBuilder = $this->getConnection()
86 32
                                 ->createQueryBuilder();
87
88 32
            $queryBuilder->select('*')
89 32
                         ->from($options->getTableName(), null);
90
91 32
            $this->defaultDbSelect = $queryBuilder;
92 32
        }
93
94 33
        $dbSelect = clone $this->defaultDbSelect;
95
96 33
        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 4
        }
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 2
        }
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 3
        }
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 2
        );
192
193 2
        if ($options->getScopeColumnName()) {
194 1
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
195 1
            $params[':scope'] = $scope;
196 1
        }
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 12
        );
220
221 12
        if ($options->getScopeColumnName()) {
222 3
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
223 3
            $params[':scope'] = $scope;
224 3
        }
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 12
        );
248
249 12
        if ($options->getScopeColumnName()) {
250 3
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
251 3
            $params[':scope'] = $scope;
252 3
        }
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 4
        );
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 4
        );
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 5
        );
328
329 5
        if ($options->getScopeColumnName()) {
330 1
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
331 1
            $params[':scope'] = $scope;
332 1
        }
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 8
        );
349
350 8
        if (null != $scope && $options->getScopeColumnName()) {
351 2
            $sql->where($options->getScopeColumnName() . ' = :scope');
352 2
            $params[':scope'] = $scope;
353 2
        }
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 22
    public function getNode($nodeId)
369
    {
370 22
        $options = $this->getOptions();
371
372 22
        $nodeId = (int) $nodeId;
373
374 22
        $connection = $this->getConnection();
375
376
377 22
        $sql = $this->getDefaultDbSelect();
378 22
        $sql->where($options->getIdColumnName() . ' = :' . $options->getIdColumnName());
379
380
        $params = array(
381 22
            $options->getIdColumnName() => $nodeId,
382 22
        );
383
384 22
        $stmt = $connection->executeQuery($sql, $params);
385
386 22
        $node = $stmt->fetch();
387
388 22
        if (is_array($node)) {
389 21
            return $node;
390
        }
391 7
    }
392
393 20
    public function getNodeInfo($nodeId)
394
    {
395 20
        $options = $this->getOptions();
396 20
        $result = $this->getNode($nodeId);
397
398 20
        if (null == $result) {
399 6
            $result = null;
400 6
        } else {
401 19
            $id        = $result[$options->getIdColumnName()];
402 19
            $parentId  = $result[$options->getParentIdColumnName()];
403 19
            $level     = $result[$options->getLevelColumnName()];
404 19
            $left      = $result[$options->getLeftColumnName()];
405 19
            $right     = $result[$options->getRightColumnName()];
406
407 19
            if (isset($result[$options->getScopeColumnName()])) {
408 6
                $scope = $result[$options->getScopeColumnName()];
409 6
            } else {
410 13
                $scope = null;
411
            }
412
413 19
            $result = new NodeInfo($id, $parentId, $level, $left, $right, $scope);
414
        }
415
416 20
        return $result;
417
    }
418
419 2
    public function getPath($nodeId, $startLevel = 0, $excludeLastNode = false)
420
    {
421 2
        $options = $this->getOptions();
422
423 2
        $startLevel = (int) $startLevel;
424
425
        // node does not exist
426 2
        if (!$nodeInfo = $this->getNodeInfo($nodeId)) {
427 1
            return;
428
        }
429
430 2
        $connection = $this->getConnection();
431
432 2
        $sql = $this->getDefaultDbSelect();
433 2
        $sql->where($options->getLeftColumnName() . ' <= :leftIndex')
434 2
            ->andWhere($options->getRightColumnName() . ' >= :rightIndex')
435 2
            ->orderBy($options->getLeftColumnName(), 'ASC');
436
437
        $params = array(
438 2
            'leftIndex' => $nodeInfo->getLeft(),
439 2
            'rightIndex' => $nodeInfo->getRight(),
440 2
        );
441
442 2
        if (0 < $startLevel) {
443 1
            $sql->andWhere($options->getLevelColumnName() . ' >= :startLevel');
444
445 1
            $params['startLevel'] = $startLevel;
446 1
        }
447
448 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...
449 1
            $sql->andWhere($options->getLevelColumnName() . ' < :level');
450
451 1
            $params['level'] = $nodeInfo->getLevel();
452 1
        }
453
454 2
        $stmt = $connection->executeQuery($sql, $params);
455
456 2
        $result = $stmt->fetchAll();
457
458 2
        if (is_array($result)) {
459 2
            return $result;
460
        }
461
    }
462
463 3
    public function getDescendants($nodeId = 1, $startLevel = 0, $levels = null, $excludeBranch = null)
464
    {
465 3
        $options = $this->getOptions();
466
467 3
        if (!$nodeInfo = $this->getNodeInfo($nodeId)) {
468 2
            return;
469
        }
470
471 3
        $connection = $this->getConnection();
472 3
        $sql = $this->getDefaultDbSelect();
473 3
        $sql->orderBy($options->getLeftColumnName(), 'ASC');
474
475 3
        $params = array();
476
477 3
        if ($options->getScopeColumnName()) {
478 1
            $sql->andWhere($options->getScopeColumnName() . ' = :scope');
479 1
            $params['scope'] = $nodeInfo->getScope();
480 1
        }
481
482 3
        if (0 != $startLevel) {
483 2
            $sql->andWhere($options->getLevelColumnName() . ' >= :startLevel');
484
485 2
            $params['startLevel'] = $nodeInfo->getLevel() + (int) $startLevel;
486 2
        }
487
488 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...
489 2
            $sql->andWhere($options->getLevelColumnName() . '< :endLevel');
490 2
            $params['endLevel'] = $nodeInfo->getLevel() + (int) $startLevel + abs($levels);
491 2
        }
492
493 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...
494 1
            $sql->andWhere('(' . $options->getLeftColumnName() . ' BETWEEN :left AND :exLeftMinusOne'
495 1
                    . ') OR (' . $options->getLeftColumnName() . ' BETWEEN :exRightPlusOne AND :right)')
496 1
                ->andWhere('(' . $options->getRightColumnName() . ' BETWEEN :exRightPlusOne AND :right'
497 1
                    . ') OR (' . $options->getRightColumnName() . ' BETWEEN :left AND :exLeftMinusOne)');
498
499 1
            $params['left']           = $nodeInfo->getLeft();
500 1
            $params['exLeftMinusOne'] = $excludeNodeInfo->getLeft() - 1;
501 1
            $params['exRightPlusOne'] = $excludeNodeInfo->getRight() + 1;
502 1
            $params['right']          = $nodeInfo->getRight();
503 1
        } else {
504 3
            $sql->andWhere($options->getLeftColumnName() . ' >= :left')
505 3
                ->andWhere($options->getRightColumnName() . ' <= :right');
506
507 3
            $params['left']  = $nodeInfo->getLeft();
508 3
            $params['right'] = $nodeInfo->getRight();
509
        }
510
511 3
        $stmt = $connection->executeQuery($sql, $params);
512
513 3
        $result = $stmt->fetchAll();
514
515 3
        if (0 < count($result)) {
516 3
            return $result;
517
        }
518 1
    }
519
}
520