Completed
Pull Request — master (#551)
by Maxence
02:27
created

Circle::getSettings()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
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\Model;
33
34
use daita\MySmallPhpTools\Db\Nextcloud\nc21\INC21QueryRow;
35
use daita\MySmallPhpTools\Exceptions\InvalidItemException;
36
use daita\MySmallPhpTools\Model\Nextcloud\nc21\INC21Convert;
37
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Convert;
38
use daita\MySmallPhpTools\Traits\TArrayTools;
39
use DateTime;
40
use JsonSerializable;
41
use OCA\Circles\Exceptions\CircleNotFoundException;
42
use OCA\Circles\Exceptions\OwnerNotFoundException;
43
44
45
/**
46
 * Class Circle
47
 *
48
 * ** examples of use of bitwise flags for members management:
49
 *      CFG_OPEN, CFG_REQUEST, CFG_INVITE, CFG_FRIEND
50
 *
51
 * - CFG_OPEN                             => everyone can enter. moderator can add members.
52
 * - CFG_OPEN | CFG_REQUEST               => anyone can initiate a request to join the circle, moderator can
53
 *                                           add members
54
 * - CFG_OPEN | CFG_INVITE                => every one can enter, moderator must send invitation.
55
 * - CFG_OPEN | CFG_INVITE | CFG_REQUEST  => every one send a request, moderator must send invitation.
56
 * - CFG_OPEN | CFG_FRIEND                => useless
57
 * - CFG_OPEN | CFG_FRIEND | *            => useless
58
 *
59
 * - CFG_CIRCLE                           => no one can enter, moderator can add members.
60
 *                                           default config, this is only for code readability.
61
 * - CFG_INVITE                           => no one can enter, moderator must send invitation.
62
 * - CFG_FRIEND                           => no one can enter, but all members can add new member.
63
 * - CFG_REQUEST                          => useless (use CFG_OPEN | CFG_REQUEST)
64
 * - CFG_FRIEND | CFG_REQUEST             => no one can join the circle, but all members can request a
65
 *                                           moderator to accept new member
66
 * - CFG_FRIEND | CFG_INVITE              => no one can join the circle, but all members can add new member.
67
 *                                           An invitation will be generated
68
 * - CFG_FRIEND | CFG_INVITE | CFG_REQUEST  => no one can join the circle, but all members can request a
69
 *                                             moderator to accept new member. An invitation will be generated
70
 *
71
 * @package OCA\Circles\Model
72
 */
73
class Circle extends ManagedModel implements INC21Convert, INC21QueryRow, JsonSerializable {
74
75
76
	use TArrayTools;
77
	use TNC21Convert;
78
79
80
	// specific value
81
	const CFG_CIRCLE = 0;        // only for code readability. Circle is locked by default.
82
	const CFG_SINGLE = 1;        // Circle with only one single member.
83
	const CFG_PERSONAL = 2;      // Personal circle, only the owner can see it.
84
85
	// bitwise
86
	const CFG_VISIBLE = 8;        // Visible to everyone, if not visible, people have to know its name to be able to find it
87
	const CFG_OPEN = 16;          // Circle is open, people can join
88
	const CFG_INVITE = 32;        // Adding a member generate an invitation that needs to be accepted
89
	const CFG_REQUEST = 64;       // Request to join Circles needs to be confirmed by a moderator
90
	const CFG_FRIEND = 128;       // Members of the circle can invite their friends
91
	const CFG_PROTECTED = 256;    // Password protected to join/request
92
	const CFG_NO_OWNER = 512;     // no owner, only members
93
	const CFG_HIDDEN = 1024;      // hidden from listing, but available as a share entity
94
	const CFG_BACKEND = 2048;     // Fully hidden, only backend Circles
95
	const CFG_ROOT = 4096;        // Circle cannot be inside another Circle
96
	const CFG_FEDERATED = 8192;   // Federated
97
98
	const ID_LENGTH = 15;
99
100
	static $DEF = [
101
		1 => 'S|Single',
102
103
		2    => 'P|Personal',
104
		8    => 'V|Visible',
105
		16   => 'O|Open',
106
		32   => 'I|Invite',
107
		64   => 'JR|Join Request',
108
		128  => 'F|Friends',
109
		256  => 'PP|Password Protected',
110
		512  => 'NO|No Owner',
111
		1024 => 'H|Hidden',
112
		2048 => 'T|Root',
113
		4096 => 'F|Federated'
114
	];
115
116
117
	/** @var string */
118
	private $id = '';
119
120
	/** @var int */
121
	private $config = 0;
122
123
	/** @var int */
124
	private $type = 0;
125
126
	/** @var string */
127
	private $name = '';
128
129
	/** @var string */
130
	private $altName = '';
131
132
	/** @var Member */
133
	private $owner;
134
135
	/** @var array */
136
	private $members = [];
137
138
	/** @var Member */
139
	private $initiator;
140
141
	/** @var array */
142
	private $settings = [];
143
144
	/** @var string */
145
	private $description = '';
146
147
	/** @var int */
148
	private $contactAddressBook = 0;
149
150
	/** @var string */
151
	private $contactGroupName = '';
152
153
	/** @var string */
154
	private $instance = '';
155
156
//	/** @var bool */
157
//	private $hidden = false;
158
159
	/** @var int */
160
	private $creation = 0;
161
162
163
	/** @var Circle[] */
164
	private $memberOf = null;
165
166
	private $completeJson = false;
167
168
169
	/**
170
	 * Circle constructor.
171
	 */
172
	public function __construct() {
173
	}
174
175
	/**
176
	 * @param string $id
177
	 *
178
	 * @return self
179
	 */
180
	public function setId(string $id): self {
181
		$this->id = $id;
182
183
		return $this;
184
	}
185
186
	/**
187
	 * @return string
188
	 */
189
	public function getId(): string {
190
		return $this->id;
191
	}
192
193
194
	/**
195
	 * @param int $config
196
	 *
197
	 * @return self
198
	 */
199
	public function setConfig(int $config): self {
200
		$this->config = $config;
201
202
//		$this->hidden = false;
203
//		foreach (array_keys(self::$DEF) as $def) {
204
//			if ($this->isType($def) && substr(self::$DEF[$def], 0, 1) === '*') {
205
//				$this->setHidden(true);
206
//				break;
207
//			}
208
//		}
209
210
		return $this;
211
	}
212
213
	/**
214
	 * @return int
215
	 */
216
	public function getConfig(): int {
217
		return $this->config;
218
	}
219
220
	/**
221
	 * @param int $flag
222
	 *
223
	 * @return bool
224
	 */
225
	public function isConfig(int $flag): bool {
226
		return (($this->getConfig() & $flag) !== 0);
227
	}
228
229
230
	/**
231
	 * @param string $name
232
	 *
233
	 * @return self
234
	 */
235
	public function setName(string $name): self {
236
		$this->name = $name;
237
238
		return $this;
239
	}
240
241
	/**
242
	 * @return string
243
	 */
244
	public function getName(): string {
245
		return $this->name;
246
	}
247
248
249
	/**
250
	 * @param string $altName
251
	 *
252
	 * @return self
253
	 */
254
	public function setAltName(string $altName): self {
255
		$this->altName = $altName;
256
257
		return $this;
258
	}
259
260
	/**
261
	 * @return string
262
	 */
263
	public function getAltName(): string {
264
		return $this->altName;
265
	}
266
267
268
	/**
269
	 * @param Member $owner
270
	 *
271
	 * @return self
272
	 */
273
	public function setOwner(Member $owner): self {
274
		$this->owner = $owner;
275
276
		return $this;
277
	}
278
279
	/**
280
	 * @return Member
281
	 */
282
	public function getOwner(): Member {
283
		return $this->owner;
284
	}
285
286
	/**
287
	 * @return bool
288
	 */
289
	public function hasOwner(): bool {
290
		return ($this->owner !== null);
291
	}
292
293
294
	/**
295
	 * @param array $members
296
	 *
297
	 * @return self
298
	 */
299
	public function setMembers(array $members): self {
300
		$this->members = $members;
301
302
		return $this;
303
	}
304
305
	/**
306
	 * @return array
307
	 */
308
	public function getMembers(): array {
309
		if (empty($this->members)) {
310
			$this->getManager()->getMembers($this);
311
		}
312
313
		return $this->members;
314
	}
315
316
317
	/**
318
	 * @param Member $initiator
319
	 *
320
	 * @return Circle
321
	 */
322
	public function setInitiator(Member $initiator): self {
323
		$this->initiator = $initiator;
324
325
		return $this;
326
	}
327
328
	/**
329
	 * @return Member
330
	 */
331
	public function getInitiator(): Member {
332
		return $this->initiator;
333
	}
334
335
	/**
336
	 * @return bool
337
	 */
338
	public function hasInitiator(): bool {
339
		return ($this->initiator !== null);
340
	}
341
342
	/**
343
	 * @param string $instance
344
	 *
345
	 * @return Circle
346
	 */
347
	public function setInstance(string $instance): self {
348
		if ($this->isConfig(self::CFG_NO_OWNER)) {
349
			$this->instance = $instance;
350
		}
351
352
		return $this;
353
	}
354
355
	/**
356
	 * @return string
357
	 * @throws OwnerNotFoundException
358
	 */
359
	public function getInstance(): string {
360
		if ($this->isConfig(self::CFG_NO_OWNER)) {
361
			return $this->instance;
362
		}
363
364
		if (!$this->hasOwner()) {
365
			throw new OwnerNotFoundException('circle has no owner, or not set to have no owner');
366
		}
367
368
		return $this->getOwner()->getInstance();
369
	}
370
371
372
	/**
373
	 * @param array $settings
374
	 *
375
	 * @return self
376
	 */
377
	public function setSettings(array $settings): self {
378
		$this->settings = $settings;
379
380
		return $this;
381
	}
382
383
	/**
384
	 * @return array
385
	 */
386
	public function getSettings(): array {
387
		return $this->settings;
388
	}
389
390
391
	/**
392
	 * @param string $description
393
	 *
394
	 * @return self
395
	 */
396
	public function setDescription(string $description): self {
397
		$this->description = $description;
398
399
		return $this;
400
	}
401
402
	/**
403
	 * @return string
404
	 */
405
	public function getDescription(): string {
406
		return $this->description;
407
	}
408
409
410
	/**
411
	 * @param int $contactAddressBook
412
	 *
413
	 * @return self
414
	 */
415
	public function setContactAddressBook(int $contactAddressBook): self {
416
		$this->contactAddressBook = $contactAddressBook;
417
418
		return $this;
419
	}
420
421
	/**
422
	 * @return int
423
	 */
424
	public function getContactAddressBook(): int {
425
		return $this->contactAddressBook;
426
	}
427
428
429
	/**
430
	 * @param string $contactGroupName
431
	 *
432
	 * @return self
433
	 */
434
	public function setContactGroupName(string $contactGroupName): self {
435
		$this->contactGroupName = $contactGroupName;
436
437
		return $this;
438
	}
439
440
	/**
441
	 * @return string
442
	 */
443
	public function getContactGroupName(): string {
444
		return $this->contactGroupName;
445
	}
446
447
448
//	/**
449
//	 * @param bool $hidden
450
//	 *
451
//	 * @return Circle
452
//	 */
453
//	public function setHidden(bool $hidden): self {
454
//		$this->hidden = $hidden;
455
//
456
//		return $this;
457
//	}
458
//
459
//	/**
460
//	 * @return bool
461
//	 */
462
//	public function isHidden(): bool {
463
//		return $this->hidden;
464
//	}
465
466
467
	/**
468
	 * @param array $memberOf
469
	 *
470
	 * @return $this
471
	 */
472
	public function setMemberOf(array $memberOf): self {
473
		$this->memberOf = $memberOf;
474
475
		return $this;
476
	}
477
478
	/**
479
	 * @return Circle[]
480
	 */
481
	public function memberOf(): array {
482
		if ($this->memberOf === null) {
483
			$this->getManager()->memberOf($this);
484
		}
485
486
		return $this->memberOf;
487
	}
488
489
490
	/**
491
	 * @param int $creation
492
	 *
493
	 * @return self
494
	 */
495
	public function setCreation(int $creation): self {
496
		$this->creation = $creation;
497
498
		return $this;
499
	}
500
501
	/**
502
	 * @return int
503
	 */
504
	public function getCreation(): int {
505
		return $this->creation;
506
	}
507
508
509
	/**
510
	 * @param array $data
511
	 *
512
	 * @return $this
513
	 */
514
	public function import(array $data): INC21Convert {
515
		$this->setId($this->get('id', $data))
516
			 ->setName($this->get('name', $data))
517
			 ->setAltName($this->get('alt_name', $data))
518
			 ->setConfig($this->getInt('config', $data))
519
			 ->setSettings($this->getArray('settings', $data))
520
//			 ->setContactAddressBook($this->get('contact_addressbook', $data))
521
//			 ->setContactGroupName($this->get('contact_groupname', $data))
522
			 ->setDescription($this->get('description', $data))
523
			 ->setCreation($this->getInt('creation', $data));
524
525
		try {
526
			/** @var Member $owner */
527
			$owner = $this->convert($this->getArray('owner', $data), Member::class);
528
			$this->setOwner($owner);
529
		} catch (InvalidItemException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
530
		}
531
532
		try {
533
			/** @var Member $owner */
534
			$initiator = $this->convert($this->getArray('initiator', $data), Member::class);
535
			$this->setInitiator($initiator);
0 ignored issues
show
Compatibility introduced by
$initiator of type object<daita\MySmallPhpT...loud\nc21\INC21Convert> is not a sub-type of object<OCA\Circles\Model\Member>. It seems like you assume a concrete implementation of the interface daita\MySmallPhpTools\Mo...cloud\nc21\INC21Convert to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
536
		} catch (InvalidItemException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
537
		}
538
539
		return $this;
540
	}
541
542
543
	/**
544
	 * @return array
545
	 */
546
	public function jsonSerialize(): array {
547
		$arr = [
548
			'id'          => $this->getId(),
549
			'name'        => $this->getName(),
550
			'alt_name'    => $this->getAltName(),
551
			'config'      => $this->getConfig(),
552
			'description' => $this->getDescription(),
553
			'settings'    => $this->getSettings(),
554
			//			'hidden'      => $this->isHidden(),
555
			'creation'    => $this->getCreation()
556
		];
557
558
		if ($this->hasOwner()) {
559
			$arr['owner'] = $this->getOwner();
560
		}
561
562
		if ($this->hasInitiator()) {
563
			$arr['initiator'] = $this->getInitiator();
564
		}
565
566
		if ($this->getManager()->isFullDetails()) {
567
			$arr['memberOf'] = $this->memberOf();
568
		}
569
570
		return array_filter($arr);
571
	}
572
573
574
	/**
575
	 * @param array $data
576
	 * @param string $prefix
577
	 *
578
	 * @return INC21QueryRow
579
	 * @throws CircleNotFoundException
580
	 */
581
	public function importFromDatabase(array $data, string $prefix = ''): INC21QueryRow {
582
		if (!array_key_exists($prefix . 'unique_id', $data)) {
583
			throw new CircleNotFoundException();
584
		}
585
586
		$this->setId($this->get($prefix . 'unique_id', $data))
587
			 ->setName($this->get($prefix . 'name', $data))
588
			 ->setAltName($this->get($prefix . 'alt_name', $data))
589
			 ->setConfig($this->getInt($prefix . 'config', $data))
590
			 ->setInstance($this->get($prefix . 'instance', $data))
591
			 ->setSettings($this->getArray($prefix . 'settings', $data))
592
			 ->setContactAddressBook($this->getInt($prefix . 'contact_addressbook', $data))
593
			 ->setContactGroupName($this->get($prefix . 'contact_groupname', $data))
594
			 ->setDescription($this->get($prefix . 'description', $data));
595
596
		$creation = $this->get($prefix . 'creation', $data);
597
		$this->setCreation(DateTime::createFromFormat('Y-m-d H:i:s', $creation)->getTimestamp());
598
599
		$this->getManager()->importOwnerFromDatabase($this, $data);
600
		$this->getManager()->importInitiatorFromDatabase($this, $data);
601
602
		return $this;
603
	}
604
605
606
	/**
607
	 * @param Circle $circle
608
	 *
609
	 * @return bool
610
	 * @throws OwnerNotFoundException
611
	 */
612
	public function compareWith(Circle $circle): bool {
613
		if ($this->getId() !== $circle->getId()
614
			|| $this->getInstance() !== $circle->getInstance()
615
			|| $this->getConfig() !== $circle->getConfig()) {
616
			return false;
617
		}
618
619
		if ($this->hasOwner()
620
			&& (!$circle->hasOwner()
621
				|| !$this->getOwner()->compareWith($circle->getOwner()))) {
622
			return false;
623
		}
624
625
		if ($this->hasInitiator()
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return !($this->hasIniti...cle->getInitiator())));.
Loading history...
626
			&& (!$circle->hasInitiator()
627
				|| !$this->getInitiator()->compareWith($circle->getInitiator()))) {
628
			return false;
629
		}
630
631
		return true;
632
	}
633
634
}
635
636