EntityManagerFactory::getConnection()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 18
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
c 1
b 0
f 0
nc 3
nop 3
dl 0
loc 18
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arp\LaminasDoctrine\Factory\Service\EntityManager;
6
7
use Arp\LaminasDoctrine\Config\EntityManagerConfigs;
8
use Arp\LaminasDoctrine\Service\Configuration\ConfigurationManagerInterface;
9
use Arp\LaminasDoctrine\Service\Configuration\Exception\ConfigurationManagerException;
10
use Arp\LaminasDoctrine\Service\Connection\ConnectionManagerInterface;
11
use Arp\LaminasDoctrine\Service\Connection\Exception\ConnectionManagerException;
12
use Arp\LaminasFactory\AbstractFactory;
13
use Doctrine\Common\EventManager;
14
use Doctrine\DBAL\Connection;
15
use Doctrine\ORM\Configuration;
16
use Doctrine\ORM\EntityManager;
17
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
18
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
19
use Laminas\ServiceManager\ServiceLocatorInterface;
20
use Psr\Container\ContainerExceptionInterface;
21
use Psr\Container\ContainerInterface;
22
23
final class EntityManagerFactory extends AbstractFactory
24
{
25
    /**
26
     * @param ContainerInterface&ServiceLocatorInterface $container
27
     * @param array<string, mixed>|null $options
28
     *
29
     * @throws ServiceNotCreatedException
30
     * @throws ServiceNotFoundException
31
     * @throws ContainerExceptionInterface
32
     */
33
    public function __invoke(ContainerInterface $container, string $requestedName, array $options = null): EntityManager
34
    {
35
        /** @var EntityManagerConfigs $configs */
36
        $configs = $this->getService($container, EntityManagerConfigs::class, $requestedName);
37
38
        $entityManagerConfig = $options ?? $configs->getEntityManagerConfig($requestedName);
39
40
        $connection = $entityManagerConfig['connection'] ?? null;
41
        if (null === $connection) {
42
            throw new ServiceNotCreatedException(
43
                sprintf(
44
                    'The required \'connection\' configuration option is missing for service \'%s\'',
45
                    $requestedName
46
                )
47
            );
48
        }
49
50
        $configuration = $entityManagerConfig['configuration'] ?? null;
51
        if (null === $configuration) {
52
            throw new ServiceNotCreatedException(
53
                sprintf(
54
                    'The required \'configuration\' configuration option is missing for service \'%s\'',
55
                    $requestedName
56
                )
57
            );
58
        }
59
60
        $eventManager = $entityManagerConfig['event_manager'] ?? null;
61
        try {
62
            return new EntityManager(
63
                $this->getConnection($container, $connection, $requestedName),
64
                $this->getConfiguration($container, $configuration, $requestedName),
65
                $this->getEventManager($container, $eventManager, $requestedName),
66
            );
67
        } catch (\Throwable $e) {
68
            throw new ServiceNotCreatedException(
69
                sprintf('Failed to create entity manager instance \'%s\': %s', $requestedName, $e->getMessage()),
70
                $e->getCode(),
71
                $e
72
            );
73
        }
74
    }
75
76
    /**
77
     * @param ContainerInterface $container
78
     * @param string|array<string, mixed>|Connection $connection
79
     *
80
     * @throws ServiceNotCreatedException
81
     * @throws ServiceNotFoundException
82
     * @throws ContainerExceptionInterface
83
     */
84
    private function getConnection(
85
        ContainerInterface $container,
86
        string|array|Connection $connection,
87
        string $serviceName
88
    ): Connection {
89
        if ($connection instanceof Connection) {
0 ignored issues
show
introduced by
$connection is never a sub-type of Doctrine\DBAL\Connection.
Loading history...
90
            return $connection;
91
        }
92
93
        /** @var ConnectionManagerInterface $connectionManager */
94
        $connectionManager = $this->getService($container, ConnectionManagerInterface::class, $serviceName);
95
96
        if (is_array($connection)) {
0 ignored issues
show
introduced by
The condition is_array($connection) is always true.
Loading history...
97
            $connectionManager->addConnectionConfig($serviceName, $connection);
98
            $connection = $serviceName;
99
        }
100
101
        return $this->loadConnection($connectionManager, $connection, $serviceName);
102
    }
103
104
    /**
105
     * @param ConnectionManagerInterface $connectionManager
106
     * @param string $name
107
     * @param string $serviceName
108
     *
109
     * @return Connection
110
     *
111
     * @throws ServiceNotCreatedException
112
     */
113
    private function loadConnection(
114
        ConnectionManagerInterface $connectionManager,
115
        string $name,
116
        string $serviceName
117
    ): Connection {
118
        if (!$connectionManager->hasConnection($name)) {
119
            throw new ServiceNotCreatedException(
120
                sprintf(
121
                    'Failed to load connection \'%s\' for service \'%s\': '
122
                    . 'The connection has not been registered with the connection manager',
123
                    $name,
124
                    $serviceName
125
                )
126
            );
127
        }
128
129
        try {
130
            return $connectionManager->getConnection($name);
131
        } catch (ConnectionManagerException $e) {
132
            throw new ServiceNotCreatedException(
133
                sprintf('Failed to load connection \'%s\' for service \'%s\'', $name, $serviceName),
134
                $e->getCode(),
135
                $e
136
            );
137
        }
138
    }
139
140
    /**
141
     * @param Configuration|string|array<string, mixed> $configuration
142
     *
143
     * @throws ServiceNotCreatedException
144
     * @throws ServiceNotFoundException
145
     * @throws ContainerExceptionInterface
146
     */
147
    private function getConfiguration(
148
        ServiceLocatorInterface $container,
149
        string|array|Configuration $configuration,
150
        string $serviceName
151
    ): Configuration {
152
        if (is_object($configuration)) {
0 ignored issues
show
introduced by
The condition is_object($configuration) is always false.
Loading history...
153
            return $configuration;
154
        }
155
156
        /** @var ConfigurationManagerInterface $configurationManager */
157
        $configurationManager = $this->getService($container, ConfigurationManagerInterface::class, $serviceName);
158
159
        if (is_array($configuration)) {
0 ignored issues
show
introduced by
The condition is_array($configuration) is always true.
Loading history...
160
            $configurationManager->addConfigurationConfig($serviceName, $configuration);
161
            $configuration = $serviceName;
162
        }
163
164
        return $this->loadConfiguration($configurationManager, $configuration, $serviceName);
165
    }
166
167
    /**
168
     * @param ConfigurationManagerInterface $configurationManager
169
     * @param string $name
170
     * @param string $serviceName
171
     *
172
     * @return Configuration
173
     *
174
     * @throws ServiceNotCreatedException
175
     */
176
    private function loadConfiguration(
177
        ConfigurationManagerInterface $configurationManager,
178
        string $name,
179
        string $serviceName
180
    ): Configuration {
181
        if (!$configurationManager->hasConfiguration($name)) {
182
            throw new ServiceNotCreatedException(
183
                sprintf(
184
                    'Failed to load configuration \'%s\' for service \'%s\': '
185
                    . 'The configuration has not been registered with the configuration manager',
186
                    $name,
187
                    $serviceName
188
                )
189
            );
190
        }
191
192
        try {
193
            return $configurationManager->getConfiguration($name);
194
        } catch (ConfigurationManagerException $e) {
195
            throw new ServiceNotCreatedException(
196
                sprintf('Failed to load configuration \'%s\' for service \'%s\'', $name, $serviceName),
197
                $e->getCode(),
198
                $e
199
            );
200
        }
201
    }
202
203
    /**
204
     * @throws ContainerExceptionInterface
205
     * @throws ServiceNotFoundException
206
     * @throws ServiceNotCreatedException
207
     */
208
    private function getEventManager(
209
        ContainerInterface $container,
210
        string|EventManager|null $eventManager,
211
        string $serviceName
212
    ): EventManager {
213
        $eventManager ??= new EventManager();
214
215
        if (is_object($eventManager)) {
216
            return $eventManager;
217
        }
218
219
        $eventManager = $this->getService($container, $eventManager, $serviceName);
220
221
        if (!$eventManager instanceof EventManager) {
222
            throw new ServiceNotCreatedException(
223
                sprintf(
224
                    'The event manager must be an object of type \'%s\'; \'%s\' provided for service \'%s\'',
225
                    EventManager::class,
226
                    is_object($eventManager) ? get_class($eventManager) : gettype($eventManager),
227
                    $serviceName,
228
                ),
229
            );
230
        }
231
232
        return $eventManager;
233
    }
234
}
235