Completed
Push — master ( 2f4ad1...18c7f8 )
by
unknown
11:43
created

Neo4jExtension::handleConnections()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5.009

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 13
cts 14
cp 0.9286
rs 8.6737
c 0
b 0
f 0
cc 5
eloc 14
nc 6
nop 2
crap 5.009
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);
1 ignored issue
show
Bug introduced by
It seems like $configuration defined by $this->getConfiguration($configs, $container) on line 30 can be null; however, Symfony\Component\Depend...:processConfiguration() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
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 4
        if ($this->validateEntityManagers($config)) {
39 4
            $loader->load('entity_manager.xml');
40 4
            $this->handleEntityMangers($config, $container, $clientServiceIds);
41
        }
42
43
        // add aliases for the default services
44 4
        $container->setAlias('neo4j.connection', 'neo4j.connection.default');
45 4
        $container->setAlias('neo4j.client', 'neo4j.client.default');
46 4
        $container->setAlias('neo4j.entity_manager', 'neo4j.entity_manager.default');
47
48
        // Configure toolbar
49 4
        if ($this->isConfigEnabled($container, $config['profiling'])) {
50 2
            $loader->load('data-collector.xml');
51
52 2
            $container->getDefinition('neo4j.factory.client')
53 2
                ->replaceArgument(0, new Reference('neo4j.client_logger'));
54
        }
55 4
    }
56
57
    /**
58
     * {@inheritdoc}
59
     */
60 4
    public function getConfiguration(array $config, ContainerBuilder $container): Configuration
61
    {
62 4
        return new Configuration($container->getParameter('kernel.debug'));
63
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68 4
    public function getAlias(): string
69
    {
70 4
        return 'neo4j';
71
    }
72
73
    /**
74
     * @param array            $config
75
     * @param ContainerBuilder $container
76
     *
77
     * @return array with service ids
78
     */
79 4
    private function handleClients(array &$config, ContainerBuilder $container): array
80
    {
81 4
        if (empty($config['clients'])) {
82
            // Add default entity manager if none set.
83 4
            $config['clients']['default'] = ['connections' => ['default']];
84
        }
85
86 4
        $serviceIds = [];
87 4
        foreach ($config['clients'] as $name => $data) {
88 4
            $serviceIds[$name] = $serviceId = sprintf('neo4j.client.%s', $name);
89 4
            $urls = [];
90 4
            foreach ($data['connections'] as $connectionName) {
91 4
                if (empty($config['connections'][$connectionName])) {
92
                    throw new InvalidConfigurationException(sprintf(
93
                        'Client "%s" is configured to use connection named "%s" but there is no such connection',
94
                        $name,
95
                        $connectionName
96
                    ));
97
                }
98 4
                $urls[] = $this->getUrl($config['connections'][$connectionName]);
99
            }
100 4
            if (empty($urls)) {
101
                $urls[] = $this->getUrl($config['connections']['default']);
102
            }
103
104
            $container
105 4
                ->setDefinition($serviceId, new DefinitionDecorator('neo4j.client.abstract'))
106 4
                ->setArguments([$urls]);
107
        }
108
109 4
        return $serviceIds;
110
    }
111
112
    /**
113
     * @param array            $config
114
     * @param ContainerBuilder $container
115
     * @param array            $clientServiceIds
116
     *
117
     * @return array
118
     */
119 4
    private function handleEntityMangers(array &$config, ContainerBuilder $container, array $clientServiceIds): array
120
    {
121 4
        $serviceIds = [];
122 4
        foreach ($config['entity_managers'] as $name => $data) {
123 4
            $serviceIds[] = $serviceId = sprintf('neo4j.entity_manager.%s', $name);
124 4
            $clientName = $data['client'];
125 4
            if (empty($clientServiceIds[$clientName])) {
126
                throw new InvalidConfigurationException(sprintf(
127
                    'EntityManager "%s" is configured to use client named "%s" but there is no such client',
128
                    $name,
129
                    $clientName
130
                ));
131
            }
132
            $container
133 4
                ->setDefinition($serviceId, new DefinitionDecorator('neo4j.entity_manager.abstract'))
134 4
                ->setArguments([
135 4
                    $container->getDefinition($clientServiceIds[$clientName]),
136 4
                    empty($data['cache_dir']) ? $container->getParameter('kernel.cache_dir').'/neo4j' : $data['cache_dir'],
137
                ]);
138
        }
139
140 4
        return $serviceIds;
141
    }
142
143
    /**
144
     * @param array            $config
145
     * @param ContainerBuilder $container
146
     *
147
     * @return array with service ids
148
     */
149 4
    private function handleConnections(array &$config, ContainerBuilder $container): array
150
    {
151 4
        $serviceIds = [];
152 4
        $firstName = null;
153 4
        foreach ($config['connections'] as $name => $data) {
154 4
            if ($firstName === null || $name === 'default') {
155 4
                $firstName = $name;
156
            }
157 4
            $def = new Definition(Connection::class);
158 4
            $def->addArgument($name);
159 4
            $def->addArgument($this->getUrl($data));
160 4
            $serviceIds[] = $serviceId = 'neo4j.connection.'.$name;
161 4
            $container->setDefinition($serviceId, $def);
162
        }
163
164
        // Make sure we got a 'default'
165 4
        if ($firstName !== 'default') {
166
            $config['connections']['default'] = $config['connections'][$firstName];
167
        }
168
169 4
        return $serviceIds;
170
    }
171
172
    /**
173
     * Get URL form config.
174
     *
175
     * @param array $config
176
     *
177
     * @return string
178
     */
179 4
    private function getUrl(array $config): string
180
    {
181 4
        return sprintf(
182 4
            '%s://%s:%s@%s:%d',
183 4
            $config['schema'],
184 4
            $config['username'],
185 4
            $config['password'],
186 4
            $config['host'],
187 4
            $this->getPort($config)
188
        );
189
    }
190
191
    /**
192
     * Return the correct default port if not manually set.
193
     *
194
     * @param array $config
195
     *
196
     * @return int
197
     */
198 4
    private function getPort(array $config)
199
    {
200 4
        if (isset($config['port'])) {
201 3
            return $config['port'];
202
        }
203
204 1
        return 'http' == $config['schema'] ? HttpDriver::DEFAULT_HTTP_PORT : BoltDriver::DEFAULT_TCP_PORT;
205
    }
206
207
    /**
208
     * Make sure the EntityManager is installed if we have configured it.
209
     *
210
     * @param array &$config
211
     *
212
     * @return bool true if "graphaware/neo4j-php-ogm" is installed
213
     *
214
     * @thorws \LogicException if EntityManagers os not installed but they are configured.
215
     */
216 4
    private function validateEntityManagers(array &$config): bool
217
    {
218 4
        $dependenciesInstalled = class_exists(EntityManager::class);
219 4
        $entityManagersConfigured = !empty($config['entity_managers']);
220
221 4
        if ($dependenciesInstalled && !$entityManagersConfigured) {
222
            // Add default entity manager if none set.
223 4
            $config['entity_managers']['default'] = ['client' => 'default'];
224
        } elseif (!$dependenciesInstalled && $entityManagersConfigured) {
225
            throw new \LogicException(
226
                'You need to install "graphaware/neo4j-php-ogm" to be able to use the EntityManager'
227
            );
228
        }
229
230 4
        return $dependenciesInstalled;
231
    }
232
}
233