Completed
Push — master ( 57a73d...51c7de )
by Alexey
38:40
created

Broadcast::setDoctrine()   A

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 SfCod\SocketIoBundle\Service;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Exception;
7
use HTMLPurifier;
8
use Psr\Log\LoggerInterface;
9
use SfCod\SocketIoBundle\Events\EventInterface;
10
use SfCod\SocketIoBundle\events\EventPolicyInterface;
11
use SfCod\SocketIoBundle\Events\EventPublisherInterface;
12
use SfCod\SocketIoBundle\events\EventRoomInterface;
13
use SfCod\SocketIoBundle\Events\EventSubscriberInterface;
14
use Symfony\Component\DependencyInjection\ContainerInterface;
15
16
/**
17
 * Class Broadcast
18
 *
19
 * @package SfCod\SocketIoBundle
20
 */
21
class Broadcast
22
{
23
    /**
24
     * @var array
25
     */
26
    protected static $channels = [];
27
    /**
28
     * @var RedisDriver
29
     */
30
    protected $redis;
31
    /**
32
     * @var LoggerInterface
33
     */
34
    protected $logger;
35
    /**
36
     * @var EventManager
37
     */
38
    protected $manager;
39
    /**
40
     * @var Process
41
     */
42
    protected $process;
43
    /**
44
     * @var EntityManagerInterface
45
     */
46
    protected $entityManager;
47
48
    /**
49
     * Broadcast constructor.
50
     *
51
     * @param ContainerInterface $container
0 ignored issues
show
Bug introduced by
There is no parameter named $container. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
52
     * @param RedisDriver $redis
53
     * @param EventManager $manager
54
     * @param LoggerInterface $logger
55
     */
56
    public function __construct(RedisDriver $redis, EventManager $manager, LoggerInterface $logger, Process $process)
57
    {
58
        $this->redis = $redis;
59
        $this->logger = $logger;
60
        $this->manager = $manager;
61
        $this->process = $process;
62
    }
63
64
    /**
65
     * Subscribe to event from client
66
     *
67
     * @param string $event
68
     * @param array $data
69
     *
70
     * @return \Symfony\Component\Process\Process
71
     *
72
     * @throws Exception
73
     */
74
    public function on(string $event, array $data)
75
    {
76
        // Clear data
77
        array_walk_recursive($data, function (&$item, $key) {
0 ignored issues
show
Unused Code introduced by
The parameter $key 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...
78
            $item = (new HtmlPurifier())->purify($item);
79
        });
80
81
        $this->logger->info(json_encode(['type' => 'on', 'name' => $event, 'data' => $data]));
82
83
        return $this->process->run($event, $data);
84
    }
85
86
    /**
87
     * Run process
88
     *
89
     * @param string $handler
90
     * @param array $data
91
     */
92
    public function process(string $handler, array $data)
93
    {
94
        try {
95
            /** @var EventInterface|EventSubscriberInterface|EventPolicyInterface $eventHandler */
96
            $eventHandler = $this->manager->resolve($handler); //container->get(sprintf('socketio.%s', $handler));
97
98
            if (false === $eventHandler instanceof EventInterface) {
99
                throw new Exception('Event should implement EventInterface');
100
            }
101
102
            $eventHandler->setPayload($data);
103
104
            if (false === $eventHandler instanceof EventSubscriberInterface) {
105
                throw new Exception('Event should implement EventSubscriberInterface');
106
            }
107
108
            if (true === $eventHandler instanceof EventPolicyInterface && false === $eventHandler->can($data)) {
109
                return;
110
            }
111
112
            if ($this->entityManager) {
113
                $connection = $this->entityManager->getConnection();
114
                $connection->close();
115
                $connection->connect();
116
            }
117
118
            $eventHandler->handle();
119
        } catch (Exception $e) {
120
            $this->logger->error($e);
121
        }
122
    }
123
124
    /**
125
     * Emit event to client
126
     *
127
     * @param string $event
128
     * @param array $data
129
     *
130
     * @throws Exception
131
     */
132
    public function emit(string $event, array $data)
133
    {
134
        $this->logger->info(json_encode(['type' => 'emit', 'name' => $event, 'data' => $data]));
135
136
        try {
137
            /** @var EventInterface|EventPublisherInterface|EventRoomInterface $eventHandler */
138
            $eventHandler = $this->container->get(sprintf('socketio.%s', $event));
0 ignored issues
show
Bug introduced by
The property container does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
139
140
            if (false === $eventHandler instanceof EventInterface) {
141
                throw new Exception('Event should implement EventInterface');
142
            }
143
144
            $eventHandler->setPayload($data);
145
146
            if (false === $eventHandler instanceof EventPublisherInterface) {
147
                throw new Exception('Event should implement EventPublisherInterface');
148
            }
149
150
            $data = $eventHandler->fire();
151
152
            if ($eventHandler instanceof EventRoomInterface) {
153
                $data['room'] = $eventHandler->room();
154
            }
155
156
            $eventHandlerClass = get_class($eventHandler);
157
            foreach ($eventHandlerClass::broadcastOn() as $channel) {
158
                $this->publish($this->channelName($channel), [
159
                    'name' => $eventHandlerClass::name(),
160
                    'data' => $data,
161
                ]);
162
            }
163
        } catch (Exception $e) {
164
            $this->logger->error($e);
165
        }
166
    }
167
168
    /**
169
     * Publish data to redis channel
170
     *
171
     * @param string $channel
172
     * @param array $data
173
     */
174
    protected function publish(string $channel, array $data)
175
    {
176
        $this->redis->getClient(true)->publish($channel, json_encode($data));
177
    }
178
179
    /**
180
     * Prepare channel name
181
     *
182
     * @param string $name
183
     *
184
     * @return string
185
     */
186
    protected function channelName(string $name): string
187
    {
188
        return $name . getenv('SOCKET_IO_NSP');
189
    }
190
191
    /**
192
     * Redis channels names
193
     *
194
     * @return array
195
     */
196
    public function channels(): array
197
    {
198
        if (empty(self::$channels)) {
199
            foreach ($this->manager->getList() as $eventHandlerClass) {
200
                self::$channels = array_merge(self::$channels, $eventHandlerClass::broadcastOn());
201
            }
202
            self::$channels = array_unique(self::$channels);
203
            self::$channels = array_map(function ($channel) {
204
                return $this->channelName($channel);
205
            }, self::$channels);
206
        }
207
208
        return self::$channels;
209
    }
210
211
    public function setDoctrine(EntityManagerInterface $entityManager)
212
    {
213
        $this->entityManager = $entityManager;
214
    }
215
}
216