Passed
Pull Request — master (#739)
by Michael
02:38
created

Version::__toString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Migrations\Version;
6
7
use DateTimeImmutable;
8
use DateTimeZone;
9
use Doctrine\DBAL\Connection;
10
use Doctrine\DBAL\Types\Type;
11
use Doctrine\Migrations\AbstractMigration;
12
use Doctrine\Migrations\Configuration\Configuration;
13
use Doctrine\Migrations\Exception\MigrationNotConvertibleToSql;
14
use Doctrine\Migrations\MigratorConfiguration;
15
use Doctrine\Migrations\OutputWriter;
16
use Doctrine\Migrations\Tracking\TableDefinition;
17
use function assert;
18
use function count;
19
use function date_default_timezone_get;
20
use function in_array;
21
use function str_replace;
22
23
/**
24
 * The Version class represents a single migration version. It wraps around your migration class
25
 * that extends the AbstractMigration class.
26
 *
27
 * @internal
28
 */
29
class Version
30
{
31
    /** @var Configuration */
32
    private $configuration;
33
34
    /** @var OutputWriter */
35
    private $outputWriter;
36
37
    /** @var string */
38
    private $version;
39
40
    /** @var AbstractMigration */
41
    private $migration;
42
43
    /** @var Connection */
44
    private $connection;
45
46
    /** @var string */
47
    private $class;
48
49
    /** @var int */
50
    private $state = State::NONE;
51
52
    /** @var ExecutorInterface */
53
    private $versionExecutor;
54
55 130
    public function __construct(
56
        Configuration $configuration,
57
        string $version,
58
        string $class,
59
        ExecutorInterface $versionExecutor
60
    ) {
61 130
        $this->configuration   = $configuration;
62 130
        $this->outputWriter    = $configuration->getOutputWriter();
63 130
        $this->class           = $class;
64 130
        $this->connection      = $configuration->getConnection();
65 130
        $this->migration       = new $class($this);
66 130
        $this->version         = $version;
67 130
        $this->versionExecutor = $versionExecutor;
68 130
    }
69
70
    public function __toString() : string
71
    {
72
        return $this->version;
73
    }
74
75 108
    public function getVersion() : string
76
    {
77 108
        return $this->version;
78
    }
79
80 1
    public function getDateTime() : string
81
    {
82 1
        $datetime = str_replace('Version', '', $this->version);
83 1
        $datetime = DateTimeImmutable::createFromFormat('YmdHis', $datetime);
84
85 1
        if ($datetime === false) {
86 1
            return '';
87
        }
88
89 1
        return $datetime->format('Y-m-d H:i:s');
90
    }
91
92 130
    public function getConfiguration() : Configuration
93
    {
94 130
        return $this->configuration;
95
    }
96
97 14
    public function getMigration() : AbstractMigration
98
    {
99 14
        return $this->migration;
100
    }
101
102 16
    public function isMigrated() : bool
103
    {
104 16
        return $this->configuration->hasVersionMigrated($this);
105
    }
106
107 4
    public function getExecutedAt() : ?DateTimeImmutable
108
    {
109 4
        $versionData          = $this->configuration->getVersionData($this);
110 4
        $executedAtColumnName = $this->configuration->getMigrationsExecutedAtColumnName();
111
112 4
        if (! isset($versionData[$executedAtColumnName])) {
113 1
            return null;
114
        }
115
116 4
        return (new DateTimeImmutable($versionData[$executedAtColumnName], new DateTimeZone('UTC')))
0 ignored issues
show
Bug Best Practice introduced by
The expression return new DateTimeImmut...efault_timezone_get())) could return the type false which is incompatible with the type-hinted return null|DateTimeImmutable. Consider adding an additional type-check to rule them out.
Loading history...
117 4
            ->setTimezone(new DateTimeZone(date_default_timezone_get()));
118
    }
119
120 55
    public function setState(int $state) : void
121
    {
122 55
        assert(in_array($state, State::STATES, true));
123
124 55
        $this->state = $state;
125 55
    }
126
127 11
    public function getExecutionState() : string
128
    {
129 11
        switch ($this->state) {
130 11
            case State::PRE:
131 1
                return 'Pre-Checks';
132
133 10
            case State::POST:
134 1
                return 'Post-Checks';
135
136 9
            case State::EXEC:
137 3
                return 'Execution';
138
139
            default:
140 6
                return 'No State';
141
        }
142
    }
143
144
    /**
145
     * @param mixed[] $params
146
     * @param mixed[] $types
147
     */
148 32
    public function addSql(string $sql, array $params = [], array $types = []) : void
149
    {
150 32
        $this->versionExecutor->addSql($sql, $params, $types);
151 32
    }
152
153 9
    public function writeSqlFile(
154
        string $path,
155
        string $direction = Direction::UP
156
    ) : bool {
157 9
        $versionExecutionResult = $this->execute(
158 9
            $direction,
159 9
            $this->getWriteSqlFileMigratorConfig()
160
        );
161
162 9
        if (count($versionExecutionResult->getParams()) !== 0) {
163 1
            throw MigrationNotConvertibleToSql::new($this->class);
164
        }
165
166 8
        $this->outputWriter->write("\n-- Version " . $this->version . "\n");
167
168 8
        $sqlQueries = [$this->version => $versionExecutionResult->getSql()];
169
170
        /*
171
         * Since the configuration object changes during the creation we cannot inject things
172
         * properly, so I had to violate LoD here (so please, let's find a way to solve it on v2).
173
         */
174 8
        return $this->configuration
175 8
            ->getQueryWriter()
176 8
            ->write($path, $direction, $sqlQueries);
177
    }
178
179 53
    public function execute(
180
        string $direction,
181
        ?MigratorConfiguration $migratorConfiguration = null
182
    ) : ExecutionResult {
183 53
        return $this->versionExecutor->execute(
184 53
            $this,
185 53
            $this->migration,
186 53
            $direction,
187 53
            $migratorConfiguration
188
        );
189
    }
190
191 12
    public function markMigrated() : void
192
    {
193 12
        $this->markVersion(Direction::UP);
194 12
    }
195
196 3
    public function markNotMigrated() : void
197
    {
198 3
        $this->markVersion(Direction::DOWN);
199 3
    }
200
201 51
    public function markVersion(string $direction) : void
202
    {
203 51
        $this->configuration->createMigrationTable();
204
205 51
        $migrationsColumnName = $this->configuration
206 51
            ->getQuotedMigrationsColumnName();
207
208 51
        $migrationsExecutedAtColumnName = $this->configuration
209 51
            ->getQuotedMigrationsExecutedAtColumnName();
210
211 51
        if ($direction === Direction::UP) {
212 50
            $this->connection->insert(
213 50
                $this->configuration->getMigrationsTableName(),
214
                [
215 50
                    $migrationsColumnName => $this->version,
216 50
                    $migrationsExecutedAtColumnName => $this->getExecutedAtDatabaseValue(),
217
                ]
218
            );
219
220 50
            return;
221
        }
222
223 10
        $this->connection->delete(
224 10
            $this->configuration->getMigrationsTableName(),
225
            [
226 10
                $migrationsColumnName => $this->version,
227
            ]
228
        );
229 10
    }
230
231 9
    private function getWriteSqlFileMigratorConfig() : MigratorConfiguration
232
    {
233 9
        return (new MigratorConfiguration())->setDryRun(true);
234
    }
235
236 50
    private function getExecutedAtDatabaseValue() : string
237
    {
238 50
        return Type::getType(TableDefinition::MIGRATION_EXECUTED_AT_COLUMN_TYPE)->convertToDatabaseValue(
0 ignored issues
show
Bug Best Practice introduced by
The expression return Doctrine\DBAL\Typ...>getDatabasePlatform()) returns the type DateTimeImmutable|false which is incompatible with the type-hinted return string.
Loading history...
239 50
            (new DateTimeImmutable('now'))->setTimezone(new DateTimeZone('UTC')),
240 50
            $this->connection->getDatabasePlatform()
241
        );
242
    }
243
}
244