Pusher::push()   B
last analyzed

Complexity

Conditions 7
Paths 12

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 7
c 1
b 0
f 0
nc 12
nop 1
dl 0
loc 16
rs 8.8333
1
<?php
2
3
namespace SwooleTW\Http\Websocket;
4
5
use SwooleTW\Http\Server\Facades\Server;
6
7
/**
8
 * Class Pusher
9
 */
10
class Pusher
11
{
12
    /**
13
     * @var \Swoole\Websocket\Server
14
     */
15
    protected $server;
16
17
    /**
18
     * @var int
19
     */
20
    protected $opcode;
21
22
    /**
23
     * @var int
24
     */
25
    protected $sender;
26
27
    /**
28
     * @var array
29
     */
30
    protected $descriptors;
31
32
    /**
33
     * @var bool
34
     */
35
    protected $broadcast;
36
37
    /**
38
     * @var bool
39
     */
40
    protected $assigned;
41
42
    /**
43
     * @var string
44
     */
45
    protected $event;
46
47
    /**
48
     * @var mixed|null
49
     */
50
    protected $message;
51
52
    /**
53
     * Push constructor.
54
     *
55
     * @param int $opcode
56
     * @param int $sender
57
     * @param array $descriptors
58
     * @param bool $broadcast
59
     * @param bool $assigned
60
     * @param string $event
61
     * @param mixed|null $message
62
     * @param \Swoole\Websocket\Server
63
     */
64
    protected function __construct(
65
        int $opcode,
66
        int $sender,
67
        array $descriptors,
68
        bool $broadcast,
69
        bool $assigned,
70
        string $event,
71
        $message = null,
72
        $server
73
    )
74
    {
75
        $this->opcode = $opcode;
76
        $this->sender = $sender;
77
        $this->descriptors = $descriptors;
78
        $this->broadcast = $broadcast;
79
        $this->assigned = $assigned;
80
        $this->event = $event;
81
        $this->message = $message;
82
        $this->server = $server;
83
    }
84
85
    /**
86
     * Static constructor
87
     *
88
     * @param array $data
89
     * @param \Swoole\Websocket\Server $server
90
     *
91
     * @return \SwooleTW\Http\Websocket\Pusher
92
     */
93
    public static function make(array $data, $server)
94
    {
95
        return new static(
96
            $data['opcode'] ?? 1,
97
            $data['sender'] ?? 0,
98
            $data['fds'] ?? [],
99
            $data['broadcast'] ?? false,
100
            $data['assigned'] ?? false,
101
            $data['event'] ?? null,
0 ignored issues
show
Bug introduced by
It seems like $data['event'] ?? null can also be of type null; however, parameter $event of SwooleTW\Http\Websocket\Pusher::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
            /** @scrutinizer ignore-type */ $data['event'] ?? null,
Loading history...
102
            $data['message'] ?? null,
103
            $server
104
        );
105
    }
106
107
    /**
108
     * @return int
109
     */
110
    public function getOpcode(): int
111
    {
112
        return $this->opcode;
113
    }
114
115
    /**
116
     * @return int
117
     */
118
    public function getSender(): int
119
    {
120
        return $this->sender;
121
    }
122
123
    /**
124
     * @return array
125
     */
126
    public function getDescriptors(): array
127
    {
128
        return $this->descriptors;
129
    }
130
131
    /**
132
     * @param int $descriptor
133
     *
134
     * @return self
135
     */
136
    public function addDescriptor($descriptor): self
137
    {
138
        return $this->addDescriptors([$descriptor]);
139
    }
140
141
    /**
142
     * @param array $descriptors
143
     *
144
     * @return self
145
     */
146
    public function addDescriptors(array $descriptors): self
147
    {
148
        $this->descriptors = array_values(
149
            array_unique(
150
                array_merge($this->descriptors, $descriptors)
151
            )
152
        );
153
154
        return $this;
155
    }
156
157
    /**
158
     * @param int $descriptor
159
     *
160
     * @return bool
161
     */
162
    public function hasDescriptor(int $descriptor): bool
163
    {
164
        return in_array($descriptor, $this->descriptors);
165
    }
166
167
    /**
168
     * @return bool
169
     */
170
    public function isBroadcast(): bool
171
    {
172
        return $this->broadcast;
173
    }
174
175
    /**
176
     * @return bool
177
     */
178
    public function isAssigned(): bool
179
    {
180
        return $this->assigned;
181
    }
182
183
    /**
184
     * @return string
185
     */
186
    public function getEvent(): string
187
    {
188
        return $this->event;
189
    }
190
191
    /**
192
     * @return mixed|null
193
     */
194
    public function getMessage()
195
    {
196
        return $this->message;
197
    }
198
199
    /**
200
     * @return \Swoole\Websocket\Server
201
     */
202
    public function getServer()
203
    {
204
        return $this->server;
205
    }
206
207
    /**
208
     * @return bool
209
     */
210
    public function shouldBroadcast(): bool
211
    {
212
        return $this->broadcast && empty($this->descriptors) && ! $this->assigned;
213
    }
214
215
    /**
216
     * Returns all descriptors that are websocket
217
     *
218
     * @param \Swoole\Connection\Iterator $descriptors
219
     *
220
     * @return array
221
     */
222
    protected function getWebsocketConnections(): array
223
    {
224
        return array_filter(iterator_to_array($this->server->connections), function ($fd) {
225
            return $this->server->isEstablished($fd);
226
        });
227
    }
228
229
    /**
230
     * @param int $fd
231
     *
232
     * @return bool
233
     */
234
    public function shouldPushToDescriptor(int $fd): bool
235
    {
236
        if (! $this->server->isEstablished($fd)) {
237
            return false;
238
        }
239
240
        return $this->broadcast ? $this->sender !== (int) $fd : true;
241
    }
242
243
    /**
244
     * Push message to related descriptors
245
     *
246
     * @param mixed $payload
247
     *
248
     * @return void
249
     */
250
    public function push($payload): void
251
    {
252
        // attach sender if not broadcast
253
        if (! $this->broadcast && $this->sender && ! $this->hasDescriptor($this->sender)) {
254
            $this->addDescriptor($this->sender);
255
        }
256
257
        // check if to broadcast to other clients
258
        if ($this->shouldBroadcast()) {
259
            $this->addDescriptors($this->getWebsocketConnections());
260
        }
261
262
        // push message to designated fds
263
        foreach ($this->descriptors as $descriptor) {
264
            if ($this->shouldPushToDescriptor($descriptor)) {
265
                $this->server->push($descriptor, $payload, $this->opcode);
0 ignored issues
show
Bug introduced by
$this->opcode of type integer is incompatible with the type boolean expected by parameter $binary_data of Swoole\WebSocket\Server::push(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

265
                $this->server->push($descriptor, $payload, /** @scrutinizer ignore-type */ $this->opcode);
Loading history...
266
            }
267
        }
268
    }
269
}
270