Completed
Pull Request — master (#162)
by Ramon
01:43
created

LiipMonitorExtension::load()   F

Complexity

Conditions 16
Paths 256

Size

Total Lines 77
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 77
rs 3.9275
c 0
b 0
f 0
cc 16
eloc 44
nc 256
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Liip\MonitorBundle\DependencyInjection;
4
5
use Doctrine\DBAL\Connection;
6
use Doctrine\DBAL\Driver\PDOSqlite\Driver;
7
use Doctrine\DBAL\Migrations\Configuration\AbstractFileConfiguration;
8
use Doctrine\DBAL\Migrations\Configuration\Configuration as MigrationConfiguration;
9
use Liip\MonitorBundle\Helper\PathHelper;
10
use Symfony\Component\Config\FileLocator;
11
use Symfony\Component\DependencyInjection\ContainerBuilder;
12
use Symfony\Component\DependencyInjection\Definition;
13
use Symfony\Component\DependencyInjection\DefinitionDecorator;
14
use Symfony\Component\DependencyInjection\Loader;
15
use Symfony\Component\DependencyInjection\Reference;
16
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
17
18
class LiipMonitorExtension extends Extension
19
{
20
    /**
21
     * Loads the services based on your application configuration.
22
     *
23
     * @param array            $configs
24
     * @param ContainerBuilder $container
25
     */
26
    public function load(array $configs, ContainerBuilder $container)
27
    {
28
        $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
29
        $loader->load('runner.xml');
30
        $loader->load('helper.xml');
31
32
        $configuration = new Configuration();
33
        $config = $this->processConfiguration($configuration, $configs);
34
35
        if (null === $config['view_template']) {
36
            $config['view_template'] = __DIR__.'/../Resources/views/health/index.html.php';
37
        }
38
39
        if ($config['enable_controller']) {
40
            $container->setParameter(sprintf('%s.view_template', $this->getAlias()), $config['view_template']);
41
            $loader->load('controller.xml');
42
        }
43
44
        if ($config['mailer']['enabled']) {
45
            $loader->load('helper/swift_mailer.xml');
46
47
            foreach ($config['mailer'] as $key => $value) {
48
                $container->setParameter(sprintf('%s.mailer.%s', $this->getAlias(), $key), $value);
49
            }
50
        }
51
52
        $container->setParameter(sprintf('%s.default_group', $this->getAlias()), $config['default_group']);
53
54
        // liip_monitor_helper is not always required
55
        if ($container->has('assets.packages')) {
56
            $helper = new Definition(PathHelper::class);
57
            $helper->setArguments(['asset.packages', 'router']);
58
            $helper->setPublic(true);
59
            $container->set('liip_monitor.helper', $helper);
60
        }
61
62
        // symfony3 does not define templating.helper.assets unless php templating is included
63
        if ($container->has('templating.helper.assets') && $container->has('liip_monitor.helper')) {
64
            $pathHelper = $container->getDefinition('liip_monitor.helper');
65
            $pathHelper->replaceArgument(0, 'templating.helper.assets');
66
        }
67
68
        // symfony3 does not define templating.helper.router unless php templating is included
69
        if ($container->has('templating.helper.router') && $container->has('liip_monitor.helper')) {
70
            $pathHelper = $container->getDefinition('liip_monitor.helper');
71
            $pathHelper->replaceArgument(1, 'templating.helper.router');
72
        }
73
74
        if (empty($config['checks'])) {
75
            return;
76
        }
77
78
        $checksLoaded = array();
79
        $containerParams = array();
80
        foreach ($config['checks']['groups'] as $group => $checks) {
81
            if (empty($checks)) {
82
                continue;
83
            }
84
85
            foreach ($checks as $check => $values) {
86
                if (empty($values)) {
87
                    continue;
88
                }
89
90
                $containerParams['groups'][$group][$check] = $values;
91
                $this->setParameters($container, $check, $group, $values);
92
93
                if (!in_array($check, $checksLoaded)) {
94
                    $loader->load('checks/'.$check.'.xml');
95
                    $checksLoaded[] = $check;
96
                }
97
            }
98
        }
99
100
        $container->setParameter(sprintf('%s.checks', $this->getAlias()), $containerParams);
101
        $this->configureDoctrineMigrationsCheck($container, $containerParams);
102
    }
103
104
    /**
105
     * @param ContainerBuilder $container
106
     * @param string           $checkName
107
     * @param string           $group
108
     * @param array            $values
109
     */
110
    private function setParameters(ContainerBuilder $container, $checkName, $group, $values)
111
    {
112
        $prefix = sprintf('%s.check.%s', $this->getAlias(), $checkName);
113
        switch ($checkName) {
114
            case 'class_exists':
115
            case 'cpu_performance':
116
            case 'php_extensions':
117
            case 'php_version':
118
            case 'php_flags':
119
            case 'readable_directory':
120
            case 'writable_directory':
121
            case 'process_running':
122
            case 'doctrine_dbal':
123
            case 'doctrine_mongodb':
124
            case 'http_service':
125
            case 'guzzle_http_service':
126
            case 'memcache':
127
            case 'redis':
128
            case 'rabbit_mq':
129
            case 'stream_wrapper_exists':
130
            case 'file_ini':
131
            case 'file_json':
132
            case 'file_xml':
133
            case 'file_yaml':
134
            case 'expressions':
135
                $container->setParameter($prefix.'.'.$group, $values);
136
                continue;
137
138
            case 'symfony_version':
139
                continue;
140
141
            case 'opcache_memory':
142
                if (!class_exists('ZendDiagnostics\Check\OpCacheMemory')) {
143
                    throw new \InvalidArgumentException('Please require at least "v1.0.4" of "ZendDiagnostics"');
144
                }
145
                continue;
146
147
            case 'doctrine_migrations':
148
                if (!class_exists('ZendDiagnostics\Check\DoctrineMigration')) {
149
                    throw new \InvalidArgumentException('Please require at least "v1.0.6" of "ZendDiagnostics"');
150
                }
151
152
                if (!class_exists('Doctrine\Bundle\MigrationsBundle\Command\DoctrineCommand')) {
153
                    throw new \InvalidArgumentException('Please require at least "v1.0.0" of "DoctrineMigrationsBundle"');
154
                }
155
156
                if (!class_exists('Doctrine\DBAL\Migrations\Configuration\Configuration')) {
157
                    throw new \InvalidArgumentException('Please require at least "v1.1.0" of "Doctrine Migrations Library"');
158
                }
159
160
                $container->setParameter($prefix.'.'.$group, $values);
161
                continue;
162
163
            case 'pdo_connections':
164
                if (!class_exists('ZendDiagnostics\Check\PDOCheck')) {
165
                    throw new \InvalidArgumentException('Please require at least "v1.0.5" of "ZendDiagnostics"');
166
                }
167
                $container->setParameter($prefix.'.'.$group, $values);
168
                continue;
169
170
        }
171
172
        if (is_array($values)) {
173
            foreach ($values as $key => $value) {
174
                $container->setParameter($prefix.'.'.$key.'.'.$group, $value);
175
            }
176
        }
177
    }
178
179
    /**
180
     * Set up doctrine migration configuration services
181
     *
182
     * @param ContainerBuilder $container The container
183
     * @param array            $params    Container params
184
     *
185
     * @return void
186
     */
187
    private function configureDoctrineMigrationsCheck(ContainerBuilder $container, array $params)
188
    {
189
        if (!$container->hasDefinition('liip_monitor.check.doctrine_migrations') || !isset($params['groups'])) {
190
            return;
191
        }
192
193
        foreach ($params['groups'] as $groupName => $groupChecks) {
194
            if (!isset($groupChecks['doctrine_migrations'])) {
195
                continue;
196
            }
197
198
            $services = [];
199
            foreach ($groupChecks['doctrine_migrations'] as $key => $config) {
200
                $serviceConfiguration =
201
                    $this->createMigrationConfigurationService($container, $config['configuration_file'], $config[ 'connection' ]);
202
203
                $serviceId = sprintf('liip_monitor.check.doctrine_migrations.configuration.%s.%s', $groupName, $key);
204
                $container->setDefinition($serviceId, $serviceConfiguration);
205
206
                $services[$key] = $serviceId;
207
            }
208
209
            $parameter = sprintf('%s.check.%s.%s', $this->getAlias(), 'doctrine_migrations', $groupName);
210
            $container->setParameter($parameter, $services);
211
        }
212
    }
213
214
    /**
215
     * Return key-value array with migration version as key and class as a value defined in config file
216
     *
217
     * @param AbstractFileConfiguration $config Current configuration
218
     * @param Connection                $connection Fake connections
219
     *
220
     * @return array[]
221
     */
222
    private function getPredefinedMigrations(AbstractFileConfiguration $config, Connection $connection)
223
    {
224
        $result = array();
225
226
        $diff = new MigrationConfiguration($connection);
227
        $diff->setMigrationsNamespace($config->getMigrationsNamespace());
228
        $diff->setMigrationsDirectory($config->getMigrationsDirectory());
229
        foreach ($config->getMigrations() as $version) {
230
            $result[$version->getVersion()] = get_class($version->getMigration());
231
        }
232
233
        foreach ($diff->getAvailableVersions() as $version) {
234
            unset($result[$version]);
235
        }
236
237
        return $result;
238
    }
239
240
    /**
241
     * Creates migration configuration service definition
242
     *
243
     * @param ContainerBuilder $container      DI Container
244
     * @param string           $filename       File name with migration configuration
245
     * @param string           $connectionName Connection name for container service
246
     *
247
     * @return DefinitionDecorator
248
     */
249
    private function createMigrationConfigurationService(ContainerBuilder $container, $filename, $connectionName)
250
    {
251
        /** @var AbstractFileConfiguration $configuration */
252
        $connection    = new Connection([], new Driver()); // needed for correct migration loading
253
        $configuration = $this->createTemporaryConfiguration($container, $connection, $filename);
254
255
        $serviceConfiguration =
256
            new DefinitionDecorator('liip_monitor.check.doctrine_migrations.abstract_configuration');
257
        $serviceConfiguration->replaceArgument(
258
            0,
259
            new Reference(sprintf('doctrine.dbal.%s_connection', $connectionName))
260
        );
261
262
        if ($configuration->getMigrationsNamespace()) {
263
            $serviceConfiguration->addMethodCall(
264
                'setMigrationsNamespace',
265
                [ $configuration->getMigrationsNamespace() ]
266
            );
267
        }
268
269
        if ($configuration->getMigrationsTableName()) {
270
            $serviceConfiguration->addMethodCall(
271
                'setMigrationsTableName',
272
                [ $configuration->getMigrationsTableName() ]
273
            );
274
        }
275
276
        if ($configuration->getMigrationsColumnName()) {
277
            $serviceConfiguration->addMethodCall(
278
                'setMigrationsColumnName',
279
                [ $configuration->getMigrationsColumnName() ]
280
            );
281
        }
282
283
        if ($configuration->getName()) {
284
            $serviceConfiguration->addMethodCall('setName', [ $configuration->getName() ]);
285
        }
286
287
        if ($configuration->getMigrationsDirectory()) {
288
            $directory        = $configuration->getMigrationsDirectory();
289
            $pathPlaceholders = array('kernel.root_dir', 'kernel.cache_dir', 'kernel.logs_dir');
290
            foreach ($pathPlaceholders as $parameter) {
291
                $kernelDir = realpath($container->getParameter($parameter));
292
                if (strpos(realpath($directory), $kernelDir) === 0) {
293
                    $directory = str_replace($kernelDir, "%{$parameter}%", $directory);
294
                    break;
295
                }
296
            }
297
298
299
            $serviceConfiguration->addMethodCall(
300
                'setMigrationsDirectory',
301
                [ $directory ]
302
            );
303
        }
304
305
        /** @var AbstractFileConfiguration $diff */
306
        $versions = $this->getPredefinedMigrations($configuration, $connection);
307
        if ($versions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $versions of type array[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
308
            $serviceConfiguration->addMethodCall('registerMigrations', [ $versions ]);
309
        }
310
311
        $serviceConfiguration->addMethodCall('configure', []);
312
313
        if ($configuration->areMigrationsOrganizedByYear()) {
314
            $serviceConfiguration->addMethodCall('setMigrationsAreOrganizedByYear', [ true ]);
315
316
            return $serviceConfiguration;
317
        } elseif ($configuration->areMigrationsOrganizedByYearAndMonth()) {
318
            $serviceConfiguration->addMethodCall('setMigrationsAreOrganizedByYearAndMonth', [ true ]);
319
320
            return $serviceConfiguration;
321
        }
322
323
        return $serviceConfiguration;
324
    }
325
326
    /**
327
     * Creates in-memory migration configuration for setting up container service
328
     *
329
     * @param ContainerBuilder $container  The container
330
     * @param Connection       $connection Fake connection
331
     * @param string           $filename   Migrations configuration file
332
     *
333
     * @return AbstractFileConfiguration
334
     */
335
    private function createTemporaryConfiguration(ContainerBuilder $container, Connection $connection, $filename)
336
    {
337
        // -------
338
        // This part must be in sync with Doctrine\DBAL\Migrations\Tools\Console\Helper\ConfigurationHelper::loadConfig
339
        $map = [
340
            'xml'  => '\XmlConfiguration',
341
            'yaml' => '\YamlConfiguration',
342
            'yml'  => '\YamlConfiguration',
343
            'php'  => '\ArrayConfiguration',
344
            'json' => '\JsonConfiguration',
345
        ];
346
        // --------
347
348
        $filename = $container->getParameterBag()->resolveValue($filename);
349
        $info     = pathinfo($filename);
350
        // check we can support this file type
351
        if (empty($map[ $info[ 'extension' ] ])) {
352
            throw new \InvalidArgumentException('Given config file type is not supported');
353
        }
354
355
        $class = 'Doctrine\DBAL\Migrations\Configuration';
356
        $class .= $map[ $info[ 'extension' ] ];
357
        // -------
358
359
        /** @var AbstractFileConfiguration $configuration */
360
        $configuration = new $class($connection);
361
        $configuration->load($filename);
362
        $configuration->validate();
363
364
        return $configuration;
365
    }
366
}
367