Completed
Push — master ( 9cb398...3fed9f )
by Alexey
105:26 queued 65:22
created

Broadcast::publish()   A

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 2
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
     * @var string
28
     */
29
    public static $yiiAlias = '@app/..';
30
31
    /**
32
     * Subscribe to event from client
33
     *
34
     * @param string $event
35
     * @param array $data
36
     *
37
     * @throws Exception
38
     */
39
    public static function on(string $event, array $data)
40
    {
41
        // Clear data
42
        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...
43
            $item = HtmlPurifier::process($item);
44
        });
45
46
        Yii::info(Json::encode([
47
            'type' => 'on',
48
            'name' => $event,
49
            'data' => $data,
50
        ]), 'socket.io');
51
52
        $eventClassName = self::getManager()->getList()[$event] ?? null;
53
        if (null === $eventClassName) {
54
            Yii::error(LoggerMessage::trace("Can not find $event", Json::encode($data)));
55
        }
56
57
        (new Process(self::$yiiAlias))->run($eventClassName, $data);
58
    }
59
60
    /**
61
     * Handle process from client
62
     *
63
     * @param string $handler
64
     * @param array $data
65
     */
66
    public static function process(string $handler, array $data)
67
    {
68
        try {
69
            /** @var EventSubInterface|EventPolicyInterface $event */
70
            $event = new $handler($data);
71
72
            if (false === $event instanceof EventSubInterface) {
73
                throw new Exception('Event should implement EventSubInterface');
74
            }
75
76
            Yii::$app->db->close();
77
            Yii::$app->db->open();
78
79
            if (true === $event instanceof EventPolicyInterface && false === $event->can($data)) {
80
                return;
81
            }
82
83
            $event->handle($data);
84
        } catch (Exception $e) {
85
            Yii::error(LoggerMessage::log($e, Json::encode($data)));
86
        }
87
    }
88
89
    /**
90
     * Emit event to client
91
     *
92
     * @param string $event
93
     * @param array $data
94
     *
95
     * @throws Exception
96
     */
97
    public static function emit(string $event, array $data)
98
    {
99
        $eventClassName = self::getManager()->getList()[$event] ?? null;
100
        try {
101
            if (null === $eventClassName) {
102
                throw new Exception("Can not find $event");
103
            }
104
105
            /** @var EventPubInterface|EventRoomInterface $event */
106
            $event = new $eventClassName($data);
107
108
            if (false === $event instanceof EventPubInterface) {
109
                throw new Exception('Event should implement EventPubInterface');
110
            }
111
112
            $data = $event->fire($data);
113
114
            if (true === $event instanceof EventRoomInterface) {
115
                $data['room'] = $event->room();
116
            }
117
118
            Yii::info(Json::encode([
119
                'type' => 'emit',
120
                'name' => $event,
121
                'data' => $data,
122
            ]), 'socket.io');
123
            foreach ($eventClassName::broadcastOn() as $channel) {
124
                static::publish(static::channelName($channel), [
125
                    'name' => $eventClassName::name(),
126
                    'data' => $data,
127
                ]);
128
            }
129
        } catch (Exception $e) {
130
            Yii::error(LoggerMessage::log($e));
131
        }
132
    }
133
134
    /**
135
     * Prepare channel name
136
     *
137
     * @param $name
138
     *
139
     * @return string
140
     */
141
    public static function channelName($name)
142
    {
143
        return $name . self::getManager()->nsp;
144
    }
145
146
    /**
147
     * Publish data to redis channel
148
     *
149
     * @param string $channel
150
     * @param array $data
151
     */
152
    public static function publish(string $channel, array $data)
153
    {
154
        static::getDriver()->getConnection(true)->publish($channel, Json::encode($data));
155
    }
156
157
    /**
158
     * Redis channels names
159
     *
160
     * @return array
161
     */
162
    public static function channels(): array
163
    {
164
        if (empty(self::$channels)) {
165
            foreach (self::getManager()->getList() as $eventClassName) {
166
                self::$channels = ArrayHelper::merge(self::$channels, $eventClassName::broadcastOn());
167
            }
168
            self::$channels = array_unique(self::$channels);
169
170
            self::$channels = array_map(function ($channel) {
171
                return static::channelName($channel);
172
            }, self::$channels);
173
            //Yii::info(Json::encode(self::$channels));
174
        }
175
176
        return self::$channels;
177
    }
178
179
    /**
180
     * @return RedisDriver
181
     */
182
    public static function getDriver()
183
    {
184
        return Yii::$app->broadcastDriver;
185
    }
186
187
    /**
188
     * @return EventManager
189
     */
190
    public static function getManager()
191
    {
192
        return Yii::$app->broadcastEvents;
193
    }
194
}
195