Lines 100.00% 26 / 26
Methods 100.00% 3 / 3
Classes 100.00% 1 / 1
Covered by tests of size
Name Lines Methods CRAP
 buildFromIds 100.00% 1 / 1 100.00% 1 / 1 1
 buildFromIdsWithStartPage 100.00% 14 / 14 100.00% 1 / 1 1
 buildCategorySegments 100.00% 11 / 11 100.00% 1 / 1 3
27final class BreadcrumbsBuilder
28{
29    /**
30     * @param array<int, array<string, mixed>> $categoryNameMap id => row (expects name, description)
31     * @param array<int> $ids ordered list from root to leaf
32     * @return array<int, array{id:int, name:string, description:string}>
33     */
34    public function buildFromIds(array $categoryNameMap, array $ids): array
35    {
36        return $this->buildCategorySegments($categoryNameMap, $ids);
37    }
38
39    /**
40     * Builds breadcrumb segments with the start page as the first segment.
41     *
42     * @param array<int, array<string, mixed>> $categoryNameMap id => row (expects name, description)
43     * @param array<int> $ids ordered list from root to leaf
44     * @param string|null $startPageName Optional start page name (defaults to Translation msgHome)
45     * @param string $startPageDescription Optional start page description
46     * @param string|null $allCategoriesName Optional all categories name (defaults to Translation msgShowAllCategories)
47     * @param string $allCategoriesDescription Optional all categories description
48     * @return array<int, array{id:int, name:string, description:string}>
49     */
50    public function buildFromIdsWithStartPage(
51        array $categoryNameMap,
52        array $ids,
53        ?string $startPageName = null,
54        string $startPageDescription = '',
55        ?string $allCategoriesName = null,
56        string $allCategoriesDescription = '',
57    ): array {
58        // Add the start page as the first segment
59        $segments = [
60            [
61                'id' => -1,
62                'name' => $startPageName ?? Translation::getString('msgHome'),
63                'description' => $startPageDescription,
64            ],
65            [
66                'id' => 0,
67                'name' => $allCategoriesName ?? Translation::getString('msgShowAllCategories'),
68                'description' => $allCategoriesDescription,
69            ],
70        ];
71
72        // Add category segments
73        $categorySegments = $this->buildCategorySegments($categoryNameMap, $ids);
74        return array_merge($segments, $categorySegments);
75    }
76
77    /**
78     * Builds category segments from category map and IDs.
79     *
80     * @param array<int, array<string, mixed>> $categoryNameMap id => row (expects name, description)
81     * @param array<int> $ids ordered list from root to leaf
82     * @return array<int, array{id:int, name:string, description:string}>
83     */
84    private function buildCategorySegments(array $categoryNameMap, array $ids): array
85    {
86        $segments = [];
87        foreach ($ids as $id) {
88            if (!array_key_exists($id, $categoryNameMap)) {
89                continue;
90            }
91
92            $row = $categoryNameMap[$id];
93            $segments[] = [
94                'id' => $id,
95                'name' => (string) ($row['name'] ?? ''),
96                'description' => (string) ($row['description'] ?? ''),
97            ];
98        }
99
100        return $segments;
101    }
102}