Completed
Push — 2.x-dev-kit ( 8d77e1 )
by
unknown
28:22 queued 25:50
created

createDoctrineQueueBackend()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 1
Metric Value
c 3
b 1
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.
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 array $config
86
     */
87
    protected function checkConfiguration(array $config)
88
    {
89
        if (isset($config['backends']) && count($config['backends']) > 1) {
90
            throw new \RuntimeException('more than one backend configured, you can have only one backend configuration');
91
        }
92
93
        if (!isset($config['backends']['rabbitmq']) && $config['backend']  === 'sonata.notification.backend.rabbitmq') {
94
            throw new \RuntimeException('Please configure the sonata_notification.backends.rabbitmq section');
95
        }
96
97
        if (!isset($config['backends']['doctrine']) && $config['backend']  === 'sonata.notification.backend.doctrine') {
98
            throw new \RuntimeException('Please configure the sonata_notification.backends.doctrine section');
99
        }
100
    }
101
102
    /**
103
     * @param ContainerBuilder $container
104
     * @param array            $config
105
     */
106
    protected function configureListeners(ContainerBuilder $container, array $config)
107
    {
108
        $ids = $config['iteration_listeners'];
109
110
        // this one clean the unit of work after every iteration
111
        // it must be set on any backend ...
112
        $ids[] = 'sonata.notification.event.doctrine_optimize';
113
114
        if (isset($config['backends']['doctrine']) && $config['backends']['doctrine']['batch_size'] > 1) {
115
            // if the backend is doctrine and the batch size > 1, then
116
            // the unit of work must be cleaned wisely to avoid any issue
117
            // while persisting entities
118
            $ids = array(
119
                'sonata.notification.event.doctrine_backend_optimize',
120
            );
121
        }
122
123
        $container->setParameter('sonata.notification.event.iteration_listeners', $ids);
124
    }
125
126
    /**
127
     * @param ContainerBuilder $container
128
     * @param array            $config
129
     */
130
    public function configureClass(ContainerBuilder $container, $config)
131
    {
132
        // admin configuration
133
        $container->setParameter('sonata.notification.admin.message.entity',       $config['class']['message']);
134
135
        // manager configuration
136
        $container->setParameter('sonata.notification.manager.message.entity',     $config['class']['message']);
137
    }
138
139
    /**
140
     * @param ContainerBuilder $container
141
     * @param array            $config
142
     */
143
    public function configureAdmin(ContainerBuilder $container, $config)
144
    {
145
        $container->setParameter('sonata.notification.admin.message.class',              $config['admin']['message']['class']);
146
        $container->setParameter('sonata.notification.admin.message.controller',         $config['admin']['message']['controller']);
147
        $container->setParameter('sonata.notification.admin.message.translation_domain', $config['admin']['message']['translation']);
148
    }
149
150
    /**
151
     * @param ContainerBuilder $container
152
     * @param array            $config
153
     */
154
    public function registerParameters(ContainerBuilder $container, $config)
155
    {
156
        $container->setParameter('sonata.notification.message.class',        $config['class']['message']);
157
        $container->setParameter('sonata.notification.admin.message.entity', $config['class']['message']);
158
    }
159
160
    /**
161
     * @param ContainerBuilder $container
162
     * @param array            $config
163
     */
164
    public function configureBackends(ContainerBuilder $container, $config)
165
    {
166
        // set the default value, will be erase if required
167
        $container->setAlias('sonata.notification.manager.message', 'sonata.notification.manager.message.default');
168
169
        if (isset($config['backends']['rabbitmq']) && $config['backend']  === 'sonata.notification.backend.rabbitmq') {
170
            $this->configureRabbitmq($container, $config);
171
172
            $container->removeDefinition('sonata.notification.backend.doctrine');
173
        } else {
174
            $container->removeDefinition('sonata.notification.backend.rabbitmq');
175
        }
176
177
        if (isset($config['backends']['doctrine']) && $config['backend']  === 'sonata.notification.backend.doctrine') {
178
            $checkLevel = array(
179
                MessageInterface::STATE_DONE         => $config['backends']['doctrine']['states']['done'],
180
                MessageInterface::STATE_ERROR        => $config['backends']['doctrine']['states']['error'],
181
                MessageInterface::STATE_IN_PROGRESS  => $config['backends']['doctrine']['states']['in_progress'],
182
                MessageInterface::STATE_OPEN         => $config['backends']['doctrine']['states']['open'],
183
            );
184
185
            $pause = $config['backends']['doctrine']['pause'];
186
            $maxAge = $config['backends']['doctrine']['max_age'];
187
            $batchSize = $config['backends']['doctrine']['batch_size'];
188
            $container->setAlias('sonata.notification.manager.message', $config['backends']['doctrine']['message_manager']);
189
190
            $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...
191
        }
192
    }
193
194
    /**
195
     * @param ContainerBuilder $container
196
     * @param array            $config
197
     * @param bool             $checkLevel
198
     * @param int              $pause
199
     * @param int              $maxAge
200
     * @param int              $batchSize
201
     *
202
     * @throws \RuntimeException
203
     */
204
    protected function configureDoctrineBackends(ContainerBuilder $container, array $config, $checkLevel, $pause, $maxAge, $batchSize)
205
    {
206
        $queues = $config['queues'];
207
        $qBackends = array();
208
209
        $definition = $container->getDefinition('sonata.notification.backend.doctrine');
210
211
        // no queue defined, set a default one
212
        if (count($queues) == 0) {
213
            $queues = array(array(
214
                'queue'   => 'default',
215
                'default' => true,
216
                'types'   => array(),
217
            ));
218
        }
219
220
        $defaultSet = false;
221
        $declaredQueues = array();
222
223
        foreach ($queues as $pos => &$queue) {
224
            if (in_array($queue['queue'], $declaredQueues)) {
225
                throw new \RuntimeException('The doctrine backend does not support 2 identicals queue name, please rename one queue');
226
            }
227
228
            $declaredQueues[] = $queue['queue'];
229
230
            // make the configuration compatible with old code and rabbitmq
231
            if (isset($queue['routing_key']) && strlen($queue['routing_key']) > 0) {
232
                $queue['types'] = array($queue['routing_key']);
233
            }
234
235
            if (empty($queue['types']) && $queue['default'] === false) {
236
                throw new \RuntimeException('You cannot declared a doctrine queue with no type defined with default = false');
237
            }
238
239
            if (!empty($queue['types']) && $queue['default'] === true) {
240
                throw new \RuntimeException('You cannot declared a doctrine queue with types defined with default = true');
241
            }
242
243
            $id = $this->createDoctrineQueueBackend($container, $definition->getArgument(0), $checkLevel, $pause, $maxAge, $batchSize, $queue['queue'], $queue['types']);
244
            $qBackends[$pos] = array(
245
                'types'   => $queue['types'],
246
                'backend' => new Reference($id),
247
            );
248
249
            if ($queue['default'] === true) {
250
                if ($defaultSet === true) {
251
                    throw new \RuntimeException('You can only set one doctrine default queue in your sonata notification configuration.');
252
                }
253
254
                $defaultSet = true;
255
                $defaultQueue = $queue['queue'];
256
            }
257
        }
258
259
        if ($defaultSet === false) {
260
            throw new \RuntimeException('You need to specify a valid default queue for the doctrine backend!');
261
        }
262
263
        $definition
264
            ->replaceArgument(1, $queues)
265
            ->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...
266
            ->replaceArgument(3, $qBackends)
267
        ;
268
    }
269
270
    /**
271
     * @param ContainerBuilder $container
272
     * @param string           $manager
273
     * @param bool             $checkLevel
274
     * @param int              $pause
275
     * @param int              $maxAge
276
     * @param int              $batchSize
277
     * @param string           $key
278
     * @param array            $types
279
     *
280
     * @return string
281
     */
282
    protected function createDoctrineQueueBackend(ContainerBuilder $container, $manager, $checkLevel, $pause, $maxAge, $batchSize, $key, array $types = array())
283
    {
284
        if ($key == '') {
285
            $id = 'sonata.notification.backend.doctrine.default_'.$this->amqpCounter++;
286
        } else {
287
            $id = 'sonata.notification.backend.doctrine.'.$key;
288
        }
289
290
        $definition = new Definition('Sonata\NotificationBundle\Backend\MessageManagerBackend', array($manager, $checkLevel, $pause, $maxAge, $batchSize, $types));
291
        $definition->setPublic(false);
292
293
        $container->setDefinition($id, $definition);
294
295
        return $id;
296
    }
297
298
    /**
299
     * @param ContainerBuilder $container
300
     * @param array            $config
301
     */
302
    protected function configureRabbitmq(ContainerBuilder $container, array $config)
303
    {
304
        $queues = $config['queues'];
305
        $connection = $config['backends']['rabbitmq']['connection'];
306
        $exchange = $config['backends']['rabbitmq']['exchange'];
307
        $amqBackends = array();
308
309
        if (count($queues) == 0) {
310
            $queues = array(array(
311
                'queue'                => 'default',
312
                'default'              => true,
313
                'routing_key'          => '',
314
                'recover'              => false,
315
                'dead_letter_exchange' => null,
316
            ));
317
        }
318
319
        $declaredQueues = array();
320
321
        $defaultSet = false;
322
        foreach ($queues as $pos => $queue) {
323
            if (in_array($queue['queue'], $declaredQueues)) {
324
                throw new \RuntimeException('The RabbitMQ backend does not support 2 identicals queue name, please rename one queue');
325
            }
326
327
            $declaredQueues[] = $queue['queue'];
328
329
            $id = $this->createAMQPBackend($container, $exchange, $queue['queue'], $queue['recover'], $queue['routing_key'], $queue['dead_letter_exchange']);
330
331
            $amqBackends[$pos] = array(
332
                'type'    => $queue['routing_key'],
333
                'backend' => new Reference($id),
334
            );
335
336
            if ($queue['default'] === true) {
337
                if ($defaultSet === true) {
338
                    throw new \RuntimeException('You can only set one rabbitmq default queue in your sonata notification configuration.');
339
                }
340
                $defaultSet = true;
341
                $defaultQueue = $queue['routing_key'];
342
            }
343
        }
344
345
        if ($defaultSet === false) {
346
            throw new \RuntimeException('You need to specify a valid default queue for the rabbitmq backend!');
347
        }
348
349
        $container->getDefinition('sonata.notification.backend.rabbitmq')
350
            ->replaceArgument(0, $connection)
351
            ->replaceArgument(1, $queues)
352
            ->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...
353
            ->replaceArgument(3, $amqBackends)
354
        ;
355
    }
356
357
    /**
358
     * @param ContainerBuilder $container
359
     * @param string           $exchange
360
     * @param string           $name
361
     * @param string           $recover
362
     * @param string           $key
363
     * @param string           $deadLetterExchange
364
     *
365
     * @return string
366
     */
367
    protected function createAMQPBackend(ContainerBuilder $container, $exchange, $name, $recover, $key = '', $deadLetterExchange = null)
368
    {
369
        $id = 'sonata.notification.backend.rabbitmq.'.$this->amqpCounter++;
370
371
        $definition = new Definition('Sonata\NotificationBundle\Backend\AMQPBackend', array($exchange, $name, $recover, $key, $deadLetterExchange));
372
        $definition->setPublic(false);
373
        $container->setDefinition($id, $definition);
374
375
        return $id;
376
    }
377
378
    /**
379
     * @param array $config
380
     */
381
    public function registerDoctrineMapping(array $config)
382
    {
383
        $collector = DoctrineCollector::getInstance();
384
385
        $collector->addIndex($config['class']['message'], 'idx_state', array(
386
            'state',
387
        ));
388
389
        $collector->addIndex($config['class']['message'], 'idx_created_at', array(
390
            'created_at',
391
        ));
392
    }
393
}
394