CompositeSources   F
last analyzed

Complexity

Total Complexity 74

Size/Duplication

Total Lines 418
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 74
eloc 109
c 1
b 0
f 0
dl 0
loc 418
ccs 135
cts 135
cp 1
rs 2.48

31 Methods

Rating   Name   Duplication   Size   Complexity  
A updateGroup() 0 5 3
A canProcess() 0 10 4
A setCurrentUser() 0 4 1
A getGroupDataOnly() 0 17 5
A updatePassword() 0 6 3
A getGroups() 0 3 1
A canAccessUserByClassId() 0 3 1
A isMaintainer() 0 3 1
A currentUserRepresents() 0 4 1
A deleteGroup() 0 6 3
A canAccessUser() 0 3 3
A getCurrentUser() 0 6 2
A canAccessGroup() 0 3 2
A updateCertData() 0 6 3
A getClasses() 0 3 1
A isAlreadyInParents() 0 8 3
A readGroup() 0 10 3
A readAccounts() 0 11 4
A __construct() 0 4 2
A createAccount() 0 5 3
A getDataOnly() 0 6 3
A isMe() 0 3 1
A updateAccount() 0 5 2
A getAccounts() 0 3 1
A getCertData() 0 6 3
A createGroup() 0 16 3
A getAuth() 0 3 1
A readClasses() 0 9 3
A hasChildren() 0 9 3
A isCurrentUserRepresented() 0 4 1
A deleteAccount() 0 6 4

How to fix   Complexity   

Complex Class

Complex classes like CompositeSources often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CompositeSources, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace kalanis\kw_auth_groups\Access;
4
5
6
use kalanis\kw_accounts\AccountsException;
7
use kalanis\kw_accounts\Interfaces;
8
use kalanis\kw_auth_sources\Access as source_access;
9
use kalanis\kw_auth_groups\Sources\KwAuth;
10
use kalanis\kw_auth_sources\AuthSourcesException;
11
use kalanis\kw_groups\GroupsException;
12
use kalanis\kw_groups\Interfaces\IProcessor;
13
use kalanis\kw_groups\Processor\Basic;
14
15
16
/**
17
 * Class CompositeSources
18
 * @package kalanis\kw_auth_groups\Access
19
 *
20
 * todo: next step: separate user rights themselves and system consistency checks
21
 */
22
class CompositeSources extends source_access\CompositeSources
23
{
24
    protected IProcessor $libGroup;
25
    protected ?Interfaces\IUser $currentUser = null;
26
27
    /**
28
     * @param source_access\SourcesAdapters\AAdapter $adapter
29
     * @param IProcessor|null $libGroup
30
     * @throws AuthSourcesException
31
     */
32 66
    public function __construct(source_access\SourcesAdapters\AAdapter $adapter, ?IProcessor $libGroup = null)
33
    {
34 66
        parent::__construct($adapter);
35 66
        $this->libGroup = $libGroup ?: new Basic(new KwAuth($adapter->getGroups()));
36 66
    }
37
38
    /**
39
     * @param string $userName
40
     * @throws AccountsException
41
     * @throws GroupsException
42
     * @return Interfaces\IUser|null
43
     */
44 13
    public function getDataOnly(string $userName): ?Interfaces\IUser
45
    {
46 13
        $data = parent::getDataOnly($userName);
47 13
        return $data && $this->canAccessUser($data)
48 6
            ? $data
49 13
            : null
50
        ;
51
    }
52
53
    /**
54
     * @param string $userName
55
     * @throws AccountsException
56
     * @throws GroupsException
57
     * @return Interfaces\ICert|null
58
     */
59 8
    public function getCertData(string $userName): ?Interfaces\ICert
60
    {
61 8
        $data = parent::getDataOnly($userName);
62 8
        return $data && $this->canAccessUser($data)
63 3
            ? parent::getCertData($userName)
64 8
            : null
65
        ;
66
    }
67
68
    /**
69
     * @param Interfaces\IUser $user
70
     * @param string $password
71
     * @throws AccountsException
72
     * @throws GroupsException
73
     * @return bool
74
     */
75 4
    public function createAccount(Interfaces\IUser $user, string $password): bool
76
    {
77 4
        return $this->canAccessUserByClassId($user->getClass()) && !$this->currentUserRepresents($user)
78 2
            ? parent::createAccount($user, $password)
79 4
            : false
80
        ;
81
    }
82
83
    /**
84
     * @throws AccountsException
85
     * @throws GroupsException
86
     * @return Interfaces\IUser[]
87
     */
88 4
    public function readAccounts(): array
89
    {
90 4
        $availableAccounts = [];
91
        /** @var Interfaces\IUser[] $allAccounts */
92 4
        $allAccounts = parent::readAccounts();
93 4
        foreach ($allAccounts as $account) {
94 3
            if ($this->canAccessUserByClassId($account->getClass()) && $this->isCurrentUserRepresented($account)) {
95 2
                $availableAccounts[] = $account;
96
            }
97
        }
98 4
        return $availableAccounts;
99
    }
100
101
    /**
102
     * @param Interfaces\IUser $user
103
     * @throws AccountsException
104
     * @throws GroupsException
105
     * @return bool
106
     */
107 7
    public function updateAccount(Interfaces\IUser $user): bool
108
    {
109 7
        return $this->canAccessUser($user)
110 5
            ? parent::updateAccount($user)
111 7
            : false
112
        ;
113
    }
114
115
    /**
116
     * @param string $userName
117
     * @param string $passWord
118
     * @throws AccountsException
119
     * @throws GroupsException
120
     * @return bool
121
     */
122 7
    public function updatePassword(string $userName, string $passWord): bool
123
    {
124 7
        $user = parent::getDataOnly($userName);
125 7
        return $user && $this->canAccessUser($user)
126 4
            ? parent::updatePassword($userName, $passWord)
127 7
            : false
128
        ;
129
    }
130
131
    /**
132
     * @param string $userName
133
     * @param string|null $certKey
134
     * @param string|null $certSalt
135
     * @throws AccountsException
136
     * @throws GroupsException
137
     * @return bool
138
     */
139 8
    public function updateCertData(string $userName, ?string $certKey, ?string $certSalt): bool
140
    {
141 8
        $user = $this->getDataOnly($userName);
142 8
        return $user && $this->canAccessUser($user)
143 3
            ? parent::updateCertData($userName, $certKey, $certSalt)
144 8
            : false
145
        ;
146
    }
147
148
    /**
149
     * @param string $userName
150
     * @throws AccountsException
151
     * @throws GroupsException
152
     * @return bool
153
     */
154 7
    public function deleteAccount(string $userName): bool
155
    {
156 7
        $user = parent::getDataOnly($userName);
157 7
        return $user && $this->canAccessUserByClassId($user->getClass()) && !$this->currentUserRepresents($user)
158 3
            ? parent::deleteAccount($userName)
159 7
            : false
160
        ;
161
    }
162
163
    /**
164
     * All lower classes than user has
165
     * @throws GroupsException
166
     * @return array<int, string>
167
     */
168 6
    public function readClasses(): array
169
    {
170 6
        $availableClasses = [];
171 6
        foreach (parent::readClasses() as $classId => $className) {
172 6
            if ($this->canAccessUserByClassId($classId)) {
173 3
                $availableClasses[$classId] = $className;
174
            }
175
        }
176 6
        return $availableClasses;
177
    }
178
179
    /**
180
     * @param Interfaces\IGroup $group
181
     * @throws AccountsException
182
     * @throws GroupsException
183
     * @return bool
184
     */
185 7
    public function createGroup(Interfaces\IGroup $group): bool
186
    {
187 7
        $reGroup = clone $group;
188 7
        $reGroup->setGroupData(
189 7
            $group->getGroupId(),
190 7
            $group->getGroupName(),
191 7
            $group->getGroupDesc(),
192 7
            $this->getCurrentUser()->getAuthId(),
193 7
            $group->getGroupStatus(),
194 7
            $group->getGroupParents(),
195 7
            $group->getGroupExtra()
196
        );
197
198 7
        return ($this->canAccessGroup($reGroup) && !$this->isAlreadyInParents($reGroup))
199 4
            ? parent::createGroup($reGroup)
200 7
            : false
201
        ;
202
    }
203
204
    /**
205
     * @param string $groupId
206
     * @throws AccountsException
207
     * @throws GroupsException
208
     * @return Interfaces\IGroup|null
209
     */
210 11
    public function getGroupDataOnly(string $groupId): ?Interfaces\IGroup
211
    {
212 11
        $thisGroup = null;
213 11
        foreach (parent::readGroup() as $group) {
214
            /** @var Interfaces\IGroup $group */
215 10
            if ($group->getGroupId() == $groupId) {
216 9
                $thisGroup = $group;
217 9
                break;
218
            }
219
        }
220 11
        if (!$thisGroup) {
221 6
            return null;
222
        }
223
224 9
        return ($this->canAccessGroup($thisGroup))
225 5
            ? $thisGroup
226 9
            : null
227
        ;
228
    }
229
230
    /**
231
     * @throws AccountsException
232
     * @throws GroupsException
233
     * @return Interfaces\IGroup[]
234
     */
235 5
    public function readGroup(): array
236
    {
237 5
        $availableGroups = [];
238 5
        foreach (parent::readGroup() as $group) {
239
            /** @var Interfaces\IGroup $group */
240 4
            if ($this->canAccessGroup($group)) {
241 2
                $availableGroups[] = $group;
242
            }
243
        }
244 5
        return $availableGroups;
245
    }
246
247
    /**
248
     * @param Interfaces\IGroup $group
249
     * @throws AccountsException
250
     * @throws GroupsException
251
     * @return bool
252
     */
253 5
    public function updateGroup(Interfaces\IGroup $group): bool
254
    {
255 5
        return $this->canAccessGroup($group) && !$this->isAlreadyInParents($group)
256 2
            ? parent::updateGroup($group)
257 5
            : false
258
        ;
259
    }
260
261
    /**
262
     * @param string $groupId
263
     * @throws AccountsException
264
     * @throws AuthSourcesException
265
     * @throws GroupsException
266
     * @return bool
267
     */
268 5
    public function deleteGroup(string $groupId): bool
269
    {
270 5
        $group = $this->getGroupDataOnly($groupId);
271 5
        return $group && !$this->hasChildren($group)
272 2
            ? parent::deleteGroup($groupId)
273 5
            : false
274
        ;
275
    }
276
277 2
    public function getAuth(): Interfaces\IAuth
278
    {
279 2
        return $this;
280
    }
281
282 2
    public function getAccounts(): Interfaces\IProcessAccounts
283
    {
284 2
        return $this;
285
    }
286
287 1
    public function getGroups(): Interfaces\IProcessGroups
288
    {
289 1
        return $this;
290
    }
291
292 1
    public function getClasses(): Interfaces\IProcessClasses
293
    {
294 1
        return $this;
295
    }
296
297 63
    public function setCurrentUser(?Interfaces\IUser $user): self
298
    {
299 63
        $this->currentUser = $user;
300 63
        return $this;
301
    }
302
303
    /**
304
     * @throws GroupsException
305
     * @return Interfaces\IUser
306
     */
307 62
    public function getCurrentUser(): Interfaces\IUser
308
    {
309 62
        if (empty($this->currentUser)) {
310 1
            throw new GroupsException('Set Current User first!');
311
        }
312 62
        return $this->currentUser;
313
    }
314
315
    /**
316
     * @param Interfaces\IUser $user
317
     * @throws GroupsException
318
     * @return bool
319
     */
320 27
    protected function canAccessUser(Interfaces\IUser $user): bool
321
    {
322 27
        return $this->isMe($user) || $this->canAccessUserByClassId($user->getClass()) || $this->isCurrentUserRepresented($user);
323
    }
324
325
    /**
326
     * Aktualni Zastupuje dodavaneho
327
     * Aktualni je potomek dodavaneho
328
     * @param Interfaces\IUser $data
329
     * @throws GroupsException
330
     * @return bool
331
     */
332 6
    protected function currentUserRepresents(Interfaces\IUser $data): bool
333
    {
334
//print_r(['grp child', $this->getCurrentUser()->getGroup(), $data->getGroup(), intval($this->libGroup->canAccess($this->getCurrentUser()->getGroup(), $data->getGroup()))]);
335 6
        return $this->libGroup->canAccess($this->getCurrentUser()->getGroup(), $data->getGroup());
336
    }
337
338
    /**
339
     * Akntualni Je zastupovan dodanym
340
     * Aktualni je rodic dodavaneho
341
     * @param Interfaces\IUser $data
342
     * @throws GroupsException
343
     * @return bool
344
     */
345 12
    protected function isCurrentUserRepresented(Interfaces\IUser $data): bool
346
    {
347
//print_r(['grp parent', $this->getCurrentUser()->getGroup(), $data->getGroup(), intval($this->libGroup->canAccess($data->getGroup(), $this->getCurrentUser()->getGroup()))]);
348 12
        return $this->libGroup->canAccess($data->getGroup(), $this->getCurrentUser()->getGroup());
349
    }
350
351
    /**
352
     * @param int $class
353
     * @throws GroupsException
354
     * @return bool
355
     */
356 35
    protected function canAccessUserByClassId(int $class): bool
357
    {
358 35
        return $this->getCurrentUser()->getClass() < $class;
359
    }
360
361
    /**
362
     * @param Interfaces\IUser $data
363
     * @throws GroupsException
364
     * @return bool
365
     */
366 27
    protected function isMe(Interfaces\IUser $data): bool
367
    {
368 27
        return $this->getCurrentUser()->getAuthId() == $data->getAuthId();
369
    }
370
371
    /**
372
     * @param Interfaces\IGroup $data
373
     * @throws GroupsException
374
     * @return bool
375
     */
376 22
    protected function canAccessGroup(Interfaces\IGroup $data): bool
377
    {
378 22
        return $this->isMaintainer() || $this->canProcess($data);
379
    }
380
381
    /**
382
     * @throws GroupsException
383
     * @return bool
384
     */
385 22
    protected function isMaintainer(): bool
386
    {
387 22
        return Interfaces\IProcessClasses::CLASS_MAINTAINER == $this->getCurrentUser()->getClass();
388
    }
389
390
    /**
391
     * @param Interfaces\IGroup $group
392
     * @throws GroupsException
393
     * @return bool
394
     */
395 17
    protected function canProcess(Interfaces\IGroup $group): bool
396
    {
397 17
        $current = $this->getCurrentUser();
398
        return
399 17
            Interfaces\IProcessClasses::CLASS_ADMIN == $current->getClass()
400
            && (
401 6
                $group->getGroupAuthorId() == $current->getAuthId()
402
                || (
403 4
                    $group->getGroupId()
404 17
                    && $this->libGroup->canAccess($group->getGroupId(), $current->getGroup())
405
                )
406
            )
407
        ;
408
    }
409
410
    /**
411
     * @param Interfaces\IGroup $group
412
     * @throws GroupsException
413
     * @return bool
414
     */
415 4
    protected function isAlreadyInParents(Interfaces\IGroup $group): bool
416
    {
417 4
        foreach ($group->getGroupParents() as $groupParent) {
418 4
            if ($this->libGroup->canAccess($groupParent, $group->getGroupId())) {
419 2
                return true;
420
            }
421
        }
422 4
        return false;
423
    }
424
425
    /**
426
     * @param Interfaces\IGroup $group
427
     * @throws AccountsException
428
     * @throws AuthSourcesException
429
     * @return bool
430
     */
431 2
    protected function hasChildren(Interfaces\IGroup $group): bool
432
    {
433 2
        $allGroups = $this->adapter->getGroups()->readGroup();
434 2
        foreach ($allGroups as $sourceGroup) {
435 2
            if (in_array($group->getGroupId(), $sourceGroup->getGroupParents())) {
436 2
                return true;
437
            }
438
        }
439 2
        return false;
440
    }
441
}
442