Broadcast::channelName()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace yiicod\socketio;
4
5
use Exception;
6
use Yii;
7
use yii\helpers\ArrayHelper;
8
use yii\helpers\HtmlPurifier;
9
use yii\helpers\Json;
10
use yiicod\base\helpers\LoggerMessage;
11
use yiicod\socketio\drivers\RedisDriver;
12
use yiicod\socketio\events\EventPolicyInterface;
13
use yiicod\socketio\events\EventPubInterface;
14
use yiicod\socketio\events\EventRoomInterface;
15
use yiicod\socketio\events\EventSubInterface;
16
17
/**
18
 * Class Broadcast
19
 *
20
 * @package yiicod\socketio
21
 */
22
class Broadcast
23
{
24
    protected static $channels = [];
25
26
    /**
27
     * Subscribe to event from client
28
     *
29
     * @param string $event
30
     * @param array $data
31
     *
32
     * @throws Exception
33
     */
34
    public static function on(string $event, array $data)
35
    {
36
        // Clear data
37
        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...
38
            $item = HtmlPurifier::process($item);
39
        });
40
41
        Yii::info(Json::encode([
42
            'type' => 'on',
43
            'name' => $event,
44
            'data' => $data,
45
        ]), 'socket.io');
46
47
        $eventClassName = self::getManager()->getList()[$event] ?? null;
48
        if (null === $eventClassName) {
49
            Yii::error(LoggerMessage::trace("Can not find $event", Json::encode($data)));
0 ignored issues
show
Documentation introduced by
\yii\helpers\Json::encode($data) is of type string, but the function expects a array.

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...
50
        }
51
52
        Yii::$container->get(Process::class)->run($eventClassName, $data);
53
    }
54
55
    /**
56
     * Handle process from client
57
     *
58
     * @param string $handler
59
     * @param array $data
60
     */
61
    public static function process(string $handler, array $data)
62
    {
63
        try {
64
            /** @var EventSubInterface|EventPolicyInterface $event */
65
            $event = new $handler($data);
66
67
            if (false === $event instanceof EventSubInterface) {
68
                throw new Exception('Event should implement EventSubInterface');
69
            }
70
71
            Yii::$app->db->close();
72
            Yii::$app->db->open();
73
74
            if (true === $event instanceof EventPolicyInterface && false === $event->can($data)) {
75
                return;
76
            }
77
78
            $event->handle($data);
79
        } catch (Exception $e) {
80
            Yii::error(LoggerMessage::log($e, Json::encode($data)));
0 ignored issues
show
Documentation introduced by
$e is of type object<Exception>, but the function expects a object<Throwable>.

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...
81
        }
82
    }
83
84
    /**
85
     * Emit event to client
86
     *
87
     * @param string $event
88
     * @param array $data
89
     *
90
     * @throws Exception
91
     */
92
    public static function emit(string $event, array $data)
93
    {
94
        $eventClassName = self::getManager()->getList()[$event] ?? null;
95
        try {
96
            if (null === $eventClassName) {
97
                throw new Exception("Can not find $event");
98
            }
99
100
            /** @var EventPubInterface|EventRoomInterface $event */
101
            $event = new $eventClassName($data);
102
103
            if (false === $event instanceof EventPubInterface) {
104
                throw new Exception('Event should implement EventPubInterface');
105
            }
106
107
            $data = $event->fire($data);
108
109
            if (true === $event instanceof EventRoomInterface) {
110
                $data['room'] = $event->room();
111
            }
112
113
            Yii::info(Json::encode([
114
                'type' => 'emit',
115
                'name' => $event,
116
                'data' => $data,
117
            ]), 'socket.io');
118
            foreach ($eventClassName::broadcastOn() as $channel) {
119
                static::publish(static::channelName($channel), [
120
                    'name' => $eventClassName::name(),
121
                    'data' => $data,
122
                ]);
123
            }
124
        } catch (Exception $e) {
125
            Yii::error(LoggerMessage::log($e));
0 ignored issues
show
Documentation introduced by
$e is of type object<Exception>, but the function expects a object<Throwable>.

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...
126
        }
127
    }
128
129
    /**
130
     * Prepare channel name
131
     *
132
     * @param $name
133
     *
134
     * @return string
135
     */
136
    public static function channelName($name)
137
    {
138
        return $name . self::getManager()->nsp;
139
    }
140
141
    /**
142
     * Publish data to redis channel
143
     *
144
     * @param string $channel
145
     * @param array $data
146
     */
147
    public static function publish(string $channel, array $data)
148
    {
149
        static::getDriver()->getConnection(true)->publish($channel, Json::encode($data));
150
    }
151
152
    /**
153
     * Redis channels names
154
     *
155
     * @return array
156
     */
157
    public static function channels(): array
158
    {
159
        if (empty(self::$channels)) {
160
            foreach (self::getManager()->getList() as $eventClassName) {
161
                self::$channels = ArrayHelper::merge(self::$channels, $eventClassName::broadcastOn());
162
            }
163
            self::$channels = array_unique(self::$channels);
164
165
            self::$channels = array_map(function ($channel) {
166
                return static::channelName($channel);
167
            }, self::$channels);
168
            //Yii::info(Json::encode(self::$channels));
169
        }
170
171
        return self::$channels;
172
    }
173
174
    /**
175
     * @return RedisDriver
176
     */
177
    public static function getDriver()
178
    {
179
        return Yii::$app->broadcastDriver;
180
    }
181
182
    /**
183
     * @return EventManager
184
     */
185
    public static function getManager()
186
    {
187
        return Yii::$app->broadcastEvents;
188
    }
189
}
190