TransactionManager::transactional()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3.009

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 9
cts 10
cp 0.9
rs 9.6
c 0
b 0
f 0
cc 3
nc 4
nop 3
crap 3.009
1
<?php
2
3
namespace Dontdrinkandroot\Repository;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Exception;
7
use InvalidArgumentException;
8
use Psr\Log\LoggerInterface;
9
use Psr\Log\NullLogger;
10
11
/**
12
 * @author Philip Washington Sorst <[email protected]>
13
 */
14
class TransactionManager
15
{
16
    /** @var LoggerInterface */
17
    private $logger;
18
19
    /** @var EntityManagerInterface */
20
    private $entityManager;
21
22 22
    public function __construct(EntityManagerInterface $entityManager)
23
    {
24 22
        $this->entityManager = $entityManager;
25 22
        $this->logger = new NullLogger();
26 22
    }
27
28 22
    public function beginTransaction(): void
29
    {
30 22
        $this->entityManager->beginTransaction();
31 22
    }
32
33 20
    public function commitTransaction(bool $forceFlush = false): bool
34
    {
35 20
        $nestingLevel = $this->entityManager->getConnection()->getTransactionNestingLevel();
36
37
        /* No active transaction */
38 20
        if (!$this->isInTransaction()) {
39
            $this->logger->warning('No active Transaction for commit');
40
41
            return false;
42
        }
43
44 20
        $flushed = false;
45
        /* Topmost transaction, flush */
46 20
        if (1 === $nestingLevel || $forceFlush) {
47 20
            $flushed = true;
48 20
            $this->entityManager->flush();
49
        }
50 20
        $this->entityManager->commit();
51
52 20
        return $flushed;
53
    }
54
55 2
    public function rollbackTransaction(bool $closeEmOnException = true): void
56
    {
57
        /* No active transaction */
58 2
        if (!$this->isInTransaction()) {
59
            $this->logger->warning('No active Transaction for commit');
60
61
            return;
62
        }
63
64 2
        if ($closeEmOnException) {
65 2
            $this->entityManager->close();
66
        }
67 2
        $this->entityManager->rollback();
68 2
    }
69
70 22
    public function isInTransaction(): bool
71
    {
72 22
        return 0 !== $this->entityManager->getConnection()->getTransactionNestingLevel();
73
    }
74
75 22
    public function transactional(Callable $func, bool $forceFlush = false, bool $closeEmOnException = true)
76
    {
77 22
        if (!is_callable($func)) {
78
            throw new InvalidArgumentException('Expected argument of type "callable", got "' . gettype($func) . '"');
79
        }
80
81 22
        $this->beginTransaction();
82
83
        try {
84 22
            $return = call_user_func($func, $this);
85
86 20
            $this->commitTransaction($forceFlush);
87
88 20
            return $return;
89 2
        } catch (Exception $e) {
90 2
            $this->rollbackTransaction($closeEmOnException);
91
92 2
            throw $e;
93
        }
94
    }
95
96
    public function setLogger(LoggerInterface $logger): void
97
    {
98
        $this->logger = $logger;
99
    }
100
}
101