You've already forked wp-bootstrap
81 lines
2.1 KiB
PHP
81 lines
2.1 KiB
PHP
|
|
<?php
|
||
|
|
/**
|
||
|
|
* Bootstrap 5 Navigation Walker.
|
||
|
|
*
|
||
|
|
* Converts flat WordPress menu items into a nested tree
|
||
|
|
* suitable for rendering Bootstrap navbar dropdowns in Twig.
|
||
|
|
*
|
||
|
|
* @package WPBootstrap
|
||
|
|
* @since 0.1.1
|
||
|
|
*/
|
||
|
|
|
||
|
|
namespace WPBootstrap\Template;
|
||
|
|
|
||
|
|
class NavWalker
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* Build a nested menu tree from flat WordPress menu items.
|
||
|
|
*
|
||
|
|
* @param array $items Array of WP_Post menu item objects.
|
||
|
|
* @return array Nested array suitable for Twig iteration.
|
||
|
|
*/
|
||
|
|
public function buildTree(array $items): array
|
||
|
|
{
|
||
|
|
$tree = [];
|
||
|
|
$children = [];
|
||
|
|
|
||
|
|
foreach ($items as $item) {
|
||
|
|
$node = [
|
||
|
|
'id' => (int) $item->ID,
|
||
|
|
'title' => $item->title,
|
||
|
|
'url' => $item->url,
|
||
|
|
'target' => $item->target ?: '',
|
||
|
|
'classes' => implode(' ', array_filter($item->classes ?? [])),
|
||
|
|
'active' => $this->isActive($item),
|
||
|
|
'children' => [],
|
||
|
|
];
|
||
|
|
|
||
|
|
if ((int) $item->menu_item_parent === 0) {
|
||
|
|
$tree[$item->ID] = $node;
|
||
|
|
} else {
|
||
|
|
$children[(int) $item->menu_item_parent][] = $node;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Assign children to their parent items.
|
||
|
|
foreach ($children as $parentId => $childItems) {
|
||
|
|
if (isset($tree[$parentId])) {
|
||
|
|
$tree[$parentId]['children'] = $childItems;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return array_values($tree);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Determine if a menu item is currently active.
|
||
|
|
*/
|
||
|
|
private function isActive(object $item): bool
|
||
|
|
{
|
||
|
|
$classes = $item->classes ?? [];
|
||
|
|
|
||
|
|
if (in_array('current-menu-item', $classes, true)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (in_array('current-menu-ancestor', $classes, true)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($item->object === 'page' && is_page((int) $item->object_id)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($item->object === 'category' && is_category((int) $item->object_id)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|