Passed
Push — main ( b3247a...904d89 )
by Iain
20:40
created

MultiTenancy::handleConfiguration()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 9
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 17
rs 9.9666
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\DependencyInjection\Modules;
23
24
use Parthenon\Common\Exception\ParameterNotSetException;
25
use Parthenon\MultiTenancy\Creator\MessengerTenantCreator;
26
use Parthenon\MultiTenancy\Creator\TenantCreatorInterface;
27
use Parthenon\MultiTenancy\Database\DatabaseCreatorInterface;
28
use Parthenon\MultiTenancy\Database\DbalDatabaseCreator;
29
use Parthenon\MultiTenancy\Database\DigitalOceanDatabaseCreator;
30
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
31
use Symfony\Component\Config\FileLocator;
32
use Symfony\Component\DependencyInjection\ContainerBuilder;
33
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
34
35
final class MultiTenancy implements ModuleConfigurationInterface
36
{
37
    public function addConfig(NodeBuilder $nodeBuilder): void
38
    {
39
        $nodeBuilder
40
            ->arrayNode('multi_tenancy')
41
                ->children()
42
                    ->booleanNode('enabled')->defaultFalse()->end()
43
                    ->booleanNode('background_creation')->defaultFalse()->end()
0 ignored issues
show
Bug introduced by
The method booleanNode() does not exist on Symfony\Component\Config...der\NodeParentInterface. It seems like you code against a sub-type of Symfony\Component\Config...der\NodeParentInterface such as Symfony\Component\Config...ion\Builder\NodeBuilder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

43
                    ->/** @scrutinizer ignore-call */ booleanNode('background_creation')->defaultFalse()->end()
Loading history...
44
                    ->scalarNode('domain')->end()
45
                    ->arrayNode('doctrine')
46
                        ->children()
47
                            ->scalarNode('dbal_connection')->end()
48
                            ->scalarNode('global_dbal_connection')->end()
49
                            ->scalarNode('orm_entity_manager')->end()
50
                            ->scalarNode('default_database')->end()
51
                        ->end()
52
                    ->end()
53
                    ->scalarNode('database_creation_strategy')->end()
54
                    ->arrayNode('migrations')
55
                        ->children()
56
                            ->scalarNode('directory')->end()
57
                        ->end()
58
                    ->end()
59
                    ->arrayNode('digitalocean')
60
                        ->children()
61
                            ->scalarNode('cluster_id')->end()
62
                        ->end()
63
                    ->end()
64
                ->end()
65
            ->end();
66
    }
67
68
    public function handleDefaultParameters(ContainerBuilder $container): void
69
    {
70
        $container->setParameter('parthenon_multi_tenancy_domain', '');
71
        $container->setParameter('parthenon_multi_tenancy_migrations_directory', '');
72
        $container->setParameter('parthenon_multi_tenancy_background_creation', false);
73
        $container->setParameter('parthenon_multi_tenancy_dbal_connection', '');
74
        $container->setParameter('parthenon_multi_tenancy_global_dbal_connection', '');
75
        $container->setParameter('parthenon_multi_tenancy_orm_entity_manager', '');
76
        $container->setParameter('parthenon_multi_tenancy_default_database', 'dummy_database');
77
        $container->setParameter('parthenon_multi_tenancy_digitalocean_cluster_id', '');
78
        $container->setParameter('parthenon_multi_tenancy_is_enabled', false);
79
    }
80
81
    public function handleConfiguration(array $config, ContainerBuilder $container): void
82
    {
83
        if (!isset($config['multi_tenancy']['enabled']) || !$config['multi_tenancy']['enabled']) {
84
            return;
85
        }
86
        $container->setParameter('parthenon_multi_tenancy_enabled', true);
87
88
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../../Resources/config'));
89
        $loader->load('services/multi_tenancy.xml');
90
91
        $this->configureMultiTenancy($config, $container);
92
93
        $bundles = $container->getParameter('kernel.bundles');
94
95
        $bundles = $this->configureDoctrine($bundles, $loader);
96
97
        $this->configureMongoDb($bundles, $loader);
98
    }
99
100
    private function configureMultiTenancy(array $config, ContainerBuilder $container): void
101
    {
102
        if (isset($config['multi_tenancy'])) {
103
            $multiTenancyConfig = $config['multi_tenancy'];
104
            $enabled = $multiTenancyConfig['enabled'] ?? false;
105
            $backgroundCreation = $multiTenancyConfig['background_creation'] ?? false;
106
107
            $container->setParameter('parthenon_multi_tenancy_is_enabled', $enabled);
108
            $container->setParameter('parthenon_multi_tenancy_background_creation', $backgroundCreation);
109
110
            if (isset($multiTenancyConfig['domain'])) {
111
                $container->setParameter('parthenon_multi_tenancy_domain', $multiTenancyConfig['domain']);
112
            } elseif (!isset($multiTenancyConfig['domain']) && $enabled) {
113
                throw new ParameterNotSetException('parthenon.multi_tenancy.domain must be set when multi_tenancy is enabled');
114
            }
115
116
            $this->configureMigrations($config, $container);
117
            $this->configureDoctrineConfig($config, $container);
118
            $this->configureTenantCreator($backgroundCreation, $container);
119
120
            $this->handleDatabaseCreationStrategy($multiTenancyConfig['database_creation_strategy'] ?? 'dbal', $container);
121
122
            $container->setParameter('parthenon_multi_tenancy_digitalocean_cluster_id', $multiTenancyConfig['digitalocean']['cluster_id'] ?? '');
123
        }
124
    }
125
126
    private function configureTenantCreator(bool $creatorBackground, ContainerBuilder $containerBuilder): void
127
    {
128
        if ($creatorBackground) {
129
            $containerBuilder->setAlias(TenantCreatorInterface::class, MessengerTenantCreator::class);
130
        }
131
    }
132
133
    private function configureMigrations(array $config, ContainerBuilder $containerBuilder): void
134
    {
135
        if (!isset($config['multi_tenancy']['migrations'])) {
136
            return;
137
        }
138
139
        $containerBuilder->setParameter('parthenon_multi_tenancy_migrations_directory', $config['multi_tenancy']['migrations']['directory'] ?? '');
140
    }
141
142
    private function configureDoctrineConfig(array $config, ContainerBuilder $containerBuilder): void
143
    {
144
        if (!isset($config['multi_tenancy']['doctrine'])) {
145
            return;
146
        }
147
148
        $containerBuilder->setParameter('parthenon_multi_tenancy_global_dbal_connection', $config['multi_tenancy']['doctrine']['global_dbal_connection'] ?? '');
149
        $containerBuilder->setParameter('parthenon_multi_tenancy_dbal_connection', $config['multi_tenancy']['doctrine']['dbal_connection'] ?? '');
150
        $containerBuilder->setParameter('parthenon_multi_tenancy_orm_entity_manager', $config['multi_tenancy']['doctrine']['orm_entity_manager'] ?? '');
151
        $containerBuilder->setParameter('parthenon_multi_tenancy_default_database', $config['multi_tenancy']['doctrine']['default_database'] ?? 'dummy_database');
152
    }
153
154
    /**
155
     * @throws \Exception
156
     */
157
    private function configureDoctrine(float|array|bool|int|string|null $bundles, XmlFileLoader $loader): string|int|bool|array|float|null
158
    {
159
        if (isset($bundles['DoctrineBundle'])) {
160
            $loader->load('services/orm/multi_tenancy.xml');
161
        }
162
163
        return $bundles;
164
    }
165
166
    /**
167
     * @throws \Exception
168
     */
169
    private function configureMongoDb(float|int|bool|array|string|null $bundles, XmlFileLoader $loader): void
170
    {
171
        if (isset($bundles['DoctrineMongoDBBundle'])) {
172
            $loader->load('services/odm/multi_tenancy.xml');
173
        }
174
    }
175
176
    /**
177
     * @throws ParameterNotSetException
178
     */
179
    private function handleDatabaseCreationStrategy($database_creation_strategy, ContainerBuilder $containerBuilder): void
180
    {
181
        $databaseCreationStrategy = strtolower($database_creation_strategy);
182
183
        switch ($databaseCreationStrategy) {
184
            case 'dbal':
185
                $id = DbalDatabaseCreator::class;
186
                break;
187
            case 'digitalocean':
188
                $id = DigitalOceanDatabaseCreator::class;
189
                break;
190
            default:
191
                throw new ParameterNotSetException(sprintf("'%s' is not a valid option for multi_tenancy.database_creation_strategy", $databaseCreationStrategy));
192
        }
193
194
        $containerBuilder->setAlias(DatabaseCreatorInterface::class, $id);
195
    }
196
}
197