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

Member::setJoined()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
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\IDeserializable;
37
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Deserialize;
38
use daita\MySmallPhpTools\Traits\TArrayTools;
39
use DateTime;
40
use JsonSerializable;
41
use OCA\Circles\Exceptions\MemberNotFoundException;
42
use OCA\Circles\Exceptions\ParseMemberLevelException;
43
use OCA\Circles\Exceptions\UserTypeNotFoundException;
44
use OCA\Circles\IFederatedUser;
45
46
47
/**
48
 * Class Member
49
 *
50
 * @package OCA\Circles\Model
51
 */
52
class Member extends ManagedModel implements IFederatedUser, IDeserializable, INC21QueryRow, JsonSerializable {
53
54
55
	use TArrayTools;
56
	use TNC21Deserialize;
57
58
59
	const LEVEL_NONE = 0;
60
	const LEVEL_MEMBER = 1;
61
	const LEVEL_MODERATOR = 4;
62
	const LEVEL_ADMIN = 8;
63
	const LEVEL_OWNER = 9;
64
65
	const TYPE_CIRCLE = 16;
66
	const TYPE_SINGLE = 8;
67
	const TYPE_USER = 1;
68
	const TYPE_GROUP = 2;
69
	const TYPE_MAIL = 3;
70
	const TYPE_CONTACT = 4;
71
72
	const STATUS_NONMEMBER = 'Unknown';
73
	const STATUS_INVITED = 'Invited';
74
	const STATUS_REQUEST = 'Requesting';
75
	const STATUS_MEMBER = 'Member';
76
	const STATUS_BLOCKED = 'Blocked';
77
	const STATUS_KICKED = 'Kicked';
78
79
80
	public static $DEF_LEVEL = [
81
		1 => 'Member',
82
		4 => 'Moderator',
83
		8 => 'Admin',
84
		9 => 'Owner'
85
	];
86
87
	public static $DEF_TYPE = [
88
		1  => 'user',
89
		16 => 'circle',
90
		8  => 'single',
91
		3  => 'mail',
92
		4  => 'contact',
93
	];
94
95
	/** @var string */
96
	private $id = '';
97
98
	/** @var string */
99
	private $circleId = '';
100
101
	/** @var string */
102
	private $singleId = '';
103
104
	/** @var string */
105
	private $userId = '';
106
107
	/** @var int */
108
	private $userType = self::TYPE_USER;
109
110
	/** @var string */
111
	private $instance = '';
112
113
	/** @var bool */
114
	private $local = false;
115
116
	/** @var int */
117
	private $level = 0;
118
119
	/** @var string */
120
	private $status = 'Unknown';
121
122
	/** @var string */
123
	private $note = '';
124
125
	/** @var string */
126
	private $displayName = '';
127
128
	/** @var int */
129
	private $displayUpdate = 0;
130
131
	/** @var string */
132
	private $contactId = '';
133
134
	/** @var string */
135
	private $contactMeta = '';
136
137
	/** @var Circle */
138
	private $circle;
139
140
141
	/** @var int */
142
	private $joined = 0;
143
144
145
	/**
146
	 * Member constructor.
147
	 */
148
	public function __construct() {
149
	}
150
151
152
	/**
153
	 * @param string $id
154
	 *
155
	 * @return $this
156
	 */
157
	public function setId(string $id): self {
158
		$this->id = $id;
159
160
		return $this;
161
	}
162
163
	/**
164
	 * @return string
165
	 */
166
	public function getId(): string {
167
		return $this->id;
168
	}
169
170
171
	/**
172
	 * @param string $circleId
173
	 *
174
	 * @return Member
175
	 */
176
	public function setCircleId(string $circleId): self {
177
		$this->circleId = $circleId;
178
179
		return $this;
180
	}
181
182
	/**
183
	 * @return string
184
	 */
185
	public function getCircleId(): string {
186
		return $this->circleId;
187
	}
188
189
190
	/**
191
	 * This should replace user_id, user_type and instance; and will use the data from Circle with
192
	 * Config=CFG_SINGLE
193
	 *
194
	 * @param string $singleId
195
	 *
196
	 * @return $this
197
	 */
198
	public function setSingleId(string $singleId): self {
199
		$this->singleId = $singleId;
200
201
		return $this;
202
	}
203
204
	/**
205
	 * @return string
206
	 */
207
	public function getSingleId(): string {
208
		return $this->singleId;
209
	}
210
211
212
	/**
213
	 * @param string $userId
214
	 *
215
	 * @return Member
216
	 */
217
	public function setUserId(string $userId): self {
218
		$this->userId = $userId;
219
		if ($this->displayName === '') {
220
			$this->displayName = $userId;
221
		}
222
223
		return $this;
224
	}
225
226
	/**
227
	 * @return string
228
	 */
229
	public function getUserId(): string {
230
		return $this->userId;
231
	}
232
233
234
	/**
235
	 * @param int $userType
236
	 *
237
	 * @return Member
238
	 */
239
	public function setUserType(int $userType): self {
240
		$this->userType = $userType;
241
242
		return $this;
243
	}
244
245
	/**
246
	 * @return int
247
	 */
248
	public function getUserType(): int {
249
		return $this->userType;
250
	}
251
252
253
	/**
254
	 * @param string $instance
255
	 *
256
	 * @return Member
257
	 */
258
	public function setInstance(string $instance): self {
259
		$this->instance = $instance;
260
261
		return $this;
262
	}
263
264
	/**
265
	 * @return string
266
	 */
267
	public function getInstance(): string {
268
		return $this->instance;
269
	}
270
271
272
	/**
273
	 * @param bool $local
274
	 *
275
	 * @return Member
276
	 */
277
	public function setLocal(bool $local): self {
278
		$this->local = $local;
279
280
		return $this;
281
	}
282
283
	/**
284
	 * @return bool
285
	 */
286
	public function isLocal(): bool {
287
		return $this->local;
288
	}
289
290
291
	/**
292
	 * @param int $level
293
	 *
294
	 * @return Member
295
	 */
296
	public function setLevel(int $level): self {
297
		$this->level = $level;
298
299
		return $this;
300
	}
301
302
	/**
303
	 * @return int
304
	 */
305
	public function getLevel(): int {
306
		return $this->level;
307
	}
308
309
310
	/**
311
	 * @param string $status
312
	 *
313
	 * @return Member
314
	 */
315
	public function setStatus(string $status): self {
316
		$this->status = $status;
317
318
		return $this;
319
	}
320
321
	/**
322
	 * @return string
323
	 */
324
	public function getStatus(): string {
325
		return $this->status;
326
	}
327
328
329
	/**
330
	 * @param string $note
331
	 *
332
	 * @return Member
333
	 */
334
	public function setNote(string $note): self {
335
		$this->note = $note;
336
337
		return $this;
338
	}
339
340
	/**
341
	 * @return string
342
	 */
343
	public function getNote(): string {
344
		return $this->note;
345
	}
346
347
348
	/**
349
	 * @param string $displayName
350
	 *
351
	 * @return Member
352
	 */
353
	public function setDisplayName(string $displayName): self {
354
		if ($displayName !== '') {
355
			$this->displayName = $displayName;
356
		}
357
358
		return $this;
359
	}
360
361
362
	/**
363
	 * @param int $displayUpdate
364
	 *
365
	 * @return Member
366
	 */
367
	public function setDisplayUpdate(int $displayUpdate): self {
368
		$this->displayUpdate = $displayUpdate;
369
370
		return $this;
371
	}
372
373
	/**
374
	 * @return int
375
	 */
376
	public function getDisplayUpdate(): int {
377
		return $this->displayUpdate;
378
	}
379
380
381
	/**
382
	 * @return string
383
	 */
384
	public function getDisplayName(): string {
385
		return $this->displayName;
386
	}
387
388
389
	/**
390
	 * @param string $contactId
391
	 *
392
	 * @return Member
393
	 */
394
	public function setContactId(string $contactId): self {
395
		$this->contactId = $contactId;
396
397
		return $this;
398
	}
399
400
	/**
401
	 * @return string
402
	 */
403
	public function getContactId(): string {
404
		return $this->contactId;
405
	}
406
407
408
	/**
409
	 * @param string $contactMeta
410
	 *
411
	 * @return Member
412
	 */
413
	public function setContactMeta(string $contactMeta): self {
414
		$this->contactMeta = $contactMeta;
415
416
		return $this;
417
	}
418
419
	/**
420
	 * @return string
421
	 */
422
	public function getContactMeta(): string {
423
		return $this->contactMeta;
424
	}
425
426
427
	/**
428
	 * @param Circle $circle
429
	 *
430
	 * @return self
431
	 */
432
	public function setCircle(Circle $circle): self {
433
		$this->circle = $circle;
434
435
		return $this;
436
	}
437
438
	/**
439
	 * @return Circle
440
	 */
441
	public function getCircle(): Circle {
442
		return $this->circle;
443
	}
444
445
	/**
446
	 * @return bool
447
	 */
448
	public function hasCircle(): bool {
449
		return (!is_null($this->circle));
450
	}
451
452
453
	/**
454
	 * @param int $joined
455
	 *
456
	 * @return Member
457
	 */
458
	public function setJoined(int $joined): self {
459
		$this->joined = $joined;
460
461
		return $this;
462
	}
463
464
	/**
465
	 * @return int
466
	 */
467
	public function getJoined(): int {
468
		return $this->joined;
469
	}
470
471
472
	/**
473
	 * @return bool
474
	 */
475
	public function isMember(): bool {
476
		return ($this->level > 0);
477
	}
478
479
480
	/**
481
	 * @param Member $member
482
	 * @param bool $full
483
	 *
484
	 * @return bool
485
	 */
486
	public function compareWith(Member $member, bool $full = true): bool {
487
		if ($this->getId() !== $member->getId()
488
			|| $this->getCircleId() !== $member->getCircleId()
489
			|| $this->getSingleId() !== $member->getSingleId()
490
			|| $this->getUserId() !== $member->getUserId()
491
			|| $this->getUserType() <> $member->getUserType()
492
			|| $this->getInstance() !== $member->getInstance()) {
493
			return false;
494
		}
495
496
		if ($full
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return !($full && ($this...$member->getStatus()));.
Loading history...
497
			&& ($this->getLevel() <> $member->getLevel()
498
				|| $this->getStatus() !== $member->getStatus())) {
499
			return false;
500
		}
501
502
		return true;
503
	}
504
505
506
	/**
507
	 * @param array $data
508
	 *
509
	 * @return $this
510
	 * @throws InvalidItemException
511
	 */
512
	public function import(array $data): IDeserializable {
513
		if ($this->get('userId', $data) === '') {
514
			throw new InvalidItemException();
515
		}
516
517
		$this->setId($this->get('id', $data));
518
		$this->setCircleId($this->get('circleId', $data));
519
		$this->setSingleId($this->get('singleId', $data));
520
		$this->setUserId($this->get('userId', $data));
521
		$this->setUserType($this->getInt('userType', $data));
522
		$this->setInstance($this->get('instance', $data));
523
		$this->setLocal($this->getBool('local', $data));
524
		$this->setLevel($this->getInt('level', $data));
525
		$this->setStatus($this->get('status', $data));
526
		$this->setDisplayName($this->get('displayName', $data));
527
		$this->setDisplayUpdate($this->getInt('displayUpdate', $data));
528
		$this->setNote($this->get('note', $data));
529
		$this->setContactId($this->get('contactId', $data));
530
		$this->setContactMeta($this->get('contactMeta', $data));
531
		$this->setJoined($this->getInt('joined', $data));
532
533
		try {
534
			/** @var Circle $circle */
535
			$circle = $this->deserialize($this->getArray('circle', $data), Circle::class);
536
			$this->setCircle($circle);
537
		} catch (InvalidItemException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
538
		}
539
540
		return $this;
541
	}
542
543
544
	/**
545
	 * @return string[]
546
	 */
547
	public function jsonSerialize(): array {
548
		$arr = array_filter(
549
			[
550
				'id'            => $this->getId(),
551
				'circleId'      => $this->getCircleId(),
552
				'singleId'      => $this->getSingleId(),
553
				'userId'        => $this->getUserId(),
554
				'userType'      => $this->getUserType(),
555
				'instance'      => $this->getInstance(),
556
				'local'         => $this->isLocal(),
557
				'level'         => $this->getLevel(),
558
				'status'        => $this->getStatus(),
559
				'displayName'   => $this->getDisplayName(),
560
				'displayUpdate' => $this->getDisplayUpdate(),
561
				'note'          => $this->getNote(),
562
				'contactId'     => $this->getContactId(),
563
				'contactMeta'   => $this->getContactMeta(),
564
				'joined'        => $this->getJoined()
565
			]
566
		);
567
568
		if ($this->hasCircle()) {
569
			$arr['circle'] = $this->getCircle();
570
		}
571
572
		return $arr;
573
	}
574
575
576
	/**
577
	 * @param array $data
578
	 * @param string $prefix
579
	 *
580
	 * @return INC21QueryRow
581
	 * @throws MemberNotFoundException
582
	 */
583
	public function importFromDatabase(array $data, string $prefix = ''): INC21QueryRow {
584
		if (!array_key_exists($prefix . 'member_id', $data)) {
585
			throw new MemberNotFoundException();
586
		}
587
588
		$this->setId($this->get($prefix . 'member_id', $data));
589
		$this->setCircleId($this->get($prefix . 'circle_id', $data));
590
		$this->setSingleId($this->get($prefix . 'single_id', $data));
591
		$this->setUserId($this->get($prefix . 'user_id', $data));
592
		$this->setUserType($this->getInt($prefix . 'user_type', $data));
593
		$this->setInstance($this->get($prefix . 'instance', $data));
594
		$this->setLevel($this->getInt($prefix . 'level', $data));
595
		$this->setStatus($this->get($prefix . 'status', $data));
596
		$this->setDisplayName($this->get($prefix . 'cached_name', $data));
597
		$this->setNote($this->get($prefix . 'note', $data));
598
		$this->setContactId($this->get($prefix . 'contact_id', $data));
599
		$this->setContactMeta($this->get($prefix . 'contact_meta', $data));
600
601
		$cachedUpdate = $this->get($prefix . 'cached_update', $data);
602
		if ($cachedUpdate !== '') {
603
			$this->setDisplayUpdate(DateTime::createFromFormat('Y-m-d H:i:s', $cachedUpdate)->getTimestamp());
604
		}
605
606
		$joined = $this->get($prefix . 'joined', $data);
607
		if ($joined !== '') {
608
			$this->setJoined(DateTime::createFromFormat('Y-m-d H:i:s', $joined)->getTimestamp());
609
		}
610
611
		if ($this->getInstance() === '') {
612
			$this->setLocal(true);
613
			$this->setInstance($this->get('_params.local', $data));
614
		}
615
616
		if ($prefix === '') {
617
			$this->getManager()->importCircleFromDatabase($this, $data);
618
		}
619
620
		return $this;
621
	}
622
623
624
	/**
625
	 * @param string $levelString
626
	 *
627
	 * @return int
628
	 * @throws ParseMemberLevelException
629
	 */
630 View Code Duplication
	public static function parseLevelString(string $levelString): int {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
631
		$levelString = ucfirst(strtolower($levelString));
632
		$level = array_search($levelString, Member::$DEF_LEVEL);
633
634
		if (!$level) {
635
			$all = implode(', ', array_values(self::$DEF_LEVEL));
636
			throw new ParseMemberLevelException('Available levels: ' . $all);
637
		}
638
639
		return (int)$level;
640
	}
641
642
	/**
643
	 * @param string $typeString
644
	 *
645
	 * @return int
646
	 * @throws UserTypeNotFoundException
647
	 */
648 View Code Duplication
	public static function parseTypeString(string $typeString): int {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
649
		$typeString = strtolower($typeString);
650
		$type = array_search($typeString, Member::$DEF_TYPE);
651
652
		if (!$type) {
653
			$all = implode(', ', array_values(self::$DEF_TYPE));
654
			throw new UserTypeNotFoundException('Available types: ' . $all);
655
		}
656
657
		return (int)$type;
658
	}
659
660
}
661
662