Completed
Push — master ( 80bdb5...459619 )
by Maxence
03:02
created

CircleService::getCircles()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 9.44
c 0
b 0
f 0
cc 2
nc 2
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
6
/**
7
 * Circles - Bring cloud-users closer together.
8
 *
9
 * This file is licensed under the Affero General Public License version 3 or
10
 * later. See the COPYING file.
11
 *
12
 * @author Maxence Lange <[email protected]>
13
 * @copyright 2021
14
 * @license GNU AGPL version 3 or any later version
15
 *
16
 * This program is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU Affero General Public License as
18
 * published by the Free Software Foundation, either version 3 of the
19
 * License, or (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License
27
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
28
 *
29
 */
30
31
32
namespace OCA\Circles\Service;
33
34
35
use daita\MySmallPhpTools\Model\SimpleDataStore;
36
use daita\MySmallPhpTools\Traits\TArrayTools;
37
use daita\MySmallPhpTools\Traits\TStringTools;
38
use OCA\Circles\Db\CircleRequest;
39
use OCA\Circles\Db\MemberRequest;
40
use OCA\Circles\Exceptions\CircleNotFoundException;
41
use OCA\Circles\Exceptions\FederatedEventException;
42
use OCA\Circles\Exceptions\FederatedItemException;
43
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
44
use OCA\Circles\Exceptions\InitiatorNotFoundException;
45
use OCA\Circles\Exceptions\MembersLimitException;
46
use OCA\Circles\Exceptions\OwnerNotFoundException;
47
use OCA\Circles\Exceptions\RemoteInstanceException;
48
use OCA\Circles\Exceptions\RemoteNotFoundException;
49
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
50
use OCA\Circles\Exceptions\RequestBuilderException;
51
use OCA\Circles\Exceptions\UnknownRemoteException;
52
use OCA\Circles\FederatedItems\CircleConfig;
53
use OCA\Circles\FederatedItems\CircleCreate;
54
use OCA\Circles\FederatedItems\CircleDestroy;
55
use OCA\Circles\FederatedItems\CircleEdit;
56
use OCA\Circles\FederatedItems\CircleJoin;
57
use OCA\Circles\FederatedItems\CircleLeave;
58
use OCA\Circles\FederatedItems\CircleSettings;
59
use OCA\Circles\Model\Circle;
60
use OCA\Circles\Model\Federated\FederatedEvent;
61
use OCA\Circles\Model\FederatedUser;
62
use OCA\Circles\Model\ManagedModel;
63
use OCA\Circles\Model\Member;
64
use OCA\Circles\StatusCode;
65
66
67
/**
68
 * Class CircleService
69
 *
70
 * @package OCA\Circles\Service
71
 */
72
class CircleService {
73
74
75
	use TArrayTools;
76
	use TStringTools;
77
78
79
	/** @var CircleRequest */
80
	private $circleRequest;
81
82
	/** @var MemberRequest */
83
	private $memberRequest;
84
85
	/** @var RemoteStreamService */
86
	private $remoteStreamService;
87
88
	/** @var FederatedUserService */
89
	private $federatedUserService;
90
91
	/** @var FederatedEventService */
92
	private $federatedEventService;
93
94
	/** @var MemberService */
95
	private $memberService;
96
97
	/** @var ConfigService */
98
	private $configService;
99
100
101
	/**
102
	 * CircleService constructor.
103
	 *
104
	 * @param CircleRequest $circleRequest
105
	 * @param MemberRequest $memberRequest
106
	 * @param RemoteStreamService $remoteStreamService
107
	 * @param FederatedUserService $federatedUserService
108
	 * @param FederatedEventService $federatedEventService
109
	 * @param MemberService $memberService
110
	 * @param ConfigService $configService
111
	 */
112
	public function __construct(
113
		CircleRequest $circleRequest, MemberRequest $memberRequest, RemoteStreamService $remoteStreamService,
114
		FederatedUserService $federatedUserService, FederatedEventService $federatedEventService,
115
		MemberService $memberService, ConfigService $configService
116
	) {
117
		$this->circleRequest = $circleRequest;
118
		$this->memberRequest = $memberRequest;
119
		$this->remoteStreamService = $remoteStreamService;
120
		$this->federatedUserService = $federatedUserService;
121
		$this->federatedEventService = $federatedEventService;
122
		$this->memberService = $memberService;
123
		$this->configService = $configService;
124
	}
125
126
127
	/**
128
	 * @param string $name
129
	 * @param FederatedUser|null $owner
130
	 * @param bool $personal
131
	 * @param bool $local
132
	 *
133
	 * @return array
134
	 * @throws FederatedEventException
135
	 * @throws FederatedItemException
136
	 * @throws InitiatorNotConfirmedException
137
	 * @throws InitiatorNotFoundException
138
	 * @throws OwnerNotFoundException
139
	 * @throws RemoteInstanceException
140
	 * @throws RemoteNotFoundException
141
	 * @throws RemoteResourceNotFoundException
142
	 * @throws UnknownRemoteException
143
	 * @throws RequestBuilderException
144
	 */
145
	public function create(
146
		string $name,
147
		?FederatedUser $owner = null,
148
		bool $personal = false,
149
		bool $local = false
150
	): array {
151
152
		$this->federatedUserService->mustHaveCurrentUser();
153
		if (is_null($owner)) {
154
			$owner = $this->federatedUserService->getCurrentUser();
155
		}
156
157
		if (is_null($owner)) {
158
			throw new OwnerNotFoundException('owner not defined');
159
		}
160
161
		$circle = new Circle();
162
		$circle->setName($name)
163
			   ->setSingleId($this->token(ManagedModel::ID_LENGTH))
164
			   ->setSource(Member::TYPE_CIRCLE);
165
166
		if ($personal) {
167
			$circle->setConfig(Circle::CFG_SINGLE);
168
		}
169
170
		if ($local) {
171
			$circle->addConfig(Circle::CFG_LOCAL);
172
		}
173
174
		$member = new Member();
175
		$member->importFromIFederatedUser($owner);
176
		$member->setId($this->token(ManagedModel::ID_LENGTH))
177
			   ->setCircleId($circle->getSingleId())
178
			   ->setLevel(Member::LEVEL_OWNER)
179
			   ->setStatus(Member::STATUS_MEMBER);
180
181
		$this->federatedUserService->setMemberPatron($member);
182
183
		$circle->setOwner($member)
184
			   ->setInitiator($member);
185
186
		$event = new FederatedEvent(CircleCreate::class);
187
		$event->setCircle($circle);
188
		$this->federatedEventService->newEvent($event);
189
190
		return $event->getOutcome();
191
	}
192
193
194
	/**
195
	 * @param string $circleId
196
	 *
197
	 * @return array
198
	 * @throws CircleNotFoundException
199
	 * @throws FederatedEventException
200
	 * @throws FederatedItemException
201
	 * @throws InitiatorNotConfirmedException
202
	 * @throws InitiatorNotFoundException
203
	 * @throws OwnerNotFoundException
204
	 * @throws RemoteInstanceException
205
	 * @throws RemoteNotFoundException
206
	 * @throws RemoteResourceNotFoundException
207
	 * @throws RequestBuilderException
208
	 * @throws UnknownRemoteException
209
	 */
210
	public function destroy(string $circleId): array {
211
		$this->federatedUserService->mustHaveCurrentUser();
212
213
		$circle = $this->getCircle($circleId);
214
215
		$event = new FederatedEvent(CircleDestroy::class);
216
		$event->setCircle($circle);
217
		$this->federatedEventService->newEvent($event);
218
219
		return $event->getOutcome();
220
	}
221
222
223
	/**
224
	 * @param string $circleId
225
	 * @param int $config
226
	 *
227
	 * @return array
228
	 * @throws CircleNotFoundException
229
	 * @throws FederatedEventException
230
	 * @throws FederatedItemException
231
	 * @throws InitiatorNotConfirmedException
232
	 * @throws InitiatorNotFoundException
233
	 * @throws OwnerNotFoundException
234
	 * @throws RemoteInstanceException
235
	 * @throws RemoteNotFoundException
236
	 * @throws RemoteResourceNotFoundException
237
	 * @throws UnknownRemoteException
238
	 * @throws RequestBuilderException
239
	 */
240
	public function updateConfig(string $circleId, int $config): array {
241
		$circle = $this->getCircle($circleId);
242
243
		$event = new FederatedEvent(CircleConfig::class);
244
		$event->setCircle($circle);
245
		$event->setData(new SimpleDataStore(['config' => $config]));
246
247
		$this->federatedEventService->newEvent($event);
248
249
		return $event->getOutcome();
250
	}
251
252
253
	/**
254
	 * @param string $circleId
255
	 * @param string $displayName
256
	 *
257
	 * @return array
258
	 * @throws CircleNotFoundException
259
	 * @throws FederatedEventException
260
	 * @throws FederatedItemException
261
	 * @throws InitiatorNotConfirmedException
262
	 * @throws InitiatorNotFoundException
263
	 * @throws OwnerNotFoundException
264
	 * @throws RemoteInstanceException
265
	 * @throws RemoteNotFoundException
266
	 * @throws RemoteResourceNotFoundException
267
	 * @throws RequestBuilderException
268
	 * @throws UnknownRemoteException
269
	 */
270
	public function updateDisplayName(string $circleId, string $displayName): array {
271
		$circle = $this->getCircle($circleId);
272
273
		$event = new FederatedEvent(CircleEdit::class);
274
		$event->setCircle($circle);
275
		$event->setData(new SimpleDataStore(['displayName' => $displayName]));
276
277
		$this->federatedEventService->newEvent($event);
278
279
		return $event->getOutcome();
280
	}
281
282
	/**
283
	 * @param string $circleId
284
	 * @param string $description
285
	 *
286
	 * @return array
287
	 * @throws CircleNotFoundException
288
	 * @throws FederatedEventException
289
	 * @throws FederatedItemException
290
	 * @throws InitiatorNotConfirmedException
291
	 * @throws InitiatorNotFoundException
292
	 * @throws OwnerNotFoundException
293
	 * @throws RemoteInstanceException
294
	 * @throws RemoteNotFoundException
295
	 * @throws RemoteResourceNotFoundException
296
	 * @throws RequestBuilderException
297
	 * @throws UnknownRemoteException
298
	 */
299
	public function updateDescription(string $circleId, string $description): array {
300
		$circle = $this->getCircle($circleId);
301
302
		$event = new FederatedEvent(CircleEdit::class);
303
		$event->setCircle($circle);
304
		$event->setData(new SimpleDataStore(['description' => $description]));
305
306
		$this->federatedEventService->newEvent($event);
307
308
		return $event->getOutcome();
309
	}
310
311
	/**
312
	 * @param string $circleId
313
	 * @param array $settings
314
	 *
315
	 * @return array
316
	 * @throws CircleNotFoundException
317
	 * @throws FederatedEventException
318
	 * @throws FederatedItemException
319
	 * @throws InitiatorNotConfirmedException
320
	 * @throws InitiatorNotFoundException
321
	 * @throws OwnerNotFoundException
322
	 * @throws RemoteInstanceException
323
	 * @throws RemoteNotFoundException
324
	 * @throws RemoteResourceNotFoundException
325
	 * @throws RequestBuilderException
326
	 * @throws UnknownRemoteException
327
	 */
328
	public function updateSettings(string $circleId, array $settings) {
329
		$circle = $this->getCircle($circleId);
330
331
		$event = new FederatedEvent(CircleSettings::class);
332
		$event->setCircle($circle);
333
		$event->setData(new SimpleDataStore(['settings' => $settings]));
334
335
		$this->federatedEventService->newEvent($event);
336
337
		return $event->getOutcome();
338
	}
339
340
341
	/**
342
	 * @param string $circleId
343
	 *
344
	 * @return array
345
	 * @throws CircleNotFoundException
346
	 * @throws FederatedEventException
347
	 * @throws FederatedItemException
348
	 * @throws InitiatorNotConfirmedException
349
	 * @throws InitiatorNotFoundException
350
	 * @throws OwnerNotFoundException
351
	 * @throws RemoteInstanceException
352
	 * @throws RemoteNotFoundException
353
	 * @throws RemoteResourceNotFoundException
354
	 * @throws UnknownRemoteException
355
	 * @throws RequestBuilderException
356
	 */
357
	public function circleJoin(string $circleId): array {
358
		$this->federatedUserService->mustHaveCurrentUser();
359
360
		$circle = $this->circleRequest->getCircle($circleId, $this->federatedUserService->getCurrentUser());
361
362
		$event = new FederatedEvent(CircleJoin::class);
363
		$event->setCircle($circle);
364
365
		$this->federatedEventService->newEvent($event);
366
367
		return $event->getOutcome();
368
	}
369
370
371
	/**
372
	 * @param string $circleId
373
	 *
374
	 * @return array
375
	 * @throws CircleNotFoundException
376
	 * @throws FederatedEventException
377
	 * @throws FederatedItemException
378
	 * @throws InitiatorNotConfirmedException
379
	 * @throws InitiatorNotFoundException
380
	 * @throws OwnerNotFoundException
381
	 * @throws RemoteInstanceException
382
	 * @throws RemoteNotFoundException
383
	 * @throws RemoteResourceNotFoundException
384
	 * @throws UnknownRemoteException
385
	 */
386
	public function circleLeave(string $circleId): array {
387
		$this->federatedUserService->mustHaveCurrentUser();
388
389
		$circle = $this->circleRequest->getCircle($circleId, $this->federatedUserService->getCurrentUser());
390
391
		$event = new FederatedEvent(CircleLeave::class);
392
		$event->setCircle($circle);
393
394
		$this->federatedEventService->newEvent($event);
395
396
		return $event->getOutcome();
397
	}
398
399
400
	/**
401
	 * @param string $circleId
402
	 * @param int $filter
403
	 *
404
	 * @return Circle
405
	 * @throws CircleNotFoundException
406
	 * @throws InitiatorNotFoundException
407
	 * @throws RequestBuilderException
408
	 */
409
	public function getCircle(
410
		string $circleId,
411
		int $filter = Circle::CFG_BACKEND | Circle::CFG_SINGLE | Circle::CFG_HIDDEN
412
	): Circle {
413
		$this->federatedUserService->mustHaveCurrentUser();
414
415
		return $this->circleRequest->getCircle(
416
			$circleId,
417
			$this->federatedUserService->getCurrentUser(),
418
			$this->federatedUserService->getRemoteInstance(),
419
			$filter
420
		);
421
	}
422
423
424
	/**
425
	 * @param Circle|null $circleFilter
426
	 * @param Member|null $memberFilter
427
	 * @param SimpleDataStore|null $params
428
	 *
429
	 * @return Circle[]
430
	 * @throws InitiatorNotFoundException
431
	 * @throws RequestBuilderException
432
	 */
433
	public function getCircles(
434
		?Circle $circleFilter = null,
435
		?Member $memberFilter = null,
436
		?SimpleDataStore $params = null
437
	): array {
438
		$this->federatedUserService->mustHaveCurrentUser();
439
440
		if ($params === null) {
441
			$params = new SimpleDataStore();
442
		}
443
		$params->default(
444
			[
445
				'limit'                  => -1,
446
				'offset'                 => 0,
447
				'mustBeMember'           => false,
448
				'includeHiddenCircles'   => false,
449
				'includeBackendCircles'  => false,
450
				'includeSystemCircles'   => false,
451
				'includePersonalCircles' => false
452
			]
453
		);
454
455
		return $this->circleRequest->getCircles(
456
			$circleFilter,
457
			$memberFilter,
458
			$this->federatedUserService->getCurrentUser(),
459
			$this->federatedUserService->getRemoteInstance(),
460
			$params
461
		);
462
	}
463
464
465
	/**
466
	 * @param Circle $circle
467
	 *
468
	 * @throws MembersLimitException
469
	 */
470
	public function confirmCircleNotFull(Circle $circle): void {
471
		if ($this->isCircleFull($circle)) {
472
			throw new MembersLimitException(StatusCode::$MEMBER_ADD[121], 121);
0 ignored issues
show
Bug introduced by
The property MEMBER_ADD cannot be accessed from this context as it is declared private in class OCA\Circles\StatusCode.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
473
		}
474
	}
475
476
477
	/**
478
	 * @param Circle $circle
479
	 *
480
	 * @return bool
481
	 */
482
	public function isCircleFull(Circle $circle): bool {
483
		$filter = new Member();
484
		$filter->setLevel(Member::LEVEL_MEMBER);
485
		$members = $this->memberRequest->getMembers($circle->getSingleId(), null, null, $filter);
486
487
		$limit = $this->getInt('members_limit', $circle->getSettings());
488
		if ($limit === -1) {
489
			return false;
490
		}
491
		if ($limit === 0) {
492
			$limit = $this->configService->getAppValue(ConfigService::MEMBERS_LIMIT);
493
		}
494
495
		return (sizeof($members) >= $limit);
496
	}
497
498
}
499
500