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 $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    /** @return list<array<string, mixed>> */
63    public function payload(): array
64    {
65        return $this->serialize($this->items());
66    }
67
68    private function register(Ref $ref): void
69    {
70        if (isset($this->collections[$ref->handle])) {
71            throw new RuntimeException('Duplicate collection handle: ' . $ref->handle);
72        }
73
74        $this->collections[$ref->handle] = $ref;
75    }
76
77    /**
78     * @param list<NavigationItem> $items
79     * @return list<array<string, mixed>>
80     */
81    private function serialize(array $items): array
82    {
83        $result = [];
84
85        foreach ($items as $item) {
86            if ($item instanceof Section) {
87                $result[] = [
88                    'type' => 'section',
89                    'name' => __($item->meta->label),
90                    'meta' => $item->meta->array(),
91                    'children' => $this->serialize($item->children()),
92                ];
93
94                continue;
95            }
96
97            if ($item instanceof NavLink) {
98                $result[] = [
99                    'type' => 'link',
100                    'url' => $item->url,
101                    'name' => __($item->meta->label),
102                    'meta' => $item->meta->array(),
103                    'children' => [],
104                ];
105
106                continue;
107            }
108
109            $result[] = [
110                'type' => 'collection',
111                'slug' => $item->slug(),
112                'name' => __($item->meta->label),
113                'meta' => $item->meta->array(),
114                'children' => [],
115            ];
116        }
117
118        return $result;
119    }
120}