1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the AntiMattr MongoDB Migrations Library, a library by Matthew Fitzgerald. |
5
|
|
|
* |
6
|
|
|
* (c) 2014 Matthew Fitzgerald |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace AntiMattr\MongoDB\Migrations\Tools\Console\Command; |
13
|
|
|
|
14
|
|
|
use AntiMattr\MongoDB\Migrations\Configuration\Configuration; |
15
|
|
|
use AntiMattr\MongoDB\Migrations\Migration; |
16
|
|
|
use Symfony\Component\Console\Input\InputArgument; |
17
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
18
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
19
|
|
|
use Symfony\Component\Console\Question\ConfirmationQuestion; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* @author Matthew Fitzgerald <[email protected]> |
23
|
|
|
*/ |
24
|
|
|
class MigrateCommand extends AbstractCommand |
25
|
|
|
{ |
26
|
|
|
protected static $defaultName = 'mongodb:migrations:migrate'; |
27
|
|
|
|
28
|
4 |
|
protected function configure() |
29
|
|
|
{ |
30
|
|
|
$this |
31
|
4 |
|
->setDescription('Execute a migration to a specified version or the latest available version.') |
32
|
4 |
|
->addArgument('version', InputArgument::OPTIONAL, 'The version to migrate to.', null) |
33
|
4 |
|
->setHelp(<<<'EOT' |
34
|
4 |
|
The <info>%command.name%</info> command executes a migration to a specified version or the latest available version: |
35
|
|
|
|
36
|
|
|
<info>%command.full_name%</info> |
37
|
|
|
|
38
|
|
|
You can optionally manually specify the version you wish to migrate to: |
39
|
|
|
|
40
|
|
|
<info>%command.full_name% YYYYMMDDHHMMSS</info> |
41
|
|
|
|
42
|
|
|
Or you can also execute the migration without a warning message which you need to interact with: |
43
|
|
|
|
44
|
|
|
<info>%command.full_name% --no-interaction</info> |
45
|
|
|
|
46
|
|
|
EOT |
47
|
|
|
); |
48
|
|
|
|
49
|
4 |
|
parent::configure(); |
50
|
4 |
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @param \Symfony\Component\Console\Input\InputInterface |
54
|
|
|
* @param \Symfony\Component\Console\Output\OutputInterface |
55
|
|
|
*/ |
56
|
4 |
|
public function execute(InputInterface $input, OutputInterface $output) |
57
|
|
|
{ |
58
|
4 |
|
$version = $input->getArgument('version'); |
59
|
|
|
|
60
|
4 |
|
$configuration = $this->getMigrationConfiguration($input, $output); |
61
|
4 |
|
$migration = $this->createMigration($configuration); |
62
|
|
|
|
63
|
4 |
|
$this->outputHeader($configuration, $output); |
64
|
|
|
|
65
|
4 |
|
$noInteraction = !$input->isInteractive(); |
66
|
|
|
|
67
|
4 |
|
$executedVersions = $configuration->getMigratedVersions(); |
68
|
4 |
|
$availableVersions = $configuration->getAvailableVersions(); |
69
|
4 |
|
$executedUnavailableVersions = array_diff($executedVersions, $availableVersions); |
70
|
|
|
|
71
|
4 |
|
if ($executedUnavailableVersions) { |
|
|
|
|
72
|
3 |
|
$output->writeln(sprintf('<error>WARNING! You have %s previously executed migrations in the database that are not registered migrations.</error>', count($executedUnavailableVersions))); |
73
|
3 |
|
foreach ($executedUnavailableVersions as $executedUnavailableVersion) { |
74
|
3 |
|
$output->writeln( |
75
|
3 |
|
sprintf( |
76
|
3 |
|
' <comment>>></comment> %s (<comment>%s</comment>)', |
77
|
3 |
|
Configuration::formatVersion($executedUnavailableVersion), |
78
|
3 |
|
$executedUnavailableVersion |
79
|
|
|
) |
80
|
|
|
); |
81
|
|
|
} |
82
|
|
|
|
83
|
3 |
|
if (!$noInteraction) { |
84
|
3 |
|
$question = new ConfirmationQuestion( |
85
|
3 |
|
'<question>Are you sure you wish to continue? (y/[n])</question> ', |
86
|
3 |
|
false |
87
|
|
|
); |
88
|
|
|
|
89
|
|
|
$confirmation = $this |
90
|
3 |
|
->getHelper('question') |
91
|
3 |
|
->ask($input, $output, $question); |
92
|
|
|
|
93
|
3 |
|
if (!$confirmation) { |
94
|
1 |
|
$output->writeln('<error>Migration cancelled!</error>'); |
95
|
|
|
|
96
|
1 |
|
return 1; |
97
|
|
|
} |
98
|
|
|
} |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
// warn the user if no dry run and interaction is on |
102
|
3 |
|
if (!$noInteraction) { |
103
|
2 |
|
$question = new ConfirmationQuestion( |
104
|
2 |
|
'<question>WARNING! You are about to execute a database migration that could result in data lost. Are you sure you wish to continue? (y/[n])</question> ', |
105
|
2 |
|
false |
106
|
|
|
); |
107
|
|
|
|
108
|
|
|
$confirmation = $this |
109
|
2 |
|
->getHelper('question') |
110
|
2 |
|
->ask($input, $output, $question); |
111
|
|
|
|
112
|
2 |
|
if (!$confirmation) { |
113
|
1 |
|
$output->writeln('<error>Migration cancelled!</error>'); |
114
|
|
|
|
115
|
1 |
|
return 1; |
116
|
|
|
} |
117
|
|
|
} |
118
|
|
|
|
119
|
2 |
|
$migration->migrate($version); |
|
|
|
|
120
|
|
|
|
121
|
2 |
|
return 0; |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
protected function createMigration(Configuration $configuration) |
125
|
|
|
{ |
126
|
|
|
return new Migration($configuration); |
127
|
|
|
} |
128
|
|
|
} |
129
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.