Completed
Push — master ( 6d57a0...58b1d8 )
by Tobias
04:42
created

Neo4jExtension::handleConnections()   B

Complexity

Conditions 6
Paths 12

Size

Total Lines 29
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 6.0061

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 17
cts 18
cp 0.9444
rs 8.439
c 0
b 0
f 0
cc 6
eloc 18
nc 12
nop 2
crap 6.0061
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Neo4j\Neo4jBundle\DependencyInjection;
6
7
use GraphAware\Bolt\Driver as BoltDriver;
8
use GraphAware\Neo4j\Client\Connection\Connection;
9
use GraphAware\Neo4j\OGM\EntityManager;
10
use GraphAware\Neo4j\Client\HttpDriver\Driver as HttpDriver;
11
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
12
use Symfony\Component\Config\FileLocator;
13
use Symfony\Component\DependencyInjection\ContainerBuilder;
14
use Symfony\Component\DependencyInjection\Definition;
15
use Symfony\Component\DependencyInjection\DefinitionDecorator;
16
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
17
use Symfony\Component\DependencyInjection\Reference;
18
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
19
20
/**
21
 * @author Tobias Nyholm <[email protected]>
22
 */
23
class Neo4jExtension extends Extension
24
{
25
    /**
26
     * {@inheritdoc}
27
     */
28 4
    public function load(array $configs, ContainerBuilder $container)
29
    {
30 4
        $configuration = $this->getConfiguration($configs, $container);
31 4
        $config = $this->processConfiguration($configuration, $configs);
32
33 4
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
34 4
        $loader->load('services.xml');
35
36 4
        $this->handleConnections($config, $container);
37 4
        $clientServiceIds = $this->handleClients($config, $container);
38
39 4
        if ($this->validateEntityManagers($config)) {
40 4
            $loader->load('entity_manager.xml');
41 4
            $this->handleEntityMangers($config, $container, $clientServiceIds);
42 4
            $container->setAlias('neo4j.entity_manager', 'neo4j.entity_manager.default');
43
        }
44
45
        // add aliases for the default services
46 4
        $container->setAlias('neo4j.connection', 'neo4j.connection.default');
47 4
        $container->setAlias('neo4j.client', 'neo4j.client.default');
48
49
        // Configure toolbar
50 4
        if ($this->isConfigEnabled($container, $config['profiling'])) {
51 2
            $loader->load('data-collector.xml');
52
        }
53 4
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58 4
    public function getConfiguration(array $config, ContainerBuilder $container): Configuration
59
    {
60 4
        return new Configuration($container->getParameter('kernel.debug'));
61
    }
62
63
    /**
64
     * {@inheritdoc}
65
     */
66 4
    public function getAlias(): string
67
    {
68 4
        return 'neo4j';
69
    }
70
71
    /**
72
     * @param array            $config
73
     * @param ContainerBuilder $container
74
     *
75
     * @return array with service ids
76
     */
77 4
    private function handleClients(array &$config, ContainerBuilder $container): array
78
    {
79 4
        if (empty($config['clients'])) {
80
            // Add default entity manager if none set.
81 4
            $config['clients']['default'] = ['connections' => ['default']];
82
        }
83
84 4
        $serviceIds = [];
85 4
        foreach ($config['clients'] as $name => $data) {
86 4
            $connections = [];
87 4
            $serviceIds[$name] = $serviceId = sprintf('neo4j.client.%s', $name);
88 4
            foreach ($data['connections'] as $connectionName) {
89 4
                if (empty($config['connections'][$connectionName])) {
90
                    throw new InvalidConfigurationException(sprintf(
91
                        'Client "%s" is configured to use connection named "%s" but there is no such connection',
92
                        $name,
93
                        $connectionName
94
                    ));
95
                }
96 4
                $connections[] = $connectionName;
97
            }
98 4
            if (empty($connections)) {
99
                $connections[] = 'default';
100
            }
101
102
            $container
103 4
                ->setDefinition($serviceId, new DefinitionDecorator('neo4j.client.abstract'))
104 4
                ->setArguments([$connections]);
105
        }
106
107 4
        return $serviceIds;
108
    }
109
110
    /**
111
     * @param array            $config
112
     * @param ContainerBuilder $container
113
     * @param array            $clientServiceIds
114
     *
115
     * @return array
116
     */
117 4
    private function handleEntityMangers(array &$config, ContainerBuilder $container, array $clientServiceIds): array
118
    {
119 4
        $serviceIds = [];
120 4
        foreach ($config['entity_managers'] as $name => $data) {
121 4
            $serviceIds[] = $serviceId = sprintf('neo4j.entity_manager.%s', $name);
122 4
            $clientName = $data['client'];
123 4
            if (empty($clientServiceIds[$clientName])) {
124
                throw new InvalidConfigurationException(sprintf(
125
                    'EntityManager "%s" is configured to use client named "%s" but there is no such client',
126
                    $name,
127
                    $clientName
128
                ));
129
            }
130
            $container
131 4
                ->setDefinition($serviceId, new DefinitionDecorator('neo4j.entity_manager.abstract'))
132 4
                ->setArguments([
133 4
                    $container->getDefinition($clientServiceIds[$clientName]),
134 4
                    empty($data['cache_dir']) ? $container->getParameter('kernel.cache_dir').'/neo4j' : $data['cache_dir'],
135
                ]);
136
        }
137
138 4
        return $serviceIds;
139
    }
140
141
    /**
142
     * @param array            $config
143
     * @param ContainerBuilder $container
144
     *
145
     * @return array with service ids
146
     */
147 4
    private function handleConnections(array &$config, ContainerBuilder $container): array
148
    {
149 4
        $serviceIds = [];
150 4
        $firstName = null;
151 4
        foreach ($config['connections'] as $name => $data) {
152 4
            if ($firstName === null || $name === 'default') {
153 4
                $firstName = $name;
154
            }
155 4
            $def = new Definition(Connection::class);
156 4
            $def->addArgument($name);
157 4
            $def->addArgument($this->getUrl($data));
158 4
            $serviceIds[$name] = $serviceId = 'neo4j.connection.'.$name;
159 4
            $container->setDefinition($serviceId, $def);
160
        }
161
162
        // Make sure we got a 'default'
163 4
        if ($firstName !== 'default') {
164
            $config['connections']['default'] = $config['connections'][$firstName];
165
        }
166
167
        // Add connections to connection manager
168 4
        $connectionManager = $container->getDefinition('neo4j.connection_manager');
169 4
        foreach ($serviceIds as $name => $serviceId) {
170 4
            $connectionManager->addMethodCall('registerExistingConnection', [$name, new Reference($serviceId)]);
171
        }
172 4
        $connectionManager->addMethodCall('setMaster', [$firstName]);
173
174 4
        return $serviceIds;
175
    }
176
177
    /**
178
     * Get URL form config.
179
     *
180
     * @param array $config
181
     *
182
     * @return string
183
     */
184 4
    private function getUrl(array $config): string
185
    {
186 4
        return sprintf(
187 4
            '%s://%s:%s@%s:%d',
188 4
            $config['scheme'],
189 4
            $config['username'],
190 4
            $config['password'],
191 4
            $config['host'],
192 4
            $this->getPort($config)
193
        );
194
    }
195
196
    /**
197
     * Return the correct default port if not manually set.
198
     *
199
     * @param array $config
200
     *
201
     * @return int
202
     */
203 4
    private function getPort(array $config)
204
    {
205 4
        if (isset($config['port'])) {
206 3
            return $config['port'];
207
        }
208
209 1
        return 'http' == $config['scheme'] ? HttpDriver::DEFAULT_HTTP_PORT : BoltDriver::DEFAULT_TCP_PORT;
210
    }
211
212
    /**
213
     * Make sure the EntityManager is installed if we have configured it.
214
     *
215
     * @param array &$config
216
     *
217
     * @return bool true if "graphaware/neo4j-php-ogm" is installed
218
     *
219
     * @thorws \LogicException if EntityManagers os not installed but they are configured.
220
     */
221 4
    private function validateEntityManagers(array &$config): bool
222
    {
223 4
        $dependenciesInstalled = class_exists(EntityManager::class);
224 4
        $entityManagersConfigured = !empty($config['entity_managers']);
225
226 4
        if ($dependenciesInstalled && !$entityManagersConfigured) {
227
            // Add default entity manager if none set.
228 4
            $config['entity_managers']['default'] = ['client' => 'default'];
229
        } elseif (!$dependenciesInstalled && $entityManagersConfigured) {
230
            throw new \LogicException(
231
                'You need to install "graphaware/neo4j-php-ogm" to be able to use the EntityManager'
232
            );
233
        }
234
235 4
        return $dependenciesInstalled;
236
    }
237
}
238