Completed
Push — master ( 12b940...ad8d5c )
by Asmir
04:05 queued 11s
created

TableMetadataStorage::complete()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 13
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 19
ccs 11
cts 11
cp 1
crap 3
rs 9.8333
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Migrations\Metadata\Storage;
6
7
use DateTimeImmutable;
8
use Doctrine\DBAL\Connection;
9
use Doctrine\DBAL\Connections\MasterSlaveConnection;
10
use Doctrine\DBAL\Platforms\AbstractPlatform;
11
use Doctrine\DBAL\Schema\AbstractSchemaManager;
12
use Doctrine\DBAL\Schema\Table;
13
use Doctrine\DBAL\Types\Type;
14
use Doctrine\Migrations\Metadata\ExecutedMigration;
15
use Doctrine\Migrations\Metadata\ExecutedMigrationsSet;
16
use Doctrine\Migrations\Version\Direction;
17
use Doctrine\Migrations\Version\ExecutionResult;
18
use Doctrine\Migrations\Version\Version;
19
use InvalidArgumentException;
20
use const CASE_LOWER;
21
use function array_change_key_case;
22
use function intval;
23
use function sprintf;
24
use function strtolower;
25
26
final class TableMetadataStorage implements MetadataStorage
27
{
28
    /** @var Connection */
29
    private $connection;
30
31
    /** @var AbstractSchemaManager */
32
    private $schemaManager;
33
34
    /** @var AbstractPlatform */
35
    private $platform;
36
37
    /** @var TableMetadataStorageConfiguration */
38
    private $configuration;
39
40 60
    public function __construct(Connection $connection, ?MetadataStorageConfiguration $configuration = null)
41
    {
42 60
        $this->connection    = $connection;
43 60
        $this->schemaManager = $connection->getSchemaManager();
44 60
        $this->platform      = $connection->getDatabasePlatform();
45
46 60
        if ($configuration !== null && ! ($configuration instanceof TableMetadataStorageConfiguration)) {
47
            throw new InvalidArgumentException(sprintf('%s accepts only %s as configuration', self::class, TableMetadataStorageConfiguration::class));
48
        }
49 60
        $this->configuration = $configuration ?: new TableMetadataStorageConfiguration();
0 ignored issues
show
introduced by
$configuration is of type null, thus it always evaluated to false.
Loading history...
50 60
    }
51
52 55
    private function isInitialized() : bool
53
    {
54 55
        if ($this->connection instanceof MasterSlaveConnection) {
55
            $this->connection->connect('master');
56
        }
57
58 55
        return $this->schemaManager->tablesExist([$this->configuration->getTableName()]);
59
    }
60
61 55
    private function initialize() : void
62
    {
63 55
        $schemaChangelog = new Table($this->configuration->getTableName());
64
65 55
        $schemaChangelog->addColumn($this->configuration->getVersionColumnName(), 'string', ['notnull' => true, 'length' => $this->configuration->getVersionColumnLength()]);
66 55
        $schemaChangelog->addColumn($this->configuration->getExecutedAtColumnName(), 'datetime', ['notnull' => false]);
67 55
        $schemaChangelog->addColumn($this->configuration->getExecutionTimeColumnName(), 'integer', ['notnull' => false]);
68
69 55
        $schemaChangelog->setPrimaryKey([$this->configuration->getVersionColumnName()]);
70
71 55
        $this->schemaManager->createTable($schemaChangelog);
72 55
    }
73
74 51
    public function getExecutedMigrations() : ExecutedMigrationsSet
75
    {
76 51
        if (! $this->isInitialized()) {
77 22
            $this->initialize();
78
        }
79
80 51
        $rows = $this->connection->fetchAll(sprintf('SELECT * FROM %s', $this->configuration->getTableName()));
81
82 51
        $migrations = [];
83 51
        foreach ($rows as $row) {
84 31
            $row = array_change_key_case($row, CASE_LOWER);
85
86 31
            $version = new Version($row[strtolower($this->configuration->getVersionColumnName())]);
87
88 31
            $executedAt = $row[strtolower($this->configuration->getExecutedAtColumnName())] ?? '';
89 31
            $executedAt = $executedAt !== ''
90 3
                ? DateTimeImmutable::createFromFormat($this->platform->getDateTimeFormatString(), $executedAt)
91 31
                : null;
92
93 31
            $executionTime = isset($row[strtolower($this->configuration->getExecutionTimeColumnName())])
94 3
                ? intval($row[strtolower($this->configuration->getExecutionTimeColumnName())])
95 31
                : null;
96
97 31
            $migration = new ExecutedMigration(
98 31
                $version,
99 31
                $executedAt instanceof DateTimeImmutable ? $executedAt : null,
100 31
                $executionTime
101
            );
102
103 31
            $migrations[(string) $version] = $migration;
104
        }
105
106 51
        return new ExecutedMigrationsSet($migrations);
107
    }
108
109 2
    public function reset() : void
110
    {
111 2
        if (! $this->isInitialized()) {
112 1
            $this->initialize();
113
        }
114
115 2
        $this->connection->executeUpdate(
116 2
            sprintf(
117 2
                'DELETE FROM %s WHERE 1 = 1',
118 2
                $this->platform->quoteIdentifier($this->configuration->getTableName())
119
            )
120
        );
121 2
    }
122
123 34
    public function complete(ExecutionResult $result) : void
124
    {
125 34
        if (! $this->isInitialized()) {
126 32
            $this->initialize();
127
        }
128
129 34
        if ($result->getDirection() === Direction::DOWN) {
130 5
            $this->connection->delete($this->configuration->getTableName(), [
131 5
                $this->configuration->getVersionColumnName() => (string) $result->getVersion(),
132
            ]);
133
        } else {
134 34
            $this->connection->insert($this->configuration->getTableName(), [
135 34
                $this->configuration->getVersionColumnName() => (string) $result->getVersion(),
136 34
                $this->configuration->getExecutedAtColumnName() => $result->getExecutedAt(),
137 34
                $this->configuration->getExecutionTimeColumnName() => $result->getTime(),
138
            ], [
139 34
                Type::STRING,
140
                Type::DATETIME,
141
                Type::INTEGER,
142
            ]);
143
        }
144 34
    }
145
}
146