Skip to content

Commit 8874a01

Browse files
committed
Refactor command
1 parent f798846 commit 8874a01

File tree

2 files changed

+43
-129
lines changed

2 files changed

+43
-129
lines changed

src/Commands/DataExtractCommand.php

Lines changed: 38 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -4,167 +4,97 @@
44

55
use Illuminate\Console\Command;
66
use NaimSolong\DataExtractor\Builder\ExtractBuilder;
7+
use NaimSolong\DataExtractor\Extract;
8+
use NaimSolong\DataExtractor\OptionsResolver;
79

810
class DataExtractCommand extends Command
911
{
10-
public $signature = 'data:extract';
12+
public $signature = 'data:extract
13+
{--name= : The name of the option to execute}
14+
{--queryId= : The ID of the model to extract data from}
15+
{--format= : The format of the extracted data (csv, sql)}';
1116

1217
public $description = 'Extract data based on predefined options';
1318

14-
public array $options = [];
19+
public OptionsResolver $options;
1520

1621
public function __construct()
1722
{
18-
$this->options = config('data-extractor.options', []);
23+
$this->options = new OptionsResolver;
1924

2025
parent::__construct();
2126
}
2227

2328
public function handle(): int
2429
{
25-
if (! config('data-extractor.allow_production') && app()->environment('production')) {
26-
$this->error('Data extraction is not allowed in production environment.');
30+
if (! config('data-extractor.is_enabled')) {
31+
$this->error('Data extraction is not enabled.');
2732

2833
return self::FAILURE;
2934
}
3035

31-
if ($this->validateOptions() === false) {
32-
return self::FAILURE;
33-
}
34-
35-
$selectedOptions = $this->promptOptions();
36+
$name = $this->option('name');
37+
$queryId = $this->option('queryId');
38+
$format = $this->option('format');
3639

37-
$id = $this->promptModelId($selectedOptions);
40+
$name != null ? $this->options->set($name) : $this->promptOptions();
3841

39-
if ($id <= 0) {
40-
return self::FAILURE;
41-
}
42+
$id = $queryId ?? $this->promptModelId();
4243

43-
$selectedSource = $selectedOptions['source'] ?? null;
44-
if (! $selectedSource) {
45-
$this->error('No source specified in the selected option.');
44+
$format = $format ?: ExtractBuilder::DEFAULT_FORMAT;
4645

46+
if ($id <= 0) {
4747
return self::FAILURE;
4848
}
49-
$source = config("data-extractor.source.$selectedSource", []);
50-
51-
$query = app($source['model'])
52-
->setConnection($source['connection'] ?? 'mysql')
53-
->with($source['relationships'] ?? [])
54-
->where('id', $id);
5549

56-
if (! $query->exists()) {
57-
$this->error("No record found with ID {$id} in the {$source['model']} model.");
50+
$results = (new Extract)
51+
->option($this->options->get()->toArray()['name'])
52+
->queryId($id)
53+
->extract($format);
5854

59-
return self::FAILURE;
60-
}
61-
62-
$data = $query->first();
63-
64-
$insertSql = $this->generateInsertSql($data);
65-
66-
$this->line("<info>Generated SQL Insert Statement:</info>\n$insertSql");
67-
68-
// Get loaded relationships
69-
$loadedRelations = $data->getRelations();
70-
71-
// Debug: Show loaded relations context
72-
$this->line('<comment>Loaded Relations:</comment>');
73-
foreach ($loadedRelations as $relationName => $relationData) {
74-
$this->line(" - {$relationName}: ".(is_countable($relationData) ? count($relationData).' records' : 'single record'));
75-
76-
$this->line("<comment>Generated SQL for relation '{$relationName}':</comment>");
77-
if (is_countable($relationData)) {
78-
foreach ($relationData as $relation) {
79-
$insertSql = $this->generateInsertSql($relation);
80-
$this->line("\n$insertSql");
81-
}
82-
} else {
83-
$insertSql = $this->generateInsertSql($relationData);
84-
$this->line("\n$insertSql");
85-
}
55+
foreach ($results as $result) {
56+
$this->line($result);
8657
}
8758

8859
return self::SUCCESS;
8960
}
9061

91-
protected function validateOptions(): bool
92-
{
93-
if (empty($this->options)) {
94-
$this->error('No options found in the configuration.');
95-
96-
return false;
97-
}
98-
99-
$sourceConnections = array_keys(config('data-extractor.source'));
100-
101-
foreach ($this->options as $option) {
102-
if (empty($option['name']) || empty($option['source']) || empty($option['export'])) {
103-
$this->error('Invalid option format. Each option must have a name, source, and export configuration.');
104-
105-
return false;
106-
}
107-
108-
if (! in_array($option['export']['format'], ExtractBuilder::FORMATS)) {
109-
$this->error('Invalid export format in option: '.$option['name']);
110-
111-
return false;
112-
}
113-
114-
if (! isset($option['source']) || ! is_string($option['source']) || ! in_array($option['source'], $sourceConnections)) {
115-
$this->error('Invalid source specified in option: '.$option['name']);
116-
117-
return false;
118-
}
119-
120-
$selectedSource = config("data-extractor.source.{$option['source']}", []);
121-
122-
if (! isset($selectedSource['model'])) {
123-
$this->error('Invalid model configuration in source: '.$option['source']);
124-
125-
return false;
126-
}
127-
}
128-
129-
return true;
130-
}
131-
13262
protected function promptOptions(): array
13363
{
64+
$options = $this->options->all();
65+
13466
$this->table(
135-
['Name', 'Description', 'Export Format'],
67+
['Name', 'Description'],
13668
array_map(function ($option) {
69+
$option = $option->toArray();
70+
13771
return [
13872
$option['name'],
139-
$option['description'] ?? 'N/A',
73+
$option['description'],
14074
];
141-
}, $this->options)
75+
}, $options)
14276
);
14377

144-
$optionNames = array_column($this->options, 'name');
78+
$optionNames = array_column($options, 'name');
14579

14680
$selectedKey = array_keys($this->choice(
14781
'Select an option to execute',
14882
$optionNames,
14983
null,
15084
null,
15185
true
152-
));
86+
))[0];
87+
88+
$this->options->set($selectedKey);
15389

154-
return $this->options[$selectedKey[0]];
90+
return $this->options->get()->toArray();
15591
}
15692

157-
protected function promptModelId($option): int
93+
protected function promptModelId(): int
15894
{
159-
$source = $option['source'] ?? null;
160-
161-
if (! $source || ! is_string($source)) {
162-
$this->error('Invalid source specified in the option.');
163-
164-
return 0;
165-
}
95+
$source = $this->options->source();
16696

167-
$modelClass = config("data-extractor.source.$source.model");
97+
$modelClass = $source->toArray()['model'];
16898

16999
if (! $modelClass || ! class_exists($modelClass)) {
170100
$this->error('Invalid model class specified in the option source.');
@@ -178,25 +108,4 @@ protected function promptModelId($option): int
178108

179109
return (int) $id;
180110
}
181-
182-
protected function generateInsertSql($data): string
183-
{
184-
$insertString = [];
185-
$dataArray = $data->toArray();
186-
foreach ($dataArray as $key => $value) {
187-
if (is_array($value)) {
188-
$insertString[] = "`$key` = '".json_encode($value, JSON_UNESCAPED_UNICODE)."'";
189-
} elseif (is_null($value)) {
190-
$insertString[] = "`$key` = NULL";
191-
} elseif (is_numeric($value)) {
192-
$insertString[] = "`$key` = $value";
193-
} elseif (is_bool($value)) {
194-
$insertString[] = "`$key` = ".($value ? '1' : '0');
195-
} else {
196-
$insertString[] = "`$key` = '".addslashes($value)."'";
197-
}
198-
}
199-
200-
return "INSERT INTO `{$data->getTable()}` VALUE (".implode(', ', $insertString).');';
201-
}
202111
}

src/OptionsResolver.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ public function set(int|string $value): self
5959
throw new InvalidArgumentException("Invalid option value: {$value}");
6060
}
6161

62+
public function all(): array
63+
{
64+
return $this->options;
65+
}
66+
6267
public function get(): Option
6368
{
6469
return $this->option;

0 commit comments

Comments
 (0)