Completed
Push — 3.x-dev-kit ( cc4dbe )
by
unknown
03:15
created

createDoctrineQueueBackend()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 2 Features 1
Metric Value
c 4
b 2
f 1
dl 0
loc 15
rs 9.4285
cc 2
eloc 9
nc 2
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/*
4
 * This file is part of the Sonata Project package.
5
 *
6
 * (c) Thomas Rabaix <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sonata\NotificationBundle\DependencyInjection;
13
14
use Sonata\EasyExtendsBundle\Mapper\DoctrineCollector;
15
use Sonata\NotificationBundle\Model\MessageInterface;
16
use Symfony\Component\Config\FileLocator;
17
use Symfony\Component\DependencyInjection\ContainerBuilder;
18
use Symfony\Component\DependencyInjection\Definition;
19
use Symfony\Component\DependencyInjection\Loader;
20
use Symfony\Component\DependencyInjection\Reference;
21
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
22
23
/**
24
 * This is the class that loads and manages your bundle configuration.
25
 *
26
 * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
27
 */
28
class SonataNotificationExtension extends Extension
29
{
30
    /**
31
     * @var int
32
     */
33
    protected $amqpCounter = 0;
34
35
    /**
36
     * {@inheritdoc}
37
     */
38
    public function load(array $configs, ContainerBuilder $container)
39
    {
40
        $configuration = new Configuration();
41
        $config = $this->processConfiguration($configuration, $configs);
42
43
        $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
44
45
        $loader->load('core.xml');
46
        $loader->load('doctrine_orm.xml');
47
        $loader->load('backend.xml');
48
        $loader->load('consumer.xml');
49
        $loader->load('selector.xml');
50
        $loader->load('event.xml');
51
52
        if ($config['consumers']['register_default']) {
53
            $loader->load('default_consumers.xml');
54
        }
55
56
        $bundles = $container->getParameter('kernel.bundles');
57
58
        if (isset($bundles['FOSRestBundle']) && isset($bundles['NelmioApiDocBundle'])) {
59
            $loader->load('api_controllers.xml');
60
            $loader->load('api_form.xml');
61
        }
62
63
        if ($config['admin']['enabled'] && isset($bundles['SonataDoctrineORMAdminBundle'])) { // for now, only support for ORM
64
            $loader->load('admin.xml');
65
        }
66
67
        if (isset($bundles['LiipMonitorBundle'])) {
68
            $loader->load('checkmonitor.xml');
69
        }
70
71
        $this->checkConfiguration($config);
72
73
        $container->setAlias('sonata.notification.backend', $config['backend']);
74
        $container->setParameter('sonata.notification.backend', $config['backend']);
75
76
        $this->registerDoctrineMapping($config);
77
        $this->registerParameters($container, $config);
78
        $this->configureBackends($container, $config);
79
        $this->configureClass($container, $config);
80
        $this->configureListeners($container, $config);
81
        $this->configureAdmin($container, $config);
82
    }
83
84
    /**
85
     * @param ContainerBuilder $container
86
     * @param array            $config
87
     */
88
    public function configureClass(ContainerBuilder $container, $config)
89
    {
90
        // admin configuration
91
        $container->setParameter('sonata.notification.admin.message.entity', $config['class']['message']);
92
93
        // manager configuration
94
        $container->setParameter('sonata.notification.manager.message.entity', $config['class']['message']);
95
    }
96
97
    /**
98
     * @param ContainerBuilder $container
99
     * @param array            $config
100
     */
101
    public function configureAdmin(ContainerBuilder $container, $config)
102
    {
103
        $container->setParameter('sonata.notification.admin.message.class', $config['admin']['message']['class']);
104
        $container->setParameter('sonata.notification.admin.message.controller', $config['admin']['message']['controller']);
105
        $container->setParameter('sonata.notification.admin.message.translation_domain', $config['admin']['message']['translation']);
106
    }
107
108
    /**
109
     * @param ContainerBuilder $container
110
     * @param array            $config
111
     */
112
    public function registerParameters(ContainerBuilder $container, $config)
113
    {
114
        $container->setParameter('sonata.notification.message.class', $config['class']['message']);
115
        $container->setParameter('sonata.notification.admin.message.entity', $config['class']['message']);
116
    }
117
118
    /**
119
     * @param ContainerBuilder $container
120
     * @param array            $config
121
     */
122
    public function configureBackends(ContainerBuilder $container, $config)
123
    {
124
        // set the default value, will be erase if required
125
        $container->setAlias('sonata.notification.manager.message', 'sonata.notification.manager.message.default');
126
127
        if (isset($config['backends']['rabbitmq']) && $config['backend']  === 'sonata.notification.backend.rabbitmq') {
128
            $this->configureRabbitmq($container, $config);
129
130
            $container->removeDefinition('sonata.notification.backend.doctrine');
131
        } else {
132
            $container->removeDefinition('sonata.notification.backend.rabbitmq');
133
        }
134
135
        if (isset($config['backends']['doctrine']) && $config['backend']  === 'sonata.notification.backend.doctrine') {
136
            $checkLevel = array(
137
                MessageInterface::STATE_DONE => $config['backends']['doctrine']['states']['done'],
138
                MessageInterface::STATE_ERROR => $config['backends']['doctrine']['states']['error'],
139
                MessageInterface::STATE_IN_PROGRESS => $config['backends']['doctrine']['states']['in_progress'],
140
                MessageInterface::STATE_OPEN => $config['backends']['doctrine']['states']['open'],
141
            );
142
143
            $pause = $config['backends']['doctrine']['pause'];
144
            $maxAge = $config['backends']['doctrine']['max_age'];
145
            $batchSize = $config['backends']['doctrine']['batch_size'];
146
            $container->setAlias('sonata.notification.manager.message', $config['backends']['doctrine']['message_manager']);
147
148
            $this->configureDoctrineBackends($container, $config, $checkLevel, $pause, $maxAge, $batchSize);
0 ignored issues
show
Documentation introduced by
$checkLevel is of type array, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
149
        }
150
    }
151
152
    /**
153
     * @param array $config
154
     */
155
    public function registerDoctrineMapping(array $config)
156
    {
157
        $collector = DoctrineCollector::getInstance();
158
159
        $collector->addIndex($config['class']['message'], 'idx_state', array(
160
            'state',
161
        ));
162
163
        $collector->addIndex($config['class']['message'], 'idx_created_at', array(
164
            'created_at',
165
        ));
166
    }
167
168
    /**
169
     * @param array $config
170
     */
171
    protected function checkConfiguration(array $config)
172
    {
173
        if (isset($config['backends']) && count($config['backends']) > 1) {
174
            throw new \RuntimeException('more than one backend configured, you can have only one backend configuration');
175
        }
176
177
        if (!isset($config['backends']['rabbitmq']) && $config['backend']  === 'sonata.notification.backend.rabbitmq') {
178
            throw new \RuntimeException('Please configure the sonata_notification.backends.rabbitmq section');
179
        }
180
181
        if (!isset($config['backends']['doctrine']) && $config['backend']  === 'sonata.notification.backend.doctrine') {
182
            throw new \RuntimeException('Please configure the sonata_notification.backends.doctrine section');
183
        }
184
    }
185
186
    /**
187
     * @param ContainerBuilder $container
188
     * @param array            $config
189
     */
190
    protected function configureListeners(ContainerBuilder $container, array $config)
191
    {
192
        $ids = $config['iteration_listeners'];
193
194
        // this one clean the unit of work after every iteration
195
        // it must be set on any backend ...
196
        $ids[] = 'sonata.notification.event.doctrine_optimize';
197
198
        if (isset($config['backends']['doctrine']) && $config['backends']['doctrine']['batch_size'] > 1) {
199
            // if the backend is doctrine and the batch size > 1, then
200
            // the unit of work must be cleaned wisely to avoid any issue
201
            // while persisting entities
202
            $ids = array(
203
                'sonata.notification.event.doctrine_backend_optimize',
204
            );
205
        }
206
207
        $container->setParameter('sonata.notification.event.iteration_listeners', $ids);
208
    }
209
210
    /**
211
     * @param ContainerBuilder $container
212
     * @param array            $config
213
     * @param bool             $checkLevel
214
     * @param int              $pause
215
     * @param int              $maxAge
216
     * @param int              $batchSize
217
     *
218
     * @throws \RuntimeException
219
     */
220
    protected function configureDoctrineBackends(ContainerBuilder $container, array $config, $checkLevel, $pause, $maxAge, $batchSize)
221
    {
222
        $queues = $config['queues'];
223
        $qBackends = array();
224
225
        $definition = $container->getDefinition('sonata.notification.backend.doctrine');
226
227
        // no queue defined, set a default one
228
        if (count($queues) == 0) {
229
            $queues = array(array(
230
                'queue' => 'default',
231
                'default' => true,
232
                'types' => array(),
233
            ));
234
        }
235
236
        $defaultSet = false;
237
        $declaredQueues = array();
238
239
        foreach ($queues as $pos => &$queue) {
240
            if (in_array($queue['queue'], $declaredQueues)) {
241
                throw new \RuntimeException('The doctrine backend does not support 2 identicals queue name, please rename one queue');
242
            }
243
244
            $declaredQueues[] = $queue['queue'];
245
246
            // make the configuration compatible with old code and rabbitmq
247
            if (isset($queue['routing_key']) && strlen($queue['routing_key']) > 0) {
248
                $queue['types'] = array($queue['routing_key']);
249
            }
250
251
            if (empty($queue['types']) && $queue['default'] === false) {
252
                throw new \RuntimeException('You cannot declared a doctrine queue with no type defined with default = false');
253
            }
254
255
            if (!empty($queue['types']) && $queue['default'] === true) {
256
                throw new \RuntimeException('You cannot declared a doctrine queue with types defined with default = true');
257
            }
258
259
            $id = $this->createDoctrineQueueBackend($container, $definition->getArgument(0), $checkLevel, $pause, $maxAge, $batchSize, $queue['queue'], $queue['types']);
260
            $qBackends[$pos] = array(
261
                'types' => $queue['types'],
262
                'backend' => new Reference($id),
263
            );
264
265
            if ($queue['default'] === true) {
266
                if ($defaultSet === true) {
267
                    throw new \RuntimeException('You can only set one doctrine default queue in your sonata notification configuration.');
268
                }
269
270
                $defaultSet = true;
271
                $defaultQueue = $queue['queue'];
272
            }
273
        }
274
275
        if ($defaultSet === false) {
276
            throw new \RuntimeException('You need to specify a valid default queue for the doctrine backend!');
277
        }
278
279
        $definition
280
            ->replaceArgument(1, $queues)
281
            ->replaceArgument(2, $defaultQueue)
0 ignored issues
show
Bug introduced by
The variable $defaultQueue does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
282
            ->replaceArgument(3, $qBackends)
283
        ;
284
    }
285
286
    /**
287
     * @param ContainerBuilder $container
288
     * @param string           $manager
289
     * @param bool             $checkLevel
290
     * @param int              $pause
291
     * @param int              $maxAge
292
     * @param int              $batchSize
293
     * @param string           $key
294
     * @param array            $types
295
     *
296
     * @return string
297
     */
298
    protected function createDoctrineQueueBackend(ContainerBuilder $container, $manager, $checkLevel, $pause, $maxAge, $batchSize, $key, array $types = array())
299
    {
300
        if ($key == '') {
301
            $id = 'sonata.notification.backend.doctrine.default_'.$this->amqpCounter++;
302
        } else {
303
            $id = 'sonata.notification.backend.doctrine.'.$key;
304
        }
305
306
        $definition = new Definition('Sonata\NotificationBundle\Backend\MessageManagerBackend', array($manager, $checkLevel, $pause, $maxAge, $batchSize, $types));
307
        $definition->setPublic(false);
308
309
        $container->setDefinition($id, $definition);
310
311
        return $id;
312
    }
313
314
    /**
315
     * @param ContainerBuilder $container
316
     * @param array            $config
317
     */
318
    protected function configureRabbitmq(ContainerBuilder $container, array $config)
319
    {
320
        $queues = $config['queues'];
321
        $connection = $config['backends']['rabbitmq']['connection'];
322
        $exchange = $config['backends']['rabbitmq']['exchange'];
323
        $amqBackends = array();
324
325
        if (count($queues) == 0) {
326
            $queues = array(array(
327
                'queue' => 'default',
328
                'default' => true,
329
                'routing_key' => '',
330
                'recover' => false,
331
                'dead_letter_exchange' => null,
332
            ));
333
        }
334
335
        $declaredQueues = array();
336
337
        $defaultSet = false;
338
        foreach ($queues as $pos => $queue) {
339
            if (in_array($queue['queue'], $declaredQueues)) {
340
                throw new \RuntimeException('The RabbitMQ backend does not support 2 identicals queue name, please rename one queue');
341
            }
342
343
            $declaredQueues[] = $queue['queue'];
344
345
            $id = $this->createAMQPBackend($container, $exchange, $queue['queue'], $queue['recover'], $queue['routing_key'], $queue['dead_letter_exchange']);
346
347
            $amqBackends[$pos] = array(
348
                'type' => $queue['routing_key'],
349
                'backend' => new Reference($id),
350
            );
351
352
            if ($queue['default'] === true) {
353
                if ($defaultSet === true) {
354
                    throw new \RuntimeException('You can only set one rabbitmq default queue in your sonata notification configuration.');
355
                }
356
                $defaultSet = true;
357
                $defaultQueue = $queue['routing_key'];
358
            }
359
        }
360
361
        if ($defaultSet === false) {
362
            throw new \RuntimeException('You need to specify a valid default queue for the rabbitmq backend!');
363
        }
364
365
        $container->getDefinition('sonata.notification.backend.rabbitmq')
366
            ->replaceArgument(0, $connection)
367
            ->replaceArgument(1, $queues)
368
            ->replaceArgument(2, $defaultQueue)
0 ignored issues
show
Bug introduced by
The variable $defaultQueue does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
369
            ->replaceArgument(3, $amqBackends)
370
        ;
371
    }
372
373
    /**
374
     * @param ContainerBuilder $container
375
     * @param string           $exchange
376
     * @param string           $name
377
     * @param string           $recover
378
     * @param string           $key
379
     * @param string           $deadLetterExchange
380
     *
381
     * @return string
382
     */
383
    protected function createAMQPBackend(ContainerBuilder $container, $exchange, $name, $recover, $key = '', $deadLetterExchange = null)
384
    {
385
        $id = 'sonata.notification.backend.rabbitmq.'.$this->amqpCounter++;
386
387
        $definition = new Definition('Sonata\NotificationBundle\Backend\AMQPBackend', array($exchange, $name, $recover, $key, $deadLetterExchange));
388
        $definition->setPublic(false);
389
        $container->setDefinition($id, $definition);
390
391
        return $id;
392
    }
393
}
394