1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Nwidart\Modules\Migrations; |
4
|
|
|
|
5
|
|
|
use \Laravel\Lumen\Application; |
6
|
|
|
use Illuminate\Support\Collection; |
7
|
|
|
use Illuminate\Support\Str; |
8
|
|
|
use Nwidart\Modules\Module; |
9
|
|
|
use Nwidart\Modules\Support\Config\GenerateConfigReader; |
10
|
|
|
|
11
|
|
View Code Duplication |
class LumenMigrator |
|
|
|
|
12
|
|
|
{ |
13
|
|
|
/** |
14
|
|
|
* Module instance. |
15
|
|
|
* @var Module |
16
|
|
|
*/ |
17
|
|
|
protected $module; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Laravel Application instance. |
21
|
|
|
* |
22
|
|
|
* @var Application. |
23
|
|
|
*/ |
24
|
|
|
protected $laravel; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* The database connection to be used |
28
|
|
|
* |
29
|
|
|
* @var string |
30
|
|
|
*/ |
31
|
|
|
protected $database = ''; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Create new instance. |
35
|
|
|
* @param Module $module |
36
|
|
|
* @param Application $application |
37
|
|
|
*/ |
38
|
|
|
public function __construct(Module $module, Application $application) |
39
|
|
|
{ |
40
|
|
|
$this->module = $module; |
41
|
|
|
$this->laravel = $application; |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Set the database connection to be used |
46
|
|
|
* |
47
|
|
|
* @param $database |
48
|
|
|
* |
49
|
|
|
* @return $this |
50
|
|
|
*/ |
51
|
|
|
public function setDatabase($database) |
52
|
|
|
{ |
53
|
|
|
if (is_string($database) && $database) { |
54
|
|
|
$this->database = $database; |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
return $this; |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* @return Module |
62
|
|
|
*/ |
63
|
|
|
public function getModule() |
64
|
|
|
{ |
65
|
|
|
return $this->module; |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* Get migration path. |
70
|
|
|
* |
71
|
|
|
* @return string |
72
|
|
|
*/ |
73
|
|
|
public function getPath() |
74
|
|
|
{ |
75
|
|
|
$config = $this->module->get('migration'); |
76
|
|
|
|
77
|
|
|
$migrationPath = GenerateConfigReader::read('migration'); |
78
|
|
|
$path = (is_array($config) && array_key_exists('path', $config)) ? $config['path'] : $migrationPath->getPath(); |
79
|
|
|
|
80
|
|
|
return $this->module->getExtraPath($path); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* Get migration files. |
85
|
|
|
* |
86
|
|
|
* @param boolean $reverse |
87
|
|
|
* @return array |
88
|
|
|
*/ |
89
|
|
|
public function getMigrations($reverse = false) |
90
|
|
|
{ |
91
|
|
|
$files = $this->laravel['files']->glob($this->getPath() . '/*_*.php'); |
92
|
|
|
|
93
|
|
|
// Once we have the array of files in the directory we will just remove the |
94
|
|
|
// extension and take the basename of the file which is all we need when |
95
|
|
|
// finding the migrations that haven't been run against the databases. |
96
|
|
|
if ($files === false) { |
97
|
|
|
return []; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
$files = array_map(function ($file) { |
101
|
|
|
return str_replace('.php', '', basename($file)); |
102
|
|
|
}, $files); |
103
|
|
|
|
104
|
|
|
// Once we have all of the formatted file names we will sort them and since |
105
|
|
|
// they all start with a timestamp this should give us the migrations in |
106
|
|
|
// the order they were actually created by the application developers. |
107
|
|
|
sort($files); |
108
|
|
|
|
109
|
|
|
if ($reverse) { |
110
|
|
|
return array_reverse($files); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
return $files; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Rollback migration. |
118
|
|
|
* |
119
|
|
|
* @return array |
120
|
|
|
*/ |
121
|
|
|
public function rollback() |
122
|
|
|
{ |
123
|
|
|
$migrations = $this->getLast($this->getMigrations(true)); |
124
|
|
|
|
125
|
|
|
$this->requireFiles($migrations->toArray()); |
126
|
|
|
|
127
|
|
|
$migrated = []; |
128
|
|
|
|
129
|
|
|
foreach ($migrations as $migration) { |
130
|
|
|
$data = $this->find($migration); |
131
|
|
|
|
132
|
|
|
if ($data->count()) { |
133
|
|
|
$migrated[] = $migration; |
134
|
|
|
|
135
|
|
|
$this->down($migration); |
136
|
|
|
|
137
|
|
|
$data->delete(); |
138
|
|
|
} |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
return $migrated; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Reset migration. |
146
|
|
|
* |
147
|
|
|
* @return array |
148
|
|
|
*/ |
149
|
|
|
public function reset() |
150
|
|
|
{ |
151
|
|
|
$migrations = $this->getMigrations(true); |
152
|
|
|
|
153
|
|
|
$this->requireFiles($migrations); |
154
|
|
|
|
155
|
|
|
$migrated = []; |
156
|
|
|
|
157
|
|
|
foreach ($migrations as $migration) { |
158
|
|
|
$data = $this->find($migration); |
159
|
|
|
|
160
|
|
|
if ($data->count()) { |
161
|
|
|
$migrated[] = $migration; |
162
|
|
|
|
163
|
|
|
$this->down($migration); |
164
|
|
|
|
165
|
|
|
$data->delete(); |
166
|
|
|
} |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
return $migrated; |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
/** |
173
|
|
|
* Run down schema from the given migration name. |
174
|
|
|
* |
175
|
|
|
* @param string $migration |
176
|
|
|
*/ |
177
|
|
|
public function down($migration) |
178
|
|
|
{ |
179
|
|
|
$this->resolve($migration)->down(); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Run up schema from the given migration name. |
184
|
|
|
* |
185
|
|
|
* @param string $migration |
186
|
|
|
*/ |
187
|
|
|
public function up($migration) |
188
|
|
|
{ |
189
|
|
|
$this->resolve($migration)->up(); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* Resolve a migration instance from a file. |
194
|
|
|
* |
195
|
|
|
* @param string $file |
196
|
|
|
* |
197
|
|
|
* @return object |
198
|
|
|
*/ |
199
|
|
|
public function resolve($file) |
200
|
|
|
{ |
201
|
|
|
$file = implode('_', array_slice(explode('_', $file), 4)); |
202
|
|
|
|
203
|
|
|
$class = Str::studly($file); |
204
|
|
|
|
205
|
|
|
return new $class(); |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* Require in all the migration files in a given path. |
210
|
|
|
* |
211
|
|
|
* @param array $files |
212
|
|
|
*/ |
213
|
|
|
public function requireFiles(array $files) |
214
|
|
|
{ |
215
|
|
|
$path = $this->getPath(); |
216
|
|
|
foreach ($files as $file) { |
217
|
|
|
$this->laravel['files']->requireOnce($path . '/' . $file . '.php'); |
218
|
|
|
} |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
/** |
222
|
|
|
* Get table instance. |
223
|
|
|
* |
224
|
|
|
* @return \Illuminate\Database\Query\Builder |
225
|
|
|
*/ |
226
|
|
|
public function table() |
227
|
|
|
{ |
228
|
|
|
return $this->laravel['db']->connection($this->database ?: null)->table(config('database.migrations')); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* Find migration data from database by given migration name. |
233
|
|
|
* |
234
|
|
|
* @param string $migration |
235
|
|
|
* |
236
|
|
|
* @return object |
237
|
|
|
*/ |
238
|
|
|
public function find($migration) |
239
|
|
|
{ |
240
|
|
|
return $this->table()->whereMigration($migration); |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* Save new migration to database. |
245
|
|
|
* |
246
|
|
|
* @param string $migration |
247
|
|
|
* |
248
|
|
|
* @return mixed |
249
|
|
|
*/ |
250
|
|
|
public function log($migration) |
251
|
|
|
{ |
252
|
|
|
return $this->table()->insert([ |
253
|
|
|
'migration' => $migration, |
254
|
|
|
'batch' => $this->getNextBatchNumber(), |
255
|
|
|
]); |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* Get the next migration batch number. |
260
|
|
|
* |
261
|
|
|
* @return int |
262
|
|
|
*/ |
263
|
|
|
public function getNextBatchNumber() |
264
|
|
|
{ |
265
|
|
|
return $this->getLastBatchNumber() + 1; |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
/** |
269
|
|
|
* Get the last migration batch number. |
270
|
|
|
* |
271
|
|
|
* @param array|null $migrations |
272
|
|
|
* @return int |
273
|
|
|
*/ |
274
|
|
|
public function getLastBatchNumber($migrations = null) |
275
|
|
|
{ |
276
|
|
|
$table = $this->table(); |
277
|
|
|
|
278
|
|
|
if (is_array($migrations)) { |
279
|
|
|
$table = $table->whereIn('migration', $migrations); |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
return $table->max('batch'); |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* Get the last migration batch. |
287
|
|
|
* |
288
|
|
|
* @param array $migrations |
289
|
|
|
* |
290
|
|
|
* @return Collection |
291
|
|
|
*/ |
292
|
|
|
public function getLast($migrations) |
293
|
|
|
{ |
294
|
|
|
$query = $this->table() |
295
|
|
|
->where('batch', $this->getLastBatchNumber($migrations)) |
296
|
|
|
->whereIn('migration', $migrations); |
297
|
|
|
|
298
|
|
|
$result = $query->orderBy('migration', 'desc')->get(); |
299
|
|
|
|
300
|
|
|
return collect($result)->map(function ($item) { |
301
|
|
|
return (array) $item; |
302
|
|
|
})->pluck('migration'); |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
/** |
306
|
|
|
* Get the ran migrations. |
307
|
|
|
* |
308
|
|
|
* @return Collection |
309
|
|
|
*/ |
310
|
|
|
public function getRan() |
311
|
|
|
{ |
312
|
|
|
return $this->table()->pluck('migration'); |
313
|
|
|
} |
314
|
|
|
} |
315
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.