Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
BreadcrumbsBuilder
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
3 / 3
5
100.00% covered (success)
100.00%
1 / 1
 buildFromIds
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 buildFromIdsWithStartPage
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
1
 buildCategorySegments
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3/**
4 * Category breadcrumb builder class
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public License,
7 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
8 * obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * @package   phpMyFAQ
11 * @author    Thorsten Rinne <thorsten@phpmyfaq.de>
12 * @copyright 2025 phpMyFAQ Team
13 * @license   https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
14 * @link      https://www.phpmyfaq.de
15 * @since     2025-10-18
16 */
17
18declare(strict_types=1);
19
20namespace phpMyFAQ\Category\Navigation;
21
22use phpMyFAQ\Translation;
23
24/**
25 * Builds breadcrumb segments from a category map and a list of ids.
26 */
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}