Completed
Push — master ( 178c75...b82d68 )
by Luís
11s
created

MigrateCommand::execute()   C

Complexity

Conditions 8
Paths 10

Size

Total Lines 66
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 41
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 66
ccs 41
cts 41
cp 1
rs 6.7081
c 0
b 0
f 0
cc 8
eloc 42
nc 10
nop 2
crap 8

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Tools\Console\Command;
21
22
use Doctrine\DBAL\Migrations\Configuration\Configuration;
23
use Doctrine\DBAL\Migrations\Migration;
24
use Symfony\Component\Console\Input\InputInterface;
25
use Symfony\Component\Console\Output\OutputInterface;
26
use Symfony\Component\Console\Input\InputArgument;
27
use Symfony\Component\Console\Input\InputOption;
28
29
/**
30
 * Command for executing a migration to a specified version or the latest available version.
31
 *
32
 * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
33
 * @link    www.doctrine-project.org
34
 * @since   2.0
35
 * @author  Jonathan Wage <[email protected]>
36
 */
37
class MigrateCommand extends AbstractCommand
38
{
39 18
    protected function configure()
40
    {
41
        $this
42 18
            ->setName('migrations:migrate')
43 18
            ->setDescription('Execute a migration to a specified version or the latest available version.')
44 18
            ->addArgument('version', InputArgument::OPTIONAL, 'The version number (YYYYMMDDHHMMSS) or alias (first, prev, next, latest) to migrate to.', 'latest')
45 18
            ->addOption('write-sql', null, InputOption::VALUE_NONE, 'The path to output the migration SQL file instead of executing it.')
46 18
            ->addOption('dry-run', null, InputOption::VALUE_NONE, 'Execute the migration as a dry run.')
47 18
            ->addOption('query-time', null, InputOption::VALUE_NONE, 'Time all the queries individually.')
48 18
            ->addOption('allow-no-migration', null, InputOption::VALUE_NONE, 'Don\'t throw an exception if no migration is available (CI).')
49 18
            ->setHelp(<<<EOT
50 18
The <info>%command.name%</info> command executes a migration to a specified version or the latest available version:
51
52
    <info>%command.full_name%</info>
53
54
You can optionally manually specify the version you wish to migrate to:
55
56
    <info>%command.full_name% YYYYMMDDHHMMSS</info>
57
58
You can specify the version you wish to migrate to using an alias:
59
60
    <info>%command.full_name% prev</info>
61
    <info>These alias are defined : first, lastest, prev, current and next</info>
62
63
You can specify the version you wish to migrate to using an number against the current version:
64
65
    <info>%command.full_name% current+3</info>
66
67
You can also execute the migration as a <comment>--dry-run</comment>:
68
69
    <info>%command.full_name% YYYYMMDDHHMMSS --dry-run</info>
70
71
You can output the would be executed SQL statements to a file with <comment>--write-sql</comment>:
72
73
    <info>%command.full_name% YYYYMMDDHHMMSS --write-sql</info>
74
75
Or you can also execute the migration without a warning message which you need to interact with:
76
77
    <info>%command.full_name% --no-interaction</info>
78
79
You can also time all the different queries if you wanna know which one is taking so long:
80
81
    <info>%command.full_name% --query-time</info>
82
EOT
83
        );
84
85 18
        parent::configure();
86 18
    }
87
88 11
    public function execute(InputInterface $input, OutputInterface $output)
89
    {
90 11
        $configuration = $this->getMigrationConfiguration($input, $output);
91 11
        $migration = $this->createMigration($configuration);
92
93 11
        $this->outputHeader($configuration, $output);
94
95 11
        $timeAllqueries = $input->getOption('query-time');
96
97 11
        $executedMigrations = $configuration->getMigratedVersions();
98 11
        $availableMigrations = $configuration->getAvailableVersions();
99
100 11
        $version = $this->getVersionNameFromAlias($input->getArgument('version'), $output, $configuration);
101 11
        if ($version === false) {
102 3
            return 1;
103
        }
104
105 8
        $executedUnavailableMigrations = array_diff($executedMigrations, $availableMigrations);
106 8
        if (!empty($executedUnavailableMigrations)) {
107 1
            $output->writeln(sprintf(
108
                '<error>WARNING! You have %s previously executed migrations'
109 1
                . ' in the database that are not registered migrations.</error>',
110 1
                count($executedUnavailableMigrations)
111
            ));
112
113 1
            foreach ($executedUnavailableMigrations as $executedUnavailableMigration) {
114 1
                $output->writeln(sprintf(
115 1
                    '    <comment>>></comment> %s (<comment>%s</comment>)',
116 1
                    $configuration->getDateTime($executedUnavailableMigration),
117 1
                    $executedUnavailableMigration
118
                ));
119
            }
120
121 1
            $question = 'Are you sure you wish to continue? (y/n)';
122 1
            if (! $this->canExecute($question, $input, $output)) {
123 1
                $output->writeln('<error>Migration cancelled!</error>');
124
125 1
                return 1;
126
            }
127
        }
128
129 7
        if ($path = $input->getOption('write-sql')) {
130 2
            $path = is_bool($path) ? getcwd() : $path;
131 2
            $migration->writeSqlFile($path, $version);
132 2
            return 0;
133
        }
134
135 5
        $dryRun = (boolean) $input->getOption('dry-run');
136
137 5
        $cancelled = false;
138 5
        $migration->setNoMigrationException($input->getOption('allow-no-migration'));
139 5
        $result = $migration->migrate($version, $dryRun, $timeAllqueries, function () use ($input, $output, &$cancelled) {
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
140
            $question = 'WARNING! You are about to execute a database migration'
141
                . ' that could result in schema changes and data lost.'
142 4
                . ' Are you sure you wish to continue? (y/n)';
143 4
            $canContinue = $this->canExecute($question, $input, $output);
144 4
            $cancelled = !$canContinue;
145
146 4
            return $canContinue;
147 5
        });
148
149 5
        if ($cancelled) {
150 1
            $output->writeln('<error>Migration cancelled!</error>');
151 1
            return 1;
152
        }
153 4
    }
154
155
    /**
156
     * Create a new migration instance to execute the migrations.
157
     *
158
     * @param $configuration The configuration with which the migrations will be executed
159
     * @return Migration a new migration instance
160
     */
161 1
    protected function createMigration(Configuration $configuration)
162
    {
163 1
        return new Migration($configuration);
164
    }
165
166
    /**
167
     * @param string $question
168
     * @param InputInterface $input
169
     * @param OutputInterface $output
170
     * @return bool
171
     */
172 5
    private function canExecute($question, InputInterface $input, OutputInterface $output)
173
    {
174 5
        if ($input->isInteractive() && ! $this->askConfirmation($question, $input, $output)) {
175 2
            return false;
176
        }
177
178 3
        return true;
179
    }
180
181
    /**
182
     * @param string $versionAlias
183
     * @param OutputInterface $output
184
     * @param Configuration $configuration
185
     * @return bool|string
186
     */
187 11
    private function getVersionNameFromAlias($versionAlias, OutputInterface $output, Configuration $configuration)
188
    {
189 11
        $version = $configuration->resolveVersionAlias($versionAlias);
190 11
        if ($version === null) {
191 3
            if ($versionAlias == 'prev') {
192 1
                $output->writeln('<error>Already at first version.</error>');
193 1
                return false;
194
            }
195 2
            if ($versionAlias == 'next') {
196 1
                $output->writeln('<error>Already at latest version.</error>');
197 1
                return false;
198
            }
199 1
            if (substr($versionAlias, 0, 7) == 'current') {
200
                $output->writeln('<error>The delta couldn\'t be reached.</error>');
201
                return false;
202
            }
203
204 1
            $output->writeln(sprintf(
205 1
                '<error>Unknown version: %s</error>',
206 1
                $output->getFormatter()->escape($versionAlias)
207
            ));
208 1
            return false;
209
        }
210
211 8
        return $version;
212
    }
213
}
214