44
55use Illuminate \Console \Command ;
66use NaimSolong \DataExtractor \Builder \ExtractBuilder ;
7+ use NaimSolong \DataExtractor \Extract ;
8+ use NaimSolong \DataExtractor \OptionsResolver ;
79
810class 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}
0 commit comments