Passed
Pull Request — master (#948)
by Asmir
02:19
created

DiffCommand::execute()   B

Complexity

Conditions 10
Paths 19

Size

Total Lines 74
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 40
CRAP Score 10.4632

Importance

Changes 0
Metric Value
cc 10
eloc 48
nc 19
nop 2
dl 0
loc 74
ccs 40
cts 48
cp 0.8333
crap 10.4632
rs 7.2678
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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
declare(strict_types=1);
4
5
namespace Doctrine\Migrations\Tools\Console\Command;
6
7
use Doctrine\Migrations\Generator\Exception\NoChangesDetected;
8
use Doctrine\Migrations\Metadata\AvailableMigrationsList;
9
use Doctrine\Migrations\Metadata\ExecutedMigrationsSet;
10
use Doctrine\Migrations\Tools\Console\Exception\InvalidOptionUsage;
11
use OutOfBoundsException;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Input\InputOption;
14
use Symfony\Component\Console\Output\OutputInterface;
15
use function addslashes;
16
use function assert;
17
use function class_exists;
18
use function count;
19
use function filter_var;
20
use function is_string;
21
use function key;
22
use function sprintf;
23
use const FILTER_VALIDATE_BOOLEAN;
24
25
/**
26
 * The DiffCommand class is responsible for generating a migration by comparing your current database schema to
27
 * your mapping information.
28
 */
29
final class DiffCommand extends DoctrineCommand
30
{
31
    /** @var string */
32
    protected static $defaultName = 'migrations:diff';
33
34 3
    protected function configure() : void
35
    {
36 3
        parent::configure();
37
38
        $this
39 3
            ->setAliases(['diff'])
40 3
            ->setDescription('Generate a migration by comparing your current database to your mapping information.')
41 3
            ->setHelp(<<<EOT
42 3
The <info>%command.name%</info> command generates a migration by comparing your current database to your mapping information:
43
44
    <info>%command.full_name%</info>
45
46
EOT
47
            )
48 3
            ->addOption(
49 3
                'namespace',
50 3
                null,
51 3
                InputOption::VALUE_REQUIRED,
52 3
                'The namespace to use for the migration (must be in the list of configured namespaces)'
53
            )
54 3
            ->addOption(
55 3
                'filter-expression',
56 3
                null,
57 3
                InputOption::VALUE_REQUIRED,
58 3
                'Tables which are filtered by Regular Expression.'
59
            )
60 3
            ->addOption(
61 3
                'formatted',
62 3
                null,
63 3
                InputOption::VALUE_NONE,
64 3
                'Format the generated SQL.'
65
            )
66 3
            ->addOption(
67 3
                'line-length',
68 3
                null,
69 3
                InputOption::VALUE_REQUIRED,
70 3
                'Max line length of unformatted lines.',
71 3
                120
72
            )
73 3
            ->addOption(
74 3
                'check-database-platform',
75 3
                null,
76 3
                InputOption::VALUE_OPTIONAL,
77 3
                'Check Database Platform to the generated code.',
78 3
                false
79
            )
80 3
            ->addOption(
81 3
                'allow-empty-diff',
82 3
                null,
83 3
                InputOption::VALUE_NONE,
84 3
                'Do not throw an exception when no changes are detected.'
85
            );
86 3
    }
87
88
    /**
89
     * @throws InvalidOptionUsage
90
     */
91 3
    protected function execute(InputInterface $input, OutputInterface $output) : ?int
92
    {
93 3
        $filterExpression = (string) $input->getOption('filter-expression') ?: null;
94 3
        $formatted        = filter_var($input->getOption('formatted'), FILTER_VALIDATE_BOOLEAN);
95 3
        $lineLength       = (int) $input->getOption('line-length');
96 3
        $allowEmptyDiff   = $input->getOption('allow-empty-diff');
97 3
        $checkDbPlatform  = filter_var($input->getOption('check-database-platform'), FILTER_VALIDATE_BOOLEAN);
98 3
        $namespace        = $input->getOption('namespace') ?: null;
99 3
        if ($formatted) {
100 1
            if (! class_exists('SqlFormatter')) {
101
                throw InvalidOptionUsage::new(
102
                    'The "--formatted" option can only be used if the sql formatter is installed. Please run "composer require jdorn/sql-formatter".'
103
                );
104
            }
105
        }
106
107 3
        $configuration = $this->getDependencyFactory()->getConfiguration();
108
109 3
        $dirs = $configuration->getMigrationDirectories();
110 3
        if ($namespace === null) {
111 2
            $namespace = key($dirs);
112 1
        } elseif (! isset($dirs[$namespace])) {
113
            throw new OutOfBoundsException(sprintf('Path not defined for the namespace %s', $namespace));
114
        }
115
116 3
        assert(is_string($namespace));
117
118 3
        $statusCalculator              = $this->getDependencyFactory()->getMigrationStatusCalculator();
119 3
        $executedUnavailableMigrations = $statusCalculator->getExecutedUnavailableMigrations();
120 3
        $newMigrations                 = $statusCalculator->getNewMigrations();
121
122 3
        if ($this->checkNewMigrationsOrExecutedUnavailable($newMigrations, $executedUnavailableMigrations, $input, $output) === false) {
123 2
            $output->writeln('<error>Migration cancelled!</error>');
124
125 2
            return 3;
126
        }
127
128 1
        $fqcn = $this->getDependencyFactory()->getClassNameGenerator()->generateClassName($namespace);
129
130 1
        $diffGenerator = $this->getDependencyFactory()->getDiffGenerator();
131
132
        try {
133 1
            $path = $diffGenerator->generate(
134 1
                $fqcn,
135 1
                $filterExpression,
136 1
                $formatted,
137 1
                $lineLength,
138 1
                $checkDbPlatform
139
            );
140
        } catch (NoChangesDetected $exception) {
141
            if ($allowEmptyDiff) {
142
                $output->writeln($exception->getMessage());
143
144
                return 0;
145
            }
146
147
            throw $exception;
148
        }
149
150 1
        $output->writeln([
151 1
            sprintf('Generated new migration class to "<info>%s</info>"', $path),
152 1
            '',
153 1
            sprintf(
154 1
                'To run just this migration for testing purposes, you can use <info>migrations:execute --up \'%s\'</info>',
155 1
                addslashes($fqcn)
156
            ),
157 1
            '',
158 1
            sprintf(
159 1
                'To revert the migration you can use <info>migrations:execute --down \'%s\'</info>',
160 1
                addslashes($fqcn)
161
            ),
162
        ]);
163
164 1
        return 0;
165
    }
166
167 3
    private function checkNewMigrationsOrExecutedUnavailable(
168
        AvailableMigrationsList $newMigrations,
169
        ExecutedMigrationsSet $executedUnavailableMigrations,
170
        InputInterface $input,
171
        OutputInterface $output
172
    ) : bool {
173 3
        if (count($newMigrations) === 0 && count($executedUnavailableMigrations) === 0) {
174 1
            return true;
175
        }
176
177 2
        if (count($newMigrations) !== 0) {
178 2
            $output->writeln(sprintf(
179 2
                '<error>WARNING! You have %s available migrations to execute.</error>',
180 2
                count($newMigrations)
181
            ));
182
        }
183
184 2
        if (count($executedUnavailableMigrations) !== 0) {
185 1
            $output->writeln(sprintf(
186 1
                '<error>WARNING! You have %s previously executed migrations in the database that are not registered migrations.</error>',
187 1
                count($executedUnavailableMigrations)
188
            ));
189
        }
190
191 2
        return $this->canExecute('Are you sure you wish to continue? (y/n)', $input, $output);
192
    }
193
}
194