Passed
Push — master ( a08165...57ee5a )
by Dominik
02:04
created

DropDatabaseDoctrineCommand::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 5
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
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\DriverManager;
9
use Symfony\Component\Console\Input\InputInterface;
10
use Symfony\Component\Console\Input\InputOption;
11
use Symfony\Component\Console\Output\OutputInterface;
12
13
/**
14
 * @link https://github.com/doctrine/DoctrineBundle/blob/master/Command/DropDatabaseDoctrineCommand.php
15
 */
16
class DropDatabaseDoctrineCommand extends DoctrineCommand
17
{
18
    const RETURN_CODE_NOT_DROP = 1;
19
20
    const RETURN_CODE_NO_FORCE = 2;
21
22
    /**
23
     * @var ConnectionRegistry
24
     */
25
    private $connectionRegistry;
26
27
    /**
28
     * @param ConnectionRegistry $connectionRegistry
29
     */
30
    public function __construct(ConnectionRegistry $connectionRegistry)
31
    {
32
        parent::__construct();
33
34
        $this->connectionRegistry = $connectionRegistry;
35
    }
36
37
    protected function configure()
38
    {
39
        $this
40
            ->setName('doctrine:database:drop')
41
            ->setDescription('Drops the configured database')
42
            ->addOption('shard', null, InputOption::VALUE_REQUIRED, 'The shard connection to use for this command')
43
            ->addOption('connection', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command')
44
            ->addOption(
45
                'if-exists',
46
                null,
47
                InputOption::VALUE_NONE,
48
                'Don\'t trigger an error, when the database doesn\'t exist'
49
            )
50
            ->addOption('force', null, InputOption::VALUE_NONE, 'Set this parameter to execute this action')
51
            ->setHelp(<<<EOT
52
The <info>%command.name%</info> command drops the default connections database:
53
54
    <info>php %command.full_name%</info>
55
56
The <info>--force</info> parameter has to be used to actually drop the database.
57
58
You can also optionally specify the name of a connection to drop the database for:
59
60
    <info>php %command.full_name% --connection=default</info>
61
62
<error>Be careful: All data in a given database will be lost when executing this command.</error>
63
EOT
64
            );
65
    }
66
67
    /**
68
     * @param InputInterface  $input
69
     * @param OutputInterface $output
70
     *
71
     * @return int
72
     */
73
    protected function execute(InputInterface $input, OutputInterface $output): int
74
    {
75
        $connectionName = $input->getOption('connection');
76
        if (empty($connectionName)) {
77
            $connectionName = $this->connectionRegistry->getDefaultConnectionName();
78
        }
79
80
        $connection = $this->connectionRegistry->getConnection($connectionName);
81
82
        $ifExists = $input->getOption('if-exists');
83
84
        $params = $connection->getParams();
85
        if (isset($params['master'])) {
86
            $params = $params['master'];
87
        }
88
89
        if (isset($params['shards'])) {
90
            $shards = $params['shards'];
91
            // Default select global
92
            $params = array_merge($params, $params['global']);
93
            if ($input->getOption('shard')) {
94
                foreach ($shards as $shard) {
95
                    if ($shard['id'] === (int) $input->getOption('shard')) {
96
                        // Select sharded database
97
                        $params = $shard;
98
                        unset($params['id']);
99
                        break;
100
                    }
101
                }
102
            }
103
        }
104
105
        $name = isset($params['path']) ? $params['path'] : (isset($params['dbname']) ? $params['dbname'] : false);
106
        if (!$name) {
107
            throw new \InvalidArgumentException(
108
                'Connection does not contain a \'path\' or \'dbname\' parameter and cannot be dropped.'
109
            );
110
        }
111
112
        unset($params['dbname'], $params['url']);
113
114
        if (!$input->getOption('force')) {
115
            $output->writeln(
116
                '<error>ATTENTION:</error> This operation should not be executed in a production environment.'
117
            );
118
            $output->writeln('');
119
            $output->writeln(
120
                sprintf(
121
                    '<info>Would drop the database <comment>%s</comment> for connection'
122
                        .' named <comment>%s</comment>.</info>',
123
                    $name,
124
                    $connectionName
125
                )
126
            );
127
            $output->writeln('Please run the operation with --force to execute');
128
            $output->writeln('<error>All data will be lost!</error>');
129
130
            return self::RETURN_CODE_NO_FORCE;
131
        }
132
133
        // Reopen connection without database name set
134
        // as some vendors do not allow dropping the database connected to.
135
        $connection->close();
136
        $connection = DriverManager::getConnection($params);
137
        $shouldDropDatabase = !$ifExists || in_array($name, $connection->getSchemaManager()->listDatabases());
138
139
        // Only quote if we don't have a path
140
        if (!isset($params['path'])) {
141
            $name = $connection->getDatabasePlatform()->quoteSingleIdentifier($name);
142
        }
143
144
        try {
145
            if ($shouldDropDatabase) {
146
                $connection->getSchemaManager()->dropDatabase($name);
147
                $output->writeln(
148
                    sprintf(
149
                        '<info>Dropped database <comment>%s</comment> for connection'
150
                            .' named <comment>%s</comment></info>',
151
                        $name,
152
                        $connectionName
153
                    )
154
                );
155
            } else {
156
                $output->writeln(
157
                    sprintf(
158
                        '<info>Database <comment>%s</comment> for connection named <comment>%s</comment>'
159
                            .' doesn\'t exist. Skipped.</info>',
160
                        $name,
161
                        $connectionName
162
                    )
163
                );
164
            }
165
        } catch (\Exception $e) {
166
            $output->writeln(
167
                sprintf(
168
                    '<error>Could not drop database <comment>%s</comment> for connection'
169
                        .' named <comment>%s</comment></error>',
170
                    $name,
171
                    $connectionName
172
                )
173
            );
174
            $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
175
176
            return self::RETURN_CODE_NOT_DROP;
177
        }
178
179
        return 0;
180
    }
181
}
182