Completed
Push — master ( a5882f...67b08d )
by Maxence
01:27 queued 01:22
created

RemoteInstance::setCircle()   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\Federated;
33
34
35
use daita\MySmallPhpTools\Db\Nextcloud\nc22\INC22QueryRow;
36
use daita\MySmallPhpTools\Model\Nextcloud\nc22\NC22Signatory;
37
use daita\MySmallPhpTools\Traits\TArrayTools;
38
use JsonSerializable;
39
use OCA\Circles\Exceptions\RemoteNotFoundException;
40
use OCA\Circles\Exceptions\RemoteUidException;
41
42
43
/**
44
 * Class AppService
45
 *
46
 * @package OCA\Circles\Model
47
 */
48
class RemoteInstance extends NC22Signatory implements INC22QueryRow, JsonSerializable {
49
50
51
	use TArrayTools;
52
53
	const TYPE_UNKNOWN = 'Unknown';    // not trusted
54
	const TYPE_PASSIVE = 'Passive';    // Minimum information about Federated Circles are broadcasted if a member belongs to the circle.
55
	const TYPE_EXTERNAL = 'External';  // info about Federated Circles and their members are broadcasted  if a member belongs to the circle.
56
	const TYPE_TRUSTED = 'Trusted';    // everything about Federated Circles are broadcasted.
57
	const TYPE_GLOBALSCALE = 'GlobalScale';  // every Circle is broadcasted,
58
59
	public static $LIST_TYPE = [
60
		self::TYPE_UNKNOWN,
61
		self::TYPE_PASSIVE,
62
		self::TYPE_EXTERNAL,
63
		self::TYPE_TRUSTED,
64
		self::TYPE_GLOBALSCALE
65
	];
66
67
	const TEST = 'test';
68
	const INCOMING = 'incoming';
69
	const EVENT = 'event';
70
	const CIRCLES = 'circles';
71
	const CIRCLE = 'circle';
72
	const MEMBERS = 'members';
73
	const MEMBER = 'member';
74
75
76
	/** @var int */
77
	private $dbId = 0;
78
79
	/** @var string */
80
	private $type = self::TYPE_UNKNOWN;
81
82
	/** @var int */
83
	private $interface = 0;
84
85
	/** @var string */
86
	private $test = '';
87
88
	/** @var array */
89
	private $aliases = [];
90
91
	/** @var string */
92
	private $incoming = '';
93
94
	/** @var string */
95
	private $root = '';
96
97
	/** @var string */
98
	private $event = '';
99
100
	/** @var string */
101
	private $circles = '';
102
103
	/** @var string */
104
	private $circle = '';
105
106
	/** @var string */
107
	private $members = '';
108
109
	/** @var string */
110
	private $member = '';
111
112
	/** @var string */
113
	private $uid = '';
114
115
	/** @var string */
116
	private $authSigned = '';
117
118
	/** @var bool */
119
	private $identityAuthed = false;
120
121
122
	/**
123
	 * @param int $dbId
124
	 *
125
	 * @return self
126
	 */
127
	public function setDbId(int $dbId): self {
128
		$this->dbId = $dbId;
129
130
		return $this;
131
	}
132
133
	/**
134
	 * @return int
135
	 */
136
	public function getDbId(): int {
137
		return $this->dbId;
138
	}
139
140
141
	/**
142
	 * @param string $type
143
	 *
144
	 * @return $this
145
	 */
146
	public function setType(string $type): self {
147
		$this->type = $type;
148
149
		return $this;
150
	}
151
152
	/**
153
	 * @return string
154
	 */
155
	public function getType(): string {
156
		return $this->type;
157
	}
158
159
160
	/**
161
	 * @param int $interface
162
	 *
163
	 * @return RemoteInstance
164
	 */
165
	public function setInterface(int $interface): self {
166
		$this->interface = $interface;
167
168
		return $this;
169
	}
170
171
	/**
172
	 * @return int
173
	 */
174
	public function getInterface(): int {
175
		return $this->interface;
176
	}
177
178
179
	/**
180
	 * @param array $aliases
181
	 *
182
	 * @return RemoteInstance
183
	 */
184
	public function setAliases(array $aliases): self {
185
		$this->aliases = $aliases;
186
187
		return $this;
188
	}
189
190
	/**
191
	 * @return array
192
	 */
193
	public function getAliases(): array {
194
		return $this->aliases;
195
	}
196
197
198
	/**
199
	 * @return string
200
	 */
201
	public function getIncoming(): string {
202
		return $this->incoming;
203
	}
204
205
	/**
206
	 * @param string $incoming
207
	 *
208
	 * @return self
209
	 */
210
	public function setIncoming(string $incoming): self {
211
		$this->incoming = $incoming;
212
213
		return $this;
214
	}
215
216
217
	/**
218
	 * @return string
219
	 */
220
	public function getRoot(): string {
221
		return $this->root;
222
	}
223
224
	/**
225
	 * @param string $root
226
	 *
227
	 * @return $this
228
	 */
229
	public function setRoot(string $root): self {
230
		$this->root = $root;
231
232
		return $this;
233
	}
234
235
236
	/**
237
	 * @return string
238
	 */
239
	public function getEvent(): string {
240
		return $this->event;
241
	}
242
243
	/**
244
	 * @param string $event
245
	 *
246
	 * @return self
247
	 */
248
	public function setEvent(string $event): self {
249
		$this->event = $event;
250
251
		return $this;
252
	}
253
254
255
	/**
256
	 * @param string $test
257
	 *
258
	 * @return RemoteInstance
259
	 */
260
	public function setTest(string $test): self {
261
		$this->test = $test;
262
263
		return $this;
264
	}
265
266
	/**
267
	 * @return string
268
	 */
269
	public function getTest(): string {
270
		return $this->test;
271
	}
272
273
274
	/**
275
	 * @return string
276
	 */
277
	public function getCircles(): string {
278
		return $this->circles;
279
	}
280
281
	/**
282
	 * @param string $circles
283
	 *
284
	 * @return self
285
	 */
286
	public function setCircles(string $circles): self {
287
		$this->circles = $circles;
288
289
		return $this;
290
	}
291
292
293
	/**
294
	 * @return string
295
	 */
296
	public function getCircle(): string {
297
		return $this->circle;
298
	}
299
300
	/**
301
	 * @param string $circle
302
	 *
303
	 * @return self
304
	 */
305
	public function setCircle(string $circle): self {
306
		$this->circle = $circle;
307
308
		return $this;
309
	}
310
311
312
	/**
313
	 * @return string
314
	 */
315
	public function getMembers(): string {
316
		return $this->members;
317
	}
318
319
	/**
320
	 * @param string $members
321
	 *
322
	 * @return self
323
	 */
324
	public function setMembers(string $members): self {
325
		$this->members = $members;
326
327
		return $this;
328
	}
329
330
331
	/**
332
	 * @return string
333
	 */
334
	public function getMember(): string {
335
		return $this->member;
336
	}
337
338
	/**
339
	 * @param string $member
340
	 *
341
	 * @return self
342
	 */
343
	public function setMember(string $member): self {
344
		$this->member = $member;
345
346
		return $this;
347
	}
348
349
350
	/**
351
	 * @return $this
352
	 */
353
	public function setUidFromKey(): self {
354
		$this->setUid(hash('sha512', $this->getPublicKey()));
355
356
		return $this;
357
	}
358
359
	/**
360
	 * @param string $uid
361
	 *
362
	 * @return RemoteInstance
363
	 */
364
	public function setUid(string $uid): self {
365
		$this->uid = $uid;
366
367
		return $this;
368
	}
369
370
	/**
371
	 * @param bool $shorten
372
	 *
373
	 * @return string
374
	 */
375
	public function getUid(bool $shorten = false): string {
376
		if ($shorten) {
377
			return substr($this->uid, 0, 18);
378
		}
379
380
		return $this->uid;
381
	}
382
383
384
	/**
385
	 * @param string $authSigned
386
	 *
387
	 * @return RemoteInstance
388
	 */
389
	public function setAuthSigned(string $authSigned): self {
390
		$this->authSigned = $authSigned;
391
392
		return $this;
393
	}
394
395
	/**
396
	 * @return string
397
	 */
398
	public function getAuthSigned(): string {
399
		return $this->authSigned;
400
	}
401
402
403
	/**
404
	 * @param bool $identityAuthed
405
	 *
406
	 * @return RemoteInstance
407
	 */
408
	public function setIdentityAuthed(bool $identityAuthed): self {
409
		$this->identityAuthed = $identityAuthed;
410
411
		return $this;
412
	}
413
414
	/**
415
	 * @return bool
416
	 */
417
	public function isIdentityAuthed(): bool {
418
		return $this->identityAuthed;
419
	}
420
421
	/**
422
	 * @throws RemoteUidException
423
	 */
424
	public function mustBeIdentityAuthed(): void {
425
		if (!$this->isIdentityAuthed()) {
426
			throw new RemoteUidException('identity not authed');
427
		}
428
	}
429
430
431
	/**
432
	 * @param array $data
433
	 *
434
	 * @return NC22Signatory
435
	 */
436
	public function import(array $data): NC22Signatory {
437
		parent::import($data);
438
439
		$this->setTest($this->get('test', $data))
440
			 ->setAliases($this->getArray('aliases', $data))
441
			 ->setEvent($this->get('event', $data))
442
			 ->setRoot($this->get('root', $data))
443
			 ->setIncoming($this->get('incoming', $data))
444
			 ->setCircles($this->get('circles', $data))
445
			 ->setCircle($this->get('circle', $data))
446
			 ->setMembers($this->get('members', $data))
447
			 ->setMember($this->get('member', $data))
448
			 ->setUid($this->get('uid', $data));
449
450
		$algo = '';
451
		$authSigned = trim($this->get('auth-signed', $data), ':');
452
		if (strpos($authSigned, ':') > 0) {
453
			list($algo, $authSigned) = explode(':', $authSigned);
454
		}
455
456
		$this->setAuthSigned($authSigned)
457
			 ->setAlgorithm($algo);
458
459
		return $this;
460
	}
461
462
463
	/**
464
	 * @return array
465
	 */
466
	public function jsonSerialize(): array {
467
		$data = [
468
			'uid'      => $this->getUid(true),
469
			'root'     => $this->getRoot(),
470
			'event'    => $this->getEvent(),
471
			'incoming' => $this->getIncoming(),
472
			'test'     => $this->getTest(),
473
			'circles'  => $this->getCircles(),
474
			'circle'   => $this->getCircle(),
475
			'members'  => $this->getMembers(),
476
			'member'   => $this->getMember(),
477
		];
478
479
		if ($this->getAuthSigned() !== '') {
480
			$data['auth-signed'] = $this->getAlgorithm() . ':' . $this->getAuthSigned();
481
		}
482
483
		if (!empty($this->getAliases())) {
484
			$data['aliases'] = $this->getAliases();
485
		}
486
487
		return array_filter(array_merge($data, parent::jsonSerialize()));
488
	}
489
490
491
	/**
492
	 * @param array $data
493
	 * @param string $prefix
494
	 *
495
	 * @return self
496
	 * @throws RemoteNotFoundException
497
	 */
498
	public function importFromDatabase(array $data, string $prefix = ''): INC22QueryRow {
499
		if ($this->getInt($prefix . 'id', $data) === 0) {
500
			throw new RemoteNotFoundException();
501
		}
502
503
		$this->setDbId($this->getInt($prefix . 'id', $data));
504
		$this->import($this->getArray($prefix . 'item', $data));
505
		$this->setOrigData($this->getArray($prefix . 'item', $data));
506
		$this->setType($this->get($prefix . 'type', $data));
507
		$this->setInterface($this->getInt($prefix . 'interface', $data));
508
		$this->setInstance($this->get($prefix . 'instance', $data));
509
		$this->setId($this->get($prefix . 'href', $data));
510
511
		return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (OCA\Circles\Model\Federated\RemoteInstance) is incompatible with the return type declared by the interface daita\MySmallPhpTools\Db...Row::importFromDatabase of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
512
	}
513
514
}
515
516