66
77use Illuminate \Console \Command ;
88use Illuminate \Support \Arr ;
9+ use Illuminate \Support \Facades \DB ;
910use Illuminate \Support \Facades \Storage ;
1011use Illuminate \Support \LazyCollection ;
1112use Parables \Geo \Actions \BuildNestedSetModelAction ;
@@ -57,7 +58,9 @@ public function handle(): int
5758
5859 $ contentsOfGeonameFiles = $ this ->readGeonameFiles (fileNames: array_slice ($ fileNames , 2 )); // skip admin2Codes.txt and hierarchy.txt
5960
60- $ nestedSet = $ this ->buildNestedSetModel (contentsOfGeonameFiles: $ contentsOfGeonameFiles );
61+ $ hierarchy = $ this ->buildHierarchy (contentsOfGeonameFiles: $ contentsOfGeonameFiles );
62+
63+ $ nestedSet = $ this ->buildNestedSetModel (hierarchy: $ hierarchy );
6164
6265 $ this ->loadGeonames (contentsOfGeonameFiles: $ contentsOfGeonameFiles , nestedSet: $ nestedSet );
6366
@@ -180,7 +183,7 @@ public function askToSelectCountries(array $countries): array
180183 public function appendFileExtension (array $ countryCodes ): array
181184 {
182185 $ fileNames = ['admin2Codes.txt ' , 'hierarchy.zip ' , 'no-country.zip ' ];
183- return $ fileNames + array_map (fn ($ code ) => $ code . '.zip ' , $ countryCodes );
186+ return $ fileNames + array_map (fn ($ code ) => $ code . '.zip ' , $ countryCodes );
184187 }
185188
186189 /**
@@ -232,17 +235,65 @@ public function readGeonameFiles(array $fileNames): LazyCollection
232235 return (new ReadFilesAction )->toastable ($ this )->execute ($ fileNames );
233236 }
234237
235- /**
236- * @param LazyCollection<int, LazyCollection> $contentsOfGeonameFiles
237- */
238- public function buildNestedSetModel (LazyCollection $ contentsOfGeonameFiles ): array
238+ /** @param LazyCollection<int, LazyCollection> $contentsOfGeonameFiles */
239+ public function buildHierarchy (LazyCollection $ contentsOfGeonameFiles ): LazyCollection
239240 {
240241 $ this ->info ('Getting hierarchy... ' );
241- $ hierarchy = (new GetHierarchyAction )
242- ->toastable ($ this )
243- ->execute (contentsOfGeonameFiles: $ contentsOfGeonameFiles );
244- $ this ->writeToFile (fileName: storage_path ('geo/hierarchy.json ' ), content: $ hierarchy );
245242
243+ $ hierarchyCacheFile = storage_path ('/geo/hierarchy.json ' );
244+
245+ $ buildFromScratch = function (LazyCollection $ contentsOfGeonameFiles )
246+ use ($ hierarchyCacheFile ) {
247+ $ this ->info ('Building hierarchy from scratch... ' );
248+ $ collection = (new GetHierarchyAction )
249+ ->toastable ($ this )
250+ ->execute (contentsOfGeonameFiles: $ contentsOfGeonameFiles );
251+
252+ // TODO: Write this to the database
253+
254+ $ this ->toast ("Inserting hierarchy into database " );
255+ DB ::table ('geonames_hierarchy ' )->insertOrIgnore ($ collection ->all ());
256+
257+ $ hierarchy = $ collection ->mapToGroups (function (array $ item , int $ key ) {
258+ return [$ item ['parent_id ' ] => $ item ['child_id ' ]];
259+ });
260+
261+ // NOTE: write the fresh update to the cache file
262+ $ this ->info ("Writing the hierarchy to: $ hierarchyCacheFile " );
263+ $ this ->writeToFile (
264+ fileName: storage_path ('geo/hierarchy.json ' ),
265+ content: $ hierarchy ->all (),
266+ );
267+
268+ return $ hierarchy ;
269+ };
270+
271+ if (file_exists ($ hierarchyCacheFile )) {
272+ $ shouldRebuild = $ this ->confirm (
273+ question: "The $ hierarchyCacheFile file already exists. Would you like to rebuild it from scratch? " ,
274+ default: false
275+ );
276+
277+ if ($ shouldRebuild ) {
278+ $ hierarchy = $ buildFromScratch ($ contentsOfGeonameFiles );
279+ } else {
280+ $ this ->info ("Reading the hierarchy from: $ hierarchyCacheFile " );
281+ // read from cache
282+ $ hierarchy = Arr::wrap (json_decode (
283+ file_get_contents ($ hierarchyCacheFile ),
284+ associative: true ,
285+ ));
286+ }
287+ } else {
288+ $ hierarchy = $ buildFromScratch ($ contentsOfGeonameFiles );
289+ }
290+
291+ return $ hierarchy ;
292+ }
293+
294+ public function buildNestedSetModel (array $ hierarchy ): array
295+ {
296+ return [];
246297 $ this ->info ('Building Nested Set Model... ' );
247298 $ nestedSet = (new BuildNestedSetModelAction )
248299 ->toastable ($ this )
@@ -276,10 +327,25 @@ public function loadGeonames(LazyCollection $contentsOfGeonameFiles, array $nest
276327 $ stream = fopen (filename: $ geonameFile , mode: 'w ' );
277328
278329 $ chunks = $ contentsOfGeonameFiles ->chunk (50 );
279- $ chunks ->each (function (LazyCollection $ contentsOfGeonameFiles , int $ index ) use ($ stream , $ nestedSet , $ transformGeonamesAction , $ loadGeonamesAction , $ chunks , $ progressBar ) {
330+ $ chunks ->each (function (LazyCollection $ contentsOfGeonameFiles , int $ index )
331+ use (
332+ $ stream ,
333+ $ nestedSet ,
334+ $ transformGeonamesAction ,
335+ $ loadGeonamesAction ,
336+ $ chunks ,
337+ $ progressBar ,
338+ ) {
280339 $ this ->info ('Processing batch: ' . ($ index + 1 ) . '/ ' . $ chunks ->count ());
281340
282- $ contentsOfGeonameFiles ->each (function (LazyCollection $ fileContents ) use ($ stream , $ nestedSet , $ transformGeonamesAction , $ loadGeonamesAction , $ progressBar ) {
341+ $ contentsOfGeonameFiles ->each (function (LazyCollection $ fileContents )
342+ use (
343+ $ stream ,
344+ $ nestedSet ,
345+ $ transformGeonamesAction ,
346+ $ loadGeonamesAction ,
347+ $ progressBar ,
348+ ) {
283349 $ this ->newLine (2 );
284350
285351 $ geonamesCollection = $ transformGeonamesAction ->execute (
@@ -289,7 +355,13 @@ public function loadGeonames(LazyCollection $contentsOfGeonameFiles, array $nest
289355 idAsindex: true
290356 );
291357
292- fwrite (stream: $ stream , data: json_encode ($ geonamesCollection , JSON_PRETTY_PRINT ));
358+ fwrite (
359+ stream: $ stream ,
360+ data: json_encode (
361+ $ geonamesCollection ->all (),
362+ JSON_PRETTY_PRINT ,
363+ ),
364+ );
293365
294366 $ loadGeonamesAction ->execute (
295367 geonamesCollection: $ geonamesCollection ,
0 commit comments