Failed Conditions
Pull Request — 2.10.x (#4011)
by
unknown
03:07
created

ReservedWordsCommand::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 9
ccs 0
cts 8
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
namespace Doctrine\DBAL\Tools\Console\Command;
4
5
use Doctrine\DBAL\Connection;
6
use Doctrine\DBAL\Platforms\Keywords\DB2Keywords;
7
use Doctrine\DBAL\Platforms\Keywords\MySQL57Keywords;
8
use Doctrine\DBAL\Platforms\Keywords\MySQL80Keywords;
9
use Doctrine\DBAL\Platforms\Keywords\MySQLKeywords;
10
use Doctrine\DBAL\Platforms\Keywords\OracleKeywords;
11
use Doctrine\DBAL\Platforms\Keywords\PostgreSQL91Keywords;
12
use Doctrine\DBAL\Platforms\Keywords\PostgreSQL92Keywords;
13
use Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords;
14
use Doctrine\DBAL\Platforms\Keywords\ReservedKeywordsValidator;
15
use Doctrine\DBAL\Platforms\Keywords\SQLAnywhere11Keywords;
16
use Doctrine\DBAL\Platforms\Keywords\SQLAnywhere12Keywords;
17
use Doctrine\DBAL\Platforms\Keywords\SQLAnywhere16Keywords;
18
use Doctrine\DBAL\Platforms\Keywords\SQLAnywhereKeywords;
19
use Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords;
20
use Doctrine\DBAL\Platforms\Keywords\SQLServer2005Keywords;
21
use Doctrine\DBAL\Platforms\Keywords\SQLServer2008Keywords;
22
use Doctrine\DBAL\Platforms\Keywords\SQLServer2012Keywords;
23
use Doctrine\DBAL\Platforms\Keywords\SQLServerKeywords;
24
use Doctrine\DBAL\Tools\Console\ConnectionProvider;
25
use Exception;
26
use InvalidArgumentException;
27
use Symfony\Component\Console\Command\Command;
28
use Symfony\Component\Console\Input\InputInterface;
29
use Symfony\Component\Console\Input\InputOption;
30
use Symfony\Component\Console\Output\OutputInterface;
31
use function array_keys;
32
use function assert;
33
use function count;
34
use function implode;
35
use function is_string;
36
use function trigger_error;
37
use const E_USER_DEPRECATED;
38
39
class ReservedWordsCommand extends Command
40
{
41
    /** @var string[] */
42
    private $keywordListClasses = [
43
        'mysql'         => MySQLKeywords::class,
44
        'mysql57'       => MySQL57Keywords::class,
45
        'mysql80'       => MySQL80Keywords::class,
46
        'sqlserver'     => SQLServerKeywords::class,
47
        'sqlserver2005' => SQLServer2005Keywords::class,
48
        'sqlserver2008' => SQLServer2008Keywords::class,
49
        'sqlserver2012' => SQLServer2012Keywords::class,
50
        'sqlite'        => SQLiteKeywords::class,
51
        'pgsql'         => PostgreSQLKeywords::class,
52
        'pgsql91'       => PostgreSQL91Keywords::class,
53
        'pgsql92'       => PostgreSQL92Keywords::class,
54
        'oracle'        => OracleKeywords::class,
55
        'db2'           => DB2Keywords::class,
56
        'sqlanywhere'   => SQLAnywhereKeywords::class,
57
        'sqlanywhere11' => SQLAnywhere11Keywords::class,
58
        'sqlanywhere12' => SQLAnywhere12Keywords::class,
59
        'sqlanywhere16' => SQLAnywhere16Keywords::class,
60
    ];
61
62
    /** @var ConnectionProvider|null */
63
    private $connectionProvider;
64
65
    public function __construct(?ConnectionProvider $connectionProvider = null)
66
    {
67
        parent::__construct();
68
        $this->connectionProvider = $connectionProvider;
69
        if ($connectionProvider !== null) {
70
            return;
71
        }
72
73
        @trigger_error('Not passing a connection provider as the first constructor argument is deprecated', E_USER_DEPRECATED);
74
    }
75
76
    /**
77
     * If you want to add or replace a keywords list use this command.
78
     *
79
     * @param string $name
80
     * @param string $class
81
     *
82
     * @return void
83
     */
84
    public function setKeywordListClass($name, $class)
85
    {
86
        $this->keywordListClasses[$name] = $class;
87
    }
88
89
    /** @return void */
90
    protected function configure()
91
    {
92
        $this
93
        ->setName('dbal:reserved-words')
94
        ->setDescription('Checks if the current database contains identifiers that are reserved.')
95
        ->setDefinition([
96
            new InputOption('connection', null, InputOption::VALUE_REQUIRED, 'The named database connection'),
97
            new InputOption(
98
                'list',
99
                'l',
100
                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
101
                'Keyword-List name.'
102
            ),
103
        ])
104
        ->setHelp(<<<EOT
105
Checks if the current database contains tables and columns
106
with names that are identifiers in this dialect or in other SQL dialects.
107
108
By default SQLite, MySQL, PostgreSQL, Microsoft SQL Server, Oracle
109
and SQL Anywhere keywords are checked:
110
111
    <info>%command.full_name%</info>
112
113
If you want to check against specific dialects you can
114
pass them to the command:
115
116
    <info>%command.full_name% -l mysql -l pgsql</info>
117
118
The following keyword lists are currently shipped with Doctrine:
119
120
    * mysql
121
    * mysql57
122
    * mysql80
123
    * pgsql
124
    * pgsql92
125
    * sqlite
126
    * oracle
127
    * sqlserver
128
    * sqlserver2005
129
    * sqlserver2008
130
    * sqlserver2012
131
    * sqlanywhere
132
    * sqlanywhere11
133
    * sqlanywhere12
134
    * sqlanywhere16
135
    * db2 (Not checked by default)
136
EOT
137
        );
138
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143
    protected function execute(InputInterface $input, OutputInterface $output)
144
    {
145
        $conn = $this->getConnection($input);
146
147
        $keywordLists = (array) $input->getOption('list');
148
        if (! $keywordLists) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $keywordLists of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
149
            $keywordLists = [
150
                'mysql',
151
                'mysql57',
152
                'mysql80',
153
                'pgsql',
154
                'pgsql92',
155
                'sqlite',
156
                'oracle',
157
                'sqlserver',
158
                'sqlserver2005',
159
                'sqlserver2008',
160
                'sqlserver2012',
161
                'sqlanywhere',
162
                'sqlanywhere11',
163
                'sqlanywhere12',
164
                'sqlanywhere16',
165
            ];
166
        }
167
168
        $keywords = [];
169
        foreach ($keywordLists as $keywordList) {
170
            if (! isset($this->keywordListClasses[$keywordList])) {
171
                throw new InvalidArgumentException(
172
                    "There exists no keyword list with name '" . $keywordList . "'. " .
173
                    'Known lists: ' . implode(', ', array_keys($this->keywordListClasses))
174
                );
175
            }
176
177
            $class      = $this->keywordListClasses[$keywordList];
178
            $keywords[] = new $class();
179
        }
180
181
        $output->write('Checking keyword violations for <comment>' . implode(', ', $keywordLists) . '</comment>...', true);
182
183
        $schema  = $conn->getSchemaManager()->createSchema();
184
        $visitor = new ReservedKeywordsValidator($keywords);
185
        $schema->visit($visitor);
186
187
        $violations = $visitor->getViolations();
188
        if (count($violations) !== 0) {
189
            $output->write('There are <error>' . count($violations) . '</error> reserved keyword violations in your database schema:', true);
190
            foreach ($violations as $violation) {
191
                $output->write('  - ' . $violation, true);
192
            }
193
194
            return 1;
195
        }
196
197
        $output->write('No reserved keywords violations have been found!', true);
198
199
        return 0;
200
    }
201
202
    private function getConnection(InputInterface $input) : Connection
203
    {
204
        $connectionName = $input->getOption('connection');
205
        assert(is_string($connectionName) || $connectionName === null);
206
207
        if ($this->connectionProvider === null) {
208
            if ($connectionName !== null) {
209
                throw new Exception('Specifying a connection is only supported when a ConnectionProvider is used.');
210
            }
211
212
            return $this->getHelper('db')->getConnection();
213
        }
214
215
        if ($connectionName !== null) {
216
            return $this->connectionProvider->getConnection($connectionName);
217
        }
218
219
        return $this->connectionProvider->getDefaultConnection();
220
    }
221
}
222