@@ -206,29 +206,55 @@ private function buildTreeFromResults($results, $parent = null): Collection
206206 // Create a mapping of results by their parent IDs for faster lookup
207207 $ resultMap = [];
208208
209+ // Create a cache of IDs
210+ $ resultCache = [];
211+
209212 // Group results by their parent IDs
210213 foreach ($ results as $ result ) {
214+ // Cache the result ID as seen
215+ $ resultCache [$ result ->id ]['in_set ' ] = 1 ;
216+ // Move any cached children to the result map
217+ if (isset ($ resultCache [$ result ->id ]['children ' ])){
218+ $ resultMap [$ result ->id ] = array_merge ($ resultMap [$ result ->id ], $ resultCache [$ result ->id ]['children ' ]);
219+ unset($ resultCache [$ result ->id ]['children ' ]);
220+ }
211221 $ parentId = $ result ->{$ this ->getParentAttribute ()};
212- if (! isset ($ resultMap [$ parentId ])) {
213- $ resultMap [$ parentId ] = [];
222+ if (! isset ($ resultCache [$ parentId ])) {
223+ // Before adding results to the map, cache the parentId to hold until the parent is confirmed to be in the result set
224+ $ resultCache [$ parentId ]['in_set ' ] = 0 ;
225+ $ resultCache [$ parentId ]['children ' ] = [];
226+ }
227+ if ($ resultCache [$ parentId ]['in_set ' ]){
228+ // if the parent has been confirmed to be in the set, add directly to result map
229+ $ resultMap [$ parentId ][] = $ result ;
230+ } else {
231+ // otherwise, hold the result in the children cache until the parent is confirmed to be in the result set
232+ $ resultCache [$ parentId ]['children ' ][] = $ result ;
214233 }
215- $ resultMap [$ parentId ][] = $ result ;
216234 }
217235
218- // Define disabled options
219- $ disabledOptions = $ this ->getDisabledOptions ();
236+ // Filter the cache for missing parents in the result set and get the children
237+ $ orphanedResults = array_map (
238+ fn ($ item ) => $ item ['children ' ],
239+ array_filter (
240+ $ resultCache ,
241+ fn ($ item ) => !$ item ['in_set ' ]
242+ )
243+ );
220244
221- // Define hidden options
222- $ hiddenOptions = $ this ->getHiddenOptions ();
245+ // Move any remaining children from the cache into the root of the tree, since their parents do not show up in the result set
246+ $ resultMap [$ parent ] = array_merge (...array_values ($ orphanedResults ));
247+
248+ debug ($ resultMap );
223249
224250 // Recursively build the tree starting from the root (null parent)
225251 $ rootResults = $ resultMap [$ parent ] ?? [];
226252
227- // If a modified parent query yields no root results, iterate over the whole map instead
228- if ( $ this ->modifyQueryUsing && empty ( $ rootResults )) {
229- // Go one layer deeper to access the results
230- $ rootResults = array_merge (... array_values ( $ resultMap ));
231- }
253+ // Define disabled options
254+ $ disabledOptions = $ this ->getDisabledOptions ();
255+
256+ // Define hidden options
257+ $ hiddenOptions = $ this -> getHiddenOptions ();
232258
233259 foreach ($ rootResults as $ result ) {
234260 // Build a node and add it to the tree
0 commit comments