Migrator::createTemplate()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 7
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 11
ccs 0
cts 10
cp 0
crap 12
rs 9.4285
1
<?php
2
namespace Wandu\Migrator;
3
4
use DirectoryIterator;
5
use RuntimeException;
6
use SplFileInfo;
7
use InvalidArgumentException;
8
use Wandu\Migrator\Contracts\Adapter;
9
use Wandu\Migrator\Contracts\MigrationInformation;
10
use Wandu\Migrator\Contracts\MigrationTemplate;
11
12
class Migrator
13
{
14
    /** @var \Wandu\Migrator\Contracts\Adapter */
15
    protected $adapter;
16
    
17
    /** @var \Wandu\Migrator\Contracts\MigrationTemplate */
18
    protected $template;
19
    
20
    /** @var \Wandu\Migrator\Configuration */
21
    protected $config;
22
23
    /**
24
     * @param \Wandu\Migrator\Contracts\Adapter $adapter
25
     * @param \Wandu\Migrator\Contracts\MigrationTemplate $template
26
     * @param \Wandu\Migrator\Configuration $config
27
     */
28
    public function __construct(Adapter $adapter, MigrationTemplate $template, Configuration $config)
29
    {
30
        $this->adapter = $adapter;
31
        $this->template = $template;
32
        $this->config = $config;
33
    }
34
35
    /**
36
     * @param string $name
37
     * @return string
38
     */
39
    public function createTemplate($name): string
40
    {
41
        $fileName = date('ymd_His_') . $name . '.php';
42
        $filePath = $this->config->getPath() . '/' . $fileName;
43
        if (file_exists($filePath) || !is_dir($this->config->getPath())) {
44
            throw new InvalidArgumentException(sprintf('cannot write the file at %s.', $filePath));
45
        }
46
47
        file_put_contents($filePath, $this->template->template($name));
48
        return $filePath;
49
    }
50
51
    /**
52
     * @return array|\Wandu\Migrator\Contracts\MigrationInformation[]
53
     */
54
    public function getMigrationInformations()
55
    {
56
        $migrations = [];
57
        foreach ($this->getAllMigrationFiles() as $file) {
58
            $migration = new FileMigrationInformation($file);
59
            $migrations[$migration->getId()] = $migration;
60
        }
61
        foreach ($this->adapter->getAppliedIds() as $version) {
62
            if (!array_key_exists($version, $migrations)) {
63
                $migrations[$version] = new UnknownMigrationInformation($version);
64
            }
65
        }
66
        ksort($migrations);
67
        return array_values($migrations);
68
    }
69
70
    /**
71
     * @param \Wandu\Migrator\Contracts\MigrationInformation $information
72
     * @return bool
73
     */
74
    public function isApplied(MigrationInformation $information): bool
75
    {
76
        return $this->adapter->isApplied($information->getId());
77
    }
78
79
    /**
80
     * @param string $migrationId
81
     */
82
    public function up($migrationId)
83
    {
84
        if (!preg_match('/^\d{6}_\d{6}$/', $migrationId)) {
85
            throw new RuntimeException("invalid migration id. it must be like 000000_000000.");
86
        }
87
        if ($this->adapter->isApplied($migrationId)) {
88
            throw new RuntimeException("this {$migrationId} is already applied.");
89
        }
90
91
        $migrationInfo = $this->getFileMigrationInformation($migrationId);
92
        $migrationInfo->loadMigrationFile();
93
94
        $this->adapter->getMigrationInstance($migrationInfo->getId(), $migrationInfo->getName())->up();
95
        $this->adapter->initialize();
96
        $this->adapter->addToMigrationTable($migrationId);
97
    }
98
99
    /**
100
     * @param string $migrationId
101
     */
102
    public function down($migrationId)
103
    {
104
        if (!preg_match('/^\d{6}_\d{6}$/', $migrationId)) {
105
            throw new RuntimeException("invalid migration id. it must be like 000000_000000.");
106
        }
107
        if (!$this->adapter->isApplied($migrationId)) {
108
            throw new RuntimeException("this {$migrationId} is not already applied.");
109
        }
110
111
        $migrationInfo = $this->getFileMigrationInformation($migrationId);
112
        $migrationInfo->loadMigrationFile();
113
114
        $this->adapter->getMigrationInstance($migrationInfo->getId(), $migrationInfo->getName())->down();
115
        $this->adapter->initialize();
116
        $this->adapter->removeFromMigrationTable($migrationId);
117
    }
118
119
    /**
120
     * @return array|\Wandu\Migrator\FileMigrationInformation[]
121
     */
122
    public function migrate()
123
    {
124
        $migratedMigrations = [];
125
        $migrations = $this->getMigrationInformations();
126
        foreach ($migrations as $migration) {
127
            if (!$this->adapter->isApplied($migration->getId())) {
128
                $this->up($migration->getId());
129
                $migratedMigrations[] = $migration;
130
            }
131
        }
132
        return $migratedMigrations;
133
    }
134
135
    /**
136
     * @param string $migrationId
137
     * @return \Wandu\Migrator\FileMigrationInformation
138
     */
139
    protected function getFileMigrationInformation($migrationId): FileMigrationInformation
140
    {
141
        foreach ($this->getAllMigrationFiles() as $file) {
142
            if (strpos($file, $migrationId . '_') !== false) {
143
                return new FileMigrationInformation($file);
144
            }
145
        }
146
        throw new RuntimeException("there is no migration id \"{$migrationId}\".");
147
    }
148
    
149
    /**
150
     * @return array
151
     */
152
    protected function getAllMigrationFiles()
153
    {
154
        $files = [];
155
        if (!is_dir($this->config->getPath())) {
156
            mkdir($this->config->getPath());
157
        }
158
        foreach (new DirectoryIterator($this->config->getPath()) as $file) {
159
            if ($file->isDot() || $file->isDir() || $file->getFilename()[0] === '.') continue;
160
            $files[] = $file->getFileInfo();
161
        }
162
        usort($files, function (SplFileInfo $file, SplFileInfo $nextFile) {
163
            if ($file->getFilename() > $nextFile->getFilename()) {
164
                return 1;
165
            }
166
            return $file->getFilename() < $nextFile->getFilename() ? -1 : 0;
167
        });
168
        return $files;
169
    }
170
}
171