Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Database\Console;
4
 
5
use Doctrine\DBAL\Schema\Column;
6
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
7
use Doctrine\DBAL\Schema\Index;
8
use Doctrine\DBAL\Schema\Table;
9
use Illuminate\Database\ConnectionResolverInterface;
10
use Illuminate\Support\Str;
11
use Symfony\Component\Console\Attribute\AsCommand;
12
 
13
#[AsCommand(name: 'db:table')]
14
class TableCommand extends DatabaseInspectionCommand
15
{
16
    /**
17
     * The name and signature of the console command.
18
     *
19
     * @var string
20
     */
21
    protected $signature = 'db:table
22
                            {table? : The name of the table}
23
                            {--database= : The database connection}
24
                            {--json : Output the table information as JSON}';
25
 
26
    /**
27
     * The console command description.
28
     *
29
     * @var string
30
     */
31
    protected $description = 'Display information about the given database table';
32
 
33
    /**
34
     * Execute the console command.
35
     *
36
     * @return int
37
     */
38
    public function handle(ConnectionResolverInterface $connections)
39
    {
40
        if (! $this->ensureDependenciesExist()) {
41
            return 1;
42
        }
43
 
44
        $connection = $connections->connection($this->input->getOption('database'));
45
 
46
        $schema = $connection->getDoctrineSchemaManager();
47
 
48
        $this->registerTypeMappings($schema->getDatabasePlatform());
49
 
50
        $table = $this->argument('table') ?: $this->components->choice(
51
            'Which table would you like to inspect?',
52
            collect($schema->listTables())->flatMap(fn (Table $table) => [$table->getName()])->toArray()
53
        );
54
 
55
        if (! $schema->tablesExist([$table])) {
56
            return $this->components->warn("Table [{$table}] doesn't exist.");
57
        }
58
 
59
        $table = $schema->listTableDetails($table);
60
 
61
        $columns = $this->columns($table);
62
        $indexes = $this->indexes($table);
63
        $foreignKeys = $this->foreignKeys($table);
64
 
65
        $data = [
66
            'table' => [
67
                'name' => $table->getName(),
68
                'columns' => $columns->count(),
69
                'size' => $this->getTableSize($connection, $table->getName()),
70
            ],
71
            'columns' => $columns,
72
            'indexes' => $indexes,
73
            'foreign_keys' => $foreignKeys,
74
        ];
75
 
76
        $this->display($data);
77
 
78
        return 0;
79
    }
80
 
81
    /**
82
     * Get the information regarding the table's columns.
83
     *
84
     * @param  \Doctrine\DBAL\Schema\Table  $table
85
     * @return \Illuminate\Support\Collection
86
     */
87
    protected function columns(Table $table)
88
    {
89
        return collect($table->getColumns())->map(fn (Column $column) => [
90
            'column' => $column->getName(),
91
            'attributes' => $this->getAttributesForColumn($column),
92
            'default' => $column->getDefault(),
93
            'type' => $column->getType()->getName(),
94
        ]);
95
    }
96
 
97
    /**
98
     * Get the attributes for a table column.
99
     *
100
     * @param  \Doctrine\DBAL\Schema\Column  $column
101
     * @return \Illuminate\Support\Collection
102
     */
103
    protected function getAttributesForColumn(Column $column)
104
    {
105
        return collect([
106
            $column->getAutoincrement() ? 'autoincrement' : null,
107
            'type' => $column->getType()->getName(),
108
            $column->getUnsigned() ? 'unsigned' : null,
109
            ! $column->getNotNull() ? 'nullable' : null,
110
        ])->filter();
111
    }
112
 
113
    /**
114
     * Get the information regarding the table's indexes.
115
     *
116
     * @param  \Doctrine\DBAL\Schema\Table  $table
117
     * @return \Illuminate\Support\Collection
118
     */
119
    protected function indexes(Table $table)
120
    {
121
        return collect($table->getIndexes())->map(fn (Index $index) => [
122
            'name' => $index->getName(),
123
            'columns' => collect($index->getColumns()),
124
            'attributes' => $this->getAttributesForIndex($index),
125
        ]);
126
    }
127
 
128
    /**
129
     * Get the attributes for a table index.
130
     *
131
     * @param  \Doctrine\DBAL\Schema\Index  $index
132
     * @return \Illuminate\Support\Collection
133
     */
134
    protected function getAttributesForIndex(Index $index)
135
    {
136
        return collect([
137
            'compound' => count($index->getColumns()) > 1,
138
            'unique' => $index->isUnique(),
139
            'primary' => $index->isPrimary(),
140
        ])->filter()->keys()->map(fn ($attribute) => Str::lower($attribute));
141
    }
142
 
143
    /**
144
     * Get the information regarding the table's foreign keys.
145
     *
146
     * @param  \Doctrine\DBAL\Schema\Table  $table
147
     * @return \Illuminate\Support\Collection
148
     */
149
    protected function foreignKeys(Table $table)
150
    {
151
        return collect($table->getForeignKeys())->map(fn (ForeignKeyConstraint $foreignKey) => [
152
            'name' => $foreignKey->getName(),
153
            'local_table' => $table->getName(),
154
            'local_columns' => collect($foreignKey->getLocalColumns()),
155
            'foreign_table' => $foreignKey->getForeignTableName(),
156
            'foreign_columns' => collect($foreignKey->getForeignColumns()),
157
            'on_update' => Str::lower(rescue(fn () => $foreignKey->getOption('onUpdate'), 'N/A')),
158
            'on_delete' => Str::lower(rescue(fn () => $foreignKey->getOption('onDelete'), 'N/A')),
159
        ]);
160
    }
161
 
162
    /**
163
     * Render the table information.
164
     *
165
     * @param  array  $data
166
     * @return void
167
     */
168
    protected function display(array $data)
169
    {
170
        $this->option('json') ? $this->displayJson($data) : $this->displayForCli($data);
171
    }
172
 
173
    /**
174
     * Render the table information as JSON.
175
     *
176
     * @param  array  $data
177
     * @return void
178
     */
179
    protected function displayJson(array $data)
180
    {
181
        $this->output->writeln(json_encode($data));
182
    }
183
 
184
    /**
185
     * Render the table information formatted for the CLI.
186
     *
187
     * @param  array  $data
188
     * @return void
189
     */
190
    protected function displayForCli(array $data)
191
    {
192
        [$table, $columns, $indexes, $foreignKeys] = [
193
            $data['table'], $data['columns'], $data['indexes'], $data['foreign_keys'],
194
        ];
195
 
196
        $this->newLine();
197
 
198
        $this->components->twoColumnDetail('<fg=green;options=bold>'.$table['name'].'</>');
199
        $this->components->twoColumnDetail('Columns', $table['columns']);
200
 
201
        if ($size = $table['size']) {
202
            $this->components->twoColumnDetail('Size', number_format($size / 1024 / 1024, 2).'MiB');
203
        }
204
 
205
        $this->newLine();
206
 
207
        if ($columns->isNotEmpty()) {
208
            $this->components->twoColumnDetail('<fg=green;options=bold>Column</>', 'Type');
209
 
210
            $columns->each(function ($column) {
211
                $this->components->twoColumnDetail(
212
                    $column['column'].' <fg=gray>'.$column['attributes']->implode(', ').'</>',
213
                    ($column['default'] ? '<fg=gray>'.$column['default'].'</> ' : '').''.$column['type'].''
214
                );
215
            });
216
 
217
            $this->newLine();
218
        }
219
 
220
        if ($indexes->isNotEmpty()) {
221
            $this->components->twoColumnDetail('<fg=green;options=bold>Index</>');
222
 
223
            $indexes->each(function ($index) {
224
                $this->components->twoColumnDetail(
225
                    $index['name'].' <fg=gray>'.$index['columns']->implode(', ').'</>',
226
                    $index['attributes']->implode(', ')
227
                );
228
            });
229
 
230
            $this->newLine();
231
        }
232
 
233
        if ($foreignKeys->isNotEmpty()) {
234
            $this->components->twoColumnDetail('<fg=green;options=bold>Foreign Key</>', 'On Update / On Delete');
235
 
236
            $foreignKeys->each(function ($foreignKey) {
237
                $this->components->twoColumnDetail(
238
                    $foreignKey['name'].' <fg=gray;options=bold>'.$foreignKey['local_columns']->implode(', ').' references '.$foreignKey['foreign_columns']->implode(', ').' on '.$foreignKey['foreign_table'].'</>',
239
                    $foreignKey['on_update'].' / '.$foreignKey['on_delete'],
240
                );
241
            });
242
 
243
            $this->newLine();
244
        }
245
    }
246
}