Completed
Pull Request — master (#4)
by dan
14:39
created

NotificationExtension   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 164
Duplicated Lines 13.41 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 9
dl 22
loc 164
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A setChannelAdapterMapping() 0 8 1
C load() 0 68 10
A createNotificationChannelSubscriber() 0 16 1
A createChannel() 8 8 1
A createChannelService() 0 6 1
A createBroadcaster() 0 5 1
A createNotificationManagerService() 14 14 1
A createChannelManagerService() 0 19 2

How to fix   Duplicated Code   

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:

1
<?php
2
3
namespace IrishDan\NotificationBundle\DependencyInjection;
4
5
use IrishDan\NotificationBundle\DependencyInjection\Factory\BroadcasterFactory;
6
use IrishDan\NotificationBundle\DependencyInjection\Factory\ChannelFactory;
7
use Symfony\Component\Config\FileLocator;
8
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
9
use Symfony\Component\DependencyInjection\Definition;
10
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
11
use Symfony\Component\DependencyInjection\Reference;
12
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
13
use Symfony\Component\DependencyInjection\ContainerBuilder;
14
15
class NotificationExtension extends Extension
16
{
17
    protected $channelKeyAdapterMappings = [];
18
    protected $defaultAdapters = [
19
        'mail',
20
        'logger',
21
        'database',
22
        'nexmo',
23
        'pusher',
24
        'slack',
25
    ];
26
27
    protected function setChannelAdapterMapping(array $maps)
28
    {
29
        $this->channelKeyAdapterMappings[$maps['channel']] = [
30
            'adapter' => $maps['adapter'],
31
            'config_id' => $maps['config_id'],
32
            'config' => $maps['config'],
33
        ];
34
    }
35
36
    public function load(array $configs, ContainerBuilder $container)
37
    {
38
        // Load our YAML resources
39
        $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
40
        $loader->load('services.yml');
41
42
        // @TODO: Broadcasters array should dynamic
43
        $configuration = new Configuration($this->defaultAdapters, ['slack', 'pusher']);
44
        $config = $this->processConfiguration($configuration, $configs);
45
46
        foreach ($configs as $subConfig) {
47
            $config = array_merge($config, $subConfig);
48
        }
49
50
        // Create the adapterless channel
51
        $this->createChannel($container, 'notification.channel');
52
53
54
        $enabledChannels = [];
55
56
        // For each enabled channel build a channel service..
57
        if (!empty($config['channels'])) {
58
            foreach ($config['channels'] as $channel => $channelConfig) {
59
                $enabledChannels[] = $channel;
60
                $container->setParameter('notification.channel.' . $channel . '.enabled', true);
61
62
                // Set a configuration parameter for each channel also.
63
                $parameters = empty($channelConfig) ? [] : $channelConfig;
64
                $parameterName = 'notification.channel.' . $channel . '.configuration';
65
                $container->setParameter($parameterName, $parameters);
66
67
                // Create a service for this channel.
68
                $this->createChannelService($channel, $container, $parameters);
69
            }
70
        }
71
72
        $container->setParameter('notification.available_channels', $enabledChannels);
73
74
        // Create the channel service
75
        $this->createChannelManagerService($enabledChannels, $container);
76
77
        // Create the notification manager service
78
        $this->createNotificationManagerService($container);
79
80
        // Create broadcasters and broadcast channels
81
        if (!empty($config['broadcasters'])) {
82
            foreach ($config['broadcasters'] as $name => $config) {
83
                $this->createBroadcaster($name, $config, $container);
84
            }
85
        }
86
87
        // Create the Event driven channel service
88
        // $this->createEventDrivenChannel($container);
89
90
        // @TODO: Check that required parameters are set.
91
        foreach ($this->defaultAdapters as $type) {
92
            if (!$container->hasParameter('notification.channel.' . $type . '.configuration')) {
93
                $container->setParameter('notification.channel.' . $type . '.configuration', []);
94
                $container->setParameter('notification.channel.' . $type . '.enabled', false);
95
            }
96
        }
97
98
        // Build the message crud listener unless its set to false
99
        // @TODO: Add this to documentation
100
        if ($config['use_default_message_subscriber']) {
101
            $this->createNotificationChannelSubscriber($container);
102
        }
103
    }
104
105
    private function createNotificationChannelSubscriber(ContainerBuilder $container) {
106
        $definition = new Definition();
107
        $definition->setClass('IrishDan\NotificationBundle\Subscriber\NotificationChannelSubscriber');
108
109
        // $config = [];
110
        // foreach ($this->channelKeyAdapterMappings as $channel => $data) {
111
        //     $config[$channel] = $data['config'];
112
        // }
113
        // create a paramater with all of the channel data.
114
        $container->setParameter('notification.channel_adapter_map', $this->channelKeyAdapterMappings);
115
116
        $definition->setArguments([new Reference('event_dispatcher'), new Reference('notification.channel'), '%notification.channel_adapter_map%']);
117
        $definition->addTag('kernel.event_subscriber');
118
119
        $container->setDefinition('notification.channel_subscriber', $definition);
120
    }
121
122 View Code Duplication
    private function createChannel(ContainerBuilder $container, string $id, $adapter = null)
0 ignored issues
show
Unused Code introduced by
The parameter $adapter is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This method seems to be duplicated in 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...
123
    {
124
        $definition = new Definition();
125
        $definition->setClass('IrishDan\NotificationBundle\Channel\Channel');
126
        $definition->addMethodCall('setEventDispatcher', [new Reference('event_dispatcher')]);
127
128
        $container->setDefinition($id, $definition);
129
    }
130
131
    private function createChannelService($channel, ContainerBuilder $container, array $config)
132
    {
133
        $factory = new ChannelFactory();
134
        $factory->create($container, $channel, $config);
135
        $this->setChannelAdapterMapping($factory->getChannelKeyAdapterMap());
136
    }
137
138
    private function createBroadcaster($name, $config, ContainerBuilder $container)
139
    {
140
        $broadcastFactory = new BroadcasterFactory();
141
        $broadcastFactory->create($container, $name, $config);
142
    }
143
144 View Code Duplication
    private function createNotificationManagerService(ContainerBuilder $container)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
145
    {
146
        $definition = new Definition();
147
        $definition->setClass('IrishDan\NotificationBundle\NotificationManager');
148
        $definition->setArguments(
149
            [
150
                new Reference('notification.channel_manager'),
151
                new Reference('notification.database_notification_manager'),
152
            ]
153
        );
154
        $definition->setPublic(true);
155
156
        $container->setDefinition('notification.manager', $definition);
157
    }
158
159
    private function createChannelManagerService(array $enabledChannels, ContainerBuilder $container)
160
    {
161
        $definition = new Definition();
162
        $definition->setClass('IrishDan\NotificationBundle\ChannelManager');
163
        $definition->setArguments(
164
            [
165
                new Reference('event_dispatcher'),
166
                $container->getParameter('notification.available_channels'),
167
            ]
168
        );
169
        $container->setDefinition('notification.channel_manager', $definition);
170
171
        foreach ($enabledChannels as $channel) {
172
            // Add the channel to the channel manager service
173
            $channelManager = $container->getDefinition('notification.channel_manager');
174
            $channelId = 'notification.channel.' . $channel;
175
            $channelManager->addMethodCall('setChannel', [$channel, new Reference($channelId)]);
176
        }
177
    }
178
}