Completed
Push — master ( a814e0...392de1 )
by Tobias
24:09
created

BazingaGeocoderExtension::getConfiguration()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
1
<?php
2
3
/**
4
 * This file is part of the BazingaGeocoderBundle package.
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @license    MIT License
9
 */
10
namespace Bazinga\Bundle\GeocoderBundle\DependencyInjection;
11
12
use Bazinga\Bundle\GeocoderBundle\ProviderFactory\ProviderFactoryInterface;
13
use Geocoder\Provider\Provider;
14
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
15
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
16
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
17
use Symfony\Component\DependencyInjection\ContainerBuilder;
18
use Symfony\Component\DependencyInjection\Definition;
19
use Symfony\Component\DependencyInjection\Reference;
20
use Symfony\Component\Config\FileLocator;
21
use Symfony\Component\Config\Definition\Processor;
22
23
/**
24
 * William Durand <[email protected]>.
25
 */
26
class BazingaGeocoderExtension extends Extension
27
{
28
    public function load(array $configs, ContainerBuilder $container)
29
    {
30
        $processor = new Processor();
31
        $configuration = $this->getConfiguration($configs, $container);
32
        $config = $processor->processConfiguration($configuration, $configs);
0 ignored issues
show
Bug introduced by
It seems like $configuration defined by $this->getConfiguration($configs, $container) on line 31 can be null; however, Symfony\Component\Config...: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...
33
34
        $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
35
        $loader->load('services.yml');
36
37
        if ($config['profiling']) {
38
            $loader->load('profiling.yml');
39
        }
40
        $this->loadProviders($container, $config);
41
42
        if (!empty($config['fake_ip']) && true === $config['fake_ip']['enabled']) {
43
            $definition = $container->getDefinition('bazinga_geocoder.event_listener.fake_request');
44
            $definition->replaceArgument(0, $config['fake_ip']['ip']);
45
46
            $tag = current($definition->getTag('kernel.event_listener'));
47
            $tag['priority'] = $config['fake_ip']['priority'];
48
            $tags = array('kernel.event_listener' => array($tag));
49
            $definition->setTags($tags);
50
        } else {
51
            $container->removeDefinition('bazinga_geocoder.event_listener.fake_request');
52
        }
53
    }
54
55
    private function loadProviders(ContainerBuilder $container, array $config)
56
    {
57
        foreach ($config['providers'] as $providerName => $providerConfig) {
58
            $factoryService = $container->getDefinition($providerConfig['factory']);
59
            $factoryClass = $factoryService->getClass() ?: $providerConfig['factory'];
60
            if (!(is_a($factoryClass, ProviderFactoryInterface::class))) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
61
                //throw new \LogicException(sprintf('Provider factory "%s" must implement ProviderFactoryInterface', $providerConfig['factory']));
0 ignored issues
show
Unused Code Comprehensibility introduced by
73% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
62
            }
63
            $factoryClass::validate($providerConfig['options'], $providerName);
64
65
            // See if any option has a service reference
66
            $providerConfig['options'] = $this->findReferences($providerConfig['options']);
67
68
            $serviceId = 'bazinga_geocoder.provider.'.$providerName;
69
            $def = $container->register($serviceId, Provider::class);
70
            $def->setFactory([new Reference($providerConfig['factory']), 'createProvider'])
71
                ->addArgument($providerConfig['options']);
72
73
            $def->addTag('bazinga_geocoder.provider');
74
            foreach ($providerConfig['aliases'] as $alias) {
75
                $container->setAlias($alias, $serviceId);
76
            }
77
78
            $this->configureCache($container, $serviceId, $providerConfig);
79
        }
80
    }
81
82
    /**
83
     * Add cache to a provider if needed.
84
     *
85
     * @param ContainerBuilder $
86
     * @param string $serviceId
87
     * @param array $providerConfig
88
     */
89
    private function configureCache(ContainerBuilder $container, string $serviceId, array $providerConfig)
90
    {
91
        if (
92
            (null !== $providerConfig['cache'] || null !== $providerConfig['cache_lifetime']) &&
93
            !class_exists(ProviderCache::class)
94
        ) {
95
            throw new \LogicException('You must install "geocoder-php/chain-provider" to use cache.');
96
        }
97
98
        if (null !== $cacheServiceId = $providerConfig['cache']) {
99
            if (!$container->has('app.cache\'')) {
100
                throw new \LogicException('You need to specify a service for cache.');
101
            }
102
            $cacheServiceId = 'app.cache';
103
        }
104
105
        $container->register($serviceId.'.cache', ProviderCache::class)
106
            ->setDecoratedService($serviceId)
107
            ->setArguments([
108
                new Reference($serviceId.'.cache.inner'),
109
                new Reference($cacheServiceId),
110
                $providerConfig['cache_lifetime']
111
            ]);
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117
    public function getConfiguration(array $config, ContainerBuilder $container)
118
    {
119
        return new Configuration($container->getParameter('kernel.debug'));
120
    }
121
122
    /**
123
     * @param array $options
124
     *
125
     * @return array
126
     */
127
    private function findReferences(array $options)
128
    {
129
        foreach ($options as $key => $value) {
130
            if (is_array($value)) {
131
                $options[$key] = $this->findReferences($value);
132
            } elseif (substr($key, -8) === '_service' || strpos($value, '@') === 0 || $key === 'service') {
133
                $options[$key] = new Reference(ltrim($value, '@'));
134
            }
135
        }
136
137
        return $options;
138
    }
139
}
140