TableRoom::getValue()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SwooleTW\Http\Websocket\Rooms;
4
5
use Swoole\Table;
6
7
class TableRoom implements RoomContract
8
{
9
    /**
10
     * @var array
11
     */
12
    protected $config;
13
14
    /**
15
     * @var \Swoole\Table
16
     */
17
    protected $rooms;
18
19
    /**
20
     * @var \Swoole\Table
21
     */
22
    protected $fds;
23
24
    /**
25
     * TableRoom constructor.
26
     *
27
     * @param array $config
28
     */
29
    public function __construct(array $config)
30
    {
31
        $this->config = $config;
32
    }
33
34
    /**
35
     * Do some init stuffs before workers started.
36
     *
37
     * @return \SwooleTW\Http\Websocket\Rooms\RoomContract
38
     */
39
    public function prepare(): RoomContract
40
    {
41
        $this->initRoomsTable();
42
        $this->initFdsTable();
43
44
        return $this;
45
    }
46
47
    /**
48
     * Add a socket fd to multiple rooms.
49
     *
50
     * @param int fd
0 ignored issues
show
Bug introduced by
The type SwooleTW\Http\Websocket\Rooms\fd was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
51
     * @param array|string rooms
0 ignored issues
show
Bug introduced by
The type SwooleTW\Http\Websocket\Rooms\rooms was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
52
     */
53
    public function add(int $fd, $roomNames)
54
    {
55
        $rooms = $this->getRooms($fd);
56
        $roomNames = is_array($roomNames) ? $roomNames : [$roomNames];
57
58
        foreach ($roomNames as $room) {
59
            $fds = $this->getClients($room);
60
61
            if (in_array($fd, $fds)) {
62
                continue;
63
            }
64
65
            $fds[] = $fd;
66
            $rooms[] = $room;
67
68
            $this->setClients($room, $fds);
69
        }
70
71
        $this->setRooms($fd, $rooms);
72
    }
73
74
    /**
75
     * Delete a socket fd from multiple rooms.
76
     *
77
     * @param int fd
78
     * @param array|string rooms
79
     */
80
    public function delete(int $fd, $roomNames = [])
81
    {
82
        $allRooms = $this->getRooms($fd);
83
        $roomNames = is_array($roomNames) ? $roomNames : [$roomNames];
84
        $rooms = count($roomNames) ? $roomNames : $allRooms;
85
86
        $removeRooms = [];
87
        foreach ($rooms as $room) {
88
            $fds = $this->getClients($room);
89
90
            if (! in_array($fd, $fds)) {
91
                continue;
92
            }
93
94
            $this->setClients($room, array_values(array_diff($fds, [$fd])));
95
            $removeRooms[] = $room;
96
        }
97
98
        $this->setRooms($fd, array_values(array_diff($allRooms, $removeRooms)));
99
    }
100
101
    /**
102
     * Get all sockets by a room key.
103
     *
104
     * @param string room
105
     *
106
     * @return array
107
     */
108
    public function getClients(string $room)
109
    {
110
        return $this->getValue($room, RoomContract::ROOMS_KEY) ?? [];
111
    }
112
113
    /**
114
     * Get all rooms by a fd.
115
     *
116
     * @param int fd
117
     *
118
     * @return array
119
     */
120
    public function getRooms(int $fd)
121
    {
122
        return $this->getValue($fd, RoomContract::DESCRIPTORS_KEY) ?? [];
123
    }
124
125
    /**
126
     * @param string $room
127
     * @param array $fds
128
     *
129
     * @return \SwooleTW\Http\Websocket\Rooms\TableRoom
130
     */
131
    protected function setClients(string $room, array $fds): TableRoom
132
    {
133
        return $this->setValue($room, $fds, RoomContract::ROOMS_KEY);
134
    }
135
136
    /**
137
     * @param int $fd
138
     * @param array $rooms
139
     *
140
     * @return \SwooleTW\Http\Websocket\Rooms\TableRoom
141
     */
142
    protected function setRooms(int $fd, array $rooms): TableRoom
143
    {
144
        return $this->setValue($fd, $rooms, RoomContract::DESCRIPTORS_KEY);
145
    }
146
147
    /**
148
     * Init rooms table
149
     */
150
    protected function initRoomsTable(): void
151
    {
152
        $this->rooms = new Table($this->config['room_rows']);
153
        $this->rooms->column('value', Table::TYPE_STRING, $this->config['room_size']);
154
        $this->rooms->create();
155
    }
156
157
    /**
158
     * Init descriptors table
159
     */
160
    protected function initFdsTable()
161
    {
162
        $this->fds = new Table($this->config['client_rows']);
163
        $this->fds->column('value', Table::TYPE_STRING, $this->config['client_size']);
164
        $this->fds->create();
165
    }
166
167
    /**
168
     * Set value to table
169
     *
170
     * @param $key
171
     * @param array $value
172
     * @param string $table
173
     *
174
     * @return $this
175
     */
176
    public function setValue($key, array $value, string $table)
177
    {
178
        $this->checkTable($table);
179
180
        $this->$table->set($key, ['value' => json_encode($value)]);
181
182
        return $this;
183
    }
184
185
    /**
186
     * Get value from table
187
     *
188
     * @param string $key
189
     * @param string $table
190
     *
191
     * @return array|mixed
192
     */
193
    public function getValue(string $key, string $table)
194
    {
195
        $this->checkTable($table);
196
197
        $value = $this->$table->get($key);
198
199
        return $value ? json_decode($value['value'], true) : [];
200
    }
201
202
    /**
203
     * Check table for exists
204
     *
205
     * @param string $table
206
     */
207
    protected function checkTable(string $table)
208
    {
209
        if (! property_exists($this, $table) || ! $this->$table instanceof Table) {
210
            throw new \InvalidArgumentException("Invalid table name: `{$table}`.");
211
        }
212
    }
213
}
214