Completed
Push — master ( 6e739b...0f594c )
by Asmir
22s queued 12s
created

ExecuteCommand   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Test Coverage

Coverage 97.18%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 95
c 1
b 0
f 0
dl 0
loc 133
ccs 69
cts 71
cp 0.9718
rs 10
wmc 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
B configure() 0 73 1
B execute() 0 53 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 5
    protected function configure() : void
28
    {
29
        $this
30 5
            ->setAliases(['execute'])
31 5
            ->setDescription(
32 5
                'Execute one or more migration versions up or down manually.'
33
            )
34 5
            ->addArgument(
35 5
                'versions',
36 5
                InputArgument::REQUIRED|InputArgument::IS_ARRAY,
37 5
                'The versions to execute.',
38 5
                null
39
            )
40 5
            ->addOption(
41 5
                'write-sql',
42 5
                null,
43 5
                InputOption::VALUE_OPTIONAL,
44 5
                'The path to output the migration SQL file instead of executing it. Defaults to current working directory.',
45 5
                false
46
            )
47 5
            ->addOption(
48 5
                'dry-run',
49 5
                null,
50 5
                InputOption::VALUE_NONE,
51 5
                'Execute the migration as a dry run.'
52
            )
53 5
            ->addOption(
54 5
                'up',
55 5
                null,
56 5
                InputOption::VALUE_NONE,
57 5
                'Execute the migration up.'
58
            )
59 5
            ->addOption(
60 5
                'down',
61 5
                null,
62 5
                InputOption::VALUE_NONE,
63 5
                'Execute the migration down.'
64
            )
65 5
            ->addOption(
66 5
                'query-time',
67 5
                null,
68 5
                InputOption::VALUE_NONE,
69 5
                'Time all the queries individually.'
70
            )
71 5
            ->setHelp(<<<EOT
72 5
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 5
        parent::configure();
100 5
    }
101
102 5
    protected function execute(InputInterface $input, OutputInterface $output) : int
103
    {
104 5
        $migratorConfigurationFactory = $this->getDependencyFactory()->getConsoleInputMigratorConfigurationFactory();
105 5
        $migratorConfiguration        = $migratorConfigurationFactory->getMigratorConfiguration($input);
106
107 5
        $question = 'WARNING! You are about to execute a database migration that could result in schema changes and data loss. Are you sure you wish to continue?';
108 5
        if (! $migratorConfiguration->isDryRun() && ! $this->canExecute($question, $input)) {
109 1
            $this->io->error('Migration cancelled!');
110
111 1
            return 1;
112
        }
113
114 4
        $this->getDependencyFactory()->getMetadataStorage()->ensureInitialized();
115
116 4
        $versions  = $input->getArgument('versions');
117 4
        $path      = $input->getOption('write-sql');
118 4
        $direction = $input->getOption('down') !== false
119 4
            ? Direction::DOWN
120 4
            : Direction::UP;
121
122 4
        $migrator       = $this->getDependencyFactory()->getMigrator();
123 4
        $planCalculator = $this->getDependencyFactory()->getMigrationPlanCalculator();
124
        $plan           = $planCalculator->getPlanForVersions(array_map(static function (string $version) : Version {
125 4
            return new Version($version);
126 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

126
        }, /** @scrutinizer ignore-type */ $versions), $direction);
Loading history...
127
128 4
        if ($migratorConfiguration->isDryRun()) {
129 2
            $sql = $migrator->migrate($plan, $migratorConfiguration);
130
131 2
            $path = is_string($path) ? $path : getcwd();
132
133 2
            if (! is_string($path) || ! is_writable($path)) {
0 ignored issues
show
introduced by
The condition is_string($path) is always true.
Loading history...
134
                $this->io->error('Path not writeable!');
135
136
                return 1;
137
            }
138
139 2
            $writer = $this->getDependencyFactory()->getQueryWriter();
140 2
            $writer->write($path, $direction, $sql);
141
142 2
            return 0;
143
        }
144
145 2
        $this->getDependencyFactory()->getLogger()->notice(
146 2
            'Executing' . ($migratorConfiguration->isDryRun() ? ' (dry-run)' : '') . ' {versions} {direction}',
147
            [
148 2
                'direction' => $plan->getDirection(),
149 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

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