Completed
Branch 09branch (1772ab)
by Anton
02:55
created

DescribeCommand::describeIndexes()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 2
nop 2
dl 0
loc 16
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
namespace Spiral\Commands\Database;
9
10
use Spiral\Console\Command;
11
use Spiral\Database\DatabaseManager;
12
use Spiral\Database\Entities\Database;
13
use Spiral\Database\Exceptions\DatabaseException;
14
use Spiral\Database\Injections\FragmentInterface;
15
use Spiral\Database\Schemas\Prototypes\AbstractTable;
16
use Symfony\Component\Console\Input\InputArgument;
17
use Symfony\Component\Console\Input\InputOption;
18
19
/**
20
 * Describe schema of specific table.
21
 */
22
class DescribeCommand extends Command
23
{
24
    /**
25
     * No information available placeholder.
26
     */
27
    const SKIP = '<comment>---</comment>';
28
29
    /**
30
     * {@inheritdoc}
31
     */
32
    const NAME = 'db:describe';
33
34
    /**
35
     * {@inheritdoc}
36
     */
37
    const DESCRIPTION = 'Describe table schema of specific database';
38
39
    /**
40
     * {@inheritdoc}
41
     */
42
    const ARGUMENTS = [
43
        ['table', InputArgument::REQUIRED, 'Table name']
44
    ];
45
46
    /**
47
     * {@inheritdoc}
48
     */
49
    const OPTIONS = [
50
        ['database', 'db', InputOption::VALUE_OPTIONAL, 'Source database', 'default'],
51
    ];
52
53
    /**
54
     * @param DatabaseManager $dbal
55
     */
56
    public function perform(DatabaseManager $dbal)
57
    {
58
        //Database
59
        $database = $dbal->database($this->option('database'));
60
61
        //Database schema
62
        $schema = $database->table($this->argument('table'))->getSchema();
63
64
        if (!$schema->exists()) {
65
            throw new DatabaseException(
66
                "Table {$database->getName()}.{$this->argument('table')} does not exists."
67
            );
68
        }
69
70
        $this->writeln(
71
            "Columns of <comment>{$database->getName()}.{$this->argument('table')}</comment>:"
72
        );
73
74
        $this->describeColumns($schema);
75
76
        if (!empty($indexes = $schema->getIndexes())) {
77
            $this->describeIndexes($database, $indexes);
78
        }
79
80
        if (!empty($foreigns = $schema->getForeigns())) {
81
            $this->describeForeigns($database, $foreigns);
82
        }
83
    }
84
85
    /**
86
     * @param AbstractTable $schema
87
     */
88
    protected function describeColumns(AbstractTable $schema)
89
    {
90
        $columnsTable = $this->table([
91
            'Column:',
92
            'Database Type:',
93
            'Abstract Type:',
94
            'PHP Type:',
95
            'Default Value:'
96
        ]);
97
98
        foreach ($schema->getColumns() as $column) {
99
            $name = $column->getName();
100
            $type = $column->getType();
101
102
            $abstractType = $column->abstractType();
103
            $defaultValue = $column->getDefaultValue();
104
105
            if ($column->getSize()) {
106
                $type .= " ({$column->getSize()})";
107
            }
108
109
            if ($column->abstractType() == 'decimal') {
110
                $type .= " ({$column->getPrecision()}, {$column->getScale()})";
111
            }
112
113
            if (in_array($column->getName(), $schema->getPrimaryKeys())) {
114
                $name = "<fg=magenta>{$name}</fg=magenta>";
115
            }
116
117
            if (in_array($abstractType, ['primary', 'bigPrimary'])) {
118
                $abstractType = "<fg=magenta>{$abstractType}</fg=magenta>";
119
            }
120
121
            if ($defaultValue instanceof FragmentInterface) {
122
                $defaultValue = "<info>{$defaultValue}</info>";
123
            }
124
125
            if ($defaultValue instanceof \DateTimeInterface) {
126
                $defaultValue = $defaultValue->format('c');
127
            }
128
129
            $columnsTable->addRow([
130
                $name,
131
                $type,
132
                $abstractType,
133
                $column->phpType(),
134
                $defaultValue ?: self::SKIP
135
            ]);
136
        }
137
138
        $columnsTable->render();
139
    }
140
141
    /**
142
     * @param Database $database
143
     * @param array    $indexes
144
     */
145
    protected function describeIndexes(Database $database, array $indexes)
146
    {
147
        $this->writeln(
148
            "\nIndexes of <comment>{$database->getName()}.{$this->argument('table')}</comment>:"
149
        );
150
151
        $indexesTable = $this->table(['Name:', 'Type:', 'Columns:']);
152
        foreach ($indexes as $index) {
153
            $indexesTable->addRow([
154
                $index->getName(),
155
                $index->isUnique() ? 'UNIQUE INDEX' : 'INDEX',
156
                join(", ", $index->getColumns())
157
            ]);
158
        }
159
        $indexesTable->render();
160
    }
161
162
    /**
163
     * @param Database $database
164
     * @param array    $foreigns
165
     */
166
    protected function describeForeigns(Database $database, array $foreigns)
167
    {
168
        $this->writeln(
169
            "\nForeign keys of <comment>{$database->getName()}.{$this->argument('table')}</comment>:"
170
        );
171
172
        $foreignsTable = $this->table([
173
            'Name:',
174
            'Column:',
175
            'Foreign Table:',
176
            'Foreign Column:',
177
            'On Delete:',
178
            'On Update:'
179
        ]);
180
181
        foreach ($foreigns as $reference) {
182
            $foreignsTable->addRow([
183
                $reference->getName(),
184
                $reference->getColumn(),
185
                $reference->getForeignTable(),
186
                $reference->getForeignKey(),
187
                $reference->getDeleteRule(),
188
                $reference->getUpdateRule()
189
            ]);
190
        }
191
192
        $foreignsTable->render();
193
    }
194
}