Completed
Push — master ( 6c4efe...df4b6e )
by Tobias
08:17
created

DependencyInjection/BazingaGeocoderExtension.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
11
namespace Bazinga\GeocoderBundle\DependencyInjection;
12
13
use Bazinga\GeocoderBundle\DataCollector\GeocoderDataCollector;
14
use Bazinga\GeocoderBundle\Plugin\FakeIpPlugin;
15
use Bazinga\GeocoderBundle\Plugin\ProfilingPlugin;
16
use Bazinga\GeocoderBundle\ProviderFactory\PluginProviderFactory;
17
use Bazinga\GeocoderBundle\ProviderFactory\ProviderFactoryInterface;
18
use Geocoder\Plugin\Plugin\CachePlugin;
19
use Geocoder\Plugin\Plugin\LimitPlugin;
20
use Geocoder\Plugin\Plugin\LocalePlugin;
21
use Geocoder\Plugin\Plugin\LoggerPlugin;
22
use Geocoder\Plugin\PluginProvider;
23
use Geocoder\Provider\Cache\ProviderCache;
24
use Symfony\Component\Config\Definition\Processor;
25
use Symfony\Component\Config\FileLocator;
26
use Symfony\Component\DependencyInjection\ContainerBuilder;
27
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
28
use Symfony\Component\DependencyInjection\Reference;
29
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
30
31
/**
32
 * William Durand <[email protected]>.
33
 */
34
class BazingaGeocoderExtension extends Extension
35
{
36 23
    public function load(array $configs, ContainerBuilder $container)
37
    {
38 23
        $processor = new Processor();
39 23
        $configuration = $this->getConfiguration($configs, $container);
40 23
        $config = $processor->processConfiguration($configuration, $configs);
41
42 23
        $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
43 23
        $loader->load('services.yml');
44
45 23
        if (true === $config['profiling']['enabled']) {
46 1
            $loader->load('profiling.yml');
47
        }
48
49 23
        if ($config['fake_ip']['enabled']) {
50
            $definition = $container->getDefinition(FakeIpPlugin::class);
51
            $definition->replaceArgument(1, $config['fake_ip']['ip']);
52
        } else {
53 23
            $container->removeDefinition(FakeIpPlugin::class);
54
        }
55
56 23
        $this->loadProviders($container, $config);
57 23
    }
58
59 23
    private function loadProviders(ContainerBuilder $container, array $config)
60
    {
61 23
        foreach ($config['providers'] as $providerName => $providerConfig) {
62 22
            $factoryService = $container->getDefinition($providerConfig['factory']);
63 22
            $factoryClass = $factoryService->getClass() ?: $providerConfig['factory'];
64 22
            if (!class_implements($factoryClass, ProviderFactoryInterface::class)) {
65
                throw new \LogicException(sprintf('Provider factory "%s" must implement ProviderFactoryInterface', $providerConfig['factory']));
66
            }
67 22
            $factoryClass::validate($providerConfig['options'], $providerName);
68
69
            // See if any option has a service reference
70 22
            $providerConfig['options'] = $this->findReferences($providerConfig['options']);
71
72 22
            $serviceId = 'bazinga_geocoder.provider.'.$providerName;
73 22
            $plugins = $this->configureProviderPlugins($container, $providerConfig, $serviceId);
74
75 22
            $def = $container->register($serviceId, PluginProvider::class)
76 22
                ->setFactory([PluginProviderFactory::class, 'createPluginProvider'])
77 22
                ->addArgument($plugins)
78 22
                ->addArgument(new Reference($providerConfig['factory']))
79 22
                ->addArgument($providerConfig['options']);
80
81 22
            $def->addTag('bazinga_geocoder.provider');
82 22
            foreach ($providerConfig['aliases'] as $alias) {
83 22
                $container->setAlias($alias, $serviceId);
84
            }
85
        }
86 23
    }
87
88
    /**
89
     * Configure plugins for a client.
90
     *
91
     * @param ContainerBuilder $container
92
     * @param array            $config
93
     * @param string           $providerServiceId
94
     *
95
     * @return array
96
     */
97 22
    public function configureProviderPlugins(ContainerBuilder $container, array $config, string $providerServiceId): array
98
    {
99 22
        $plugins = [];
100 22
        foreach ($config['plugins'] as $plugin) {
101
            $plugins[] = $plugin['id'];
102
        }
103
104 22
        if (isset($config['cache']) || isset($config['cache_lifetime'])) {
105 1 View Code Duplication
            if (null === $cacheServiceId = $config['cache']) {
106
                if (!$container->has('app.cache')) {
107
                    throw new \LogicException('You need to specify a service for cache.');
108
                }
109
                $cacheServiceId = 'app.cache';
110
            }
111 1
            $plugins[] = $providerServiceId.'.cache';
112 1
            $container->register($providerServiceId.'.cache', CachePlugin::class)
113 1
                ->setPublic(false)
114 1
                ->setArguments([new Reference($cacheServiceId), (int) $config['cache_lifetime']]);
115
        }
116
117 22 View Code Duplication
        if (isset($config['limit'])) {
118
            $plugins[] = $providerServiceId.'.limit';
119
            $container->register($providerServiceId.'.limit', LimitPlugin::class)
120
                ->setPublic(false)
121
                ->setArguments([(int) $config['limit']]);
122
        }
123
124 22 View Code Duplication
        if (isset($config['locale'])) {
125
            $plugins[] = $providerServiceId.'.locale';
126
            $container->register($providerServiceId.'.locale', LocalePlugin::class)
127
                ->setPublic(false)
128
                ->setArguments([$config['locale']]);
129
        }
130
131 22 View Code Duplication
        if (isset($config['logger'])) {
132
            $plugins[] = $providerServiceId.'.logger';
133
            $container->register($providerServiceId.'.logger', LoggerPlugin::class)
134
                ->setPublic(false)
135
                ->setArguments([new Reference($config['logger'])]);
136
        }
137
138 22
        if ($container->has(FakeIpPlugin::class)) {
139
            $plugins[] = FakeIpPlugin::class;
140
        }
141
142 22
        if ($container->has(GeocoderDataCollector::class)) {
143
            $plugins[] = $providerServiceId.'.profiler';
144
            $container->register($providerServiceId.'.profiler', ProfilingPlugin::class)
145
                ->setPublic(false)
146
                ->setArguments([substr($providerServiceId, strlen('bazinga_geocoder.provider.'))])
147
                ->addTag('bazinga_geocoder.profiling_plugin');
148
        }
149
150 22
        return array_map(function (string $id) {
151 1
            return new Reference($id);
152 22
        }, $plugins);
153
    }
154
155
    /**
156
     * Add cache to a provider if needed.
157
     *
158
     * @param ContainerBuilder $
159
     * @param string $serviceId
160
     * @param array  $providerConfig
161
     */
162
    private function configureCache(ContainerBuilder $container, string $serviceId, array $providerConfig)
0 ignored issues
show
This method is not used, and could be removed.
Loading history...
163
    {
164
        if (null === $providerConfig['cache'] && null === $providerConfig['cache_lifetime']) {
165
            return;
166
        }
167
168
        if (!class_exists(ProviderCache::class)) {
169
            throw new \LogicException('You must install "geocoder-php/cache-provider" to use cache.');
170
        }
171
172 View Code Duplication
        if (null === $cacheServiceId = $providerConfig['cache']) {
173
            if (!$container->has('app.cache')) {
174
                throw new \LogicException('You need to specify a service for cache.');
175
            }
176
            $cacheServiceId = 'app.cache';
177
        }
178
179
        $container->register($serviceId.'.cache', ProviderCache::class)
180
            ->setDecoratedService($serviceId)
181
            ->setArguments([
182
                new Reference($serviceId.'.cache.inner'),
183
                new Reference($cacheServiceId),
184
                $providerConfig['cache_lifetime'],
185
            ]);
186
    }
187
188
    /**
189
     * {@inheritdoc}
190
     */
191 23
    public function getConfiguration(array $config, ContainerBuilder $container)
192
    {
193 23
        return new Configuration($container->getParameter('kernel.debug'));
194
    }
195
196
    /**
197
     * @param array $options
198
     *
199
     * @return array
200
     */
201 22
    private function findReferences(array $options)
202
    {
203 22
        foreach ($options as $key => $value) {
204 18
            if (is_array($value)) {
205 1
                $options[$key] = $this->findReferences($value);
206 18
            } elseif (substr($key, -8) === '_service' || strpos($value, '@') === 0 || $key === 'service') {
207 18
                $options[$key] = new Reference(ltrim($value, '@'));
208
            }
209
        }
210
211 22
        return $options;
212
    }
213
}
214