Passed
Push — main ( 662c49...013415 )
by Iain
18:11
created

CurrentTenantProvider::setTenant()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright (C) 2020-2024 Iain Cambridge
7
 *
8
 *     This program is free software: you can redistribute it and/or modify
9
 *     it under the terms of the GNU General Public License as published by
10
 *     the Free Software Foundation, either version 3 of the License, or
11
 *     (at your option) any later version.
12
 *
13
 *     This program is distributed in the hope that it will be useful,
14
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *     GNU General Public License for more details.
17
 *
18
 *     You should have received a copy of the GNU General Public License
19
 *     along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
namespace Parthenon\MultiTenancy\TenantProvider;
23
24
use Parthenon\Common\Exception\NoEntityFoundException;
25
use Parthenon\MultiTenancy\Entity\Tenant;
26
use Parthenon\MultiTenancy\Entity\TenantInterface;
27
use Parthenon\MultiTenancy\Exception\NoTenantFoundException;
28
use Parthenon\MultiTenancy\Repository\TenantRepositoryInterface;
29
use Symfony\Component\HttpFoundation\Request;
30
use Symfony\Component\HttpFoundation\RequestStack;
31
32
final class CurrentTenantProvider implements TenantProviderInterface
33
{
34
    private TenantInterface $tenant;
35
    private bool $previouslyFailed = false;
36
37
    public function __construct(
38
        private TenantRepositoryInterface $tenantRepository,
39
        private RequestStack $requestStack,
40
        private string $defaultDatabase,
41
        private string $domain,
42
    ) {
43
    }
44
45
    public function setTenant(TenantInterface $tenant): void
46
    {
47
        $this->tenant = $tenant;
48
    }
49
50
    /**
51
     * @throws NoTenantFoundException
52
     */
53
    public function getCurrentTenant(bool $refresh = false): TenantInterface
54
    {
55
        if (isset($this->tenant) && !$refresh) {
56
            return $this->tenant;
57
        }
58
59
        $request = $this->requestStack->getMainRequest();
60
61
        if (!$request instanceof Request) {
62
            return Tenant::createWithSubdomainAndDatabase($this->defaultDatabase, 'dummy.subdomain');
63
        }
64
65
        $host = $request->getHost();
66
        if (!str_ends_with($host, $this->domain)) {
67
            return Tenant::createWithSubdomainAndDatabase($this->defaultDatabase, 'dummy.subdomain');
68
        }
69
        $subdomain = preg_replace('~^([a-z0-9-]+)(\..*)$~', '$1', $host);
70
71
        if ($this->previouslyFailed && !$refresh) {
72
            // If it's already failed other attempts by other possible factors will fail too.
73
            throw new NoTenantFoundException(sprintf('Previously Unable to find tenant for \'%s\'', $subdomain), $e->getCode(), $e);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $e seems to be never defined.
Loading history...
74
        }
75
76
        try {
77
            $this->tenant = $this->tenantRepository->findBySubdomain($subdomain);
78
        } catch (NoEntityFoundException $e) {
79
            $this->previouslyFailed = true;
80
            throw new NoTenantFoundException(sprintf('Unable to find tenant for \'%s\'', $subdomain), $e->getCode(), $e);
81
        }
82
83
        return $this->tenant;
84
    }
85
}
86