Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
MetaController
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
2 / 2
3
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 index
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3/**
4 * The Metadata Controller for the REST API
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 2023-2026 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     2026-04-11
16 */
17
18declare(strict_types=1);
19
20namespace phpMyFAQ\Controller\Api;
21
22use OpenApi\Attributes as OA;
23use phpMyFAQ\Api\MetaService;
24use phpMyFAQ\Api\OAuthDiscoveryService;
25use phpMyFAQ\Controller\AbstractController;
26use Symfony\Component\HttpFoundation\JsonResponse;
27use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
28use Symfony\Component\Routing\Attribute\Route;
29
30final class MetaController extends AbstractController
31{
32    private MetaService $metaService;
33
34    public function __construct(?MetaService $metaService = null)
35    {
36        parent::__construct();
37        $this->metaService = $metaService ?? new MetaService(
38            $this->configuration,
39            new OAuthDiscoveryService($this->configuration),
40        );
41
42        if (!$this->isApiEnabled()) {
43            throw new UnauthorizedHttpException(challenge: 'API is not enabled');
44        }
45    }
46
47    #[OA\Get(path: '/api/v4.0/meta', operationId: 'getMeta', tags: ['Public Endpoints'])]
48    #[OA\Response(
49        response: 200,
50        description: 'Returns bootstrap metadata for the phpMyFAQ instance.',
51        content: new OA\JsonContent(properties: [
52            new OA\Property(property: 'version', type: 'string', example: '4.0.0'),
53            new OA\Property(property: 'title', type: 'string', example: 'phpMyFAQ Codename Porus'),
54            new OA\Property(property: 'language', type: 'string', example: 'en'),
55            new OA\Property(property: 'availableLanguages', type: 'object', example: [
56                'de' => 'German',
57                'en' => 'English',
58            ]),
59            new OA\Property(property: 'enabledFeatures', type: 'object'),
60            new OA\Property(
61                property: 'publicLogoUrl',
62                type: 'string',
63                example: 'https://localhost/assets/images/logo-transparent.svg',
64            ),
65            new OA\Property(property: 'themeColors', type: 'object', example: [
66                'light' => [
67                    '--bs-primary' => '#083c83',
68                    '--bs-body-bg' => '#ffffff',
69                ],
70                'dark' => [
71                    '--bs-primary' => '#083c83',
72                    '--bs-body-bg' => 'var(--bs-dark)',
73                ],
74                'highContrast' => [
75                    '--bs-primary' => '#ffff00',
76                    '--bs-body-bg' => '#000000',
77                ],
78            ]),
79            new OA\Property(property: 'oauthDiscovery', type: 'object'),
80        ]),
81    )]
82    #[Route(path: 'v4.0/meta', name: 'api.meta', methods: ['GET'])]
83    public function index(): JsonResponse
84    {
85        return $this->json($this->metaService->getPublicMetadata());
86    }
87}