Completed
Push — master ( 9613ab...ee300a )
by Mike
03:47
created

MigrateCommand::execute()   C

Complexity

Conditions 8
Paths 10

Size

Total Lines 66
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 39
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 66
ccs 39
cts 39
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
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
62
You can also execute the migration as a <comment>--dry-run</comment>:
63
64
    <info>%command.full_name% YYYYMMDDHHMMSS --dry-run</info>
65
66
You can output the would be executed SQL statements to a file with <comment>--write-sql</comment>:
67
68
    <info>%command.full_name% YYYYMMDDHHMMSS --write-sql</info>
69
70
Or you can also execute the migration without a warning message which you need to interact with:
71
72
    <info>%command.full_name% --no-interaction</info>
73
74
You can also time all the different queries if you wanna know which one is taking so long:
75
76 18
    <info>%command.full_name% --query-time</info>
77
EOT
78
        );
79
80 18
        parent::configure();
81 18
    }
82
83 11
    public function execute(InputInterface $input, OutputInterface $output)
84
    {
85 11
        $configuration = $this->getMigrationConfiguration($input, $output);
86 11
        $migration = $this->createMigration($configuration);
87
88 11
        $this->outputHeader($configuration, $output);
89
90 11
        $timeAllqueries = $input->getOption('query-time');
91
92 11
        $executedMigrations = $configuration->getMigratedVersions();
93 11
        $availableMigrations = $configuration->getAvailableVersions();
94
95 11
        $version = $this->getVersionNameFromAlias($input->getArgument('version'), $output, $configuration);
96 11
        if ($version === false) {
97 3
            return 1;
98
        }
99
100 8
        $executedUnavailableMigrations = array_diff($executedMigrations, $availableMigrations);
101 8
        if (!empty($executedUnavailableMigrations)) {
102 1
            $output->writeln(sprintf(
103
                '<error>WARNING! You have %s previously executed migrations'
104 1
                . ' in the database that are not registered migrations.</error>',
105
                count($executedUnavailableMigrations)
106
            ));
107
108 1
            foreach ($executedUnavailableMigrations as $executedUnavailableMigration) {
109 1
                $output->writeln(sprintf(
110 1
                    '    <comment>>></comment> %s (<comment>%s</comment>)',
111 1
                    $configuration->getDateTime($executedUnavailableMigration),
112
                    $executedUnavailableMigration
113
                ));
114
            }
115
116 1
            $question = 'Are you sure you wish to continue? (y/n)';
117 1
            if (! $this->canExecute($question, $input, $output)) {
118 1
                $output->writeln('<error>Migration cancelled!</error>');
119
120 1
                return 1;
121
            }
122
        }
123
124 7
        if ($path = $input->getOption('write-sql')) {
125 2
            $path = is_bool($path) ? getcwd() : $path;
126 2
            $migration->writeSqlFile($path, $version);
127 2
            return 0;
128
        }
129
130 5
        $dryRun = (boolean) $input->getOption('dry-run');
131
132 5
        $cancelled = false;
133 5
        $migration->setNoMigrationException($input->getOption('allow-no-migration'));
134 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...
135
            $question = 'WARNING! You are about to execute a database migration'
136
                . ' that could result in schema changes and data lost.'
137 4
                . ' Are you sure you wish to continue? (y/n)';
138 4
            $canContinue = $this->canExecute($question, $input, $output);
139 4
            $cancelled = !$canContinue;
140
141 4
            return $canContinue;
142 5
        });
143
144 5
        if ($cancelled) {
145 1
            $output->writeln('<error>Migration cancelled!</error>');
146 1
            return 1;
147
        }
148 4
    }
149
150
    /**
151
     * Create a new migration instance to execute the migrations.
152
     *
153
     * @param $configuration The configuration with which the migrations will be executed
154
     * @return Migration a new migration instance
155
     */
156 1
    protected function createMigration(Configuration $configuration)
157
    {
158 1
        return new Migration($configuration);
159
    }
160
161
    /**
162
     * @param string $question
163
     * @param InputInterface $input
164
     * @param OutputInterface $output
165
     * @return bool
166
     */
167 5
    private function canExecute($question, InputInterface $input, OutputInterface $output)
168
    {
169 5
        if ($input->isInteractive() && ! $this->askConfirmation($question, $input, $output)) {
170 2
            return false;
171
        }
172
173 3
        return true;
174
    }
175
176
    /**
177
     * @param string $versionAlias
178
     * @param OutputInterface $output
179
     * @param Configuration $configuration
180
     * @return bool|string
181
     */
182 11
    private function getVersionNameFromAlias($versionAlias, OutputInterface $output, Configuration $configuration)
183
    {
184 11
        $version = $configuration->resolveVersionAlias($versionAlias);
185 11
        if ($version === null) {
186 3
            if ($versionAlias == 'prev') {
187 1
                $output->writeln('<error>Already at first version.</error>');
188 1
                return false;
189
            }
190 2
            if ($versionAlias == 'next') {
191 1
                $output->writeln('<error>Already at latest version.</error>');
192 1
                return false;
193
            }
194
195 1
            $output->writeln(sprintf(
196 1
                '<error>Unknown version: %s</error>',
197 1
                $output->getFormatter()->escape($versionAlias)
198
            ));
199 1
            return false;
200
        }
201
202 8
        return $version;
203
    }
204
}
205