ConnectionHelperFactory   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 127
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 50
c 1
b 0
f 0
dl 0
loc 127
rs 10
wmc 13

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getConnection() 0 35 5
A __invoke() 0 26 4
A resolveConnection() 0 26 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arp\LaminasDoctrine\Factory\Console\Helper;
6
7
use Arp\LaminasDoctrine\Console\Helper\ConnectionHelper;
8
use Arp\LaminasDoctrine\Factory\Service\EntityManager\EntityManagerFactoryProviderTrait;
9
use Arp\LaminasDoctrine\Factory\Service\EntityManager\ObjectManagerArgvInputProviderTrait;
10
use Arp\LaminasDoctrine\Service\Connection\ConnectionManagerInterface;
11
use Arp\LaminasDoctrine\Service\Connection\Exception\ConnectionManagerException;
12
use Arp\LaminasFactory\AbstractFactory;
13
use Doctrine\DBAL\Connection;
14
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
15
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
16
use Psr\Container\ContainerExceptionInterface;
17
use Psr\Container\ContainerInterface;
18
use Symfony\Component\Console\Input\ArgvInput;
19
20
final class ConnectionHelperFactory extends AbstractFactory
21
{
22
    use ObjectManagerArgvInputProviderTrait;
23
    use EntityManagerFactoryProviderTrait;
24
25
    /**
26
     * @param ContainerInterface $container
27
     * @param string $requestedName
28
     * @param array<string, mixed>|null $options
29
     *
30
     * @return ConnectionHelper
31
     *
32
     * @throws ServiceNotCreatedException
33
     * @throws ServiceNotFoundException
34
     * @throws ContainerExceptionInterface
35
     */
36
    public function __invoke(
37
        ContainerInterface $container,
38
        string $requestedName,
39
        array $options = null
40
    ): ConnectionHelper {
41
        $options = $options ?? $this->getServiceOptions($container, $requestedName);
42
43
        if (empty($options['connection'])) {
44
            $options['connection'] = $this->resolveConnection($container, $requestedName);
45
        }
46
47
        if (!empty($options['default_connection'])) {
48
            $options['connection'] = $options['default_connection'];
49
        }
50
51
        if (empty($options['connection'])) {
52
            throw new ServiceNotCreatedException(
53
                sprintf(
54
                    'The required \'connection\' configuration option is missing for service \'%s\'',
55
                    $requestedName
56
                )
57
            );
58
        }
59
60
        return new ConnectionHelper(
61
            $this->getConnection($container, $options['connection'], $requestedName)
62
        );
63
    }
64
65
    /**
66
     * @param ContainerInterface $container
67
     * @param string             $serviceName
68
     *
69
     * @return Connection|string|null
70
     *
71
     * @throws ServiceNotCreatedException
72
     */
73
    private function resolveConnection(ContainerInterface $container, string $serviceName): Connection|string|null
74
    {
75
        try {
76
            $arguments = new ArgvInput();
77
78
            // First check if we require a specific connection
79
            if ($arguments->hasOption('--connection')) {
80
                /** @var string $connectionName */
81
                $connectionName = $arguments->getOption('--connection');
82
                return $connectionName;
83
            }
84
85
            // Fall back to checking if we provided a --object-manager option
86
            $objectManagerName = $this->getEntityManagerArgvInput();
87
            if (!empty($objectManagerName)) {
88
                return $this->getEntityManager($container, $objectManagerName, $serviceName)->getConnection();
89
            }
90
        } catch (\Throwable $e) {
91
            throw new ServiceNotCreatedException(
92
                sprintf('Failed to resolve connection for service \'%s\': %s', $serviceName, $e->getMessage()),
93
                $e->getCode(),
94
                $e
95
            );
96
        }
97
98
        return null;
99
    }
100
101
    /**
102
     * @param ContainerInterface $container
103
     * @param string|Connection|mixed $connection
104
     * @param string $serviceName
105
     *
106
     * @return Connection
107
     *
108
     * @throws ServiceNotCreatedException
109
     * @throws ServiceNotFoundException
110
     * @throws ContainerExceptionInterface
111
     */
112
    private function getConnection(ContainerInterface $container, mixed $connection, string $serviceName): Connection
113
    {
114
        if (is_string($connection)) {
115
            $connectionName = $connection;
116
117
            /** @var ConnectionManagerInterface $connectionManager */
118
            $connectionManager = $this->getService($container, ConnectionManagerInterface::class, $serviceName);
119
120
            try {
121
                $connection = $connectionManager->getConnection($connection);
122
            } catch (ConnectionManagerException $e) {
123
                throw new ServiceNotCreatedException(
124
                    sprintf(
125
                        'The connection \'%s\' could not be found for service \'%s\'',
126
                        $connectionName,
127
                        $serviceName
128
                    ),
129
                    $e->getCode(),
130
                    $e
131
                );
132
            }
133
        }
134
135
        if (!$connection instanceof Connection) {
136
            throw new ServiceNotCreatedException(
137
                sprintf(
138
                    'The connection must be an object of type \'%s\'; \'%s\' provided for service \'%s\'',
139
                    Connection::class,
140
                    (is_object($connection) ? get_class($connection) : gettype($connection)),
141
                    $serviceName
142
                )
143
            );
144
        }
145
146
        return $connection;
147
    }
148
}
149