Failed Conditions
Pull Request — master (#707)
by Jonathan
03:12
created

Version::writeSqlFile()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2

Importance

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