Completed
Push — master ( 740609...cb74ad )
by Grégoire
02:47
created

ExecuteCommand::execute()   B

Complexity

Conditions 8
Paths 12

Size

Total Lines 47
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 8.021

Importance

Changes 0
Metric Value
cc 8
eloc 29
nc 12
nop 2
dl 0
loc 47
ccs 27
cts 29
cp 0.931
crap 8.021
rs 8.2114
c 0
b 0
f 0
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 is_string;
16
use function is_writable;
17
18
/**
19
 * The ExecuteCommand class is responsible for executing migration versions up or down manually.
20
 */
21
class ExecuteCommand extends DoctrineCommand
22
{
23
    /** @var string */
24
    protected static $defaultName = 'migrations:execute';
25
26 5
    protected function configure() : void
27
    {
28
        $this
29 5
            ->setAliases(['execute'])
30 5
            ->setDescription(
31 5
                'Execute one or more migration versions up or down manually.'
32
            )
33 5
            ->addArgument(
34 5
                'versions',
35 5
                InputArgument::REQUIRED|InputArgument::IS_ARRAY,
36 5
                'The versions to execute.',
37 5
                null
38
            )
39 5
            ->addOption(
40 5
                'write-sql',
41 5
                null,
42 5
                InputOption::VALUE_OPTIONAL,
43 5
                'The path to output the migration SQL file instead of executing it. Defaults to current working directory.',
44 5
                false
45
            )
46 5
            ->addOption(
47 5
                'dry-run',
48 5
                null,
49 5
                InputOption::VALUE_NONE,
50 5
                'Execute the migration as a dry run.'
51
            )
52 5
            ->addOption(
53 5
                'up',
54 5
                null,
55 5
                InputOption::VALUE_NONE,
56 5
                'Execute the migration up.'
57
            )
58 5
            ->addOption(
59 5
                'down',
60 5
                null,
61 5
                InputOption::VALUE_NONE,
62 5
                'Execute the migration down.'
63
            )
64 5
            ->addOption(
65 5
                'query-time',
66 5
                null,
67 5
                InputOption::VALUE_NONE,
68 5
                'Time all the queries individually.'
69
            )
70 5
            ->setHelp(<<<EOT
71 5
The <info>%command.name%</info> command executes migration versions up or down manually:
72
73
    <info>%command.full_name% FQCN</info>
74
    
75
If no <comment>--up</comment> or <comment>--down</comment> option is specified it defaults to up:
76
77
    <info>%command.full_name% FQCN --down</info>
78
79
You can also execute the migration as a <comment>--dry-run</comment>:
80
81
    <info>%command.full_name% FQCN --dry-run</info>
82
83
You can output the would be executed SQL statements to a file with <comment>--write-sql</comment>:
84
85
    <info>%command.full_name% FQCN --write-sql</info>
86
87
Or you can also execute the migration without a warning message which you need to interact with:
88
89
    <info>%command.full_name% FQCN --no-interaction</info>
90
91
All the previous commands accept multiple migration versions, allowing you run execute more than
92
one migration at once:
93
    <info>%command.full_name% FQCN-1 FQCN-2 ...FQCN-n </info>
94
95
EOT
96
        );
97
98 5
        parent::configure();
99 5
    }
100
101 5
    public function execute(InputInterface $input, OutputInterface $output) : ?int
102
    {
103 5
        $versions  = $input->getArgument('versions');
104 5
        $path      = $input->getOption('write-sql');
105 5
        $direction = $input->getOption('down') !== false
106 5
            ? Direction::DOWN
107 5
            : Direction::UP;
108
109 5
        $migrator       = $this->getDependencyFactory()->getMigrator();
110 5
        $planCalculator = $this->getDependencyFactory()->getMigrationPlanCalculator();
111
        $plan           = $planCalculator->getPlanForVersions(array_map(static function (string $version) : Version {
112 5
            return new Version($version);
113 5
        }, $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

113
        }, /** @scrutinizer ignore-type */ $versions), $direction);
Loading history...
114
115 5
        $migratorConfigurationFactory = $this->getDependencyFactory()->getConsoleInputMigratorConfigurationFactory();
116 5
        $migratorConfiguration        = $migratorConfigurationFactory->getMigratorConfiguration($input);
117
118 5
        if ($path !== false) {
119 2
            $migratorConfiguration->setDryRun(true);
120 2
            $sql = $migrator->migrate($plan, $migratorConfiguration);
121
122 2
            $path = is_string($path) ? $path : getcwd();
123
124 2
            if (! is_string($path) || ! is_writable($path)) {
0 ignored issues
show
introduced by
The condition is_string($path) is always true.
Loading history...
125
                $output->writeln('<error>Path not writeable!</error>');
126
127
                return 1;
128
            }
129
130 2
            $writer = $this->getDependencyFactory()->getQueryWriter();
131 2
            $writer->write($path, $direction, $sql);
132
133 2
            return 0;
134
        }
135
136 3
        $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? (y/n)';
137
138 3
        if (! $migratorConfiguration->isDryRun() && ! $this->canExecute($question, $input, $output)) {
139 1
            $output->writeln('<error>Migration cancelled!</error>');
140
141 1
            return 1;
142
        }
143
144 2
        $this->getDependencyFactory()->getMetadataStorage()->ensureInitialized();
145 2
        $migrator->migrate($plan, $migratorConfiguration);
146
147 2
        return 0;
148
    }
149
}
150