Passed
Push — master ( 3880dd...1a3c5e )
by Ilario
04:06
created

ClientRegistry::getClient()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 14
nc 6
nop 2
dl 0
loc 24
ccs 7
cts 7
cp 1
crap 4
rs 9.7998
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Facile\MongoDbBundle\Services;
6
7
use Facile\MongoDbBundle\Capsule\Client as BundleClient;
8
use Facile\MongoDbBundle\Event\ConnectionEvent;
9
use Facile\MongoDbBundle\Models\ClientConfiguration;
10
use Facile\MongoDbBundle\Services\DriverOptions\DriverOptionsInterface;
11
use MongoDB\Client;
12
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
13
use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy;
14
15
/**
16
 * Class ClientRegistry.
17
 *
18
 * @internal
19
 */
20
final class ClientRegistry
21
{
22
    /** @var Client[] */
23
    private $clients;
24
25
    /** @var ClientConfiguration[] */
26
    private $configurations;
27
28
    /** @var bool */
29
    private $debug;
30
31
    /** @var EventDispatcherInterface */
32
    private $eventDispatcher;
33
34
    /** @var DriverOptionsInterface */
35
    private $driverOptionsService;
36
37
    /**
38 31
     * ClientRegistry constructor.
39
     *
40 31
     * @param EventDispatcherInterface $eventDispatcher
41 31
     * @param bool $debug
42 31
     * @param DriverOptionsInterface|null $driverOptionsService
43 31
     */
44 31
    public function __construct(
45
        EventDispatcherInterface $eventDispatcher,
46
        bool $debug,
47
        ?DriverOptionsInterface $driverOptionsService
48
    ) {
49 31
        $this->clients = [];
50
        $this->configurations = [];
51 31
        $this->debug = $debug;
52 31
        $this->eventDispatcher = $eventDispatcher;
53
        $this->driverOptionsService = $driverOptionsService;
54 31
    }
55
56
    /**
57
     * @param array $configurations
58
     */
59
    public function addClientsConfigurations(array $configurations)
60 31
    {
61
        foreach ($configurations as $name => $conf) {
62 31
            $this->addClientConfiguration($name, $conf);
63 31
        }
64
    }
65
66
    /**
67
     * @param string $name
68
     * @param array  $conf
69
     */
70 31
    private function addClientConfiguration(string $name, array $conf)
71
    {
72 31
        $this->configurations[$name] = $this->buildClientConfiguration($conf);
73 30
    }
74
75
    /**
76 31
     * @param array $conf
77 31
     *
78 31
     * @return ClientConfiguration
79 31
     */
80 31
    private function buildClientConfiguration(array $conf): ClientConfiguration
81
    {
82 31
        if (! $conf['uri']) {
83 31
            $conf['uri'] = $this->buildConnectionUri($conf['hosts']);
84 31
        }
85 31
86
        $conf['driverOptions'] = [];
87
        if ($this->driverOptionsService instanceof DriverOptionsInterface) {
0 ignored issues
show
introduced by
$this->driverOptionsService is always a sub-type of Facile\MongoDbBundle\Ser...\DriverOptionsInterface.
Loading history...
88
            $conf['driverOptions'] = $this->driverOptionsService->buildDriverOptions($conf);
89
        }
90
91
        return new ClientConfiguration(
92
            $conf['uri'],
93
            $conf['username'],
94
            $conf['password'],
95 30
            $conf['authSource'],
96
            [
97 30
                'replicaSet' => $conf['replicaSet'],
98 30
                'ssl' => $conf['ssl'],
99 30
                'connectTimeoutMS' => $conf['connectTimeoutMS'],
100 30
                'readPreference' => $conf['readPreference'],
101 30
            ],
102 30
            $conf['driverOptions']
103 30
        );
104
    }
105
106
    /**
107
     * @param array $hosts
108
     *
109
     * @return string
110
     */
111
    private function buildConnectionUri(array $hosts): string
112
    {
113
        return 'mongodb://' . implode(
114 11
            ',',
115
            array_map(
116 11
                function (array $host) {
117
                    return sprintf('%s:%d', $host['host'], $host['port']);
118
                },
119
                $hosts
120
            )
121
        );
122 2
    }
123
124 2
    /**
125
     * @param string $name
126
     * @param string $databaseName
127
     *
128
     * @return Client
129
     */
130
    public function getClientForDatabase(string $name, string $databaseName): Client
131
    {
132
        return $this->getClient($name, $databaseName);
133 29
    }
134
135 29
    /**
136
     * @return array
137 29
     */
138 29
    public function getClientNames(): array
139 29
    {
140
        return array_keys($this->clients);
141 29
    }
142 29
143
    /**
144 29
     * @param string $name
145
     * @param string $databaseName
146 29
     *
147
     * @return Client
148 29
     */
149 29
    public function getClient(string $name, string $databaseName = null): Client
150 29
    {
151
        $clientKey = null !== $databaseName ? $name . '.' . $databaseName : $name;
152
153
        if (! isset($this->clients[$clientKey])) {
154 29
            $conf = $this->configurations[$name];
155
            $options = array_merge(
156
                [
157
                    'database' => $databaseName,
158
                    'authSource' => $conf->getAuthSource() ?? $databaseName ?? 'admin',
159
                ],
160
                $conf->getOptions()
161
            );
162
            $this->clients[$clientKey] = $this->buildClient($name, $conf->getUri(), $options, $conf->getDriverOptions());
163
164
            $event = new ConnectionEvent($clientKey);
165 29
            if (class_exists(LegacyEventDispatcherProxy::class)) {
166
                $this->eventDispatcher->dispatch($event, ConnectionEvent::CLIENT_CREATED);
0 ignored issues
show
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with Facile\MongoDbBundle\Eve...onEvent::CLIENT_CREATED. ( Ignorable by Annotation )

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

166
                $this->eventDispatcher->/** @scrutinizer ignore-call */ 
167
                                        dispatch($event, ConnectionEvent::CLIENT_CREATED);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
167 29
            } else {
168 5
                $this->eventDispatcher->dispatch(ConnectionEvent::CLIENT_CREATED, $event);
0 ignored issues
show
Bug introduced by
Facile\MongoDbBundle\Eve...onEvent::CLIENT_CREATED of type string is incompatible with the type object expected by parameter $event of Symfony\Contracts\EventD...erInterface::dispatch(). ( Ignorable by Annotation )

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

168
                $this->eventDispatcher->dispatch(/** @scrutinizer ignore-type */ ConnectionEvent::CLIENT_CREATED, $event);
Loading history...
169
            }
170
        }
171 24
172
        return $this->clients[$clientKey];
173
    }
174
175
    /**
176
     * @param string $clientName
177
     * @param string $uri
178
     * @param array  $options
179
     * @param array  $driverOptions
180
     *
181
     * @return Client
182
     */
183
    private function buildClient(string $clientName, string $uri, array $options, array $driverOptions): Client
184
    {
185
        if (true === $this->debug) {
186
            return new BundleClient($uri, $options, $driverOptions, $clientName, $this->eventDispatcher);
187
        }
188
189
        return new Client($uri, $options, $driverOptions);
190
    }
191
}
192