Completed
Branch feature/pre-split (9269d3)
by Anton
05:27
created

Transaction::run()   D

Complexity

Conditions 9
Paths 44

Size

Total Lines 40
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 20
nc 44
nop 0
dl 0
loc 40
rs 4.909
c 0
b 0
f 0
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\ORM;
8
9
use Spiral\ORM\Exceptions\RecordException;
10
11
/**
12
 * Singular ORM transaction with ability to automatically open transaction for all involved
13
 * drivers.
14
 *
15
 * Drivers will be automatically fetched from commands.
16
 */
17
class Transaction implements TransactionInterface
18
{
19
    /**
20
     * @var CommandInterface[]
21
     */
22
    private $commands = [];
23
24
    /**
25
     * Store entity information (update or insert).
26
     *
27
     * @param RecordInterface $record
28
     *
29
     * @throws RecordException
30
     */
31
    public function store(RecordInterface $record)
32
    {
33
        $this->addCommand($record->queueStore());
34
    }
35
36
    /**
37
     * Delete entity from database.
38
     *
39
     * @param RecordInterface $record
40
     *
41
     * @throws RecordException
42
     */
43
    public function delete(RecordInterface $record)
44
    {
45
        $this->addCommand($record->queueDelete());
46
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51
    public function addCommand(CommandInterface $command)
52
    {
53
        $this->commands[] = $command;
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     *
59
     * Executing transaction.
60
     */
61
    public function run()
62
    {
63
        //Related DBAL drivers
64
        $drivers = [];
65
66
        try {
67
            foreach ($this->commands as $command) {
68
                if ($command instanceof SQLCommandInterface) {
69
                    $driver = $command->getDriver();
70
71
                    if (in_array($driver, $drivers)) {
72
                        //Command requires DBAL driver to open transaction
73
                        $drivers[] = $driver;
74
                        $driver->beginTransaction();
75
                    }
76
                }
77
78
                //Execute command
79
                $command->execute();
80
            }
81
        } catch (\Throwable $e) {
82
            foreach (array_reverse($drivers) as $driver) {
83
                $driver->rollbackTransaction();
84
            }
85
86
            foreach (array_reverse($this->commands) as $command) {
87
                $command->rollBack();
88
            }
89
90
            throw $e;
91
        }
92
93
        foreach ($drivers as $driver) {
94
            $driver->commitTransaction();
95
        }
96
97
        foreach ($this->commands as $command) {
98
            $command->complete();
99
        }
100
    }
101
}