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\nc22\INC22QueryRow; |
35
|
|
|
use daita\MySmallPhpTools\Exceptions\InvalidItemException; |
36
|
|
|
use daita\MySmallPhpTools\IDeserializable; |
37
|
|
|
use daita\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Deserialize; |
38
|
|
|
use daita\MySmallPhpTools\Traits\TArrayTools; |
39
|
|
|
use JsonSerializable; |
40
|
|
|
use OCA\Circles\Exceptions\FederatedUserNotFoundException; |
41
|
|
|
use OCA\Circles\Exceptions\OwnerNotFoundException; |
42
|
|
|
use OCA\Circles\IFederatedUser; |
43
|
|
|
use OCA\Circles\IMemberships; |
44
|
|
|
|
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Class FederatedUser |
48
|
|
|
* |
49
|
|
|
* @package OCA\Circles\Model |
50
|
|
|
*/ |
51
|
|
|
class FederatedUser extends ManagedModel implements |
52
|
|
|
IFederatedUser, |
53
|
|
|
IMemberships, |
54
|
|
|
IDeserializable, |
55
|
|
|
INC22QueryRow, |
56
|
|
|
JsonSerializable { |
57
|
|
|
|
58
|
|
|
|
59
|
|
|
use TArrayTools; |
60
|
|
|
use TNC22Deserialize; |
61
|
|
|
|
62
|
|
|
|
63
|
|
|
/** @var string */ |
64
|
|
|
private $singleId = ''; |
65
|
|
|
|
66
|
|
|
/** @var string */ |
67
|
|
|
private $userId; |
68
|
|
|
|
69
|
|
|
/** @var int */ |
70
|
|
|
private $userType; |
71
|
|
|
|
72
|
|
|
/** @var Circle */ |
73
|
|
|
private $basedOn; |
74
|
|
|
|
75
|
|
|
/** @var int */ |
76
|
|
|
private $config = 0; |
77
|
|
|
|
78
|
|
|
/** @var string */ |
79
|
|
|
private $instance; |
80
|
|
|
|
81
|
|
|
/** @var Membership */ |
82
|
|
|
private $link; |
83
|
|
|
|
84
|
|
|
/** @var Membership[] */ |
85
|
|
|
private $memberships = null; |
86
|
|
|
|
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* FederatedUser constructor. |
90
|
|
|
*/ |
91
|
|
|
public function __construct() { |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* @param string $userId |
97
|
|
|
* @param string $instance |
98
|
|
|
* @param int $type |
99
|
|
|
* @param Circle|null $basedOn |
100
|
|
|
* |
101
|
|
|
* @return $this |
102
|
|
|
*/ |
103
|
|
|
public function set( |
104
|
|
|
string $userId, |
105
|
|
|
$instance = '', |
106
|
|
|
int $type = Member::TYPE_USER, |
107
|
|
|
?Circle $basedOn = null |
108
|
|
|
): self { |
109
|
|
|
|
110
|
|
|
$this->userId = $userId; |
111
|
|
|
$this->setInstance($instance); |
112
|
|
|
$this->userType = $type; |
113
|
|
|
$this->basedOn = $basedOn; |
114
|
|
|
|
115
|
|
|
return $this; |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* @param string $singleId |
121
|
|
|
* |
122
|
|
|
* @return self |
123
|
|
|
*/ |
124
|
|
|
public function setSingleId(string $singleId): self { |
125
|
|
|
$this->singleId = $singleId; |
126
|
|
|
|
127
|
|
|
return $this; |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* @return string |
132
|
|
|
*/ |
133
|
|
|
public function getSingleId(): string { |
134
|
|
|
return $this->singleId; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* @param string $userId |
140
|
|
|
* |
141
|
|
|
* @return self |
142
|
|
|
*/ |
143
|
|
|
public function setUserId(string $userId): self { |
144
|
|
|
$this->userId = $userId; |
145
|
|
|
|
146
|
|
|
return $this; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* @return string |
151
|
|
|
*/ |
152
|
|
|
public function getUserId(): string { |
153
|
|
|
return $this->userId; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* @param int $userType |
159
|
|
|
* |
160
|
|
|
* @return self |
161
|
|
|
*/ |
162
|
|
|
public function setUserType(int $userType): self { |
163
|
|
|
$this->userType = $userType; |
164
|
|
|
|
165
|
|
|
return $this; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* @return int |
171
|
|
|
*/ |
172
|
|
|
public function getUserType(): int { |
173
|
|
|
return $this->userType; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* @return bool |
179
|
|
|
*/ |
180
|
|
|
public function hasBasedOn(): bool { |
181
|
|
|
return !is_null($this->basedOn); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* @param Circle|null $basedOn |
186
|
|
|
* |
187
|
|
|
* @return $this |
188
|
|
|
*/ |
189
|
|
|
public function setBasedOn(?Circle $basedOn): self { |
190
|
|
|
$this->basedOn = $basedOn; |
191
|
|
|
|
192
|
|
|
return $this; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* @return Circle |
197
|
|
|
*/ |
198
|
|
|
public function getBasedOn(): Circle { |
199
|
|
|
return $this->basedOn; |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
|
203
|
|
|
/** |
204
|
|
|
* @param int $config |
205
|
|
|
* |
206
|
|
|
* @return self |
207
|
|
|
*/ |
208
|
|
|
public function setConfig(int $config): self { |
209
|
|
|
$this->config = $config; |
210
|
|
|
|
211
|
|
|
return $this; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* @return int |
216
|
|
|
*/ |
217
|
|
|
public function getConfig(): int { |
218
|
|
|
return $this->config; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
|
222
|
|
|
/** |
223
|
|
|
* @param string $instance |
224
|
|
|
* |
225
|
|
|
* @return self |
226
|
|
|
*/ |
227
|
|
|
public function setInstance(string $instance): self { |
228
|
|
|
if ($instance === '') { |
229
|
|
|
$instance = $this->getManager()->getLocalInstance(); |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
$this->instance = $instance; |
233
|
|
|
|
234
|
|
|
return $this; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
/** |
238
|
|
|
* @return string |
239
|
|
|
*/ |
240
|
|
|
public function getInstance(): string { |
241
|
|
|
return $this->instance; |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* @return bool |
247
|
|
|
*/ |
248
|
|
|
public function hasMemberships(): bool { |
249
|
|
|
return !is_null($this->memberships); |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* @param array $memberships |
254
|
|
|
* |
255
|
|
|
* @return self |
256
|
|
|
*/ |
257
|
|
|
public function setMemberships(array $memberships): IMemberships { |
258
|
|
|
$this->memberships = $memberships; |
259
|
|
|
|
260
|
|
|
return $this; |
|
|
|
|
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
/** |
264
|
|
|
* @return Membership[] |
265
|
|
|
*/ |
266
|
|
|
public function getMemberships(): array { |
267
|
|
|
if (!$this->hasMemberships()) { |
268
|
|
|
$this->getManager()->getMemberships($this); |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
return $this->memberships; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* @return bool |
277
|
|
|
*/ |
278
|
|
|
public function hasLink(): bool { |
279
|
|
|
return !is_null($this->link); |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
/** |
283
|
|
|
* @param Membership $link |
284
|
|
|
* |
285
|
|
|
* @return $this |
286
|
|
|
*/ |
287
|
|
|
public function setLink(Membership $link): self { |
288
|
|
|
$this->link = $link; |
289
|
|
|
|
290
|
|
|
return $this; |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
/** |
294
|
|
|
* @return Membership |
295
|
|
|
*/ |
296
|
|
|
public function getLink(): Membership { |
297
|
|
|
return $this->link; |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
|
301
|
|
|
/** |
302
|
|
|
* @param array $data |
303
|
|
|
* |
304
|
|
|
* @return $this |
305
|
|
|
* @throws InvalidItemException |
306
|
|
|
*/ |
307
|
|
|
public function import(array $data): IDeserializable { |
308
|
|
|
if ($this->get('user_id', $data) === '') { |
309
|
|
|
throw new InvalidItemException(); |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
$this->setSingleId($this->get('id', $data)); |
313
|
|
|
$this->setUserId($this->get('user_id', $data)); |
314
|
|
|
$this->setUserType($this->getInt('user_type', $data)); |
315
|
|
|
$this->setInstance($this->get('instance', $data)); |
316
|
|
|
//$this->setMemberships($this->getArray('memberships')); |
317
|
|
|
|
318
|
|
|
try { |
319
|
|
|
/** @var Circle $circle */ |
320
|
|
|
$circle = $this->deserialize($this->getArray('basedOn', $data), Circle::class); |
321
|
|
|
$this->setBasedOn($circle); |
322
|
|
|
} catch (InvalidItemException $e) { |
|
|
|
|
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
return $this; |
|
|
|
|
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
|
329
|
|
|
/** |
330
|
|
|
* @param Circle $circle |
331
|
|
|
* |
332
|
|
|
* @return FederatedUser |
333
|
|
|
* @throws OwnerNotFoundException |
334
|
|
|
*/ |
335
|
|
|
public function importFromCircle(Circle $circle): self { |
336
|
|
|
$this->setSingleId($circle->getSingleId()); |
337
|
|
|
|
338
|
|
|
if ($circle->isConfig(Circle::CFG_SINGLE)) { |
339
|
|
|
$owner = $circle->getOwner(); |
340
|
|
|
$this->set($owner->getUserId(), $owner->getInstance(), $owner->getUserType(), $circle); |
341
|
|
|
} else { |
342
|
|
|
$this->set($circle->getDisplayName(), $circle->getInstance(), Member::TYPE_CIRCLE, $circle); |
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
return $this; |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
|
349
|
|
|
/** |
350
|
|
|
* @param array $data |
351
|
|
|
* @param string $prefix |
352
|
|
|
* |
353
|
|
|
* @return INC22QueryRow |
354
|
|
|
* @throws FederatedUserNotFoundException |
355
|
|
|
*/ |
356
|
|
|
public function importFromDatabase(array $data, string $prefix = ''): INC22QueryRow { |
357
|
|
|
if ($this->get($prefix . 'single_id', $data) === '') { |
358
|
|
|
throw new FederatedUserNotFoundException(); |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
$this->setSingleId($this->get($prefix . 'single_id', $data)); |
362
|
|
|
$this->setUserId($this->get($prefix . 'user_id', $data)); |
363
|
|
|
$this->setUserType($this->getInt($prefix . 'user_type', $data)); |
364
|
|
|
$this->setInstance($this->get($prefix . 'instance', $data)); |
365
|
|
|
|
366
|
|
|
$this->getManager()->manageImportFromDatabase($this, $data, $prefix); |
367
|
|
|
|
368
|
|
|
return $this; |
|
|
|
|
369
|
|
|
} |
370
|
|
|
|
371
|
|
|
|
372
|
|
|
/** |
373
|
|
|
* @return string[] |
374
|
|
|
*/ |
375
|
|
|
public function jsonSerialize(): array { |
376
|
|
|
$arr = [ |
377
|
|
|
'id' => $this->getSingleId(), |
378
|
|
|
'user_id' => $this->getUserId(), |
379
|
|
|
'user_type' => $this->getUserType(), |
380
|
|
|
'instance' => $this->getInstance() |
381
|
|
|
]; |
382
|
|
|
|
383
|
|
|
if ($this->hasBasedOn()) { |
384
|
|
|
$arr['basedOn'] = $this->getBasedOn(); |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
if ($this->hasLink()) { |
388
|
|
|
$arr['link'] = $this->getLink(); |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
if (!is_null($this->memberships)) { |
392
|
|
|
$arr['memberships'] = $this->getMemberships(); |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
return $arr; |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
|
399
|
|
|
/** |
400
|
|
|
* @param IFederatedUser $member |
401
|
|
|
* |
402
|
|
|
* @return bool |
403
|
|
|
*/ |
404
|
|
|
public function compareWith(IFederatedUser $member): bool { |
405
|
|
|
return !($this->getSingleId() !== $member->getSingleId() |
406
|
|
|
|| $this->getUserId() !== $member->getUserId() |
407
|
|
|
|| $this->getUserType() <> $member->getUserType() |
408
|
|
|
|| $this->getInstance() !== $member->getInstance()); |
409
|
|
|
} |
410
|
|
|
|
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
|
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:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.