Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
96.61% |
57 / 59 |
|
88.89% |
8 / 9 |
CRAP | |
0.00% |
0 / 1 |
| Menu | |
96.61% |
57 / 59 |
|
88.89% |
8 / 9 |
24 | |
0.00% |
0 / 1 |
| __construct | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 | |||
| rewind | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| current | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| key | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| next | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| valid | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| html | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| compileHtml | |
94.87% |
37 / 39 |
|
0.00% |
0 / 1 |
12.02 | |||
| makeTree | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
4 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | namespace Cosray\Finder; |
| 6 | |
| 7 | use Cosray\Context; |
| 8 | use Cosray\Exception\RuntimeException; |
| 9 | use Iterator; |
| 10 | |
| 11 | class Menu implements Iterator |
| 12 | { |
| 13 | protected array $items; |
| 14 | protected int $pointer = 0; |
| 15 | |
| 16 | public function __construct( |
| 17 | protected readonly Context $context, |
| 18 | string $menu, |
| 19 | ) { |
| 20 | $this->items = $this->makeTree( |
| 21 | $context->db->menus->get(['menu' => $menu])->all(), |
| 22 | ); |
| 23 | |
| 24 | if (count($this->items) === 0) { |
| 25 | throw new RuntimeException('Menu not found'); |
| 26 | } |
| 27 | } |
| 28 | |
| 29 | public function rewind(): void |
| 30 | { |
| 31 | reset($this->items); |
| 32 | } |
| 33 | |
| 34 | public function current(): MenuItem |
| 35 | { |
| 36 | return new MenuItem($this->context, current($this->items)); |
| 37 | } |
| 38 | |
| 39 | public function key(): string |
| 40 | { |
| 41 | return key($this->items); |
| 42 | } |
| 43 | |
| 44 | public function next(): void |
| 45 | { |
| 46 | next($this->items); |
| 47 | } |
| 48 | |
| 49 | public function valid(): bool |
| 50 | { |
| 51 | return key($this->items) !== null; |
| 52 | } |
| 53 | |
| 54 | public function html(string $class = '', string $tag = 'nav'): string |
| 55 | { |
| 56 | return $this->compileHtml($this, $class, $tag); |
| 57 | } |
| 58 | |
| 59 | protected function compileHtml( |
| 60 | Iterator $items, |
| 61 | string $class = '', |
| 62 | string $tag = 'nav', |
| 63 | ): string { |
| 64 | $out = ''; |
| 65 | |
| 66 | foreach ($items as $item) { |
| 67 | $class = $item->class(); |
| 68 | $image = $item->image() ?: ''; |
| 69 | |
| 70 | if ($image) { |
| 71 | $image = sprintf('<div class="nav-image"><img src="%s" alt="Navigation Icon"/></div>', $image); |
| 72 | } |
| 73 | |
| 74 | $submenu = $this->compileHtml($item->children(), tag: ''); |
| 75 | |
| 76 | if ($submenu) { |
| 77 | $submenu = sprintf('<div class="nav-submenu">%s</div>', $submenu); |
| 78 | } |
| 79 | |
| 80 | $content = sprintf( |
| 81 | '%s<div class="nav-label"><span>%s</span></div>%s', |
| 82 | $image, |
| 83 | $item->title(), |
| 84 | $submenu, |
| 85 | ); |
| 86 | |
| 87 | $content = match ($item->type()) { |
| 88 | 'page' => sprintf('<a href="%s">%s</a>', $item->path(), $content), |
| 89 | default => $content, |
| 90 | }; |
| 91 | |
| 92 | $out .= sprintf( |
| 93 | '<li class="nav-level-%s%s%s">%s</li>', |
| 94 | (string) $item->level(), |
| 95 | $item->hasChildren() ? ' nav-has-children' : '', |
| 96 | $class ? ' ' . $class : '', |
| 97 | $content, |
| 98 | ); |
| 99 | } |
| 100 | |
| 101 | if ($out) { |
| 102 | $class = $class ? sprintf(' class="%s"', $class) : ''; |
| 103 | |
| 104 | return $tag |
| 105 | ? sprintf( |
| 106 | '<%s%s><ul class="nav-level-%s">%s</ul></%s>', |
| 107 | $tag, |
| 108 | $class, |
| 109 | $item->level(), |
| 110 | $out, |
| 111 | $tag, |
| 112 | ) |
| 113 | : sprintf('<ul%s class="nav-level-%s">%s</ul>', $class, $item->level(), $out); |
| 114 | } |
| 115 | |
| 116 | return ''; |
| 117 | } |
| 118 | |
| 119 | protected function makeTree(array $items): array |
| 120 | { |
| 121 | $tree = []; |
| 122 | |
| 123 | foreach ($items as $item) { |
| 124 | $arr = &$tree; |
| 125 | |
| 126 | foreach (explode('.', $item['path']) as $segment) { |
| 127 | if (isset($arr[$segment])) { |
| 128 | $arr = &$arr[$segment]['children']; |
| 129 | } else { |
| 130 | $arr[$segment] = $item; |
| 131 | $arr[$segment]['children'] = []; |
| 132 | } |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | return $tree; |
| 137 | } |
| 138 | } |