AbTesting   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 129
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 64
c 1
b 0
f 0
dl 0
loc 129
rs 10
wmc 20

8 Methods

Rating   Name   Duplication   Size   Complexity  
A configureOptimizely() 0 14 4
A configureDbal() 0 6 2
A handleConfiguration() 0 25 4
A configureReports() 0 8 2
A configreDecisions() 0 16 4
A configureDisabledUserAgents() 0 7 2
A handleDefaultParameters() 0 4 1
A addConfig() 0 23 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright (C) 2020-2025 Iain Cambridge
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by
10
 * the Free Software Foundation, either version 2.1 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 Lesser 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\AbTesting\Decider\EnabledDeciderInterface;
25
use Parthenon\Common\Exception\ParameterNotSetException;
26
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
27
use Symfony\Component\Config\FileLocator;
28
use Symfony\Component\DependencyInjection\ContainerBuilder;
29
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
30
use Symfony\Component\DependencyInjection\Reference;
31
32
final class AbTesting implements ModuleConfigurationInterface
33
{
34
    public function addConfig(NodeBuilder $nodeBuilder): void
35
    {
36
        $nodeBuilder->arrayNode('ab_testing')
37
            ->children()
38
                ->booleanNode('enabled')->end()
39
                ->scalarNode('provider')->defaultValue('parthenon')->end()
0 ignored issues
show
Bug introduced by
The method scalarNode() 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

39
                ->/** @scrutinizer ignore-call */ scalarNode('provider')->defaultValue('parthenon')->end()
Loading history...
40
                ->arrayNode('optimizely')
41
                    ->children()
42
                        ->scalarNode('api_key')->end()
43
                    ->end()
44
                ->end()
45
                ->arrayNode('parthenon')
46
                    ->children()
47
                        ->scalarNode('report_handler_service')->end()
48
                        ->scalarNode('dbal_connection_service')->end()
49
                        ->booleanNode('predefined_decisions_enabled')->end()
50
                        ->scalarNode('predefined_decisions_redis_service')->end()
51
                        ->booleanNode('log_user_results')->end()
52
                        ->arrayNode('disabled_user_agents')->scalarPrototype()->end()
53
                    ->end()
54
                ->end()
55
                ->end()
56
            ->end();
57
    }
58
59
    public function handleDefaultParameters(ContainerBuilder $container): void
60
    {
61
        $container->setParameter('parthenon.ab_testing.disabled_user_agents', []);
62
        $container->setParameter('parthenon_abtesting_decsions_enabled', false);
63
    }
64
65
    public function handleConfiguration(array $config, ContainerBuilder $container): void
66
    {
67
        if (!isset($config['ab_testing']) || !isset($config['ab_testing']['enabled']) || false == $config['ab_testing']['enabled']) {
68
            return;
69
        }
70
        $container->setParameter('parthenon_abtesting_enabled', true);
71
72
        $container->registerForAutoconfiguration(EnabledDeciderInterface::class)->addTag('parthenon.ab_testing.decider');
73
74
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../../Resources/config'));
75
76
        $config = $this->configureReports($config, $container);
77
78
        $config = $this->configureDisabledUserAgents($config, $container);
79
80
        $config = $this->configreDecisions($config, $container, $loader);
81
82
        $logUserResults = $config['ab_testing']['parthenon']['log_user_results'] ?? false;
83
        $container->setParameter('ab_testing_log_user_results', $logUserResults);
84
85
        $config = $this->configureOptimizely($config, $container, $loader);
86
87
        $this->configureDbal($config, $container, $loader);
88
        $loader->load('services/ab_testing.xml');
89
        $loader->load('services/ab_testing/parthenon.xml');
90
    }
91
92
    /**
93
     * @throws \Exception
94
     */
95
    private function configureDbal(array $config, ContainerBuilder $container, XmlFileLoader $loader): void
96
    {
97
        if (isset($config['ab_testing']['parthenon']['dbal_connection_service'])) {
98
            $container->setAlias('parthenon_ab_dbal_connection', $config['ab_testing']['parthenon']['dbal_connection_service']);
99
100
            $loader->load('services/ab_testing_dbal.xml');
101
        }
102
    }
103
104
    private function configureReports(array $config, ContainerBuilder $container): array
105
    {
106
        if (isset($config['ab_testing']['report_handler_service'])) {
107
            $definition = $container->getDefinition('parthenon.ab_testing.report.generator');
108
            $definition->addMethodCall('setGenerationHandler', [new Reference($config['ab_testing']['parthenon']['report_handler_service'])]);
109
        }
110
111
        return $config;
112
    }
113
114
    private function configureDisabledUserAgents(mixed $config, ContainerBuilder $container): mixed
115
    {
116
        if (isset($config['ab_testing']['disabled_user_agents'])) {
117
            $container->setParameter('parthenon.ab_testing.disabled_user_agents', $config['ab_testing']['parthenon']['disabled_user_agents']);
118
        }
119
120
        return $config;
121
    }
122
123
    /**
124
     * @throws \Exception
125
     */
126
    private function configreDecisions(mixed $config, ContainerBuilder $container, XmlFileLoader $loader): mixed
127
    {
128
        if (isset($config['ab_testing']['predefined_decisions_enabled']) && true === $config['ab_testing']['parthenon']['predefined_decisions_enabled']) {
129
            if (!isset($config['ab_testing']['predefined_decisions_redis_service'])) {
130
                throw new \Exception('Redis service is not defined');
131
            }
132
133
            $container->setParameter('parthenon_abtesting_decsions_enabled', true);
134
            $container->setAlias('parthenon.ab_testing.decider.choice_decider.cache_redis', $config['ab_testing']['parthenon']['predefined_decisions_redis_service']);
135
            $loader->load('services/ab_testing_decision_cache.xml');
136
137
            $definition = $container->getDefinition('parthenon.ab_testing.decider.choice_decider.decider_manager');
138
            $definition->addMethodCall('addDecider', [new Reference('parthenon.ab_testing.decider.choice_decider.predefined_choice')]);
139
        }
140
141
        return $config;
142
    }
143
144
    /**
145
     * @throws ParameterNotSetException
146
     */
147
    private function configureOptimizely(mixed $config, ContainerBuilder $container, XmlFileLoader $loader): mixed
148
    {
149
        if (isset($config['ab_testing']['provider']) && 'optimizely' === strtolower($config['ab_testing']['provider'])) {
150
            if (!isset($config['ab_testing']['optimizely']['api_key'])) {
151
                throw new ParameterNotSetException('If parthenon.abtesting.provider is optimizely then the parthenon.ab_testing.optimizely.api_key must be set.');
152
            }
153
            $container->setParameter('parthenon_ab_testing_optimizely_api_key', $config['ab_testing']['optimizely']['api_key']);
154
155
            $loader->load('services/ab_testing/optimizely.xml');
156
157
            $loader->load('services/ab_testing.xml');
158
        }
159
160
        return $config;
161
    }
162
}
163