TableCommand::getAttributesForIndex()   A
last analyzed

Complexity

Conditions 3
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 6
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 9
ccs 8
cts 8
cp 1
crap 3
rs 10
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Console;
4
5
use Illuminate\Database\ConnectionResolverInterface;
6
use Illuminate\Database\Console\TableCommand as IlluminateTableCommand;
7
use Illuminate\Database\Schema\Builder;
8
use Illuminate\Support\Number;
9
use LaravelFreelancerNL\Aranguent\Connection;
10
11
use function Laravel\Prompts\select;
12
13
class TableCommand extends IlluminateTableCommand
14
{
15
    /**
16
     * The name and signature of the console command.
17
     *
18
     * @var string
19
     */
20
    protected $signature = 'db:table
21
                            {table? : The name of the table}
22
                            {--database= : The database connection}
23
                            {--system= : Include system tables (ArangoDB)}
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 4
    public function handle(ConnectionResolverInterface $connections)
39
    {
40 4
        $connection = $connections->connection($this->input->getOption('database'));
41
42 4
        if (! $connection instanceof Connection) {
43
            return parent::handle($connections);
44
        }
45
46 4
        $schema = $connection->getSchemaBuilder();
47
48 4
        $tables = collect(
49 4
            ($this->input->getOption('system'))
0 ignored issues
show
Bug introduced by
$this->input->getOption(... : $schema->getTables() of type array<mixed,mixed> is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

49
            /** @scrutinizer ignore-type */ ($this->input->getOption('system'))
Loading history...
50
                ? $schema->getAllTables()
51 4
                : $schema->getTables(),
52 4
        )
53 4
            ->keyBy(fn($table) => (string) $table['name'])
54 4
            ->all();
55
56 4
        $tableName = (string) $this->argument('table') ?: select(
57 4
            'Which table would you like to inspect?',
58 4
            array_keys($tables),
59 4
        );
60
61 4
        $table = $schema->getTable((string) $tableName);
62
63 4
        if (! $table) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $table of type array 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...
64
            $this->components->warn("Table [{$tableName}] doesn't exist.");
65
66
            return 1;
67
        }
68
69 4
        [$columns, $indexes] = $connection->withoutTablePrefix(function ($connection) use ($table) {
70 4
            $schema = $connection->getSchemaBuilder();
71 4
            $tableName = $table['name'];
72
73 4
            return [
74 4
                $this->columns($schema, $tableName),
75 4
                $this->indexes($schema, $tableName),
76 4
            ];
77 4
        });
78
79
80
81 4
        $data = [
82 4
            'table' => $table,
83 4
            'columns' => $columns,
84 4
            'indexes' => $indexes,
85 4
        ];
86
87 4
        $this->display($data);
88
89 4
        return 0;
90
    }
91
92
    /**
93
     * Get the information regarding the table's columns.
94
     *
95
     * @param  \Illuminate\Database\Schema\Builder  $schema
96
     * @param  string  $table
97
     * @return \Illuminate\Support\Collection
98
     */
99 4
    protected function columns(Builder $schema, string $table)
100
    {
101 4
        return collect($schema->getColumns($table));
102
    }
103
104
    /**
105
     * Get the information regarding the table's indexes.
106
     *
107
     * @param  \Illuminate\Database\Schema\Builder  $schema
108
     * @param  string  $table
109
     * @return \Illuminate\Support\Collection
110
     */
111 4
    protected function indexes(Builder $schema, string $table)
112
    {
113 4
        return collect($schema->getIndexes($table))->map(fn($index) => [
114 4
            'name' => (string) $index['name'],
115 4
            'columns' => collect((array) $index['fields']),
0 ignored issues
show
Bug introduced by
(array)$index['fields'] of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

115
            'columns' => collect(/** @scrutinizer ignore-type */ (array) $index['fields']),
Loading history...
116 4
            'attributes' => $this->getAttributesForIndex((array) $index),
117 4
        ]);
118
    }
119
120
    /**
121
     * Get the attributes for a table index.
122
     *
123
     * @param  array<mixed>  $index
124
     * @return \Illuminate\Support\Collection
125
     */
126 4
    protected function getAttributesForIndex($index)
127
    {
128 4
        return collect(
129 4
            array_filter([
0 ignored issues
show
Bug introduced by
array_filter(array('spar...pe' => $index['type'])) of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

129
            /** @scrutinizer ignore-type */ array_filter([
Loading history...
130 4
                'sparse' => $index['sparse'] ? 'sparse' : null,
131 4
                'unique' => $index['unique'] ? 'unique' : null,
132 4
                'type' => $index['type'],
133 4
            ]),
134 4
        )->filter();
135
    }
136
137
    /**
138
     * Render the table information.
139
     *
140
     * @param  mixed[]  $data
141
     * @return void
142
     */
143 4
    protected function display(array $data)
144
    {
145 4
        $this->option('json') ? $this->displayJson($data) : $this->displayForCli($data);
146
    }
147
148 1
    protected function displayLongStringValue(string $value): string
149
    {
150 1
        if (strlen($value) < 136) {
151 1
            return $value;
152
        }
153
        return substr($value, 0, 133) . '...';
154
    }
155
156
    /**
157
     * Render the table information formatted for the CLI.
158
     *
159
     * @param  mixed[] $data
160
     * @return void
161
     */
162 4
    protected function displayForCli(array $data)
163
    {
164 4
        [$table, $columns, $indexes ] = [
165 4
            $data['table'], $data['columns'], $data['indexes'],
166 4
        ];
167
168 4
        $this->newLine();
169
170 4
        $this->components->twoColumnDetail('<fg=green;options=bold>Table</>', '<fg=green;options=bold>' . $table['name'] . '</>');
171 4
        $this->components->twoColumnDetail('Type', ($table['type'] == 2) ? 'Vertex' : 'Edge');
172 4
        $this->components->twoColumnDetail('Status', $table['statusString']);
173 4
        $this->components->twoColumnDetail('User Keys Allowed', ($table['keyOptions']->allowUserKeys) ? 'Yes' : 'No');
174 4
        $this->components->twoColumnDetail('Key Type', $table['keyOptions']->type);
175 4
        $this->components->twoColumnDetail('Last Used Key', $table['keyOptions']->lastValue);
176 4
        $this->components->twoColumnDetail('Wait For Sync', ($table['waitForSync']) ? 'Yes' : 'No');
177 4
        $this->components->twoColumnDetail('Columns', $table['count']);
178 4
        $this->components->twoColumnDetail('Size Estimate', Number::fileSize($table['figures']->documentsSize, 2));
179
180 4
        $this->newLine();
181
182 4
        if ($columns->isNotEmpty()) {
183 1
            $this->components->twoColumnDetail('<fg=green;options=bold>Column</>', '<fg=green;options=bold>Type</>');
184
185 1
            $columns->each(function ($column) {
186 1
                $this->components->twoColumnDetail(
187 1
                    $column['name'],
188 1
                    implode(', ', $column['type']),
189 1
                );
190 1
            });
191 1
            $this->components->info('ArangoDB is schemaless by default. Hence, the column & types are a representation of current data within the table.');
192
        }
193
194 4
        $computedValues = collect((array) $table['computedValues']);
0 ignored issues
show
Bug introduced by
(array)$table['computedValues'] of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

194
        $computedValues = collect(/** @scrutinizer ignore-type */ (array) $table['computedValues']);
Loading history...
195 4
        if ($computedValues->isNotEmpty()) {
196 1
            $this->components->twoColumnDetail('<fg=green;options=bold>Computed Value</>', '<fg=green;options=bold>Expression</>');
197
198 1
            $computedValues->each(function ($value) {
199 1
                $this->components->twoColumnDetail(
200 1
                    $value->name,
201 1
                    $this->displayLongStringValue($value->expression),
202 1
                );
203 1
            });
204
205 1
            $this->newLine();
206
        }
207
208 4
        if ($indexes->isNotEmpty()) {
209 4
            $this->components->twoColumnDetail('<fg=green;options=bold>Index</>');
210
211 4
            $indexes->each(function ($index) {
212 4
                $this->components->twoColumnDetail(
213 4
                    $index['name'] . ' <fg=gray>' . $index['columns']->implode(', ') . '</>',
214 4
                    $index['attributes']->implode(', '),
215 4
                );
216 4
            });
217
218 4
            $this->newLine();
219
        }
220
    }
221
}
222