Failed Conditions
Pull Request — master (#968)
by Edi
02:04
created

ExecuteCommand   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 135
Duplicated Lines 0 %

Test Coverage

Coverage 94.44%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 96
c 1
b 0
f 0
dl 0
loc 135
ccs 68
cts 72
cp 0.9444
rs 10
wmc 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
B configure() 0 73 1
B execute() 0 55 9
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Migrations\Tools\Console\Command;
6
7
use Doctrine\Migrations\Version\Direction;
8
use Doctrine\Migrations\Version\Version;
9
use Symfony\Component\Console\Input\InputArgument;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Input\InputOption;
12
use Symfony\Component\Console\Output\OutputInterface;
13
use function array_map;
14
use function getcwd;
15
use function implode;
16
use function is_string;
17
use function is_writable;
18
19
/**
20
 * The ExecuteCommand class is responsible for executing migration versions up or down manually.
21
 */
22
final class ExecuteCommand extends DoctrineCommand
23
{
24
    /** @var string */
25
    protected static $defaultName = 'migrations:execute';
26
27 4
    protected function configure() : void
28
    {
29
        $this
30 4
            ->setAliases(['execute'])
31 4
            ->setDescription(
32 4
                'Execute one or more migration versions up or down manually.'
33
            )
34 4
            ->addArgument(
35 4
                'versions',
36 4
                InputArgument::REQUIRED|InputArgument::IS_ARRAY,
37 4
                'The versions to execute.',
38 4
                null
39
            )
40 4
            ->addOption(
41 4
                'write-sql',
42 4
                null,
43 4
                InputOption::VALUE_OPTIONAL,
44 4
                'The path to output the migration SQL file instead of executing it. Defaults to current working directory.',
45 4
                false
46
            )
47 4
            ->addOption(
48 4
                'dry-run',
49 4
                null,
50 4
                InputOption::VALUE_NONE,
51 4
                'Execute the migration as a dry run.'
52
            )
53 4
            ->addOption(
54 4
                'up',
55 4
                null,
56 4
                InputOption::VALUE_NONE,
57 4
                'Execute the migration up.'
58
            )
59 4
            ->addOption(
60 4
                'down',
61 4
                null,
62 4
                InputOption::VALUE_NONE,
63 4
                'Execute the migration down.'
64
            )
65 4
            ->addOption(
66 4
                'query-time',
67 4
                null,
68 4
                InputOption::VALUE_NONE,
69 4
                'Time all the queries individually.'
70
            )
71 4
            ->setHelp(<<<EOT
72 4
The <info>%command.name%</info> command executes migration versions up or down manually:
73
74
    <info>%command.full_name% FQCN</info>
75
76
If no <comment>--up</comment> or <comment>--down</comment> option is specified it defaults to up:
77
78
    <info>%command.full_name% FQCN --down</info>
79
80
You can also execute the migration as a <comment>--dry-run</comment>:
81
82
    <info>%command.full_name% FQCN --dry-run</info>
83
84
You can output the would be executed SQL statements to a file with <comment>--write-sql</comment>:
85
86
    <info>%command.full_name% FQCN --write-sql</info>
87
88
Or you can also execute the migration without a warning message which you need to interact with:
89
90
    <info>%command.full_name% FQCN --no-interaction</info>
91
92
All the previous commands accept multiple migration versions, allowing you run execute more than
93
one migration at once:
94
    <info>%command.full_name% FQCN-1 FQCN-2 ...FQCN-n </info>
95
96
EOT
97
        );
98
99 4
        parent::configure();
100 4
    }
101
102 4
    protected function execute(InputInterface $input, OutputInterface $output) : int
103
    {
104 4
        $versions  = $input->getArgument('versions');
105 4
        $path      = $input->getOption('write-sql');
106 4
        $direction = $input->getOption('down') !== false
107 4
            ? Direction::DOWN
108 4
            : Direction::UP;
109
110 4
        $migrator       = $this->getDependencyFactory()->getMigrator();
111 4
        $planCalculator = $this->getDependencyFactory()->getMigrationPlanCalculator();
112
        $plan           = $planCalculator->getPlanForVersions(array_map(static function (string $version) : Version {
113 4
            return new Version($version);
114 4
        }, $versions), $direction);
0 ignored issues
show
Bug introduced by
It seems like $versions can also be of type null and string; however, parameter $arr1 of array_map() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

114
        }, /** @scrutinizer ignore-type */ $versions), $direction);
Loading history...
115
116 4
        $migratorConfigurationFactory = $this->getDependencyFactory()->getConsoleInputMigratorConfigurationFactory();
117 4
        $migratorConfiguration        = $migratorConfigurationFactory->getMigratorConfiguration($input);
118
119 4
        if ($path !== false) {
120 2
            $migratorConfiguration->setDryRun(true);
121 2
            $sql = $migrator->migrate($plan, $migratorConfiguration);
122
123 2
            $path = is_string($path) ? $path : getcwd();
124
125 2
            if (! is_string($path) || ! is_writable($path)) {
0 ignored issues
show
introduced by
The condition is_string($path) is always true.
Loading history...
126
                $this->io->error('Path not writeable!');
127
128
                return 1;
129
            }
130
131 2
            $writer = $this->getDependencyFactory()->getQueryWriter();
132 2
            $writer->write($path, $direction, $sql);
133
134 2
            return 0;
135
        }
136
137 2
        $question = 'WARNING! You are about to execute a database migration that could result in schema changes and data lost. Are you sure you wish to continue?';
138
139 2
        if (! $migratorConfiguration->isDryRun() && ! $this->canExecute($question, $input)) {
140
            $this->io->error('Migration cancelled!');
141
142
            return 1;
143
        }
144
145 2
        $this->getDependencyFactory()->getMetadataStorage()->ensureInitialized();
146
147 2
        $this->getDependencyFactory()->getLogger()->notice(
148 2
            'Executing' . ($migratorConfiguration->isDryRun() ? ' (dry-run)' : '') . ' {versions} {direction}',
149
            [
150 2
                'direction' => $plan->getDirection(),
151 2
                'versions' => implode(', ', $versions),
0 ignored issues
show
Bug introduced by
It seems like $versions can also be of type null and string; however, parameter $pieces of implode() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

151
                'versions' => implode(', ', /** @scrutinizer ignore-type */ $versions),
Loading history...
152
            ]
153
        );
154 2
        $migrator->migrate($plan, $migratorConfiguration);
155
156 2
        return 0;
157
    }
158
}
159