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

Member::parseLevelString()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 11
Ratio 100 %

Importance

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