Completed
Push — master ( 6cb661...4c7e7c )
by
unknown
13:11
created

Neo4jExtension   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 215
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 86.02%

Importance

Changes 0
Metric Value
wmc 30
lcom 1
cbo 9
dl 0
loc 215
ccs 80
cts 93
cp 0.8602
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
B load() 0 26 3
A getConfiguration() 0 4 1
A getAlias() 0 4 1
B handleConnections() 0 29 6
A getUrl() 0 11 1
A getPort() 0 8 3
B validateEntityManagers() 0 16 5
B handleClients() 0 32 6
B handleEntityMangers() 0 23 4
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'))
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
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'))
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
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