Passed
Push — master ( e0b916...9184fe )
by Albert
06:29 queued 04:25
created

Pusher::isAssigned()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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 string|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 string|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
        string $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\Push
92
     */
93
    public static function make(array $data, $server)
94
    {
95
        return new static(
0 ignored issues
show
Bug Best Practice introduced by
The expression return new static($data[...age'] ?? null, $server) returns the type SwooleTW\Http\Websocket\Pusher which is incompatible with the documented return type SwooleTW\Http\Websocket\Push.
Loading history...
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 string|null
193
     */
194
    public function getMessage(): ?string
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
     * Check if it's a websocket fd.
217
     *
218
     * @param int $fd
219
     *
220
     * @return bool
221
     */
222
    public function isServerWebsocket(int $fd): bool
223
    {
224
        return $this->server->connection_info($fd)['websocket_status'] ?? false;
225
    }
226
227
    /**
228
     * Returns all descriptors that are websocket
229
     *
230
     * @param \Swoole\Connection\Iterator $descriptors
231
     *
232
     * @return array
233
     */
234
    protected function getWebsocketConnections(): array
235
    {
236
        return array_filter(iterator_to_array($this->server->connections), function ($fd) {
237
            return $this->isServerWebsocket($fd);
238
        });
239
    }
240
241
    /**
242
     * @param int $fd
243
     *
244
     * @return bool
245
     */
246
    public function shouldPushToDescriptor(int $fd): bool
247
    {
248
        return $this->server->exist($fd)
249
            && ($this->broadcast && $this->sender !== (int) $fd);
250
    }
251
252
    /**
253
     * Push message to related descriptors
254
     *
255
     * @param mixed $payload
256
     *
257
     * @return void
258
     */
259
    public function push($payload): void
260
    {
261
        // attach sender if not broadcast
262
        if (! $this->broadcast && $this->sender && ! $this->hasDescriptor($this->sender)) {
263
            $this->addDescriptor($this->sender);
264
        }
265
266
        // check if to broadcast to other clients
267
        if ($this->shouldBroadcast()) {
268
            $this->addDescriptors($this->getWebsocketConnections());
269
        }
270
271
        // push message to designated fds
272
        foreach ($this->descriptors as $descriptor) {
273
            if ($this->shouldPushToDescriptor($descriptor)) {
274
                $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

274
                $this->server->push($descriptor, $payload, /** @scrutinizer ignore-type */ $this->opcode);
Loading history...
275
            }
276
        }
277
    }
278
}