ReservedWordsCommand::configure()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 37
dl 0
loc 13
ccs 0
cts 13
cp 0
rs 9.328
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\DBAL\Tools\Console\Command;
6
7
use Doctrine\DBAL\Connection;
8
use Doctrine\DBAL\Platforms\Keywords\DB2Keywords;
9
use Doctrine\DBAL\Platforms\Keywords\MariaDb102Keywords;
10
use Doctrine\DBAL\Platforms\Keywords\MySQL57Keywords;
11
use Doctrine\DBAL\Platforms\Keywords\MySQL80Keywords;
12
use Doctrine\DBAL\Platforms\Keywords\MySQLKeywords;
13
use Doctrine\DBAL\Platforms\Keywords\OracleKeywords;
14
use Doctrine\DBAL\Platforms\Keywords\PostgreSQL100Keywords;
15
use Doctrine\DBAL\Platforms\Keywords\PostgreSQL94Keywords;
16
use Doctrine\DBAL\Platforms\Keywords\ReservedKeywordsValidator;
17
use Doctrine\DBAL\Platforms\Keywords\SQLAnywhere16Keywords;
18
use Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords;
19
use Doctrine\DBAL\Platforms\Keywords\SQLServer2012Keywords;
20
use InvalidArgumentException;
21
use Symfony\Component\Console\Command\Command;
22
use Symfony\Component\Console\Input\InputInterface;
23
use Symfony\Component\Console\Input\InputOption;
24
use Symfony\Component\Console\Output\OutputInterface;
25
use function array_keys;
26
use function assert;
27
use function count;
28
use function implode;
29
use function sprintf;
30
31
class ReservedWordsCommand extends Command
32
{
33
    /** @var array<string, string> */
34
    private $keywordListClasses = [
35
        'db2'           => DB2Keywords::class,
36
        'mysql'         => MySQLKeywords::class,
37
        'mysql57'       => MySQL57Keywords::class,
38
        'mysql80'       => MySQL80Keywords::class,
39
        'mariadb102'    => MariaDb102Keywords::class,
40
        'oracle'        => OracleKeywords::class,
41
        'pgsql'         => PostgreSQL94Keywords::class,
42
        'pgsql100'      => PostgreSQL100Keywords::class,
43
        'sqlanywhere'   => SQLAnywhere16Keywords::class,
44
        'sqlite'        => SQLiteKeywords::class,
45
        'sqlserver'     => SQLServer2012Keywords::class,
46
    ];
47
48
    /**
49
     * If you want to add or replace a keywords list use this command.
50
     */
51
    public function setKeywordListClass(string $name, string $class) : void
52
    {
53
        $this->keywordListClasses[$name] = $class;
54
    }
55
56
    protected function configure() : void
57
    {
58
        $this
59
        ->setName('dbal:reserved-words')
60
        ->setDescription('Checks if the current database contains identifiers that are reserved.')
61
        ->setDefinition([new InputOption(
62
            'list',
63
            'l',
64
            InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
65
            'Keyword-List name.'
66
        ),
67
        ])
68
        ->setHelp(<<<EOT
69
Checks if the current database contains tables and columns
70
with names that are identifiers in this dialect or in other SQL dialects.
71
72
By default SQLite, MySQL, PostgreSQL, Microsoft SQL Server, Oracle
73
and SQL Anywhere keywords are checked:
74
75
    <info>%command.full_name%</info>
76
77
If you want to check against specific dialects you can
78
pass them to the command:
79
80
    <info>%command.full_name% -l mysql -l pgsql</info>
81
82
The following keyword lists are currently shipped with Doctrine:
83
84
    * mysql
85
    * mysql57
86
    * mysql80
87
    * mariadb102
88
    * pgsql
89
    * pgsql100
90
    * sqlite
91
    * oracle
92
    * sqlserver
93
    * sqlserver2012
94
    * sqlanywhere
95
    * db2 (Not checked by default)
96
EOT
97
        );
98
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103
    protected function execute(InputInterface $input, OutputInterface $output)
104
    {
105
        $conn = $this->getHelper('db')->getConnection();
106
        assert($conn instanceof Connection);
107
108
        $keywordLists = (array) $input->getOption('list');
109
        if (count($keywordLists) === 0) {
110
            $keywordLists = array_keys($this->keywordListClasses);
111
        }
112
113
        $keywords = [];
114
        foreach ($keywordLists as $keywordList) {
115
            if (! isset($this->keywordListClasses[$keywordList])) {
116
                throw new InvalidArgumentException(sprintf(
117
                    'There exists no keyword list with name "%s". Known lists: %s',
118
                    $keywordList,
119
                    implode(', ', array_keys($this->keywordListClasses))
120
                ));
121
            }
122
123
            $class      = $this->keywordListClasses[$keywordList];
124
            $keywords[] = new $class();
125
        }
126
127
        $output->write('Checking keyword violations for <comment>' . implode(', ', $keywordLists) . '</comment>...', true);
128
129
        $schema  = $conn->getSchemaManager()->createSchema();
130
        $visitor = new ReservedKeywordsValidator($keywords);
131
        $schema->visit($visitor);
132
133
        $violations = $visitor->getViolations();
134
        if (count($violations) !== 0) {
135
            $output->write('There are <error>' . count($violations) . '</error> reserved keyword violations in your database schema:', true);
136
            foreach ($violations as $violation) {
137
                $output->write('  - ' . $violation, true);
138
            }
139
140
            return 1;
141
        }
142
143
        $output->write('No reserved keywords violations have been found!', true);
144
145
        return 0;
146
    }
147
}
148