1
|
|
|
<?php |
2
|
|
|
namespace Wandu\Database\Migrator; |
3
|
|
|
|
4
|
|
|
use DirectoryIterator; |
5
|
|
|
use RuntimeException; |
6
|
|
|
use SplFileInfo; |
7
|
|
|
use Wandu\Database\Contracts\Migrator\MigrateAdapterInterface; |
8
|
|
|
use Wandu\Database\Contracts\Migrator\MigrationInterface; |
9
|
|
|
use Wandu\DI\ContainerInterface; |
10
|
|
|
|
11
|
|
|
class Migrator |
12
|
|
|
{ |
13
|
|
|
/** @var \Wandu\Database\Contracts\Migrator\MigrateAdapterInterface */ |
14
|
|
|
protected $adapter; |
15
|
|
|
|
16
|
|
|
/** @var \Wandu\Database\Migrator\Configuration */ |
17
|
|
|
protected $config; |
18
|
|
|
|
19
|
|
|
/** @var \Wandu\DI\ContainerInterface */ |
20
|
|
|
protected $container; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* @param \Wandu\Database\Contracts\Migrator\MigrateAdapterInterface $adapter |
24
|
|
|
* @param \Wandu\Database\Migrator\Configuration $config |
25
|
|
|
* @param \Wandu\DI\ContainerInterface $container |
26
|
|
|
*/ |
27
|
|
|
public function __construct(MigrateAdapterInterface $adapter, Configuration $config, ContainerInterface $container) |
28
|
|
|
{ |
29
|
|
|
$this->adapter = $adapter; |
30
|
|
|
$this->config = $config; |
31
|
|
|
$this->container = $container; |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @return array|\Wandu\Database\Migrator\MigrationContainer[] |
36
|
|
|
*/ |
37
|
|
|
public function migrations() |
38
|
|
|
{ |
39
|
|
|
$migrations = []; |
40
|
|
|
foreach ($this->getAllMigrationFiles() as $file) { |
41
|
|
|
$migrations[] = new MigrationContainer($file, $this->adapter, $this->container); |
42
|
|
|
} |
43
|
|
|
return $migrations; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @param string $migrationId |
48
|
|
|
* @return \Wandu\Database\Migrator\MigrationContainer |
49
|
|
|
*/ |
50
|
|
|
public function migration($migrationId) |
51
|
|
|
{ |
52
|
|
|
foreach ($this->getAllMigrationFiles() as $file) { |
53
|
|
|
if (strpos($file, $migrationId . '_') !== false) { |
54
|
|
|
return new MigrationContainer($file, $this->adapter, $this->container); |
55
|
|
|
} |
56
|
|
|
} |
57
|
|
|
throw new RuntimeException("there is no migration id \"{$migrationId}\"."); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* @param string $migrationId |
62
|
|
|
*/ |
63
|
|
|
public function up($migrationId) |
64
|
|
|
{ |
65
|
|
|
if (!preg_match('/^\d{6}_\d{6}$/', $migrationId)) { |
66
|
|
|
throw new RuntimeException("invalid migration id. it must be like 000000_000000."); |
67
|
|
|
} |
68
|
|
|
$version = $this->adapter->version($migrationId); |
69
|
|
|
if ($version) { |
|
|
|
|
70
|
|
|
throw new RuntimeException("this {$migrationId} is already applied."); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
$this->migration($migrationId)->up(); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* @param string $migrationId |
78
|
|
|
*/ |
79
|
|
|
public function down($migrationId) |
80
|
|
|
{ |
81
|
|
|
if (!preg_match('/^\d{6}_\d{6}$/', $migrationId)) { |
82
|
|
|
throw new RuntimeException("invalid migration id. it must be like 000000_000000."); |
83
|
|
|
} |
84
|
|
|
$version = $this->adapter->version($migrationId); |
85
|
|
|
if (!$version) { |
|
|
|
|
86
|
|
|
throw new RuntimeException("this {$migrationId} is not already applied."); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
$this->migration($migrationId)->down(); |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* @return array|\Wandu\Database\Migrator\MigrationContainer[] |
94
|
|
|
*/ |
95
|
|
|
public function migrate() |
96
|
|
|
{ |
97
|
|
|
$migratedMigrations = []; |
98
|
|
|
$migrations = $this->migrations(); |
99
|
|
|
foreach ($migrations as $migration) { |
100
|
|
|
if (!$this->adapter->version($migration->getId())) { |
101
|
|
|
$migration->up(); |
102
|
|
|
$migratedMigrations[] = $migration; |
103
|
|
|
} |
104
|
|
|
} |
105
|
|
|
return $migratedMigrations; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* @return array |
110
|
|
|
*/ |
111
|
|
|
protected function getAllMigrationFiles() |
112
|
|
|
{ |
113
|
|
|
$files = []; |
114
|
|
|
foreach (new DirectoryIterator($this->config->getPath()) as $file) { |
115
|
|
|
if ($file->isDot() || $file->isDir() || $file->getFilename()[0] === '.') continue; |
116
|
|
|
$files[] = $file->getFileInfo(); |
117
|
|
|
} |
118
|
|
|
usort($files, function (SplFileInfo $file, SplFileInfo $nextFile) { |
119
|
|
|
if ($file->getFilename() > $nextFile->getFilename()) { |
120
|
|
|
return 1; |
121
|
|
|
} |
122
|
|
|
return $file->getFilename() < $nextFile->getFilename() ? -1 : 0; |
123
|
|
|
}); |
124
|
|
|
return $files; |
125
|
|
|
} |
126
|
|
|
} |
127
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.