Skip to content

Commit 7f9318c

Browse files
Merge pull request #182 from gp-lnuff/revert-baspa-4-x
Revised changes
2 parents ac9617a + ff2ee56 commit 7f9318c

File tree

1 file changed

+47
-9
lines changed

1 file changed

+47
-9
lines changed

src/SelectTree.php

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
2121
use Illuminate\Support\Arr;
2222
use Illuminate\Support\Collection;
23+
use Illuminate\Support\LazyCollection;
2324
use InvalidArgumentException;
2425

2526
class SelectTree extends Field implements HasAffixActions
@@ -85,7 +86,7 @@ class SelectTree extends Field implements HasAffixActions
8586

8687
protected bool $storeResults = false;
8788

88-
protected Collection|array|null $results = null;
89+
protected LazyCollection|array|null $results = null;
8990

9091
protected Closure|bool|null $multiple = null;
9192

@@ -179,8 +180,8 @@ protected function buildTree(): Collection
179180
$nonNullParentQuery->withTrashed($this->withTrashed);
180181
}
181182

182-
$nullParentResults = $nullParentQuery->get();
183-
$nonNullParentResults = $nonNullParentQuery->get();
183+
$nullParentResults = $nullParentQuery->lazy();
184+
$nonNullParentResults = $nonNullParentQuery->lazy();
184185

185186
// Combine the results from both queries
186187
$combinedResults = $nullParentResults->concat($nonNullParentResults);
@@ -206,23 +207,60 @@ private function buildTreeFromResults($results, $parent = null): Collection
206207
// Create a mapping of results by their parent IDs for faster lookup
207208
$resultMap = [];
208209

210+
// Create a cache of IDs
211+
$resultCache = [];
212+
209213
// Group results by their parent IDs
210214
foreach ($results as $result) {
211-
$parentId = $result->{$this->getParentAttribute()};
212-
if (! isset($resultMap[$parentId])) {
213-
$resultMap[$parentId] = [];
215+
// Cache the result as seen
216+
$resultKey = $this->getCustomKey($result);
217+
$resultCache[$resultKey]['in_set'] = 1;
218+
// Move any cached children to the result map
219+
if(isset($resultCache[$resultKey]['children'])){
220+
// Since the result map won't have a key for a given result until it's confirmed to be in the set (i.e. this very moment),
221+
// we don't have to preserve the previous value for that key; it is guaranteed to have been unset
222+
$resultMap[$resultKey] = $resultCache[$resultKey]['children'];
223+
unset($resultCache[$resultKey]['children']);
224+
}
225+
$parentKey = $result->{$this->getParentAttribute()};
226+
if (! isset($resultCache[$parentKey])) {
227+
// Before adding results to the map, cache the parentId to hold until the parent is confirmed to be in the result set
228+
$resultCache[$parentKey]['in_set'] = 0;
229+
$resultCache[$parentKey]['children'] = [];
230+
}
231+
if($resultCache[$parentKey]['in_set']){
232+
// if the parent has been confirmed to be in the set, add directly to result map
233+
$resultMap[$parentKey][] = $result;
234+
} else {
235+
// otherwise, hold the result in the children cache until the parent is confirmed to be in the result set
236+
$resultCache[$parentKey]['children'][] = $result;
214237
}
215-
$resultMap[$parentId][] = $result;
216238
}
217239

240+
// Filter the cache for missing parents in the result set and get the children
241+
$orphanedResults = array_map(
242+
fn($item) => $item['children'],
243+
array_filter(
244+
$resultCache,
245+
fn($item) => !$item['in_set']
246+
)
247+
);
248+
249+
// Move any remaining children from the cache into the root of the tree, since their parents do not show up in the result set
250+
$resultMap[$parent] = [];
251+
foreach($orphanedResults as $orphanedResult){
252+
$resultMap[$parent] += $orphanedResult;
253+
}
254+
255+
// Recursively build the tree starting from the root (null parent)
256+
$rootResults = $resultMap[$parent] ?? [];
257+
218258
// Define disabled options
219259
$disabledOptions = $this->getDisabledOptions();
220260

221261
// Define hidden options
222262
$hiddenOptions = $this->getHiddenOptions();
223263

224-
// Recursively build the tree starting from the root (null parent)
225-
$rootResults = $resultMap[$parent] ?? [];
226264
foreach ($rootResults as $result) {
227265
// Build a node and add it to the tree
228266
$node = $this->buildNode($result, $resultMap, $disabledOptions, $hiddenOptions);

0 commit comments

Comments
 (0)