Completed
Push — develop ( 0f123e...6d6ae7 )
by Bartko
05:00
created

Doctrine2DBALAdapter::getConnection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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