AdmingeneratorGeneratorExtension   A
last analyzed

Complexity

Total Complexity 40

Size/Duplication

Total Lines 320
Duplicated Lines 23.75 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
wmc 40
lcom 1
cbo 10
dl 76
loc 320
rs 9.2
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A prepend() 0 14 3
A load() 0 36 3
C processModelManagerConfiguration() 46 67 11
A addTemplatesInitialization() 0 9 2
A processTwigConfiguration() 0 9 2
A processCacheConfiguration() 0 25 5
A addCacheProviderToGenerator() 0 8 1
A registerGeneratedFormsAsServices() 0 19 4
B registerFormsServicesFromGenerator() 30 49 6
A getConfiguration() 0 4 1
A getAlias() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like AdmingeneratorGeneratorExtension often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AdmingeneratorGeneratorExtension, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Admingenerator\GeneratorBundle\DependencyInjection;
4
5
use Admingenerator\GeneratorBundle\Exception\ModelManagerNotSelectedException;
6
use Admingenerator\GeneratorBundle\Filesystem\GeneratorsFinder;
7
use Symfony\Component\Config\FileLocator;
8
use Symfony\Component\DependencyInjection\ContainerBuilder;
9
use Symfony\Component\DependencyInjection\Definition;
10
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
11
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
12
use Symfony\Component\DependencyInjection\Reference;
13
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
14
use Symfony\Component\HttpKernel\KernelInterface;
15
use Symfony\Component\Yaml\Yaml;
16
17
class AdmingeneratorGeneratorExtension extends Extension
18
{
19
    /**
20
     * @var KernelInterface
21
     */
22
    private $kernel;
23
24
    /**
25
     * @param KernelInterface $kernel
26
     */
27
    public function __construct(KernelInterface $kernel)
28
    {
29
        $this->kernel = $kernel;
30
    }
31
32
    /**
33
     * Prepend KnpMenuBundle config
34
     */
35
    public function prepend(ContainerBuilder $container)
36
    {
37
        $config = array('twig' => array(
38
            'template' => 'AdmingeneratorGeneratorBundle:KnpMenu:knp_menu_trans.html.twig',
39
        ));
40
41
        foreach ($container->getExtensions() as $name => $extension) {
42
            switch ($name) {
43
                case 'knp_menu':
44
                    $container->prependExtensionConfig($name, $config);
45
                    break;
46
            }
47
        }
48
    }
49
50
    public function load(array $configs, ContainerBuilder $container)
51
    {
52
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
53
        $loader->load('services.xml');
54
55
        $config = $this->processConfiguration($this->getConfiguration($configs, $container), $configs);
56
57
        $container->setParameter('admingenerator', $config);
58
        $container->setParameter('admingenerator.base_admin_template', $config['base_admin_template']);
59
        $container->setParameter('admingenerator.dashboard_route', $config['dashboard_route']);
60
        $container->setParameter('admingenerator.login_route', $config['login_route']);
61
        $container->setParameter('admingenerator.logout_route', $config['logout_route']);
62
        $container->setParameter('admingenerator.exit_route', $config['exit_route']);
63
        $container->setParameter('admingenerator.stylesheets', $config['stylesheets']);
64
        $container->setParameter('admingenerator.javascripts', $config['javascripts']);
65
        $container->setParameter('admingenerator.default_action_after_save', $config['default_action_after_save']);
66
67
        $container->setParameter('admingenerator.throw_exceptions', $container->getParameter('kernel.debug')
68
            ? true
69
            : $config['throw_exceptions']
70
        );
71
72
        $container->setParameter('admingenerator.use_doctrine_orm_batch_remove', $config['use_doctrine_orm_batch_remove']);
73
        $container->setParameter('admingenerator.use_doctrine_odm_batch_remove', $config['use_doctrine_odm_batch_remove']);
74
        $container->setParameter('admingenerator.use_propel_batch_remove', $config['use_propel_batch_remove']);
75
76
        if ($config['use_jms_security']) {
77
            $container->getDefinition('twig.extension.admingenerator.security')->addArgument(true);
78
            $container->getDefinition('twig.extension.admingenerator.echo')->addArgument(true);
79
        } 
80
81
        $this->registerGeneratedFormsAsServices($container);
82
        $this->processModelManagerConfiguration($config, $container);
83
        $this->processTwigConfiguration($config['twig'], $container);
84
        $this->processCacheConfiguration($config, $container);
85
    }
86
87
    /**
88
     * @param array $config
89
     * @param ContainerBuilder $container
90
     * @throws ModelManagerNotSelectedException
91
     */
92
    private function processModelManagerConfiguration(array $config, ContainerBuilder $container)
93
    {
94
        if (!($config['use_doctrine_orm'] || $config['use_doctrine_odm'] || $config['use_propel'])) {
95
            throw new ModelManagerNotSelectedException();
96
        }
97
98
        $loader = new XmlFileLoader($container, new FileLocator(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Resources' . DIRECTORY_SEPARATOR . 'config'));
99
        $config['templates_dirs'][] = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Resources' . DIRECTORY_SEPARATOR . 'templates';
100
101
        $doctrineOrmTemplatesDirs = array();
102
        $doctrineOdmTemplatesDirs = array();
103
        $propelTemplatesDirs = array();
104
        foreach ($config['templates_dirs'] as $dir) {
105
            $doctrineOrmTemplatesDirs[] = $dir . DIRECTORY_SEPARATOR . 'Doctrine';
106
            $doctrineOdmTemplatesDirs[] = $dir . DIRECTORY_SEPARATOR . 'DoctrineODM';
107
            $propelTemplatesDirs[] = $dir . DIRECTORY_SEPARATOR . 'Propel';
108
        }
109
110 View Code Duplication
        if ($config['use_doctrine_orm']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
111
            $loader->load('doctrine_orm.xml');
112
            $this->addTemplatesInitialization($container->getDefinition('admingenerator.generator.doctrine'), $doctrineOrmTemplatesDirs);
113
            if ($config['overwrite_if_exists']) {
114
                $container
115
                    ->getDefinition('admingenerator.generator.doctrine')
116
                    ->addMethodCall('forceOverwriteIfExists');
117
118
            }
119
120
            $container->getDefinition('admingenerator.fieldguesser.doctrine')
121
                ->addArgument($config['form_types']['doctrine_orm'])
122
                ->addArgument($config['filter_types']['doctrine_orm'])
123
                ->addArgument($config['guess_required'])
124
                ->addArgument($config['default_required']);
125
        }
126
127 View Code Duplication
        if ($config['use_doctrine_odm']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
128
            $loader->load('doctrine_odm.xml');
129
            $this->addTemplatesInitialization($container->getDefinition('admingenerator.generator.doctrine_odm'), $doctrineOdmTemplatesDirs);
130
            if ($config['overwrite_if_exists']) {
131
                $container
132
                    ->getDefinition('admingenerator.generator.doctrine_odm')
133
                    ->addMethodCall('forceOverwriteIfExists');
134
            }
135
136
            $container->getDefinition('admingenerator.generator.doctrine_odm')
137
                ->addArgument($config['form_types']['doctrine_odm'])
138
                ->addArgument($config['filter_types']['doctrine_odm'])
139
                ->addArgument($config['guess_required'])
140
                ->addArgument($config['default_required']);
141
        }
142
143 View Code Duplication
        if ($config['use_propel']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
144
            $loader->load('propel.xml');
145
            $this->addTemplatesInitialization($container->getDefinition('admingenerator.generator.propel'), $propelTemplatesDirs);
146
            if ($config['overwrite_if_exists']) {
147
                $container
148
                    ->getDefinition('admingenerator.generator.propel')
149
                    ->addMethodCall('forceOverwriteIfExists');
150
            }
151
152
            $container->getDefinition('admingenerator.fieldguesser.propel')
153
                ->addArgument($config['form_types']['propel'])
154
                ->addArgument($config['filter_types']['propel'])
155
                ->addArgument($config['guess_required'])
156
                ->addArgument($config['default_required']);
157
        }
158
    }
159
160
    /**
161
     * Update $generatorDefinition to add calls to the addTemplatesDirectory
162
     * for all $directories.
163
     *
164
     * @param Definition $generatorDefinition
165
     * @param array $directories
166
     */
167
    private function addTemplatesInitialization(Definition $generatorDefinition, array $directories)
168
    {
169
        foreach ($directories as $directory) {
170
            $generatorDefinition->addMethodCall(
171
                'addTemplatesDirectory',
172
                array($directory)
173
            );
174
        }
175
    }
176
177
    /**
178
     * @param array $twigConfiguration
179
     * @param ContainerBuilder $container
180
     */
181
    private function processTwigConfiguration(array $twigConfiguration, ContainerBuilder $container)
182
    {
183
        $container->setParameter('admingenerator.twig', $twigConfiguration);
184
185
        if ($twigConfiguration['use_localized_date']) {
186
            // Register Intl extension for localized date
187
            $container->register('twig.extension.intl', 'Twig_Extensions_Extension_Intl')->addTag('twig.extension');
188
        }
189
    }
190
191
    /**
192
     * @param array $config
193
     * @param ContainerBuilder $container
194
     */
195
    private function processCacheConfiguration(array $config, ContainerBuilder $container)
196
    {
197
        if (empty($config['generator_cache'])) {
198
            return;
199
        }
200
201
        $container
202
            ->getDefinition('admingenerator.generator.listener')
203
            ->addMethodCall('setCacheProvider', array(
204
                new Reference($config['generator_cache']),
205
                $container->getParameter('kernel.environment'),
206
            ));
207
208
        if ($config['use_doctrine_orm']) {
209
            $this->addCacheProviderToGenerator($config['generator_cache'], $container->getDefinition('admingenerator.generator.doctrine'), $container);
210
        }
211
212
        if ($config['use_doctrine_odm']) {
213
            $this->addCacheProviderToGenerator($config['generator_cache'], $container->getDefinition('admingenerator.generator.doctrine_odm'), $container);
214
        }
215
216
        if ($config['use_propel']) {
217
            $this->addCacheProviderToGenerator($config['generator_cache'], $container->getDefinition('admingenerator.generator.propel'), $container);
218
        }
219
    }
220
221
    /**
222
     * @param string $cacheProviderServiceName
223
     * @param Definition $serviceDefinition
224
     */
225
    private function addCacheProviderToGenerator($cacheProviderServiceName, Definition $serviceDefinition, ContainerBuilder $container)
226
    {
227
        $serviceDefinition
228
            ->addMethodCall('setCacheProvider', array(
229
                new Reference($cacheProviderServiceName),
230
                $container->getParameter('kernel.environment'),
231
            ));
232
    }
233
234
    /**
235
     * Since Symfony 2.8, we need to use FQCN for FormType (using FormType instance in Factory is deprecated)
236
     * Unfortunately, our generated form types require Dependency Injection.
237
     * We so need to register all generated form as services so Security Authorization
238
     * Checker is injected.
239
     * @param ContainerBuilder $container
240
     */
241
    private function registerGeneratedFormsAsServices(ContainerBuilder $container)
242
    {
243
        $finder = new GeneratorsFinder($this->kernel);
244
245
        foreach ($finder->findAll() as $path => $generator) {
246
            $generator = Yaml::parse(file_get_contents($generator));
247
            if (!array_key_exists('params', $generator)) {
248
                throw new \InvalidArgumentException('"params" field is missing in ' . $generator);
249
            }
250
251
            if (!array_key_exists('builders', $generator)) {
252
                throw new \InvalidArgumentException('"builders" field is missing in ' . $generator);
253
            }
254
            preg_match('/[^\/|\\\\]*-generator.yml/', $path, $prefix);
255
            $prefix = substr($prefix[0], 0, strlen($prefix[0]) - strlen('-generator.yml'));
256
            $generator['params']['prefix'] = $prefix;
257
            $this->registerFormsServicesFromGenerator($generator['params'], array_keys($generator['builders']), $container);
258
        }
259
    }
260
261
    /**
262
     * Register forms as services for a generator.
263
     * Register only generated forms based on defined builders.
264
     *
265
     * @param array $generatorParameters
266
     * @param array $builders
267
     * @param ContainerBuilder $container
268
     */
269
    private function registerFormsServicesFromGenerator(array $generatorParameters, array $builders, ContainerBuilder $container)
270
    {
271
        $modelParts                       = explode('\\', $generatorParameters['model']);
272
        $model                            = strtolower(array_pop($modelParts)); // @TODO: BC Support, remove it starting from v.3.0.0
273
        $fullQualifiedNormalizedModelName = strtolower(str_replace('\\', '_', ltrim($generatorParameters['model'], '\\'))); // @TODO: BC Support, remove it starting from v.3.0.0
274
        $namespace_prefix                 = $generatorParameters['namespace_prefix'] ? $generatorParameters['namespace_prefix'] . '\\' : '';
275
        $fullQualifiedNormalizedFormName  = sprintf('%s%s_%s', str_replace('\\', '_', ltrim($namespace_prefix, '\\')), $generatorParameters['bundle_name'], $generatorParameters['prefix']);
276
277
        $formsBundleNamespace = sprintf(
278
            '%s%s\\Form\\Type\\%s',
279
            $namespace_prefix,
280
            $generatorParameters['bundle_name'],
281
            $generatorParameters['prefix']
282
        );
283
        $authorizationCheckerServiceReference = new Reference('security.authorization_checker');
284
285 View Code Duplication
        if (in_array('new', $builders)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
286
            $newDefinition = new Definition($formsBundleNamespace . '\\' . 'NewType');
287
            $newDefinition
288
                ->addMethodCall('setAuthorizationChecker', array($authorizationCheckerServiceReference))
289
                ->addTag('form.type');
290
291
            $container->setDefinition(($id = 'admingen_generator_' . $fullQualifiedNormalizedFormName . '_new'), $newDefinition);
292
            $container->setAlias('admingen_generator_' . $fullQualifiedNormalizedModelName . '_new', $id);
293
            $container->setAlias('admingen_generator_' . $model . '_new', $id);
294
        }
295
296 View Code Duplication
        if (in_array('edit', $builders)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
297
            $editDefinition = new Definition($formsBundleNamespace . '\\' . 'EditType');
298
            $editDefinition
299
                ->addMethodCall('setAuthorizationChecker', array($authorizationCheckerServiceReference))
300
                ->addTag('form.type');
301
302
            $container->setDefinition(($id = 'admingen_generator_' . $fullQualifiedNormalizedFormName . '_edit'), $editDefinition);
303
            $container->setAlias('admingen_generator_' . $fullQualifiedNormalizedModelName . '_edit', $id);
304
            $container->setAlias('admingen_generator_' . $model . '_edit', $id);
305
        }
306
307 View Code Duplication
        if (in_array('list', $builders) || in_array('nested_list', $builders)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
308
            $filterDefinition = new Definition($formsBundleNamespace . '\\' . 'FiltersType');
309
            $filterDefinition
310
                ->addMethodCall('setAuthorizationChecker', array($authorizationCheckerServiceReference))
311
                ->addTag('form.type');
312
313
            $container->setDefinition(($id = 'admingen_generator_' . $fullQualifiedNormalizedFormName . '_filter'), $filterDefinition);
314
            $container->setAlias('admingen_generator_' . $fullQualifiedNormalizedModelName . '_filter', $id);
315
            $container->setAlias('admingen_generator_' . $model . '_filter', $id);
316
        }
317
    }
318
319
    /**
320
     * @param array $config
321
     * @param ContainerBuilder $container
322
     * @return Configuration
323
     */
324
    public function getConfiguration(array $config, ContainerBuilder $container)
325
    {
326
        return new Configuration($this->getAlias());
327
    }
328
329
    /**
330
     * @return string
331
     */
332
    public function getAlias()
333
    {
334
        return 'admingenerator_generator';
335
    }
336
}
337