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\Output\OutputInterface; |
13
|
|
|
use Symfony\Component\Console\Input\InputOption; |
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
|
5 |
|
public function __construct(ConnectionRegistry $connectionRegistry) |
29
|
|
|
{ |
30
|
5 |
|
parent::__construct(); |
31
|
|
|
|
32
|
5 |
|
$this->connectionRegistry = $connectionRegistry; |
33
|
5 |
|
} |
34
|
|
|
|
35
|
5 |
|
protected function configure() |
36
|
|
|
{ |
37
|
|
|
$this |
38
|
5 |
|
->setName('dbal:database:create') |
39
|
5 |
|
->setDescription('Creates the configured database') |
40
|
5 |
|
->addOption('connection', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command') |
41
|
5 |
|
->addOption( |
42
|
5 |
|
'if-not-exists', |
43
|
5 |
|
null, |
44
|
5 |
|
InputOption::VALUE_NONE, |
45
|
5 |
|
'Don\'t trigger an error, when the database already exists' |
46
|
|
|
) |
47
|
5 |
|
->setHelp(<<<EOT |
48
|
5 |
|
The <info>%command.name%</info> command creates the default connections database: |
49
|
|
|
|
50
|
|
|
<info>php %command.full_name%</info> |
51
|
|
|
|
52
|
|
|
You can also optionally specify the name of a connection to create the database for: |
53
|
|
|
|
54
|
|
|
<info>php %command.full_name% --connection=default</info> |
55
|
|
|
EOT |
56
|
|
|
); |
57
|
5 |
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* @param InputInterface $input |
61
|
|
|
* @param OutputInterface $output |
62
|
|
|
* |
63
|
|
|
* @return int |
64
|
|
|
*/ |
65
|
5 |
|
protected function execute(InputInterface $input, OutputInterface $output): int |
66
|
|
|
{ |
67
|
5 |
|
$connectionName = $this->getConnectionName($input); |
68
|
|
|
|
69
|
5 |
|
$connection = $this->connectionRegistry->getConnection($connectionName); |
70
|
|
|
|
71
|
5 |
|
$params = $this->getParams($connection); |
72
|
|
|
|
73
|
5 |
|
$dbName = $this->getDbName($params, $connectionName); |
74
|
|
|
|
75
|
4 |
|
$isPath = isset($params['path']); |
76
|
|
|
|
77
|
|
|
// Need to get rid of _every_ occurrence of dbname from connection configuration |
78
|
4 |
|
unset($params['dbname'], $params['path'], $params['url']); |
79
|
|
|
|
80
|
4 |
|
$ifNotExists = $input->getOption('if-not-exists'); |
81
|
|
|
|
82
|
4 |
|
$tmpConnection = DriverManager::getConnection($params); |
83
|
4 |
|
$shouldNotCreateDatabase = $ifNotExists && in_array($dbName, $tmpConnection->getSchemaManager()->listDatabases()); |
84
|
|
|
|
85
|
|
|
// Only quote if we don't have a path |
86
|
3 |
|
if (!$isPath) { |
87
|
2 |
|
$dbName = $tmpConnection->getDatabasePlatform()->quoteSingleIdentifier($dbName); |
88
|
|
|
} |
89
|
|
|
|
90
|
1 |
|
return $this->createDatabase($output, $connectionName, $tmpConnection, $dbName, $shouldNotCreateDatabase); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* @param InputInterface $input |
95
|
|
|
* |
96
|
|
|
* @return string |
97
|
|
|
*/ |
98
|
5 |
View Code Duplication |
private function getConnectionName(InputInterface $input): string |
|
|
|
|
99
|
|
|
{ |
100
|
5 |
|
$connectionName = $input->getOption('connection'); |
101
|
|
|
|
102
|
5 |
|
if (null !== $connectionName) { |
103
|
3 |
|
return $connectionName; |
104
|
|
|
} |
105
|
|
|
|
106
|
2 |
|
return $this->connectionRegistry->getDefaultConnectionName(); |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* @param Connection $connection |
111
|
|
|
* |
112
|
|
|
* @return array |
113
|
|
|
*/ |
114
|
5 |
View Code Duplication |
private function getParams(Connection $connection): array |
|
|
|
|
115
|
|
|
{ |
116
|
5 |
|
$params = $connection->getParams(); |
117
|
5 |
|
if (isset($params['master'])) { |
118
|
3 |
|
$params = $params['master']; |
119
|
|
|
} |
120
|
|
|
|
121
|
5 |
|
return $params; |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* @param array $params |
126
|
|
|
* @param string $connectionName |
127
|
|
|
* |
128
|
|
|
* @return string |
129
|
|
|
*/ |
130
|
5 |
|
private function getDbName(array $params, string $connectionName): string |
|
|
|
|
131
|
|
|
{ |
132
|
5 |
|
if (isset($params['path'])) { |
133
|
1 |
|
return $params['path']; |
134
|
|
|
} |
135
|
|
|
|
136
|
4 |
|
if (isset($params['dbname'])) { |
137
|
3 |
|
return $params['dbname']; |
138
|
|
|
} |
139
|
|
|
|
140
|
1 |
|
throw new \InvalidArgumentException('Connection does not contain a \'path\' or \'dbname\' parameter.'); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* @param OutputInterface $output |
145
|
|
|
* @param string $connectionName |
146
|
|
|
* @param Connection $tmpConnection |
147
|
|
|
* @param string $dbName |
148
|
|
|
* @param bool $shouldNotCreateDatabase |
149
|
|
|
* |
150
|
|
|
* @return int |
151
|
|
|
*/ |
152
|
1 |
|
private function createDatabase( |
153
|
|
|
OutputInterface $output, |
154
|
|
|
string $connectionName, |
155
|
|
|
Connection $tmpConnection, |
156
|
|
|
string $dbName, |
157
|
|
|
bool $shouldNotCreateDatabase |
158
|
|
|
): int { |
159
|
|
|
try { |
160
|
1 |
|
if ($shouldNotCreateDatabase) { |
161
|
|
|
$output->writeln( |
162
|
|
|
sprintf( |
163
|
|
|
'<info>Database <comment>%s</comment> for connection named <comment>%s</comment>' |
164
|
|
|
.' already exists. Skipped.</info>', |
165
|
|
|
$dbName, |
166
|
|
|
$connectionName |
167
|
|
|
) |
168
|
|
|
); |
169
|
|
|
} else { |
170
|
1 |
|
$tmpConnection->getSchemaManager()->createDatabase($dbName); |
171
|
1 |
|
$output->writeln( |
172
|
1 |
|
sprintf( |
173
|
|
|
'<info>Created database <comment>%s</comment>' |
174
|
1 |
|
.' for connection named <comment>%s</comment>.</info>', |
175
|
1 |
|
$dbName, |
176
|
1 |
|
$connectionName |
177
|
|
|
) |
178
|
|
|
); |
179
|
|
|
} |
180
|
|
|
|
181
|
1 |
|
return 0; |
182
|
|
|
} catch (\Exception $e) { |
183
|
|
|
$output->writeln(sprintf('<error>Could not create database <comment>%s</comment>.</error>', $dbName)); |
184
|
|
|
$output->writeln(sprintf('<error>%s</error>', $e->getMessage())); |
185
|
|
|
|
186
|
|
|
return 1; |
187
|
|
|
} |
188
|
|
|
} |
189
|
|
|
} |
190
|
|
|
|
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.