Issues (65)

src/Migrations/Migrator.php (1 issue)

1
<?php
2
3
namespace Rawilk\LaravelModules\Migrations;
4
5
use Illuminate\Contracts\Foundation\Application;
6
use Illuminate\Database\Query\Builder;
7
use Illuminate\Support\Collection;
8
use Illuminate\Support\Str;
9
use Rawilk\LaravelModules\Module;
10
use Rawilk\LaravelModules\Support\Config\GenerateConfigReader;
11
12
class Migrator
13
{
14
    /** @var string */
15
    protected $database = '';
16
17
    /** @var \Illuminate\Contracts\Foundation\Application */
18
    protected $laravel;
19
20
    /** @var \Rawilk\LaravelModules\Module */
21
    protected $module;
22
23
    /**
24
     * @param \Rawilk\LaravelModules\Module $module
25
     * @param \Illuminate\Contracts\Foundation\Application $app
26
     */
27
    public function __construct(Module $module, Application $app)
28
    {
29
        $this->module = $module;
30
        $this->laravel = $app;
31
    }
32
33
    public function down(string $migration): void
34
    {
35
        $this->resolve($migration)->down();
36
    }
37
38
    public function find(string $migration): object
39
    {
40
        return $this->table()->whereMigration($migration);
41
    }
42
43
    public function getMigrations(bool $reverse = false): array
44
    {
45
        $files = $this->laravel['files']->glob($this->getPath() . '/*_*.php');
46
47
        // Once we have the array of files in the directory we will just remove the
48
        // extension and take the basename of the file which is all we need when
49
        // finding the migrations that haven't been run against the database.
50
        if ($files === false) {
51
            return [];
52
        }
53
54
        $files = array_map(static function ($file) {
55
            return str_replace('.php', '', basename($file));
56
        }, $files);
57
58
        // Once we have all of the formatted file names we will sort them and since
59
        // they all start with a timestamp this should give us the migrations in
60
        // the order they were actually created by the application developers.
61
        sort($files);
62
63
        if ($reverse) {
64
            return array_reverse($files);
65
        }
66
67
        return $files;
68
    }
69
70
    public function getLast(?array $migrations): Collection
71
    {
72
        $rows = $this->table()
73
            ->where('batch', $this->getLastBatchNumber($migrations))
74
            ->whereIn('migration', $migrations)
75
            ->orderBy('migration', 'desc')
76
            ->get();
77
78
        return collect($rows)->map(static function ($row) {
79
            return (array) $row;
80
        })->pluck('migration');
81
    }
82
83
    public function getLastBatchNumber(?array $migrations = null): int
84
    {
85
        $table = $this->table();
86
87
        if (is_array($migrations)) {
88
            $table = $table->whereIn('migration', $migrations);
89
        }
90
91
        return $table->max('batch');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $table->max('batch') could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
92
    }
93
94
    public function getModule(): Module
95
    {
96
        return $this->module;
97
    }
98
99
    public function getNextBatchNumber(): int
100
    {
101
        return $this->getLastBatchNumber() + 1;
102
    }
103
104
    public function getPath(): string
105
    {
106
        $config = $this->module->get('migration');
107
108
        $migrationPath = GenerateConfigReader::read('migration');
109
        $path = (is_array($config) && array_key_exists('path', $config))
110
            ? $config['path']
111
            : $migrationPath->getPath();
112
113
        return $this->module->getExtraPath($path);
114
    }
115
116
    public function getRan(): Collection
117
    {
118
        return $this->table()->pluck('migration');
119
    }
120
121
    public function log(string $migration): bool
122
    {
123
        return $this->table()->insert([
124
            'migration' => $migration,
125
            'batch'     => $this->getNextBatchNumber()
126
        ]);
127
    }
128
129
    public function requireFiles(array $files): void
130
    {
131
        $path = $this->getPath();
132
133
        foreach ($files as $file) {
134
            $this->laravel['files']->requireOnce("{$path}/{$file}.php");
135
        }
136
    }
137
138
    public function reset(): array
139
    {
140
        $migrations = $this->getMigrations(true);
141
142
        $this->requireFiles($migrations);
143
144
        $migrated = [];
145
146
        foreach ($migrations as $migration) {
147
            $data = $this->find($migration);
148
149
            if ($data->count()) {
150
                $migrated[] = $migration;
151
152
                $this->down($migration);
153
154
                $data->delete();
155
            }
156
        }
157
158
        return $migrated;
159
    }
160
161
    public function resolve(string $file): object
162
    {
163
        $file = implode('_', array_slice(explode('_', $file), 4));
164
165
        $class = Str::studly($file);
166
167
        return new $class;
168
    }
169
170
    public function rollback(): array
171
    {
172
        $migrations = $this->getLast($this->getMigrations(true));
173
174
        $this->requireFiles($migrations->toArray());
175
176
        $migrated = [];
177
178
        foreach ($migrations as $migration) {
179
            $data = $this->find($migration);
180
181
            if ($data->count()) {
182
                $migrated[] = $migration;
183
184
                $this->down($migration);
185
186
                $data->delete();
187
            }
188
        }
189
190
        return $migrated;
191
    }
192
193
    public function setDatabase($database): self
194
    {
195
        if (is_string($database) && $database) {
196
            $this->database = $database;
197
        }
198
199
        return $this;
200
    }
201
202
    public function table(): Builder
203
    {
204
        return $this->laravel['db']->connection($this->database ?: null)->table(config('database.migrations'));
205
    }
206
207
    public function up(string $migration): void
208
    {
209
        $this->resolve($migration)->up();
210
    }
211
}
212