Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
80.00% covered (warning)
80.00%
32 / 40
90.00% covered (success)
90.00%
9 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
Navigation
80.00% covered (warning)
80.00%
32 / 40
90.00% covered (success)
90.00%
9 / 10
16.80
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 section
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 collection
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 children
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 items
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 refs
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 ref
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 payload
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 register
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 serialize
70.37% covered (warning)
70.37%
19 / 27
0.00% covered (danger)
0.00%
0 / 1
4.42
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray;
6
7use Closure;
8use Cosray\Collection\Ref;
9use Cosray\Collection\Schemas;
10use Cosray\Exception\RuntimeException;
11
12final class Navigation
13{
14    private readonly Section $root;
15
16    /** @var array<string, Ref> */
17    private array $collections = [];
18
19    public function __construct(?Schemas $schemas = null)
20    {
21        $this->root = new Section('_root', Closure::fromCallable([$this, 'register']), $schemas);
22    }
23
24    public function section(string $label): Section
25    {
26        return $this->root->section($label);
27    }
28
29    /** @param class-string<Collection> $class */
30    public function collection(string $class): Ref
31    {
32        return $this->root->collection($class);
33    }
34
35    /** @return list<NavigationItem> */
36    public function children(): array
37    {
38        return $this->root->children();
39    }
40
41    /** @return list<NavigationItem> */
42    public function items(): array
43    {
44        return $this->children();
45    }
46
47    /** @return array<string, Ref> */
48    public function refs(): array
49    {
50        return $this->collections;
51    }
52
53    public function ref(string $handle): Ref
54    {
55        if (!isset($this->collections[$handle])) {
56            throw new RuntimeException('Unknown collection handle: ' . $handle);
57        }
58
59        return $this->collections[$handle];
60    }
61
62    public function payload(): array
63    {
64        return $this->serialize($this->items());
65    }
66
67    private function register(Ref $ref): void
68    {
69        if (isset($this->collections[$ref->handle])) {
70            throw new RuntimeException('Duplicate collection handle: ' . $ref->handle);
71        }
72
73        $this->collections[$ref->handle] = $ref;
74    }
75
76    /**
77     * @param list<NavigationItem> $items
78     * @return list<array<string, mixed>>
79     */
80    private function serialize(array $items): array
81    {
82        $result = [];
83
84        foreach ($items as $item) {
85            if ($item instanceof Section) {
86                $result[] = [
87                    'type' => 'section',
88                    'name' => __($item->meta->label),
89                    'meta' => $item->meta->array(),
90                    'children' => $this->serialize($item->children()),
91                ];
92
93                continue;
94            }
95
96            if ($item instanceof NavLink) {
97                $result[] = [
98                    'type' => 'link',
99                    'url' => $item->url,
100                    'name' => __($item->meta->label),
101                    'meta' => $item->meta->array(),
102                    'children' => [],
103                ];
104
105                continue;
106            }
107
108            $result[] = [
109                'type' => 'collection',
110                'slug' => $item->slug(),
111                'name' => __($item->meta->label),
112                'meta' => $item->meta->array(),
113                'children' => [],
114            ];
115        }
116
117        return $result;
118    }
119}