Completed
Push — master ( a52247...91a49a )
by Zach
02:12
created

Migrator::log()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Yarak\Migrations;
4
5
use Yarak\Helpers\Str;
6
use Yarak\Config\Config;
7
use Yarak\Helpers\Paths;
8
use Yarak\DB\ConnectionResolver;
9
10
class Migrator
11
{
12
    use Paths;
13
14
    /**
15
     * Yarak config.
16
     *
17
     * @var Config
18
     */
19
    protected $config;
20
21
    /**
22
     * Database connection resolver.
23
     *
24
     * @var ConnectionResolver
25
     */
26
    protected $resolver;
27
28
    /**
29
     * Repository for logging migration activity.
30
     *
31
     * @var MigrationRepository
32
     */
33
    protected $repository;
34
35
    /**
36
     * The active database connection.
37
     *
38
     * @var Phalcon\Db\Adapter\Pdo
39
     */
40
    protected $connection = null;
41
42
    /**
43
     * Log of info/error messages.
44
     *
45
     * @var array
46
     */
47
    protected $log = [];
48
49
    /**
50
     * Construct.
51
     *
52
     * @param Config                       $config
53
     * @param ConnectionResolver           $resolver
54
     * @param MigrationRepositoryInterface $repository
55
     */
56
    public function __construct(
57
        Config $config,
58
        ConnectionResolver $resolver,
59
        MigrationRepository $repository
60
    ) {
61
        $this->config = $config;
62
        $this->resolver = $resolver;
63
        $this->repository = $repository;
64
    }
65
66
    /**
67
     * Run migrations.
68
     *
69
     * @return array
70
     */
71
    public function run()
72
    {
73
        $this->setUp();
74
75
        $pendingMigrations = $this->getPendingMigrations();
76
77
        return $this->runPending($pendingMigrations);
78
    }
79
80
    /**
81
     * Get all migration filenames that have not been run.
82
     *
83
     * @return array
84
     */
85
    protected function getPendingMigrations()
86
    {
87
        return array_diff(
88
            $this->getMigrationFiles(),
89
            $this->repository->getRanMigrations()
90
        );
91
    }
92
93
    /**
94
     * Get array of migration file names from directory listed in config.
95
     *
96
     * @return array
97
     */
98
    protected function getMigrationFiles()
99
    {
100
        $files = scandir($this->config->getMigrationDirectory());
101
102
        $files = array_filter($files, function ($file) {
103
            return strpos($file, '.php') !== false;
104
        });
105
106
        $files = array_map(function ($file) {
107
            return str_replace('.php', '', $file);
108
        }, $files);
109
110
        return array_values($files);
111
    }
112
113
    /**
114
     * Run pending migrations.
115
     *
116
     * @param array $migrations
117
     *
118
     * @return array
119
     */
120
    protected function runPending(array $migrations)
121
    {
122
        if (count($migrations) === 0) {
123
            $this->log('<info>No pending migrations to run.</info>');
124
125
            return [];
126
        }
127
128
        $batch = $this->repository->getNextBatchNumber();
129
130
        $this->connection->begin();
131
132
        foreach ($migrations as $migration) {
133
            $this->runUp($migration, $batch);
134
        }
135
136
        $this->connection->commit();
137
138
        return $migrations;
139
    }
140
141
    /**
142
     * Run the migration.
143
     *
144
     * @param string $migration
145
     * @param int    $batch
146
     */
147 View Code Duplication
    protected function runUp($migration, $batch)
148
    {
149
        $migrationClass = $this->resolveMigrationClass($migration);
150
151
        try {
152
            $migrationClass->up($this->connection);
153
        } catch (\Exception $e) {
154
            return $this->log("<error>{$e->getMessage()}</error>");
155
        }
156
157
        $this->log("<info>Migrated {$migration}.</info>");
158
159
        $this->repository->insertRecord($migration, $batch);
160
    }
161
162
    /**
163
     * Resolve the migration class from the file name.
164
     *
165
     * @param string $migration
166
     *
167
     * @return Yarak\Migrations\Migration
168
     */
169
    public function resolveMigrationClass($migration)
170
    {
171
        require_once $this->config->getMigrationDirectory().$migration.'.php';
172
173
        $class = Str::studly(implode('_', array_slice(explode('_', $migration), 4)));
174
175
        return new $class();
176
    }
177
178
    /**
179
     * Rollback migrations.
180
     *
181
     * @param int $steps
182
     *
183
     * @return array
184
     */
185
    public function rollback($steps = 1)
186
    {
187
        $this->setUp();
188
189
        $toRollback = $this->repository->getRanMigrations(null, $steps);
190
191
        return $this->runRollback($toRollback);
192
    }
193
194
    /**
195
     * Rollback given migrations.
196
     *
197
     * @param array $migrations
198
     *
199
     * @return array
200
     */
201
    protected function runRollback(array $migrations)
202
    {
203
        if (count($migrations) === 0) {
204
            $this->log('<info>Nothing to rollback.</info>');
205
206
            return [];
207
        }
208
209
        $this->connection->begin();
210
211
        foreach (array_reverse($migrations) as $migration) {
212
            $this->runDown($migration);
213
        }
214
215
        $this->connection->commit();
216
217
        return $migrations;
218
    }
219
220
    /**
221
     * Rollback the migration.
222
     *
223
     * @param string $migration
224
     */
225 View Code Duplication
    protected function runDown($migration)
226
    {
227
        $migrationClass = $this->resolveMigrationClass($migration);
228
229
        try {
230
            $migrationClass->down($this->connection);
231
        } catch (\Exception $e) {
232
            return $this->log("<error>{$e->getMessage()}</error>");
233
        }
234
235
        $this->log("<info>Rolled back {$migration}.</info>");
236
237
        $this->repository->deleteRecord($migration);
238
    }
239
240
    /**
241
     * Reset the database by rolling back all migrations.
242
     *
243
     * @return array
244
     */
245
    public function reset()
246
    {
247
        $this->setUp();
248
249
        $toRollback = $this->repository->getRanMigrations();
250
251
        return $this->runRollback($toRollback);
252
    }
253
254
    /**
255
     * Reset the database and run all migrations.
256
     *
257
     * @return array
258
     */
259
    public function refresh()
260
    {
261
        $this->setUp();
262
263
        $toRollback = $this->repository->getRanMigrations();
264
265
        $this->runRollback($toRollback);
266
267
        $pendingMigrations = $this->getPendingMigrations();
268
269
        return $this->runPending($pendingMigrations);
270
    }
271
272
    /**
273
     * Perform setup procedures for migrations.
274
     */
275
    protected function setUp()
276
    {
277
        if (!$this->connection) {
278
            $this->setConnection();
279
        }
280
281
        $this->createMigrationsRepository();
282
283
        $this->makeDirectoryStructure($this->config->getAllDatabaseDirectories());
284
    }
285
286
    /**
287
     * Set connection to database on object.
288
     *
289
     * @return Pdo
290
     */
291
    public function setConnection()
292
    {
293
        $dbConfig = $this->config->get('database');
294
295
        $this->connection = $this->resolver->getConnection($dbConfig);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->resolver->getConnection($dbConfig) of type object<Yarak\DB\Phalcon\Db\Adapter\Pdo> is incompatible with the declared type object<Yarak\Migrations\Phalcon\Db\Adapter\Pdo> of property $connection.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
296
297
        $this->repository->setConnection($this->connection);
298
299
        return $this;
300
    }
301
302
    /**
303
     * Return the connection.
304
     *
305
     * @return Phalcon\Db\Adapter\Pdo
306
     */
307
    public function getConnection()
308
    {
309
        return $this->connection;
310
    }
311
312
    /**
313
     * Create the migrations table if it doesn't exist.
314
     */
315
    public function createMigrationsRepository()
316
    {
317
        if (!$this->repository->exists()) {
318
            $this->repository->create();
319
        }
320
321
        return $this;
322
    }
323
324
    /**
325
     * Log a message.
326
     *
327
     * @param string $message
328
     */
329
    protected function log($message)
330
    {
331
        $this->log[] = $message;
332
    }
333
334
    /**
335
     * Return the object log.
336
     *
337
     * @return array
338
     */
339
    public function getLog()
340
    {
341
        return $this->log;
342
    }
343
}
344