TableCommand::handle()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 52
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 31
CRAP Score 5.0373

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 29
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 52
ccs 31
cts 35
cp 0.8857
crap 5.0373
rs 9.1448

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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