Rooms   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 294
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 3
dl 0
loc 294
rs 10
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A all() 0 8 2
A joinUser() 0 7 1
A join() 0 4 1
A joinByName() 0 4 1
A findByName() 0 4 1
A kick() 0 8 1
A leave() 0 4 1
A topic() 0 8 1
A searchIndex() 0 8 1
A tags() 0 8 1
A delete() 0 7 1
A users() 0 21 4
A events() 0 8 1
A messages() 0 8 1
A getIterator() 0 8 2
1
<?php
2
/**
3
 * This file is part of GitterApi package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Gitter\Resources;
11
12
use Gitter\Route;
13
use Gitter\Support\Observer;
14
15
/**
16
 * A Room in Gitter can represent a GitHub Organisation, a GitHub Repository, a Gitter Channel
17
 *  or a One-to-one conversation.
18
 *
19
 * In the case of the Organisations and Repositories, the access control policies are inherited from GitHub.
20
 *
21
 * The following types of room exist:
22
 *  - ORG:          A room that represents a GitHub Organisation.
23
 *  - REPO:         A room that represents a GitHub Repository.
24
 *  - ONETOONE:     A one-to-one chat.
25
 *  - ORG_CHANNEL:  A Gitter channel nested under a GitHub Organisation.
26
 *  - REPO_CHANNEL: A Gitter channel nested under a GitHub Repository.
27
 *  - USER_CHANNEL: A Gitter channel nested under a GitHub User.
28
 *
29
 * Room schema:
30
 *  - id:              Room ID.
31
 *  - name:            Room name.
32
 *  - topic:           Room topic. (default: GitHub repo description)
33
 *  - uri:             Room URI on Gitter.
34
 *  - oneToOne:        Indicates if the room is a one-to-one chat.
35
 *  - users:           List of users in the room.
36
 *  - userCount:       Count of users in the room.
37
 *  - unreadItems:     Number of unread messages for the current user.
38
 *  - mentions:        Number of unread mentions for the current user.
39
 *  - lastAccessTime:  Last time the current user accessed the room in ISO format.
40
 *  - favourite:       Indicates if the room is on of your favourites.
41
 *  - lurk:            Indicates if the current user has disabled notifications.
42
 *  - url:             Path to the room on gitter.
43
 *  - githubType:      Type of the room.
44
 *  - tags:            Tags that define the room.
45
 *  - v:               Room version.
46
 *
47
 * @package Gitter\Resources
48
 */
49
class Rooms extends AbstractResource implements \IteratorAggregate
50
{
51
    const GITHUB_ORG   = 'ORG';
52
    const ORG_CHANNEL  = 'ORG_CHANNEL';
53
54
    const GITHUB_REPO  = 'REPO';
55
    const REPO_CHANNEL = 'REPO_CHANNEL';
56
57
    const ONE_TO_ONE   = 'ONETOONE';
58
    const USER_CHANNEL = 'USER_CHANNEL';
59
60
    /**
61
     * List rooms the current user is in
62
     *
63
     * @param string $query Search query
64
     * @return array
65
     * @throws \InvalidArgumentException
66
     * @throws \Throwable
67
     * @throws \Exception
68
     */
69
    public function all(string $query = null): array
70
    {
71
        if ($query !== null) {
72
            return $this->fetch(Route::get('rooms')->with('q', $query));
73
        }
74
75
        return $this->fetch(Route::get('rooms'));
76
    }
77
78
    /**
79
     * To join a room you'll need to provide a URI for it.
80
     * Said URI can represent a GitHub Org, a GitHub Repo or a Gitter Channel.
81
     *  - If the room exists and the user has enough permission to access it, it'll be added to the room.
82
     *  - If the room doesn't exist but the supplied URI represents a GitHub Org or GitHub Repo the user
83
     * is an admin of, the room will be created automatically and the user added.
84
     *
85
     * @param string $roomId Required ID of the room you would like to join
86
     * @param string $userId Required ID of the user
87
     * @return array
88
     * @throws \InvalidArgumentException
89
     * @throws \Throwable
90
     * @throws \Exception
91
     */
92
    public function joinUser(string $roomId, string $userId): array
93
    {
94
        return $this->fetch(
95
            Route::post('user/{userId}/rooms')->with('userId', $userId)
96
                ->withBody('id', $roomId)
97
        );
98
    }
99
100
    /**
101
     * Join to target room
102
     *
103
     * @param string $roomId Required ID of the room you would like to join
104
     * @return array
105
     * @throws \RuntimeException
106
     * @throws \InvalidArgumentException
107
     * @throws \Throwable
108
     * @throws \Exception
109
     * @throws \GuzzleHttp\Exception\ClientException
110
     */
111
    public function join(string $roomId): array
112
    {
113
        return $this->joinUser($roomId, $this->client()->authId());
114
    }
115
116
    /**
117
     * To join a room you'll need to provide a URI for it.
118
     *
119
     * Said URI can represent a GitHub Org, a GitHub Repo or a Gitter Channel.
120
     *  - If the room exists and the user has enough permission to access it, it'll be added to the room.
121
     *  - If the room doesn't exist but the supplied URI represents a GitHub Org or GitHub Repo the user
122
     *
123
     * is an admin of, the room will be created automatically and the user added.
124
     *
125
     * @param string $name Required URI of the room you would like to join
126
     * @return array
127
     * @throws \InvalidArgumentException
128
     * @throws \Throwable
129
     * @throws \Exception
130
     */
131
    public function joinByName(string $name): array
132
    {
133
        return $this->fetch(Route::post('rooms')->withBody('uri', $name));
134
    }
135
136
    /**
137
     * @param string $name
138
     * @return array
139
     * @throws \InvalidArgumentException
140
     * @throws \Throwable
141
     * @throws \Exception
142
     */
143
    public function findByName(string $name): array
144
    {
145
        return $this->joinByName($name);
146
    }
147
148
    /**
149
     * Kick target user from target room
150
     *
151
     * @param string $roomId Required ID of the room
152
     * @param string $userId Required ID of the user
153
     * @return array
154
     * @throws \InvalidArgumentException
155
     * @throws \Throwable
156
     * @throws \Exception
157
     */
158
    public function kick(string $roomId, string $userId): array
159
    {
160
        return $this->fetch(
161
            Route::delete('rooms/{roomId}/users/{userId}')
162
                ->with('roomId', $roomId)
163
                ->with('userId', $userId)
164
        );
165
    }
166
167
    /**
168
     * This can be self-inflicted to leave the the room and remove room from your left menu.
169
     *
170
     * @param string $roomId Required ID of the room
171
     * @return array
172
     * @throws \RuntimeException
173
     * @throws \InvalidArgumentException
174
     * @throws \Throwable
175
     * @throws \Exception
176
     * @throws \GuzzleHttp\Exception\ClientException
177
     */
178
    public function leave(string $roomId): array
179
    {
180
        return $this->kick($roomId, $this->client()->authId());
181
    }
182
183
    /**
184
     * Sets up a new topic of target room
185
     *
186
     * @param string $roomId Room id
187
     * @param string $topic Room topic
188
     * @return mixed
189
     * @throws \InvalidArgumentException
190
     * @throws \Throwable
191
     * @throws \Exception
192
     */
193
    public function topic(string $roomId, string $topic): array
194
    {
195
        return $this->fetch(
196
            Route::put('rooms/{roomId}')
197
                ->with('roomId', $roomId)
198
                ->withBody('topic', $topic)
199
        );
200
    }
201
202
    /**
203
     * Sets the room is indexed by search engines
204
     *
205
     * @param string $roomId Room id
206
     * @param bool $enabled Enable or disable room indexing
207
     * @return array
208
     * @throws \InvalidArgumentException
209
     * @throws \Throwable
210
     * @throws \Exception
211
     */
212
    public function searchIndex(string $roomId, bool $enabled = true): array
213
    {
214
        return $this->fetch(
215
            Route::put('rooms/{roomId}')
216
                ->with('roomId', $roomId)
217
                ->withBody('noindex', !$enabled)
218
        );
219
    }
220
221
    /**
222
     * Sets the tags that define the room
223
     *
224
     * @param string $roomId Room id
225
     * @param array $tags Target tags
226
     * @return array
227
     * @throws \InvalidArgumentException
228
     * @throws \Throwable
229
     * @throws \Exception
230
     */
231
    public function tags(string $roomId, array $tags = []): array
232
    {
233
        return $this->fetch(
234
            Route::put('rooms/{roomId}')
235
                ->with('roomId', $roomId)
236
                ->withBody('tags', implode(', ', $tags))
237
        );
238
    }
239
240
    /**
241
     * If you hate one of the rooms - you can destroy it!
242
     * Fatality.
243
     *
244
     * @internal BE CAREFUL: THIS IS VERY DANGEROUS OPERATION.
245
     *
246
     * @param string $roomId Target room id
247
     * @return array
248
     * @throws \InvalidArgumentException
249
     * @throws \Throwable
250
     * @throws \Exception
251
     */
252
    public function delete(string $roomId): array
253
    {
254
        return $this->fetch(
255
            Route::delete('rooms/{roomId}')
256
                ->with('roomId', $roomId)
257
        );
258
    }
259
260
    /**
261
     * List of Users currently in the room.
262
     *
263
     * @param string $roomId Target room id
264
     * @param string $query Optional query for users search
265
     * @return \Generator
266
     * @throws \InvalidArgumentException
267
     * @throws \Throwable
268
     * @throws \Exception
269
     */
270
    public function users(string $roomId, string $query = null): \Generator
271
    {
272
        $skip  = 0;
273
        $limit = 30;
274
275
        do {
276
            $route = Route::get('rooms/{roomId}/users')
277
                ->withMany([
278
                    'roomId' => $roomId,
279
                    'skip'   => $skip,
280
                    'limit'  => $limit,
281
                ]);
282
283
            if ($query !== null) {
284
                $route->with('q', $query);
285
            }
286
287
            yield from $response = $this->fetch($route);
288
289
        } while(\count($response) >= $limit && ($skip += $limit));
290
    }
291
292
    /**
293
     * Use the streaming API to listen events.
294
     * The streaming API allows real-time access to messages fetching.
295
     *
296
     * @param string $roomId
297
     * @return Observer
298
     * @throws \InvalidArgumentException
299
     * @throws \Throwable
300
     */
301
    public function events(string $roomId): Observer
302
    {
303
        return $this->stream(
304
            Route::get('rooms/{roomId}/events')
305
                ->with('roomId', $roomId)
306
                ->toStream()
307
        );
308
    }
309
310
    /**
311
     * Use the streaming API to listen messages.
312
     * The streaming API allows real-time access to messages fetching.
313
     *
314
     * @param string $roomId
315
     * @return Observer
316
     * @throws \InvalidArgumentException
317
     * @throws \Throwable
318
     */
319
    public function messages(string $roomId): Observer
320
    {
321
        return $this->stream(
322
            Route::get('rooms/{roomId}/chatMessages')
323
                ->with('roomId', $roomId)
324
                ->toStream()
325
        );
326
    }
327
328
    /**
329
     * @return \Generator
330
     * @throws \InvalidArgumentException
331
     * @throws \Throwable
332
     * @throws \Exception
333
     */
334
    public function getIterator(): \Generator
335
    {
336
        $rooms = $this->all();
337
338
        foreach ($rooms as $i => $room) {
339
            yield $i => $room;
340
        }
341
    }
342
}
343