Passed
Push — master ( c9bb3c...50c2c4 )
by Dominik
02:35
created

DropDatabaseDoctrineCommand::execute()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 34
ccs 17
cts 17
cp 1
rs 9.376
c 0
b 0
f 0
cc 4
nc 5
nop 2
crap 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chubbyphp\DoctrineDbServiceProvider\Command;
6
7
use Doctrine\Common\Persistence\ConnectionRegistry;
8
use Doctrine\DBAL\Connection;
9
use Doctrine\DBAL\DriverManager;
10
use Symfony\Component\Console\Command\Command;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Input\InputOption;
13
use Symfony\Component\Console\Output\OutputInterface;
14
15
/**
16
 * @see https://github.com/doctrine/DoctrineBundle/blob/master/Command/DropDatabaseDoctrineCommand.php
17
 */
18
final class DropDatabaseDoctrineCommand extends Command
19
{
20
    const RETURN_CODE_NOT_DROP = 1;
21
22
    const RETURN_CODE_NO_FORCE = 2;
23
24
    /**
25
     * @var ConnectionRegistry
26
     */
27
    private $connectionRegistry;
28
29
    /**
30
     * @param ConnectionRegistry $connectionRegistry
31
     */
32 6
    public function __construct(ConnectionRegistry $connectionRegistry)
33
    {
34 6
        parent::__construct();
35
36 6
        $this->connectionRegistry = $connectionRegistry;
37 6
    }
38
39 6
    protected function configure()
40
    {
41
        $this
42 6
            ->setName('dbal:database:drop')
43 6
            ->setDescription('Drops the configured database')
44 6
            ->addOption('connection', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command')
45 6
            ->addOption(
46 6
                'if-exists',
47 6
                null,
48 6
                InputOption::VALUE_NONE,
49 6
                'Don\'t trigger an error, when the database doesn\'t exist'
50
            )
51 6
            ->addOption('force', null, InputOption::VALUE_NONE, 'Set this parameter to execute this action')
52 6
            ->setHelp(<<<EOT
53 6
The <info>%command.name%</info> command drops the default connections database:
54
55
    <info>php %command.full_name%</info>
56
57
The <info>--force</info> parameter has to be used to actually drop the database.
58
59
You can also optionally specify the name of a connection to drop the database for:
60
61
    <info>php %command.full_name% --connection=default</info>
62
63
<error>Be careful: All data in a given database will be lost when executing this command.</error>
64
EOT
65
            );
66 6
    }
67
68
    /**
69
     * @param InputInterface  $input
70
     * @param OutputInterface $output
71
     *
72
     * @return int
73
     */
74 6
    protected function execute(InputInterface $input, OutputInterface $output): int
75
    {
76 6
        $connectionName = $this->getConnectionName($input);
77
78 6
        $connection = $this->connectionRegistry->getConnection($connectionName);
79
80 6
        $params = $this->getParams($connection);
81
82 6
        $dbName = $this->getDbName($params, $connectionName);
83
84 5
        if (!$input->getOption('force')) {
85 1
            $this->writeMissingForceOutput($output, $dbName, $connectionName);
86
87 1
            return self::RETURN_CODE_NO_FORCE;
88
        }
89
90 4
        $isPath = isset($params['path']);
91
92 4
        $ifExists = $input->getOption('if-exists');
93
94
        // Need to get rid of _every_ occurrence of dbname from connection configuration
95 4
        unset($params['dbname'], $params['path'], $params['url']);
96
97 4
        $connection->close();
98 4
        $connection = DriverManager::getConnection($params);
99 4
        $shouldDropDatabase = !$ifExists || in_array($dbName, $connection->getSchemaManager()->listDatabases());
100
101
        // Only quote if we don't have a path
102 4
        if (!$isPath) {
103 3
            $dbName = $connection->getDatabasePlatform()->quoteSingleIdentifier($dbName);
104
        }
105
106 4
        return $this->dropDatabase($output, $connectionName, $connection, $dbName, $shouldDropDatabase);
107
    }
108
109
    /**
110
     * @param InputInterface $input
111
     *
112
     * @return string
113
     */
114 6 View Code Duplication
    private function getConnectionName(InputInterface $input): string
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
115
    {
116 6
        $connectionName = $input->getOption('connection');
117
118 6
        if (null !== $connectionName) {
119 3
            return $connectionName;
120
        }
121
122 3
        return $this->connectionRegistry->getDefaultConnectionName();
123
    }
124
125
    /**
126
     * @param Connection $connection
127
     *
128
     * @return array
129
     */
130 6 View Code Duplication
    private function getParams(Connection $connection): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
131
    {
132 6
        $params = $connection->getParams();
133 6
        if (isset($params['master'])) {
134 3
            $params = $params['master'];
135
        }
136
137 6
        return $params;
138
    }
139
140
    /**
141
     * @param array  $params
142
     * @param string $connectionName
143
     *
144
     * @return string
145
     */
146 6 View Code Duplication
    private function getDbName(array $params, string $connectionName): string
0 ignored issues
show
Unused Code introduced by
The parameter $connectionName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
147
    {
148 6
        if (isset($params['path'])) {
149 2
            return $params['path'];
150
        }
151
152 4
        if (isset($params['dbname'])) {
153 3
            return $params['dbname'];
154
        }
155
156 1
        throw new \InvalidArgumentException('Connection does not contain a \'path\' or \'dbname\' parameter.');
157
    }
158
159
    /**
160
     * @param OutputInterface $output
161
     * @param string          $dbName
162
     * @param string          $connectionName
163
     */
164 1
    private function writeMissingForceOutput(OutputInterface $output, string $dbName, string $connectionName)
165
    {
166 1
        $output->writeln(
167 1
            '<error>ATTENTION:</error> This operation should not be executed in a production environment.'
168
        );
169 1
        $output->writeln('');
170 1
        $output->writeln(
171 1
            sprintf(
172
                '<info>Would drop the database <comment>%s</comment> for connection'
173 1
                    .' named <comment>%s</comment>.</info>',
174 1
                $dbName,
175 1
                $connectionName
176
            )
177
        );
178 1
        $output->writeln('Please run the operation with --force to execute');
179 1
        $output->writeln('<error>All data will be lost!</error>');
180 1
    }
181
182
    /**
183
     * @param OutputInterface $output
184
     * @param string          $connectionName
185
     * @param Connection      $connection
186
     * @param string          $dbName
187
     * @param bool            $shouldNotCreateDatabase
0 ignored issues
show
Bug introduced by
There is no parameter named $shouldNotCreateDatabase. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
188
     *
189
     * @return int
190
     */
191 4 View Code Duplication
    private function dropDatabase(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
192
        OutputInterface $output,
193
        string $connectionName,
194
        Connection $connection,
195
        string $dbName,
196
        bool $shouldDropDatabase
197
    ): int {
198
        try {
199 4
            if ($shouldDropDatabase) {
200 3
                $connection->getSchemaManager()->dropDatabase($dbName);
201 2
                $output->writeln(
202 2
                    sprintf(
203
                        '<info>Dropped database <comment>%s</comment> for connection'
204 2
                            .' named <comment>%s</comment>.</info>',
205 2
                        $dbName,
206 2
                        $connectionName
207
                    )
208
                );
209
            } else {
210 1
                $output->writeln(
211 1
                    sprintf(
212
                        '<info>Database <comment>%s</comment> for connection named <comment>%s</comment>'
213 1
                            .' doesn\'t exist. Skipped.</info>',
214 1
                        $dbName,
215 3
                        $connectionName
216
                    )
217
                );
218
            }
219 1
        } catch (\Exception $e) {
220 1
            $output->writeln(
221 1
                sprintf(
222
                    '<error>Could not drop database <comment>%s</comment> for connection'
223 1
                        .' named <comment>%s</comment>.</error>',
224 1
                    $dbName,
225 1
                    $connectionName
226
                )
227
            );
228 1
            $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
229
230 1
            return self::RETURN_CODE_NOT_DROP;
231
        }
232
233 3
        return 0;
234
    }
235
}
236