Completed
Push — master ( 82e7b9...66591e )
by Bartko
03:50
created

Zend2DbAdapter::rollbackTransaction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 5
ccs 0
cts 4
cp 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
crap 2
1
<?php
2
namespace StefanoTree\NestedSet\Adapter;
3
4
use StefanoTree\NestedSet\Options;
5
use StefanoDb\Adapter\Adapter as DbAdapter;
6
use Zend\Db;
7
use StefanoTree\NestedSet\NodeInfo;
8
use StefanoLockTable\Factory as LockSqlBuilderFactory;
9
use StefanoLockTable\Adapter\AdapterInterface as LockSqlBuilderInterface;
10
11
class Zend2DbAdapter
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 $dbAdapter;
17
18
    private $defaultDbSelect = null;
19
20
    private $lockSqlBuilder;
21
22 21
    public function __construct(Options $options, DbAdapter $dbAdapter)
23
    {
24 21
        $this->options = $options;
25 21
        $this->dbAdapter = $dbAdapter;
26 21
    }
27
28
    /**
29
     * @return Options
30
     */
31 20
    private function getOptions()
32
    {
33 20
        return $this->options;
34
    }
35
36
    /**
37
     * @return DbAdapter
38
     */
39 17
    private function getDbAdapter()
40
    {
41 17
        return $this->dbAdapter;
42
    }
43
44
    /**
45
     * Data cannot contain keys like idColumnName, levelColumnName, ...
46
     *
47
     * @param array $data
48
     * @return array
49
     */
50 1
    private function cleanData(array $data)
51
    {
52 1
        $options = $this->getOptions();
53
54
        $disallowedDataKeys = array(
55 1
            $options->getIdColumnName(),
56 1
            $options->getLeftColumnName(),
57 1
            $options->getRightColumnName(),
58 1
            $options->getLevelColumnName(),
59 1
            $options->getParentIdColumnName(),
60 1
        );
61
62 1
        return array_diff_key($data, array_flip($disallowedDataKeys));
63
    }
64
65
    /**
66
     * @param Db\Sql\Select $dbSelect
67
     * @return void
68
     */
69 1
    public function setDefaultDbSelect(Db\Sql\Select $dbSelect)
70
    {
71 1
        $this->defaultDbSelect = $dbSelect;
72 1
    }
73
74
    /**
75
     * Return clone of default db select
76
     * @return Db\Sql\Select
77
     */
78 18
    public function getDefaultDbSelect()
79
    {
80 18
        $options = $this->getOptions();
81
82 18
        if (null == $this->defaultDbSelect) {
83 18
            $this->defaultDbSelect = new Db\Sql\Select($options->getTableName());
84 17
        }
85
86 18
        $dbSelect = clone $this->defaultDbSelect;
87
88 18
        return $dbSelect;
89
    }
90
91
    /**
92
    * @return LockSqlBuilderInterface
93
    */
94 12
    private function getLockSqlBuilder()
95
    {
96 12
        if (null == $this->lockSqlBuilder) {
97 12
            $vendorName = $this->getDbAdapter()
98 12
                               ->getDriver()
99 12
                               ->getDatabasePlatformName();
100
101 12
            $factory = new LockSqlBuilderFactory();
102 12
            $this->lockSqlBuilder = $factory->createAdapter($vendorName);
103 12
        }
104
105 12
        return $this->lockSqlBuilder;
106
    }
107
108 12
    public function lockTable()
109
    {
110 12
        $tableName = $this->getOptions()
111 12
                          ->getTableName();
112
113 12
        $sql = $this->getLockSqlBuilder()
114 12
                    ->getLockSqlString($tableName);
115
116 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...
117 12
            $this->getDbAdapter()
118 12
                 ->query($sql, DbAdapter::QUERY_MODE_EXECUTE);
119 12
        }
120 12
    }
121
122 12
    public function unlockTable()
123
    {
124 12
        $sql = $this->getLockSqlBuilder()
125 12
                    ->getUnlockSqlString();
126
127 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...
128
            $this->getDbAdapter()
129
                 ->query($sql, DbAdapter::QUERY_MODE_EXECUTE);
130
        }
131 12
    }
132
133 12
    public function beginTransaction()
134
    {
135 12
        $this->getDbAdapter()
136 12
             ->begin();
137 12
    }
138
139 12
    public function commitTransaction()
140
    {
141 12
        $this->getDbAdapter()
142 12
             ->commit();
143 12
    }
144
145
    public function rollbackTransaction()
146
    {
147
        $this->getDbAdapter()
148
             ->rollback();
149
    }
150
151 2
    public function update($nodeId, array $data, NodeInfo $nodeInfo = null)
152
    {
153 2
        $options = $this->getOptions();
154
155 2
        $dbAdapter = $this->getDbAdapter();
156
157 2
        if (null == $nodeInfo) {
158 1
            $data = $this->cleanData($data);
159 1
        } else {
160 1
            $data[$options->getParentIdColumnName()] = $nodeInfo->getParentId();
161 1
            $data[$options->getLevelColumnName()]    = $nodeInfo->getLevel();
162 1
            $data[$options->getLeftColumnName()]     = $nodeInfo->getLeft();
163 1
            $data[$options->getRightColumnName()]    = $nodeInfo->getRight();
164
        }
165
166 2
        $update = new Db\Sql\Update($options->getTableName());
167 2
        $update->set($data)
168 2
               ->where(array(
169 2
                    $options->getIdColumnName() => $nodeId,
170 2
               ));
171
172 2
        $dbAdapter->query($update->getSqlString($dbAdapter->getPlatform()),
173 2
                DbAdapter::QUERY_MODE_EXECUTE);
174 2
    }
175
176 5
    public function insert(NodeInfo $nodeInfo, array $data)
177
    {
178 4
        $options = $this->getOptions();
179
180 4
        $dbAdapter = $this->getDbAdapter();
181
182 4
        $data[$options->getParentIdColumnName()] = $nodeInfo->getParentId();
183 4
        $data[$options->getLevelColumnName()]    = $nodeInfo->getLevel();
184 5
        $data[$options->getLeftColumnName()]     = $nodeInfo->getLeft();
185 4
        $data[$options->getRightColumnName()]    = $nodeInfo->getRight();
186
187 4
        $insert = new Db\Sql\Insert($options->getTableName());
188 4
        $insert->values($data);
189 4
        $dbAdapter->query($insert->getSqlString($dbAdapter->getPlatform()),
190 4
            DbAdapter::QUERY_MODE_EXECUTE);
191
192 4
        $lastGeneratedValue = $dbAdapter->getDriver()
193 4
                                        ->getLastGeneratedValue($options->getSequenceName());
0 ignored issues
show
Unused Code introduced by
The call to DriverInterface::getLastGeneratedValue() has too many arguments starting with $options->getSequenceName().

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
194
195 4
        return $lastGeneratedValue;
196
    }
197
198 1
    public function delete($leftIndex, $rightIndex)
199
    {
200 1
        $options = $this->getOptions();
201
202 1
        $dbAdapter = $this->getDbAdapter();
203
204 1
        $delete = new Db\Sql\Delete($options->getTableName());
205 1
        $delete->where
206 1
               ->greaterThanOrEqualTo($options->getLeftColumnName(), $leftIndex)
207 1
               ->AND
208 1
               ->lessThanOrEqualTo($options->getRightColumnName(), $rightIndex);
209
210 1
        $dbAdapter->query($delete->getSqlString($dbAdapter->getPlatform()),
211 1
            DbAdapter::QUERY_MODE_EXECUTE);
212 1
    }
213
214 2
    public function deleteAll($expectNodeId)
215
    {
216 1
        $options = $this->getOptions();
217 1
        $dbAdapter = $this->getDbAdapter();
218
219 1
        $delete = new Db\Sql\Delete;
220 1
        $delete->from($options->getTableName())
221 2
               ->where
222 1
               ->notEqualTo($options->getIdColumnName(), $expectNodeId);
223 1
        $dbAdapter->query($delete->getSqlString($dbAdapter->getPlatform()),
224 1
            DbAdapter::QUERY_MODE_EXECUTE);
225 1
    }
226
227 9
    public function moveLeftIndexes($fromIndex, $shift)
228
    {
229 9
        $options = $this->getOptions();
230
231 9
        if (0 == $shift) {
232
            return;
233
        }
234
235 9
        $dbAdapter = $this->getDbAdapter();
236 9
        $dbPlatform = $dbAdapter->getPlatform();
237
238 9
        $sql = 'UPDATE ' . $dbPlatform->quoteIdentifier($options->getTableName())
239 9
                . ' SET '
240 9
                    . $dbPlatform->quoteIdentifier($options->getLeftColumnName()) . ' = '
241 9
                        . $dbPlatform->quoteIdentifier($options->getLeftColumnName()) . ' + :shift'
242 9
                . ' WHERE '
243 9
                    . $dbPlatform->quoteIdentifier($options->getLeftColumnName()) . ' > :fromIndex';
244
245
        $binds = array(
246 9
            ':shift' => $shift,
247 9
            ':fromIndex' => $fromIndex,
248 9
        );
249
250 9
        $dbAdapter->query($sql)
0 ignored issues
show
Bug introduced by
The method execute does only exist in Zend\Db\Adapter\Driver\StatementInterface, but not in Zend\Db\Adapter\Driver\R...tSet\ResultSetInterface.

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

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
251 9
                  ->execute($binds);
252 9
    }
253
254 15
    public function moveRightIndexes($fromIndex, $shift)
255
    {
256 9
        $options = $this->getOptions();
257
258 9
        if (0 == $shift) {
259
            return;
260
        }
261
262 9
        $dbAdapter = $this->getDbAdapter();
263 9
        $dbPlatform = $dbAdapter->getPlatform();
264
265 15
        $sql = 'UPDATE ' . $dbPlatform->quoteIdentifier($options->getTableName())
266 9
                . ' SET '
267 9
                    . $dbPlatform->quoteIdentifier($options->getRightColumnName()) . ' = '
268 9
                        . $dbPlatform->quoteIdentifier($options->getRightColumnName()) . ' + :shift'
269 9
                . ' WHERE '
270 9
                    . $dbPlatform->quoteIdentifier($options->getRightColumnName()) . ' > :fromIndex';
271
272
        $binds = array(
273 9
            ':shift' => $shift,
274 9
            ':fromIndex' => $fromIndex,
275 9
        );
276
277 9
        $dbAdapter->query($sql)
0 ignored issues
show
Bug introduced by
The method execute does only exist in Zend\Db\Adapter\Driver\StatementInterface, but not in Zend\Db\Adapter\Driver\R...tSet\ResultSetInterface.

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

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
278 9
                  ->execute($binds);
279 9
    }
280
281 4
    public function updateParentId($nodeId, $newParentId)
282
    {
283 4
        $options = $this->getOptions();
284
285 4
        $dbAdapter = $this->getDbAdapter();
286
287 4
        $update = new Db\Sql\Update($options->getTableName());
288 4
        $update->set(array(
289 4
                    $options->getParentIdColumnName() => $newParentId,
290 4
               ))
291 4
               ->where(array(
292 4
                   $options->getIdColumnName() => $nodeId,
293 4
               ));
294
295 4
        $dbAdapter->query($update->getSqlString($dbAdapter->getPlatform()),
296 4
            DbAdapter::QUERY_MODE_EXECUTE);
297 4
    }
298
299 4
    public function updateLevels($leftIndexFrom, $rightIndexTo, $shift)
300
    {
301 4
        $options = $this->getOptions();
302
303 4
        if (0 == $shift) {
304
            return;
305
        }
306
307 4
        $dbAdapter = $this->getDbAdapter();
308 4
        $dbPlatform = $dbAdapter->getPlatform();
309
310 4
        $sql = 'UPDATE ' . $dbPlatform->quoteIdentifier($options->getTableName())
311 4
            . ' SET '
312 4
                . $dbPlatform->quoteIdentifier($options->getLevelColumnName()) . ' = '
313 4
                    . $dbPlatform->quoteIdentifier($options->getLevelColumnName()) . ' + :shift'
314 4
            . ' WHERE '
315 4
                . $dbPlatform->quoteIdentifier($options->getLeftColumnName()) . ' >= :leftFrom'
316 4
                . ' AND ' . $dbPlatform->quoteIdentifier($options->getRightColumnName()) . ' <= :rightTo';
317
318
        $binds = array(
319 4
            ':shift' => $shift,
320 4
            ':leftFrom' => $leftIndexFrom,
321 4
            ':rightTo' => $rightIndexTo,
322 4
        );
323
324 4
        $dbAdapter->query($sql)
0 ignored issues
show
Bug introduced by
The method execute does only exist in Zend\Db\Adapter\Driver\StatementInterface, but not in Zend\Db\Adapter\Driver\R...tSet\ResultSetInterface.

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

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
325 4
                  ->execute($binds);
326 4
    }
327
328 4
    public function moveBranch($leftIndexFrom, $rightIndexTo, $shift)
329
    {
330 4
        if (0 == $shift) {
331
            return;
332
        }
333
334 4
        $options = $this->getOptions();
335
336 4
        $dbAdapter = $this->getDbAdapter();
337 4
        $dbPlatform = $dbAdapter->getPlatform();
338
339 4
        $sql = 'UPDATE ' . $dbPlatform->quoteIdentifier($options->getTableName())
340 4
            . ' SET '
341 4
                . $dbPlatform->quoteIdentifier($options->getLeftColumnName()) . ' = '
342 4
                    . $dbPlatform->quoteIdentifier($options->getLeftColumnName()) . ' + :shift, '
343 4
                . $dbPlatform->quoteIdentifier($options->getRightColumnName()) . ' = '
344 4
                    . $dbPlatform->quoteIdentifier($options->getRightColumnName()) . ' + :shift'
345 4
            . ' WHERE '
346 4
                . $dbPlatform->quoteIdentifier($options->getLeftColumnName()) . ' >= :leftFrom'
347 4
                . ' AND ' . $dbPlatform->quoteIdentifier($options->getRightColumnName()) . ' <= :rightTo';
348
349
        $binds = array(
350 4
            ':shift' => $shift,
351 4
            ':leftFrom' => $leftIndexFrom,
352 4
            ':rightTo' => $rightIndexTo,
353 4
        );
354
355 4
        $dbAdapter->query($sql)
0 ignored issues
show
Bug introduced by
The method execute does only exist in Zend\Db\Adapter\Driver\StatementInterface, but not in Zend\Db\Adapter\Driver\R...tSet\ResultSetInterface.

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

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
356 4
                  ->execute($binds);
357 4
    }
358
359 15
    public function getNode($nodeId)
360
    {
361 15
        $options = $this->getOptions();
362
363 15
        $nodeId = (int) $nodeId;
364
365 15
        $dbAdapter = $this->getDbAdapter();
366
367 15
        $select = $this->getDefaultDbSelect()
368 15
                       ->where(array($options->getIdColumnName() =>  $nodeId));
369
370 15
        $result = $dbAdapter->query($select->getSqlString($dbAdapter->getPlatform()),
371 15
                DbAdapter::QUERY_MODE_EXECUTE);
372
373 15
        $array = $result->toArray();
374
375 15
        if (0 < count($array)) {
376 14
            return $array[0];
377 1
        }
378 7
    }
379
380 14
    public function getNodeInfo($nodeId)
381
    {
382 14
        $options = $this->getOptions();
383 14
        $result = $this->getNode($nodeId);
384
385 14
        if (null == $result) {
386 6
            $result = null;
387 6
        } else {
388 13
            $id        = $result[$options->getIdColumnName()];
389 13
            $parentId  = $result[$options->getParentIdColumnName()];
390 13
            $level     = $result[$options->getLevelColumnName()];
391 13
            $left      = $result[$options->getLeftColumnName()];
392 13
            $right     = $result[$options->getRightColumnName()];
393
394 13
            $result = new NodeInfo($id, $parentId, $level, $left, $right);
395
        }
396
397 14
        return $result;
398
    }
399
400 1
    public function getPath($nodeId, $startLevel = 0, $excludeLastNode = false)
401
    {
402 1
        $options = $this->getOptions();
403
404 1
        $startLevel = (int) $startLevel;
405
406
        // node does not exist
407 1
        if (!$nodeInfo = $this->getNodeInfo($nodeId)) {
408 1
            return;
409
        }
410
411 1
        $dbAdapter = $this->getDbAdapter();
412
413 1
        $select = $this->getDefaultDbSelect();
414 1
        $select->where
415 1
               ->lessThanOrEqualTo($options->getLeftColumnName(), $nodeInfo->getLeft())
416 1
               ->AND
417 1
               ->greaterThanOrEqualTo($options->getRightColumnName(), $nodeInfo->getRight());
418
419 1
        $select->order($options->getLeftColumnName() . ' ASC');
420
421 1
        if (0 < $startLevel) {
422 1
            $select->where
423 1
                   ->greaterThanOrEqualTo($options->getLevelColumnName(), $startLevel);
424 1
        }
425
426 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...
427 1
            $select->where
428 1
                   ->lessThan($options->getLevelColumnName(), $nodeInfo->getLevel());
429 1
        }
430
431 1
        $result = $dbAdapter->query($select->getSqlString($dbAdapter->getPlatform()),
432 1
            DbAdapter::QUERY_MODE_EXECUTE);
433
434 1
        return $result->toArray();
435
    }
436
437 2
    public function getDescendants($nodeId = 1, $startLevel = 0, $levels = null, $excludeBranch = null)
438
    {
439 2
        $options = $this->getOptions();
440
441 2
        if (!$nodeInfo = $this->getNodeInfo($nodeId)) {
442 2
            return;
443
        }
444
445 2
        $dbAdapter = $this->getDbAdapter();
446 2
        $select = $this->getDefaultDbSelect();
447 2
        $select->order($options->getLeftColumnName() . ' ASC');
448
449
450 2
        if (0 != $startLevel) {
451 2
            $level = $nodeInfo->getLevel() + (int) $startLevel;
452 2
            $select->where
453 2
                   ->greaterThanOrEqualTo($options->getLevelColumnName(), $level);
454 2
        }
455
456 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...
457 2
            $endLevel = $nodeInfo->getLevel() + (int) $startLevel + abs($levels);
458 2
            $select->where
459 2
                   ->lessThan($options->getLevelColumnName(), $endLevel);
460 2
        }
461
462 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...
463 1
            $select->where
464 1
                   ->NEST
465 1
                   ->between($options->getLeftColumnName(),
466 1
                        $nodeInfo->getLeft(), $excludeNodeInfo->getLeft() - 1)
467 1
                   ->OR
468 1
                   ->between($options->getLeftColumnName(),
469 1
                        $excludeNodeInfo->getRight() + 1, $nodeInfo->getRight())
470 1
                   ->UNNEST
471 1
                   ->AND
472 1
                   ->NEST
473 1
                   ->between($options->getRightColumnName(),
474 1
                        $excludeNodeInfo->getRight() + 1, $nodeInfo->getRight())
475 1
                   ->OR
476 1
                   ->between($options->getRightColumnName(),
477 1
                        $nodeInfo->getLeft(), $excludeNodeInfo->getLeft() - 1)
478 1
                   ->UNNEST;
479 1
        } else {
480 2
            $select->where
481 2
                   ->greaterThanOrEqualTo($options->getLeftColumnName(), $nodeInfo->getLeft())
482 2
                   ->AND
483 2
                   ->lessThanOrEqualTo($options->getRightColumnName(), $nodeInfo->getRight());
484
        }
485
486 2
        $result =  $dbAdapter->query($select->getSqlString($dbAdapter->getPlatform()),
487 2
            DbAdapter::QUERY_MODE_EXECUTE);
488
489 2
        $resultArray = $result->toArray();
490
491 2
        if (0 < count($resultArray)) {
492 2
            return $resultArray;
493
        }
494 1
    }
495
}
496