Completed
Push — master ( 5df0c5...b8286e )
by Mike
10:15
created

Configuration::generateVersionNumber()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
cc 2
eloc 3
nc 2
nop 1
crap 2
1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\DBAL\Migrations\Configuration;
21
22
use Doctrine\DBAL\Connection;
23
use Doctrine\DBAL\Migrations\Finder\MigrationDeepFinderInterface;
24
use Doctrine\DBAL\Migrations\MigrationException;
25
use Doctrine\DBAL\Migrations\OutputWriter;
26
use Doctrine\DBAL\Migrations\Version;
27
use Doctrine\DBAL\Migrations\Finder\MigrationFinderInterface;
28
use Doctrine\DBAL\Migrations\Finder\RecursiveRegexFinder;
29
use Doctrine\DBAL\Schema\Column;
30
use Doctrine\DBAL\Schema\Table;
31
use Doctrine\DBAL\Types\Type;
32
33
/**
34
 * Default Migration Configuration object used for configuring an instance of
35
 * the Migration class. Set the connection, version table name, register migration
36
 * classes/versions, etc.
37
 *
38
 * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
39
 * @link        www.doctrine-project.org
40
 * @since       2.0
41
 * @author      Jonathan H. Wage <[email protected]>
42
 */
43
class Configuration
44
{
45
    /**
46
     * Configure versions to be organized by year.
47
     */
48
    const VERSIONS_ORGANIZATION_BY_YEAR = 'year';
49
50
    /**
51
     * Configure versions to be organized by year and month.
52
     *
53
     * @var string
54
     */
55
    const VERSIONS_ORGANIZATION_BY_YEAR_AND_MONTH = 'year_and_month';
56
57
    /**
58
     * The date format for new version numbers
59
     */
60
    const VERSION_FORMAT = 'YmdHis';
61
62
    /**
63
     * Name of this set of migrations
64
     *
65
     * @var string
66
     */
67
    private $name;
68
69
    /**
70
     * Flag for whether or not the migration table has been created
71
     *
72
     * @var boolean
73
     */
74
    private $migrationTableCreated = false;
75
76
    /**
77
     * Connection instance to use for migrations
78
     *
79
     * @var Connection
80
     */
81
    private $connection;
82
83
    /**
84
     * OutputWriter instance for writing output during migrations
85
     *
86
     * @var OutputWriter
87
     */
88
    private $outputWriter;
89
90
    /**
91
     * The migration finder implementation -- used to load migrations from a
92
     * directory.
93
     *
94
     * @var MigrationFinderInterface
95
     */
96
    private $migrationFinder;
97
98
    /**
99
     * The migration table name to track versions in
100
     *
101
     * @var string
102
     */
103
    private $migrationsTableName = 'doctrine_migration_versions';
104
105
    /**
106
     * The migration column name to track versions in
107
     *
108
     * @var string
109
     */
110
    private $migrationsColumnName = 'version';
111
112
    /**
113
     * The path to a directory where new migration classes will be written
114
     *
115
     * @var string
116
     */
117
    private $migrationsDirectory;
118
119
    /**
120
     * Namespace the migration classes live in
121
     *
122
     * @var string
123
     */
124
    private $migrationsNamespace;
125
126
    /**
127
     * Array of the registered migrations
128
     *
129
     * @var Version[]
130
     */
131
    private $migrations = [];
132
133
    /**
134
     * Versions are organized by year.
135
     *
136
     * @var boolean
137
     */
138
    private $migrationsAreOrganizedByYear = false;
139
140
    /**
141
     * Versions are organized by year and month.
142
     *
143
     * @var boolean
144
     */
145
    private $migrationsAreOrganizedByYearAndMonth = false;
146
147
    /**
148
     * Construct a migration configuration object.
149
     *
150
     * @param Connection               $connection   A Connection instance
151
     * @param OutputWriter             $outputWriter A OutputWriter instance
152
     * @param MigrationFinderInterface $finder       Migration files finder
153
     */
154 261
    public function __construct(Connection $connection, OutputWriter $outputWriter = null, MigrationFinderInterface $finder = null)
155
    {
156 261
        $this->connection = $connection;
157 261
        if ($outputWriter === null) {
158 223
            $outputWriter = new OutputWriter();
159 223
        }
160 261
        $this->outputWriter = $outputWriter;
161 261
        if ($finder === null) {
162 257
            $finder = new RecursiveRegexFinder();
163 257
        }
164 261
        $this->migrationFinder = $finder;
165 261
    }
166
167
    /**
168
     * @return bool
169
     */
170 22
    public function areMigrationsOrganizedByYear()
171
    {
172 22
        return $this->migrationsAreOrganizedByYear;
173
    }
174
175
    /**
176
     * @return bool
177
     */
178 22
    public function areMigrationsOrganizedByYearAndMonth()
179
    {
180 22
        return $this->migrationsAreOrganizedByYearAndMonth;
181
    }
182
183
    /**
184
     * Validation that this instance has all the required properties configured
185
     *
186
     * @throws MigrationException
187
     */
188 137
    public function validate()
189
    {
190 137
        if (!$this->migrationsNamespace) {
191 10
            throw MigrationException::migrationsNamespaceRequired();
192
        }
193 127
        if (!$this->migrationsDirectory) {
194 10
            throw MigrationException::migrationsDirectoryRequired();
195
        }
196 117
    }
197
198
    /**
199
     * Set the name of this set of migrations
200
     *
201
     * @param string $name The name of this set of migrations
202
     */
203 63
    public function setName($name)
204
    {
205 63
        $this->name = $name;
206 63
    }
207
208
    /**
209
     * Returns the name of this set of migrations
210
     *
211
     * @return string $name The name of this set of migrations
212
     */
213 15
    public function getName()
214
    {
215 15
        return $this->name;
216
    }
217
218
    /**
219
     * Sets the output writer.
220
     *
221
     * @param OutputWriter $outputWriter
222
     */
223 1
    public function setOutputWriter(OutputWriter $outputWriter)
224
    {
225 1
        $this->outputWriter = $outputWriter;
226 1
    }
227
228
    /**
229
     * Returns the OutputWriter instance
230
     *
231
     * @return OutputWriter $outputWriter  The OutputWriter instance
232
     */
233 108
    public function getOutputWriter()
234
    {
235 108
        return $this->outputWriter;
236
    }
237
238
    /**
239
     * Returns a timestamp version as a formatted date
240
     *
241
     * @param string $version
242
     *
243
     * @return string The formatted version
244
     * @deprecated
245
     */
246
    public function formatVersion($version)
247
    {
248
        return $this->getDateTime($version);
249
    }
250
251
    /**
252
     * Returns the datetime of a migration
253
     *
254
     * @param $version
255
     * @return string
256
     */
257 21
    public function getDateTime($version)
258
    {
259 21
        $datetime = str_replace('Version', '', $version);
260 21
        $datetime = \DateTime::createFromFormat('YmdHis', $datetime);
261
262 21
        if ($datetime === false) {
263 7
            return '';
264
        }
265
266 14
        return $datetime->format('Y-m-d H:i:s');
267
    }
268
269
    /**
270
     * Returns the Connection instance
271
     *
272
     * @return Connection $connection  The Connection instance
273
     */
274 108
    public function getConnection()
275
    {
276 108
        return $this->connection;
277
    }
278
279
    /**
280
     * Set the migration table name
281
     *
282
     * @param string $tableName The migration table name
283
     */
284 82
    public function setMigrationsTableName($tableName)
285
    {
286 82
        $this->migrationsTableName = $tableName;
287 82
    }
288
289
    /**
290
     * Returns the migration table name
291
     *
292
     * @return string $migrationsTableName The migration table name
293
     */
294 67
    public function getMigrationsTableName()
295
    {
296 67
        return $this->migrationsTableName;
297
    }
298
299
    /**
300
     * Set the migration column name
301
     *
302
     * @param string $columnName The migration column name
303
     */
304 53
    public function setMigrationsColumnName($columnName)
305
    {
306 53
        $this->migrationsColumnName = $columnName;
307 53
    }
308
309
    /**
310
     * Returns the migration column name
311
     *
312
     * @return string $migrationsColumnName The migration column name
313
     */
314 62
    public function getMigrationsColumnName()
315
    {
316 62
        return $this->migrationsColumnName;
317
    }
318
319
    /**
320
     * Set the new migrations directory where new migration classes are generated
321
     *
322
     * @param string $migrationsDirectory The new migrations directory
323
     */
324 173
    public function setMigrationsDirectory($migrationsDirectory)
325
    {
326 173
        $this->migrationsDirectory = $migrationsDirectory;
327 173
    }
328
329
    /**
330
     * Returns the new migrations directory where new migration classes are generated
331
     *
332
     * @return string $migrationsDirectory The new migrations directory
333
     */
334 64
    public function getMigrationsDirectory()
335
    {
336 64
        return $this->migrationsDirectory;
337
    }
338
339
    /**
340
     * Set the migrations namespace
341
     *
342
     * @param string $migrationsNamespace The migrations namespace
343
     */
344 185
    public function setMigrationsNamespace($migrationsNamespace)
345
    {
346 185
        $this->migrationsNamespace = $migrationsNamespace;
347 185
    }
348
349
    /**
350
     * Returns the migrations namespace
351
     *
352
     * @return string $migrationsNamespace The migrations namespace
353
     */
354 91
    public function getMigrationsNamespace()
355
    {
356 91
        return $this->migrationsNamespace;
357
    }
358
359
    /**
360
     * Set the implementation of the migration finder.
361
     *
362
     * @param MigrationFinderInterface $finder The new migration finder
363
     * @throws MigrationException
364
     */
365 8
    public function setMigrationsFinder(MigrationFinderInterface $finder)
366
    {
367 8
        if (($this->migrationsAreOrganizedByYear || $this->migrationsAreOrganizedByYearAndMonth) &&
368 8
            !($finder instanceof MigrationDeepFinderInterface)) {
369
370 4
            throw MigrationException::configurationIncompatibleWithFinder(
371 4
                'organize-migrations',
372
                $finder
373 4
            );
374
        }
375
376 4
        $this->migrationFinder = $finder;
377 4
    }
378
379
    /**
380
     * Register migrations from a given directory. Recursively finds all files
381
     * with the pattern VersionYYYYMMDDHHMMSS.php as the filename and registers
382
     * them as migrations.
383
     *
384
     * @param string $path The root directory to where some migration classes live.
385
     *
386
     * @return Version[] The array of migrations registered.
387
     */
388 103
    public function registerMigrationsFromDirectory($path)
389
    {
390 103
        $this->validate();
391
392 87
        return $this->registerMigrations($this->findMigrations($path));
393
    }
394
395
    /**
396
     * Register a single migration version to be executed by a AbstractMigration
397
     * class.
398
     *
399
     * @param string $version The version of the migration in the format YYYYMMDDHHMMSS.
400
     * @param string $class   The migration class to execute for the version.
401
     *
402
     * @return Version
403
     *
404
     * @throws MigrationException
405
     */
406 61
    public function registerMigration($version, $class)
407
    {
408 61
        $this->ensureMigrationClassExists($class);
409
410 60
        $version = (string) $version;
411 60
        $class = (string) $class;
412 60
        if (isset($this->migrations[$version])) {
413 1
            throw MigrationException::duplicateMigrationVersion($version, get_class($this->migrations[$version]));
414
        }
415 60
        $version = new Version($this, $version, $class);
416 60
        $this->migrations[$version->getVersion()] = $version;
417 60
        ksort($this->migrations, SORT_STRING);
418
419 60
        return $version;
420
    }
421
422
    /**
423
     * Register an array of migrations. Each key of the array is the version and
424
     * the value is the migration class name.
425
     *
426
     *
427
     * @param array $migrations
428
     *
429
     * @return Version[]
430
     */
431 90
    public function registerMigrations(array $migrations)
432
    {
433 90
        $versions = [];
434 90
        foreach ($migrations as $version => $class) {
435 33
            $versions[] = $this->registerMigration($version, $class);
436 89
        }
437
438 89
        return $versions;
439
    }
440
441
    /**
442
     * Get the array of registered migration versions.
443
     *
444
     * @return Version[] $migrations
445
     */
446 28
    public function getMigrations()
447
    {
448 28
        return $this->migrations;
449
    }
450
451
    /**
452
     * Returns the Version instance for a given version in the format YYYYMMDDHHMMSS.
453
     *
454
     * @param string $version The version string in the format YYYYMMDDHHMMSS.
455
     *
456
     * @return Version
457
     *
458
     * @throws MigrationException Throws exception if migration version does not exist.
459
     */
460 18
    public function getVersion($version)
461
    {
462 18
        if (empty($this->migrations)) {
463 7
            $this->registerMigrationsFromDirectory($this->getMigrationsDirectory());
464 7
        }
465
466 18
        if (!isset($this->migrations[$version])) {
467 2
            throw MigrationException::unknownMigrationVersion($version);
468
        }
469
470 16
        return $this->migrations[$version];
471
    }
472
473
    /**
474
     * Check if a version exists.
475
     *
476
     * @param string $version
477
     *
478
     * @return boolean
479
     */
480 21
    public function hasVersion($version)
481
    {
482 21
        if (empty($this->migrations)) {
483 4
            $this->registerMigrationsFromDirectory($this->getMigrationsDirectory());
484 2
        }
485
486 19
        return isset($this->migrations[$version]);
487
    }
488
489
    /**
490
     * Check if a version has been migrated or not yet
491
     *
492
     * @param Version $version
493
     *
494
     * @return boolean
495
     */
496 21
    public function hasVersionMigrated(Version $version)
497
    {
498 21
        $this->createMigrationTable();
499
500 21
        $version = $this->connection->fetchColumn(
501 21
            "SELECT " . $this->migrationsColumnName . " FROM " . $this->migrationsTableName . " WHERE " . $this->migrationsColumnName . " = ?",
502 21
            [$version->getVersion()]
503 21
        );
504
505 21
        return $version !== false;
506
    }
507
508
    /**
509
     * Returns all migrated versions from the versions table, in an array.
510
     *
511
     * @return Version[]
512
     */
513 33 View Code Duplication
    public function getMigratedVersions()
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...
514
    {
515 33
        $this->createMigrationTable();
516
517 33
        $ret = $this->connection->fetchAll("SELECT " . $this->migrationsColumnName . " FROM " . $this->migrationsTableName);
518
519 33
        return array_map('current', $ret);
520
    }
521
522
    /**
523
     * Returns an array of available migration version numbers.
524
     *
525
     * @return array
526
     */
527 15
    public function getAvailableVersions()
528
    {
529 15
        $availableVersions = [];
530
531 15
        if (empty($this->migrations)) {
532 3
            $this->registerMigrationsFromDirectory($this->getMigrationsDirectory());
533 1
        }
534
535 13
        foreach ($this->migrations as $migration) {
536 13
            $availableVersions[] = $migration->getVersion();
537 13
        }
538
539 13
        return $availableVersions;
540
    }
541
542
    /**
543
     * Returns the current migrated version from the versions table.
544
     *
545
     * @return string
546
     */
547 35
    public function getCurrentVersion()
548
    {
549 35
        $this->createMigrationTable();
550
551 33
        if (empty($this->migrations)) {
552 15
            $this->registerMigrationsFromDirectory($this->getMigrationsDirectory());
553 15
        }
554
555 33
        $where = null;
556 33
        if (!empty($this->migrations)) {
557 29
            $migratedVersions = [];
558 29
            foreach ($this->migrations as $migration) {
559 29
                $migratedVersions[] = sprintf("'%s'", $migration->getVersion());
560 29
            }
561 29
            $where = " WHERE " . $this->migrationsColumnName . " IN (" . implode(', ', $migratedVersions) . ")";
562 29
        }
563
564 33
        $sql = sprintf("SELECT %s FROM %s%s ORDER BY %s DESC",
565 33
            $this->migrationsColumnName, $this->migrationsTableName, $where, $this->migrationsColumnName
566 33
        );
567
568 33
        $sql = $this->connection->getDatabasePlatform()->modifyLimitQuery($sql, 1);
569 33
        $result = $this->connection->fetchColumn($sql);
570
571 33
        return $result !== false ? (string) $result : '0';
572
    }
573
574
    /**
575
     * Returns the version prior to the current version.
576
     *
577
     * @return string|null A version string, or null if the current version is
578
     *                     the first.
579
     */
580 9
    public function getPrevVersion()
581
    {
582 9
        return $this->getRelativeVersion($this->getCurrentVersion(), -1);
583
    }
584
585
    /**
586
     * Returns the version following the current version.
587
     *
588
     * @return string|null A version string, or null if the current version is
589
     *                     the latest.
590
     */
591 9
    public function getNextVersion()
592
    {
593 9
        return $this->getRelativeVersion($this->getCurrentVersion(), 1);
594
    }
595
596
    /**
597
     * Returns the version with the specified offset to the specified version.
598
     *
599
     * @return string|null A version string, or null if the specified version
600
     *                     is unknown or the specified delta is not within the
601
     *                     list of available versions.
602
     */
603 14
    public function getRelativeVersion($version, $delta)
604
    {
605 14
        if (empty($this->migrations)) {
606 5
            $this->registerMigrationsFromDirectory($this->getMigrationsDirectory());
607 3
        }
608
609 12
        $versions = array_map('strval', array_keys($this->migrations));
610 12
        array_unshift($versions, '0');
611 12
        $offset = array_search((string)$version, $versions);
612 12
        if ($offset === false || !isset($versions[$offset + $delta])) {
613
            // Unknown version or delta out of bounds.
614 10
            return null;
615
        }
616
617 10
        return $versions[$offset + $delta];
618
    }
619
620
    /**
621
     * Returns the version number from an alias.
622
     *
623
     * Supported aliases are:
624
     * - first: The very first version before any migrations have been run.
625
     * - current: The current version.
626
     * - prev: The version prior to the current version.
627
     * - next: The version following the current version.
628
     * - latest: The latest available version.
629
     *
630
     * If an existing version number is specified, it is returned verbatimly.
631
     *
632
     * @return string|null A version number, or null if the specified alias
633
     *                     does not map to an existing version, e.g. if "next"
634
     *                     is passed but the current version is already the
635
     *                     latest.
636
     */
637 8
    public function resolveVersionAlias($alias)
638
    {
639 8
        if ($this->hasVersion($alias)) {
640 1
            return $alias;
641
        }
642
        switch ($alias) {
643 8
            case 'first':
644 1
                return '0';
645 8
            case 'current':
646 8
                return $this->getCurrentVersion();
647 8
            case 'prev':
648 8
                return $this->getPrevVersion();
649 8
            case 'next':
650 8
                return $this->getNextVersion();
651 8
            case 'latest':
652 8
                return $this->getLatestVersion();
653 1
            default:
654 1
                return null;
655 1
        }
656
    }
657
658
    /**
659
     * Returns the total number of executed migration versions
660
     *
661
     * @return integer
662
     */
663 1 View Code Duplication
    public function getNumberOfExecutedMigrations()
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...
664
    {
665 1
        $this->createMigrationTable();
666
667 1
        $result = $this->connection->fetchColumn("SELECT COUNT(" . $this->migrationsColumnName . ") FROM " . $this->migrationsTableName);
668
669 1
        return $result !== false ? $result : 0;
670
    }
671
672
    /**
673
     * Returns the total number of available migration versions
674
     *
675
     * @return integer
676
     */
677 5
    public function getNumberOfAvailableMigrations()
678
    {
679 5
        if (empty($this->migrations)) {
680 4
            $this->registerMigrationsFromDirectory($this->getMigrationsDirectory());
681 2
        }
682
683 3
        return count($this->migrations);
684
    }
685
686
    /**
687
     * Returns the latest available migration version.
688
     *
689
     * @return string The version string in the format YYYYMMDDHHMMSS.
690
     */
691 21
    public function getLatestVersion()
692
    {
693 21
        if (empty($this->migrations)) {
694 7
            $this->registerMigrationsFromDirectory($this->getMigrationsDirectory());
695 5
        }
696
697 19
        $versions = array_keys($this->migrations);
698 19
        $latest = end($versions);
699
700 19
        return $latest !== false ? (string) $latest : '0';
701
    }
702
703
    /**
704
     * Create the migration table to track migrations with.
705
     *
706
     * @return boolean Whether or not the table was created.
707
     */
708 55
    public function createMigrationTable()
709
    {
710 55
        $this->validate();
711
712 53
        if ($this->migrationTableCreated) {
713 43
            return false;
714
        }
715
716 53
        if ($this->connection->getSchemaManager()->tablesExist([$this->migrationsTableName])) {
717 3
            $this->migrationTableCreated = true;
718
719 3
            return false;
720
        }
721
722
        $columns = [
723 53
            $this->migrationsColumnName => new Column($this->migrationsColumnName, Type::getType('string'), ['length' => 255]),
724 53
        ];
725 53
        $table = new Table($this->migrationsTableName, $columns);
726 53
        $table->setPrimaryKey([$this->migrationsColumnName]);
727 53
        $this->connection->getSchemaManager()->createTable($table);
728
729 53
        $this->migrationTableCreated = true;
730
731 53
        return true;
732
    }
733
734
    /**
735
     * Returns the array of migrations to executed based on the given direction
736
     * and target version number.
737
     *
738
     * @param string $direction The direction we are migrating.
739
     * @param string $to        The version to migrate to.
740
     *
741
     * @return Version[] $migrations   The array of migrations we can execute.
742
     */
743 33
    public function getMigrationsToExecute($direction, $to)
744
    {
745 33
        if (empty($this->migrations)) {
746 11
            $this->registerMigrationsFromDirectory($this->getMigrationsDirectory());
747 5
        }
748
749 27
        if ($direction === Version::DIRECTION_DOWN) {
750 7
            if (count($this->migrations)) {
751 7
                $allVersions = array_reverse(array_keys($this->migrations));
752 7
                $classes = array_reverse(array_values($this->migrations));
753 7
                $allVersions = array_combine($allVersions, $classes);
754 7
            } else {
755
                $allVersions = [];
756
            }
757 7
        } else {
758 25
            $allVersions = $this->migrations;
759
        }
760 27
        $versions = [];
761 27
        $migrated = $this->getMigratedVersions();
762 27
        foreach ($allVersions as $version) {
763 25
            if ($this->shouldExecuteMigration($direction, $version, $to, $migrated)) {
764 23
                $versions[$version->getVersion()] = $version;
765 23
            }
766 27
        }
767
768 27
        return $versions;
769
    }
770
771
    /**
772
     * Find all the migrations in a given directory.
773
     *
774
     * @param   string $path the directory to search.
775
     * @return  array
776
     */
777 87
    protected function findMigrations($path)
778
    {
779 87
        return $this->migrationFinder->findMigrations($path, $this->getMigrationsNamespace());
780
    }
781
782
    /**
783
     * @param bool $migrationsAreOrganizedByYear
784
     * @throws MigrationException
785
     */
786 9
    public function setMigrationsAreOrganizedByYear($migrationsAreOrganizedByYear = true)
787
    {
788 9
        $this->ensureOrganizeMigrationsIsCompatibleWithFinder();
789
790 5
        $this->migrationsAreOrganizedByYear = $migrationsAreOrganizedByYear;
791 5
    }
792
793
    /**
794
     * @param bool $migrationsAreOrganizedByYearAndMonth
795
     * @throws MigrationException
796
     */
797 10
    public function setMigrationsAreOrganizedByYearAndMonth($migrationsAreOrganizedByYearAndMonth = true)
798
    {
799 10
        $this->ensureOrganizeMigrationsIsCompatibleWithFinder();
800
801 10
        $this->migrationsAreOrganizedByYear = $migrationsAreOrganizedByYearAndMonth;
802 10
        $this->migrationsAreOrganizedByYearAndMonth = $migrationsAreOrganizedByYearAndMonth;
803 10
    }
804
805
    /**
806
     * Generate a new migration version. A version is (usually) a datetime string.
807
     *
808
     * @param DateTimeInterface|null $now Defaults to the current time in UTC
809
     * @return string The newly generated version
810
     */
811 9
    public function generateVersionNumber(\DateTimeInterface $now=null)
812
    {
813 9
        $now = $now ?: new \DateTime('now', new \DateTimeZone('UTC'));
814
815 9
        return $now->format(self::VERSION_FORMAT);
816
    }
817
818
    /**
819
     * @throws MigrationException
820
     */
821 19
    private function ensureOrganizeMigrationsIsCompatibleWithFinder()
822
    {
823 19
        if (!($this->migrationFinder instanceof MigrationDeepFinderInterface)) {
824 4
            throw MigrationException::configurationIncompatibleWithFinder(
825 4
                'organize-migrations',
826 4
                $this->migrationFinder
827 4
            );
828
        }
829 15
    }
830
831
    /**
832
     * Check if we should execute a migration for a given direction and target
833
     * migration version.
834
     *
835
     * @param string  $direction The direction we are migrating.
836
     * @param Version $version   The Version instance to check.
837
     * @param string  $to        The version we are migrating to.
838
     * @param array   $migrated  Migrated versions array.
839
     *
840
     * @return boolean
841
     */
842 25
    private function shouldExecuteMigration($direction, Version $version, $to, $migrated)
843
    {
844 25 View Code Duplication
        if ($direction === Version::DIRECTION_DOWN) {
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...
845 7
            if (!in_array($version->getVersion(), $migrated)) {
846 4
                return false;
847
            }
848
849 5
            return $version->getVersion() > $to;
850
        }
851
852 23 View Code Duplication
        if ($direction === Version::DIRECTION_UP) {
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...
853 23
            if (in_array($version->getVersion(), $migrated)) {
854 7
                return false;
855
            }
856
857 23
            return $version->getVersion() <= $to;
858
        }
859
    }
860
861
    /**
862
     * @param string $class
863
     */
864 61
    private function ensureMigrationClassExists($class)
865
    {
866 61
        if ( ! class_exists($class)) {
867 1
            throw MigrationException::migrationClassNotFound($class, $this->getMigrationsNamespace());
868
        }
869 60
    }
870
}
871