Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.15% covered (success)
96.15%
25 / 26
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
TenantContextResolver
96.15% covered (success)
96.15%
25 / 26
66.67% covered (warning)
66.67%
2 / 3
10
0.00% covered (danger)
0.00%
0 / 1
 resolve
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
3
 readIntEnv
83.33% covered (success)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
4.07
 readStringEnv
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3/**
4 * Tenant context resolver
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 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-02-08
16 */
17
18declare(strict_types=1);
19
20namespace phpMyFAQ\Tenant;
21
22use phpMyFAQ\Database;
23use Symfony\Component\HttpFoundation\Request;
24
25class TenantContextResolver
26{
27    public function resolve(?Request $request = null): TenantContext
28    {
29        $request ??= Request::createFromGlobals();
30        $hostname = $request->getHost();
31
32        if ($hostname === '') {
33            $hostname = 'localhost';
34        }
35
36        $configDir = defined('PMF_CONFIG_DIR') ? (string) PMF_CONFIG_DIR : '';
37        $tablePrefix = Database::getTablePrefix();
38
39        $tenantId = $this->readIntEnv('PMF_TENANT_ID') ?? 0;
40        $plan = $this->readStringEnv('PMF_TENANT_PLAN') ?? 'free';
41
42        $quotas = new TenantQuotas(
43            $this->readIntEnv('PMF_TENANT_QUOTA_MAX_FAQS'),
44            $this->readIntEnv('PMF_TENANT_QUOTA_MAX_ATTACHMENT_SIZE'),
45            $this->readIntEnv('PMF_TENANT_QUOTA_MAX_USERS'),
46            $this->readIntEnv('PMF_TENANT_QUOTA_MAX_API_REQUESTS'),
47            $this->readIntEnv('PMF_TENANT_QUOTA_MAX_CATEGORIES'),
48        );
49
50        return new TenantContext($tenantId, $hostname, $tablePrefix, $configDir, $plan, $quotas);
51    }
52
53    private function readIntEnv(string $key): ?int
54    {
55        $value = getenv($key);
56        if ($value === false || $value === '') {
57            return null;
58        }
59
60        if (!is_numeric($value)) {
61            return null;
62        }
63
64        return (int) $value;
65    }
66
67    private function readStringEnv(string $key): ?string
68    {
69        $value = getenv($key);
70        if ($value === false || $value === '') {
71            return null;
72        }
73
74        return trim($value);
75    }
76}