Skip to content

Commit 31357cb

Browse files
authored
Merge pull request #87 from LaswitchTech/dev
General: Version bumped to v0.0.87
2 parents a237944 + 119c065 commit 31357cb

2 files changed

Lines changed: 71 additions & 18 deletions

File tree

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.0.86
1+
v0.0.87

src/Builder.php

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -122,14 +122,52 @@ public function menu($location = 'sidebar', $parent = null, int $maxDepth = 2):
122122
}
123123
if (!$eligible) return [];
124124

125-
// 2) Build parent->children map among eligible routes
125+
// --- NEW: helper to promote parents to nearest eligible ancestor(s) ---
126+
$resolveParents = function(array $declared) use ($all, $eligible): array {
127+
$result = [];
128+
$queue = $declared;
129+
$seen = [];
130+
while ($queue) {
131+
$cur = array_shift($queue);
132+
if (!is_string($cur) || $cur === '' || isset($seen[$cur])) continue;
133+
$seen[$cur] = true;
134+
135+
if (isset($eligible[$cur])) {
136+
// found an eligible ancestor for this branch
137+
$result[$cur] = true;
138+
continue;
139+
}
140+
141+
// climb up if we know about this route in $all
142+
if (!isset($all[$cur])) continue;
143+
$pp = $all[$cur]['parent'] ?? null;
144+
if ($pp === null) continue;
145+
146+
foreach (is_array($pp) ? $pp : [$pp] as $up) {
147+
if (is_string($up) && $up !== '') $queue[] = $up;
148+
}
149+
}
150+
return array_keys($result);
151+
};
152+
153+
// 2) Build parent->children map among eligible routes (with promotion)
126154
$children = []; // parentRoute => [childRoute...]
127155
foreach ($eligible as $r => $_) $children[$r] = [];
156+
157+
// keep a promoted-parents cache to avoid recomputing
158+
$effParentCache = [];
159+
128160
foreach ($eligible as $child => $node) {
129-
foreach ($node['parents'] as $par) {
130-
if (isset($eligible[$par])) $children[$par][] = $child;
161+
$declared = $node['parents'];
162+
$eff = $effParentCache[$child] ?? $resolveParents($declared);
163+
$effParentCache[$child] = $eff;
164+
165+
foreach ($eff as $parEff) {
166+
// only link to eligible parents
167+
if (isset($children[$parEff])) $children[$parEff][] = $child;
131168
}
132169
}
170+
133171
$sortKeys = function(array &$arr) { ksort($arr, SORT_NATURAL | SORT_FLAG_CASE); };
134172
$sortList = function(array &$list) { sort($list, SORT_NATURAL | SORT_FLAG_CASE); };
135173
foreach ($children as &$lst) $sortList($lst);
@@ -138,28 +176,45 @@ public function menu($location = 'sidebar', $parent = null, int $maxDepth = 2):
138176
// 3) Determine start nodes
139177
$starts = [];
140178
if ($parent === null) {
141-
// global roots = nodes that have no eligible parent
179+
// global roots = nodes that have no eligible (promoted) parent
142180
foreach ($eligible as $route => $node) {
143-
$hasEligibleParent = false;
144-
foreach ($node['parents'] as $p) {
145-
if (isset($eligible[$p])) { $hasEligibleParent = true; break; }
146-
}
147-
if (!$hasEligibleParent) $starts[] = $route;
181+
$eff = $effParentCache[$route] ?? $resolveParents($node['parents']);
182+
if (empty($eff)) $starts[] = $route;
148183
}
149184
$sortList($starts);
150185
} else {
186+
// pick descendants under the requested parent, even if that parent itself is not eligible
151187
$want = is_array($parent) ? $parent : [$parent];
152188
$seen = [];
189+
190+
// If the requested parent is eligible, we can directly use $children
153191
foreach ($want as $p) {
154192
if (isset($children[$p])) {
155-
foreach ($children[$p] as $c) { $seen[$c] = true; }
156-
} else {
157-
// if parent isn't itself eligible, include any eligible that declares it as parent
158-
foreach ($eligible as $route => $node) {
159-
if (in_array($p, $node['parents'], true)) $seen[$route] = true;
193+
foreach ($children[$p] as $c) $seen[$c] = true;
194+
}
195+
196+
// Also include any eligible node that has $p in its ancestry chain (promoted)
197+
foreach ($eligible as $route => $node) {
198+
// Check if $p appears in ancestry by climbing from declared parents
199+
$queue = $node['parents'];
200+
$visited = [];
201+
$found = false;
202+
while ($queue && !$found) {
203+
$cur = array_shift($queue);
204+
if (isset($visited[$cur])) continue;
205+
$visited[$cur] = true;
206+
if ($cur === $p) { $found = true; break; }
207+
if (!isset($all[$cur])) continue;
208+
$pp = $all[$cur]['parent'] ?? null;
209+
if ($pp === null) continue;
210+
foreach (is_array($pp) ? $pp : [$pp] as $up) {
211+
if (is_string($up) && $up !== '') $queue[] = $up;
212+
}
160213
}
214+
if ($found) $seen[$route] = true;
161215
}
162216
}
217+
163218
$starts = array_keys($seen);
164219
$sortList($starts);
165220
}
@@ -185,7 +240,6 @@ public function menu($location = 'sidebar', $parent = null, int $maxDepth = 2):
185240
if (isset($visited[$cur])) continue;
186241
$visited[$cur] = true;
187242
$out[$cur] = $makeLeaf($cur);
188-
// enqueue children (we want *all* descendants in flat mode)
189243
foreach ($children[$cur] ?? [] as $ch) $queue[] = $ch;
190244
}
191245
$sortKeys($out);
@@ -195,7 +249,7 @@ public function menu($location = 'sidebar', $parent = null, int $maxDepth = 2):
195249
// 4b) Depth >= 2: build nested tree up to $maxDepth; deeper nodes are omitted
196250
$buildTree = function(string $route, int $depth) use (&$buildTree, $maxDepth, $children, $makeLeaf): array {
197251
$node = $makeLeaf($route);
198-
if ($depth >= $maxDepth) return $node; // reached cap; omit deeper nodes
252+
if ($depth >= $maxDepth) return $node;
199253
$items = [];
200254
foreach ($children[$route] ?? [] as $ch) {
201255
$items[$ch] = $buildTree($ch, $depth + 1);
@@ -215,7 +269,6 @@ public function menu($location = 'sidebar', $parent = null, int $maxDepth = 2):
215269
return $result;
216270
}
217271

218-
219272
/**
220273
* Create Crumbs
221274
*

0 commit comments

Comments
 (0)