Completed
Push — master ( da5872...2f4ad1 )
by Tobias
05:23
created

Neo4jExtension::getPort()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

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