Completed
Push — master ( 2bd329...4a0c8e )
by Gaetano
18:18 queued 15:28
created

Migration::loadMigrationsByStatus()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 3
crap 1
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\StorageHandler\Database;
4
5
use Kaliop\eZMigrationBundle\API\StorageHandlerInterface;
6
use Kaliop\eZMigrationBundle\API\Collection\MigrationCollection;
7
use eZ\Publish\Core\Persistence\Database\DatabaseHandler;
8
use Doctrine\DBAL\Schema\Schema;
9
use eZ\Publish\Core\Persistence\Database\SelectQuery;
10
use Kaliop\eZMigrationBundle\API\Value\Migration as APIMigration;
11
use Kaliop\eZMigrationBundle\API\Value\MigrationDefinition;
12
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
13
14
/**
15
 * Database-backed storage for info on executed migrations
16
 *
17
 * @todo replace all usage of the ezcdb api with the doctrine dbal one, so that we only depend on one
18
 */
19
class Migration extends TableStorage implements StorageHandlerInterface
20
{
21
    protected $fieldList = 'migration, md5, path, execution_date, status, execution_error';
22
23
    /**
24
     * @param DatabaseHandler $dbHandler
25
     * @param string $tableName
26
     */
27 72
    public function __construct(DatabaseHandler $dbHandler, $tableName = 'kaliop_migrations')
28
    {
29 72
        parent::__construct($dbHandler, $tableName);
30 72
    }
31
32
    /**
33
     * @param int $limit
34
     * @param int $offset
35
     * @return MigrationCollection
36
     */
37 71
    public function loadMigrations($limit = null, $offset = null)
38
    {
39 71
        return $this->loadMigrationsInner(null, $limit, $offset);
40
    }
41
42
    /**
43
     * @param int $status
44
     * @param int $limit
45
     * @param int $offset
46
     * @return MigrationCollection
47
     */
48 1
    public function loadMigrationsByStatus($status, $limit = null, $offset = null)
49
    {
50 1
        return $this->loadMigrationsInner($status, $limit, $offset);
51
    }
52
53
    /**
54
     * @param int $status
55
     * @param int $limit
56
     * @param int $offset
57
     * @return MigrationCollection
58
     */
59 71
    protected function loadMigrationsInner($status = null, $limit = null, $offset = null)
60
    {
61 71
        $this->createTableIfNeeded();
62
63
        /** @var \eZ\Publish\Core\Persistence\Database\SelectQuery $q */
64 71
        $q = $this->dbHandler->createSelectQuery();
65 71
        $q->select($this->fieldList)
0 ignored issues
show
Unused Code introduced by
The call to SelectQuery::select() has too many arguments starting with $this->fieldList.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
66 71
            ->from($this->tableName)
0 ignored issues
show
Unused Code introduced by
The call to SelectQuery::from() has too many arguments starting with $this->tableName.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
67 71
            ->orderBy('migration', SelectQuery::ASC);
68 71
        if ($status !== null) {
69 1
            $q->where($q->expr->eq('status', $q->bindValue($status)));
0 ignored issues
show
Bug introduced by
Accessing expr on the interface eZ\Publish\Core\Persistence\Database\SelectQuery suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Unused Code introduced by
The call to SelectQuery::where() has too many arguments starting with $q->expr->eq('status', $q->bindValue($status)).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
70
        }
71 71
        if ($limit > 0 || $offset > 0) {
72 1
            if ($limit <= 0) {
73
                $limit = null;
74
            }
75 1
            if ($offset == 0) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $offset of type integer|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
76 1
                $offset = null;
77
            }
78 1
            $q->limit($limit, $offset);
79
        }
80 71
        $stmt = $q->prepare();
81 71
        $stmt->execute();
82 71
        $results = $stmt->fetchAll();
83
84 71
        $migrations = array();
85 71
        foreach ($results as $result) {
86 40
            $migrations[$result['migration']] = $this->arrayToMigration($result);
87
        }
88
89 71
        return new MigrationCollection($migrations);
90
    }
91
92
    /**
93
     * @param string $migrationName
94
     * @return APIMigration|null
95
     */
96 41 View Code Duplication
    public function loadMigration($migrationName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
97
    {
98 41
        $this->createTableIfNeeded();
99
100
        /** @var \eZ\Publish\Core\Persistence\Database\SelectQuery $q */
101 41
        $q = $this->dbHandler->createSelectQuery();
102 41
        $q->select($this->fieldList)
0 ignored issues
show
Unused Code introduced by
The call to SelectQuery::select() has too many arguments starting with $this->fieldList.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
103 41
            ->from($this->tableName)
0 ignored issues
show
Unused Code introduced by
The call to SelectQuery::from() has too many arguments starting with $this->tableName.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
104 41
            ->where($q->expr->eq('migration', $q->bindValue($migrationName)));
0 ignored issues
show
Bug introduced by
Accessing expr on the interface eZ\Publish\Core\Persistence\Database\SelectQuery suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Unused Code introduced by
The call to SelectQuery::where() has too many arguments starting with $q->expr->eq('migration'...dValue($migrationName)).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
105 41
        $stmt = $q->prepare();
106 41
        $stmt->execute();
107 41
        $result = $stmt->fetch(\PDO::FETCH_ASSOC);
108
109 41
        if (is_array($result) && !empty($result)) {
110 40
            return $this->arrayToMigration($result);
111
        }
112
113 39
        return null;
114
    }
115
116
    /**
117
     * Creates and stores a new migration (leaving it in TODO status)
118
     * @param MigrationDefinition $migrationDefinition
119
     * @return APIMigration
120
     * @throws \Exception If the migration exists already (we rely on the PK for that)
121
     */
122 40
    public function addMigration(MigrationDefinition $migrationDefinition)
123
    {
124 40
        $this->createTableIfNeeded();
125
126 40
        $conn = $this->getConnection();
127
128 40
        $migration = new APIMigration(
129 40
            $migrationDefinition->name,
130 40
            md5($migrationDefinition->rawDefinition),
131 40
            $migrationDefinition->path,
132 40
            null,
133 40
            APIMigration::STATUS_TODO
134
        );
135
        try {
136 40
            $conn->insert($this->tableName, $this->migrationToArray($migration));
137
        } catch (UniqueConstraintViolationException $e) {
138
            throw new \Exception("Migration '{$migrationDefinition->name}' already exists");
139
        }
140
141 40
        return $migration;
142
    }
143
144
    /**
145
     * Starts a migration, given its definition: stores its status in the db, returns the Migration object
146
     *
147
     * @param MigrationDefinition $migrationDefinition
148
     * @return APIMigration
149
     * @throws \Exception if migration was already executing or already done
150
     * @todo add a parameter to allow re-execution of already-done migrations
151
     */
152 32
    public function startMigration(MigrationDefinition $migrationDefinition)
153
    {
154 32
        return $this->createMigration($migrationDefinition, APIMigration::STATUS_STARTED, 'started');
155
    }
156
157
    /**
158
     * Stops a migration by storing it in the db. Migration status can not be 'started'
159
     *
160
     * NB: if this call happens within another DB transaction which has already been flagged for rollback, the result
161
     * will be that a RuntimeException is thrown, as Doctrine does not allow to call commit() after rollback().
162
     * One way to fix the problem would be not to use a transaction and select-for-update here, but since that is the
163
     * best way to insure atomic updates, I am loath to remove it.
164
     * A known workaround is to call the Doctrine Connection method setNestTransactionsWithSavepoints(true); this can
165
     * be achieved as simply as setting the parameter 'use_savepoints' in the doctrine connection configuration.
166
     *
167
     * @param APIMigration $migration
168
     * @param bool $force When true, the migration will be updated even if it was not in 'started' status
169
     * @throws \Exception If the migration was not started (unless $force=true)
170
     */
171 32
    public function endMigration(APIMigration $migration, $force = false)
172
    {
173 32
        if ($migration->status == APIMigration::STATUS_STARTED) {
174
            throw new \Exception($this->getEntityName($migration)." '{$migration->name}' can not be ended as its status is 'started'...");
175
        }
176
177 32
        $this->createTableIfNeeded();
178
179
        // select for update
180
181
        // annoyingly enough, neither Doctrine nor EZP provide built in support for 'FOR UPDATE' in their query builders...
182
        // at least the doctrine one allows us to still use parameter binding when we add our sql particle
183 32
        $conn = $this->getConnection();
184
185 32
        $qb = $conn->createQueryBuilder();
186 32
        $qb->select('*')
187 32
            ->from($this->tableName, 'm')
188 32
            ->where('migration = ?');
189 32
        $sql = $qb->getSQL() . ' FOR UPDATE';
190
191 32
        $conn->beginTransaction();
192
193 32
        $stmt = $conn->executeQuery($sql, array($migration->name));
194 32
        $existingMigrationData = $stmt->fetch(\PDO::FETCH_ASSOC);
195
196
        // fail if it was not executing
197
198 32 View Code Duplication
        if (!is_array($existingMigrationData)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
199
            // commit to release the lock
200
            $conn->commit();
201
            throw new \Exception($this->getEntityName($migration)." '{$migration->name}' can not be ended as it is not found");
202
        }
203
204 32 View Code Duplication
        if (($existingMigrationData['status'] != APIMigration::STATUS_STARTED) && !$force) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
205
            // commit to release the lock
206
            $conn->commit();
207
            throw new \Exception($this->getEntityName($migration)." '{$migration->name}' can not be ended as it is not executing");
208
        }
209
210 32
        $conn->update(
211 32
            $this->tableName,
212
            array(
213 32
                'status' => $migration->status,
214
                /// @todo use mb_substr (if all dbs we support count col length not in bytes but in chars...)
215 32
                'execution_error' => substr($migration->executionError, 0, 4000),
216 32
                'execution_date' => $migration->executionDate
217
            ),
218 32
            array('migration' => $migration->name)
219
        );
220
221 32
        $conn->commit();
222 32
    }
223
224
    /**
225
     * Removes a Migration from the table - regardless of its state!
226
     *
227
     * @param APIMigration $migration
228
     */
229 38
    public function deleteMigration(APIMigration $migration)
230
    {
231 38
        $this->createTableIfNeeded();
232 38
        $conn = $this->getConnection();
233 38
        $conn->delete($this->tableName, array('migration' => $migration->name));
234 38
    }
235
236
    /**
237
     * Skips a migration by storing it in the db. Migration status can not be 'started'
238
     *
239
     * @param MigrationDefinition $migrationDefinition
240
     * @return APIMigration
241
     * @throws \Exception If the migration was already executed or executing
242
     */
243
    public function skipMigration(MigrationDefinition $migrationDefinition)
244
    {
245
        return $this->createMigration($migrationDefinition, APIMigration::STATUS_SKIPPED, 'skipped');
246
    }
247
248
    /**
249
     * @param MigrationDefinition $migrationDefinition
250
     * @param int $status
251
     * @param string $action
252
     * @return APIMigration
253
     * @throws \Exception
254
     */
255 32
    protected function createMigration(MigrationDefinition $migrationDefinition, $status, $action)
256
    {
257 32
        $this->createTableIfNeeded();
258
259
        // select for update
260
261
        // annoyingly enough, neither Doctrine nor EZP provide built in support for 'FOR UPDATE' in their query builders...
262
        // at least the doctrine one allows us to still use parameter binding when we add our sql particle
263 32
        $conn = $this->getConnection();
264
265 32
        $qb = $conn->createQueryBuilder();
266 32
        $qb->select('*')
267 32
            ->from($this->tableName, 'm')
268 32
            ->where('migration = ?');
269 32
        $sql = $qb->getSQL() . ' FOR UPDATE';
270
271 32
        $conn->beginTransaction();
272
273 32
        $stmt = $conn->executeQuery($sql, array($migrationDefinition->name));
274 32
        $existingMigrationData = $stmt->fetch(\PDO::FETCH_ASSOC);
275
276 32
        if (is_array($existingMigrationData)) {
277
            // migration exists
278
279
            // fail if it was already executing or already done
280 30 View Code Duplication
            if ($existingMigrationData['status'] == APIMigration::STATUS_STARTED) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
281
                // commit to release the lock
282
                $conn->commit();
283
                throw new \Exception("Migration '{$migrationDefinition->name}' can not be $action as it is already executing");
284
            }
285 30 View Code Duplication
            if ($existingMigrationData['status'] == APIMigration::STATUS_DONE) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
286
                // commit to release the lock
287
                $conn->commit();
288
                throw new \Exception("Migration '{$migrationDefinition->name}' can not be $action as it was already executed");
289
            }
290 30 View Code Duplication
            if ($existingMigrationData['status'] == APIMigration::STATUS_SKIPPED) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
291
                // commit to release the lock
292
                $conn->commit();
293
                throw new \Exception("Migration '{$migrationDefinition->name}' can not be $action as it was already skipped");
294
            }
295
296
            // do not set migration start date if we are skipping it
297 30
            $migration = new APIMigration(
298 30
                $migrationDefinition->name,
299 30
                md5($migrationDefinition->rawDefinition),
300 30
                $migrationDefinition->path,
301 30
                ($status == APIMigration::STATUS_SKIPPED ? null : time()),
302 30
                $status
303
            );
304 30
            $conn->update(
305 30
                $this->tableName,
306
                array(
307 30
                    'execution_date' => $migration->executionDate,
308 30
                    'status' => $status,
309
                    'execution_error' => null
310
                ),
311 30
                array('migration' => $migrationDefinition->name)
312
            );
313 30
            $conn->commit();
314
315
        } else {
316
            // migration did not exist. Create it!
317
318
            // commit immediately, to release the lock and avoid deadlocks
319 2
            $conn->commit();
320
321 2
            $migration = new APIMigration(
322 2
                $migrationDefinition->name,
323 2
                md5($migrationDefinition->rawDefinition),
324 2
                $migrationDefinition->path,
325 2
                ($status == APIMigration::STATUS_SKIPPED ? null : time()),
326 2
                $status
327
            );
328 2
            $conn->insert($this->tableName, $this->migrationToArray($migration));
329
        }
330
331 32
        return $migration;
332
    }
333
334
    public function resumeMigration(APIMigration $migration)
335
    {
336
        $this->createTableIfNeeded();
337
338
        // select for update
339
340
        // annoyingly enough, neither Doctrine nor EZP provide built in support for 'FOR UPDATE' in their query builders...
341
        // at least the doctrine one allows us to still use parameter binding when we add our sql particle
342
        $conn = $this->getConnection();
343
344
        $qb = $conn->createQueryBuilder();
345
        $qb->select('*')
346
            ->from($this->tableName, 'm')
347
            ->where('migration = ?');
348
        $sql = $qb->getSQL() . ' FOR UPDATE';
349
350
        $conn->beginTransaction();
351
352
        $stmt = $conn->executeQuery($sql, array($migration->name));
353
        $existingMigrationData = $stmt->fetch(\PDO::FETCH_ASSOC);
354
355 View Code Duplication
        if (!is_array($existingMigrationData)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
356
            // commit immediately, to release the lock and avoid deadlocks
357
            $conn->commit();
358
            throw new \Exception($this->getEntityName($migration)." '{$migration->name}' can not be resumed as it is not found");
359
        }
360
361
        // migration exists
362
363
        // fail if it was not suspended
364 View Code Duplication
        if ($existingMigrationData['status'] != APIMigration::STATUS_SUSPENDED) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
365
            // commit to release the lock
366
            $conn->commit();
367
            throw new \Exception($this->getEntityName($migration)." '{$migration->name}' can not be resumed as it is not suspended");
368
        }
369
370
        $migration = new APIMigration(
371
            $migration->name,
372
            $migration->md5,
373
            $migration->path,
374
            time(),
375
            APIMigration::STATUS_STARTED
376
        );
377
378
        $conn->update(
379
            $this->tableName,
380
            array(
381
                'execution_date' => $migration->executionDate,
382
                'status' => APIMigration::STATUS_STARTED,
383
                'execution_error' => null
384
            ),
385
            array('migration' => $migration->name)
386
        );
387
        $conn->commit();
388
389
        return $migration;
390
    }
391
392
    /**
393
     * Removes all migration from storage (regardless of their status)
394
     */
395
    public function deleteMigrations()
396
    {
397
        $this->drop();
398
    }
399
400 1
    public function createTable()
401
    {
402
        /** @var \Doctrine\DBAL\Schema\AbstractSchemaManager $sm */
403 1
        $sm = $this->getConnection()->getSchemaManager();
404 1
        $dbPlatform = $sm->getDatabasePlatform();
405
406 1
        $schema = new Schema();
407
408 1
        $t = $schema->createTable($this->tableName);
409 1
        $t->addColumn('migration', 'string', array('length' => 255));
410 1
        $t->addColumn('path', 'string', array('length' => 4000));
411 1
        $t->addColumn('md5', 'string', array('length' => 32));
412 1
        $t->addColumn('execution_date', 'integer', array('notnull' => false));
413 1
        $t->addColumn('status', 'integer', array('default ' => APIMigration::STATUS_TODO));
414 1
        $t->addColumn('execution_error', 'string', array('length' => 4000, 'notnull' => false));
415 1
        $t->setPrimaryKey(array('migration'));
416
        // in case users want to look up migrations by their full path
417
        // NB: disabled for the moment, as it causes problems on some versions of mysql which limit index length to 767 bytes,
418
        // and 767 bytes can be either 255 chars or 191 chars depending on charset utf8 or utf8mb4...
419
        //$t->addIndex(array('path'));
0 ignored issues
show
Unused Code Comprehensibility introduced by
90% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
420
421 1
        foreach ($schema->toSql($dbPlatform) as $sql) {
422 1
            $this->dbHandler->exec($sql);
423
        }
424 1
    }
425
426 41
    protected function migrationToArray(APIMigration $migration)
427
    {
428
        return array(
429 41
            'migration' => $migration->name,
430 41
            'md5' => $migration->md5,
431 41
            'path' => $migration->path,
432 41
            'execution_date' => $migration->executionDate,
433 41
            'status' => $migration->status,
434 41
            'execution_error' => $migration->executionError
435
        );
436
    }
437
438 41
    protected function arrayToMigration(array $data)
439
    {
440 41
        return new APIMigration(
441 41
            $data['migration'],
442 41
            $data['md5'],
443 41
            $data['path'],
444 41
            $data['execution_date'],
445 41
            $data['status'],
446 41
            $data['execution_error']
447
        );
448
    }
449
450
    protected function getEntityName($migration)
451
    {
452
        return end(explode('\\', get_class($migration)));
0 ignored issues
show
Bug introduced by
explode('\\', get_class($migration)) cannot be passed to end() as the parameter $array expects a reference.
Loading history...
453
    }
454
}
455