Passed
Push — master ( c972b4...91262f )
by Yaroslav
03:18
created

LoadDataToDBCommand::handle()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 9
ccs 6
cts 6
cp 1
crap 2
rs 10
1
<?php
2
3
namespace LaraGeoData\Console\Commands;
4
5
use Illuminate\Console\Command;
6
use Illuminate\Filesystem\Filesystem;
7
use Illuminate\Support\Facades\DB;
8
use Illuminate\Support\Facades\Schema;
9
use Illuminate\Support\Str;
10
use LaraGeoData\Facades\GeoDataImporter;
11
12
class LoadDataToDBCommand extends Command
13
{
14
    /**
15
     * The name and signature of the console command.
16
     *
17
     * @var string
18
     */
19
    protected $signature = 'geonames:import:file-to-db
20
        {type : Migration type. }
21
        {file? : Csv file path. }
22
        {--suffix= : Suffix used for specify country if need. }
23
        {--truncate : Truncate table before import. }
24
    ';
25
26
    /**
27
     * The console command description.
28
     *
29
     * @var string
30
     */
31
    protected $description = 'Upload data from csv file to DB.';
32
33
    /**
34
     * The filesystem instance.
35
     *
36
     * @var Filesystem
37
     */
38
    protected Filesystem $files;
39
40
    protected string $character = 'utf8mb4';
41
42
    /**
43
     * Create a new command instance.
44
     *
45
     * @param Filesystem $files
46
     *
47
     * @return void
48
     */
49 13
    public function __construct(Filesystem $files)
50
    {
51 13
        parent::__construct();
52
53 13
        $this->files = $files;
54 13
    }
55
56 6
    public function handle()
57
    {
58 6
        $type       = $this->argument('type');
59 6
        $methodName = 'import' . Str::ucfirst(Str::camel($type)) . 'Data';
0 ignored issues
show
Bug introduced by
It seems like $type can also be of type array; however, parameter $value of Illuminate\Support\Str::camel() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

59
        $methodName = 'import' . Str::ucfirst(Str::camel(/** @scrutinizer ignore-type */ $type)) . 'Data';
Loading history...
60 6
        if (!method_exists($this, $methodName)) {
61 1
            throw new \Exception("Import type [{$type}] not supported.");
62
        }
63
64 5
        return $this->{$methodName}();
65
    }
66
67
    /**
68
     * Process import for geonames.
69
     *
70
     * @return int
71
     * @throws \Exception
72
     */
73 5
    protected function importGeonamesData(): int
74
    {
75 5
        $tableName = $this->getTableName('geonames');
76 4
        $filePath  = $this->getFilePath('geonames');
77
78 1
        if ($this->option('truncate')) {
79 1
            DB::table($tableName)->truncate();
80
        }
81 1
        DB::connection(config('geonames.database.connection'))->statement(
82 1
            "LOAD DATA LOCAL INFILE '{$filePath}'
83 1
        INTO TABLE `{$tableName}`
84 1
        CHARACTER SET  '{$this->character()}'
85
        (geoname_id,
86
        name,
87
        ascii_name,
88
        alternate_names,
89
        lat,
90
        lng,
91
        fclass,
92
        fcode,
93
        country,
94
        cc2,
95
        admin1,
96
        admin2,
97
        admin3,
98
        admin4,
99
        population,
100
        elevation,
101
        gtopo30,
102
        timezone,
103
        moddate,
104
        @status,
105
        @created_at,
106
        @updated_at)
107
        SET status=2,created_at=NOW(),updated_at=NOW()"
108
        );
109
110 1
        return 0;
111
    }
112
113
    /**
114
     * Find table name.
115
     *
116
     * @param string $type
117
     *
118
     * @return string
119
     * @throws \Exception
120
     */
121 5
    protected function getTableName(string $type): string
122
    {
123 5
        $suffix = $this->getSuffix();
124
125 5
        $tableName = config("geonames.database.tables.{$type}");
126
127 5
        if (!$tableName) {
128
            throw new \Exception("Table name not found for type [{$type}]");
129
        }
130
131 5
        if ($suffix) {
132 3
            $tableName = "{$tableName}_{$suffix}";
133
        }
134
135 5
        if (!Schema::connection(config('geonames.database.connection'))->hasTable($tableName)) {
136 1
            throw new \Exception("Table [{$tableName}] not found. Maybe you need run migrations.");
137
        }
138
139 4
        return $tableName;
140
    }
141
142
    /**
143
     * Find file path.
144
     *
145
     * @param string $type
146
     *
147
     * @return string
148
     * @throws \Exception
149
     */
150 4
    protected function getFilePath(string $type): string
151
    {
152 4
        $filePath = $this->argument('file');
153
154 4
        if (!$filePath) {
155 3
            $filePath = match ($type) {
156 3
                'geonames' => $this->getGeonamesDefaultFilePath()
157
            };
158
        }
159
160 4
        if (!$filePath || !$this->files->exists($filePath)) {
0 ignored issues
show
Bug introduced by
It seems like $filePath can also be of type array; however, parameter $path of Illuminate\Filesystem\Filesystem::exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

160
        if (!$filePath || !$this->files->exists(/** @scrutinizer ignore-type */ $filePath)) {
Loading history...
161 3
            throw new \Exception("File [{$filePath}] not found.");
162
        }
163
164 1
        return $filePath;
165
    }
166
167
168
    /**
169
     * Get formatted suffix.
170
     *
171
     * @return string|null
172
     */
173 5
    protected function getSuffix(): ?string
174
    {
175 5
        $suffix = $this->option('suffix');
176 5
        if ($suffix) {
177 3
            $suffix = Str::snake($suffix);
178
        }
179
180 5
        return $suffix;
181
    }
182
183
    /**
184
     * Get default file path.
185
     *
186
     * @return string
187
     */
188 3
    protected function getGeonamesDefaultFilePath(): string
189
    {
190 3
        $suffix = $this->getSuffix();
191
192 3
        if (!$suffix) {
193 1
            return GeoDataImporter::storagePath('allCountries.txt');
194
        }
195
196 2
        return GeoDataImporter::storagePath(Str::upper($suffix) . '.txt');
197
    }
198
199
    /**
200
     * @return string
201
     */
202 1
    protected function character(): string
203
    {
204 1
        return $this->character;
205
    }
206
}
207