AdmingeneratorGeneratorExtension::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
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