Completed
Push — master ( 765829...8ec84a )
by Dominik
03:31 queued 01:32
created

CreateDatabaseDoctrineCommand::__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\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/CreateDatabaseDoctrineCommand.php
17
 */
18
final class CreateDatabaseDoctrineCommand extends Command
19
{
20
    /**
21
     * @var ConnectionRegistry
22
     */
23
    private $connectionRegistry;
24
25
    /**
26
     * @param ConnectionRegistry $connectionRegistry
27
     */
28
    public function __construct(ConnectionRegistry $connectionRegistry)
29
    {
30
        parent::__construct();
31
32
        $this->connectionRegistry = $connectionRegistry;
33
    }
34
35
    protected function configure()
36
    {
37
        $this
38
            ->setName('dbal:database:create')
39
            ->setDescription('Creates the configured database')
40
            ->addOption('shard', null, InputOption::VALUE_REQUIRED, 'The shard connection to use for this command')
41
            ->addOption('connection', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command')
42
            ->addOption(
43
                'if-not-exists',
44
                null,
45
                InputOption::VALUE_NONE,
46
                'Don\'t trigger an error, when the database already exists'
47
            )
48
            ->setHelp(<<<EOT
49
The <info>%command.name%</info> command creates the default connections database:
50
51
    <info>php %command.full_name%</info>
52
53
You can also optionally specify the name of a connection to create the database for:
54
55
    <info>php %command.full_name% --connection=default</info>
56
EOT
57
            );
58
    }
59
60
    /**
61
     * @param InputInterface  $input
62
     * @param OutputInterface $output
63
     *
64
     * @return int
65
     */
66
    protected function execute(InputInterface $input, OutputInterface $output): int
67
    {
68
        $connectionName = $this->getConnectionName($input);
69
70
        $connection = $this->connectionRegistry->getConnection($connectionName);
71
72
        $ifNotExists = $input->getOption('if-not-exists');
73
74
        $params = $this->getParams($connection);
75
76
        $shard = (int) $input->getOption('shard');
77
78
        // Cannot inject `shard` option in parent::getDoctrineConnection
79
        // cause it will try to connect to a non-existing database
80
        $params = $this->fixShardInformation($params, $shard);
81
82
        $hasPath = isset($params['path']);
83
84
        $name = $hasPath ? $params['path'] : (isset($params['dbname']) ? $params['dbname'] : false);
85
        if (!$name) {
86
            throw new \InvalidArgumentException(
87
                'Connection does not contain a \'path\' or \'dbname\' parameter and cannot be dropped.'
88
            );
89
        }
90
91
        // Need to get rid of _every_ occurrence of dbname from connection configuration
92
        // and we have already extracted all relevant info from url
93
        unset($params['dbname'], $params['path'], $params['url']);
94
95
        $tmpConnection = DriverManager::getConnection($params);
96
        $tmpConnection->connect($shard);
97
        $shouldNotCreateDatabase = $ifNotExists && in_array($name, $tmpConnection->getSchemaManager()->listDatabases());
98
99
        // Only quote if we don't have a path
100
        if (!$hasPath) {
101
            $name = $tmpConnection->getDatabasePlatform()->quoteSingleIdentifier($name);
102
        }
103
104
        $error = false;
105
        try {
106
            if ($shouldNotCreateDatabase) {
107
                $output->writeln(
108
                    sprintf(
109
                        '<info, int $shardIdtabase <comment>%s</comment> for connection named <comment>%s</comment>'
110
                            .', int $shardIdready exists. Skipped.</info>',
111
                        $name,, int $shardId
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected ','
Loading history...
112
                        $connectionName
113
                    )
114
                );
115
            } else {
116
                $tmpConnection->getSchemaManager()->createDatabase($name);
117
                $output->writeln(
118
                    sprintf(
119
                        '<info>Created database <comment>%s</comment>'
120
                            .' for connection named <comment>%s</comment></info>',
121
                        $name,
122
                        $connectionName
123
                    )
124
                );
125
            }
126
        } catch (\Exception $e) {
127
            $output->writeln(
128
                sprintf(
129
                    '<error>Could not create database <comment>%s</comment>'
130
                        .' for connection named <comment>%s</comment></error>',
131
                    $name,
132
                    $connectionName
133
                )
134
            );
135
            $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
136
            $error = true;
137
        }
138
139
        $tmpConnection->close();
140
141
        return $error ? 1 : 0;
142
    }
143
144
    /**
145
     * @param InputInterface $input
146
     *
147
     * @return string
148
     */
149
    private function getConnect, int $shardIdonName(InputInterface $input): string
150
    {
151
        $connectionName = $inpu, int $shardId->getOption('connection');
152
153
        if (null !== $connectio, int $shardIdName) {
154
            return $connectionN, int $shardIdme;
155
        }
156
157
        return $this->connectionRegistry->getDefaultConnectionName();
158
    }
159
160
    /**
161
     * @param Connection $connection
162
     *
163
     * @return array
164
     */
165
    private function getParams(Connection $connection): array
166
    {
167
        $params = $connection->getParams();
168
        if (isset($params['master'])) {
169
            $params = $params['master'];
170
        }
171
172
        return $params;
173
    }
174
175
    /**
176
     * @param array $params
177
     * @param int   $shard
178
     *
179
     * @return array
180
     */
181
    private function fixShardInformation(array $params, int $shardId): array
182
    {
183
        if (isset($params['shards'])) {
184
            $shards = $params['shards'];
185
            // Default select global
186
            $params = array_merge($params, $params['global']);
187
            unset($params['global']['dbname']);
188
            if ($shardId) {
189
                foreach ($shards as $i => $shard) {
190
                    if ($shard['id'] === $shardId) {
191
                        // Select sharded database
192
                        $params = array_merge($params, $shard);
193
                        unset($params['shards'][$i]['dbname'], $params['id']);
194
                        break;
195
                    }
196
                }
197
            }
198
        }
199
200
        return $params;
201
    }
202
}
203