Passed
Push — main ( 25ab27...21c65b )
by Proyecto
08:42
created

SQLiteRepository::addModuleToRole()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 10
ccs 8
cts 8
cp 1
rs 10
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
namespace ProyectoTAU\TAU\Common;
4
5
use PDO;
6
use PDOException;
7
use ProyectoTAU\TAU\Module\Administration\User\Domain\User;
8
use ProyectoTAU\TAU\Module\Administration\Group\Domain\Group;
9
use ProyectoTAU\TAU\Module\Administration\Role\Domain\Role;
10
use ProyectoTAU\TAU\Module\Administration\Module\Domain\Module;
11
12
/*
13
 * @see https://phpenthusiast.com/blog/the-singleton-design-pattern-in-php
14
 */
15
16
// General singleton class.
17
class SQLiteRepository implements Repository
18
{
19
    // Hold the class instance.
20
    private static ?Repository $instance = null;
21
    private static ?PDO $db = null;
22
23
    // Primary Keys Cache
24
    private $userDataStore = [];
25
    private $groupDataStore = [];
26
    private $roleDataStore = [];
27
    private $moduleDataStore = [];
28
29
    // The constructor is private
30
    // to prevent initiation with outer code.
31
    private function __construct()
32
    {
33
        // The expensive process (e.g.,db connection) goes here.
34
        $dbname = __DIR__ . '/admin.sqlite3';
35
        try {
36
            self::$db = new PDO('sqlite:' . $dbname);
37
            self::$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
38
            //self::$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
39
        } catch (PDOException $e) {
40
            die($e->getMessage().' ('.$dbname.')');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
41
        }
42
    }
43
44
    // The object is created from within the class itself
45
    // only if the class has no instance.
46 34
    public static function getInstance(): Repository
47
    {
48 34
        if (self::$instance == null)
49
        {
50
            self::$instance = new static();
51
        }
52
53 34
        return self::$instance;
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::instance could return the type null which is incompatible with the type-hinted return ProyectoTAU\TAU\Common\Repository. Consider adding an additional type-check to rule them out.
Loading history...
54
    }
55
56
    /*
57
     * Transactions
58
     */
59 34
    public function begin(): void
60
    {
61 34
        self::$db->beginTransaction();
0 ignored issues
show
Bug introduced by
The method beginTransaction() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

61
        self::$db->/** @scrutinizer ignore-call */ 
62
                   beginTransaction();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
62 34
    }
63
64 34
    public function commit(): void
65
    {
66 34
        self::$db->commit();
67 34
    }
68
69
    public function rollBack(): void
70
    {
71
        self::$db->rollBack();
72
    }
73
74
75
    /*
76
     * @see https://www.tutorialspoint.com/sqlite/sqlite_truncate_table.htm
77
     */
78 10
    public function clearUser(): void
79
    {
80 10
        $ps = self::$db->query('DELETE FROM user_group;');
81 10
        $this->executeOrFail($ps);
82 10
        $ps = self::$db->query('DELETE FROM User;');
83 10
        $this->executeOrFail($ps);
84 10
    }
85
86 16
    public function clearGroup(): void
87
    {
88 16
        $ps = self::$db->query('DELETE FROM user_group;');
89 16
        $this->executeOrFail($ps);
90 16
        $ps = self::$db->query('DELETE FROM group_role;');
91 16
        $this->executeOrFail($ps);
92 16
        $ps = self::$db->query('DELETE FROM "Group";');
93 16
        $this->executeOrFail($ps);
94 16
    }
95
96 16
    public function clearRole(): void
97
    {
98 16
        $ps = self::$db->query('DELETE FROM group_role;');
99 16
        $this->executeOrFail($ps);
100 16
        $ps = self::$db->query('DELETE FROM role_module;');
101 16
        $this->executeOrFail($ps);
102 16
        $ps = self::$db->query('DELETE FROM Role;');
103 16
        $this->executeOrFail($ps);
104 16
    }
105
106 10
    public function clearModule(): void
107
    {
108 10
        $ps = self::$db->query('DELETE FROM role_module;');
109 10
        $this->executeOrFail($ps);
110 10
        $ps = self::$db->query('DELETE FROM Module;');
111 10
        $this->executeOrFail($ps);
112 10
    }
113
114
    /*
115
     * User
116
     */
117
118 10
    public function createUser(User $user): void
119
    {
120 10
        $ps = self::$db->prepare('INSERT INTO User (user_id, name, surname, login)'.
121 10
                                            ' VALUES(:user_id, :name, :surname, :login);');
122 10
        $this->executeOrFail($ps, [
123 10
            ':user_id' => $user->getId(),
124 10
            ':name' => $user->getName(),
125 10
            ':surname' => $user->getSurname(),
126 10
            ':login' => $user->getLogin()
127
        ]);
128
129 10
        $this->userDataStore[$user->getId()] = self::$db->lastInsertId();
130 10
    }
131
132 7
    public function readUser($id): User
133
    {
134 7
        $ps = self::$db->prepare('SELECT user_pk, user_id, name, surname, login FROM User WHERE user_id = :user_id;');
135
136 7
        $this->executeOrFail($ps, [':user_id' => $id]);
137
138 7
        $resultSet = $ps->fetch(PDO::FETCH_ASSOC);
139 7
        if( $resultSet === false )
140
            throw new \InvalidArgumentException("User with id = $id not found");
141
142 7
        $ref = new \ReflectionClass(User::class);
143 7
        $user = $this->castUser($ref->newInstanceWithoutConstructor());
144
145 7
        $user->setId($resultSet['user_id']);
146 7
        $user->setName($resultSet['name']);
147 7
        $user->setSurname($resultSet['surname']);
148 7
        $user->setLogin($resultSet['login']);
149
150 7
        $this->userDataStore[$user->getId()] = $resultSet['user_pk'];
151
152 7
        return $user;
153
    }
154
155 1
    public function updateUser($id, $name, $surname, $login): void
156
    {
157 1
        $ps = self::$db->prepare('UPDATE User SET '.
158
                                            'name = :name,'.
159
                                            'surname = :surname,'.
160
                                            'login = :login'.
161 1
                                            ' WHERE user_id = :user_id;');
162
163 1
        $this->executeOrFail($ps, [
164 1
            ':user_id' => $id,
165 1
            ':name' => $name,
166 1
            ':surname' => $surname,
167 1
            ':login' => $login
168
        ]);
169 1
    }
170
171 1
    public function deleteUser($id): void
172
    {
173 1
        $ps = self::$db->prepare('DELETE FROM User WHERE user_id = :user_id;');
174
175 1
        $this->executeOrFail($ps, [':user_id' => $id]);
176
177 1
        unset($this->userDataStore[$id]);
178 1
    }
179
180 2
    public function getGroupsFromUser(User $user): array
181
    {
182 2
        $ps = self::$db->prepare('SELECT group_pk, g.group_id, name, description FROM "Group" g'.
183
                                        ' INNER JOIN user_group rel ON g.group_pk = rel.group_fk'.
184 2
                                        ' WHERE rel.user_id = :user_id;');
185
186 2
        $resultSet = $this->queryOrFail($ps, [
187 2
            ':user_id' => $user->getid()
188
        ]);
189
190 2
        $groups = [];
191 2
        foreach ($resultSet as $entry) {
192 1
            $ref = new \ReflectionClass(Group::class);
193 1
            $group = $this->castGroup($ref->newInstanceWithoutConstructor());
194
195 1
            $group->setPropertiesBag(['id', 'name', 'desc']);
196 1
            $group->setSettersBag($group->getPropertiesBag());
197
198 1
            $group->setId($entry['group_id']);
199 1
            $group->setName($entry['name']);
200 1
            $group->setDesc($entry['description']);
201
202 1
            $groups[$entry['group_id']] = $group;
203
        }
204
205 2
        $available = array_diff_assoc($this->getAllGroups(), $groups);
206
        $r = [
207 2
            'belongsto' => $groups,
208 2
            'available' => $available
209
        ];
210
211 2
        return $r;
212
    }
213
214 7
    private function castUser($o): User
215
    {
216 7
        return $o;
217
    }
218
219 13
    private function castGroup($o): Group
220
    {
221 13
        return $o;
222
    }
223
224 8
    private function queryOrFail($ps, $params = [], $debug = 0): array
225
    {
226 8
        $this->executeOrFail($ps, $params, $debug);
227 8
        $resultSet =  $ps->fetchAll(PDO::FETCH_ASSOC);
228
229 8
        return $resultSet;
230
    }
231
232 34
    private function executeOrFail($ps, $params = [], $debug = 0): void
233
    {
234 34
        if($debug) { //TODO: toggle to enable
235
            $sql = $ps->queryString;
236
            $b = str_replace(array_keys($params), array_values($params), $sql);
237
            echo "\n$b\n";
238
        }
239
240
        try {
241 34
            $result = $ps->execute($params);
242
        } catch (PDOException $e){
243
            $result = false;
244
        }
245
246 34
        if( $result === false ) {
247
            $debug = 1;
248
            if($debug) {
249
                $sql = $ps->queryString;
250
                $b = str_replace(array_keys($params), array_values($params), $sql);
251
                echo "\n$b\n";
252
            }
253
            $errorInfo = $ps->errorInfo();
254
            $SQLSTATE_error_code = $errorInfo[0];
255
            $Driver_specific_error_code = $errorInfo[1];
256
            $Driver_specific_error_message = $errorInfo[2];
257
            throw new \Exception(
258
                '['.$SQLSTATE_error_code.'] '.$Driver_specific_error_message.
259
                ' (Driver specific error code: '.$Driver_specific_error_code.')',
260
                $SQLSTATE_error_code);
261
        }
262 34
    }
263
264 3
    private function getAllGroups(): array
265
    {
266 3
        $ps = self::$db->prepare('SELECT group_pk, group_id, group_id, name, description FROM "Group";');
267
268 3
        $resultSet = $this->queryOrFail($ps);
269
270 3
        $groups = [];
271 3
        foreach ($resultSet as $entry) {
272 3
            $ref = new \ReflectionClass(Group::class);
273 3
            $group = $this->castGroup($ref->newInstanceWithoutConstructor());
274
275 3
            $group->setPropertiesBag(['id', 'name', 'desc']);
276 3
            $group->setSettersBag($group->getPropertiesBag());
277
278 3
            $group->setId($entry['group_id']);
279 3
            $group->setName($entry['name']);
280 3
            $group->setDesc($entry['description']);
281
282 3
            $this->groupDataStore[$entry['group_id']] = $entry['group_pk'];
283
284 3
            $groups[$entry['group_id']] = $group;
285
        }
286
287 3
        return $groups;
288
    }
289
290 16
    public function createGroup(Group $group): void
291
    {
292 16
        $ps = self::$db->prepare('INSERT INTO "Group" (group_id, name, description)'.
293 16
                                            ' VALUES(:group_id, :name, :description);');
294 16
        $this->executeOrFail($ps, [
295 16
            ':group_id' => $group->getId(),
296 16
            ':name' => $group->getName(),
297 16
            ':description' => $group->getDesc()
298
        ]);
299
300 16
        $this->groupDataStore[$group->getId()] = self::$db->lastInsertId();
301 16
    }
302
303 12
    public function readGroup($id): Group
304
    {
305 12
        $ps = self::$db->prepare('SELECT group_pk, group_id, name, description FROM "Group" WHERE group_id = :group_id;');
306
307 12
        $this->executeOrFail($ps, [':group_id' => $id]);
308
309 12
        $resultSet = $ps->fetch(PDO::FETCH_ASSOC);
310 12
        if( $resultSet === false )
311
            throw new \InvalidArgumentException("Group with id = $id not found");
312
313 12
        $ref = new \ReflectionClass(Group::class);
314 12
        $group = $this->castGroup($ref->newInstanceWithoutConstructor());
315
316 12
        $group->setPropertiesBag(['id', 'name', 'desc']);
317 12
        $group->setSettersBag($group->getPropertiesBag());
318
319 12
        $group->setId($resultSet['group_id']);
320 12
        $group->setName($resultSet['name']);
321 12
        $group->setDesc($resultSet['description']);
322
323 12
        $this->groupDataStore[$group->getId()] = $resultSet['group_pk'];
324
325 12
        return $group;
326
    }
327
328 1
    public function updateGroup($id, $name, $desc): void
329
    {
330 1
        $ps = self::$db->prepare('UPDATE "Group" SET '.
331
                                            'name = :name,'.
332
                                            'description = :description'.
333 1
                                            ' WHERE group_id = :group_id;');
334
335 1
        $this->executeOrFail($ps, [
336 1
            ':group_id' => $id,
337 1
            ':name' => $name,
338 1
            ':description' => $desc
339
        ]);
340 1
    }
341
342 1
    public function deleteGroup($id): void
343
    {
344 1
        $ps = self::$db->prepare('DELETE FROM "Group" WHERE group_id = :group_id;');
345
346 1
        $this->executeOrFail($ps, [':group_id' => $id]);
347
348 1
        unset($this->groupDataStore[$id]);
349 1
    }
350
351 1
    public function getUsersFromGroup(Group $group): array
352
    {
353 1
        $ps = self::$db->prepare('SELECT user_pk, u.user_id, name, surname, login FROM User u'.
354
                                        ' INNER JOIN user_group rel ON u.user_pk = rel.user_fk'.
355 1
                                        ' WHERE rel.group_id = :group_id;');
356
357 1
        $resultSet = $this->queryOrFail($ps, [
358 1
            ':group_id' => $group->getId()
359
        ]);
360
361 1
        $users = [];
362 1
        foreach ($resultSet as $entry) {
363 1
            $ref = new \ReflectionClass(User::class);
364 1
            $user = $this->castUser($ref->newInstanceWithoutConstructor());
365
366 1
            $user->setId($entry['user_id']);
367 1
            $user->setName($entry['name']);
368 1
            $user->setSurname($entry['surname']);
369 1
            $user->setLogin($entry['login']);
370
371 1
            $users[$entry['user_id']] = $user;
372
        }
373
374 1
        $available = array_diff_assoc($this->getAllUsers(), $users);
375
        $r = [
376 1
            'members' => $users,
377 1
            'available' => $available
378
        ];
379
380 1
        return $r;
381
    }
382
383 1
    private function getAllUsers(): array
384
    {
385 1
        $ps = self::$db->prepare('SELECT user_pk, user_id, name, surname, login FROM User;');
386
387 1
        $resultSet = $this->queryOrFail($ps);
388
389 1
        $users = [];
390 1
        foreach ($resultSet as $entry) {
391 1
            $ref = new \ReflectionClass(User::class);
392 1
            $user = $this->castUser($ref->newInstanceWithoutConstructor());
393
394 1
            $user->setId($entry['user_id']);
395 1
            $user->setName($entry['name']);
396 1
            $user->setSurname($entry['surname']);
397 1
            $user->setLogin($entry['login']);
398
399 1
            $this->userDataStore[$entry['user_id']] = $entry['user_pk'];
400
401 1
            $users[$entry['user_id']] = $user;
402
        }
403
404 1
        return $users;
405
    }
406
407 3
    public function addUserToGroup(User $user, Group $group)
408
    {
409 3
        $ps = self::$db->prepare('INSERT INTO user_group (user_fk, group_fk, user_id, group_id)'.
410 3
                                        ' VALUES (:user_fk, :group_fk, :user_id, :group_id);');
411
412 3
        $this->executeOrFail($ps, [
413 3
            ':user_fk' => $this->userDataStore[$user->getId()],
414 3
            ':group_fk' => $this->groupDataStore[$group->getId()],
415 3
            ':user_id' => $user->getId(),
416 3
            ':group_id' => $group->getId()
417
        ]);
418 3
    }
419
420 1
    public function removeUserFromGroup(User $user, Group $group)
421
    {
422 1
        $ps = self::$db->prepare('DELETE FROM user_group'.
423
                                        ' WHERE user_id = :user_id'.
424 1
                                        ' AND group_id = :group_id;');
425
426 1
        $this->executeOrFail($ps, [
427 1
            ':user_id' => $user->getId(),
428 1
            ':group_id' => $group->getId()
429
        ]);
430 1
    }
431
432 16
    public function createRole(Role $role): void
433
    {
434 16
        $ps = self::$db->prepare('INSERT INTO Role (role_id, name, description)'.
435 16
                                        ' VALUES(:role_id, :name, :description);');
436
437 16
        $this->executeOrFail($ps, [
438 16
            ':role_id' => $role->getId(),
439 16
            ':name' => $role->getName(),
440 16
            ':description' => $role->getDesc()
441
        ]);
442
443 16
        $this->roleDataStore[$role->getId()] = self::$db->lastInsertId();
444 16
    }
445
446 13
    public function readRole($id): Role
447
    {
448 13
        $ps = self::$db->prepare('SELECT role_pk, role_id, name, description FROM Role WHERE role_id = :role_id;');
449
450 13
        $this->executeOrFail($ps, [':role_id' => $id]);
451
452 13
        $resultSet = $ps->fetch(PDO::FETCH_ASSOC);
453 13
        if( $resultSet === false )
454
            throw new \InvalidArgumentException("Role with id = $id not found");
455
456 13
        $ref = new \ReflectionClass(Role::class);
457 13
        $role = $this->castRole($ref->newInstanceWithoutConstructor());
458
459 13
        $role->setPropertiesBag(['id', 'name', 'desc']);
460 13
        $role->setSettersBag($role->getPropertiesBag());
461
462 13
        $role->setId($resultSet['role_id']);
463 13
        $role->setName($resultSet['name']);
464 13
        $role->setDesc($resultSet['description']);
465
466 13
        $this->roleDataStore[$role->getId()] = $resultSet['role_pk'];
467
468 13
        return $role;
469
    }
470
471 13
    private function castRole($o): Role
472
    {
473 13
        return $o;
474
    }
475
476 3
    public function addGroupToRole(Group $group, Role $role)
477
    {
478 3
        $ps = self::$db->prepare('INSERT INTO group_role (group_fk, role_fk, group_id, role_id)'.
479 3
                                        ' VALUES (:group_fk, :role_fk, :group_id, :role_id);');
480
481 3
        $this->executeOrFail($ps, [
482 3
            ':group_fk' => $this->groupDataStore[$group->getId()],
483 3
            ':role_fk' => $this->roleDataStore[$role->getId()],
484 3
            ':group_id' => $group->getId(),
485 3
            ':role_id' => $role->getId()
486
        ]);
487 3
    }
488
489 1
    public function getGroupsFromRole(Role $role): array
490
    {
491 1
        $ps = self::$db->prepare('SELECT group_pk, g.group_id, name, description FROM "Group" g'.
492
                                        ' INNER JOIN group_role rel ON g.group_pk = rel.group_fk'.
493 1
                                        ' WHERE rel.role_id = :role_id;');
494
495 1
        $resultSet = $this->queryOrFail($ps, [
496 1
            ':role_id' => $role->getId()
497
        ]);
498
499 1
        $groups = [];
500 1
        foreach ($resultSet as $entry) {
501 1
            $ref = new \ReflectionClass(Group::class);
502 1
            $group = $this->castGroup($ref->newInstanceWithoutConstructor());
503
504 1
            $group->setPropertiesBag(['id', 'name', 'desc']);
505 1
            $group->setSettersBag($group->getPropertiesBag());
506
507 1
            $group->setId($entry['group_id']);
508 1
            $group->setName($entry['name']);
509 1
            $group->setDesc($entry['description']);
510
511 1
            $groups[$entry['group_id']] = $group;
512
        }
513
514 1
        $available = array_diff_assoc($this->getAllGroups(), $groups);
515
        $r = [
516 1
            'grantedby' => $groups,
517 1
            'available' => $available
518
        ];
519
520 1
        return $r;
521
    }
522
523 1
    public function removeGroupFromRole(Group $group, Role $role)
524
    {
525 1
        $ps = self::$db->prepare('DELETE FROM group_role'.
526
                                        ' WHERE group_id = :group_id'.
527 1
                                        ' AND role_id = :role_id;');
528
529 1
        $this->executeOrFail($ps, [
530 1
            ':group_id' => $group->getId(),
531 1
            ':role_id' => $role->getId()
532
        ]);
533 1
    }
534
535 2
    public function addGroupToUser(Group $group, User $user)
536
    {
537 2
        $ps = self::$db->prepare('INSERT INTO user_group (user_fk, group_fk, user_id, group_id)'.
538 2
                                        ' VALUES (:user_fk, :group_fk, :user_id, :group_id);');
539
540 2
        $this->executeOrFail($ps, [
541 2
            ':user_fk' => $this->userDataStore[$user->getId()],
542 2
            ':group_fk' => $this->groupDataStore[$group->getId()],
543 2
            ':user_id' => $user->getId(),
544 2
            ':group_id' => $group->getId()
545
        ]);
546 2
    }
547
548 1
    public function removeGroupFromUser(Group $group, User $user)
549
    {
550 1
        $ps = self::$db->prepare('DELETE FROM user_group'.
551
                                        ' WHERE user_id = :user_id'.
552 1
                                        ' AND group_id = :group_id;');
553
554 1
        $this->executeOrFail($ps, [
555 1
            ':user_id' => $user->getId(),
556 1
            ':group_id' => $group->getId()
557
        ]);
558 1
    }
559
560 1
    public function updateRole($id, $name, $desc): void
561
    {
562 1
        $ps = self::$db->prepare('UPDATE Role SET '.
563
                                        'name = :name,'.
564
                                        'description = :description'.
565 1
                                        ' WHERE role_id = :role_id;');
566
567 1
        $this->executeOrFail($ps, [
568 1
            ':role_id' => $id,
569 1
            ':name' => $name,
570 1
            ':description' => $desc
571
        ]);
572 1
    }
573
574 1
    public function deleteRole($id): void
575
    {
576 1
        $ps = self::$db->prepare('DELETE FROM Role WHERE role_id = :role_id;');
577
578 1
        $this->executeOrFail($ps, [
579 1
            ':role_id' => $id
580
        ]);
581
582 1
        unset($this->roleDataStore[$id]);
583 1
    }
584
585 3
    public function addRoleToGroup(Role $role, Group $group)
586
    {
587 3
        $ps = self::$db->prepare('INSERT INTO group_role (group_fk, role_fk, group_id, role_id)'.
588 3
                                        ' VALUES (:group_fk, :role_fk, :group_id, :role_id);');
589
590 3
        $this->executeOrFail($ps, [
591 3
            ':group_fk' => $this->groupDataStore[$group->getId()],
592 3
            ':role_fk' => $this->roleDataStore[$role->getId()],
593 3
            ':group_id' => $group->getId(),
594 3
            ':role_id' => $role->getId()
595
        ]);
596 3
    }
597
598 1
    public function getRolesFromGroup(Group $group): array
599
    {
600 1
        $ps = self::$db->prepare('SELECT role_pk, r.role_id, name, description FROM Role r'.
601
                                        ' INNER JOIN group_role rel ON r.role_pk = rel.role_fk'.
602 1
                                        ' WHERE rel.group_id = :group_id;');
603
604 1
        $resultSet = $this->queryOrFail($ps, [
605 1
            ':group_id' => $group->getId()
606
        ]);
607
608 1
        $roles = [];
609 1
        foreach ($resultSet as $entry) {
610 1
            $ref = new \ReflectionClass(Role::class);
611 1
            $role = $this->castRole($ref->newInstanceWithoutConstructor());
612
613 1
            $role->setPropertiesBag(['id', 'name', 'desc']);
614 1
            $role->setSettersBag($role->getPropertiesBag());
615
616 1
            $role->setId($entry['role_id']);
617 1
            $role->setName($entry['name']);
618 1
            $role->setDesc($entry['description']);
619
620 1
            $roles[$entry['role_id']] = $role;
621
        }
622
623 1
        $available = array_diff_assoc($this->getAllRoles(), $roles);
624
        $r = [
625 1
            'plays' => $roles,
626 1
            'available' => $available
627
        ];
628
629 1
        return $r;
630
    }
631
632 2
    private function getAllRoles(): array
633
    {
634 2
        $ps = self::$db->prepare('SELECT role_pk, role_id, role_id, name, description FROM Role;');
635
636 2
        $resultSet = $this->queryOrFail($ps);
637
638 2
        $roles = [];
639 2
        foreach ($resultSet as $entry) {
640 2
            $ref = new \ReflectionClass(Role::class);
641 2
            $role = $this->castRole($ref->newInstanceWithoutConstructor());
642
643 2
            $role->setPropertiesBag(['id', 'name', 'desc']);
644 2
            $role->setSettersBag($role->getPropertiesBag());
645
646 2
            $role->setId($entry['role_id']);
647 2
            $role->setName($entry['name']);
648 2
            $role->setDesc($entry['description']);
649
650 2
            $this->roleDataStore[$entry['role_id']] = $entry['role_pk'];
651
652 2
            $roles[$entry['role_id']] = $role;
653
        }
654
655 2
        return $roles;
656
    }
657
658 1
    public function removeRoleFromGroup(Role $role, Group $group)
659
    {
660 1
        $ps = self::$db->prepare('DELETE FROM group_role'.
661
                                        ' WHERE role_id = :role_id'.
662 1
                                        ' AND group_id = :group_id;');
663
664 1
        $this->executeOrFail($ps, [
665 1
            ':role_id' => $role->getId(),
666 1
            ':group_id' => $group->getId()
667
        ]);
668 1
    }
669
670 6
    public function addModuleToRole(Module $module, Role $role)
671
    {
672 6
        $ps = self::$db->prepare('INSERT INTO role_module (role_fk, module_fk, role_id, module_id)'.
673 6
                                        ' VALUES (:role_fk, :module_fk, :role_id, :module_id);');
674
675 6
        $this->executeOrFail($ps, [
676 6
            ':role_fk' => $this->roleDataStore[$role->getId()],
677 6
            ':module_fk' => $this->moduleDataStore[$module->getId()],
678 6
            ':role_id' => $role->getId(),
679 6
            ':module_id' => $module->getId()
680
        ]);
681 6
    }
682
683 2
    public function removeModuleFromRole(Module $module, Role $role)
684
    {
685 2
        $ps = self::$db->prepare('DELETE FROM role_module'.
686
                                        ' WHERE role_id = :role_id'.
687 2
                                        ' AND module_id = :module_id;');
688
689 2
        $this->executeOrFail($ps, [
690 2
            ':module_id' => $module->getId(),
691 2
            ':role_id' => $role->getId()
692
        ]);
693 2
    }
694
695 2
    public function getModulesFromRole(Role $role): array
696
    {
697 2
        $ps = self::$db->prepare('SELECT module_pk, m.module_id, name, description FROM Module m'.
698
                                        ' INNER JOIN role_module rel ON m.module_pk = rel.module_fk'.
699 2
                                        ' WHERE rel.role_id = :role_id;');
700
701 2
        $resultSet = $this->queryOrFail($ps, [
702 2
            ':role_id' => $role->getId()
703
        ]);
704
705 2
        $modules = [];
706 2
        foreach ($resultSet as $entry) {
707 2
            $ref = new \ReflectionClass(Module::class);
708 2
            $module = $this->castModule($ref->newInstanceWithoutConstructor());
709
710 2
            $module->setPropertiesBag(['id', 'name', 'desc']);
711 2
            $module->setSettersBag($module->getPropertiesBag());
712
713 2
            $module->setId($entry['module_id']);
714 2
            $module->setName($entry['name']);
715 2
            $module->setDesc($entry['description']);
716
717 2
            $modules[$entry['module_id']] = $module;
718
        }
719
720 2
        $available = array_diff_assoc($this->getAllModules(), $modules);
721
        $r = [
722 2
            'canrun' => $modules,
723 2
            'available' => $available
724
        ];
725
726 2
        return $r;
727
    }
728
729 7
    private function castModule($o): Module
730
    {
731 7
        return $o;
732
    }
733
734 2
    private function getAllModules()
735
    {
736 2
        $ps = self::$db->prepare('SELECT module_pk, module_id, module_id, name, description FROM Module;');
737
738 2
        $resultSet = $this->queryOrFail($ps);
739
740 2
        $modules = [];
741 2
        foreach ($resultSet as $entry) {
742 2
            $ref = new \ReflectionClass(Module::class);
743 2
            $module = $this->castModule($ref->newInstanceWithoutConstructor());
744
745 2
            $module->setPropertiesBag(['id', 'name', 'desc']);
746 2
            $module->setSettersBag($module->getPropertiesBag());
747
748 2
            $module->setId($entry['module_id']);
749 2
            $module->setName($entry['name']);
750 2
            $module->setDesc($entry['description']);
751
752 2
            $this->moduleDataStore[$entry['module_id']] = $entry['module_pk'];
753
754 2
            $modules[$entry['module_id']] = $module;
755
        }
756
757 2
        return $modules;
758
    }
759
760 10
    public function createModule(Module $module): void
761
    {
762 10
        $ps = self::$db->prepare('INSERT INTO Module (module_id, name, description)'.
763 10
                                        ' VALUES(:module_id, :name, :description);');
764 10
        $this->executeOrFail($ps, [
765 10
            ':module_id' => $module->getId(),
766 10
            ':name' => $module->getName(),
767 10
            ':description' => $module->getDesc()
768
        ]);
769
770 10
        $this->moduleDataStore[$module->getId()] = self::$db->lastInsertId();
771 10
    }
772
773 7
    public function readModule($id): Module
774
    {
775 7
        $ps = self::$db->prepare('SELECT module_pk, module_id, name, description FROM Module'.
776 7
                                        ' WHERE module_id = :module_id;');
777
778 7
        $this->executeOrFail($ps, [
779 7
            ':module_id' => $id
780
        ]);
781
782 7
        $resultSet = $ps->fetch(PDO::FETCH_ASSOC);
783 7
        if( $resultSet === false )
784
            throw new \InvalidArgumentException("Module with id = $id not found");
785
786 7
        $ref = new \ReflectionClass(Module::class);
787 7
        $module = $this->castModule($ref->newInstanceWithoutConstructor());
788
789 7
        $module->setPropertiesBag(['id', 'name', 'desc']);
790 7
        $module->setSettersBag($module->getPropertiesBag());
791
792 7
        $module->setId($resultSet['module_id']);
793 7
        $module->setName($resultSet['name']);
794 7
        $module->setDesc($resultSet['description']);
795
796 7
        $this->moduleDataStore[$module->getId()] = $resultSet['module_pk'];
797
798 7
        return $module;
799
    }
800
801 1
    public function updateModule($id, $name, $desc): void
802
    {
803 1
        $ps = self::$db->prepare('UPDATE Module SET '.
804
                                        'name = :name,'.
805
                                        'description = :description'.
806 1
                                        ' WHERE module_id = :module_id;');
807
808 1
        $this->executeOrFail($ps, [
809 1
            ':module_id' => $id,
810 1
            ':name' => $name,
811 1
            ':description' => $desc
812
        ]);
813 1
    }
814
815 1
    public function deleteModule($id): void
816
    {
817 1
        $ps = self::$db->prepare('DELETE FROM Module WHERE module_id = :module_id;');
818
819 1
        $this->executeOrFail($ps, [
820 1
            ':module_id' => $id
821
        ]);
822
823 1
        unset($this->moduleDataStore[$id]);
824 1
    }
825
826 3
    public function addRoleToModule(Role $role, Module $module)
827
    {
828 3
        $this->addModuleToRole($module, $role);
829 3
    }
830
831 1
    public function removeRoleFromModule(Role $role, Module $module)
832
    {
833 1
        $this->removeModuleFromRole($module, $role);
834 1
    }
835
836 1
    public function getRolesFromModule(Module $module): array
837
    {
838 1
        $ps = self::$db->prepare('SELECT role_pk, r.role_id, name, description FROM Role r'.
839
                                        ' INNER JOIN role_module rel ON r.role_pk = rel.role_fk'.
840 1
                                        ' WHERE rel.module_id = :module_id;');
841
842 1
        $resultSet = $this->queryOrFail($ps, [
843 1
            ':module_id' => $module->getId()
844
        ]);
845
846 1
        $roles = [];
847 1
        foreach ($resultSet as $entry) {
848 1
            $ref = new \ReflectionClass(Role::class);
849 1
            $role = $this->castRole($ref->newInstanceWithoutConstructor());
850
851 1
            $role->setPropertiesBag(['id', 'name', 'desc']);
852 1
            $role->setSettersBag($role->getPropertiesBag());
853
854 1
            $role->setId($entry['role_id']);
855 1
            $role->setName($entry['name']);
856 1
            $role->setDesc($entry['description']);
857
858 1
            $roles[$entry['role_id']] = $role;
859
        }
860
861 1
        $available = array_diff_assoc($this->getAllRoles(), $roles);
862
        $r = [
863 1
            'authorizedby' => $roles,
864 1
            'available' => $available
865
        ];
866
867 1
        return $r;
868
    }
869
}
870